[PATCH 1/4] Import upstream version 3.6.1

Julian Wollrath jwollrath at web.de
Sun May 3 11:51:31 UTC 2015


---
 .gitignore                                        |    1 -
 AUTHORS                                           |  174 -
 COPYING                                           |   41 +-
 acinclude.m4                                      |  124 +-
 config.h.in                                       |   21 +-
 configure                                         | 3447 ++++++---
 configure.ac                                      |  503 +-
 debian/changelog                                  |    7 +
 extra.mk.in                                       |   13 +
 m4/buildsys.m4                                    |   10 +-
 po/Makefile                                       |    3 +
 po/POTFILES.in                                    |  305 +-
 po/audacious-plugins.pot                          | 2603 ++++---
 po/be.po                                          | 2714 +++----
 po/bg.po                                          | 2882 ++++----
 po/ca.po                                          | 2702 +++----
 po/cmn.po                                         | 2833 ++++----
 po/cs.po                                          | 3118 ++++----
 po/da.po                                          | 3182 +++++----
 po/de.po                                          | 2977 ++++----
 po/el.po                                          | 2740 +++----
 po/en_GB.po                                       | 2646 +++----
 po/es.po                                          | 3756 +++++-----
 po/es_AR.po                                       | 2794 ++++----
 po/es_MX.po                                       | 2974 ++++----
 po/et.po                                          | 2706 +++----
 po/eu.po                                          | 2729 +++----
 po/fa_IR.po                                       | 2657 +++----
 po/fi.po                                          | 3000 ++++----
 po/fr.po                                          | 3002 ++++----
 po/gl.po                                          | 2964 ++++----
 po/hu.po                                          | 3047 ++++----
 po/id_ID.po                                       | 2979 ++++----
 po/it.po                                          | 2955 ++++----
 po/ja.po                                          | 3114 ++++----
 po/ko.po                                          | 2858 ++++----
 po/ky.po                                          | 2695 +++----
 po/lt.po                                          | 2856 ++++----
 po/lv.po                                          | 2921 ++++----
 po/ml_IN.po                                       | 2736 +++----
 po/ms.po                                          | 4352 ++++++++++++
 po/nl.po                                          | 4078 +++++++++++
 po/pl.po                                          | 3191 +++++----
 po/process-transifex-po                           |    7 +-
 po/pt_BR.po                                       | 2915 ++++----
 po/pt_PT.po                                       | 3266 +++++----
 po/ru.po                                          | 2916 ++++----
 po/si.po                                          | 2837 ++++----
 po/sk.po                                          | 2836 ++++----
 po/sr.po                                          | 2966 ++++----
 po/sr_RS.po                                       | 2798 ++++----
 po/sv.po                                          | 4012 +++++++++++
 po/ta.po                                          | 2739 +++----
 po/tr.po                                          | 2736 +++----
 po/uk.po                                          | 3081 ++++----
 po/update-potfiles.sh                             |    3 +-
 po/zh_CN.po                                       | 2984 ++++----
 po/zh_TW.po                                       | 2898 ++++----
 src/aac-raw/Makefile                              |    4 +-
 src/aac-raw/aac.c                                 |  482 --
 src/aac-raw/aac.cc                                |  477 ++
 src/aac/Makefile                                  |   20 -
 src/aac/itunes-cover.c                            |   92 -
 src/aac/libmp4.c                                  |  320 -
 src/aac/mp4_utils.c                               |   31 -
 src/aac/mp4ff/mp4atom.c                           |  676 --
 src/aac/mp4ff/mp4ff.c                             |  480 --
 src/aac/mp4ff/mp4ff.h                             |  138 -
 src/aac/mp4ff/mp4ff_int_types.h                   |   23 -
 src/aac/mp4ff/mp4ffint.h                          |  308 -
 src/aac/mp4ff/mp4meta.c                           |  468 --
 src/aac/mp4ff/mp4sample.c                         |  155 -
 src/aac/mp4ff/mp4tagupdate.c                      |  658 --
 src/aac/mp4ff/mp4util.c                           |  191 -
 src/adplug/Makefile                               |  111 +-
 src/adplug/adplug-xmms.cc                         |  205 +-
 src/adplug/adplug-xmms.h                          |   34 -
 src/adplug/core/a2m.cc                            |  597 ++
 src/adplug/core/a2m.cxx                           |  597 --
 src/adplug/core/a2m.h                             |    3 +-
 src/adplug/core/adl.cc                            | 2874 ++++++++
 src/adplug/core/adl.cxx                           | 2874 --------
 src/adplug/core/adl.h                             |    2 +-
 src/adplug/core/adlibemu.c                        |  600 --
 src/adplug/core/adlibemu.cc                       |  594 ++
 src/adplug/core/adplug.cc                         |  266 +
 src/adplug/core/adplug.cxx                        |  266 -
 src/adplug/core/adplug.h                          |    2 +-
 src/adplug/core/adtrack.cc                        |  238 +
 src/adplug/core/adtrack.cxx                       |  239 -
 src/adplug/core/adtrack.h                         |    2 +-
 src/adplug/core/amd.cc                            |  231 +
 src/adplug/core/amd.cxx                           |  231 -
 src/adplug/core/amd.h                             |    2 +-
 src/adplug/core/bam.cc                            |  244 +
 src/adplug/core/bam.cxx                           |  244 -
 src/adplug/core/bam.h                             |    2 +-
 src/adplug/core/binio_virtual.h                   |   78 +-
 src/adplug/core/bmf.cc                            |  636 ++
 src/adplug/core/bmf.cxx                           |  636 --
 src/adplug/core/cff.cc                            |  531 ++
 src/adplug/core/cff.cxx                           |  541 --
 src/adplug/core/cff.h                             |    2 +-
 src/adplug/core/cmf.cc                            |  788 +++
 src/adplug/core/cmf.cxx                           |  788 ---
 src/adplug/core/cmf.h                             |    4 +-
 src/adplug/core/d00.cc                            |  653 ++
 src/adplug/core/d00.cxx                           |  653 --
 src/adplug/core/d00.h                             |    2 +-
 src/adplug/core/database.cc                       |  520 ++
 src/adplug/core/database.cxx                      |  520 --
 src/adplug/core/debug.c                           |   57 -
 src/adplug/core/debug.cc                          |   57 +
 src/adplug/core/debug.h                           |   13 +-
 src/adplug/core/dfm.cc                            |  137 +
 src/adplug/core/dfm.cxx                           |  137 -
 src/adplug/core/dfm.h                             |    2 +-
 src/adplug/core/dmo.cc                            |  456 ++
 src/adplug/core/dmo.cxx                           |  456 --
 src/adplug/core/dmo.h                             |    2 +-
 src/adplug/core/dro.cc                            |  151 +
 src/adplug/core/dro.cxx                           |  151 -
 src/adplug/core/dro.h                             |    2 +-
 src/adplug/core/dro2.cc                           |  142 +
 src/adplug/core/dro2.cxx                          |  142 -
 src/adplug/core/dro2.h                            |    2 +-
 src/adplug/core/dtm.cc                            |  338 +
 src/adplug/core/dtm.cxx                           |  338 -
 src/adplug/core/dtm.h                             |    2 +-
 src/adplug/core/emuopl.cc                         |  166 +
 src/adplug/core/emuopl.cxx                        |  166 -
 src/adplug/core/emuopl.h                          |    8 +-
 src/adplug/core/flash.cc                          |  259 +
 src/adplug/core/flash.cxx                         |  259 -
 src/adplug/core/fmc.cc                            |  243 +
 src/adplug/core/fmc.cxx                           |  243 -
 src/adplug/core/fmc.h                             |    2 +-
 src/adplug/core/fmopl.c                           | 1389 ----
 src/adplug/core/fmopl.cc                          | 1393 ++++
 src/adplug/core/fprovide.cc                       |   73 +
 src/adplug/core/fprovide.cxx                      |   77 -
 src/adplug/core/fprovide.h                        |    4 +-
 src/adplug/core/hsc.cc                            |  389 +
 src/adplug/core/hsc.cxx                           |  389 -
 src/adplug/core/hsc.h                             |    2 +-
 src/adplug/core/hsp.cc                            |   86 +
 src/adplug/core/hsp.cxx                           |   86 -
 src/adplug/core/hsp.h                             |    2 +-
 src/adplug/core/hybrid.cc                         |  268 +
 src/adplug/core/hybrid.cxx                        |  268 -
 src/adplug/core/hyp.cc                            |  129 +
 src/adplug/core/hyp.cxx                           |  129 -
 src/adplug/core/imf.cc                            |  229 +
 src/adplug/core/imf.cxx                           |  229 -
 src/adplug/core/imf.h                             |    2 +-
 src/adplug/core/jbm.cc                            |  294 +
 src/adplug/core/jbm.cxx                           |  294 -
 src/adplug/core/jbm.h                             |   14 +-
 src/adplug/core/kemuopl.h                         |    8 +-
 src/adplug/core/ksm.cc                            |  419 ++
 src/adplug/core/ksm.cxx                           |  420 --
 src/adplug/core/ksm.h                             |    2 +-
 src/adplug/core/lds.cc                            |  817 +++
 src/adplug/core/lds.cxx                           |  817 ---
 src/adplug/core/lds.h                             |   10 +-
 src/adplug/core/mad.cc                            |  146 +
 src/adplug/core/mad.cxx                           |  146 -
 src/adplug/core/mad.h                             |    2 +-
 src/adplug/core/mid.cc                            | 1101 +++
 src/adplug/core/mid.cxx                           | 1105 ---
 src/adplug/core/mid.h                             |    2 +-
 src/adplug/core/mkj.cc                            |  225 +
 src/adplug/core/mkj.cxx                           |  225 -
 src/adplug/core/mkj.h                             |    2 +-
 src/adplug/core/msc.cc                            |  338 +
 src/adplug/core/msc.cxx                           |  338 -
 src/adplug/core/msc.h                             |    2 +-
 src/adplug/core/mtk.cc                            |  168 +
 src/adplug/core/mtk.cxx                           |  168 -
 src/adplug/core/mtk.h                             |    2 +-
 src/adplug/core/player.cc                         |   73 +
 src/adplug/core/player.cxx                        |   73 -
 src/adplug/core/player.h                          |    2 +-
 src/adplug/core/players.cc                        |  107 +
 src/adplug/core/players.cxx                       |  107 -
 src/adplug/core/protrack.cc                       |  996 +++
 src/adplug/core/protrack.cxx                      |  996 ---
 src/adplug/core/protrack.h                        |    8 +-
 src/adplug/core/psi.cc                            |  187 +
 src/adplug/core/psi.cxx                           |  187 -
 src/adplug/core/rad.cc                            |  155 +
 src/adplug/core/rad.cxx                           |  155 -
 src/adplug/core/rad.h                             |    2 +-
 src/adplug/core/rat.cc                            |  311 +
 src/adplug/core/rat.cxx                           |  311 -
 src/adplug/core/raw.cc                            |  129 +
 src/adplug/core/raw.cxx                           |  129 -
 src/adplug/core/raw.h                             |    2 +-
 src/adplug/core/rix.cc                            |  611 ++
 src/adplug/core/rix.cxx                           |  612 --
 src/adplug/core/rix.h                             |    2 +-
 src/adplug/core/rol.cc                            |  747 ++
 src/adplug/core/rol.cxx                           |  750 --
 src/adplug/core/rol.h                             |    8 +-
 src/adplug/core/s3m.cc                            |  728 ++
 src/adplug/core/s3m.cxx                           |  728 --
 src/adplug/core/s3m.h                             |    4 +-
 src/adplug/core/sa2.cc                            |  314 +
 src/adplug/core/sa2.cxx                           |  314 -
 src/adplug/core/sa2.h                             |    2 +-
 src/adplug/core/sng.cc                            |  113 +
 src/adplug/core/sng.cxx                           |  113 -
 src/adplug/core/sng.h                             |    2 +-
 src/adplug/core/temuopl.cc                        |   85 +
 src/adplug/core/temuopl.cxx                       |   85 -
 src/adplug/core/temuopl.h                         |    8 +-
 src/adplug/core/u6m.cc                            | 1064 +++
 src/adplug/core/u6m.cxx                           | 1064 ---
 src/adplug/core/u6m.h                             |    3 +-
 src/adplug/core/xad.cc                            |  155 +
 src/adplug/core/xad.cxx                           |  155 -
 src/adplug/core/xad.h                             |    2 +-
 src/adplug/core/xsm.cc                            |  136 +
 src/adplug/core/xsm.cxx                           |  136 -
 src/adplug/core/xsm.h                             |    2 +-
 src/adplug/plugin.c                               |   22 -
 src/alarm/Makefile                                |   10 +-
 src/alarm/alarm.c                                 |  817 ---
 src/alarm/alarm.cc                                |  822 +++
 src/alarm/alarm.h                                 |    2 +-
 src/alarm/callbacks.h                             |   20 +-
 src/alarm/interface.c                             |  457 --
 src/alarm/interface.cc                            |  424 ++
 src/alarm/interface.h                             |    4 +-
 src/albumart-qt/Makefile                          |   13 +
 src/albumart-qt/albumart.cc                       |   89 +
 src/albumart/Makefile                             |    5 +-
 src/albumart/albumart.c                           |   75 -
 src/albumart/albumart.cc                          |   88 +
 src/alsa/Makefile                                 |   11 +-
 src/alsa/alsa.c                                   |  743 --
 src/alsa/alsa.cc                                  |  675 ++
 src/alsa/alsa.h                                   |   84 +-
 src/alsa/config.c                                 |  525 --
 src/alsa/config.cc                                |  330 +
 src/alsa/plugin.c                                 |   59 -
 src/amidi-plug/Makefile                           |   15 +-
 src/amidi-plug/amidi-plug.c                       |  477 --
 src/amidi-plug/amidi-plug.cc                      |  450 ++
 src/amidi-plug/amidi-plug.logo.xpm                |  743 --
 src/amidi-plug/amidi-plug.midiicon.xpm            |    2 +-
 src/amidi-plug/backend-fluidsynth/Makefile        |   12 -
 src/amidi-plug/backend-fluidsynth/b-fluidsynth.c  |  257 -
 src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc |  233 +
 src/amidi-plug/i_backend.h                        |   23 +-
 src/amidi-plug/i_configure-fluidsynth.c           |  277 -
 src/amidi-plug/i_configure-fluidsynth.cc          |  275 +
 src/amidi-plug/i_configure.c                      |  148 -
 src/amidi-plug/i_configure.cc                     |  156 +
 src/amidi-plug/i_configure.h                      |    4 +-
 src/amidi-plug/i_fileinfo.c                       |  381 -
 src/amidi-plug/i_fileinfo.cc                      |  340 +
 src/amidi-plug/i_fileinfo.h                       |    4 +-
 src/amidi-plug/i_midi.c                           |  897 ---
 src/amidi-plug/i_midi.cc                          |  803 +++
 src/amidi-plug/i_midi.h                           |   98 +-
 src/amidi-plug/i_midievent.h                      |   22 +-
 src/amidi-plug/i_utils.c                          |   73 -
 src/amidi-plug/i_utils.h                          |   26 -
 src/aosd/Makefile                                 |   14 +-
 src/aosd/aosd.c                                   |  101 -
 src/aosd/aosd.cc                                  |   59 +
 src/aosd/aosd.h                                   |   30 +-
 src/aosd/aosd_cfg.c                               |  403 --
 src/aosd/aosd_cfg.cc                              |  174 +
 src/aosd/aosd_cfg.h                               |   79 +-
 src/aosd/aosd_common.h                            |   33 -
 src/aosd/aosd_osd.c                               |  543 --
 src/aosd/aosd_osd.cc                              |  509 ++
 src/aosd/aosd_osd.h                               |    7 +-
 src/aosd/aosd_style.c                             |  391 -
 src/aosd/aosd_style.cc                            |  341 +
 src/aosd/aosd_style.h                             |   20 +-
 src/aosd/aosd_style_private.h                     |   17 +-
 src/aosd/aosd_trigger.c                           |  337 -
 src/aosd/aosd_trigger.cc                          |  284 +
 src/aosd/aosd_trigger.h                           |   16 +-
 src/aosd/aosd_trigger_private.h                   |   13 +-
 src/aosd/aosd_ui.c                                |  977 ---
 src/aosd/aosd_ui.cc                               |  886 +++
 src/aosd/aosd_ui.h                                |   33 -
 src/aosd/ghosd.c                                  |    2 -
 src/aosd/ghosd.h                                  |   10 +-
 src/asx/Makefile                                  |    8 +-
 src/asx/asx.c                                     |   87 -
 src/asx/asx.cc                                    |   80 +
 src/asx3/Makefile                                 |    8 +-
 src/asx3/asx3.c                                   |  184 -
 src/asx3/asx3.cc                                  |  187 +
 src/audpl/Makefile                                |    4 +-
 src/audpl/audpl.c                                 |  191 -
 src/audpl/audpl.cc                                |  170 +
 src/blur_scope/Makefile                           |    3 +-
 src/blur_scope/blur_scope.c                       |  232 -
 src/blur_scope/blur_scope.cc                      |  234 +
 src/bs2b/Makefile                                 |    7 +-
 src/bs2b/plugin.c                                 |  198 -
 src/bs2b/plugin.cc                                |  145 +
 src/cairo-spectrum/Makefile                       |    3 +-
 src/cairo-spectrum/cairo-spectrum.c               |  300 -
 src/cairo-spectrum/cairo-spectrum.cc              |  266 +
 src/cd-menu-items/Makefile                        |    3 +-
 src/cd-menu-items/cd-menu-items.c                 |   61 -
 src/cd-menu-items/cd-menu-items.cc                |   73 +
 src/cdaudio-ng/Makefile                           |    8 +-
 src/cdaudio-ng/cdaudio-ng.c                       |  873 ---
 src/cdaudio-ng/cdaudio-ng.cc                      |  815 +++
 src/compressor/Makefile                           |    7 +-
 src/compressor/compressor.c                       |  241 -
 src/compressor/compressor.cc                      |  232 +
 src/compressor/compressor.h                       |   28 -
 src/compressor/plugin.c                           |   70 -
 src/console/Audacious_Driver.cc                   |  292 +
 src/console/Audacious_Driver.cxx                  |  302 -
 src/console/Ay_Apu.cc                             |  395 ++
 src/console/Ay_Apu.cxx                            |  395 --
 src/console/Ay_Apu.h                              |    5 +-
 src/console/Ay_Cpu.cc                             | 1661 +++++
 src/console/Ay_Cpu.cxx                            | 1661 -----
 src/console/Ay_Emu.cc                             |  405 ++
 src/console/Ay_Emu.cxx                            |  405 --
 src/console/Ay_Emu.h                              |    1 -
 src/console/Blip_Buffer.cc                        |  460 ++
 src/console/Blip_Buffer.cxx                       |  460 --
 src/console/Blip_Buffer.h                         |    2 +-
 src/console/Classic_Emu.cc                        |  184 +
 src/console/Classic_Emu.cxx                       |  184 -
 src/console/Classic_Emu.h                         |    4 +-
 src/console/Data_Reader.cc                        |  315 +
 src/console/Data_Reader.cxx                       |  315 -
 src/console/Dual_Resampler.cc                     |  129 +
 src/console/Dual_Resampler.cxx                    |  131 -
 src/console/Effects_Buffer.cc                     |  529 ++
 src/console/Effects_Buffer.cxx                    |  529 --
 src/console/Fir_Resampler.cc                      |  199 +
 src/console/Fir_Resampler.cxx                     |  199 -
 src/console/Gb_Apu.cc                             |  306 +
 src/console/Gb_Apu.cxx                            |  306 -
 src/console/Gb_Apu.h                              |    4 +-
 src/console/Gb_Cpu.cc                             | 1052 +++
 src/console/Gb_Cpu.cxx                            | 1052 ---
 src/console/Gb_Oscs.cc                            |  336 +
 src/console/Gb_Oscs.cxx                           |  336 -
 src/console/Gb_Oscs.h                             |    2 +-
 src/console/Gbs_Emu.cc                            |  289 +
 src/console/Gbs_Emu.cxx                           |  289 -
 src/console/Gme_File.cc                           |  215 +
 src/console/Gme_File.cxx                          |  215 -
 src/console/Gme_File.h                            |    4 +-
 src/console/Gym_Emu.cc                            |  380 +
 src/console/Gym_Emu.cxx                           |  380 -
 src/console/Gzip_Reader.cc                        |  108 +
 src/console/Gzip_Reader.cxx                       |  108 -
 src/console/Hes_Apu.cc                            |  315 +
 src/console/Hes_Apu.cxx                           |  315 -
 src/console/Hes_Cpu.cc                            | 1301 ++++
 src/console/Hes_Cpu.cxx                           | 1301 ----
 src/console/Hes_Emu.cc                            |  531 ++
 src/console/Hes_Emu.cxx                           |  531 --
 src/console/Kss_Cpu.cc                            | 1704 +++++
 src/console/Kss_Cpu.cxx                           | 1704 -----
 src/console/Kss_Emu.cc                            |  416 ++
 src/console/Kss_Emu.cxx                           |  416 --
 src/console/Kss_Emu.h                             |    1 -
 src/console/Kss_Scc_Apu.cc                        |   97 +
 src/console/Kss_Scc_Apu.cxx                       |   97 -
 src/console/Kss_Scc_Apu.h                         |    4 +-
 src/console/M3u_Playlist.cc                       |  426 ++
 src/console/M3u_Playlist.cxx                      |  426 --
 src/console/Makefile                              |  106 +-
 src/console/Multi_Buffer.cc                       |  232 +
 src/console/Multi_Buffer.cxx                      |  232 -
 src/console/Music_Emu.cc                          |  411 ++
 src/console/Music_Emu.cxx                         |  411 --
 src/console/Nes_Apu.cc                            |  391 +
 src/console/Nes_Apu.cxx                           |  391 -
 src/console/Nes_Apu.h                             |   14 +-
 src/console/Nes_Cpu.cc                            | 1082 +++
 src/console/Nes_Cpu.cxx                           | 1082 ---
 src/console/Nes_Fme7_Apu.cc                       |  121 +
 src/console/Nes_Fme7_Apu.cxx                      |  121 -
 src/console/Nes_Fme7_Apu.h                        |    2 +-
 src/console/Nes_Namco_Apu.cc                      |  145 +
 src/console/Nes_Namco_Apu.cxx                     |  145 -
 src/console/Nes_Oscs.cc                           |  551 ++
 src/console/Nes_Oscs.cxx                          |  551 --
 src/console/Nes_Vrc6_Apu.cc                       |  215 +
 src/console/Nes_Vrc6_Apu.cxx                      |  215 -
 src/console/Nsf_Emu.cc                            |  559 ++
 src/console/Nsf_Emu.cxx                           |  559 --
 src/console/Nsfe_Emu.cc                           |  332 +
 src/console/Nsfe_Emu.cxx                          |  332 -
 src/console/Sap_Apu.cc                            |  334 +
 src/console/Sap_Apu.cxx                           |  334 -
 src/console/Sap_Cpu.cc                            | 1009 +++
 src/console/Sap_Cpu.cxx                           | 1009 ---
 src/console/Sap_Emu.cc                            |  525 ++
 src/console/Sap_Emu.cxx                           |  444 --
 src/console/Sap_Emu.h                             |    2 +
 src/console/Sms_Apu.cc                            |  330 +
 src/console/Sms_Apu.cxx                           |  330 -
 src/console/Sms_Apu.h                             |    4 +-
 src/console/Sms_Oscs.h                            |    2 +-
 src/console/Snes_Spc.cc                           |  380 +
 src/console/Snes_Spc.cxx                          |  380 -
 src/console/Snes_Spc.h                            |    2 +-
 src/console/Spc_Cpu.cc                            |  565 ++
 src/console/Spc_Cpu.cxx                           |  565 --
 src/console/Spc_Dsp.cc                            |  701 ++
 src/console/Spc_Dsp.cxx                           |  701 --
 src/console/Spc_Dsp.h                             |    2 +-
 src/console/Spc_Emu.cc                            |  352 +
 src/console/Spc_Emu.cxx                           |  352 -
 src/console/Spc_Filter.cc                         |   83 +
 src/console/Spc_Filter.cxx                        |   83 -
 src/console/Track_Emu.cc                          |  186 +
 src/console/Track_Emu.cxx                         |  186 -
 src/console/Vfs_File.cc                           |   57 +
 src/console/Vfs_File.cxx                          |   71 -
 src/console/Vfs_File.h                            |   12 +-
 src/console/Vgm_Emu.cc                            |  416 ++
 src/console/Vgm_Emu.cxx                           |  416 --
 src/console/Vgm_Emu_Impl.cc                       |  314 +
 src/console/Vgm_Emu_Impl.cxx                      |  314 -
 src/console/Vgm_Emu_Impl.h                        |    2 +-
 src/console/Ym2413_Emu.cc                         | 2216 ++++++
 src/console/Ym2413_Emu.cxx                        | 2224 ------
 src/console/Ym2612_Emu.cc                         | 1319 ++++
 src/console/Ym2612_Emu.cxx                        | 1319 ----
 src/console/Zlib_Inflater.cc                      |  175 +
 src/console/Zlib_Inflater.cxx                     |  175 -
 src/console/blargg_endian.h                       |   21 +-
 src/console/configure.c                           |   56 -
 src/console/configure.cc                          |   57 +
 src/console/configure.h                           |   20 +-
 src/console/gme.cc                                |  374 +
 src/console/gme.cxx                               |  374 -
 src/console/gme.h                                 |   21 +-
 src/console/gme_design.txt                        |    2 +-
 src/console/gme_notes.txt                         |   10 +-
 src/console/gme_type_list.cc                      |   38 +
 src/console/gme_type_list.cxx                     |   38 -
 src/console/plugin.c                              |   71 -
 src/console/plugin.cc                             |   56 +
 src/console/plugin.h                              |   47 +
 src/console/sap_cpu_io.h                          |   22 +-
 src/coreaudio/Makefile                            |   13 +
 src/coreaudio/coreaudio.cc                        |  470 ++
 src/crossfade/Makefile                            |    6 +-
 src/crossfade/crossfade.c                         |  284 -
 src/crossfade/crossfade.cc                        |  308 +
 src/crystalizer/Makefile                          |    3 +-
 src/crystalizer/crystalizer.c                     |  105 -
 src/crystalizer/crystalizer.cc                    |  105 +
 src/cue/Makefile                                  |    8 +-
 src/cue/cue.c                                     |  159 -
 src/cue/cue.cc                                    |  155 +
 src/delete-files/Makefile                         |    6 +-
 src/delete-files/delete-files.c                   |  177 -
 src/delete-files/delete-files.cc                  |  186 +
 src/echo_plugin/Makefile                          |    6 +-
 src/echo_plugin/echo.c                            |  132 -
 src/echo_plugin/echo.cc                           |  115 +
 src/ffaudio/Makefile                              |    8 +-
 src/ffaudio/ffaudio-core.c                        |  655 --
 src/ffaudio/ffaudio-core.cc                       |  622 ++
 src/ffaudio/ffaudio-io.c                          |   49 -
 src/ffaudio/ffaudio-io.cc                         |   48 +
 src/ffaudio/ffaudio-stdinc.h                      |   26 +-
 src/ffaudio/itunes-cover.cc                       |   91 +
 src/filewriter/Makefile                           |   14 +-
 src/filewriter/convert.c                          |   45 -
 src/filewriter/convert.cc                         |   43 +
 src/filewriter/convert.h                          |   10 +-
 src/filewriter/filewriter.c                       |  542 --
 src/filewriter/filewriter.cc                      |  507 ++
 src/filewriter/filewriter.h                       |   36 +-
 src/filewriter/flac.c                             |  204 -
 src/filewriter/flac.cc                            |  206 +
 src/filewriter/mp3.c                              | 1238 ----
 src/filewriter/mp3.cc                             | 1200 ++++
 src/filewriter/plugins.h                          |    8 +-
 src/filewriter/vorbis.c                           |  263 -
 src/filewriter/vorbis.cc                          |  248 +
 src/filewriter/wav.c                              |  147 -
 src/filewriter/wav.cc                             |  152 +
 src/flacng/Makefile                               |   14 +-
 src/flacng/flacng.h                               |   81 +-
 src/flacng/metadata.c                             |  444 --
 src/flacng/metadata.cc                            |  438 ++
 src/flacng/plugin.c                               |  207 -
 src/flacng/plugin.cc                              |  173 +
 src/flacng/seekable_stream_callbacks.c            |  170 -
 src/flacng/seekable_stream_callbacks.cc           |  173 +
 src/flacng/tools.c                                |   79 -
 src/flacng/tools.cc                               |   52 +
 src/gio/Makefile                                  |    4 +-
 src/gio/gio.c                                     |  319 -
 src/gio/gio.cc                                    |  388 +
 src/gl-spectrum-qt/Makefile                       |   13 +
 src/gl-spectrum-qt/gl-spectrum.cc                 |  292 +
 src/gl-spectrum/Makefile                          |    3 +-
 src/gl-spectrum/gl-spectrum.c                     |  416 --
 src/gl-spectrum/gl-spectrum.cc                    |  426 ++
 src/gnomeshortcuts/Makefile                       |    3 +-
 src/gnomeshortcuts/gnomeshortcuts.c               |  294 -
 src/gnomeshortcuts/gnomeshortcuts.cc              |  289 +
 src/gtkui/Makefile                                |   24 +-
 src/gtkui/columns.c                               |  332 -
 src/gtkui/columns.cc                              |  350 +
 src/gtkui/gtkui.h                                 |   23 +-
 src/gtkui/layout.c                                |  580 --
 src/gtkui/layout.cc                               |  616 ++
 src/gtkui/layout.h                                |   15 +-
 src/gtkui/menus.c                                 |  285 -
 src/gtkui/menus.cc                                |  293 +
 src/gtkui/playlist_util.c                         |  125 -
 src/gtkui/playlist_util.cc                        |  150 +
 src/gtkui/playlist_util.h                         |   13 +-
 src/gtkui/settings.c                              |   62 -
 src/gtkui/settings.cc                             |   54 +
 src/gtkui/ui_gtk.c                                | 1022 ---
 src/gtkui/ui_gtk.cc                               | 1120 +++
 src/gtkui/ui_infoarea.c                           |  597 --
 src/gtkui/ui_infoarea.cc                          |  566 ++
 src/gtkui/ui_infoarea.h                           |    4 +-
 src/gtkui/ui_playlist_notebook.c                  |  564 --
 src/gtkui/ui_playlist_notebook.cc                 |  573 ++
 src/gtkui/ui_playlist_notebook.h                  |   15 +-
 src/gtkui/ui_playlist_widget.c                    |  497 --
 src/gtkui/ui_playlist_widget.cc                   |  488 ++
 src/gtkui/ui_playlist_widget.h                    |   38 +-
 src/gtkui/ui_statusbar.c                          |  144 -
 src/gtkui/ui_statusbar.cc                         |  163 +
 src/gtkui/ui_statusbar.h                          |    2 +-
 src/hotkey/Makefile                               |    5 +-
 src/hotkey/grab.c                                 |  388 -
 src/hotkey/grab.cc                                |  388 +
 src/hotkey/gui.c                                  |  650 --
 src/hotkey/gui.cc                                 |  631 ++
 src/hotkey/gui.h                                  |    4 +-
 src/hotkey/plugin.c                               |  449 --
 src/hotkey/plugin.cc                              |  446 ++
 src/hotkey/plugin.h                               |    9 +-
 src/jack-ng/Makefile                              |   13 +
 src/jack-ng/jack-ng.cc                            |  402 ++
 src/jack/Makefile                                 |   13 -
 src/jack/bio2jack.c                               | 2652 -------
 src/jack/bio2jack.h                               |  145 -
 src/jack/jack.c                                   |  453 --
 src/jack/jack.h                                   |   16 -
 src/ladspa/Makefile                               |   12 +-
 src/ladspa/effect.c                               |  262 -
 src/ladspa/effect.cc                              |  241 +
 src/ladspa/ladspa.h                               |   20 +-
 src/ladspa/loaded-list.c                          |  135 -
 src/ladspa/loaded-list.cc                         |  125 +
 src/ladspa/plugin-list.c                          |   77 -
 src/ladspa/plugin-list.cc                         |   71 +
 src/ladspa/plugin.c                               |  687 --
 src/ladspa/plugin.cc                              |  560 ++
 src/ladspa/plugin.h                               |  110 +-
 src/lirc/Makefile                                 |    3 +-
 src/lirc/lirc.c                                   |  409 --
 src/lirc/lirc.cc                                  |  401 ++
 src/lyricwiki-qt/Makefile                         |   14 +
 src/lyricwiki-qt/lyricwiki.cc                     |  354 +
 src/lyricwiki/Makefile                            |    4 +-
 src/lyricwiki/lyricwiki.c                         |  416 --
 src/lyricwiki/lyricwiki.cc                        |  386 +
 src/m3u/Makefile                                  |    7 +-
 src/m3u/m3u.c                                     |  121 -
 src/m3u/m3u.cc                                    |  117 +
 src/mac-media-keys/MacMediaKeys.h                 |   40 +
 src/mac-media-keys/MacMediaKeys.mm                |  103 +
 src/mac-media-keys/Makefile                       |   16 +
 src/mac-media-keys/SPInvocationGrabbing.h         |   41 +
 src/mac-media-keys/SPInvocationGrabbing.m         |  138 +
 src/mac-media-keys/SPMediaKeyTap.h                |   54 +
 src/mac-media-keys/SPMediaKeyTap.m                |  356 +
 src/metronom/Makefile                             |    4 +-
 src/metronom/metronom.c                           |  234 -
 src/metronom/metronom.cc                          |  242 +
 src/mixer/Makefile                                |    6 +-
 src/mixer/mixer.c                                 |  196 -
 src/mixer/mixer.cc                                |  212 +
 src/mms/Makefile                                  |    4 +-
 src/mms/mms.c                                     |  199 -
 src/mms/mms.cc                                    |  196 +
 src/modplug/Makefile                              |   15 +-
 src/modplug/archive/arch_raw.cc                   |   49 +
 src/modplug/archive/arch_raw.cxx                  |   52 -
 src/modplug/archive/arch_raw.h                    |    4 +-
 src/modplug/archive/archive.cc                    |   78 +
 src/modplug/archive/archive.cxx                   |   78 -
 src/modplug/archive/open.cc                       |   15 +
 src/modplug/archive/open.cxx                      |   15 -
 src/modplug/modplugbmp.cc                         |  401 ++
 src/modplug/modplugbmp.cxx                        |  414 --
 src/modplug/modplugbmp.h                          |   52 +-
 src/modplug/plugin.cxx                            |   36 -
 src/modplug/plugin.h                              |   21 -
 src/modplug/plugin_main.c                         |  245 -
 src/modplug/plugin_main.cc                        |  158 +
 src/modplug/settings.h                            |   26 +-
 src/mpg123/Makefile                               |    4 +-
 src/mpg123/mpg123.c                               |  422 --
 src/mpg123/mpg123.cc                              |  426 ++
 src/mpris2/Makefile                               |    4 +-
 src/mpris2/plugin.c                               |  408 --
 src/mpris2/plugin.cc                              |  413 ++
 src/neon/Makefile                                 |   11 +-
 src/neon/cert_verification.c                      |  429 --
 src/neon/cert_verification.cc                     |  427 ++
 src/neon/debug.h                                  |   31 -
 src/neon/neon.c                                   | 1062 ---
 src/neon/neon.cc                                  | 1102 +++
 src/neon/neon.h                                   |   79 -
 src/neon/rb.c                                     |  203 -
 src/neon/rb.h                                     |   50 -
 src/notify/Makefile                               |    6 +-
 src/notify/event.c                                |  177 -
 src/notify/event.cc                               |  162 +
 src/notify/notify.c                               |   98 -
 src/notify/notify.cc                              |  118 +
 src/notify/osd.c                                  |  110 -
 src/notify/osd.cc                                 |  111 +
 src/oss4/Makefile                                 |    8 +-
 src/oss4/oss.c                                    |  316 -
 src/oss4/oss.cc                                   |  365 +
 src/oss4/oss.h                                    |  122 +-
 src/oss4/plugin.c                                 |  134 -
 src/oss4/plugin.cc                                |  103 +
 src/oss4/utils.c                                  |  205 -
 src/oss4/utils.cc                                 |  204 +
 src/playlist-manager/Makefile                     |   13 +
 src/playlist-manager/playlist-manager.cc          |  271 +
 src/pls/Makefile                                  |    6 +-
 src/pls/pls.c                                     |  107 -
 src/pls/pls.cc                                    |  100 +
 src/psf/Makefile                                  |   30 +-
 src/psf/ao.h                                      |   14 +-
 src/psf/corlett.c                                 |  389 -
 src/psf/corlett.cc                                |  390 +
 src/psf/cpuintrf.h                                |    4 +-
 src/psf/eng_protos.h                              |   10 +-
 src/psf/eng_psf.c                                 |  398 --
 src/psf/eng_psf.cc                                |  372 +
 src/psf/eng_psf2.c                                |  671 --
 src/psf/eng_psf2.cc                               |  662 ++
 src/psf/eng_spx.c                                 |  244 -
 src/psf/eng_spx.cc                                |  243 +
 src/psf/peops/License.txt                         |    3 +-
 src/psf/peops/adsr.c                              |  618 --
 src/psf/peops/adsr.cc                             |  618 ++
 src/psf/peops/dma.c                               |   80 -
 src/psf/peops/dma.cc                              |   80 +
 src/psf/peops/registers.c                         |  499 --
 src/psf/peops/registers.cc                        |  499 ++
 src/psf/peops/reverb.c                            |  383 -
 src/psf/peops/reverb.cc                           |  383 +
 src/psf/peops/spu.c                               |  673 --
 src/psf/peops/spu.cc                              |  671 ++
 src/psf/peops/spu.h                               |    2 +-
 src/psf/peops2/License.txt                        |    3 +-
 src/psf/peops2/adsr.c                             |  656 --
 src/psf/peops2/adsr.cc                            |  656 ++
 src/psf/peops2/dma.c                              |  175 -
 src/psf/peops2/dma.cc                             |  175 +
 src/psf/peops2/registers.c                        | 1343 ----
 src/psf/peops2/registers.cc                       | 1343 ++++
 src/psf/peops2/reverb.c                           |  420 --
 src/psf/peops2/reverb.cc                          |  420 ++
 src/psf/peops2/spu.c                              | 1036 ---
 src/psf/peops2/spu.cc                             | 1034 +++
 src/psf/peops2/spu.h                              |    2 +-
 src/psf/peops2/xa.c                               |  363 -
 src/psf/peops2/xa.cc                              |  363 +
 src/psf/plugin.c                                  |  215 -
 src/psf/plugin.cc                                 |  215 +
 src/psf/psx.c                                     | 3005 --------
 src/psf/psx.cc                                    | 3005 ++++++++
 src/psf/psx_hw.c                                  | 3543 ----------
 src/psf/psx_hw.cc                                 | 3542 ++++++++++
 src/pulse_audio/Makefile                          |    3 +-
 src/pulse_audio/pulse_audio.c                     |  677 --
 src/pulse_audio/pulse_audio.cc                    |  625 ++
 src/qtaudio/Makefile                              |   13 +
 src/qtaudio/qtaudio.cc                            |  302 +
 src/qtui/Makefile                                 |  107 +
 src/qtui/QtUi/16/audio-volume-high.png            |  Bin 0 -> 709 bytes
 src/qtui/QtUi/16/audio-volume-low.png             |  Bin 0 -> 577 bytes
 src/qtui/QtUi/16/audio-volume-medium.png          |  Bin 0 -> 632 bytes
 src/qtui/QtUi/16/audio-volume-muted.png           |  Bin 0 -> 527 bytes
 src/qtui/QtUi/16/audio-volume-off.png             |  Bin 0 -> 495 bytes
 src/qtui/QtUi/16/document-open.png                |  Bin 0 -> 585 bytes
 src/qtui/QtUi/16/edit-find.png                    |  Bin 0 -> 643 bytes
 src/qtui/QtUi/16/list-add.png                     |  Bin 0 -> 463 bytes
 src/qtui/QtUi/16/media-playback-pause.png         |  Bin 0 -> 380 bytes
 src/qtui/QtUi/16/media-playback-start.png         |  Bin 0 -> 437 bytes
 src/qtui/QtUi/16/media-playback-stop.png          |  Bin 0 -> 327 bytes
 src/qtui/QtUi/16/media-playlist-repeat.png        |  Bin 0 -> 555 bytes
 src/qtui/QtUi/16/media-playlist-shuffle.png       |  Bin 0 -> 652 bytes
 src/qtui/QtUi/16/media-skip-backward.png          |  Bin 0 -> 545 bytes
 src/qtui/QtUi/16/media-skip-forward.png           |  Bin 0 -> 543 bytes
 src/qtui/QtUi/22/audio-volume-high.png            |  Bin 0 -> 976 bytes
 src/qtui/QtUi/22/audio-volume-low.png             |  Bin 0 -> 741 bytes
 src/qtui/QtUi/22/audio-volume-medium.png          |  Bin 0 -> 877 bytes
 src/qtui/QtUi/22/audio-volume-muted.png           |  Bin 0 -> 663 bytes
 src/qtui/QtUi/22/audio-volume-off.png             |  Bin 0 -> 604 bytes
 src/qtui/QtUi/22/document-open.png                |  Bin 0 -> 604 bytes
 src/qtui/QtUi/22/edit-find.png                    |  Bin 0 -> 887 bytes
 src/qtui/QtUi/22/list-add.png                     |  Bin 0 -> 462 bytes
 src/qtui/QtUi/22/media-playback-pause.png         |  Bin 0 -> 279 bytes
 src/qtui/QtUi/22/media-playback-start.png         |  Bin 0 -> 555 bytes
 src/qtui/QtUi/22/media-playback-stop.png          |  Bin 0 -> 252 bytes
 src/qtui/QtUi/22/media-playlist-repeat.png        |  Bin 0 -> 676 bytes
 src/qtui/QtUi/22/media-playlist-shuffle.png       |  Bin 0 -> 793 bytes
 src/qtui/QtUi/22/media-skip-backward.png          |  Bin 0 -> 537 bytes
 src/qtui/QtUi/22/media-skip-forward.png           |  Bin 0 -> 469 bytes
 src/qtui/QtUi/32/audio-volume-high.png            |  Bin 0 -> 1687 bytes
 src/qtui/QtUi/32/audio-volume-low.png             |  Bin 0 -> 1279 bytes
 src/qtui/QtUi/32/audio-volume-medium.png          |  Bin 0 -> 1475 bytes
 src/qtui/QtUi/32/audio-volume-muted.png           |  Bin 0 -> 1093 bytes
 src/qtui/QtUi/32/audio-volume-off.png             |  Bin 0 -> 1036 bytes
 src/qtui/QtUi/32/document-open.png                |  Bin 0 -> 1053 bytes
 src/qtui/QtUi/32/edit-find.png                    |  Bin 0 -> 1469 bytes
 src/qtui/QtUi/32/list-add.png                     |  Bin 0 -> 581 bytes
 src/qtui/QtUi/32/media-playback-pause.png         |  Bin 0 -> 527 bytes
 src/qtui/QtUi/32/media-playback-start.png         |  Bin 0 -> 805 bytes
 src/qtui/QtUi/32/media-playback-stop.png          |  Bin 0 -> 388 bytes
 src/qtui/QtUi/32/media-playlist-repeat.png        |  Bin 0 -> 1109 bytes
 src/qtui/QtUi/32/media-playlist-shuffle.png       |  Bin 0 -> 1464 bytes
 src/qtui/QtUi/32/media-skip-backward.png          |  Bin 0 -> 1099 bytes
 src/qtui/QtUi/32/media-skip-forward.png           |  Bin 0 -> 1108 bytes
 src/qtui/QtUi/44/audio-volume-high.png            |  Bin 0 -> 2413 bytes
 src/qtui/QtUi/44/audio-volume-low.png             |  Bin 0 -> 1729 bytes
 src/qtui/QtUi/44/audio-volume-medium.png          |  Bin 0 -> 2072 bytes
 src/qtui/QtUi/44/audio-volume-muted.png           |  Bin 0 -> 1412 bytes
 src/qtui/QtUi/44/audio-volume-off.png             |  Bin 0 -> 1318 bytes
 src/qtui/QtUi/44/document-open.png                |  Bin 0 -> 1038 bytes
 src/qtui/QtUi/44/edit-find.png                    |  Bin 0 -> 2105 bytes
 src/qtui/QtUi/44/list-add.png                     |  Bin 0 -> 696 bytes
 src/qtui/QtUi/44/media-playback-pause.png         |  Bin 0 -> 402 bytes
 src/qtui/QtUi/44/media-playback-start.png         |  Bin 0 -> 1091 bytes
 src/qtui/QtUi/44/media-playback-stop.png          |  Bin 0 -> 350 bytes
 src/qtui/QtUi/44/media-playlist-repeat.png        |  Bin 0 -> 1339 bytes
 src/qtui/QtUi/44/media-playlist-shuffle.png       |  Bin 0 -> 1806 bytes
 src/qtui/QtUi/44/media-skip-backward.png          |  Bin 0 -> 996 bytes
 src/qtui/QtUi/44/media-skip-forward.png           |  Bin 0 -> 940 bytes
 src/qtui/QtUi/AUTHORS                             |    3 +
 src/qtui/QtUi/index.theme                         |   17 +
 src/qtui/dialog_windows.cc                        |   68 +
 src/qtui/dialog_windows.h                         |   53 +
 src/qtui/filter_input.cc                          |   56 +
 src/qtui/filter_input.h                           |   34 +
 src/qtui/info_bar.cc                              |  211 +
 src/qtui/info_bar.h                               |   96 +
 src/qtui/main_window.cc                           |  317 +
 src/qtui/main_window.h                            |  103 +
 src/qtui/main_window_actions.cc                   |  197 +
 src/qtui/playlist.cc                              |  287 +
 src/qtui/playlist.h                               |   63 +
 src/qtui/playlist_model.cc                        |  181 +
 src/qtui/playlist_model.h                         |   54 +
 src/qtui/playlist_tabs.cc                         |  239 +
 src/qtui/playlist_tabs.h                          |   82 +
 src/qtui/qtui.cc                                  |   83 +
 src/qtui/status_bar.cc                            |   99 +
 src/qtui/status_bar.h                             |   49 +
 src/qtui/time_slider.cc                           |  121 +
 src/qtui/time_slider.h                            |   61 +
 src/qtui/tool_bar.cc                              |   65 +
 src/qtui/tool_bar.h                               |   63 +
 src/resample/Makefile                             |    8 +-
 src/resample/resample.c                           |  225 -
 src/resample/resample.cc                          |  247 +
 src/scrobbler2/Makefile                           |   10 +-
 src/scrobbler2/config_window.c                    |  234 -
 src/scrobbler2/config_window.cc                   |  224 +
 src/scrobbler2/scrobbler.c                        |  308 -
 src/scrobbler2/scrobbler.cc                       |  291 +
 src/scrobbler2/scrobbler.h                        |   44 +-
 src/scrobbler2/scrobbler_communication.c          |  789 ---
 src/scrobbler2/scrobbler_communication.cc         |  703 ++
 src/scrobbler2/scrobbler_xml_parsing.c            |  322 -
 src/scrobbler2/scrobbler_xml_parsing.cc           |  300 +
 src/sdlout/Makefile                               |    8 +-
 src/sdlout/plugin.c                               |   48 -
 src/sdlout/sdlout.c                               |  348 -
 src/sdlout/sdlout.cc                              |  335 +
 src/sdlout/sdlout.h                               |   38 -
 src/search-tool/Makefile                          |    6 +-
 src/search-tool/search-tool.c                     |  792 ---
 src/search-tool/search-tool.cc                    |  759 ++
 src/sid/Makefile                                  |   13 +-
 src/sid/xmms-sid.c                                |  375 -
 src/sid/xmms-sid.cc                               |  326 +
 src/sid/xmms-sid.h                                |   31 +-
 src/sid/xs_config.c                               |   79 -
 src/sid/xs_config.cc                              |  140 +
 src/sid/xs_config.h                               |   37 +-
 src/sid/xs_length.c                               |  528 --
 src/sid/xs_length.h                               |   39 -
 src/sid/xs_md5.c                                  |   25 -
 src/sid/xs_md5.h                                  |   21 -
 src/sid/xs_player.h                               |   29 -
 src/sid/xs_sidplay2.cc                            |  372 +-
 src/sid/xs_sidplay2.h                             |   28 +-
 src/sid/xs_slsup.c                                |  273 -
 src/sid/xs_slsup.h                                |   29 -
 src/sid/xs_stil.c                                 |  429 --
 src/sid/xs_stil.h                                 |   41 -
 src/sid/xs_support.c                              |  116 -
 src/sid/xs_support.h                              |   28 -
 src/silence-removal/Makefile                      |   13 +
 src/silence-removal/silence-removal.cc            |  192 +
 src/skins/Makefile                                |   67 +-
 src/skins/actions-mainwin.h                       |    2 +
 src/skins/actions-playlist.h                      |    8 +
 src/skins/dnd.h                                   |   15 +-
 src/skins/drag-handle.c                           |  105 -
 src/skins/drag-handle.cc                          |  106 +
 src/skins/drag-handle.h                           |    4 +-
 src/skins/draw-compat.h                           |   21 +-
 src/skins/menus.c                                 |  322 -
 src/skins/menus.cc                                |  311 +
 src/skins/menus.h                                 |    3 +-
 src/skins/plugin-window.cc                        |  175 +
 src/skins/plugin-window.h                         |   33 +
 src/skins/plugin.c                                |  148 -
 src/skins/plugin.cc                               |  202 +
 src/skins/plugin.h                                |    6 +-
 src/skins/preset-browser.c                        |  169 -
 src/skins/preset-browser.cc                       |  158 +
 src/skins/preset-list.c                           |  468 --
 src/skins/preset-list.cc                          |  462 ++
 src/skins/skins_cfg.c                             |  355 -
 src/skins/skins_cfg.cc                            |  342 +
 src/skins/skins_cfg.h                             |   37 +-
 src/skins/surface.c                               |   72 -
 src/skins/surface.cc                              |   74 +
 src/skins/surface.h                               |   12 +-
 src/skins/ui_dock.c                               |  384 -
 src/skins/ui_dock.cc                              |  384 +
 src/skins/ui_dock.h                               |    8 +-
 src/skins/ui_equalizer.c                          |  526 --
 src/skins/ui_equalizer.cc                         |  498 ++
 src/skins/ui_equalizer.h                          |   23 +-
 src/skins/ui_main.c                               | 1297 ----
 src/skins/ui_main.cc                              | 1352 ++++
 src/skins/ui_main.h                               |   32 +-
 src/skins/ui_main_evlisteners.c                   |  345 -
 src/skins/ui_main_evlisteners.cc                  |  346 +
 src/skins/ui_playlist.c                           | 1124 ---
 src/skins/ui_playlist.cc                          | 1163 +++
 src/skins/ui_playlist.h                           |    6 +-
 src/skins/ui_skin.c                               |  821 ---
 src/skins/ui_skin.cc                              |  809 +++
 src/skins/ui_skin.h                               |  166 +-
 src/skins/ui_skin_load_ini.c                      |  440 --
 src/skins/ui_skin_load_ini.cc                     |  315 +
 src/skins/ui_skinned_button.c                     |  263 -
 src/skins/ui_skinned_button.cc                    |  264 +
 src/skins/ui_skinned_button.h                     |   10 +-
 src/skins/ui_skinned_equalizer_graph.c            |  143 -
 src/skins/ui_skinned_equalizer_graph.cc           |  147 +
 src/skins/ui_skinned_equalizer_slider.c           |  191 -
 src/skins/ui_skinned_equalizer_slider.cc          |  191 +
 src/skins/ui_skinned_equalizer_slider.h           |    6 +-
 src/skins/ui_skinned_horizontal_slider.c          |  238 -
 src/skins/ui_skinned_horizontal_slider.cc         |  241 +
 src/skins/ui_skinned_horizontal_slider.h          |   12 +-
 src/skins/ui_skinned_menurow.c                    |  149 -
 src/skins/ui_skinned_menurow.cc                   |  147 +
 src/skins/ui_skinned_monostereo.c                 |   65 -
 src/skins/ui_skinned_monostereo.cc                |   66 +
 src/skins/ui_skinned_monostereo.h                 |    2 +-
 src/skins/ui_skinned_number.c                     |   92 -
 src/skins/ui_skinned_number.cc                    |   93 +
 src/skins/ui_skinned_number.h                     |    4 +-
 src/skins/ui_skinned_playlist.c                   |  948 ---
 src/skins/ui_skinned_playlist.cc                  |  945 +++
 src/skins/ui_skinned_playlist.h                   |   16 +-
 src/skins/ui_skinned_playlist_slider.c            |  141 -
 src/skins/ui_skinned_playlist_slider.cc           |  144 +
 src/skins/ui_skinned_playlist_slider.h            |    4 +-
 src/skins/ui_skinned_playstatus.c                 |   81 -
 src/skins/ui_skinned_playstatus.cc                |   82 +
 src/skins/ui_skinned_playstatus.h                 |    2 +-
 src/skins/ui_skinned_textbox.c                    |  405 --
 src/skins/ui_skinned_textbox.cc                   |  412 ++
 src/skins/ui_skinned_textbox.h                    |   10 +-
 src/skins/ui_skinned_window.c                     |  196 -
 src/skins/ui_skinned_window.cc                    |  246 +
 src/skins/ui_skinned_window.h                     |    9 +-
 src/skins/ui_skinselector.c                       |  398 --
 src/skins/ui_skinselector.cc                      |  398 ++
 src/skins/ui_svis.c                               |  206 -
 src/skins/ui_svis.cc                              |  215 +
 src/skins/ui_vis.c                                |  316 -
 src/skins/ui_vis.cc                               |  325 +
 src/skins/ui_vis.h                                |    4 +-
 src/skins/util.c                                  |  453 --
 src/skins/util.cc                                 |  432 ++
 src/skins/util.h                                  |   28 +-
 src/skins/view.c                                  |  204 -
 src/skins/view.cc                                 |  222 +
 src/skins/view.h                                  |   23 +-
 src/sndfile/Makefile                              |    8 +-
 src/sndfile/plugin.c                              |  379 -
 src/sndfile/plugin.cc                             |  351 +
 src/sndio-ng/Makefile                             |   13 +
 src/sndio-ng/sndio.cc                             |  376 +
 src/sndio/Makefile                                |   12 -
 src/sndio/sndio.c                                 |  432 --
 src/song-info-qt/Makefile                         |   13 +
 src/song-info-qt/song-info.cc                     |   99 +
 src/song_change/Makefile                          |    4 +-
 src/song_change/formatter.c                       |  103 -
 src/song_change/formatter.cc                      |  104 +
 src/song_change/formatter.h                       |    8 +-
 src/song_change/song_change.c                     |  523 --
 src/song_change/song_change.cc                    |  415 ++
 src/sox-resampler/Makefile                        |    7 +-
 src/sox-resampler/sox-resampler.c                 |  175 -
 src/sox-resampler/sox-resampler.cc                |  166 +
 src/speed-pitch/Makefile                          |    7 +-
 src/speed-pitch/speed-pitch.c                     |  277 -
 src/speed-pitch/speed-pitch.cc                    |  237 +
 src/statusicon/Makefile                           |    8 +-
 src/statusicon/statusicon.c                       |  405 --
 src/statusicon/statusicon.cc                      |  395 ++
 src/statusicon/statusicon.h                       |   34 -
 src/statusicon/util.c                             |   35 -
 src/stereo_plugin/Makefile                        |    3 +-
 src/stereo_plugin/stereo.c                        |   82 -
 src/stereo_plugin/stereo.cc                       |   84 +
 src/tonegen/Makefile                              |    8 +-
 src/tonegen/tonegen.c                             |  190 -
 src/tonegen/tonegen.cc                            |  165 +
 src/voice_removal/Makefile                        |    3 +-
 src/voice_removal/voice_removal.c                 |   59 -
 src/voice_removal/voice_removal.cc                |   61 +
 src/vorbis/Makefile                               |    8 +-
 src/vorbis/vcedit.c                               |  469 --
 src/vorbis/vcedit.cc                              |  443 ++
 src/vorbis/vcedit.h                               |   30 +-
 src/vorbis/vcupdate.c                             |  219 -
 src/vorbis/vcupdate.cc                            |  210 +
 src/vorbis/vorbis.c                               |  517 --
 src/vorbis/vorbis.cc                              |  481 ++
 src/vorbis/vorbis.h                               |   29 +-
 src/vtx/Makefile                                  |   14 +-
 src/vtx/ay8912.c                                  |  495 --
 src/vtx/ay8912.cc                                 |  494 ++
 src/vtx/ayemu.h                                   |   10 +-
 src/vtx/ayemu_8912.h                              |   14 +-
 src/vtx/ayemu_vtxfile.h                           |   60 +-
 src/vtx/info.c                                    |   40 -
 src/vtx/info.cc                                   |   38 +
 src/vtx/lh5dec.c                                  |  300 -
 src/vtx/lh5dec.cc                                 |  305 +
 src/vtx/vtx.c                                     |  181 -
 src/vtx/vtx.cc                                    |  186 +
 src/vtx/vtx.h                                     |   12 +-
 src/vtx/vtxfile.c                                 |  331 -
 src/vtx/vtxfile.cc                                |  229 +
 src/wavpack/Makefile                              |    8 +-
 src/wavpack/wavpack.c                             |  279 -
 src/wavpack/wavpack.cc                            |  258 +
 src/xsf/Makefile                                  |   18 +-
 src/xsf/corlett.c                                 |  382 -
 src/xsf/corlett.cc                                |  385 +
 src/xsf/desmume/COPYING                           |    4 +-
 src/xsf/desmume/FIFO.c                            |   65 -
 src/xsf/desmume/FIFO.cc                           |   65 +
 src/xsf/desmume/FIFO.h                            |   10 +-
 src/xsf/desmume/GPU.c                             |   98 -
 src/xsf/desmume/GPU.cc                            |   98 +
 src/xsf/desmume/GPU.h                             |   16 +-
 src/xsf/desmume/MMU.c                             | 3565 ----------
 src/xsf/desmume/MMU.cc                            | 3526 +++++++++
 src/xsf/desmume/MMU.h                             |   41 +-
 src/xsf/desmume/NDSSystem.c                       |  748 --
 src/xsf/desmume/NDSSystem.cc                      |  748 ++
 src/xsf/desmume/NDSSystem.h                       |   55 +-
 src/xsf/desmume/SPU.c                             |  961 ---
 src/xsf/desmume/SPU.cc                            |  963 +++
 src/xsf/desmume/SPU.h                             |    2 +-
 src/xsf/desmume/arm_instructions.c                | 7857 ---------------------
 src/xsf/desmume/arm_instructions.cc               | 7857 +++++++++++++++++++++
 src/xsf/desmume/arm_instructions.h                |    2 +-
 src/xsf/desmume/armcpu.c                          |  487 --
 src/xsf/desmume/armcpu.cc                         |  487 ++
 src/xsf/desmume/armcpu.h                          |   19 +-
 src/xsf/desmume/bios.c                            | 1073 ---
 src/xsf/desmume/bios.cc                           | 1073 +++
 src/xsf/desmume/bios.h                            |    2 +-
 src/xsf/desmume/config.h                          |    2 +-
 src/xsf/desmume/cp15.c                            |  590 --
 src/xsf/desmume/cp15.cc                           |  590 ++
 src/xsf/desmume/cp15.h                            |    2 +-
 src/xsf/desmume/dscard.h                          |    2 +-
 src/xsf/desmume/instruction_tabdef.inc            |    2 +-
 src/xsf/desmume/matrix.c                          |  257 -
 src/xsf/desmume/matrix.cc                         |  257 +
 src/xsf/desmume/matrix.h                          |    2 +-
 src/xsf/desmume/mc.c                              |  121 -
 src/xsf/desmume/mc.cc                             |  121 +
 src/xsf/desmume/mc.h                              |   14 +-
 src/xsf/desmume/mem.h                             |    2 +-
 src/xsf/desmume/registers.h                       |    2 +-
 src/xsf/desmume/thumb_instructions.c              |  944 ---
 src/xsf/desmume/thumb_instructions.cc             |  944 +++
 src/xsf/desmume/thumb_instructions.h              |    2 +-
 src/xsf/desmume/thumb_tabdef.inc                  |    2 +-
 src/xsf/desmume/types.h                           |   10 +-
 src/xsf/plugin.c                                  |  223 -
 src/xsf/plugin.cc                                 |  242 +
 src/xsf/tagget.h                                  |    2 +-
 src/xsf/vio2sf.c                                  |  841 ---
 src/xsf/vio2sf.cc                                 |  828 +++
 src/xsf/vio2sf.h                                  |    5 +-
 src/xsf/xsfdrv.h                                  |    9 -
 src/xspf/Makefile                                 |    4 +-
 src/xspf/xspf.c                                   |  443 --
 src/xspf/xspf.cc                                  |  429 ++
 1038 files changed, 218366 insertions(+), 198382 deletions(-)
 delete mode 100644 .gitignore
 delete mode 100644 AUTHORS
 create mode 100644 po/ms.po
 create mode 100644 po/nl.po
 create mode 100644 po/sv.po
 delete mode 100644 src/aac-raw/aac.c
 create mode 100644 src/aac-raw/aac.cc
 delete mode 100644 src/aac/Makefile
 delete mode 100644 src/aac/itunes-cover.c
 delete mode 100644 src/aac/libmp4.c
 delete mode 100644 src/aac/mp4_utils.c
 delete mode 100644 src/aac/mp4ff/mp4atom.c
 delete mode 100644 src/aac/mp4ff/mp4ff.c
 delete mode 100644 src/aac/mp4ff/mp4ff.h
 delete mode 100644 src/aac/mp4ff/mp4ff_int_types.h
 delete mode 100644 src/aac/mp4ff/mp4ffint.h
 delete mode 100644 src/aac/mp4ff/mp4meta.c
 delete mode 100644 src/aac/mp4ff/mp4sample.c
 delete mode 100644 src/aac/mp4ff/mp4tagupdate.c
 delete mode 100644 src/aac/mp4ff/mp4util.c
 delete mode 100644 src/adplug/adplug-xmms.h
 create mode 100644 src/adplug/core/a2m.cc
 delete mode 100644 src/adplug/core/a2m.cxx
 create mode 100644 src/adplug/core/adl.cc
 delete mode 100644 src/adplug/core/adl.cxx
 delete mode 100644 src/adplug/core/adlibemu.c
 create mode 100644 src/adplug/core/adlibemu.cc
 create mode 100644 src/adplug/core/adplug.cc
 delete mode 100644 src/adplug/core/adplug.cxx
 create mode 100644 src/adplug/core/adtrack.cc
 delete mode 100644 src/adplug/core/adtrack.cxx
 create mode 100644 src/adplug/core/amd.cc
 delete mode 100644 src/adplug/core/amd.cxx
 create mode 100644 src/adplug/core/bam.cc
 delete mode 100644 src/adplug/core/bam.cxx
 create mode 100644 src/adplug/core/bmf.cc
 delete mode 100644 src/adplug/core/bmf.cxx
 create mode 100644 src/adplug/core/cff.cc
 delete mode 100644 src/adplug/core/cff.cxx
 create mode 100644 src/adplug/core/cmf.cc
 delete mode 100644 src/adplug/core/cmf.cxx
 create mode 100644 src/adplug/core/d00.cc
 delete mode 100644 src/adplug/core/d00.cxx
 create mode 100644 src/adplug/core/database.cc
 delete mode 100644 src/adplug/core/database.cxx
 delete mode 100644 src/adplug/core/debug.c
 create mode 100644 src/adplug/core/debug.cc
 create mode 100644 src/adplug/core/dfm.cc
 delete mode 100644 src/adplug/core/dfm.cxx
 create mode 100644 src/adplug/core/dmo.cc
 delete mode 100644 src/adplug/core/dmo.cxx
 create mode 100644 src/adplug/core/dro.cc
 delete mode 100644 src/adplug/core/dro.cxx
 create mode 100644 src/adplug/core/dro2.cc
 delete mode 100644 src/adplug/core/dro2.cxx
 create mode 100644 src/adplug/core/dtm.cc
 delete mode 100644 src/adplug/core/dtm.cxx
 create mode 100644 src/adplug/core/emuopl.cc
 delete mode 100644 src/adplug/core/emuopl.cxx
 create mode 100644 src/adplug/core/flash.cc
 delete mode 100644 src/adplug/core/flash.cxx
 create mode 100644 src/adplug/core/fmc.cc
 delete mode 100644 src/adplug/core/fmc.cxx
 delete mode 100644 src/adplug/core/fmopl.c
 create mode 100644 src/adplug/core/fmopl.cc
 create mode 100644 src/adplug/core/fprovide.cc
 delete mode 100644 src/adplug/core/fprovide.cxx
 create mode 100644 src/adplug/core/hsc.cc
 delete mode 100644 src/adplug/core/hsc.cxx
 create mode 100644 src/adplug/core/hsp.cc
 delete mode 100644 src/adplug/core/hsp.cxx
 create mode 100644 src/adplug/core/hybrid.cc
 delete mode 100644 src/adplug/core/hybrid.cxx
 create mode 100644 src/adplug/core/hyp.cc
 delete mode 100644 src/adplug/core/hyp.cxx
 create mode 100644 src/adplug/core/imf.cc
 delete mode 100644 src/adplug/core/imf.cxx
 create mode 100644 src/adplug/core/jbm.cc
 delete mode 100644 src/adplug/core/jbm.cxx
 create mode 100644 src/adplug/core/ksm.cc
 delete mode 100644 src/adplug/core/ksm.cxx
 create mode 100644 src/adplug/core/lds.cc
 delete mode 100644 src/adplug/core/lds.cxx
 create mode 100644 src/adplug/core/mad.cc
 delete mode 100644 src/adplug/core/mad.cxx
 create mode 100644 src/adplug/core/mid.cc
 delete mode 100644 src/adplug/core/mid.cxx
 create mode 100644 src/adplug/core/mkj.cc
 delete mode 100644 src/adplug/core/mkj.cxx
 create mode 100644 src/adplug/core/msc.cc
 delete mode 100644 src/adplug/core/msc.cxx
 create mode 100644 src/adplug/core/mtk.cc
 delete mode 100644 src/adplug/core/mtk.cxx
 create mode 100644 src/adplug/core/player.cc
 delete mode 100644 src/adplug/core/player.cxx
 create mode 100644 src/adplug/core/players.cc
 delete mode 100644 src/adplug/core/players.cxx
 create mode 100644 src/adplug/core/protrack.cc
 delete mode 100644 src/adplug/core/protrack.cxx
 create mode 100644 src/adplug/core/psi.cc
 delete mode 100644 src/adplug/core/psi.cxx
 create mode 100644 src/adplug/core/rad.cc
 delete mode 100644 src/adplug/core/rad.cxx
 create mode 100644 src/adplug/core/rat.cc
 delete mode 100644 src/adplug/core/rat.cxx
 create mode 100644 src/adplug/core/raw.cc
 delete mode 100644 src/adplug/core/raw.cxx
 create mode 100644 src/adplug/core/rix.cc
 delete mode 100644 src/adplug/core/rix.cxx
 create mode 100644 src/adplug/core/rol.cc
 delete mode 100644 src/adplug/core/rol.cxx
 create mode 100644 src/adplug/core/s3m.cc
 delete mode 100644 src/adplug/core/s3m.cxx
 create mode 100644 src/adplug/core/sa2.cc
 delete mode 100644 src/adplug/core/sa2.cxx
 create mode 100644 src/adplug/core/sng.cc
 delete mode 100644 src/adplug/core/sng.cxx
 create mode 100644 src/adplug/core/temuopl.cc
 delete mode 100644 src/adplug/core/temuopl.cxx
 create mode 100644 src/adplug/core/u6m.cc
 delete mode 100644 src/adplug/core/u6m.cxx
 create mode 100644 src/adplug/core/xad.cc
 delete mode 100644 src/adplug/core/xad.cxx
 create mode 100644 src/adplug/core/xsm.cc
 delete mode 100644 src/adplug/core/xsm.cxx
 delete mode 100644 src/adplug/plugin.c
 delete mode 100644 src/alarm/alarm.c
 create mode 100644 src/alarm/alarm.cc
 delete mode 100644 src/alarm/interface.c
 create mode 100644 src/alarm/interface.cc
 create mode 100644 src/albumart-qt/Makefile
 create mode 100644 src/albumart-qt/albumart.cc
 delete mode 100644 src/albumart/albumart.c
 create mode 100644 src/albumart/albumart.cc
 delete mode 100644 src/alsa/alsa.c
 create mode 100644 src/alsa/alsa.cc
 delete mode 100644 src/alsa/config.c
 create mode 100644 src/alsa/config.cc
 delete mode 100644 src/alsa/plugin.c
 delete mode 100644 src/amidi-plug/amidi-plug.c
 create mode 100644 src/amidi-plug/amidi-plug.cc
 delete mode 100644 src/amidi-plug/amidi-plug.logo.xpm
 delete mode 100644 src/amidi-plug/backend-fluidsynth/Makefile
 delete mode 100644 src/amidi-plug/backend-fluidsynth/b-fluidsynth.c
 create mode 100644 src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc
 delete mode 100644 src/amidi-plug/i_configure-fluidsynth.c
 create mode 100644 src/amidi-plug/i_configure-fluidsynth.cc
 delete mode 100644 src/amidi-plug/i_configure.c
 create mode 100644 src/amidi-plug/i_configure.cc
 delete mode 100644 src/amidi-plug/i_fileinfo.c
 create mode 100644 src/amidi-plug/i_fileinfo.cc
 delete mode 100644 src/amidi-plug/i_midi.c
 create mode 100644 src/amidi-plug/i_midi.cc
 delete mode 100644 src/amidi-plug/i_utils.c
 delete mode 100644 src/amidi-plug/i_utils.h
 delete mode 100644 src/aosd/aosd.c
 create mode 100644 src/aosd/aosd.cc
 delete mode 100644 src/aosd/aosd_cfg.c
 create mode 100644 src/aosd/aosd_cfg.cc
 delete mode 100644 src/aosd/aosd_common.h
 delete mode 100644 src/aosd/aosd_osd.c
 create mode 100644 src/aosd/aosd_osd.cc
 delete mode 100644 src/aosd/aosd_style.c
 create mode 100644 src/aosd/aosd_style.cc
 delete mode 100644 src/aosd/aosd_trigger.c
 create mode 100644 src/aosd/aosd_trigger.cc
 delete mode 100644 src/aosd/aosd_ui.c
 create mode 100644 src/aosd/aosd_ui.cc
 delete mode 100644 src/aosd/aosd_ui.h
 delete mode 100644 src/asx/asx.c
 create mode 100644 src/asx/asx.cc
 delete mode 100644 src/asx3/asx3.c
 create mode 100644 src/asx3/asx3.cc
 delete mode 100644 src/audpl/audpl.c
 create mode 100644 src/audpl/audpl.cc
 delete mode 100644 src/blur_scope/blur_scope.c
 create mode 100644 src/blur_scope/blur_scope.cc
 delete mode 100644 src/bs2b/plugin.c
 create mode 100644 src/bs2b/plugin.cc
 delete mode 100644 src/cairo-spectrum/cairo-spectrum.c
 create mode 100644 src/cairo-spectrum/cairo-spectrum.cc
 delete mode 100644 src/cd-menu-items/cd-menu-items.c
 create mode 100644 src/cd-menu-items/cd-menu-items.cc
 delete mode 100644 src/cdaudio-ng/cdaudio-ng.c
 create mode 100644 src/cdaudio-ng/cdaudio-ng.cc
 delete mode 100644 src/compressor/compressor.c
 create mode 100644 src/compressor/compressor.cc
 delete mode 100644 src/compressor/compressor.h
 delete mode 100644 src/compressor/plugin.c
 create mode 100644 src/console/Audacious_Driver.cc
 delete mode 100644 src/console/Audacious_Driver.cxx
 create mode 100644 src/console/Ay_Apu.cc
 delete mode 100644 src/console/Ay_Apu.cxx
 create mode 100644 src/console/Ay_Cpu.cc
 delete mode 100644 src/console/Ay_Cpu.cxx
 create mode 100644 src/console/Ay_Emu.cc
 delete mode 100644 src/console/Ay_Emu.cxx
 create mode 100644 src/console/Blip_Buffer.cc
 delete mode 100644 src/console/Blip_Buffer.cxx
 create mode 100644 src/console/Classic_Emu.cc
 delete mode 100644 src/console/Classic_Emu.cxx
 create mode 100644 src/console/Data_Reader.cc
 delete mode 100644 src/console/Data_Reader.cxx
 create mode 100644 src/console/Dual_Resampler.cc
 delete mode 100644 src/console/Dual_Resampler.cxx
 create mode 100644 src/console/Effects_Buffer.cc
 delete mode 100644 src/console/Effects_Buffer.cxx
 create mode 100644 src/console/Fir_Resampler.cc
 delete mode 100644 src/console/Fir_Resampler.cxx
 create mode 100644 src/console/Gb_Apu.cc
 delete mode 100644 src/console/Gb_Apu.cxx
 create mode 100644 src/console/Gb_Cpu.cc
 delete mode 100644 src/console/Gb_Cpu.cxx
 create mode 100644 src/console/Gb_Oscs.cc
 delete mode 100644 src/console/Gb_Oscs.cxx
 create mode 100644 src/console/Gbs_Emu.cc
 delete mode 100644 src/console/Gbs_Emu.cxx
 create mode 100644 src/console/Gme_File.cc
 delete mode 100644 src/console/Gme_File.cxx
 create mode 100644 src/console/Gym_Emu.cc
 delete mode 100644 src/console/Gym_Emu.cxx
 create mode 100644 src/console/Gzip_Reader.cc
 delete mode 100644 src/console/Gzip_Reader.cxx
 create mode 100644 src/console/Hes_Apu.cc
 delete mode 100644 src/console/Hes_Apu.cxx
 create mode 100644 src/console/Hes_Cpu.cc
 delete mode 100644 src/console/Hes_Cpu.cxx
 create mode 100644 src/console/Hes_Emu.cc
 delete mode 100644 src/console/Hes_Emu.cxx
 create mode 100644 src/console/Kss_Cpu.cc
 delete mode 100644 src/console/Kss_Cpu.cxx
 create mode 100644 src/console/Kss_Emu.cc
 delete mode 100644 src/console/Kss_Emu.cxx
 create mode 100644 src/console/Kss_Scc_Apu.cc
 delete mode 100644 src/console/Kss_Scc_Apu.cxx
 create mode 100644 src/console/M3u_Playlist.cc
 delete mode 100644 src/console/M3u_Playlist.cxx
 create mode 100644 src/console/Multi_Buffer.cc
 delete mode 100644 src/console/Multi_Buffer.cxx
 create mode 100644 src/console/Music_Emu.cc
 delete mode 100644 src/console/Music_Emu.cxx
 create mode 100644 src/console/Nes_Apu.cc
 delete mode 100644 src/console/Nes_Apu.cxx
 create mode 100644 src/console/Nes_Cpu.cc
 delete mode 100644 src/console/Nes_Cpu.cxx
 create mode 100644 src/console/Nes_Fme7_Apu.cc
 delete mode 100644 src/console/Nes_Fme7_Apu.cxx
 create mode 100644 src/console/Nes_Namco_Apu.cc
 delete mode 100644 src/console/Nes_Namco_Apu.cxx
 create mode 100644 src/console/Nes_Oscs.cc
 delete mode 100644 src/console/Nes_Oscs.cxx
 create mode 100644 src/console/Nes_Vrc6_Apu.cc
 delete mode 100644 src/console/Nes_Vrc6_Apu.cxx
 create mode 100644 src/console/Nsf_Emu.cc
 delete mode 100644 src/console/Nsf_Emu.cxx
 create mode 100644 src/console/Nsfe_Emu.cc
 delete mode 100644 src/console/Nsfe_Emu.cxx
 create mode 100644 src/console/Sap_Apu.cc
 delete mode 100644 src/console/Sap_Apu.cxx
 create mode 100644 src/console/Sap_Cpu.cc
 delete mode 100644 src/console/Sap_Cpu.cxx
 create mode 100644 src/console/Sap_Emu.cc
 delete mode 100644 src/console/Sap_Emu.cxx
 create mode 100644 src/console/Sms_Apu.cc
 delete mode 100644 src/console/Sms_Apu.cxx
 create mode 100644 src/console/Snes_Spc.cc
 delete mode 100644 src/console/Snes_Spc.cxx
 create mode 100644 src/console/Spc_Cpu.cc
 delete mode 100644 src/console/Spc_Cpu.cxx
 create mode 100644 src/console/Spc_Dsp.cc
 delete mode 100644 src/console/Spc_Dsp.cxx
 create mode 100644 src/console/Spc_Emu.cc
 delete mode 100644 src/console/Spc_Emu.cxx
 create mode 100644 src/console/Spc_Filter.cc
 delete mode 100644 src/console/Spc_Filter.cxx
 create mode 100644 src/console/Track_Emu.cc
 delete mode 100644 src/console/Track_Emu.cxx
 create mode 100644 src/console/Vfs_File.cc
 delete mode 100644 src/console/Vfs_File.cxx
 create mode 100644 src/console/Vgm_Emu.cc
 delete mode 100644 src/console/Vgm_Emu.cxx
 create mode 100644 src/console/Vgm_Emu_Impl.cc
 delete mode 100644 src/console/Vgm_Emu_Impl.cxx
 create mode 100644 src/console/Ym2413_Emu.cc
 delete mode 100644 src/console/Ym2413_Emu.cxx
 create mode 100644 src/console/Ym2612_Emu.cc
 delete mode 100644 src/console/Ym2612_Emu.cxx
 create mode 100644 src/console/Zlib_Inflater.cc
 delete mode 100644 src/console/Zlib_Inflater.cxx
 delete mode 100644 src/console/configure.c
 create mode 100644 src/console/configure.cc
 create mode 100644 src/console/gme.cc
 delete mode 100644 src/console/gme.cxx
 create mode 100644 src/console/gme_type_list.cc
 delete mode 100644 src/console/gme_type_list.cxx
 delete mode 100644 src/console/plugin.c
 create mode 100644 src/console/plugin.cc
 create mode 100644 src/console/plugin.h
 create mode 100644 src/coreaudio/Makefile
 create mode 100644 src/coreaudio/coreaudio.cc
 delete mode 100644 src/crossfade/crossfade.c
 create mode 100644 src/crossfade/crossfade.cc
 delete mode 100644 src/crystalizer/crystalizer.c
 create mode 100644 src/crystalizer/crystalizer.cc
 delete mode 100644 src/cue/cue.c
 create mode 100644 src/cue/cue.cc
 delete mode 100644 src/delete-files/delete-files.c
 create mode 100644 src/delete-files/delete-files.cc
 delete mode 100644 src/echo_plugin/echo.c
 create mode 100644 src/echo_plugin/echo.cc
 delete mode 100644 src/ffaudio/ffaudio-core.c
 create mode 100644 src/ffaudio/ffaudio-core.cc
 delete mode 100644 src/ffaudio/ffaudio-io.c
 create mode 100644 src/ffaudio/ffaudio-io.cc
 create mode 100644 src/ffaudio/itunes-cover.cc
 delete mode 100644 src/filewriter/convert.c
 create mode 100644 src/filewriter/convert.cc
 delete mode 100644 src/filewriter/filewriter.c
 create mode 100644 src/filewriter/filewriter.cc
 delete mode 100644 src/filewriter/flac.c
 create mode 100644 src/filewriter/flac.cc
 delete mode 100644 src/filewriter/mp3.c
 create mode 100644 src/filewriter/mp3.cc
 delete mode 100644 src/filewriter/vorbis.c
 create mode 100644 src/filewriter/vorbis.cc
 delete mode 100644 src/filewriter/wav.c
 create mode 100644 src/filewriter/wav.cc
 delete mode 100644 src/flacng/metadata.c
 create mode 100644 src/flacng/metadata.cc
 delete mode 100644 src/flacng/plugin.c
 create mode 100644 src/flacng/plugin.cc
 delete mode 100644 src/flacng/seekable_stream_callbacks.c
 create mode 100644 src/flacng/seekable_stream_callbacks.cc
 delete mode 100644 src/flacng/tools.c
 create mode 100644 src/flacng/tools.cc
 delete mode 100644 src/gio/gio.c
 create mode 100644 src/gio/gio.cc
 create mode 100644 src/gl-spectrum-qt/Makefile
 create mode 100644 src/gl-spectrum-qt/gl-spectrum.cc
 delete mode 100644 src/gl-spectrum/gl-spectrum.c
 create mode 100644 src/gl-spectrum/gl-spectrum.cc
 delete mode 100644 src/gnomeshortcuts/gnomeshortcuts.c
 create mode 100644 src/gnomeshortcuts/gnomeshortcuts.cc
 delete mode 100644 src/gtkui/columns.c
 create mode 100644 src/gtkui/columns.cc
 delete mode 100644 src/gtkui/layout.c
 create mode 100644 src/gtkui/layout.cc
 delete mode 100644 src/gtkui/menus.c
 create mode 100644 src/gtkui/menus.cc
 delete mode 100644 src/gtkui/playlist_util.c
 create mode 100644 src/gtkui/playlist_util.cc
 delete mode 100644 src/gtkui/settings.c
 create mode 100644 src/gtkui/settings.cc
 delete mode 100644 src/gtkui/ui_gtk.c
 create mode 100644 src/gtkui/ui_gtk.cc
 delete mode 100644 src/gtkui/ui_infoarea.c
 create mode 100644 src/gtkui/ui_infoarea.cc
 delete mode 100644 src/gtkui/ui_playlist_notebook.c
 create mode 100644 src/gtkui/ui_playlist_notebook.cc
 delete mode 100644 src/gtkui/ui_playlist_widget.c
 create mode 100644 src/gtkui/ui_playlist_widget.cc
 delete mode 100644 src/gtkui/ui_statusbar.c
 create mode 100644 src/gtkui/ui_statusbar.cc
 delete mode 100644 src/hotkey/grab.c
 create mode 100644 src/hotkey/grab.cc
 delete mode 100644 src/hotkey/gui.c
 create mode 100644 src/hotkey/gui.cc
 delete mode 100644 src/hotkey/plugin.c
 create mode 100644 src/hotkey/plugin.cc
 create mode 100644 src/jack-ng/Makefile
 create mode 100644 src/jack-ng/jack-ng.cc
 delete mode 100644 src/jack/Makefile
 delete mode 100644 src/jack/bio2jack.c
 delete mode 100644 src/jack/bio2jack.h
 delete mode 100644 src/jack/jack.c
 delete mode 100644 src/jack/jack.h
 delete mode 100644 src/ladspa/effect.c
 create mode 100644 src/ladspa/effect.cc
 delete mode 100644 src/ladspa/loaded-list.c
 create mode 100644 src/ladspa/loaded-list.cc
 delete mode 100644 src/ladspa/plugin-list.c
 create mode 100644 src/ladspa/plugin-list.cc
 delete mode 100644 src/ladspa/plugin.c
 create mode 100644 src/ladspa/plugin.cc
 delete mode 100644 src/lirc/lirc.c
 create mode 100644 src/lirc/lirc.cc
 create mode 100644 src/lyricwiki-qt/Makefile
 create mode 100644 src/lyricwiki-qt/lyricwiki.cc
 delete mode 100644 src/lyricwiki/lyricwiki.c
 create mode 100644 src/lyricwiki/lyricwiki.cc
 delete mode 100644 src/m3u/m3u.c
 create mode 100644 src/m3u/m3u.cc
 create mode 100644 src/mac-media-keys/MacMediaKeys.h
 create mode 100644 src/mac-media-keys/MacMediaKeys.mm
 create mode 100644 src/mac-media-keys/Makefile
 create mode 100644 src/mac-media-keys/SPInvocationGrabbing.h
 create mode 100644 src/mac-media-keys/SPInvocationGrabbing.m
 create mode 100644 src/mac-media-keys/SPMediaKeyTap.h
 create mode 100644 src/mac-media-keys/SPMediaKeyTap.m
 delete mode 100644 src/metronom/metronom.c
 create mode 100644 src/metronom/metronom.cc
 delete mode 100644 src/mixer/mixer.c
 create mode 100644 src/mixer/mixer.cc
 delete mode 100644 src/mms/mms.c
 create mode 100644 src/mms/mms.cc
 create mode 100644 src/modplug/archive/arch_raw.cc
 delete mode 100644 src/modplug/archive/arch_raw.cxx
 create mode 100644 src/modplug/archive/archive.cc
 delete mode 100644 src/modplug/archive/archive.cxx
 create mode 100644 src/modplug/archive/open.cc
 delete mode 100644 src/modplug/archive/open.cxx
 create mode 100644 src/modplug/modplugbmp.cc
 delete mode 100644 src/modplug/modplugbmp.cxx
 delete mode 100644 src/modplug/plugin.cxx
 delete mode 100644 src/modplug/plugin.h
 delete mode 100644 src/modplug/plugin_main.c
 create mode 100644 src/modplug/plugin_main.cc
 delete mode 100644 src/mpg123/mpg123.c
 create mode 100644 src/mpg123/mpg123.cc
 delete mode 100644 src/mpris2/plugin.c
 create mode 100644 src/mpris2/plugin.cc
 delete mode 100644 src/neon/cert_verification.c
 create mode 100644 src/neon/cert_verification.cc
 delete mode 100644 src/neon/debug.h
 delete mode 100644 src/neon/neon.c
 create mode 100644 src/neon/neon.cc
 delete mode 100644 src/neon/neon.h
 delete mode 100644 src/neon/rb.c
 delete mode 100644 src/neon/rb.h
 delete mode 100644 src/notify/event.c
 create mode 100644 src/notify/event.cc
 delete mode 100644 src/notify/notify.c
 create mode 100644 src/notify/notify.cc
 delete mode 100644 src/notify/osd.c
 create mode 100644 src/notify/osd.cc
 delete mode 100644 src/oss4/oss.c
 create mode 100644 src/oss4/oss.cc
 delete mode 100644 src/oss4/plugin.c
 create mode 100644 src/oss4/plugin.cc
 delete mode 100644 src/oss4/utils.c
 create mode 100644 src/oss4/utils.cc
 create mode 100644 src/playlist-manager/Makefile
 create mode 100644 src/playlist-manager/playlist-manager.cc
 delete mode 100644 src/pls/pls.c
 create mode 100644 src/pls/pls.cc
 delete mode 100644 src/psf/corlett.c
 create mode 100644 src/psf/corlett.cc
 delete mode 100644 src/psf/eng_psf.c
 create mode 100644 src/psf/eng_psf.cc
 delete mode 100644 src/psf/eng_psf2.c
 create mode 100644 src/psf/eng_psf2.cc
 delete mode 100644 src/psf/eng_spx.c
 create mode 100644 src/psf/eng_spx.cc
 delete mode 100644 src/psf/peops/adsr.c
 create mode 100644 src/psf/peops/adsr.cc
 delete mode 100644 src/psf/peops/dma.c
 create mode 100644 src/psf/peops/dma.cc
 delete mode 100644 src/psf/peops/registers.c
 create mode 100644 src/psf/peops/registers.cc
 delete mode 100644 src/psf/peops/reverb.c
 create mode 100644 src/psf/peops/reverb.cc
 delete mode 100644 src/psf/peops/spu.c
 create mode 100644 src/psf/peops/spu.cc
 delete mode 100644 src/psf/peops2/adsr.c
 create mode 100644 src/psf/peops2/adsr.cc
 delete mode 100644 src/psf/peops2/dma.c
 create mode 100644 src/psf/peops2/dma.cc
 delete mode 100644 src/psf/peops2/registers.c
 create mode 100644 src/psf/peops2/registers.cc
 delete mode 100644 src/psf/peops2/reverb.c
 create mode 100644 src/psf/peops2/reverb.cc
 delete mode 100644 src/psf/peops2/spu.c
 create mode 100644 src/psf/peops2/spu.cc
 delete mode 100644 src/psf/peops2/xa.c
 create mode 100644 src/psf/peops2/xa.cc
 delete mode 100644 src/psf/plugin.c
 create mode 100644 src/psf/plugin.cc
 delete mode 100644 src/psf/psx.c
 create mode 100644 src/psf/psx.cc
 delete mode 100644 src/psf/psx_hw.c
 create mode 100644 src/psf/psx_hw.cc
 delete mode 100644 src/pulse_audio/pulse_audio.c
 create mode 100644 src/pulse_audio/pulse_audio.cc
 create mode 100644 src/qtaudio/Makefile
 create mode 100644 src/qtaudio/qtaudio.cc
 create mode 100644 src/qtui/Makefile
 create mode 100644 src/qtui/QtUi/16/audio-volume-high.png
 create mode 100644 src/qtui/QtUi/16/audio-volume-low.png
 create mode 100644 src/qtui/QtUi/16/audio-volume-medium.png
 create mode 100644 src/qtui/QtUi/16/audio-volume-muted.png
 create mode 100644 src/qtui/QtUi/16/audio-volume-off.png
 create mode 100644 src/qtui/QtUi/16/document-open.png
 create mode 100644 src/qtui/QtUi/16/edit-find.png
 create mode 100644 src/qtui/QtUi/16/list-add.png
 create mode 100644 src/qtui/QtUi/16/media-playback-pause.png
 create mode 100644 src/qtui/QtUi/16/media-playback-start.png
 create mode 100644 src/qtui/QtUi/16/media-playback-stop.png
 create mode 100644 src/qtui/QtUi/16/media-playlist-repeat.png
 create mode 100644 src/qtui/QtUi/16/media-playlist-shuffle.png
 create mode 100644 src/qtui/QtUi/16/media-skip-backward.png
 create mode 100644 src/qtui/QtUi/16/media-skip-forward.png
 create mode 100644 src/qtui/QtUi/22/audio-volume-high.png
 create mode 100644 src/qtui/QtUi/22/audio-volume-low.png
 create mode 100644 src/qtui/QtUi/22/audio-volume-medium.png
 create mode 100644 src/qtui/QtUi/22/audio-volume-muted.png
 create mode 100644 src/qtui/QtUi/22/audio-volume-off.png
 create mode 100644 src/qtui/QtUi/22/document-open.png
 create mode 100644 src/qtui/QtUi/22/edit-find.png
 create mode 100644 src/qtui/QtUi/22/list-add.png
 create mode 100644 src/qtui/QtUi/22/media-playback-pause.png
 create mode 100644 src/qtui/QtUi/22/media-playback-start.png
 create mode 100644 src/qtui/QtUi/22/media-playback-stop.png
 create mode 100644 src/qtui/QtUi/22/media-playlist-repeat.png
 create mode 100644 src/qtui/QtUi/22/media-playlist-shuffle.png
 create mode 100644 src/qtui/QtUi/22/media-skip-backward.png
 create mode 100644 src/qtui/QtUi/22/media-skip-forward.png
 create mode 100644 src/qtui/QtUi/32/audio-volume-high.png
 create mode 100644 src/qtui/QtUi/32/audio-volume-low.png
 create mode 100644 src/qtui/QtUi/32/audio-volume-medium.png
 create mode 100644 src/qtui/QtUi/32/audio-volume-muted.png
 create mode 100644 src/qtui/QtUi/32/audio-volume-off.png
 create mode 100644 src/qtui/QtUi/32/document-open.png
 create mode 100644 src/qtui/QtUi/32/edit-find.png
 create mode 100644 src/qtui/QtUi/32/list-add.png
 create mode 100644 src/qtui/QtUi/32/media-playback-pause.png
 create mode 100644 src/qtui/QtUi/32/media-playback-start.png
 create mode 100644 src/qtui/QtUi/32/media-playback-stop.png
 create mode 100644 src/qtui/QtUi/32/media-playlist-repeat.png
 create mode 100644 src/qtui/QtUi/32/media-playlist-shuffle.png
 create mode 100644 src/qtui/QtUi/32/media-skip-backward.png
 create mode 100644 src/qtui/QtUi/32/media-skip-forward.png
 create mode 100644 src/qtui/QtUi/44/audio-volume-high.png
 create mode 100644 src/qtui/QtUi/44/audio-volume-low.png
 create mode 100644 src/qtui/QtUi/44/audio-volume-medium.png
 create mode 100644 src/qtui/QtUi/44/audio-volume-muted.png
 create mode 100644 src/qtui/QtUi/44/audio-volume-off.png
 create mode 100644 src/qtui/QtUi/44/document-open.png
 create mode 100644 src/qtui/QtUi/44/edit-find.png
 create mode 100644 src/qtui/QtUi/44/list-add.png
 create mode 100644 src/qtui/QtUi/44/media-playback-pause.png
 create mode 100644 src/qtui/QtUi/44/media-playback-start.png
 create mode 100644 src/qtui/QtUi/44/media-playback-stop.png
 create mode 100644 src/qtui/QtUi/44/media-playlist-repeat.png
 create mode 100644 src/qtui/QtUi/44/media-playlist-shuffle.png
 create mode 100644 src/qtui/QtUi/44/media-skip-backward.png
 create mode 100644 src/qtui/QtUi/44/media-skip-forward.png
 create mode 100644 src/qtui/QtUi/AUTHORS
 create mode 100644 src/qtui/QtUi/index.theme
 create mode 100644 src/qtui/dialog_windows.cc
 create mode 100644 src/qtui/dialog_windows.h
 create mode 100644 src/qtui/filter_input.cc
 create mode 100644 src/qtui/filter_input.h
 create mode 100644 src/qtui/info_bar.cc
 create mode 100644 src/qtui/info_bar.h
 create mode 100644 src/qtui/main_window.cc
 create mode 100644 src/qtui/main_window.h
 create mode 100644 src/qtui/main_window_actions.cc
 create mode 100644 src/qtui/playlist.cc
 create mode 100644 src/qtui/playlist.h
 create mode 100644 src/qtui/playlist_model.cc
 create mode 100644 src/qtui/playlist_model.h
 create mode 100644 src/qtui/playlist_tabs.cc
 create mode 100644 src/qtui/playlist_tabs.h
 create mode 100644 src/qtui/qtui.cc
 create mode 100644 src/qtui/status_bar.cc
 create mode 100644 src/qtui/status_bar.h
 create mode 100644 src/qtui/time_slider.cc
 create mode 100644 src/qtui/time_slider.h
 create mode 100644 src/qtui/tool_bar.cc
 create mode 100644 src/qtui/tool_bar.h
 delete mode 100644 src/resample/resample.c
 create mode 100644 src/resample/resample.cc
 delete mode 100644 src/scrobbler2/config_window.c
 create mode 100644 src/scrobbler2/config_window.cc
 delete mode 100644 src/scrobbler2/scrobbler.c
 create mode 100644 src/scrobbler2/scrobbler.cc
 delete mode 100644 src/scrobbler2/scrobbler_communication.c
 create mode 100644 src/scrobbler2/scrobbler_communication.cc
 delete mode 100644 src/scrobbler2/scrobbler_xml_parsing.c
 create mode 100644 src/scrobbler2/scrobbler_xml_parsing.cc
 delete mode 100644 src/sdlout/plugin.c
 delete mode 100644 src/sdlout/sdlout.c
 create mode 100644 src/sdlout/sdlout.cc
 delete mode 100644 src/sdlout/sdlout.h
 delete mode 100644 src/search-tool/search-tool.c
 create mode 100644 src/search-tool/search-tool.cc
 delete mode 100644 src/sid/xmms-sid.c
 create mode 100644 src/sid/xmms-sid.cc
 delete mode 100644 src/sid/xs_config.c
 create mode 100644 src/sid/xs_config.cc
 delete mode 100644 src/sid/xs_length.c
 delete mode 100644 src/sid/xs_length.h
 delete mode 100644 src/sid/xs_md5.c
 delete mode 100644 src/sid/xs_md5.h
 delete mode 100644 src/sid/xs_player.h
 delete mode 100644 src/sid/xs_slsup.c
 delete mode 100644 src/sid/xs_slsup.h
 delete mode 100644 src/sid/xs_stil.c
 delete mode 100644 src/sid/xs_stil.h
 delete mode 100644 src/sid/xs_support.c
 delete mode 100644 src/sid/xs_support.h
 create mode 100644 src/silence-removal/Makefile
 create mode 100644 src/silence-removal/silence-removal.cc
 delete mode 100644 src/skins/drag-handle.c
 create mode 100644 src/skins/drag-handle.cc
 delete mode 100644 src/skins/menus.c
 create mode 100644 src/skins/menus.cc
 create mode 100644 src/skins/plugin-window.cc
 create mode 100644 src/skins/plugin-window.h
 delete mode 100644 src/skins/plugin.c
 create mode 100644 src/skins/plugin.cc
 delete mode 100644 src/skins/preset-browser.c
 create mode 100644 src/skins/preset-browser.cc
 delete mode 100644 src/skins/preset-list.c
 create mode 100644 src/skins/preset-list.cc
 delete mode 100644 src/skins/skins_cfg.c
 create mode 100644 src/skins/skins_cfg.cc
 delete mode 100644 src/skins/surface.c
 create mode 100644 src/skins/surface.cc
 delete mode 100644 src/skins/ui_dock.c
 create mode 100644 src/skins/ui_dock.cc
 delete mode 100644 src/skins/ui_equalizer.c
 create mode 100644 src/skins/ui_equalizer.cc
 delete mode 100644 src/skins/ui_main.c
 create mode 100644 src/skins/ui_main.cc
 delete mode 100644 src/skins/ui_main_evlisteners.c
 create mode 100644 src/skins/ui_main_evlisteners.cc
 delete mode 100644 src/skins/ui_playlist.c
 create mode 100644 src/skins/ui_playlist.cc
 delete mode 100644 src/skins/ui_skin.c
 create mode 100644 src/skins/ui_skin.cc
 delete mode 100644 src/skins/ui_skin_load_ini.c
 create mode 100644 src/skins/ui_skin_load_ini.cc
 delete mode 100644 src/skins/ui_skinned_button.c
 create mode 100644 src/skins/ui_skinned_button.cc
 delete mode 100644 src/skins/ui_skinned_equalizer_graph.c
 create mode 100644 src/skins/ui_skinned_equalizer_graph.cc
 delete mode 100644 src/skins/ui_skinned_equalizer_slider.c
 create mode 100644 src/skins/ui_skinned_equalizer_slider.cc
 delete mode 100644 src/skins/ui_skinned_horizontal_slider.c
 create mode 100644 src/skins/ui_skinned_horizontal_slider.cc
 delete mode 100644 src/skins/ui_skinned_menurow.c
 create mode 100644 src/skins/ui_skinned_menurow.cc
 delete mode 100644 src/skins/ui_skinned_monostereo.c
 create mode 100644 src/skins/ui_skinned_monostereo.cc
 delete mode 100644 src/skins/ui_skinned_number.c
 create mode 100644 src/skins/ui_skinned_number.cc
 delete mode 100644 src/skins/ui_skinned_playlist.c
 create mode 100644 src/skins/ui_skinned_playlist.cc
 delete mode 100644 src/skins/ui_skinned_playlist_slider.c
 create mode 100644 src/skins/ui_skinned_playlist_slider.cc
 delete mode 100644 src/skins/ui_skinned_playstatus.c
 create mode 100644 src/skins/ui_skinned_playstatus.cc
 delete mode 100644 src/skins/ui_skinned_textbox.c
 create mode 100644 src/skins/ui_skinned_textbox.cc
 delete mode 100644 src/skins/ui_skinned_window.c
 create mode 100644 src/skins/ui_skinned_window.cc
 delete mode 100644 src/skins/ui_skinselector.c
 create mode 100644 src/skins/ui_skinselector.cc
 delete mode 100644 src/skins/ui_svis.c
 create mode 100644 src/skins/ui_svis.cc
 delete mode 100644 src/skins/ui_vis.c
 create mode 100644 src/skins/ui_vis.cc
 delete mode 100644 src/skins/util.c
 create mode 100644 src/skins/util.cc
 delete mode 100644 src/skins/view.c
 create mode 100644 src/skins/view.cc
 delete mode 100644 src/sndfile/plugin.c
 create mode 100644 src/sndfile/plugin.cc
 create mode 100644 src/sndio-ng/Makefile
 create mode 100644 src/sndio-ng/sndio.cc
 delete mode 100644 src/sndio/Makefile
 delete mode 100644 src/sndio/sndio.c
 create mode 100644 src/song-info-qt/Makefile
 create mode 100644 src/song-info-qt/song-info.cc
 delete mode 100644 src/song_change/formatter.c
 create mode 100644 src/song_change/formatter.cc
 delete mode 100644 src/song_change/song_change.c
 create mode 100644 src/song_change/song_change.cc
 delete mode 100644 src/sox-resampler/sox-resampler.c
 create mode 100644 src/sox-resampler/sox-resampler.cc
 delete mode 100644 src/speed-pitch/speed-pitch.c
 create mode 100644 src/speed-pitch/speed-pitch.cc
 delete mode 100644 src/statusicon/statusicon.c
 create mode 100644 src/statusicon/statusicon.cc
 delete mode 100644 src/statusicon/statusicon.h
 delete mode 100644 src/statusicon/util.c
 delete mode 100644 src/stereo_plugin/stereo.c
 create mode 100644 src/stereo_plugin/stereo.cc
 delete mode 100644 src/tonegen/tonegen.c
 create mode 100644 src/tonegen/tonegen.cc
 delete mode 100644 src/voice_removal/voice_removal.c
 create mode 100644 src/voice_removal/voice_removal.cc
 delete mode 100644 src/vorbis/vcedit.c
 create mode 100644 src/vorbis/vcedit.cc
 delete mode 100644 src/vorbis/vcupdate.c
 create mode 100644 src/vorbis/vcupdate.cc
 delete mode 100644 src/vorbis/vorbis.c
 create mode 100644 src/vorbis/vorbis.cc
 delete mode 100644 src/vtx/ay8912.c
 create mode 100644 src/vtx/ay8912.cc
 delete mode 100644 src/vtx/info.c
 create mode 100644 src/vtx/info.cc
 delete mode 100644 src/vtx/lh5dec.c
 create mode 100644 src/vtx/lh5dec.cc
 delete mode 100644 src/vtx/vtx.c
 create mode 100644 src/vtx/vtx.cc
 delete mode 100644 src/vtx/vtxfile.c
 create mode 100644 src/vtx/vtxfile.cc
 delete mode 100644 src/wavpack/wavpack.c
 create mode 100644 src/wavpack/wavpack.cc
 delete mode 100644 src/xsf/corlett.c
 create mode 100644 src/xsf/corlett.cc
 delete mode 100644 src/xsf/desmume/FIFO.c
 create mode 100644 src/xsf/desmume/FIFO.cc
 delete mode 100644 src/xsf/desmume/GPU.c
 create mode 100644 src/xsf/desmume/GPU.cc
 delete mode 100644 src/xsf/desmume/MMU.c
 create mode 100644 src/xsf/desmume/MMU.cc
 delete mode 100644 src/xsf/desmume/NDSSystem.c
 create mode 100644 src/xsf/desmume/NDSSystem.cc
 delete mode 100644 src/xsf/desmume/SPU.c
 create mode 100644 src/xsf/desmume/SPU.cc
 delete mode 100644 src/xsf/desmume/arm_instructions.c
 create mode 100644 src/xsf/desmume/arm_instructions.cc
 delete mode 100644 src/xsf/desmume/armcpu.c
 create mode 100644 src/xsf/desmume/armcpu.cc
 delete mode 100644 src/xsf/desmume/bios.c
 create mode 100644 src/xsf/desmume/bios.cc
 delete mode 100644 src/xsf/desmume/cp15.c
 create mode 100644 src/xsf/desmume/cp15.cc
 delete mode 100644 src/xsf/desmume/matrix.c
 create mode 100644 src/xsf/desmume/matrix.cc
 delete mode 100644 src/xsf/desmume/mc.c
 create mode 100644 src/xsf/desmume/mc.cc
 delete mode 100644 src/xsf/desmume/thumb_instructions.c
 create mode 100644 src/xsf/desmume/thumb_instructions.cc
 delete mode 100644 src/xsf/plugin.c
 create mode 100644 src/xsf/plugin.cc
 delete mode 100644 src/xsf/vio2sf.c
 create mode 100644 src/xsf/vio2sf.cc
 delete mode 100644 src/xspf/xspf.c
 create mode 100644 src/xspf/xspf.cc

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 845ca0677527..000000000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-.pc
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 9059c8011dcd..000000000000
--- a/AUTHORS
+++ /dev/null
@@ -1,174 +0,0 @@
-Audacious (C) GPL 2005-2009
-
-Authors listed alphabetically, by last name:
---------------------------------------------
-
-George Averill <nhjm449 at gmail.com>
-Kieran Clancy <clancy.kieran+audacious at gmail.com>
-Michael Färber <0102 at gmx.at>
-Matti Hämäläinen <ccr at tnsp.org>
-Giacomo Lozito <james at develia.org>
-Tomasz Moń <desowin at gmail.com>
-William Pitcock <nenolod at sacredspiral.co.uk>
-Derek Pomery <nemo at m8y.org>
-Mohammed Sameer <msameer at foolab.org>
-Jonathan Schleifer <js-audacious at webkeks.org>
-Stephen Sokolow <deitarion at gmail.com>
-Ben Tucker <ben at tucker.org>
-Tony Vroon <chainsaw at gentoo.org>
-Yoshiki Yazawa <yaz at cc.or.rim.jp>
-
-Translators
------------
-
-Dutch              - Tony Vroon
-Hungarian          - Dvornik László
-German             - Michael Hanselmann
-                     Matthias Debus
-Greek              - Kouzinopoulos Haris
-                     Stavros Giannouris
-                     Stathis Kamperis
-Italian            - Diego Petteno
-Japanese           - Dai
-Finnish            - Pauli Virtanen
-                     Matti Hämäläinen
-
--
-
-Based on:
-
-BMP - beep media player (C) GPL 2003-2005
-
-Authors alphabetically
-----------------------
-
-Artem Baguinski <artm at v2.nl>
-Edward Brocklesby <ejb at goth.net>
-Chong Kai Xiong <descender at phreaker.net>
-Milosz Derezynski <m.derezynski at arcor.de>
-David Lau <coder_sku at users.sourceforge.net>
-Ole Andre Vadla Ravnaas <oleavr at jblinux.net>
-Michiel Sikkes <michiel at eyesopened.nl>
-
-Patch Authors
--------------
-
-Andrei Badea
-Peter Behroozi
-Bernard Blackham
-Oliver Blin
-David Le Brun
-Tomas Bzatek
-Liviu Danicel
-Jon Dowland
-Artur Frysiak
-Sebastian Kapfer
-Lukas Koberstein
-Dan Korostelev
-Oliver Lehmann
-Jolan Luff
-Mike Lundy
-Michael Marineau
-Tim-Philipp Muller
-Julien Portalier
-Andrew Ruder
-Olivier Samyn
-John Spray
-Takashi Iwai
-Martijn Vernooij
-Thierry Vignaud
-
-Translators
------------
-
-Brazilian Portuguese - Philipi Pinto <philipi at gmx.net>
-Breton               - Thierry Vignaud <tvignaud at mandrakesoft.com>
-Czech                - Jan Narovec <jnarovec at students.zcu.cz>
-Dutch                - Laurens Buhler <masterpe at xs4all.nl>
-German               - Matthias Debus <psic4t at netbands.de>
-Georgian             - George Machitidze <giomac at global-erty.net>
-Greek                - Kouzinopoulos Haris <haris at mpa.gr>
-                       Stavros Giannouris <stavrosg2002 at freemail.gr>
-Finnish              - Pauli Virtanen <pauli.virtanen at hut.fi>
-French               - David Le Brun <david at dyn-ns.net>
-Hindi                - Dhananjaya Sharma <dysxhi at yahoo.co.in>
-Hungarian            - Dvornik László <dvornik at gnome.hu>
-Italian              - Alessio D'Ascanio <otaku at fastwebnet.it>
-Japanese             - Takeshi Aihana <aihana at gnome.gr.jp>
-Korean               - DongCheon Park <dcpark at kaist.ac.kr>
-Lithuanian           - Rimas Kudelis <rq at akl.lt>
-Macedonian           - Arangel Angov <ufo at linux.net.mk>
-Polish               - Jacek Wolszczak <shutdownrunner at o2.pl>
-Romanian             - Liviu Danicel <liviu.danicel at spymac.com>
-Russian              - Pavlo Bohmat <bohm at ukr.net>
-                       Dan Korostelev <dan at ats.energo.ru>
-                       Vitaly Lipatov <lav at altlinux.ru>
-                       Maxim Musatov <m1kc at yandex.ru>
-Simplified Chinese   - Chong Kai Xiong <descender at phreaker.net>
-Traditional Chinese  - Chao-Hsiung Liao <pesder.liao at msa.hinet.net>
-Slovak               - Pavel Kanzelsberger <kanzels at zmail.sk>
-Spanish              - Francisco Javier F. Serrador <serrador at cvs.gnome.org>
-Swedish              - Martin Persenius <martin at persenius.net>
-Ukrainian            - Mykola Lynnyk<definer at users.sf.net>
-Welsh                - Edward Brocklesby <ejb at goth.net>
-                       (Based on XMMS from Rhoslyn Prys <rhoslyn.prys at meddal.org.uk>)
-
-
-(please tell us if we left your name out)
-
--
-
-Based on:
-
-XMMS - X Multimedia System (C)1998-2003
-
-       Main Programming: Peter Alm
-
- Additional Programming: Håvard Kvålen
-                         Derrik Pates
-
-   With Additional Help: Sean Atkinson
-                         Jorn Baayen
-                         James M. Cape
-                         Anders Carlsson (effect plugins)
-                         Chun-Chung Chen (xfont patch)
-                         Tim Ferguson (joystick plugin)
-                         Ben Gertzfield
-                         Vesa Halttunen
-                         Logan Hanks
-                         Eric L. Hernes (FreeBSD patches)
-                         Ville Herva
-                         higway (MMX)
-                         Michael Hipp and others (MPG123 engine)
-                         Olle Hällnäs (compiling fixes)
-                         David Jacoby
-                         Osamu Kayasono (3DNow!)
-                         Lyle B Kempler
-                         J. Nick Koston (MikMod plugin)
-                         Aaron Lehmann
-                         Johan Levin (echo + stereo plugin)
-                         Eric Lindvall
-                         Colin Marquardt
-                         Willem Monsuwe
-                         John Riddoch (Solaris plugin)
-                         Josip Rodin
-                         Pablo Saratxaga (i18n)
-                         Carl van Schaik (pro logic plugin)
-                         Jörg Schuler
-                         Charles Sielski (irman plugin)
-                         Espen Skoglund
-                         Matthieu Sozeau (ALSA plugin)
-                         Kimura Takuhiro (3DNow!)
-                         Zinx Verituse
-                         Ryan Weaver (RPMs among other things)
-                         Chris Wilson
-                         Dave Yearke
-                         Stephan K. Zitz
-
-           Default skin: Leonard "Blayde" Tan
-                         Robin Sylvestre (Equalizer and Playlist)
-                         Thomas Nilsson (New titles, and cleanups)
-
-  Homepage and Graphics: Thomas Nilsson
-
-       Support and Docs: Olle Hällnäs
diff --git a/COPYING b/COPYING
index 8dd4e9166445..f634604e545f 100644
--- a/COPYING
+++ b/COPYING
@@ -1,35 +1,22 @@
-The buildsystem and framework for installing and managing plugins is:
+The build system and framework for installing and managing plugins is:
 
-Copyright (c) 2005-2007 Audacious development team.
+Copyright © 2001-2015 Audacious developers
 
-All rights reserved.
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
 
-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.
 
-      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.
 
-      Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
-
-      Neither the name of the author nor the names of its contributors may be
-      used to endorse or promote products derived from this software without
-      specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+    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.
 
 ------------------------------------------------------------------------------
 
-The plugins themselves are distributed under their own distribution terms,
-read the sourcecode for plugin-specific licensing details.
+The plugins themselves are distributed under their own distribution terms.
+Read the source code for individual copyright holders and licensing details.
diff --git a/acinclude.m4 b/acinclude.m4
index 157258c8586b..cccd41186b06 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,5 +1,5 @@
 dnl Add $1 to CFLAGS and CXXFLAGS if supported
-dnl ------------------------------------------
+dnl ==========================================
 
 AC_DEFUN([AUD_CHECK_CFLAGS],[
     AC_MSG_CHECKING([whether the C/C++ compiler supports $1])
@@ -15,25 +15,30 @@ AC_DEFUN([AUD_CHECK_CFLAGS],[
     ])
 ])
 
+dnl Add $1 to CXXFLAGS if supported
+dnl ===============================
+
+AC_DEFUN([AUD_CHECK_CXXFLAGS],[
+    AC_MSG_CHECKING([whether the C++ compiler supports $1])
+    AC_LANG_PUSH([C++])
+    OLDCXXFLAGS="$CXXFLAGS"
+    CXXFLAGS="$CXXFLAGS $1 -Werror"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[return 0;])],[
+        AC_MSG_RESULT(yes)
+        CXXFLAGS="$OLDCXXFLAGS $1"
+    ],[
+        AC_MSG_RESULT(no)
+        CXXFLAGS="$OLDCXXFLAGS"
+    ])
+    AC_LANG_POP([C++])
+])
+
 
 dnl **
 dnl ** Common checks
 dnl **
 AC_DEFUN([AUD_COMMON_PROGS], [
 
-dnl Check for C and C++ compilers
-dnl =============================
-AC_REQUIRE([AC_PROG_CC])
-AC_REQUIRE([AC_PROG_CXX])
-AC_REQUIRE([AC_C_BIGENDIAN])
-AC_REQUIRE([AC_SYS_LARGEFILE])
-
-if test "x$GCC" = "xyes"; then
-    CFLAGS="$CFLAGS -std=gnu99 -ffast-math -Wall -pipe"
-    CXXFLAGS="$CXXFLAGS -Wall -pipe"
-    AUD_CHECK_CFLAGS(-Wtype-limits)
-fi
-
 dnl Check platform
 dnl ==============
 
@@ -44,6 +49,7 @@ AC_MSG_CHECKING([operating system type])
 
 HAVE_LINUX=no
 HAVE_MSWINDOWS=no
+HAVE_DARWIN=no
 
 case "$target" in
     *linux*)
@@ -54,6 +60,10 @@ case "$target" in
         AC_MSG_RESULT(Windows)
         HAVE_MSWINDOWS=yes
         ;;
+    *darwin*)
+        AC_MSG_RESULT(Darwin)
+        HAVE_DARWIN=yes
+        ;;
     *)
         AC_MSG_RESULT(other UNIX)
         ;;
@@ -61,6 +71,38 @@ esac
 
 AC_SUBST(HAVE_MSWINDOWS)
 AC_SUBST(HAVE_LINUX)
+AC_SUBST(HAVE_DARWIN)
+
+dnl Check for C and C++ compilers
+dnl =============================
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([AC_C_BIGENDIAN])
+AC_REQUIRE([AC_SYS_LARGEFILE])
+
+if test "x$GCC" = "xyes"; then
+    CFLAGS="$CFLAGS -std=gnu99 -ffast-math -Wall -pipe"
+    if test "x$HAVE_DARWIN" = "xyes"; then
+        CXXFLAGS="$CXXFLAGS -stdlib=libc++ -std=gnu++11 -ffast-math -Wall -pipe"
+        LDFLAGS="$LDFLAGS -lc++ -stdlib=libc++"
+    else
+        CXXFLAGS="$CXXFLAGS -std=gnu++11 -ffast-math -Wall -pipe"
+    fi
+    AUD_CHECK_CFLAGS(-Wtype-limits)
+    AUD_CHECK_CXXFLAGS(-Woverloaded-virtual)
+fi
+
+dnl On Mac, check for Objective-C and -C++ compilers
+dnl ================================================
+
+if test "x$HAVE_DARWIN" = "xyes"; then
+    AC_PROG_OBJC
+    AC_PROG_OBJCPP
+    AC_PROG_OBJCXX
+    AC_PROG_OBJCXXCPP
+
+    OBJCXXFLAGS="$OBJCXXFLAGS -stdlib=libc++ -std=c++11"
+fi
 
 dnl Enable "-Wl,-z,defs" only on Linux
 dnl ==================================
@@ -74,6 +116,26 @@ if test $HAVE_MSWINDOWS = yes ; then
 	CFLAGS="$CFLAGS -march=i686"
 fi
 
+dnl Byte order
+dnl ==========
+AC_C_BIGENDIAN([BIGENDIAN=1], [BIGENDIAN=0],
+ [AC_MSG_ERROR([Unknown machine byte order])],
+ [AC_MSG_ERROR([Universal builds are not supported, sorry])])
+AC_SUBST([BIGENDIAN])
+
+dnl Prevent symbol collisions
+dnl =========================
+if test "x$HAVE_MSWINDOWS" = "xyes" ; then
+    EXPORT="__declspec(dllexport)"
+elif test "x$GCC" = "xyes" ; then
+    CFLAGS="$CFLAGS -fvisibility=hidden"
+    CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
+    EXPORT="__attribute__((visibility(\"default\")))"
+else
+    AC_MSG_ERROR([Unknown syntax for EXPORT keyword])
+fi
+AC_DEFINE_UNQUOTED([EXPORT], [$EXPORT], [Define to compiler syntax for public symbols])
+
 dnl Checks for various programs
 dnl ===========================
 AC_PROG_LN_S
@@ -93,7 +155,20 @@ dnl =======================
 
 PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32)
 PKG_CHECK_MODULES(GMODULE, gmodule-2.0 >= 2.32)
-PKG_CHECK_MODULES(GTK, gtk+-3.0 >= 3.4)
+
+dnl GTK+ support
+dnl =============
+
+AC_ARG_ENABLE(gtk,
+ AS_HELP_STRING(--disable-gtk, [Disable GTK+ support (default=enabled)]),
+ USE_GTK=$enableval, USE_GTK=yes)
+
+if test $USE_GTK = yes ; then
+    PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.24)
+    AC_DEFINE(USE_GTK, 1, [Define if GTK+ support enabled])
+fi
+
+AC_SUBST(USE_GTK)
 
 if test $HAVE_MSWINDOWS = yes ; then
     PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.32)
@@ -110,4 +185,23 @@ AC_SUBST(GMODULE_LIBS)
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
+dnl Qt support
+dnl ==========
+
+AC_ARG_ENABLE(qt,
+ AS_HELP_STRING(--enable-qt, [Enable Qt support (default=disabled)]),
+ USE_QT=$enableval, USE_QT=no)
+
+if test $USE_QT = yes ; then
+    PKG_CHECK_MODULES([QT], [Qt5Core Qt5Gui Qt5Widgets])
+    AC_DEFINE(USE_QT, 1, [Define if Qt support enabled])
+
+    # needed if Qt was built with -reduce-relocations
+    QT_CFLAGS="$QT_CFLAGS -fPIC"
+fi
+
+AC_SUBST(USE_QT)
+AC_SUBST(QT_CFLAGS)
+AC_SUBST(QT_LIBS)
+
 ])
diff --git a/config.h.in b/config.h.in
index a49878055624..19fddce57eea 100644
--- a/config.h.in
+++ b/config.h.in
@@ -7,6 +7,9 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* Define to compiler syntax for public symbols */
+#undef EXPORT
+
 /* Define if FLAC output part should be built */
 #undef FILEWRITER_FLAC
 
@@ -28,6 +31,9 @@
    */
 #undef HAVE_DCGETTEXT
 
+/* Define if using FFmpeg */
+#undef HAVE_FFMPEG
+
 /* Define if the GNU gettext() function is already present or preinstalled. */
 #undef HAVE_GETTEXT
 
@@ -37,18 +43,15 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define if using libav */
+#undef HAVE_LIBAV
+
 /* Define to 1 if you have the <lirc/lirc_client.h> header file. */
 #undef HAVE_LIRC_LIRC_CLIENT_H
 
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
-/* Define to 1 if you have the `mkdtemp' function. */
-#undef HAVE_MKDTEMP
-
-/* Whether we have ne_set_connect_timeout */
-#undef HAVE_NE_SET_CONNECT_TIMEOUT
-
 /* Define to 1 if you have the <soundcard.h> header file. */
 #undef HAVE_SOUNDCARD_H
 
@@ -109,6 +112,12 @@
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* Define if GTK+ support enabled */
+#undef USE_GTK
+
+/* Define if Qt support enabled */
+#undef USE_QT
+
 /* Version number of package */
 #undef VERSION
 
diff --git a/configure b/configure
index 82da64cf60e7..2eb511616727 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for audacious-plugins 3.5.
+# Generated by GNU Autoconf 2.69 for audacious-plugins 3.6.1.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -9,7 +9,7 @@
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
 #
-# (C) 2005-2014 Audacious Team
+# Copyright (C) 2001-2015 Audacious developers and others
 ## -------------------- ##
 ## M4sh Initialization. ##
 ## -------------------- ##
@@ -579,8 +579,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='audacious-plugins'
 PACKAGE_TARNAME='audacious-plugins'
-PACKAGE_VERSION='3.5'
-PACKAGE_STRING='audacious-plugins 3.5'
+PACKAGE_VERSION='3.6.1'
+PACKAGE_STRING='audacious-plugins 3.6.1'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -651,11 +651,15 @@ EFFECT_PLUGIN_DIR
 OUTPUT_PLUGIN_DIR
 INPUT_PLUGIN_DIR
 plugindir
+QTOPENGL_LIBS
+QTOPENGL_CFLAGS
 GL_LIBS
 GLIB214_LIBS
 GLIB214_CFLAGS
 SOXR_LIBS
 SOXR_CFLAGS
+SAMPLERATE_LIBS
+SAMPLERATE_CFLAGS
 BS2B_LIBS
 BS2B_CFLAGS
 FILEWRITER_LIBS
@@ -684,8 +688,6 @@ ALSA_CFLAGS
 OSS_CFLAGS
 SIDPLAYFP_LIBS
 SIDPLAYFP_CFLAGS
-SAMPLERATE_LIBS
-SAMPLERATE_CFLAGS
 JACK_LIBS
 JACK_CFLAGS
 FFMPEG_LIBS
@@ -719,8 +721,10 @@ MPG123_LIBS
 MPG123_CFLAGS
 PULSE_LIBS
 PULSE_CFLAGS
-XML_LIBS
+QTMULTIMEDIA_LIBS
+QTMULTIMEDIA_CFLAGS
 XML_CFLAGS
+XML_LIBS
 AUDACIOUS_LIBS
 AUDACIOUS_CFLAGS
 POSUB
@@ -757,8 +761,12 @@ LIB_SUFFIX
 LIB_PREFIX
 LIB_LDFLAGS
 LIB_CFLAGS
+USE_QT
+QT_LIBS
+QT_CFLAGS
 GIO_LIBS
 GIO_CFLAGS
+USE_GTK
 GTK_LIBS
 GTK_CFLAGS
 GMODULE_LIBS
@@ -775,6 +783,29 @@ CP
 MV
 RM
 LN_S
+BIGENDIAN
+OBJCXXCPP
+ac_ct_OBJCXX
+OBJCXXFLAGS
+OBJCXX
+OBJCPP
+ac_ct_OBJC
+OBJCFLAGS
+OBJC
+EGREP
+GREP
+CPP
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+HAVE_DARWIN
 HAVE_LINUX
 HAVE_MSWINDOWS
 target_os
@@ -789,19 +820,6 @@ build_os
 build_vendor
 build_cpu
 build
-EGREP
-GREP
-CPP
-ac_ct_CXX
-CXXFLAGS
-CXX
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
 target_alias
 host_alias
 build_alias
@@ -844,13 +862,18 @@ ac_subst_files=''
 ac_user_opts='
 enable_option_checking
 enable_largefile
+enable_gtk
+enable_qt
 enable_nls
 with_gnu_ld
 enable_rpath
 with_libiconv_prefix
 with_libintl_prefix
+with_system_libxml2
 enable_console
 enable_xsf
+enable_qtaudio
+enable_coreaudio
 enable_pulse
 enable_psf
 enable_mp3
@@ -858,7 +881,6 @@ enable_hotkey
 enable_gnomeshortcuts
 enable_lirc
 enable_songchange
-enable_statusicon
 enable_aosd
 enable_aosd_xcomp
 enable_notify
@@ -870,12 +892,13 @@ enable_wavpack
 enable_aac
 enable_sndfile
 enable_modplug
-enable_ffaudio
+with_ffmpeg
 enable_jack
 enable_sid
 enable_oss4
 enable_alsa
 enable_sdlout
+with_libsdl
 enable_sndio
 enable_amidiplug
 enable_cdaudio
@@ -890,10 +913,14 @@ enable_bs2b
 enable_resample
 enable_speedpitch
 enable_soxr
-enable_gtkui
-enable_skins
 enable_lyricwiki
 enable_glspectrum
+enable_qtglspectrum
+enable_vtx
+enable_ladspa
+enable_blur_scope
+enable_cairo_spectrum
+enable_mac_media_keys
 '
       ac_precious_vars='build_alias
 host_alias
@@ -907,6 +934,12 @@ CXX
 CXXFLAGS
 CCC
 CPP
+OBJC
+OBJCFLAGS
+OBJCPP
+OBJCXX
+OBJCXXFLAGS
+OBJCXXCPP
 PKG_CONFIG
 PKG_CONFIG_PATH
 PKG_CONFIG_LIBDIR
@@ -918,10 +951,14 @@ GTK_CFLAGS
 GTK_LIBS
 GIO_CFLAGS
 GIO_LIBS
+QT_CFLAGS
+QT_LIBS
 AUDACIOUS_CFLAGS
 AUDACIOUS_LIBS
 XML_CFLAGS
 XML_LIBS
+QTMULTIMEDIA_CFLAGS
+QTMULTIMEDIA_LIBS
 PULSE_CFLAGS
 PULSE_LIBS
 MPG123_CFLAGS
@@ -952,8 +989,6 @@ FFMPEG_CFLAGS
 FFMPEG_LIBS
 JACK_CFLAGS
 JACK_LIBS
-SAMPLERATE_CFLAGS
-SAMPLERATE_LIBS
 SIDPLAYFP_CFLAGS
 SIDPLAYFP_LIBS
 ALSA_CFLAGS
@@ -978,10 +1013,14 @@ FLAC_CFLAGS
 FLAC_LIBS
 BS2B_CFLAGS
 BS2B_LIBS
+SAMPLERATE_CFLAGS
+SAMPLERATE_LIBS
 SOXR_CFLAGS
 SOXR_LIBS
 GLIB214_CFLAGS
-GLIB214_LIBS'
+GLIB214_LIBS
+QTOPENGL_CFLAGS
+QTOPENGL_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1522,7 +1561,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures audacious-plugins 3.5 to adapt to many kinds of systems.
+\`configure' configures audacious-plugins 3.6.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1589,7 +1628,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of audacious-plugins 3.5:";;
+     short | recursive ) echo "Configuration of audacious-plugins 3.6.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1598,32 +1637,34 @@ Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-largefile     omit support for large files
+  --disable-gtk           Disable GTK+ support (default=enabled)
+  --enable-qt             Enable Qt support (default=disabled)
   --disable-nls           do not use Native Language Support
   --disable-rpath         do not hardcode runtime library paths
   --disable-console       disable game music decoder (console)
   --disable-xsf           disable Nintendo DS audio decoder (xsf)
+  --disable-qtaudio       disable QtMultimedia output plugin (default=enabled)
+  --disable-coreaudio     disable CoreAudio output plugin (default=enabled)
   --disable-pulse         disable PulseAudio output plugin (default=enabled)
   --disable-psf           disable PlayStation (psf/psf2) audio decoder
-  --disable-mp3           disable MP3 plugin (default=enabled)
+  --disable-mp3           disable MP3 support (default=enabled)
   --disable-hotkey        disable global hotkey plugin (default=enabled)
   --disable-gnomeshortcuts
                           disable gnome shortcuts (default=enabled)
   --disable-lirc          disable LIRC support (default=enabled)
   --disable-songchange    disable song change plugin
-  --disable-statusicon    disable X11 Status Icon plugin (default=enabled)
   --disable-aosd          disable Audacious OSD plugin (default=enabled)
   --disable-aosd-xcomp    disable Audacious OSD X Composite Support
                           (default=enabled)
   --disable-notify        disable notify plugin (default=enabled)
   --disable-mpris2        disable MPRIS 2 support (default=auto)
   --disable-adplug        disable AdPlug plugin (default=enabled)
-  --disable-vorbis        disable Ogg Vorbis decoding and encoding
-  --disable-flacng        disable flac input plugin (default=enabled)
+  --disable-vorbis        disable Ogg Vorbis support (default=enabled)
+  --disable-flacng        disable FLAC support (default=enabled)
   --disable-wavpack       disable WavPack input plugin (default=enabled)
-  --disable-aac           disable aac plugin (default=enabled)
+  --disable-aac           disable AAC support (default=enabled)
   --disable-sndfile       disable sndfile extensions. [default=enabled]
   --disable-modplug       disable ModPlug plugin (default=enabled)
-  --disable-ffaudio       disable ffaudio plugin (default=enabled)
   --disable-jack          disable JACK output plugin (default=enabled)
   --disable-sid           disable SID input plugin (default=enabled)
   --disable-oss4          disable OSS4 output plugin
@@ -1647,10 +1688,16 @@ Optional Features:
   --disable-speedpitch    disable Speed and Pitch effect plugin
   --disable-soxr          disable SoX Resampler effect plugin
                           (default=enabled)
-  --disable-gtkui         disable GTK interface (gtkui)
-  --disable-skins         disable Winamp Classic interface (skins)
   --disable-lyricwiki     disable LyricWiki plugin (default=enabled)
   --enable-glspectrum     enable OpenGL Spectrum Analyzer (default=auto)
+  --disable-qtglspectrum  disable Qt OpenGL Spectrum Analyzer
+                          (default=enabled)
+  --disable-vtx           disable VTX Decoder
+  --disable-ladspa        disable LADSPA Host
+  --disable-blur-scope    disable Blur Scope
+  --disable-cairo-spectrum
+                          disable Cairo Spectrum Analyzer
+  --enable-mac-media-keys enable Mac Media Keys
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1660,6 +1707,13 @@ Optional Packages:
   --without-libiconv-prefix     don't search for libiconv in includedir and libdir
   --with-libintl-prefix[=DIR]  search for libintl in DIR/include and DIR/lib
   --without-libintl-prefix     don't search for libintl in includedir and libdir
+  --with-system-libxml2=yes,no
+                          Use system version of libxml2 (default=yes)
+  --with-ffmpeg=ffmpeg,libav,none
+                          choose between FFmpeg, libav, or neither
+                          (default=ffmpeg)
+  --with-libsdl=VER       select which SDL version to use. Set VER to 1 for
+                          libsdl1, to 2 for libsdl2. [default=check]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1672,6 +1726,12 @@ Some influential environment variables:
   CXX         C++ compiler command
   CXXFLAGS    C++ compiler flags
   CPP         C preprocessor
+  OBJC        Objective C compiler command
+  OBJCFLAGS   Objective C compiler flags
+  OBJCPP      Objective C preprocessor
+  OBJCXX      Objective C++ compiler command
+  OBJCXXFLAGS Objective C++ compiler flags
+  OBJCXXCPP   Objective C++ preprocessor
   PKG_CONFIG  path to pkg-config utility
   PKG_CONFIG_PATH
               directories to add to pkg-config's search path
@@ -1687,12 +1747,18 @@ Some influential environment variables:
   GTK_LIBS    linker flags for GTK, overriding pkg-config
   GIO_CFLAGS  C compiler flags for GIO, overriding pkg-config
   GIO_LIBS    linker flags for GIO, overriding pkg-config
+  QT_CFLAGS   C compiler flags for QT, overriding pkg-config
+  QT_LIBS     linker flags for QT, overriding pkg-config
   AUDACIOUS_CFLAGS
               C compiler flags for AUDACIOUS, overriding pkg-config
   AUDACIOUS_LIBS
               linker flags for AUDACIOUS, overriding pkg-config
   XML_CFLAGS  C compiler flags for XML, overriding pkg-config
   XML_LIBS    linker flags for XML, overriding pkg-config
+  QTMULTIMEDIA_CFLAGS
+              C compiler flags for QTMULTIMEDIA, overriding pkg-config
+  QTMULTIMEDIA_LIBS
+              linker flags for QTMULTIMEDIA, overriding pkg-config
   PULSE_CFLAGS
               C compiler flags for PULSE, overriding pkg-config
   PULSE_LIBS  linker flags for PULSE, overriding pkg-config
@@ -1742,10 +1808,6 @@ Some influential environment variables:
   FFMPEG_LIBS linker flags for FFMPEG, overriding pkg-config
   JACK_CFLAGS C compiler flags for JACK, overriding pkg-config
   JACK_LIBS   linker flags for JACK, overriding pkg-config
-  SAMPLERATE_CFLAGS
-              C compiler flags for SAMPLERATE, overriding pkg-config
-  SAMPLERATE_LIBS
-              linker flags for SAMPLERATE, overriding pkg-config
   SIDPLAYFP_CFLAGS
               C compiler flags for SIDPLAYFP, overriding pkg-config
   SIDPLAYFP_LIBS
@@ -1774,12 +1836,20 @@ Some influential environment variables:
   FLAC_LIBS   linker flags for FLAC, overriding pkg-config
   BS2B_CFLAGS C compiler flags for BS2B, overriding pkg-config
   BS2B_LIBS   linker flags for BS2B, overriding pkg-config
+  SAMPLERATE_CFLAGS
+              C compiler flags for SAMPLERATE, overriding pkg-config
+  SAMPLERATE_LIBS
+              linker flags for SAMPLERATE, overriding pkg-config
   SOXR_CFLAGS C compiler flags for SOXR, overriding pkg-config
   SOXR_LIBS   linker flags for SOXR, overriding pkg-config
   GLIB214_CFLAGS
               C compiler flags for GLIB214, overriding pkg-config
   GLIB214_LIBS
               linker flags for GLIB214, overriding pkg-config
+  QTOPENGL_CFLAGS
+              C compiler flags for QTOPENGL, overriding pkg-config
+  QTOPENGL_LIBS
+              linker flags for QTOPENGL, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1847,14 +1917,14 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-audacious-plugins configure 3.5
+audacious-plugins configure 3.6.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 
-(C) 2005-2014 Audacious Team
+Copyright (C) 2001-2015 Audacious developers and others
 _ACEOF
   exit
 fi
@@ -2049,6 +2119,156 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_header_compile
 
+# ac_fn_objc_try_compile LINENO
+# -----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_objc_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_objc_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_objc_try_compile
+
+# ac_fn_objc_try_cpp LINENO
+# -------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_objc_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_objc_preproc_warn_flag$ac_objc_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_objc_try_cpp
+
+# ac_fn_objcxx_try_compile LINENO
+# -------------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_objcxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_objcxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_objcxx_try_compile
+
+# ac_fn_objcxx_try_cpp LINENO
+# ---------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_objcxx_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_objcxx_preproc_warn_flag$ac_objcxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_objcxx_try_cpp
+
 # ac_fn_c_try_link LINENO
 # -----------------------
 # Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -2095,73 +2315,6 @@ fi
 
 } # ac_fn_c_try_link
 
-# ac_fn_c_check_func LINENO FUNC VAR
-# ----------------------------------
-# Tests whether FUNC exists, setting the cache variable VAR accordingly
-ac_fn_c_check_func ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $2 innocuous_$2
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $2 (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $2
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $2 ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$2 || defined __stub___$2
-choke me
-#endif
-
-int
-main ()
-{
-return $2 ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  eval "$3=yes"
-else
-  eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_func
-
 # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
 # -------------------------------------------------------
 # Tests whether HEADER exists, giving a warning if it cannot be compiled using
@@ -2248,60 +2401,14 @@ fi
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_mongrel
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
 
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
-# ---------------------------------------------
-# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
-# accordingly.
-ac_fn_c_check_decl ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  as_decl_name=`echo $2|sed 's/ *(.*//'`
-  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-#ifndef $as_decl_name
-#ifdef __cplusplus
-  (void) $as_decl_use;
-#else
-  (void) $as_decl_name;
-#endif
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  eval "$3=yes"
-else
-  eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_decl
-cat >config.log <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by audacious-plugins $as_me 3.5, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
-
-  $ $0 $@
+It was created by audacious-plugins $as_me 3.6.1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
 
 _ACEOF
 exec 5>>config.log
@@ -2693,6 +2800,116 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4561,116 +4778,7 @@ rm -rf conftest*
 
 fi
 
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
-  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
-  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
-  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
-  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "x$host_alias" = x; then
-  ac_cv_host=$ac_cv_build
-else
-  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
-    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
-$as_echo_n "checking target system type... " >&6; }
-if ${ac_cv_target+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "x$target_alias" = x; then
-  ac_cv_target=$ac_cv_host
-else
-  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
-    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
-$as_echo "$ac_cv_target" >&6; }
-case $ac_cv_target in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
-esac
-target=$ac_cv_target
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_target
-shift
-target_cpu=$1
-target_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-target_os=$*
-IFS=$ac_save_IFS
-case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-
 
-# The aliases save the names the user supplied, while $host etc.
-# will get canonicalized.
-test -n "$target_alias" &&
-  test "$program_prefix$program_suffix$program_transform_name" = \
-    NONENONEs,x,x, &&
-  program_prefix=${target_alias}-
 
 
 
@@ -4797,29 +4905,71 @@ fi
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking operating system type" >&5
+$as_echo_n "checking operating system type... " >&6; }
 
-if test "x$GCC" = "xyes"; then
-    CFLAGS="$CFLAGS -std=gnu99 -ffast-math -Wall -pipe"
-    CXXFLAGS="$CXXFLAGS -Wall -pipe"
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C/C++ compiler supports -Wtype-limits" >&5
-$as_echo_n "checking whether the C/C++ compiler supports -Wtype-limits... " >&6; }
-    OLDCFLAGS="$CFLAGS"
-    CFLAGS="$CFLAGS -Wtype-limits -Werror"
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+HAVE_LINUX=no
+HAVE_MSWINDOWS=no
+HAVE_DARWIN=no
 
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+case "$target" in
+    *linux*)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux" >&5
+$as_echo "Linux" >&6; }
+        HAVE_LINUX=yes
+        ;;
+    *mingw*)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5
+$as_echo "Windows" >&6; }
+        HAVE_MSWINDOWS=yes
+        ;;
+    *darwin*)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Darwin" >&5
+$as_echo "Darwin" >&6; }
+        HAVE_DARWIN=yes
+        ;;
+    *)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: other UNIX" >&5
+$as_echo "other UNIX" >&6; }
+        ;;
+esac
+
+
+
+
+
+
+
+
+
+
+if test "x$GCC" = "xyes"; then
+    CFLAGS="$CFLAGS -std=gnu99 -ffast-math -Wall -pipe"
+    if test "x$HAVE_DARWIN" = "xyes"; then
+        CXXFLAGS="$CXXFLAGS -stdlib=libc++ -std=gnu++11 -ffast-math -Wall -pipe"
+        LDFLAGS="$LDFLAGS -lc++ -stdlib=libc++"
+    else
+        CXXFLAGS="$CXXFLAGS -std=gnu++11 -ffast-math -Wall -pipe"
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C/C++ compiler supports -Wtype-limits" >&5
+$as_echo_n "checking whether the C/C++ compiler supports -Wtype-limits... " >&6; }
+    OLDCFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -Wtype-limits -Werror"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
         CFLAGS="$OLDCFLAGS -Wtype-limits"
         CXXFLAGS="$CXXFLAGS -Wtype-limits"
@@ -4831,47 +4981,1071 @@ $as_echo "no" >&6; }
         CFLAGS="$OLDCFLAGS"
 
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler supports -Woverloaded-virtual" >&5
+$as_echo_n "checking whether the C++ compiler supports -Woverloaded-virtual... " >&6; }
+    ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+    OLDCXXFLAGS="$CXXFLAGS"
+    CXXFLAGS="$CXXFLAGS -Woverloaded-virtual -Werror"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        CXXFLAGS="$OLDCXXFLAGS -Woverloaded-virtual"
+
+else
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+        CXXFLAGS="$OLDCXXFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+
+
+if test "x$HAVE_DARWIN" = "xyes"; then
+    ac_ext=m
+ac_cpp='$OBJCPP $CPPFLAGS'
+ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_objc_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in gcc objcc objc cc CC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJC"; then
+  ac_cv_prog_OBJC="$OBJC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJC=$ac_cv_prog_OBJC
+if test -n "$OBJC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJC" >&5
+$as_echo "$OBJC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$OBJC" && break
+  done
+fi
+if test -z "$OBJC"; then
+  ac_ct_OBJC=$OBJC
+  for ac_prog in gcc objcc objc cc CC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJC"; then
+  ac_cv_prog_ac_ct_OBJC="$ac_ct_OBJC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJC=$ac_cv_prog_ac_ct_OBJC
+if test -n "$ac_ct_OBJC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJC" >&5
+$as_echo "$ac_ct_OBJC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_OBJC" && break
+done
+
+  if test "x$ac_ct_OBJC" = x; then
+    OBJC="gcc"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJC=$ac_ct_OBJC
+  fi
+fi
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for Objective C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5
+$as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; }
+if ${ac_cv_objc_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objc_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_objc_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objc_compiler_gnu" >&5
+$as_echo "$ac_cv_objc_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GOBJC=yes
+else
+  GOBJC=
+fi
+ac_test_OBJCFLAGS=${OBJCFLAGS+set}
+ac_save_OBJCFLAGS=$OBJCFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5
+$as_echo_n "checking whether $OBJC accepts -g... " >&6; }
+if ${ac_cv_prog_objc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_objc_werror_flag=$ac_objc_werror_flag
+   ac_objc_werror_flag=yes
+   ac_cv_prog_objc_g=no
+   OBJCFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objc_try_compile "$LINENO"; then :
+  ac_cv_prog_objc_g=yes
+else
+  OBJCFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objc_try_compile "$LINENO"; then :
+
+else
+  ac_objc_werror_flag=$ac_save_objc_werror_flag
+	 OBJCFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objc_try_compile "$LINENO"; then :
+  ac_cv_prog_objc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_objc_werror_flag=$ac_save_objc_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objc_g" >&5
+$as_echo "$ac_cv_prog_objc_g" >&6; }
+if test "$ac_test_OBJCFLAGS" = set; then
+  OBJCFLAGS=$ac_save_OBJCFLAGS
+elif test $ac_cv_prog_objc_g = yes; then
+  if test "$GOBJC" = yes; then
+    OBJCFLAGS="-g -O2"
+  else
+    OBJCFLAGS="-g"
+  fi
+else
+  if test "$GOBJC" = yes; then
+    OBJCFLAGS="-O2"
+  else
+    OBJCFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    ac_ext=m
+ac_cpp='$OBJCPP $CPPFLAGS'
+ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_objc_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the Objective C preprocessor" >&5
+$as_echo_n "checking how to run the Objective C preprocessor... " >&6; }
+if test -z "$OBJCPP"; then
+  if ${ac_cv_prog_OBJCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because OBJCPP needs to be expanded
+    for OBJCPP in "$OBJC -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_objc_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_objc_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_objc_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_OBJCPP=$OBJCPP
+
+fi
+  OBJCPP=$ac_cv_prog_OBJCPP
+else
+  ac_cv_prog_OBJCPP=$OBJCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCPP" >&5
+$as_echo "$OBJCPP" >&6; }
+ac_preproc_ok=false
+for ac_objc_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_objc_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_objc_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Objective C preprocessor \"$OBJCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    ac_ext=mm
+ac_cpp='$OBJCXXCPP $CPPFLAGS'
+ac_compile='$OBJCXX -c $OBJCXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$OBJCXX -o conftest$ac_exeext $OBJCXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_objcxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ objc++ objcxx c++ CXX
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJCXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJCXX"; then
+  ac_cv_prog_OBJCXX="$OBJCXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJCXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJCXX=$ac_cv_prog_OBJCXX
+if test -n "$OBJCXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCXX" >&5
+$as_echo "$OBJCXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$OBJCXX" && break
+  done
+fi
+if test -z "$OBJCXX"; then
+  ac_ct_OBJCXX=$OBJCXX
+  for ac_prog in g++ objc++ objcxx c++ CXX
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJCXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJCXX"; then
+  ac_cv_prog_ac_ct_OBJCXX="$ac_ct_OBJCXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJCXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJCXX=$ac_cv_prog_ac_ct_OBJCXX
+if test -n "$ac_ct_OBJCXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJCXX" >&5
+$as_echo "$ac_ct_OBJCXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_OBJCXX" && break
+done
+
+  if test "x$ac_ct_OBJCXX" = x; then
+    OBJCXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJCXX=$ac_ct_OBJCXX
+  fi
+fi
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for Objective C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU Objective C++ compiler... " >&6; }
+if ${ac_cv_objcxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objcxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_objcxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objcxx_compiler_gnu" >&5
+$as_echo "$ac_cv_objcxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GOBJCXX=yes
+else
+  GOBJCXX=
+fi
+ac_test_OBJCXXFLAGS=${OBJCXXFLAGS+set}
+ac_save_OBJCXXFLAGS=$OBJCXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJCXX accepts -g" >&5
+$as_echo_n "checking whether $OBJCXX accepts -g... " >&6; }
+if ${ac_cv_prog_objcxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_objcxx_werror_flag=$ac_objcxx_werror_flag
+   ac_objcxx_werror_flag=yes
+   ac_cv_prog_objcxx_g=no
+   OBJCXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objcxx_try_compile "$LINENO"; then :
+  ac_cv_prog_objcxx_g=yes
+else
+  OBJCXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objcxx_try_compile "$LINENO"; then :
+
+else
+  ac_objcxx_werror_flag=$ac_save_objcxx_werror_flag
+	 OBJCXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_objcxx_try_compile "$LINENO"; then :
+  ac_cv_prog_objcxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_objcxx_werror_flag=$ac_save_objcx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objcxx_g" >&5
+$as_echo "$ac_cv_prog_objcxx_g" >&6; }
+if test "$ac_test_OBJCXXFLAGS" = set; then
+  OBJCXXFLAGS=$ac_save_OBJCXXFLAGS
+elif test $ac_cv_prog_objcxx_g = yes; then
+  if test "$GOBJCXX" = yes; then
+    OBJCXXFLAGS="-g -O2"
+  else
+    OBJCXXFLAGS="-g"
+  fi
+else
+  if test "$GOBJCXX" = yes; then
+    OBJCXXFLAGS="-O2"
+  else
+    OBJCXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+    ac_ext=mm
+ac_cpp='$OBJCXXCPP $CPPFLAGS'
+ac_compile='$OBJCXX -c $OBJCXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$OBJCXX -o conftest$ac_exeext $OBJCXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_objcxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the Objective C++ preprocessor" >&5
+$as_echo_n "checking how to run the Objective C++ preprocessor... " >&6; }
+if test -z "$OBJCXXCPP"; then
+  if ${ac_cv_prog_OBJCXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because OBJCXXCPP needs to be expanded
+    for OBJCXXCPP in "$OBJCXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_objcxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_objcxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_objcxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_OBJCXXCPP=$OBJCXXCPP
+
+fi
+  OBJCXXCPP=$ac_cv_prog_OBJCXXCPP
+else
+  ac_cv_prog_OBJCXXCPP=$OBJCXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJCXXCPP" >&5
+$as_echo "$OBJCXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_objcxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_objcxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_objcxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Objective C++ preprocessor \"$OBJCXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+    OBJCXXFLAGS="$OBJCXXFLAGS -stdlib=libc++ -std=c++11"
+fi
+
+if test $HAVE_LINUX = yes ; then
+	LDFLAGS="$LDFLAGS -Wl,-z,defs"
+fi
+
+if test $HAVE_MSWINDOWS = yes ; then
+	CFLAGS="$CFLAGS -march=i686"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     BIGENDIAN=1;; #(
+   no)
+     BIGENDIAN=0 ;; #(
+   universal)
+     as_fn_error $? "Universal builds are not supported, sorry" "$LINENO" 5
+     ;; #(
+   *)
+     as_fn_error $? "Unknown machine byte order" "$LINENO" 5 ;;
+ esac
 
 
 
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking operating system type" >&5
-$as_echo_n "checking operating system type... " >&6; }
-
-HAVE_LINUX=no
-HAVE_MSWINDOWS=no
-
-case "$target" in
-    *linux*)
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux" >&5
-$as_echo "Linux" >&6; }
-        HAVE_LINUX=yes
-        ;;
-    *mingw*)
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: Windows" >&5
-$as_echo "Windows" >&6; }
-        HAVE_MSWINDOWS=yes
-        ;;
-    *)
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: other UNIX" >&5
-$as_echo "other UNIX" >&6; }
-        ;;
-esac
-
-
-
-
-if test $HAVE_LINUX = yes ; then
-	LDFLAGS="$LDFLAGS -Wl,-z,defs"
+if test "x$HAVE_MSWINDOWS" = "xyes" ; then
+    EXPORT="__declspec(dllexport)"
+elif test "x$GCC" = "xyes" ; then
+    CFLAGS="$CFLAGS -fvisibility=hidden"
+    CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
+    EXPORT="__attribute__((visibility(\"default\")))"
+else
+    as_fn_error $? "Unknown syntax for EXPORT keyword" "$LINENO" 5
 fi
 
-if test $HAVE_MSWINDOWS = yes ; then
-	CFLAGS="$CFLAGS -march=i686"
-fi
+cat >>confdefs.h <<_ACEOF
+#define EXPORT $EXPORT
+_ACEOF
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
 $as_echo_n "checking whether ln -s works... " >&6; }
@@ -5366,6 +6540,17 @@ $as_echo "yes" >&6; }
 
 fi
 
+
+# Check whether --enable-gtk was given.
+if test "${enable_gtk+set}" = set; then :
+  enableval=$enable_gtk; USE_GTK=$enableval
+else
+  USE_GTK=yes
+fi
+
+
+if test $USE_GTK = yes ; then
+
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5
 $as_echo_n "checking for GTK... " >&6; }
@@ -5374,12 +6559,12 @@ if test -n "$GTK_CFLAGS"; then
     pkg_cv_GTK_CFLAGS="$GTK_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= 3.4\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= 3.4") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.24\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.24") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-3.0 >= 3.4" 2>/dev/null`
+  pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= 2.24" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -5391,12 +6576,12 @@ if test -n "$GTK_LIBS"; then
     pkg_cv_GTK_LIBS="$GTK_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-3.0 >= 3.4\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gtk+-3.0 >= 3.4") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.24\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.24") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-3.0 >= 3.4" 2>/dev/null`
+  pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= 2.24" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -5417,14 +6602,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-3.0 >= 3.4" 2>&1`
+	        GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0 >= 2.24" 2>&1`
         else
-	        GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-3.0 >= 3.4" 2>&1`
+	        GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0 >= 2.24" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$GTK_PKG_ERRORS" >&5
 
-	as_fn_error $? "Package requirements (gtk+-3.0 >= 3.4) were not met:
+	as_fn_error $? "Package requirements (gtk+-2.0 >= 2.24) were not met:
 
 $GTK_PKG_ERRORS
 
@@ -5457,6 +6642,12 @@ $as_echo "yes" >&6; }
 
 fi
 
+$as_echo "#define USE_GTK 1" >>confdefs.h
+
+fi
+
+
+
 if test $HAVE_MSWINDOWS = yes ; then
 
 pkg_failed=no
@@ -5653,6 +6844,119 @@ fi
 
 
 
+# Check whether --enable-qt was given.
+if test "${enable_qt+set}" = set; then :
+  enableval=$enable_qt; USE_QT=$enableval
+else
+  USE_QT=no
+fi
+
+
+if test $USE_QT = yes ; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for QT" >&5
+$as_echo_n "checking for QT... " >&6; }
+
+if test -n "$QT_CFLAGS"; then
+    pkg_cv_QT_CFLAGS="$QT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core Qt5Gui Qt5Widgets\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5Core Qt5Gui Qt5Widgets") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QT_CFLAGS=`$PKG_CONFIG --cflags "Qt5Core Qt5Gui Qt5Widgets" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$QT_LIBS"; then
+    pkg_cv_QT_LIBS="$QT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core Qt5Gui Qt5Widgets\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5Core Qt5Gui Qt5Widgets") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QT_LIBS=`$PKG_CONFIG --libs "Qt5Core Qt5Gui Qt5Widgets" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        QT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "Qt5Core Qt5Gui Qt5Widgets" 2>&1`
+        else
+	        QT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "Qt5Core Qt5Gui Qt5Widgets" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$QT_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (Qt5Core Qt5Gui Qt5Widgets) were not met:
+
+$QT_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables QT_CFLAGS
+and QT_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables QT_CFLAGS
+and QT_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+	QT_CFLAGS=$pkg_cv_QT_CFLAGS
+	QT_LIBS=$pkg_cv_QT_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+$as_echo "#define USE_QT 1" >>confdefs.h
+
+
+    # needed if Qt was built with -reduce-relocations
+    QT_CFLAGS="$QT_CFLAGS -fPIC"
+fi
+
+
+
+
+
+
 
 
 
@@ -5662,15 +6966,15 @@ $as_echo_n "checking for shared library system... " >&6; }
 		darwin*)
 			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Darwin" >&5
 $as_echo "Darwin" >&6; }
-			LIB_CFLAGS='-fPIC -DPIC'
-			LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
+			LIB_CFLAGS='-fPIC -DPIC -mmacosx-version-min=10.7'
+			LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR} -mmacosx-version-min=10.7 -install_name "${libdir}/$$(i=${SHARED_LIB}; echo $${i%${LIB_SUFFIX}}).${LIB_MAJOR}${LIB_SUFFIX}"'
 			LIB_PREFIX='lib'
 			LIB_SUFFIX='.dylib'
 			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
-			PLUGIN_CFLAGS='-fPIC -DPIC'
-			PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup'
+			PLUGIN_CFLAGS='-fPIC -DPIC -mmacosx-version-min=10.7'
+			PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup -mmacosx-version-min=10.7'
 			PLUGIN_SUFFIX='.bundle'
-			INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && install_name_tool -id ${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
+			INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
 			UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib'
 			CLEAN_LIB=''
 			;;
@@ -5749,18 +7053,6 @@ $as_echo "GNU" >&6; }
 
 
 
-for ac_func in mkdtemp
-do :
-  ac_fn_c_check_func "$LINENO" "mkdtemp" "ac_cv_func_mkdtemp"
-if test "x$ac_cv_func_mkdtemp" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_MKDTEMP 1
-_ACEOF
-
-fi
-done
-
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
 set x ${MAKE-make}
@@ -6012,7 +7304,7 @@ $as_echo "$USE_NLS" >&6; }
 
 
 
-      GETTEXT_MACRO_VERSION=0.18
+      GETTEXT_MACRO_VERSION=0.19
 
 
 
@@ -7263,36 +8555,42 @@ else
       if test $am_cv_lib_iconv = yes; then
         LIBS="$LIBS $LIBICONV"
       fi
-      if test "$cross_compiling" = yes; then :
-
-         case "$host_os" in
-           aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
-           *)            am_cv_func_iconv_works="guessing yes" ;;
-         esac
-
+      am_cv_func_iconv_works=no
+      for ac_iconv_const in '' 'const'; do
+        if test "$cross_compiling" = yes; then :
+  case "$host_os" in
+             aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+             *)            am_cv_func_iconv_works="guessing yes" ;;
+           esac
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 #include <iconv.h>
 #include <string.h>
-int main ()
+
+#ifndef ICONV_CONST
+# define ICONV_CONST $ac_iconv_const
+#endif
+
+int
+main ()
 {
-  int result = 0;
+int result = 0;
   /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
      returns.  */
   {
     iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
     if (cd_utf8_to_88591 != (iconv_t)(-1))
       {
-        static const char input[] = "\342\202\254"; /* EURO SIGN */
+        static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
         char buf[10];
-        const char *inptr = input;
+        ICONV_CONST char *inptr = input;
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
         size_t res = iconv (cd_utf8_to_88591,
-                            (char **) &inptr, &inbytesleft,
+                            &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
         if (res == 0)
           result |= 1;
@@ -7305,14 +8603,14 @@ int main ()
     iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
     if (cd_ascii_to_88591 != (iconv_t)(-1))
       {
-        static const char input[] = "\263";
+        static ICONV_CONST char input[] = "\263";
         char buf[10];
-        const char *inptr = input;
+        ICONV_CONST char *inptr = input;
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
         size_t res = iconv (cd_ascii_to_88591,
-                            (char **) &inptr, &inbytesleft,
+                            &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
         if (res == 0)
           result |= 2;
@@ -7324,14 +8622,14 @@ int main ()
     iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
     if (cd_88591_to_utf8 != (iconv_t)(-1))
       {
-        static const char input[] = "\304";
+        static ICONV_CONST char input[] = "\304";
         static char buf[2] = { (char)0xDE, (char)0xAD };
-        const char *inptr = input;
+        ICONV_CONST char *inptr = input;
         size_t inbytesleft = 1;
         char *outptr = buf;
         size_t outbytesleft = 1;
         size_t res = iconv (cd_88591_to_utf8,
-                            (char **) &inptr, &inbytesleft,
+                            &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
         if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
           result |= 4;
@@ -7344,14 +8642,14 @@ int main ()
     iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
     if (cd_88591_to_utf8 != (iconv_t)(-1))
       {
-        static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+        static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
         char buf[50];
-        const char *inptr = input;
+        ICONV_CONST char *inptr = input;
         size_t inbytesleft = strlen (input);
         char *outptr = buf;
         size_t outbytesleft = sizeof (buf);
         size_t res = iconv (cd_88591_to_utf8,
-                            (char **) &inptr, &inbytesleft,
+                            &inptr, &inbytesleft,
                             &outptr, &outbytesleft);
         if ((int)res > 0)
           result |= 8;
@@ -7371,17 +8669,20 @@ int main ()
       && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
     result |= 16;
   return result;
+
+  ;
+  return 0;
 }
 _ACEOF
 if ac_fn_c_try_run "$LINENO"; then :
   am_cv_func_iconv_works=yes
-else
-  am_cv_func_iconv_works=no
 fi
 rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
   conftest.$ac_objext conftest.beam conftest.$ac_ext
 fi
 
+        test "$am_cv_func_iconv_works" = no || break
+      done
       LIBS="$am_save_LIBS"
 
 fi
@@ -8075,12 +9376,12 @@ if test -n "$AUDACIOUS_CFLAGS"; then
     pkg_cv_AUDACIOUS_CFLAGS="$AUDACIOUS_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"audacious >= 3.5\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "audacious >= 3.5") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"audacious >= 3.6\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "audacious >= 3.6") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_AUDACIOUS_CFLAGS=`$PKG_CONFIG --cflags "audacious >= 3.5" 2>/dev/null`
+  pkg_cv_AUDACIOUS_CFLAGS=`$PKG_CONFIG --cflags "audacious >= 3.6" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -8092,12 +9393,12 @@ if test -n "$AUDACIOUS_LIBS"; then
     pkg_cv_AUDACIOUS_LIBS="$AUDACIOUS_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"audacious >= 3.5\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "audacious >= 3.5") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"audacious >= 3.6\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "audacious >= 3.6") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_AUDACIOUS_LIBS=`$PKG_CONFIG --libs "audacious >= 3.5" 2>/dev/null`
+  pkg_cv_AUDACIOUS_LIBS=`$PKG_CONFIG --libs "audacious >= 3.6" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -8118,32 +9419,141 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        AUDACIOUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "audacious >= 3.5" 2>&1`
+	        AUDACIOUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "audacious >= 3.6" 2>&1`
         else
-	        AUDACIOUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "audacious >= 3.5" 2>&1`
+	        AUDACIOUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "audacious >= 3.6" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$AUDACIOUS_PKG_ERRORS" >&5
 
-	as_fn_error $? "Cannot find Audacious 3.5; have you installed Audacious yet?" "$LINENO" 5
+	as_fn_error $? "Cannot find Audacious 3.6; have you installed Audacious yet?" "$LINENO" 5
+
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	as_fn_error $? "Cannot find Audacious 3.6; have you installed Audacious yet?" "$LINENO" 5
+
+else
+	AUDACIOUS_CFLAGS=$pkg_cv_AUDACIOUS_CFLAGS
+	AUDACIOUS_LIBS=$pkg_cv_AUDACIOUS_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+CPPFLAGS="$CPPFLAGS $AUDACIOUS_CFLAGS"
+LIBS="$LIBS $AUDACIOUS_LIBS"
+
+
+if test $HAVE_DARWIN = yes ; then
+
+# Check whether --with-system-libxml2 was given.
+if test "${with_system_libxml2+set}" = set; then :
+  withval=$with_system_libxml2; with_system_libxml2=$withval
+else
+  with_system_libxml2=yes
+fi
+
+
+    if test $with_system_libxml2 = yes ; then
+        XML_LIBS="-lxml2"
+        XML_CFLAGS="-I/usr/include/libxml2"
+
+
+    else
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML" >&5
+$as_echo_n "checking for XML... " >&6; }
+
+if test -n "$XML_CFLAGS"; then
+    pkg_cv_XML_CFLAGS="$XML_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_XML_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$XML_LIBS"; then
+    pkg_cv_XML_LIBS="$XML_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_XML_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        XML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1`
+        else
+	        XML_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$XML_PKG_ERRORS" >&5
+
+	as_fn_error $? "Package requirements (libxml-2.0) were not met:
+
+$XML_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
 
+Alternatively, you may set the environment variables XML_CFLAGS
+and XML_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	as_fn_error $? "Cannot find Audacious 3.5; have you installed Audacious yet?" "$LINENO" 5
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables XML_CFLAGS
+and XML_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
 
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
 else
-	AUDACIOUS_CFLAGS=$pkg_cv_AUDACIOUS_CFLAGS
-	AUDACIOUS_LIBS=$pkg_cv_AUDACIOUS_LIBS
+	XML_CFLAGS=$pkg_cv_XML_CFLAGS
+	XML_LIBS=$pkg_cv_XML_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
 fi
-
-CPPFLAGS="$CPPFLAGS $AUDACIOUS_CFLAGS"
-LIBS="$LIBS $AUDACIOUS_LIBS"
-
-
+    fi
+else
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML" >&5
@@ -8235,16 +9645,27 @@ else
 $as_echo "yes" >&6; }
 
 fi
+fi
 
 
-INPUT_PLUGINS="tonegen metronom vtx"
+INPUT_PLUGINS="tonegen metronom"
 OUTPUT_PLUGINS=""
-EFFECT_PLUGINS="compressor crossfade crystalizer ladspa mixer stereo_plugin voice_removal echo_plugin"
-GENERAL_PLUGINS="alarm albumart delete-files search-tool"
-VISUALIZATION_PLUGINS="blur_scope cairo-spectrum"
+EFFECT_PLUGINS="compressor crossfade crystalizer mixer silence-removal stereo_plugin voice_removal echo_plugin"
+GENERAL_PLUGINS=""
+VISUALIZATION_PLUGINS=""
 CONTAINER_PLUGINS="asx asx3 audpl m3u pls xspf"
 TRANSPORT_PLUGINS="gio"
 
+if test "x$USE_GTK" = "xyes" ; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS alarm albumart delete-files playlist-manager search-tool statusicon"
+    GENERAL_PLUGINS="$GENERAL_PLUGINS gtkui skins"
+fi
+
+if test "x$USE_QT" = "xyes" ; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS albumart-qt lyricwiki-qt song-info-qt"
+    GENERAL_PLUGINS="$GENERAL_PLUGINS qtui"
+fi
+
 
 # Check whether --enable-console was given.
 if test "${enable_console+set}" = set; then :
@@ -8290,6 +9711,116 @@ if test "x$enable_xsf" != "xno"; then
 fi
 
 
+# Check whether --enable-qtaudio was given.
+if test "${enable_qtaudio+set}" = set; then :
+  enableval=$enable_qtaudio; enable_qtaudio=$enableval
+else
+  enable_qtaudio=auto
+fi
+
+
+have_qtaudio=no
+if test "x$enable_qtaudio" = "xyes" -o \( "x$USE_QT" = "xyes" -a "x$enable_qtaudio" = "xauto" \); then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for QTMULTIMEDIA" >&5
+$as_echo_n "checking for QTMULTIMEDIA... " >&6; }
+
+if test -n "$QTMULTIMEDIA_CFLAGS"; then
+    pkg_cv_QTMULTIMEDIA_CFLAGS="$QTMULTIMEDIA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Multimedia\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5Multimedia") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QTMULTIMEDIA_CFLAGS=`$PKG_CONFIG --cflags "Qt5Multimedia" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$QTMULTIMEDIA_LIBS"; then
+    pkg_cv_QTMULTIMEDIA_LIBS="$QTMULTIMEDIA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Multimedia\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5Multimedia") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QTMULTIMEDIA_LIBS=`$PKG_CONFIG --libs "Qt5Multimedia" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        QTMULTIMEDIA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "Qt5Multimedia" 2>&1`
+        else
+	        QTMULTIMEDIA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "Qt5Multimedia" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$QTMULTIMEDIA_PKG_ERRORS" >&5
+
+	have_qtaudio=no
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	have_qtaudio=no
+else
+	QTMULTIMEDIA_CFLAGS=$pkg_cv_QTMULTIMEDIA_CFLAGS
+	QTMULTIMEDIA_LIBS=$pkg_cv_QTMULTIMEDIA_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	have_qtaudio=yes
+fi
+    if test "x$have_qtaudio" = "xyes"; then
+        QTMULTIMEDIA_CFLAGS="$QTMULTIMEDIA_CFLAGS -fPIC"
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS qtaudio"
+    elif test "x$enable_qtaudio" = "xyes"; then
+        as_fn_error $? "QtAudio output plugin requested but QtMultimedia not found!" "$LINENO" 5
+    fi
+fi
+
+
+# Check whether --enable-coreaudio was given.
+if test "${enable_coreaudio+set}" = set; then :
+  enableval=$enable_coreaudio; enable_coreaudio=$enableval
+else
+  enable_coreaudio=auto
+
+fi
+
+
+have_coreaudio=no
+if test "x$enable_coreaudio" != "xno"; then
+    if test "x$HAVE_DARWIN" != "xno"; then
+        have_coreaudio=yes
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS coreaudio"
+    fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** CoreAudio output plugin disabled per user request ***" >&5
+$as_echo "*** CoreAudio output plugin disabled per user request ***" >&6; }
+fi
+
 
 # Check whether --enable-pulse was given.
 if test "${enable_pulse+set}" = set; then :
@@ -8403,12 +9934,11 @@ fi
 if test "${enable_mp3+set}" = set; then :
   enableval=$enable_mp3; enable_mp3=$enableval
 else
-  enable_mp3=auto
+  enable_mp3=yes
 fi
 
 
-have_mp3=no
-if test "x$enable_mp3" != "xno"; then
+if test $enable_mp3 = yes ; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MPG123" >&5
@@ -8468,28 +9998,39 @@ fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$MPG123_PKG_ERRORS" >&5
 
-	if test "x$enable_mp3" = "xyes"; then
-          as_fn_error $? "Cannot find libmpg123 development files (ver >= 1.12), but compilation of MP3 plugin has been explicitly requested; please install libmpg123 dev files and run configure again" "$LINENO" 5
-      fi
+	as_fn_error $? "Package requirements (libmpg123 >= 1.12) were not met:
+
+$MPG123_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
 
+Alternatively, you may set the environment variables MPG123_CFLAGS
+and MPG123_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_mp3" = "xyes"; then
-          as_fn_error $? "Cannot find libmpg123 development files (ver >= 1.12), but compilation of MP3 plugin has been explicitly requested; please install libmpg123 dev files and run configure again" "$LINENO" 5
-      fi
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
 
+Alternatively, you may set the environment variables MPG123_CFLAGS
+and MPG123_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	MPG123_CFLAGS=$pkg_cv_MPG123_CFLAGS
 	MPG123_LIBS=$pkg_cv_MPG123_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_mp3=yes
-      INPUT_PLUGINS="$INPUT_PLUGINS mpg123"
+
 fi
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** libmpg123 not found; MP3 plugin disabled" >&5
-$as_echo "*** libmpg123 not found; MP3 plugin disabled" >&6; }
+    INPUT_PLUGINS="$INPUT_PLUGINS mpg123"
 fi
 
 
@@ -8513,12 +10054,12 @@ if test -n "$GDKX11_CFLAGS"; then
     pkg_cv_GDKX11_CFLAGS="$GDKX11_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-x11-3.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gdk-x11-3.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-x11-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gdk-x11-2.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GDKX11_CFLAGS=`$PKG_CONFIG --cflags "gdk-x11-3.0" 2>/dev/null`
+  pkg_cv_GDKX11_CFLAGS=`$PKG_CONFIG --cflags "gdk-x11-2.0" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -8530,12 +10071,12 @@ if test -n "$GDKX11_LIBS"; then
     pkg_cv_GDKX11_LIBS="$GDKX11_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-x11-3.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gdk-x11-3.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gdk-x11-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gdk-x11-2.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GDKX11_LIBS=`$PKG_CONFIG --libs "gdk-x11-3.0" 2>/dev/null`
+  pkg_cv_GDKX11_LIBS=`$PKG_CONFIG --libs "gdk-x11-2.0" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -8556,22 +10097,22 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        GDKX11_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gdk-x11-3.0" 2>&1`
+	        GDKX11_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gdk-x11-2.0" 2>&1`
         else
-	        GDKX11_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gdk-x11-3.0" 2>&1`
+	        GDKX11_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gdk-x11-2.0" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$GDKX11_PKG_ERRORS" >&5
 
 	if test "x$enable_hotkey" = "xyes"; then
-            as_fn_error $? "Cannot find gdk-x11-3.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-3.0 dev files and run configure again" "$LINENO" 5
+            as_fn_error $? "Cannot find gdk-x11-2.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-2.0 dev files and run configure again" "$LINENO" 5
          fi
 
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 	if test "x$enable_hotkey" = "xyes"; then
-            as_fn_error $? "Cannot find gdk-x11-3.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-3.0 dev files and run configure again" "$LINENO" 5
+            as_fn_error $? "Cannot find gdk-x11-2.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-2.0 dev files and run configure again" "$LINENO" 5
          fi
 
 else
@@ -8744,19 +10285,6 @@ done
 fi
 
 
-# Check whether --enable-statusicon was given.
-if test "${enable_statusicon+set}" = set; then :
-  enableval=$enable_statusicon; have_statusicon=$enableval
-else
-  have_statusicon="yes"
-fi
-
-
-if test "x$have_statusicon" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS statusicon"
-fi
-
-
 # Check whether --enable-aosd was given.
 if test "${enable_aosd+set}" = set; then :
   enableval=$enable_aosd; enable_aosd=$enableval
@@ -9202,16 +10730,16 @@ $as_echo "*** AdPlug plugin disabled per user request ***" >&6; }
 fi
 
 
+
 # Check whether --enable-vorbis was given.
 if test "${enable_vorbis+set}" = set; then :
   enableval=$enable_vorbis; enable_vorbis=$enableval
 else
-  enable_vorbis=auto
+  enable_vorbis=yes
 fi
 
 
-have_vorbis=no
-if test "x$enable_vorbis" != "xno"; then
+if test $enable_vorbis = yes ; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VORBIS" >&5
@@ -9271,25 +10799,39 @@ fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$VORBIS_PKG_ERRORS" >&5
 
-	if test "x$enable_vorbis" = "xyes"; then
-            as_fn_error $? "Cannot find ogg, vorbis, vorbisenc or vorbisfile development files (ver >= 1.0), but compilation of Ogg Vorbis decoding and encoding has been explicitly requested; please install ogg, vorbis, vorbisenc and vorbisfile dev files and run configure again" "$LINENO" 5
-         fi
+	as_fn_error $? "Package requirements (ogg >= 1.0 vorbis >= 1.0 vorbisenc >= 1.0 vorbisfile >= 1.0) were not met:
+
+$VORBIS_PKG_ERRORS
 
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables VORBIS_CFLAGS
+and VORBIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_vorbis" = "xyes"; then
-            as_fn_error $? "Cannot find ogg, vorbis, vorbisenc or vorbisfile development files (ver >= 1.0), but compilation of Ogg Vorbis decoding and encoding has been explicitly requested; please install ogg, vorbis, vorbisenc and vorbisfile dev files and run configure again" "$LINENO" 5
-         fi
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables VORBIS_CFLAGS
+and VORBIS_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
 
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	VORBIS_CFLAGS=$pkg_cv_VORBIS_CFLAGS
 	VORBIS_LIBS=$pkg_cv_VORBIS_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_vorbis=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS vorbis"
+
 fi
+    INPUT_PLUGINS="$INPUT_PLUGINS vorbis"
 fi
 
 
@@ -9297,13 +10839,11 @@ fi
 if test "${enable_flacng+set}" = set; then :
   enableval=$enable_flacng; enable_flacng=$enableval
 else
-  enable_flacng=auto
-
+  enable_flacng=yes
 fi
 
 
-have_flacng=no
-if test "x$enable_flacng" != "xno"; then
+if test $enable_flacng = yes ; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBFLAC" >&5
@@ -9363,28 +10903,39 @@ fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBFLAC_PKG_ERRORS" >&5
 
-	if test "x$enable_flacng" = "xyes"; then
-            as_fn_error $? "Cannot find libFLAC development files (ver >= 1.2.1), but compilation of FLACng plugin has been explicitly requested; please install libFLAC dev files and run configure again" "$LINENO" 5
-         fi
+	as_fn_error $? "Package requirements (flac >= 1.2.1) were not met:
+
+$LIBFLAC_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
 
+Alternatively, you may set the environment variables LIBFLAC_CFLAGS
+and LIBFLAC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_flacng" = "xyes"; then
-            as_fn_error $? "Cannot find libFLAC development files (ver >= 1.2.1), but compilation of FLACng plugin has been explicitly requested; please install libFLAC dev files and run configure again" "$LINENO" 5
-         fi
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
 
+Alternatively, you may set the environment variables LIBFLAC_CFLAGS
+and LIBFLAC_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	LIBFLAC_CFLAGS=$pkg_cv_LIBFLAC_CFLAGS
 	LIBFLAC_LIBS=$pkg_cv_LIBFLAC_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_flacng=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS flacng"
+
 fi
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** FLACng plugin disabled per user request ***" >&5
-$as_echo "*** FLACng plugin disabled per user request ***" >&6; }
+    INPUT_PLUGINS="$INPUT_PLUGINS flacng"
 fi
 
 
@@ -9487,25 +11038,20 @@ fi
 if test "${enable_aac+set}" = set; then :
   enableval=$enable_aac; enable_aac=$enableval
 else
-  enable_aac=auto
-
+  enable_aac=yes
 fi
 
 
-have_aac=no
-if test "x$enable_aac" != "xno"; then
-    FAAD_LIBS="-lfaad"
-    FAAD_CFLAGS=
+if test $enable_aac = yes ; then
+    ac_fn_c_check_header_mongrel "$LINENO" "neaacdec.h" "ac_cv_header_neaacdec_h" "$ac_includes_default"
+if test "x$ac_cv_header_neaacdec_h" = xyes; then :
+  have_aac=yes
+else
+  have_aac=no
+fi
 
-    ac_fn_c_check_header_mongrel "$LINENO" "faad.h" "ac_cv_header_faad_h" "$ac_includes_default"
-if test "x$ac_cv_header_faad_h" = xyes; then :
-  ac_fn_c_check_decl "$LINENO" "FAAD2_VERSION" "ac_cv_have_decl_FAAD2_VERSION" "#include <neaacdec.h>
-"
-if test "x$ac_cv_have_decl_FAAD2_VERSION" = xyes; then :
-  ac_fn_c_check_decl "$LINENO" "NeAACDecInit2" "ac_cv_have_decl_NeAACDecInit2" "#include <neaacdec.h>
-"
-if test "x$ac_cv_have_decl_NeAACDecInit2" = xyes; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NeAACDecInit2 in -lfaad" >&5
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NeAACDecInit2 in -lfaad" >&5
 $as_echo_n "checking for NeAACDecInit2 in -lfaad... " >&6; }
 if ${ac_cv_lib_faad_NeAACDecInit2+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -9542,24 +11088,22 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_faad_NeAACDecInit2" >&5
 $as_echo "$ac_cv_lib_faad_NeAACDecInit2" >&6; }
 if test "x$ac_cv_lib_faad_NeAACDecInit2" = xyes; then :
-  have_aac=yes
-
-
-                     INPUT_PLUGINS="$INPUT_PLUGINS aac aac-raw"
-fi
-
+  have_aac=$have_aac
+else
+  have_aac=no
 fi
 
-fi
 
+    if test $have_aac != yes ; then
+        as_fn_error $? "Please install libfaad, or use --disable-aac to disable AAC support." "$LINENO" 5
+    fi
 
-fi
+    FAAD_CFLAGS=
+    FAAD_LIBS="-lfaad"
 
 
 
-    if test "x$enable_aac" = "xyes" -a "x$have_aac" != "xyes"; then
-        as_fn_error $? "Cannot find faad development files, but compilation of aac plugin has been explicitly requested; please install faad dev files and run configure again" "$LINENO" 5
-    fi
+    INPUT_PLUGINS="$INPUT_PLUGINS aac-raw"
 fi
 
 
@@ -9744,23 +11288,97 @@ else
 	MODPLUG_LIBS=$pkg_cv_MODPLUG_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	INPUT_PLUGINS="$INPUT_PLUGINS modplug"
-      have_modplug=yes
-fi
-fi
-
+	INPUT_PLUGINS="$INPUT_PLUGINS modplug"
+      have_modplug=yes
+fi
+fi
+
+
+
+# Check whether --with-ffmpeg was given.
+if test "${with_ffmpeg+set}" = set; then :
+  withval=$with_ffmpeg; ffmpeg_variant=$withval
+else
+  ffmpeg_variant=ffmpeg
+fi
+
+
+if test $ffmpeg_variant = ffmpeg ; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FFMPEG" >&5
+$as_echo_n "checking for FFMPEG... " >&6; }
+
+if test -n "$FFMPEG_CFLAGS"; then
+    pkg_cv_FFMPEG_CFLAGS="$FFMPEG_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FFMPEG_CFLAGS=`$PKG_CONFIG --cflags "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$FFMPEG_LIBS"; then
+    pkg_cv_FFMPEG_LIBS="$FFMPEG_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_FFMPEG_LIBS=`$PKG_CONFIG --libs "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0" 2>&1`
+        else
+	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$FFMPEG_PKG_ERRORS" >&5
+
+	as_fn_error $? "FFmpeg is not installed or too old (required: libavcodec 53.40.0, libavformat 53.21.0, libavutil 51.27.0).  Use --with-ffmpeg=none to disable the ffaudio plugin or --with-ffmpeg=libav to use libav instead." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	as_fn_error $? "FFmpeg is not installed or too old (required: libavcodec 53.40.0, libavformat 53.21.0, libavutil 51.27.0).  Use --with-ffmpeg=none to disable the ffaudio plugin or --with-ffmpeg=libav to use libav instead." "$LINENO" 5
+else
+	FFMPEG_CFLAGS=$pkg_cv_FFMPEG_CFLAGS
+	FFMPEG_LIBS=$pkg_cv_FFMPEG_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"
 
-# Check whether --enable-ffaudio was given.
-if test "${enable_ffaudio+set}" = set; then :
-  enableval=$enable_ffaudio; enable_ffaudio=$enableval
-else
-  enable_ffaudio=auto
+$as_echo "#define HAVE_FFMPEG 1" >>confdefs.h
 
 fi
-
-
-have_ffaudio=no
-if test "x$enable_ffaudio" != "xno"; then
+elif test $ffmpeg_variant = libav ; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FFMPEG" >&5
@@ -9770,12 +11388,12 @@ if test -n "$FFMPEG_CFLAGS"; then
     pkg_cv_FFMPEG_CFLAGS="$FFMPEG_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_FFMPEG_CFLAGS=`$PKG_CONFIG --cflags "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>/dev/null`
+  pkg_cv_FFMPEG_CFLAGS=`$PKG_CONFIG --cflags "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -9787,12 +11405,12 @@ if test -n "$FFMPEG_LIBS"; then
     pkg_cv_FFMPEG_LIBS="$FFMPEG_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_FFMPEG_LIBS=`$PKG_CONFIG --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>/dev/null`
+  pkg_cv_FFMPEG_LIBS=`$PKG_CONFIG --libs "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -9813,31 +11431,27 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>&1`
+	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0" 2>&1`
         else
-	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0" 2>&1`
+	        FFMPEG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$FFMPEG_PKG_ERRORS" >&5
 
-	if test "x$enable_ffaudio" = "xyes"; then
-            as_fn_error $? "Cannot find FFmpeg development files (libavcodec ver >= 53.40.0, libavformat ver >= 53.5.0, libavutil ver >= 50.42.0), but compilation of ffaudio plugin has been explicitly requested; please install FFmpeg dev files and run configure again" "$LINENO" 5
-         fi
-
+	as_fn_error $? "libav is not installed or too old (required: libavcodec 53.25.0, libavformat 53.15.0, libavutil 51.18.0)." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_ffaudio" = "xyes"; then
-            as_fn_error $? "Cannot find FFmpeg development files (libavcodec ver >= 53.40.0, libavformat ver >= 53.5.0, libavutil ver >= 50.42.0), but compilation of ffaudio plugin has been explicitly requested; please install FFmpeg dev files and run configure again" "$LINENO" 5
-         fi
-
+	as_fn_error $? "libav is not installed or too old (required: libavcodec 53.25.0, libavformat 53.15.0, libavutil 51.18.0)." "$LINENO" 5
 else
 	FFMPEG_CFLAGS=$pkg_cv_FFMPEG_CFLAGS
 	FFMPEG_LIBS=$pkg_cv_FFMPEG_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_ffaudio=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"
+	INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"
+
+$as_echo "#define HAVE_LIBAV 1" >>confdefs.h
+
 fi
 fi
 
@@ -10067,85 +11681,9 @@ $as_echo "yes" >&6; }
 fi
 
     if test "x$have_jack" = "xyes"; then
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SAMPLERATE" >&5
-$as_echo_n "checking for SAMPLERATE... " >&6; }
-
-if test -n "$SAMPLERATE_CFLAGS"; then
-    pkg_cv_SAMPLERATE_CFLAGS="$SAMPLERATE_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "samplerate") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_SAMPLERATE_CFLAGS=`$PKG_CONFIG --cflags "samplerate" 2>/dev/null`
-		      test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$SAMPLERATE_LIBS"; then
-    pkg_cv_SAMPLERATE_LIBS="$SAMPLERATE_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "samplerate") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_SAMPLERATE_LIBS=`$PKG_CONFIG --libs "samplerate" 2>/dev/null`
-		      test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-	        SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "samplerate" 2>&1`
-        else
-	        SAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "samplerate" 2>&1`
-        fi
-	# Put the nasty error message in config.log where it belongs
-	echo "$SAMPLERATE_PKG_ERRORS" >&5
-
-	have_jack=no
-
-elif test $pkg_failed = untried; then
-     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-	have_jack=no
-
-else
-	SAMPLERATE_CFLAGS=$pkg_cv_SAMPLERATE_CFLAGS
-	SAMPLERATE_LIBS=$pkg_cv_SAMPLERATE_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-fi
-    fi
-
-    if test "x$have_jack" = "xyes"; then
-        OUTPUT_PLUGINS="$OUTPUT_PLUGINS jack"
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS jack-ng"
     elif test "x$enable_jack" = "xyes"; then
-        as_fn_error $? "Cannot find JACK (ver >= 0.120.1 but < 1.0 or >= 1.9.7) or libsamplerate development files, but compilation of JACK output plugin has been explicitly requested; please install JACK and libsamplerate dev files and run configure again" "$LINENO" 5
+        as_fn_error $? "Cannot find JACK (ver >= 0.120.1 but < 1.0 or >= 1.9.7) development files, but compilation of JACK output plugin has been explicitly requested; please install JACK dev files and run configure again" "$LINENO" 5
     fi
 fi
 
@@ -10269,42 +11807,22 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
   cat >>confdefs.h <<_ACEOF
 #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
-
+ have_oss4=yes
 fi
 
 done
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OSS4" >&5
-$as_echo_n "checking for OSS4... " >&6; }
-
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifdef HAVE_SYS_SOUNDCARD_H
-      #include <sys/soundcard.h>
-      #elif defined HAVE_SOUNDCARD_H
-      #include <soundcard.h>
-      #endif
-      #if OSS_VERSION >= 0x40000 || SOUND_VERSION >= 0x40000
-          yes
-      #endif
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "yes" >/dev/null 2>&1; then :
-  have_oss4=yes
-      OUTPUT_PLUGINS="$OUTPUT_PLUGINS oss4"
-
-else
-  if test "x$enable_oss4" = "xyes"; then
-        as_fn_error $? "Cannot find OSS4 development files, but compilation of OSS4 output plugin has been explicitly requested; please install OSS4 dev files and run configure again" "$LINENO" 5
-      fi
+    CPPFLAGS="$OLD_CPPFLAGS"
 
-fi
-rm -f conftest*
+    if test "x$have_oss4" = "xyes" ; then
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS oss4"
 
+    elif test "x$enable_oss4" = "xyes" ; then
+        as_fn_error $? "OSS4 output was enabled but soundcard.h was not found" "$LINENO" 5
+    fi
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_oss4" >&5
 $as_echo "$have_oss4" >&6; }
-    CPPFLAGS="$OLD_CPPFLAGS"
 fi
 
 
@@ -10321,19 +11839,190 @@ have_alsa=no
 if test "x$enable_alsa" != "xno"; then
 
 pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5
-$as_echo_n "checking for ALSA... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5
+$as_echo_n "checking for ALSA... " >&6; }
+
+if test -n "$ALSA_CFLAGS"; then
+    pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0.16\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa >= 1.0.16") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa >= 1.0.16" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$ALSA_LIBS"; then
+    pkg_cv_ALSA_LIBS="$ALSA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0.16\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa >= 1.0.16") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa >= 1.0.16" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "alsa >= 1.0.16" 2>&1`
+        else
+	        ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "alsa >= 1.0.16" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$ALSA_PKG_ERRORS" >&5
+
+	if test "x$enable_alsa" = "xyes"; then
+            as_fn_error $? "Cannot find ALSA development files (ver >= 1.0.16), but compilation of ALSA output plugin has been explicitly requested; please install ALSA dev files and run configure again" "$LINENO" 5
+         fi
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	if test "x$enable_alsa" = "xyes"; then
+            as_fn_error $? "Cannot find ALSA development files (ver >= 1.0.16), but compilation of ALSA output plugin has been explicitly requested; please install ALSA dev files and run configure again" "$LINENO" 5
+         fi
+else
+	ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS
+	ALSA_LIBS=$pkg_cv_ALSA_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	have_alsa=yes
+         OUTPUT_PLUGINS="$OUTPUT_PLUGINS alsa"
+fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** ALSA output plugin disabled per user request ***" >&5
+$as_echo "*** ALSA output plugin disabled per user request ***" >&6; }
+fi
+
+
+# Check whether --enable-sdlout was given.
+if test "${enable_sdlout+set}" = set; then :
+  enableval=$enable_sdlout; enable_sdlout=$enableval
+else
+  enable_sdlout=auto
+fi
+
+
+if test "x$enable_sdlout" != "xno"; then
+
+# Check whether --with-libsdl was given.
+if test "${with_libsdl+set}" = set; then :
+  withval=$with_libsdl; case "x$withval" in
+                     x1) ;;
+                     x2) ;;
+                     x*) withval=check;;
+                 esac
+                 with_libsdl=$withval
+else
+  with_libsdl=check
+fi
+
+fi
+
+libsdl1_min="1.2.11";
+libsdl2_min="2.0";
+
+have_sdlout=no
+if test "x$enable_sdlout" != "xno"; then
+    if test "x$with_libsdl" = "xcheck"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
+$as_echo_n "checking for SDL... " >&6; }
+
+if test -n "$SDL_CFLAGS"; then
+    pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= \$libsdl2_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl2 >= $libsdl2_min") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl2 >= $libsdl2_min" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$SDL_LIBS"; then
+    pkg_cv_SDL_LIBS="$SDL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= \$libsdl2_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl2 >= $libsdl2_min") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl2 >= $libsdl2_min" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl2 >= $libsdl2_min" 2>&1`
+        else
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl2 >= $libsdl2_min" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$SDL_PKG_ERRORS" >&5
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
+$as_echo_n "checking for SDL... " >&6; }
 
-if test -n "$ALSA_CFLAGS"; then
-    pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS"
+if test -n "$SDL_CFLAGS"; then
+    pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0.16\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "alsa >= 1.0.16") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa >= 1.0.16" 2>/dev/null`
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10341,16 +12030,16 @@ fi
  else
     pkg_failed=untried
 fi
-if test -n "$ALSA_LIBS"; then
-    pkg_cv_ALSA_LIBS="$ALSA_LIBS"
+if test -n "$SDL_LIBS"; then
+    pkg_cv_SDL_LIBS="$SDL_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0.16\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "alsa >= 1.0.16") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa >= 1.0.16" 2>/dev/null`
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10371,46 +12060,33 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "alsa >= 1.0.16" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         else
-	        ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "alsa >= 1.0.16" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
-	echo "$ALSA_PKG_ERRORS" >&5
+	echo "$SDL_PKG_ERRORS" >&5
 
-	if test "x$enable_alsa" = "xyes"; then
-            as_fn_error $? "Cannot find ALSA development files (ver >= 1.0.16), but compilation of ALSA output plugin has been explicitly requested; please install ALSA dev files and run configure again" "$LINENO" 5
-         fi
+	if test "x$enable_sdlout" = "xyes"; then
+                   as_fn_error $? "Cannot find SDL development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
+                fi
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_alsa" = "xyes"; then
-            as_fn_error $? "Cannot find ALSA development files (ver >= 1.0.16), but compilation of ALSA output plugin has been explicitly requested; please install ALSA dev files and run configure again" "$LINENO" 5
-         fi
+	if test "x$enable_sdlout" = "xyes"; then
+                   as_fn_error $? "Cannot find SDL development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
+                fi
 else
-	ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS
-	ALSA_LIBS=$pkg_cv_ALSA_LIBS
+	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
+	SDL_LIBS=$pkg_cv_SDL_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_alsa=yes
-         OUTPUT_PLUGINS="$OUTPUT_PLUGINS alsa"
-fi
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** ALSA output plugin disabled per user request ***" >&5
-$as_echo "*** ALSA output plugin disabled per user request ***" >&6; }
-fi
-
-
-# Check whether --enable-sdlout was given.
-if test "${enable_sdlout+set}" = set; then :
-  enableval=$enable_sdlout; enable_sdlout=$enableval
-else
-  enable_sdlout=auto
+	have_sdlout=yes
+                OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
 fi
-
-
-have_sdlout=no
-if test "x$enable_sdlout" != "xno"; then
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
@@ -10420,12 +12096,12 @@ if test -n "$SDL_CFLAGS"; then
     pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= 2.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl2 >= 2.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl2 >= 2.0" 2>/dev/null`
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10437,12 +12113,12 @@ if test -n "$SDL_LIBS"; then
     pkg_cv_SDL_LIBS="$SDL_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= 2.0\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl2 >= 2.0") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl2 >= 2.0" 2>/dev/null`
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10463,13 +12139,39 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl2 >= 2.0" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         else
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl2 >= 2.0" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$SDL_PKG_ERRORS" >&5
 
+	if test "x$enable_sdlout" = "xyes"; then
+                   as_fn_error $? "Cannot find SDL development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
+                fi
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	if test "x$enable_sdlout" = "xyes"; then
+                   as_fn_error $? "Cannot find SDL development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
+                fi
+else
+	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
+	SDL_LIBS=$pkg_cv_SDL_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	have_sdlout=yes
+                OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
+fi
+else
+	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
+	SDL_LIBS=$pkg_cv_SDL_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	have_sdlout=yes
+            OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
+fi
+    elif test "x$with_libsdl" = "x1"; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
@@ -10479,12 +12181,12 @@ if test -n "$SDL_CFLAGS"; then
     pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= 1.2.11\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl >= 1.2.11") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl >= 1.2.11" 2>/dev/null`
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10496,12 +12198,12 @@ if test -n "$SDL_LIBS"; then
     pkg_cv_SDL_LIBS="$SDL_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= 1.2.11\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl >= 1.2.11") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= \$libsdl1_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl >= $libsdl1_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl >= 1.2.11" 2>/dev/null`
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl >= $libsdl1_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10522,33 +12224,31 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl >= 1.2.11" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         else
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl >= 1.2.11" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl >= $libsdl1_min" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$SDL_PKG_ERRORS" >&5
 
 	if test "x$enable_sdlout" = "xyes"; then
-               as_fn_error $? "Cannot find SDL development files (ver >= 1.2.11), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
-            fi
+                 as_fn_error $? "Cannot find SDL1 development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL1 dev files and run configure again" "$LINENO" 5
+             fi
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 	if test "x$enable_sdlout" = "xyes"; then
-               as_fn_error $? "Cannot find SDL development files (ver >= 1.2.11), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
-            fi
+                 as_fn_error $? "Cannot find SDL1 development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL1 dev files and run configure again" "$LINENO" 5
+             fi
 else
 	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
 	SDL_LIBS=$pkg_cv_SDL_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 	have_sdlout=yes
-            OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
 fi
-elif test $pkg_failed = untried; then
-     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+    elif test "x$with_libsdl" = "x2"; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5
@@ -10558,12 +12258,12 @@ if test -n "$SDL_CFLAGS"; then
     pkg_cv_SDL_CFLAGS="$SDL_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= 1.2.11\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl >= 1.2.11") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= \$libsdl2_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl2 >= $libsdl2_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl >= 1.2.11" 2>/dev/null`
+  pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl2 >= $libsdl2_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10575,12 +12275,12 @@ if test -n "$SDL_LIBS"; then
     pkg_cv_SDL_LIBS="$SDL_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl >= 1.2.11\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sdl >= 1.2.11") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl2 >= \$libsdl2_min\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sdl2 >= $libsdl2_min") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl >= 1.2.11" 2>/dev/null`
+  pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl2 >= $libsdl2_min" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -10601,38 +12301,31 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl >= 1.2.11" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sdl2 >= $libsdl2_min" 2>&1`
         else
-	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl >= 1.2.11" 2>&1`
+	        SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sdl2 >= $libsdl2_min" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$SDL_PKG_ERRORS" >&5
 
 	if test "x$enable_sdlout" = "xyes"; then
-               as_fn_error $? "Cannot find SDL development files (ver >= 1.2.11), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
-            fi
+                 as_fn_error $? "Cannot find SDL2 development files (ver >= $libsdl2_min), but compilation of SDL output plugin has been explicitly requested; please install SDL2 dev files and run configure again" "$LINENO" 5
+             fi
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 	if test "x$enable_sdlout" = "xyes"; then
-               as_fn_error $? "Cannot find SDL development files (ver >= 1.2.11), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again" "$LINENO" 5
-            fi
-else
-	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
-	SDL_LIBS=$pkg_cv_SDL_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-	have_sdlout=yes
-            OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
-fi
+                 as_fn_error $? "Cannot find SDL2 development files (ver >= $libsdl2_min), but compilation of SDL output plugin has been explicitly requested; please install SDL2 dev files and run configure again" "$LINENO" 5
+             fi
 else
 	SDL_CFLAGS=$pkg_cv_SDL_CFLAGS
 	SDL_LIBS=$pkg_cv_SDL_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 	have_sdlout=yes
-        OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"
 fi
+    fi
 fi
 
 
@@ -10687,7 +12380,7 @@ fi
 $as_echo "$ac_cv_lib_sndio_sio_open" >&6; }
 if test "x$ac_cv_lib_sndio_sio_open" = xyes; then :
   have_sndio=yes
-             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sndio"
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sndio-ng"
              SNDIO_LIBS="-lsndio"
 
 
@@ -10704,6 +12397,11 @@ fi
 fi
 
 
+if test "x$OUTPUT_PLUGINS" = "x" ; then
+    as_fn_error $? "No output plugin was enabled.  Please install the necessary packages for your system and run configure again." "$LINENO" 5
+fi
+
+
 # Check whether --enable-amidiplug was given.
 if test "${enable_amidiplug+set}" = set; then :
   enableval=$enable_amidiplug; enable_amidiplug=$enableval
@@ -10788,7 +12486,7 @@ else
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 	have_amidiplug=yes
-         OUTPUT_PLUGINS="$OUTPUT_PLUGINS amidi-plug"
+         INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug"
 fi
 fi
 
@@ -11063,12 +12761,11 @@ fi
 if test "${enable_neon+set}" = set; then :
   enableval=$enable_neon; enable_neon=$enableval
 else
-  enable_neon=auto
+  enable_neon=yes
 fi
 
 
-have_neon=no
-if test "x$enable_neon" != "xno"; then
+if test $enable_neon = yes ; then
 
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NEON" >&5
@@ -11078,12 +12775,12 @@ if test -n "$NEON_CFLAGS"; then
     pkg_cv_NEON_CFLAGS="$NEON_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"neon >= 0.26\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "neon >= 0.26") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"neon >= 0.27\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "neon >= 0.27") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_NEON_CFLAGS=`$PKG_CONFIG --cflags "neon >= 0.26" 2>/dev/null`
+  pkg_cv_NEON_CFLAGS=`$PKG_CONFIG --cflags "neon >= 0.27" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -11095,12 +12792,12 @@ if test -n "$NEON_LIBS"; then
     pkg_cv_NEON_LIBS="$NEON_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"neon >= 0.26\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "neon >= 0.26") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"neon >= 0.27\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "neon >= 0.27") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_NEON_LIBS=`$PKG_CONFIG --libs "neon >= 0.26" 2>/dev/null`
+  pkg_cv_NEON_LIBS=`$PKG_CONFIG --libs "neon >= 0.27" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -11121,76 +12818,46 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        NEON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "neon >= 0.26" 2>&1`
+	        NEON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "neon >= 0.27" 2>&1`
         else
-	        NEON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "neon >= 0.26" 2>&1`
+	        NEON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "neon >= 0.27" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$NEON_PKG_ERRORS" >&5
 
-	if test "x$enable_neon" = "xyes"; then
-            as_fn_error $? "Cannot find neon development files (ver >= 0.26), but compilation of neon HTTP support has been explicitly requested; please install neon dev files and run configure again" "$LINENO" 5
-         fi
+	as_fn_error $? "Package requirements (neon >= 0.27) were not met:
+
+$NEON_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
 
+Alternatively, you may set the environment variables NEON_CFLAGS
+and NEON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-	if test "x$enable_neon" = "xyes"; then
-            as_fn_error $? "Cannot find neon development files (ver >= 0.26), but compilation of neon HTTP support has been explicitly requested; please install neon dev files and run configure again" "$LINENO" 5
-         fi
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
 
+Alternatively, you may set the environment variables NEON_CFLAGS
+and NEON_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
 else
 	NEON_CFLAGS=$pkg_cv_NEON_CFLAGS
 	NEON_LIBS=$pkg_cv_NEON_LIBS
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
-	have_neon=yes
-         TRANSPORT_PLUGINS="$TRANSPORT_PLUGINS neon"
-         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ne_set_connect_timeout in -lneon" >&5
-$as_echo_n "checking for ne_set_connect_timeout in -lneon... " >&6; }
-if ${ac_cv_lib_neon_ne_set_connect_timeout+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lneon $NEON_LIBS $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ne_set_connect_timeout ();
-int
-main ()
-{
-return ne_set_connect_timeout ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_neon_ne_set_connect_timeout=yes
-else
-  ac_cv_lib_neon_ne_set_connect_timeout=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_neon_ne_set_connect_timeout" >&5
-$as_echo "$ac_cv_lib_neon_ne_set_connect_timeout" >&6; }
-if test "x$ac_cv_lib_neon_ne_set_connect_timeout" = xyes; then :
-
-$as_echo "#define HAVE_NE_SET_CONNECT_TIMEOUT 1" >>confdefs.h
-
-fi
-
-
 
 fi
+    TRANSPORT_PLUGINS="$TRANSPORT_PLUGINS neon"
 fi
 
 
@@ -11462,7 +13129,7 @@ fi
 
 
 have_vorbisenc=no
-if test "x$have_filewriter" = "xyes" -a "x$have_vorbis" = "xyes"; then
+if test "x$have_filewriter" = "xyes" -a "x$enable_vorbis" = "xyes"; then
     have_vorbisenc=yes
 
 $as_echo "#define FILEWRITER_VORBIS 1" >>confdefs.h
@@ -11940,32 +13607,6 @@ fi
 fi
 
 
-# Check whether --enable-gtkui was given.
-if test "${enable_gtkui+set}" = set; then :
-  enableval=$enable_gtkui; enable_gtkui=$enableval
-else
-  enable_gtkui="yes"
-fi
-
-
-if test "x$enable_gtkui" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS gtkui"
-fi
-
-
-# Check whether --enable-skins was given.
-if test "${enable_skins+set}" = set; then :
-  enableval=$enable_skins; enable_skins=$enableval
-else
-  enable_skins="yes"
-fi
-
-
-if test "x$enable_skins" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS skins"
-fi
-
-
 # Check whether --enable-lyricwiki was given.
 if test "${enable_lyricwiki+set}" = set; then :
   enableval=$enable_lyricwiki; enable_lyricwiki=$enableval
@@ -12131,6 +13772,164 @@ fi
 
 
 
+# Check whether --enable-qtglspectrum was given.
+if test "${enable_qtglspectrum+set}" = set; then :
+  enableval=$enable_qtglspectrum; enable_qtglspectrum=$enableval
+else
+  enable_qtglspectrum=auto
+fi
+
+
+have_qtglspectrum=no
+if test "x$USE_QT" = "xno" -a "x$enable_qtglspectrum" = "xyes"; then
+    as_fn_error $? "--enable-qtglspectrum cannot be used without --enable-qt" "$LINENO" 5
+fi
+if test "x$USE_QT" = "xyes" -a "x$enable_qtglspectrum" != "xno"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for QTOPENGL" >&5
+$as_echo_n "checking for QTOPENGL... " >&6; }
+
+if test -n "$QTOPENGL_CFLAGS"; then
+    pkg_cv_QTOPENGL_CFLAGS="$QTOPENGL_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5OpenGL\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5OpenGL") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QTOPENGL_CFLAGS=`$PKG_CONFIG --cflags "Qt5OpenGL" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$QTOPENGL_LIBS"; then
+    pkg_cv_QTOPENGL_LIBS="$QTOPENGL_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5OpenGL\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "Qt5OpenGL") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_QTOPENGL_LIBS=`$PKG_CONFIG --libs "Qt5OpenGL" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        QTOPENGL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "Qt5OpenGL" 2>&1`
+        else
+	        QTOPENGL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "Qt5OpenGL" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$QTOPENGL_PKG_ERRORS" >&5
+
+	have_qtglspectrum=no
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	have_qtglspectrum=no
+else
+	QTOPENGL_CFLAGS=$pkg_cv_QTOPENGL_CFLAGS
+	QTOPENGL_LIBS=$pkg_cv_QTOPENGL_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	have_qtglspectrum=yes
+fi
+    if test "x$have_qtglspectrum" = "xyes"; then
+        QTOPENGL_CFLAGS="$QTOPENGL_CFLAGS -fPIC"
+        VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS gl-spectrum-qt"
+    elif test "x$enable_qtglspectrum" = "xyes"; then
+        as_fn_error $? "Qt OpenGL Spectrum Analyzer plugin requested but QtOpenGL not found!" "$LINENO" 5
+    fi
+fi
+
+
+# Check whether --enable-vtx was given.
+if test "${enable_vtx+set}" = set; then :
+  enableval=$enable_vtx; enable_vtx=$enableval
+else
+  enable_vtx="yes"
+fi
+
+
+if test "x$enable_vtx" != "xno"; then
+    INPUT_PLUGINS="$INPUT_PLUGINS vtx"
+fi
+
+
+# Check whether --enable-ladspa was given.
+if test "${enable_ladspa+set}" = set; then :
+  enableval=$enable_ladspa; enable_ladspa=$enableval
+else
+  enable_ladspa="yes"
+fi
+
+
+if test "x$enable_ladspa" != "xno"; then
+    EFFECT_PLUGINS="$EFFECT_PLUGINS ladspa"
+fi
+
+
+# Check whether --enable-blur_scope was given.
+if test "${enable_blur_scope+set}" = set; then :
+  enableval=$enable_blur_scope; enable_blur_scope=$enableval
+else
+  enable_blur_scope="yes"
+fi
+
+
+if test "x$enable_blur_scope" != "xno"; then
+    VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS blur_scope"
+fi
+
+
+# Check whether --enable-cairo_spectrum was given.
+if test "${enable_cairo_spectrum+set}" = set; then :
+  enableval=$enable_cairo_spectrum; enable_cairo_spectrum=$enableval
+else
+  enable_cairo_spectrum="yes"
+fi
+
+
+if test "x$enable_cairo_spectrum" != "xno"; then
+    VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS cairo-spectrum"
+fi
+
+
+# Check whether --enable-mac_media_keys was given.
+if test "${enable_mac_media_keys+set}" = set; then :
+  enableval=$enable_mac_media_keys; enable_mac_media_keys=$enableval
+else
+  enable_mac_media_keys="no"
+fi
+
+
+if test "x$enable_mac_media_keys" != "xno"; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS mac-media-keys"
+fi
+
+
 plugindir=`pkg-config audacious --variable=plugin_dir`
 
 
@@ -12799,7 +14598,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by audacious-plugins $as_me 3.5, which was
+This file was extended by audacious-plugins $as_me 3.6.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12865,7 +14664,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-audacious-plugins config.status 3.5
+audacious-plugins config.status 3.6.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -13737,9 +15536,11 @@ echo "  --------------"
 echo "  Open Sound System (oss4):               $have_oss4"
 echo "  Advanced Linux Sound Arch. (alsa):      $have_alsa"
 echo "  Sndio (sndio):                          $have_sndio"
+echo "  CoreAudio (coreaudio):                  $have_coreaudio"
 echo "  PulseAudio (pulse):                     $have_pulse"
 echo "  Jack Audio Connection Kit (jack):       $have_jack"
 echo "  Simple DirectMedia Layer (sdlout):      $have_sdlout"
+echo "  Qt Multimedia (qtaudio):                $have_qtaudio"
 echo "  FileWriter:                             $have_filewriter"
 echo "    -> FileWriter MP3 output part:        $have_lame"
 echo "    -> FileWriter Vorbis output part:     $have_vorbisenc"
@@ -13747,16 +15548,16 @@ echo "    -> FileWriter FLAC output part:       $have_writer_flac"
 echo
 echo "  Input Plugins"
 echo "  -------------"
-echo "  MPEG-1 Layer I/II/III (mpg123):         $have_mp3"
-echo "  MPEG-2/4 AAC (aac):                     $have_aac"
-echo "  FFaudio (ffaudio):                      $have_ffaudio"
+echo "  MPEG-1 Layer I/II/III (mpg123):         $enable_mp3"
+echo "  MPEG-2/4 AAC (aac):                     $enable_aac"
+echo "  FFaudio (ffaudio):                      $ffmpeg_variant"
 echo "  Module decoder (modplug):               $have_modplug"
 echo "  MIDI synthesizer (amidi-plug):          $have_amidiplug"
 echo "  CD Digital Audio (cdaudio_ng):          $have_cdaudio_ng"
 echo "  sndfile extensions:                     $have_sndfile"
 echo "  Tone Generator:                         yes"
-echo "  Ogg Vorbis (vorbis):                    $have_vorbis"
-echo "  Free Lossless Audio Codec (flacng):     $have_flacng"
+echo "  Ogg Vorbis (vorbis):                    $enable_vorbis"
+echo "  Free Lossless Audio Codec (flacng):     $enable_flacng"
 echo "  Commodore 64 audio (SID):               $have_sidplay"
 echo "  Game music (spc, nsf & gbs):            $have_console"
 echo "  PlayStation (psf/psf2) audio:           $enable_psf"
@@ -13764,17 +15565,19 @@ echo "  Nintendo DS audio (xsf):                $enable_xsf"
 echo "  AdLib synthesizer (adplug):             $have_adplug"
 echo "  WavPack 4.31+ (wavpack):                $have_wavpack"
 echo "  Metronom:                               yes"
+echo "  VTX Decoder:                            $enable_vtx"
 echo
 echo "  General"
 echo "  -------"
-echo "  Alarm:                                  yes"
-echo "  Album Art:                              yes"
-echo "  Delete from Filesystem:                 yes"
+echo "  Alarm:                                  $USE_GTK"
+echo "  Album Art:                              $USE_GTK"
+echo "  Delete from Filesystem:                 $USE_GTK"
 echo "  Linux Infrared Remote Control (LIRC)    $have_lirc"
 echo "  MPRIS 2 Server:                         $have_mpris2"
-echo "  Search Tool:                            yes"
+echo "  Playlist Manager:                       $USE_GTK"
+echo "  Search Tool:                            $USE_GTK"
 echo "  Song Change:                            $have_songchange"
-echo "  Status Icon:                            $have_statusicon"
+echo "  Status Icon:                            $USE_GTK"
 echo "  Audacious OSD:                          $have_aosd"
 echo "    -> X Composite support:               $have_aosd_xcomp"
 echo "  libnotify OSD:                          $have_notify"
@@ -13782,6 +15585,7 @@ echo "  Global Hotkey Plugin:                   $have_hotkey"
 echo "  Gnome Shortcuts Plugin:                 $have_gnomeshortcuts"
 echo "  Scrobbler 2.0:                          $have_scrobbler2"
 echo "  LyricWiki viewer:                       $have_lyricwiki"
+echo "  Mac Media Keys:                         $enable_mac_media_keys"
 echo
 echo "  Effect"
 echo "  ------"
@@ -13790,22 +15594,24 @@ echo "  Crystalizer:                            yes"
 echo "  Dynamic Range Compressor:               yes"
 echo "  Echo/Surround:                          yes"
 echo "  Extra Stereo:                           yes"
-echo "  LADSPA Host:                            yes"
+echo "  LADSPA Host:                            $enable_ladspa"
 echo "  Voice Removal:                          yes"
 echo "  Bauer stereophonic-to-binaural (bs2b):  $have_bs2b"
 echo "  Sample Rate Converter (resample):       $have_resample"
+echo "  Silence Removal:                        yes"
 echo "  Speed and Pitch:                        $have_speedpitch"
 echo "  SoX Resampler:                          $have_soxr"
 echo
 echo "  Visualization"
 echo "  -------------"
-echo "  Blur Scope:                             yes"
-echo "  Cairo Spectrum Analyzer:                yes"
-echo "  OpenGL Spectrum Analyzer:               $have_glspectrum"
+echo "  Blur Scope:                             $enable_blur_scope"
+echo "  Cairo Spectrum Analyzer:                $enable_cairo_spectrum"
+echo "  GTK+ OpenGL Spectrum Analyzer:          $have_glspectrum"
+echo "  Qt OpenGL Spectrum Analyzer:            $have_qtglspectrum"
 echo
 echo "  Transport"
 echo "  ---------"
-echo "  neon-based http/https:                  $have_neon"
+echo "  neon-based http/https:                  $enable_neon"
 echo "  libmms-based mms:                       $have_mms"
 echo "  GIO:                                    yes"
 echo
@@ -13821,6 +15627,7 @@ echo "  CUE playlist format (cue):              $have_cue"
 echo
 echo "  Interfaces"
 echo "  ----------"
-echo "  GTK (gtkui):                            $enable_gtkui"
-echo "  Winamp Classic (skins):                 $enable_skins"
+echo "  GTK (gtkui):                            $USE_GTK"
+echo "  Qt (qtui):                              $USE_QT"
+echo "  Winamp Classic (skins):                 $USE_GTK"
 echo
diff --git a/configure.ac b/configure.ac
index e750ca215c72..ce53000f856a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,8 +5,8 @@ dnl ***
 dnl Initialize
 dnl ==========
 AC_PREREQ([2.59])
-AC_INIT([audacious-plugins], [3.5])
-AC_COPYRIGHT([(C) 2005-2014 Audacious Team])
+AC_INIT([audacious-plugins], [3.6.1])
+AC_COPYRIGHT([Copyright (C) 2001-2015 Audacious developers and others])
 
 AC_DEFINE_UNQUOTED([PACKAGE], "$PACKAGE_NAME", [Name of package])
 AC_DEFINE_UNQUOTED([VERSION], "$PACKAGE_VERSION", [Version number of package])
@@ -19,10 +19,6 @@ AUD_COMMON_PROGS
 
 BUILDSYS_SHARED_LIB
 
-dnl Headers and functions
-dnl =====================
-AC_CHECK_FUNCS([mkdtemp])
-
 dnl gettext
 dnl =======
 AM_GNU_GETTEXT([external])
@@ -35,9 +31,9 @@ LIBS="$LIBS $LIBINTL"
 dnl Check for Audacious
 dnl ===================
 
-PKG_CHECK_MODULES(AUDACIOUS, [audacious >= 3.5],
+PKG_CHECK_MODULES(AUDACIOUS, [audacious >= 3.6],
     [],
-    [AC_MSG_ERROR([Cannot find Audacious 3.5; have you installed Audacious yet?])]
+    [AC_MSG_ERROR([Cannot find Audacious 3.6; have you installed Audacious yet?])]
 )
 
 CPPFLAGS="$CPPFLAGS $AUDACIOUS_CFLAGS"
@@ -46,19 +42,45 @@ LIBS="$LIBS $AUDACIOUS_LIBS"
 dnl Check for libxml2 (required to load XSPF playlists from previous versions)
 dnl ==========================================================================
 
-PKG_CHECK_MODULES([XML], [libxml-2.0])
+if test $HAVE_DARWIN = yes ; then
+    AC_ARG_WITH([system-libxml2],
+     [AS_HELP_STRING([--with-system-libxml2=yes,no], [Use system version of libxml2 (default=yes)])],
+     [with_system_libxml2=$withval],
+     [with_system_libxml2=yes])
+
+    if test $with_system_libxml2 = yes ; then
+        XML_LIBS="-lxml2"
+        XML_CFLAGS="-I/usr/include/libxml2"
+        AC_SUBST(XML_LIBS)
+        AC_SUBST(XML_CFLAGS)
+    else
+        PKG_CHECK_MODULES([XML], [libxml-2.0])
+    fi
+else
+    PKG_CHECK_MODULES([XML], [libxml-2.0])
+fi
 
 dnl Default Set of Plugins
 dnl ======================
 
-INPUT_PLUGINS="tonegen metronom vtx"
+INPUT_PLUGINS="tonegen metronom"
 OUTPUT_PLUGINS=""
-EFFECT_PLUGINS="compressor crossfade crystalizer ladspa mixer stereo_plugin voice_removal echo_plugin"
-GENERAL_PLUGINS="alarm albumart delete-files search-tool"
-VISUALIZATION_PLUGINS="blur_scope cairo-spectrum"
+EFFECT_PLUGINS="compressor crossfade crystalizer mixer silence-removal stereo_plugin voice_removal echo_plugin"
+GENERAL_PLUGINS=""
+VISUALIZATION_PLUGINS=""
 CONTAINER_PLUGINS="asx asx3 audpl m3u pls xspf"
 TRANSPORT_PLUGINS="gio"
 
+if test "x$USE_GTK" = "xyes" ; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS alarm albumart delete-files playlist-manager search-tool statusicon"
+    GENERAL_PLUGINS="$GENERAL_PLUGINS gtkui skins"
+fi
+
+if test "x$USE_QT" = "xyes" ; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS albumart-qt lyricwiki-qt song-info-qt"
+    GENERAL_PLUGINS="$GENERAL_PLUGINS qtui"
+fi
+
 dnl Console
 dnl =======
 
@@ -88,6 +110,43 @@ if test "x$enable_xsf" != "xno"; then
     INPUT_PLUGINS="$INPUT_PLUGINS xsf"
 fi
 
+dnl QtAudio
+dnl =======
+
+AC_ARG_ENABLE(qtaudio,
+    [AS_HELP_STRING([--disable-qtaudio], [disable QtMultimedia output plugin (default=enabled)])],
+    [enable_qtaudio=$enableval],
+    [enable_qtaudio=auto])
+
+have_qtaudio=no
+if test "x$enable_qtaudio" = "xyes" -o \( "x$USE_QT" = "xyes" -a "x$enable_qtaudio" = "xauto" \); then
+    PKG_CHECK_MODULES(QTMULTIMEDIA, [Qt5Multimedia], [have_qtaudio=yes], [have_qtaudio=no])
+    if test "x$have_qtaudio" = "xyes"; then
+        QTMULTIMEDIA_CFLAGS="$QTMULTIMEDIA_CFLAGS -fPIC"
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS qtaudio"
+    elif test "x$enable_qtaudio" = "xyes"; then
+        AC_MSG_ERROR([QtAudio output plugin requested but QtMultimedia not found!])
+    fi
+fi
+
+dnl CoreAudio
+dnl =========
+
+AC_ARG_ENABLE(coreaudio,
+    [AS_HELP_STRING([--disable-coreaudio], [disable CoreAudio output plugin (default=enabled)])],
+    [enable_coreaudio=$enableval],
+    [enable_coreaudio=auto]
+)
+
+have_coreaudio=no
+if test "x$enable_coreaudio" != "xno"; then
+    if test "x$HAVE_DARWIN" != "xno"; then
+        have_coreaudio=yes
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS coreaudio"
+    fi
+else
+    AC_MSG_RESULT([*** CoreAudio output plugin disabled per user request ***])
+fi
 
 dnl PulseAudio
 dnl ==========
@@ -123,23 +182,16 @@ if test "x$enable_psf" != "xno"; then
     INPUT_PLUGINS="$INPUT_PLUGINS psf"
 fi
 
-dnl *** MP3
+dnl MP3 (enabled by default)
+dnl ========================
 
 AC_ARG_ENABLE(mp3,
- [AS_HELP_STRING([--disable-mp3], [disable MP3 plugin (default=enabled)])],
- [enable_mp3=$enableval], [enable_mp3=auto])
-
-have_mp3=no
-if test "x$enable_mp3" != "xno"; then
-    PKG_CHECK_MODULES(MPG123, [libmpg123 >= 1.12],
-     [have_mp3=yes
-      INPUT_PLUGINS="$INPUT_PLUGINS mpg123"],
-     [if test "x$enable_mp3" = "xyes"; then
-          AC_MSG_ERROR([Cannot find libmpg123 development files (ver >= 1.12), but compilation of MP3 plugin has been explicitly requested; please install libmpg123 dev files and run configure again])
-      fi]
-    )
-else
-    AC_MSG_RESULT([*** libmpg123 not found; MP3 plugin disabled])
+ [AS_HELP_STRING([--disable-mp3], [disable MP3 support (default=enabled)])],
+ [enable_mp3=$enableval], [enable_mp3=yes])
+
+if test $enable_mp3 = yes ; then
+    PKG_CHECK_MODULES(MPG123, [libmpg123 >= 1.12])
+    INPUT_PLUGINS="$INPUT_PLUGINS mpg123"
 fi
 
 dnl *** Global Hotkey general plugin (only built on X11)
@@ -152,11 +204,11 @@ AC_ARG_ENABLE(hotkey,
 
 have_hotkey=no
 if test "x$enable_hotkey" != "xno"; then
-    PKG_CHECK_MODULES(GDKX11, [gdk-x11-3.0],
+    PKG_CHECK_MODULES(GDKX11, [gdk-x11-2.0],
         [have_hotkey="yes"
          GENERAL_PLUGINS="$GENERAL_PLUGINS hotkey"],
         [if test "x$enable_hotkey" = "xyes"; then
-            AC_MSG_ERROR([Cannot find gdk-x11-3.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-3.0 dev files and run configure again])
+            AC_MSG_ERROR([Cannot find gdk-x11-2.0 development files, but compilation of X11 Global Hotkey plugin has been explicitly requested; please install gdk-x11-2.0 dev files and run configure again])
          fi]
     )
 else
@@ -219,17 +271,6 @@ if test "x$enable_songchange" != "xno"; then
     )
 fi
 
-dnl Status Icon
-dnl ===========
-
-AC_ARG_ENABLE(statusicon,
- [AS_HELP_STRING([--disable-statusicon], [disable X11 Status Icon plugin (default=enabled)])],
- [have_statusicon=$enableval], [have_statusicon="yes"])
-
-if test "x$have_statusicon" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS statusicon"
-fi
-
 dnl *** Audacious OSD plugin (pangocairo-based)
 
 AC_ARG_ENABLE(aosd,
@@ -338,45 +379,30 @@ else
     AC_MSG_RESULT([*** AdPlug plugin disabled per user request ***])
 fi
 
-dnl Ogg Vorbis
-dnl ==========
+dnl Ogg Vorbis (enabled by default)
+dnl ===============================
+
 dnl This test is reused later to enable/disable Vorbis support in filewriter.
 
 AC_ARG_ENABLE(vorbis,
- [AS_HELP_STRING([--disable-vorbis], [disable Ogg Vorbis decoding and encoding])],
- [enable_vorbis=$enableval], [enable_vorbis=auto])
-
-have_vorbis=no
-if test "x$enable_vorbis" != "xno"; then
-    PKG_CHECK_MODULES(VORBIS, [ogg >= 1.0 vorbis >= 1.0 vorbisenc >= 1.0 vorbisfile >= 1.0],
-        [have_vorbis=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS vorbis"],
-        [if test "x$enable_vorbis" = "xyes"; then
-            AC_MSG_ERROR([Cannot find ogg, vorbis, vorbisenc or vorbisfile development files (ver >= 1.0), but compilation of Ogg Vorbis decoding and encoding has been explicitly requested; please install ogg, vorbis, vorbisenc and vorbisfile dev files and run configure again])
-         fi]
-    )
+ [AS_HELP_STRING([--disable-vorbis], [disable Ogg Vorbis support (default=enabled)])],
+ [enable_vorbis=$enableval], [enable_vorbis=yes])
+
+if test $enable_vorbis = yes ; then
+    PKG_CHECK_MODULES(VORBIS, [ogg >= 1.0 vorbis >= 1.0 vorbisenc >= 1.0 vorbisfile >= 1.0])
+    INPUT_PLUGINS="$INPUT_PLUGINS vorbis"
 fi
 
-dnl FLAC
-dnl ====
+dnl FLAC (enabled by default)
+dnl =========================
 
 AC_ARG_ENABLE(flacng,
-    [AS_HELP_STRING([--disable-flacng], [disable flac input plugin (default=enabled)])],
-    [enable_flacng=$enableval],
-    [enable_flacng=auto]
-)
+ [AS_HELP_STRING([--disable-flacng], [disable FLAC support (default=enabled)])],
+ [enable_flacng=$enableval], [enable_flacng=yes])
 
-have_flacng=no
-if test "x$enable_flacng" != "xno"; then
-    PKG_CHECK_MODULES(LIBFLAC, [flac >= 1.2.1],
-        [have_flacng=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS flacng"],
-        [if test "x$enable_flacng" = "xyes"; then
-            AC_MSG_ERROR([Cannot find libFLAC development files (ver >= 1.2.1), but compilation of FLACng plugin has been explicitly requested; please install libFLAC dev files and run configure again])
-         fi]
-    )
-else
-    AC_MSG_RESULT([*** FLACng plugin disabled per user request ***])
+if test $enable_flacng = yes ; then
+    PKG_CHECK_MODULES(LIBFLAC, [flac >= 1.2.1])
+    INPUT_PLUGINS="$INPUT_PLUGINS flacng"
 fi
 
 dnl *** WavPack 4.31 support
@@ -400,34 +426,27 @@ else
     AC_MSG_RESULT([*** WavPack plugin disabled per user request ***])
 fi
 
-dnl *** AAC
+dnl AAC (enabled by default)
+dnl ========================
 
 AC_ARG_ENABLE(aac,
-    [AS_HELP_STRING([--disable-aac], [disable aac plugin (default=enabled)])],
-    [enable_aac=$enableval],
-    [enable_aac=auto]
-)
+ [AS_HELP_STRING([--disable-aac], [disable AAC support (default=enabled)])],
+ [enable_aac=$enableval], [enable_aac=yes])
 
-have_aac=no
-if test "x$enable_aac" != "xno"; then
-    FAAD_LIBS="-lfaad"
-    FAAD_CFLAGS=
-
-    AC_CHECK_HEADER([faad.h],
-        [AC_CHECK_DECL([FAAD2_VERSION],
-            [AC_CHECK_DECL([NeAACDecInit2],
-                [AC_CHECK_LIB([faad],[NeAACDecInit2],
-                    [have_aac=yes
-                     AC_SUBST(FAAD_CFLAGS)
-                     AC_SUBST(FAAD_LIBS)
-                     INPUT_PLUGINS="$INPUT_PLUGINS aac aac-raw"])],
-                [], [#include <neaacdec.h>])],
-            [], [#include <neaacdec.h>])]
-    )
+if test $enable_aac = yes ; then
+    AC_CHECK_HEADER([neaacdec.h], [have_aac=yes], [have_aac=no])
+    AC_CHECK_LIB([faad], [NeAACDecInit2], [have_aac=$have_aac], [have_aac=no])
 
-    if test "x$enable_aac" = "xyes" -a "x$have_aac" != "xyes"; then
-        AC_MSG_ERROR([Cannot find faad development files, but compilation of aac plugin has been explicitly requested; please install faad dev files and run configure again])
+    if test $have_aac != yes ; then
+        AC_MSG_ERROR([Please install libfaad, or use --disable-aac to disable AAC support.])
     fi
+
+    FAAD_CFLAGS=
+    FAAD_LIBS="-lfaad"
+    AC_SUBST(FAAD_CFLAGS)
+    AC_SUBST(FAAD_LIBS)
+
+    INPUT_PLUGINS="$INPUT_PLUGINS aac-raw"
 fi
 
 dnl *** sndfile
@@ -472,21 +491,21 @@ fi
 
 dnl *** FFaudio
 
-AC_ARG_ENABLE(ffaudio,
-    [AS_HELP_STRING([--disable-ffaudio], [disable ffaudio plugin (default=enabled)])],
-    [enable_ffaudio=$enableval],
-    [enable_ffaudio=auto]
-)
-
-have_ffaudio=no
-if test "x$enable_ffaudio" != "xno"; then
-    PKG_CHECK_MODULES([FFMPEG], [libavcodec >= 53.40.0 libavformat >= 53.5.0 libavutil >= 50.42.0],
-        [have_ffaudio=yes
-         INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"],
-        [if test "x$enable_ffaudio" = "xyes"; then
-            AC_MSG_ERROR([Cannot find FFmpeg development files (libavcodec ver >= 53.40.0, libavformat ver >= 53.5.0, libavutil ver >= 50.42.0), but compilation of ffaudio plugin has been explicitly requested; please install FFmpeg dev files and run configure again])
-         fi]
-    )
+AC_ARG_WITH([ffmpeg],
+ AS_HELP_STRING([--with-ffmpeg=ffmpeg,libav,none], [choose between FFmpeg, libav, or neither (default=ffmpeg)]),
+ [ffmpeg_variant=$withval],
+ [ffmpeg_variant=ffmpeg])
+
+if test $ffmpeg_variant = ffmpeg ; then
+    PKG_CHECK_MODULES([FFMPEG], [libavcodec >= 53.40.0 libavformat >= 53.21.0 libavutil >= 51.27.0],
+     [INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"
+      AC_DEFINE([HAVE_FFMPEG], [1], [Define if using FFmpeg])],
+     [AC_MSG_ERROR([FFmpeg is not installed or too old (required: libavcodec 53.40.0, libavformat 53.21.0, libavutil 51.27.0).  Use --with-ffmpeg=none to disable the ffaudio plugin or --with-ffmpeg=libav to use libav instead.])])
+elif test $ffmpeg_variant = libav ; then
+    PKG_CHECK_MODULES([FFMPEG], [libavcodec >= 53.25.0 libavformat >= 53.15.0 libavutil >= 51.18.0],
+     [INPUT_PLUGINS="$INPUT_PLUGINS ffaudio"
+      AC_DEFINE([HAVE_LIBAV], [1], [Define if using libav])],
+     [AC_MSG_ERROR([libav is not installed or too old (required: libavcodec 53.25.0, libavformat 53.15.0, libavutil 51.18.0).])])
 fi
 
 dnl *** jack output plugin
@@ -505,15 +524,9 @@ if test "x$enable_jack" != "xno"; then
     )
 
     if test "x$have_jack" = "xyes"; then
-        PKG_CHECK_MODULES([SAMPLERATE], [samplerate],
-            [], [have_jack=no]
-        )
-    fi
-
-    if test "x$have_jack" = "xyes"; then
-        OUTPUT_PLUGINS="$OUTPUT_PLUGINS jack"
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS jack-ng"
     elif test "x$enable_jack" = "xyes"; then
-        AC_MSG_ERROR([Cannot find JACK (ver >= 0.120.1 but < 1.0 or >= 1.9.7) or libsamplerate development files, but compilation of JACK output plugin has been explicitly requested; please install JACK and libsamplerate dev files and run configure again])
+        AC_MSG_ERROR([Cannot find JACK (ver >= 0.120.1 but < 1.0 or >= 1.9.7) development files, but compilation of JACK output plugin has been explicitly requested; please install JACK dev files and run configure again])
     fi
 fi
 
@@ -539,7 +552,7 @@ dnl OSS output
 dnl ==========
 
 AC_ARG_ENABLE(oss4,
- [AS_HELP_STRING([--disable-oss4],[disable OSS4 output plugin])],
+ [AS_HELP_STRING([--disable-oss4], [disable OSS4 output plugin])],
  [enable_oss4=$enableval], [enable_oss4=auto])
 
 OSS_CFLAGS=
@@ -552,28 +565,17 @@ if test "x$enable_oss4" != "xno" ; then
 
     OLD_CPPFLAGS="$CPPFLAGS"
     CPPFLAGS="$CPPFLAGS $OSS_CFLAGS"
-    AC_CHECK_HEADERS([sys/soundcard.h soundcard.h])
-    AC_MSG_CHECKING(for OSS4)
-
-    AC_EGREP_CPP(yes,
-     [#ifdef HAVE_SYS_SOUNDCARD_H
-      #include <sys/soundcard.h>
-      #elif defined HAVE_SOUNDCARD_H
-      #include <soundcard.h>
-      #endif
-      #if OSS_VERSION >= 0x40000 || SOUND_VERSION >= 0x40000
-          yes
-      #endif],
-     [have_oss4=yes
-      OUTPUT_PLUGINS="$OUTPUT_PLUGINS oss4"
-      AC_SUBST(OSS_CFLAGS)],
-     [if test "x$enable_oss4" = "xyes"; then
-        AC_MSG_ERROR([Cannot find OSS4 development files, but compilation of OSS4 output plugin has been explicitly requested; please install OSS4 dev files and run configure again])
-      fi]
-    )
+    AC_CHECK_HEADERS([sys/soundcard.h soundcard.h], [have_oss4=yes])
+    CPPFLAGS="$OLD_CPPFLAGS"
+
+    if test "x$have_oss4" = "xyes" ; then
+        OUTPUT_PLUGINS="$OUTPUT_PLUGINS oss4"
+        AC_SUBST(OSS_CFLAGS)
+    elif test "x$enable_oss4" = "xyes" ; then
+        AC_MSG_ERROR([OSS4 output was enabled but soundcard.h was not found])
+    fi
 
     AC_MSG_RESULT([$have_oss4])
-    CPPFLAGS="$OLD_CPPFLAGS"
 fi
 
 dnl *** ALSA output plugin
@@ -603,17 +605,47 @@ AC_ARG_ENABLE(sdlout,
  [AS_HELP_STRING([--disable-sdlout], [disable SDL output plugin])],
  [enable_sdlout=$enableval], [enable_sdlout=auto])
 
+if test "x$enable_sdlout" != "xno"; then
+    AC_ARG_WITH(libsdl,
+                [AS_HELP_STRING([--with-libsdl=VER], [select which SDL version to use. Set VER to 1 for libsdl1, to 2 for libsdl2. @<:@default=check@:>@])],
+                [case "x$withval" in
+                     x1) ;;
+                     x2) ;;
+                     x*) withval=check;;
+                 esac
+                 with_libsdl=$withval], [with_libsdl=check])
+fi
+
+libsdl1_min="1.2.11";
+libsdl2_min="2.0";
+
 have_sdlout=no
 if test "x$enable_sdlout" != "xno"; then
-    PKG_CHECK_MODULES([SDL], [sdl2 >= 2.0],
-       [have_sdlout=yes
-        OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"],
-       [PKG_CHECK_MODULES([SDL], [sdl >= 1.2.11],
+    if test "x$with_libsdl" = "xcheck"; then
+        PKG_CHECK_MODULES([SDL], [sdl2 >= $libsdl2_min],
            [have_sdlout=yes
             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"],
-           [if test "x$enable_sdlout" = "xyes"; then
-               AC_MSG_ERROR([Cannot find SDL development files (ver >= 1.2.11), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again])
-            fi])])
+           [PKG_CHECK_MODULES([SDL], [sdl >= $libsdl1_min],
+               [have_sdlout=yes
+                OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"],
+               [if test "x$enable_sdlout" = "xyes"; then
+                   AC_MSG_ERROR([Cannot find SDL development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL dev files and run configure again])
+                fi])])
+    elif test "x$with_libsdl" = "x1"; then
+        PKG_CHECK_MODULES([SDL], [sdl >= $libsdl1_min],
+            [have_sdlout=yes
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"],
+            [if test "x$enable_sdlout" = "xyes"; then
+                 AC_MSG_ERROR([Cannot find SDL1 development files (ver >= $libsdl1_min), but compilation of SDL output plugin has been explicitly requested; please install SDL1 dev files and run configure again])
+             fi])
+    elif test "x$with_libsdl" = "x2"; then
+        PKG_CHECK_MODULES([SDL], [sdl2 >= $libsdl2_min],
+            [have_sdlout=yes
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sdlout"],
+            [if test "x$enable_sdlout" = "xyes"; then
+                 AC_MSG_ERROR([Cannot find SDL2 development files (ver >= $libsdl2_min), but compilation of SDL output plugin has been explicitly requested; please install SDL2 dev files and run configure again])
+             fi])
+    fi
 fi
 
 dnl *** sndio output
@@ -629,7 +661,7 @@ if test "x$enable_sndio" != "xno"; then
     AC_CHECK_HEADER([sndio.h],
         [AC_CHECK_LIB([sndio], [sio_open],
             [have_sndio=yes
-             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sndio"
+             OUTPUT_PLUGINS="$OUTPUT_PLUGINS sndio-ng"
              SNDIO_LIBS="-lsndio"
              AC_SUBST(SNDIO_LIBS)]
          )]
@@ -640,6 +672,13 @@ if test "x$enable_sndio" != "xno"; then
     fi
 fi
 
+dnl Check for at least one output plugin (not including filewriter)
+dnl ===============================================================
+
+if test "x$OUTPUT_PLUGINS" = "x" ; then
+    AC_MSG_ERROR([No output plugin was enabled.  Please install the necessary packages for your system and run configure again.])
+fi
+
 dnl amidi-plug
 dnl ==========
 
@@ -651,7 +690,7 @@ have_amidiplug=no
 if test "x$enable_amidiplug" != "xno"; then
     PKG_CHECK_MODULES(FLUIDSYNTH, [fluidsynth >= 1.0.6],
         [have_amidiplug=yes
-         OUTPUT_PLUGINS="$OUTPUT_PLUGINS amidi-plug"],
+         INPUT_PLUGINS="$INPUT_PLUGINS amidi-plug"],
         [if test "x$enable_amidiplug" = "xyes"; then
             AC_MSG_ERROR([Cannot find FluidSynth development files (ver >= 1.0.6), but compilation of amidi-plug input plugin has been explicitly requested; please install FluidSynth dev files and run configure again])
          fi])
@@ -706,25 +745,16 @@ if test "x$enable_scrobbler2" != "xno"; then
     )
 fi
 
-dnl *** neon http plugin ***
+dnl neon HTTP support (enabled by default)
+dnl ======================================
 
 AC_ARG_ENABLE(neon,
-[AS_HELP_STRING([--disable-neon], [disable neon HTTP support (default=enabled)])],
-[enable_neon=$enableval],
-[enable_neon=auto])
-
-have_neon=no
-if test "x$enable_neon" != "xno"; then
-    PKG_CHECK_MODULES(NEON, [neon >= 0.26],
-        [have_neon=yes
-         TRANSPORT_PLUGINS="$TRANSPORT_PLUGINS neon"
-         AC_CHECK_LIB([neon], [ne_set_connect_timeout], [AC_DEFINE(HAVE_NE_SET_CONNECT_TIMEOUT, 1, [Whether we have ne_set_connect_timeout])], [], [$NEON_LIBS])
-         AC_SUBST([NEON_LIBS])
-         AC_SUBST([NEON_CFLAGS])],
-        [if test "x$enable_neon" = "xyes"; then
-            AC_MSG_ERROR([Cannot find neon development files (ver >= 0.26), but compilation of neon HTTP support has been explicitly requested; please install neon dev files and run configure again])
-         fi]
-    )
+ [AS_HELP_STRING([--disable-neon], [disable neon HTTP support (default=enabled)])],
+ [enable_neon=$enableval], [enable_neon=yes])
+
+if test $enable_neon = yes ; then
+    PKG_CHECK_MODULES(NEON, [neon >= 0.27])
+    TRANSPORT_PLUGINS="$TRANSPORT_PLUGINS neon"
 fi
 
 dnl MMS
@@ -806,7 +836,7 @@ fi
 dnl Vorbis support reuses test done for Vorbis input plugin.
 
 have_vorbisenc=no
-if test "x$have_filewriter" = "xyes" -a "x$have_vorbis" = "xyes"; then
+if test "x$have_filewriter" = "xyes" -a "x$enable_vorbis" = "xyes"; then
     have_vorbisenc=yes
     AC_DEFINE(FILEWRITER_VORBIS, 1, [Define if Vorbis output part should be built])
     FILEWRITER_CFLAGS="$FILEWRITER_CFLAGS $VORBIS_CFLAGS"
@@ -909,28 +939,6 @@ if test "x$enable_soxr" != "xno"; then
     )
 fi
 
-dnl GTK Interface
-dnl =============
-
-AC_ARG_ENABLE(gtkui,
- [AS_HELP_STRING([--disable-gtkui], [disable GTK interface (gtkui)])],
- [enable_gtkui=$enableval], [enable_gtkui="yes"])
-
-if test "x$enable_gtkui" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS gtkui"
-fi
-
-dnl Winamp Classic Interface
-dnl =============
-
-AC_ARG_ENABLE(skins,
- [AS_HELP_STRING([--disable-skins], [disable Winamp Classic interface (skins)])],
- [enable_skins=$enableval], [enable_skins="yes"])
-
-if test "x$enable_skins" != "xno"; then
-    GENERAL_PLUGINS="$GENERAL_PLUGINS skins"
-fi
-
 dnl LyricWiki
 dnl =========
 
@@ -980,6 +988,83 @@ fi
 
 AC_SUBST(GL_LIBS)
 
+dnl Qt OpenGL Spectrum Analyzer
+dnl ===========================
+
+AC_ARG_ENABLE(qtglspectrum,
+    [AS_HELP_STRING([--disable-qtglspectrum], [disable Qt OpenGL Spectrum Analyzer (default=enabled)])],
+    [enable_qtglspectrum=$enableval],
+    [enable_qtglspectrum=auto])
+
+have_qtglspectrum=no
+if test "x$USE_QT" = "xno" -a "x$enable_qtglspectrum" = "xyes"; then
+    AC_MSG_ERROR([--enable-qtglspectrum cannot be used without --enable-qt])
+fi
+if test "x$USE_QT" = "xyes" -a "x$enable_qtglspectrum" != "xno"; then
+    PKG_CHECK_MODULES(QTOPENGL, [Qt5OpenGL], [have_qtglspectrum=yes], [have_qtglspectrum=no])
+    if test "x$have_qtglspectrum" = "xyes"; then
+        QTOPENGL_CFLAGS="$QTOPENGL_CFLAGS -fPIC"
+        VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS gl-spectrum-qt"
+    elif test "x$enable_qtglspectrum" = "xyes"; then
+        AC_MSG_ERROR([Qt OpenGL Spectrum Analyzer plugin requested but QtOpenGL not found!])
+    fi
+fi
+
+dnl VTX Decoder
+dnl =============
+
+AC_ARG_ENABLE(vtx,
+ [AS_HELP_STRING([--disable-vtx], [disable VTX Decoder])],
+ [enable_vtx=$enableval], [enable_vtx="yes"])
+
+if test "x$enable_vtx" != "xno"; then
+    INPUT_PLUGINS="$INPUT_PLUGINS vtx"
+fi
+
+dnl LADSPA Host
+dnl =============
+
+AC_ARG_ENABLE(ladspa,
+ [AS_HELP_STRING([--disable-ladspa], [disable LADSPA Host])],
+ [enable_ladspa=$enableval], [enable_ladspa="yes"])
+
+if test "x$enable_ladspa" != "xno"; then
+    EFFECT_PLUGINS="$EFFECT_PLUGINS ladspa"
+fi
+
+dnl Blur Scope
+dnl =============
+
+AC_ARG_ENABLE(blur_scope,
+ [AS_HELP_STRING([--disable-blur-scope], [disable Blur Scope])],
+ [enable_blur_scope=$enableval], [enable_blur_scope="yes"])
+
+if test "x$enable_blur_scope" != "xno"; then
+    VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS blur_scope"
+fi
+
+dnl Cairo Spectrum Analyzer
+dnl =============
+
+AC_ARG_ENABLE(cairo_spectrum,
+ [AS_HELP_STRING([--disable-cairo-spectrum], [disable Cairo Spectrum Analyzer])],
+ [enable_cairo_spectrum=$enableval], [enable_cairo_spectrum="yes"])
+
+if test "x$enable_cairo_spectrum" != "xno"; then
+    VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS cairo-spectrum"
+fi
+
+dnl Mac Media Keys
+dnl ============
+
+AC_ARG_ENABLE(mac_media_keys,
+ [AS_HELP_STRING([--enable-mac-media-keys], [enable Mac Media Keys])],
+ [enable_mac_media_keys=$enableval], [enable_mac_media_keys="no"])
+
+if test "x$enable_mac_media_keys" != "xno"; then
+    GENERAL_PLUGINS="$GENERAL_PLUGINS mac-media-keys"
+fi
+
 dnl *** End of all plugin checks ***
 
 plugindir=`pkg-config audacious --variable=plugin_dir`
@@ -1044,9 +1129,11 @@ echo "  --------------"
 echo "  Open Sound System (oss4):               $have_oss4"
 echo "  Advanced Linux Sound Arch. (alsa):      $have_alsa"
 echo "  Sndio (sndio):                          $have_sndio"
+echo "  CoreAudio (coreaudio):                  $have_coreaudio"
 echo "  PulseAudio (pulse):                     $have_pulse"
 echo "  Jack Audio Connection Kit (jack):       $have_jack"
 echo "  Simple DirectMedia Layer (sdlout):      $have_sdlout"
+echo "  Qt Multimedia (qtaudio):                $have_qtaudio"
 echo "  FileWriter:                             $have_filewriter"
 echo "    -> FileWriter MP3 output part:        $have_lame"
 echo "    -> FileWriter Vorbis output part:     $have_vorbisenc"
@@ -1054,16 +1141,16 @@ echo "    -> FileWriter FLAC output part:       $have_writer_flac"
 echo
 echo "  Input Plugins"
 echo "  -------------"
-echo "  MPEG-1 Layer I/II/III (mpg123):         $have_mp3"
-echo "  MPEG-2/4 AAC (aac):                     $have_aac"
-echo "  FFaudio (ffaudio):                      $have_ffaudio"
+echo "  MPEG-1 Layer I/II/III (mpg123):         $enable_mp3"
+echo "  MPEG-2/4 AAC (aac):                     $enable_aac"
+echo "  FFaudio (ffaudio):                      $ffmpeg_variant"
 echo "  Module decoder (modplug):               $have_modplug"
 echo "  MIDI synthesizer (amidi-plug):          $have_amidiplug"
 echo "  CD Digital Audio (cdaudio_ng):          $have_cdaudio_ng"
 echo "  sndfile extensions:                     $have_sndfile"
 echo "  Tone Generator:                         yes"
-echo "  Ogg Vorbis (vorbis):                    $have_vorbis"
-echo "  Free Lossless Audio Codec (flacng):     $have_flacng"
+echo "  Ogg Vorbis (vorbis):                    $enable_vorbis"
+echo "  Free Lossless Audio Codec (flacng):     $enable_flacng"
 echo "  Commodore 64 audio (SID):               $have_sidplay"
 echo "  Game music (spc, nsf & gbs):            $have_console"
 echo "  PlayStation (psf/psf2) audio:           $enable_psf"
@@ -1071,17 +1158,19 @@ echo "  Nintendo DS audio (xsf):                $enable_xsf"
 echo "  AdLib synthesizer (adplug):             $have_adplug"
 echo "  WavPack 4.31+ (wavpack):                $have_wavpack"
 echo "  Metronom:                               yes"
+echo "  VTX Decoder:                            $enable_vtx"
 echo
 echo "  General"
 echo "  -------"
-echo "  Alarm:                                  yes"
-echo "  Album Art:                              yes"
-echo "  Delete from Filesystem:                 yes"
+echo "  Alarm:                                  $USE_GTK"
+echo "  Album Art:                              $USE_GTK"
+echo "  Delete from Filesystem:                 $USE_GTK"
 echo "  Linux Infrared Remote Control (LIRC)    $have_lirc"
 echo "  MPRIS 2 Server:                         $have_mpris2"
-echo "  Search Tool:                            yes"
+echo "  Playlist Manager:                       $USE_GTK"
+echo "  Search Tool:                            $USE_GTK"
 echo "  Song Change:                            $have_songchange"
-echo "  Status Icon:                            $have_statusicon"
+echo "  Status Icon:                            $USE_GTK"
 echo "  Audacious OSD:                          $have_aosd"
 echo "    -> X Composite support:               $have_aosd_xcomp"
 echo "  libnotify OSD:                          $have_notify"
@@ -1089,6 +1178,7 @@ echo "  Global Hotkey Plugin:                   $have_hotkey"
 echo "  Gnome Shortcuts Plugin:                 $have_gnomeshortcuts"
 echo "  Scrobbler 2.0:                          $have_scrobbler2"
 echo "  LyricWiki viewer:                       $have_lyricwiki"
+echo "  Mac Media Keys:                         $enable_mac_media_keys"
 echo
 echo "  Effect"
 echo "  ------"
@@ -1097,22 +1187,24 @@ echo "  Crystalizer:                            yes"
 echo "  Dynamic Range Compressor:               yes"
 echo "  Echo/Surround:                          yes"
 echo "  Extra Stereo:                           yes"
-echo "  LADSPA Host:                            yes"
+echo "  LADSPA Host:                            $enable_ladspa"
 echo "  Voice Removal:                          yes"
 echo "  Bauer stereophonic-to-binaural (bs2b):  $have_bs2b"
 echo "  Sample Rate Converter (resample):       $have_resample"
+echo "  Silence Removal:                        yes"
 echo "  Speed and Pitch:                        $have_speedpitch"
 echo "  SoX Resampler:                          $have_soxr"
 echo
 echo "  Visualization"
 echo "  -------------"
-echo "  Blur Scope:                             yes"
-echo "  Cairo Spectrum Analyzer:                yes"
-echo "  OpenGL Spectrum Analyzer:               $have_glspectrum"
+echo "  Blur Scope:                             $enable_blur_scope"
+echo "  Cairo Spectrum Analyzer:                $enable_cairo_spectrum"
+echo "  GTK+ OpenGL Spectrum Analyzer:          $have_glspectrum"
+echo "  Qt OpenGL Spectrum Analyzer:            $have_qtglspectrum"
 echo
 echo "  Transport"
 echo "  ---------"
-echo "  neon-based http/https:                  $have_neon"
+echo "  neon-based http/https:                  $enable_neon"
 echo "  libmms-based mms:                       $have_mms"
 echo "  GIO:                                    yes"
 echo
@@ -1128,6 +1220,7 @@ echo "  CUE playlist format (cue):              $have_cue"
 echo
 echo "  Interfaces"
 echo "  ----------"
-echo "  GTK (gtkui):                            $enable_gtkui"
-echo "  Winamp Classic (skins):                 $enable_skins"
+echo "  GTK (gtkui):                            $USE_GTK"
+echo "  Qt (qtui):                              $USE_QT"
+echo "  Winamp Classic (skins):                 $USE_GTK"
 echo
diff --git a/debian/changelog b/debian/changelog
index f9fc1f5689ef..9d877c7f462b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+audacious-plugins (3.6.1-0.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream version.
+
+ -- Julian Wollrath <jwollrath at web.de>  Sun, 03 May 2015 13:00:41 +0200
+
 audacious-plugins (3.5-1) unstable; urgency=low
 
   [ Alin Andrei ]
diff --git a/extra.mk.in b/extra.mk.in
index 3beebf95be79..7c2ec0cdfe84 100644
--- a/extra.mk.in
+++ b/extra.mk.in
@@ -16,6 +16,9 @@ TRANSPORT_PLUGINS ?= @TRANSPORT_PLUGINS@
 VISUALIZATION_PLUGINS ?= @VISUALIZATION_PLUGINS@
 VISUALIZATION_PLUGIN_DIR ?= @VISUALIZATION_PLUGIN_DIR@
 
+USE_GTK ?= @USE_GTK@
+USE_QT ?= @USE_QT@
+
 ALSA_CFLAGS ?= @ALSA_CFLAGS@
 ALSA_LIBS ?= @ALSA_LIBS@
 BINIO_CFLAGS ?= @BINIO_CFLAGS@
@@ -75,6 +78,12 @@ SIDPLAYFP_LIBS ?= @SIDPLAYFP_LIBS@
 SNDFILE_CFLAGS ?= @SNDFILE_CFLAGS@
 SNDFILE_LIBS ?= @SNDFILE_LIBS@
 SNDIO_LIBS ?= @SNDIO_LIBS@
+QT_CFLAGS ?= @QT_CFLAGS@
+QT_LIBS ?= @QT_LIBS@
+QTMULTIMEDIA_CFLAGS ?= @QTMULTIMEDIA_CFLAGS@
+QTMULTIMEDIA_LIBS ?= @QTMULTIMEDIA_LIBS@
+QTOPENGL_CFLAGS ?= @QTOPENGL_CFLAGS@
+QTOPENGL_LIBS ?= @QTOPENGL_LIBS@
 VORBIS_CFLAGS ?= @VORBIS_CFLAGS@
 VORBIS_LIBS ?= @VORBIS_LIBS@
 WAVPACK_CFLAGS ?= @WAVPACK_CFLAGS@
@@ -85,3 +94,7 @@ XML_CFLAGS ?= @XML_CFLAGS@
 XML_LIBS ?= @XML_LIBS@
 XRENDER_CFLAGS ?= @XRENDER_CFLAGS@
 XRENDER_LIBS ?= @XRENDER_LIBS@
+
+HAVE_LINUX ?= @HAVE_LINUX@
+HAVE_MSWINDOWS ?= @HAVE_MSWINDOWS@
+HAVE_DARWIN ?= @HAVE_DARWIN@
diff --git a/m4/buildsys.m4 b/m4/buildsys.m4
index 6afd8c6a0fdb..6a9af41c3b6a 100644
--- a/m4/buildsys.m4
+++ b/m4/buildsys.m4
@@ -108,15 +108,15 @@ AC_DEFUN([BUILDSYS_SHARED_LIB], [
 	case "$host_os" in
 		darwin*)
 			AC_MSG_RESULT(Darwin)
-			LIB_CFLAGS='-fPIC -DPIC'
-			LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}'
+			LIB_CFLAGS='-fPIC -DPIC -mmacosx-version-min=10.7'
+			LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR} -mmacosx-version-min=10.7 -install_name "${libdir}/$$(i=${SHARED_LIB}; echo $${i%${LIB_SUFFIX}}).${LIB_MAJOR}${LIB_SUFFIX}"'
 			LIB_PREFIX='lib'
 			LIB_SUFFIX='.dylib'
 			LDFLAGS_RPATH='-Wl,-rpath,${libdir}'
-			PLUGIN_CFLAGS='-fPIC -DPIC'
-			PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup'
+			PLUGIN_CFLAGS='-fPIC -DPIC -mmacosx-version-min=10.7'
+			PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup -mmacosx-version-min=10.7'
 			PLUGIN_SUFFIX='.bundle'
-			INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && install_name_tool -id ${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
+			INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i'
 			UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib'
 			CLEAN_LIB=''
 			;;
diff --git a/po/Makefile b/po/Makefile
index 203b04d40a4b..6c827daa4d58 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -34,6 +34,8 @@ LOCALES = be.po \
 	  lt.po \
 	  lv.po \
 	  ml_IN.po \
+	  ms.po \
+	  nl.po \
 	  pl.po \
 	  pt_BR.po \
 	  pt_PT.po \
@@ -42,6 +44,7 @@ LOCALES = be.po \
 	  sk.po \
 	  sr.po \
 	  sr_RS.po \
+	  sv.po \
 	  ta.po \
 	  tr.po \
 	  uk.po \
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2028d6e614da..65eb00da6c6a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,129 +1,180 @@
 # Please don't update this file manually - use ./update-potfiles.sh instead!
-src/aac/libmp4.c
-src/aac-raw/aac.c
+src/aac-raw/aac.cc
 src/adplug/adplug-xmms.cc
-src/adplug/plugin.c
-src/alarm/alarm.c
-src/alarm/interface.c
-src/albumart/albumart.c
-src/alsa/config.c
-src/alsa/plugin.c
-src/amidi-plug/amidi-plug.c
-src/amidi-plug/i_configure.c
-src/amidi-plug/i_configure-fluidsynth.c
-src/amidi-plug/i_fileinfo.c
-src/amidi-plug/i_utils.c
-src/aosd/aosd.c
-src/aosd/aosd_style.c
-src/aosd/aosd_trigger.c
-src/aosd/aosd_ui.c
-src/asx3/asx3.c
-src/asx/asx.c
-src/audpl/audpl.c
-src/blur_scope/blur_scope.c
-src/bs2b/plugin.c
-src/cairo-spectrum/cairo-spectrum.c
-src/cdaudio-ng/cdaudio-ng.c
-src/cd-menu-items/cd-menu-items.c
-src/compressor/plugin.c
-src/console/Ay_Apu.cxx
-src/console/Ay_Emu.cxx
-src/console/Blip_Buffer.cxx
-src/console/Classic_Emu.cxx
-src/console/Data_Reader.cxx
-src/console/Dual_Resampler.cxx
-src/console/Fir_Resampler.cxx
-src/console/Gbs_Emu.cxx
-src/console/Gme_File.cxx
-src/console/Gym_Emu.cxx
-src/console/Gzip_Reader.cxx
-src/console/Hes_Emu.cxx
-src/console/Kss_Emu.cxx
-src/console/M3u_Playlist.cxx
-src/console/Multi_Buffer.cxx
-src/console/Music_Emu.cxx
-src/console/Nes_Apu.cxx
-src/console/Nsfe_Emu.cxx
-src/console/Nsf_Emu.cxx
-src/console/plugin.c
-src/console/Sap_Emu.cxx
-src/console/Spc_Cpu.cxx
-src/console/Spc_Dsp.cxx
-src/console/Spc_Emu.cxx
-src/console/Vgm_Emu.cxx
-src/console/Ym2612_Emu.cxx
-src/crossfade/crossfade.c
-src/crystalizer/crystalizer.c
-src/cue/cue.c
-src/delete-files/delete-files.c
-src/echo_plugin/echo.c
-src/ffaudio/ffaudio-core.c
-src/filewriter/filewriter.c
-src/filewriter/mp3.c
-src/filewriter/vorbis.c
-src/flacng/metadata.c
-src/flacng/plugin.c
-src/gio/gio.c
-src/gl-spectrum/gl-spectrum.c
-src/gnomeshortcuts/gnomeshortcuts.c
-src/gtkui/columns.c
-src/gtkui/layout.c
-src/gtkui/menus.c
-src/gtkui/settings.c
-src/gtkui/ui_gtk.c
-src/gtkui/ui_playlist_widget.c
-src/gtkui/ui_statusbar.c
-src/hotkey/gui.c
-src/hotkey/plugin.c
-src/jack/bio2jack.c
-src/jack/jack.c
-src/ladspa/plugin.c
-src/lirc/lirc.c
-src/lyricwiki/lyricwiki.c
-src/m3u/m3u.c
-src/metronom/metronom.c
-src/mixer/mixer.c
-src/mms/mms.c
-src/modplug/modplugbmp.cxx
-src/modplug/plugin_main.c
-src/mpg123/mpg123.c
-src/mpris2/plugin.c
-src/neon/neon.c
-src/notify/event.c
-src/notify/notify.c
-src/notify/osd.c
-src/oss4/plugin.c
-src/pls/pls.c
-src/psf/plugin.c
-src/pulse_audio/pulse_audio.c
-src/resample/resample.c
-src/scrobbler2/config_window.c
-src/scrobbler2/scrobbler.c
-src/scrobbler2/scrobbler_communication.c
-src/sdlout/plugin.c
-src/search-tool/search-tool.c
-src/skins/menus.c
-src/skins/plugin.c
-src/skins/preset-browser.c
-src/skins/preset-list.c
-src/skins/skins_cfg.c
-src/skins/ui_equalizer.c
-src/skins/ui_main.c
-src/skins/ui_main_evlisteners.c
-src/skins/ui_playlist.c
-src/skins/ui_skinselector.c
-src/skins/util.c
-src/sndfile/plugin.c
-src/sndio/sndio.c
-src/song_change/song_change.c
-src/sox-resampler/sox-resampler.c
-src/speed-pitch/speed-pitch.c
-src/statusicon/statusicon.c
-src/stereo_plugin/stereo.c
-src/tonegen/tonegen.c
-src/voice_removal/voice_removal.c
-src/vorbis/vorbis.c
-src/vtx/vtx.c
-src/wavpack/wavpack.c
-src/xsf/plugin.c
-src/xspf/xspf.c
+src/adplug/core/rix.h
+src/alarm/alarm.cc
+src/alarm/interface.cc
+src/albumart/albumart.cc
+src/albumart-qt/albumart.cc
+src/alsa/alsa.h
+src/alsa/config.cc
+src/amidi-plug/amidi-plug.cc
+src/amidi-plug/i_configure.cc
+src/amidi-plug/i_configure-fluidsynth.cc
+src/amidi-plug/i_fileinfo.cc
+src/aosd/aosd.cc
+src/aosd/aosd.h
+src/aosd/aosd_style.cc
+src/aosd/aosd_trigger.cc
+src/aosd/aosd_ui.cc
+src/asx3/asx3.cc
+src/asx/asx.cc
+src/audpl/audpl.cc
+src/blur_scope/blur_scope.cc
+src/bs2b/plugin.cc
+src/cairo-spectrum/cairo-spectrum.cc
+src/cdaudio-ng/cdaudio-ng.cc
+src/cd-menu-items/cd-menu-items.cc
+src/compressor/compressor.cc
+src/console/Ay_Apu.cc
+src/console/Ay_Apu.h
+src/console/Ay_Emu.cc
+src/console/Ay_Emu.h
+src/console/blargg_common.h
+src/console/blargg_source.h
+src/console/Blip_Buffer.cc
+src/console/Blip_Buffer.h
+src/console/Classic_Emu.cc
+src/console/Classic_Emu.h
+src/console/Data_Reader.cc
+src/console/Dual_Resampler.cc
+src/console/Dual_Resampler.h
+src/console/Fir_Resampler.cc
+src/console/Fir_Resampler.h
+src/console/gb_cpu_io.h
+src/console/Gbs_Emu.cc
+src/console/Gbs_Emu.h
+src/console/Gme_File.cc
+src/console/Gme_File.h
+src/console/Gym_Emu.cc
+src/console/Gym_Emu.h
+src/console/Gzip_Reader.cc
+src/console/Gzip_Reader.h
+src/console/hes_cpu_io.h
+src/console/Hes_Emu.cc
+src/console/Hes_Emu.h
+src/console/Kss_Emu.cc
+src/console/Kss_Emu.h
+src/console/M3u_Playlist.cc
+src/console/M3u_Playlist.h
+src/console/Multi_Buffer.cc
+src/console/Music_Emu.cc
+src/console/Music_Emu.h
+src/console/Nes_Apu.cc
+src/console/Nes_Apu.h
+src/console/Nsfe_Emu.cc
+src/console/Nsfe_Emu.h
+src/console/Nsf_Emu.cc
+src/console/Nsf_Emu.h
+src/console/plugin.cc
+src/console/plugin.h
+src/console/sap_cpu_io.h
+src/console/Sap_Emu.cc
+src/console/Sap_Emu.h
+src/console/Snes_Spc.h
+src/console/Spc_Cpu.cc
+src/console/Spc_Cpu.h
+src/console/Spc_Dsp.cc
+src/console/Spc_Emu.cc
+src/console/Spc_Emu.h
+src/console/Vgm_Emu.cc
+src/console/Vgm_Emu.h
+src/console/Ym2612_Emu.cc
+src/coreaudio/coreaudio.cc
+src/crossfade/crossfade.cc
+src/crystalizer/crystalizer.cc
+src/cue/cue.cc
+src/delete-files/delete-files.cc
+src/echo_plugin/echo.cc
+src/ffaudio/ffaudio-core.cc
+src/filewriter/filewriter.cc
+src/filewriter/mp3.cc
+src/filewriter/vorbis.cc
+src/flacng/flacng.h
+src/flacng/metadata.cc
+src/flacng/plugin.cc
+src/gio/gio.cc
+src/gl-spectrum/gl-spectrum.cc
+src/gl-spectrum-qt/gl-spectrum.cc
+src/gnomeshortcuts/gnomeshortcuts.cc
+src/gtkui/columns.cc
+src/gtkui/layout.cc
+src/gtkui/menus.cc
+src/gtkui/settings.cc
+src/gtkui/ui_gtk.cc
+src/gtkui/ui_playlist_widget.cc
+src/gtkui/ui_statusbar.cc
+src/hotkey/gui.cc
+src/hotkey/plugin.cc
+src/jack-ng/jack-ng.cc
+src/ladspa/plugin.cc
+src/ladspa/plugin.h
+src/lirc/lirc.cc
+src/lyricwiki/lyricwiki.cc
+src/lyricwiki-qt/lyricwiki.cc
+src/m3u/m3u.cc
+src/metronom/metronom.cc
+src/mixer/mixer.cc
+src/mms/mms.cc
+src/modplug/modplugbmp.cc
+src/modplug/modplugbmp.h
+src/modplug/plugin_main.cc
+src/mpg123/mpg123.cc
+src/mpris2/plugin.cc
+src/neon/neon.cc
+src/notify/event.cc
+src/notify/notify.cc
+src/notify/osd.cc
+src/oss4/oss.h
+src/oss4/plugin.cc
+src/playlist-manager/playlist-manager.cc
+src/pls/pls.cc
+src/psf/plugin.cc
+src/psf/psx.h
+src/pulse_audio/pulse_audio.cc
+src/qtaudio/qtaudio.cc
+src/qtui/dialog_windows.cc
+src/qtui/filter_input.cc
+src/qtui/main_window_actions.cc
+src/qtui/main_window.cc
+src/qtui/playlist_model.cc
+src/qtui/qtui.cc
+src/qtui/status_bar.cc
+src/resample/resample.cc
+src/scrobbler2/config_window.cc
+src/scrobbler2/scrobbler.cc
+src/scrobbler2/scrobbler_communication.cc
+src/sdlout/sdlout.cc
+src/search-tool/search-tool.cc
+src/sid/xmms-sid.cc
+src/sid/xs_config.cc
+src/silence-removal/silence-removal.cc
+src/skins/menus.cc
+src/skins/plugin.cc
+src/skins/preset-browser.cc
+src/skins/preset-list.cc
+src/skins/skins_cfg.cc
+src/skins/ui_equalizer.cc
+src/skins/ui_main.cc
+src/skins/ui_main_evlisteners.cc
+src/skins/ui_playlist.cc
+src/skins/ui_skinselector.cc
+src/skins/util.cc
+src/sndfile/plugin.cc
+src/sndio-ng/sndio.cc
+src/song_change/song_change.cc
+src/song-info-qt/song-info.cc
+src/sox-resampler/sox-resampler.cc
+src/speed-pitch/speed-pitch.cc
+src/statusicon/statusicon.cc
+src/stereo_plugin/stereo.cc
+src/tonegen/tonegen.cc
+src/voice_removal/voice_removal.cc
+src/vorbis/vorbis.cc
+src/vorbis/vorbis.h
+src/vtx/info.cc
+src/vtx/vtx.cc
+src/wavpack/wavpack.cc
+src/xsf/desmume/types.h
+src/xsf/plugin.cc
+src/xspf/xspf.cc
diff --git a/po/audacious-plugins.pot b/po/audacious-plugins.pot
index ff95c3deb993..f8c64fd52001 100644
--- a/po/audacious-plugins.pot
+++ b/po/audacious-plugins.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:13+0200\n"
+"POT-Creation-Date: 2015-04-03 11:54+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -18,51 +18,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr ""
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr ""
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr ""
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
 msgstr ""
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr ""
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -85,7 +69,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -107,7 +91,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -121,360 +105,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr ""
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr ""
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr ""
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr ""
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr ""
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr ""
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr ""
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr ""
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr ""
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr ""
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr ""
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr ""
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr ""
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr ""
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr ""
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr ""
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr ""
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr ""
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr ""
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr ""
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr ""
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr ""
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr ""
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr ""
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr ""
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr ""
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr ""
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr ""
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr ""
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr ""
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr ""
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr ""
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr ""
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr ""
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr ""
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr ""
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr ""
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr ""
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr ""
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -485,261 +475,258 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr ""
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr ""
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr ""
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD won't work properly"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr ""
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -751,169 +738,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr ""
 
-#: src/cd-menu-items/cd-menu-items.c:31
-msgid "Play CD"
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
 msgstr ""
 
-#: src/cd-menu-items/cd-menu-items.c:31
-msgid "Add CD"
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Play CD"
 msgstr ""
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Add CD"
 msgstr ""
 
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr ""
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr ""
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -923,195 +897,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr ""
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr ""
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr ""
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr ""
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr ""
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr ""
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr ""
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr ""
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr ""
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr ""
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr ""
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr ""
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr ""
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
 msgstr ""
 
-#: src/echo_plugin/echo.c:122
-msgid "Echo"
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1121,55 +1120,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr ""
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr ""
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr ""
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr ""
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
 msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
 msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1187,165 +1186,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr ""
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr ""
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr ""
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr ""
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr ""
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr ""
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr ""
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr ""
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr ""
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr ""
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr ""
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr ""
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr ""
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr ""
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr ""
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr ""
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr ""
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr ""
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr ""
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
 msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr ""
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr ""
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr ""
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr ""
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr ""
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr ""
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1353,21 +1356,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1379,530 +1386,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr ""
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr ""
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr ""
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr ""
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr ""
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr ""
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr ""
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr ""
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr ""
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr ""
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr ""
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr ""
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr ""
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr ""
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr ""
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr ""
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr ""
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr ""
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr ""
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr ""
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr ""
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr ""
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr ""
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr ""
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr ""
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr ""
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr ""
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr ""
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr ""
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr ""
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr ""
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr ""
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr ""
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr ""
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr ""
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr ""
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr ""
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr ""
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr ""
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr ""
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr ""
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr ""
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr ""
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr ""
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr ""
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr ""
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr ""
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr ""
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr ""
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr ""
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr ""
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr ""
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr ""
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr ""
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr ""
 
-#: src/hotkey/gui.c:70
-msgid "Previous track"
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
-msgid "Play"
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
 msgstr ""
 
-#: src/hotkey/gui.c:72
-msgid "Pause/Resume"
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
 msgstr ""
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:71
+msgid "Previous track"
+msgstr ""
+
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
+msgid "Play"
+msgstr ""
+
+#: src/hotkey/gui.cc:73
+msgid "Pause/Resume"
+msgstr ""
+
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr ""
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr ""
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr ""
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr ""
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1910,37 +1994,37 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr ""
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr ""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr ""
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1955,124 +2039,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
-msgstr ""
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr ""
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr ""
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr ""
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr ""
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr ""
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr ""
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr ""
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
 msgstr ""
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2088,73 +2138,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr ""
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
-#, c-format
-msgid "Unable to fetch %s"
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
+#, c-format
+msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr ""
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr ""
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2163,162 +2221,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr ""
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
 msgstr ""
 
-#: src/mms/mms.c:195
-msgid "MMS Plugin"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpg123/mpg123.c:412
-msgid "MPG123 Plugin"
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr ""
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr ""
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2338,55 +2428,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr ""
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr ""
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
 msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr ""
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr ""
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2395,19 +2494,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2427,143 +2542,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr ""
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr ""
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr ""
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr ""
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2574,765 +2758,840 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr ""
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr ""
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr ""
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr ""
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr ""
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr ""
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr ""
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr ""
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr ""
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr ""
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr ""
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr ""
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr ""
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr ""
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr ""
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr ""
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr ""
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr ""
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr ""
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr ""
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr ""
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr ""
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr ""
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
 msgstr ""
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr ""
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr ""
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
 msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr ""
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr ""
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr ""
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr ""
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr ""
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr ""
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr ""
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr ""
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr ""
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr ""
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr ""
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr ""
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr ""
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr ""
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr ""
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr ""
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr ""
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr ""
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr ""
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr ""
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr ""
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr ""
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr ""
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr ""
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr ""
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr ""
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr ""
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr ""
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr ""
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr ""
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr ""
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr ""
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr ""
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr ""
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3340,57 +3599,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr ""
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr ""
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3412,75 +3675,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
+#: src/song_change/song_change.cc:33
+msgid "Song Change"
 msgstr ""
 
-#: src/song_change/song_change.c:54
-msgid "Song Change"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
 msgstr ""
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
 msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
 msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3495,17 +3752,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3514,51 +3769,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
 msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3569,63 +3824,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr ""
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr ""
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr ""
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3634,15 +3889,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3663,44 +3914,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/be.po b/po/be.po
index d0302f411432..9e4d60303b6f 100644
--- a/po/be.po
+++ b/po/be.po
@@ -7,11 +7,11 @@
 # debconf <prach.by at gmail.com>, 2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Belarusian (http://www.transifex.com/projects/p/audacious/"
 "language/be/)\n"
 "Language: be\n"
@@ -21,51 +21,35 @@ msgstr ""
 "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "мона"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стэрэа"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr ""
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Плэер)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib Плэер)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Алярм"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Алярм"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -88,7 +72,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -110,7 +94,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -124,360 +108,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Гэта ваш выклік абуджэння."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Напамін"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Панядзелак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Аўторак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Серада"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Чацвер"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Пятніца"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Субота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Нядзеля"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Наладкі алярмаў"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Час"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Алярм у час (па-змоўчванню):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "г"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Сцішыць пасля:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "гадзін"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "хвілін"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Абярыце дні для ўжывання алярмаў"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Дзень"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Па-змоўчванню"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дзён"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Згасанне"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунд"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Гучнасць"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Пачаць у"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Фінальны"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Бягучы"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Дадатковы загад"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "уключыць"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Плэйліст (апцыянальны)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Выбраць плэйліст"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опцыі"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Што азначаюць гэтыя опцыі?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Даведка"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Афармленне альбома"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Вывад ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Тыповая PCM-прылада"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Тыповая прылада мікшара"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM прылада:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Прылада мікшара:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Элемент мікшара:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Апрацоўваць бітыя завісанні"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Вывад ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Гц"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Назва файла"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Імя файла"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Памер (байтаў)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Назва:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Звесткі па MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Фармат:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Даўжыня (мсек):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Нум. трэкаў:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "пераменны"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "УЗХ:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "УЗХ (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Каментары і Лірыка </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr " * у гэтым MIDI-файле каментарыі недаступныя *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* у гэтым MIDI-файле лірыка недаступная *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Закры_ць"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(недапушчальны UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -488,152 +478,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Прамавугольнік"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Скруглены Прамавугольнік"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Увагнуты Прамавугольнік"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Няма"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Старт Прайгравання"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Выводзіць OSD калі пункт плэйліста прайграваецца."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Змена Назвы"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Выводзіць OSD, калі падчас прайгравання змяняецца назва песні, але імя файла "
-"застаецца ранейшым. Гэта ў асноўным карысна для вываду зменаў у інтэрнэт-"
-"трансляцыях."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Паўза УКЛ."
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Выводзіць OSD калі прайграванне на паўзе."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Паўза ВЫКЛ."
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Выводзіць OSD калі прайраванне працягваецца з паўзы."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Змяшчэнне"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Зрушэнне адносна X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Зрушэнне адносна Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Максімальная шырыня OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Опцыі для некалькіх манітораў"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Паказваць OSD праз:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "усе маніторы"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "манітор %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Затрымка (мс)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Паказваць:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "З'яўленне:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Знікненне:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Шрыфты"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Шрыфт %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Цень"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Стыль Рэндэру"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Колеры"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Колер %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Уключыць трыгер"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Падзея"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Выяўлены кампазітны менэджар"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -643,112 +627,112 @@ msgstr ""
 "калі вы не ведаёце, ці запушчаны ён, актывуйце кампазітны менэджар. Інакш "
 "OSD не будзе працаваць карэктна"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Кампазітны менэджар не патрэбны для імітацыйнай празрыстасці"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Празрыстасць"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Імітацыйная празрыстасць"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Сапраўдная празрыстасць (патрабуе X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Кампазітныя пашырэнні не загружаны"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Кампазітныя пашырэнні недаступныя"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - канфігураванне"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Пазіцыя"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анімацыя"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Тэкст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Абрамленне"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Пераключальнік"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Іншае"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Плэйлісты ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Плэйлісты Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Колер</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Размыты асцылограф"
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr ""
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "Прэсеты:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr ""
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Спектральны аналізатар"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Плагін Аўдыё КД"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -760,169 +744,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Прылада</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метазвесткі</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Ужываць CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Ужываць CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Ужываць HTTP замест CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Шлях:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Порт:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Плагін Аўдыё КД"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Прывад пусты."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Тып не падтрымліваецца."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Прайграць CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Дадаць CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Кампрэсія</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Гучнасць цэнтру:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Дынамічны дыяпазон:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -932,195 +903,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Бас:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Сапрана:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Тыповая працягласць песні:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Уключыць перасэмплаванне гуку"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Частата перасэмплавання:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Гц"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr ""
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Узмацніць рэха"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr ""
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Пераход</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Перакрыццё:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Пераход"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Крышталайзер</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Інтэнсіўнасць:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Крышталайзер"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Сцерці"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Скасаваць"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Рэха</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Затрымка:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "мс"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Зваротная сувязь:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Гучнасць:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Рэха"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Плагін FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1130,55 +1126,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Плагін FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Плагін запісу файлаў"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Фармат файла вываду:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Канфігураваць"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Запісваць у выточны каталог"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Запісваць у адмысловы каталог"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Каталог файлаў вываду:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Абраць каталог"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Атрымаць назву файла з:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "арыгінальных тэгаў"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "арыгінальнай назвы файла"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Не адкідваць пашырэнне назвы файла"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Дадаваць нумар трэка перад назвай файла"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1196,165 +1192,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Плагін запісу файлаў"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Аўта"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Аб'яднанае стэрэа"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стэрэа"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Мона"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Канфігурацыя MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Алгарытмічная якасць:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Частата квантавання вываду:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Гц)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Суадносіны Bitrate / Compression:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Бітрэйт (кб/с):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Узровень сціску:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Рэжым аўдыё:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Інш:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Забяспечыць строгую фдпаведнасць ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Абарона ад памылак"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Якасць"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Уключыць VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Тып:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Опцыі VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Мінімальны бітрэйт (кб/с):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Максімальны бітрэйт (кб/с):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Строгая адпаведнасць мінімальнаму бітрэйту"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Опцыі ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Сярэдні бітрэйт (кб/с):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Узровень якасці VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Не запісваць загаловак Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Пазначыць copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Пазначыць як арыгінал"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 параметры:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Прымусова дадаваць тэг версіі 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Дадаваць толькі тэг v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Дадаваць толькі тэг v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Тэгі"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Канфігурацыя Энкэдэра Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Узровень якасці (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Дэкодар FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1362,21 +1362,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Дэкодар FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Плагін GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1388,446 +1392,509 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Цэтлікі Гнома"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Нумар запіса"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Назва"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Выканаўца"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Год"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Альбом"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Трэк"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Пазіцыя ў чарзе"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Працягласць"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Шлях да файла"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Імя файла"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Адмысловы загаловак"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Бітрэйт"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Пошукавая прылада"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Стыкаваць Злева"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Стыкаваць Справа"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Стыкаваць Уверсе"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Стыкаваць Долу"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Выключыць"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Пошукавая прылада"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Адк_рыць файлы ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Адкрыць _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Дадаць _файлы ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Дадаць U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "Аб ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "Вы_йсці"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Прайграць"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Па_уза"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "Сп_ыніць"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Пап_ярэдні"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Нас_тупны"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Па_ўтор"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "У_разнабой"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_Не пераходзіць да наступнай"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Звесткі пра песню ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Перайсці да _часу ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Перайсці да песні ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Па _назве"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Па _нумары трэка"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Па вык_анаўцу"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Па даце _выдання"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Па шляху да файла"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Па адмы_словым загалоўку"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Ад_варотны парадак"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Выпад_ковы парадак"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Прайграць плэйліст"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "А_бнавіць"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Парадкаваць"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Сцерці _недаступныя файлы"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Дадаць"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Перайменаваць ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Імпарт ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "Э_кспарт ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Кіра_ўнік плэйлістоў ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Кіраўнік _чаргі ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Гучней"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Цішэй"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "Э_квалайзер"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Паказваць стужку _меню"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Паказваць стужку звес_так"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Паказваць ві_зуалізацыю стужкі звестак"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Паказваць стужку _статусу"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "Ф_айл"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Прайграванне"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "П_лэйліст"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "Сервіс_ы"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Выва_д"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "Вы_гляд"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "У чаргу / З чаргі"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Выразаць"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Капіраваць"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Уставіць"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Вылучыць усе"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "П_ерайменаваць ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Інтэрфейс GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Назапашванне ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "мона"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стэрэа"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1836,84 +1903,98 @@ msgstr[1] "%d каналы"
 msgstr[2] "%d каналаў"
 msgstr[3] "%d каналаў"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d кб/с"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Рэжым плэйліста."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Спыненне пасля песні."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Граць"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Паўза/Працягнуць"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Спыніць"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Цішыня"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Паказаць Дысплей на Экране :OSD:"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(няма)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1921,37 +2002,37 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr ""
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr ""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr ""
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Дзеянне:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1966,124 +2047,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Вывад JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Вывад JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Настаўленні"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Настаўленні хоста LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Шлях да модуля:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Даступныя плагіны:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Уключыць"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Уключаныя плагіны:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Настаўленні"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: спроба паўторнага злучэння...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: невядомы загад \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: злучэнне з LIRC страчана\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Плагін LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2099,73 +2146,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Злучэнне</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Перазлучэнне з серверам LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Плагін LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Плагін LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Словы недаступныя"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Памылка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Немагчыма атрымаць %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Памылка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Немагчыма разабраць %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Шукаюцца словы ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Адсутнічаюць метазвесткі ў песні"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Злучэнне з lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Плагін LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Плэйлісты M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Тактавы генератар"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Тактавы генератар: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Тактавы генератар: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2174,162 +2229,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Тактавы генератар"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Мікшар каналаў"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Мікшар каналаў</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Каналаў вываду:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Мікшар каналаў"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Плагін MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr ""
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Плагін MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr ""
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Плагін Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Спынена"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious не іграе."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2349,55 +2436,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Пауза"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Наступны"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Тыповая прылада"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Вывад OSS4"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Аўдыё-прылада:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr ""
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Захоўваць гучнасць паміж сеансамі."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2406,19 +2502,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Вывад OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Плэйлісты PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Дэкодар OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Вывад PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2438,143 +2550,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Вывад PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Папярэдні"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Паўтор"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Уразнабой"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Лінейная інтэрпаляцыя"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Канверсія</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метад:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 кГц:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 кГц:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22,05 кГц:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44,1 кГц:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 кГц:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 кГц:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 кГц:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2585,771 +2766,846 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Бібліятэка"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Невядомы выканаўца"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Невядомы альбом"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 msgstr[3] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 msgstr[3] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 msgstr[3] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Стварыць плэйліст"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Дадаць у плэйліст"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Шукаць у бібліятэцы"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Пачакайце, калі ласка ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Выберыце каталог"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Прайграванне"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Плэйліст"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Выгляд"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Паўтор"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Уразнабой"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Не пераходзіць да наступнай"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Папярэдні"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Новы плэйліст"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Паказваць рэдактар спісаў"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Паказваць эквалайзер"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Заўсёды зверху"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Па загалоўку"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Па назве файла"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Сцерці усе"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Ачысціць чаргу"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Сцерці недаступныя файлы"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Сцерці дублікаты"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Сцерці невылучаныя"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Сцерці вылучаныя"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Пошук і вылучэнне"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Інвертаваць вылучэнне"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Зняць вылучэнне"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Вылучыць усе"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Па альбому"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Па нумары трэка"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Па выканаўцу"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Па альбому"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Па нумары трэка"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Раскідаць спіс"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Спіс наадварот"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Сартаваць вылучаныя"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Сартаваць спіс"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Выразаць"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Капіраваць"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Уставіць"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Інтэрфейс Winamp-класік"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Запісаць"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Загрузіць"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Прэсеты"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Чытаць прэсет"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Чытаць аўта-прэсет"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Запісаць прэсет"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Запісаць аўта-прэсет"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Сцерці прэсет"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Сцерці аўта-прэсет"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "Плэер:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Вылучыце шрыфт для галоўнага вакна плэера:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "Пл_эйліст:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Выберыце шрыфт для плэйліста:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Пракручваць назву песні ў абодвух кірунках"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Аналізатар"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Асцылограф"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Выкл"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Норма"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Полымя"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Лініі"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Слупкі"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Наймарудней"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Марудна"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Сярэдне"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Хутка"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Найхутчэй"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лёд"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Гладка"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Агульныя"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Візуалізацыя"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Перадузмацненне"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "2 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 кГц"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Эквалайзер Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr ""
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Гучнасць: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Баланс: %d%% ўлева"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Баланс: цэнтр"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Баланс:  %d%% ўправа"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Меню опцый"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Адключыць 'Заўсёды зверху'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Уключыць 'Заўсёды зверху'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr ""
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Рэжым плэйліста."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Спыненне пасля песні."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Шукаць запісы ў бягучым плэйлісце"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3357,57 +3613,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Загаловак: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Альбом: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Выканаўца: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Назва файла: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Ачысціць папярэдняе вылучэнне перад пошукам"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Аўтаматычна пераключыць чаргу для адпаведных запісаў"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Стварыць новы плэйліст з адпаведнымі запісамі"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Рэдактар плэйлістоў Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d з %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Сціснутая абалонка Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Несціснутая абалонка Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Немагчыма стварыць каталог (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Плагін Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3429,75 +3689,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Плагін Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Пра плагін вываду Sndfile"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Фармат не падтрымліваецца"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "прылада sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Так"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Пераключэнне песні"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
 msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Загад:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Загад, які выканаць па заканчэнні песні."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Выконваць загад, калі Audacious дасягае канца плэйліста."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3512,17 +3766,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Загады"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3531,51 +3783,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Хуткасць"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Значок статусу"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3586,63 +3838,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Дзеянні колца мышы</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Змяняць гук"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Змяняць песню"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Іншыя настаўленні</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Адключыць усплыўное акно"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Значок статусу"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Дадатковае стэрэа"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Дадатковае стэрэа</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Дадатковае стэрэа"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Гц"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr ""
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3651,15 +3903,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Выдаленне голасу"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3680,44 +3928,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Дэкодар Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Дэкодар VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Дэкодар VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Дэкодар WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Дэкодар WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Дэкодар 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/bg.po b/po/bg.po
index ad7a7a07dc75..c4b5bfe8ff17 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -3,17 +3,20 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# Ivailo Monev <xakepa10 at gmail.com>, 2014
+# Kiril Kirilov <cybercop_montana at abv.bg>, 2014-2015
 # Pandi3a <pandi3a at gmail.com>, 2012
 # Pandi3a <pandi3a at gmail.com>, 2012
-# Радослав <reckku at gmail.com>, 2013-2014
-# Радослав <reckku at gmail.com>, 2013
+# Радослав Иванов <reckku at gmail.com>, 2013-2014
+# Радослав Иванов <reckku at gmail.com>, 2013
+# Радослав Иванов <reckku at gmail.com>, 2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-13 11:48+0000\n"
-"Last-Translator: Радослав <reckku at gmail.com>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-19 22:33+0000\n"
+"Last-Translator: Радослав Иванов <reckku at gmail.com>\n"
 "Language-Team: Bulgarian (http://www.transifex.com/projects/p/audacious/"
 "language/bg/)\n"
 "Language: bg\n"
@@ -22,40 +25,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "еднозвучие"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "многозвучие"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "обграждащ звук"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Разкодиране на AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Разкодиране на AAC (Raw)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Плейър)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "подредени"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib Плеър)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Аларма"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Задаване на Аларма ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -66,11 +57,7 @@ msgstr ""
 "\n"
 "Оригинално написана от Adam Feakin и Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Аларма"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -112,7 +99,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -150,7 +137,7 @@ msgstr ""
 "Допълнителна команда:\n"
 "Стартиране на тази команда по време на алармата.\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -174,183 +161,156 @@ msgstr ""
 "Въведете известието в кутията и включете клавиша за\n"
 "превключване, ако искате да бъде извеждано."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Това е Вашият сигнал за събуждане."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Вашето напомняне за днес е..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Напомняне"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Понеделник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Вторник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Сряда"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Четвъртък"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Петък"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Събота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Неделя"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Настройки на аларма"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_Добре"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Отказ"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Час"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Алармиране в (по подразбиране):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "ч"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Затишие след:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "часове"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "минути"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Избор на дни, в които да се активира алармата"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Ден"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "По подразбиране"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дни"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Затихване"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунди"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Сила на звука"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Начало"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Край"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Текущо"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Допълнителна команда"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "активиране"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Списък за изпълнение (по избор)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Избор на списък"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опции"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Какво означават тези опции?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Помощ"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Обложка на албум"
 
-#: src/alsa/config.c:210
-msgid "Default PCM device"
-msgstr "PCM устройство по подразбиране"
-
-#: src/alsa/config.c:239
-msgid "Default mixer device"
-msgstr "Миксер устройство по подразбиране"
-
-#: src/alsa/config.c:428
-msgid "PCM device:"
-msgstr "PCM устройство:"
-
-#: src/alsa/config.c:430
-msgid "Mixer device:"
-msgstr "Миксер:"
-
-#: src/alsa/config.c:432
-msgid "Mixer element:"
-msgstr "Елемент на миксера:"
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Албум Изп (Qt)"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Избягване на повторение"
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA Изход"
 
-#: src/alsa/plugin.c:27
+#: src/alsa/config.cc:28
 msgid ""
 "ALSA Output Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren\n"
@@ -365,194 +325,208 @@ msgstr ""
 "NG, чийто код служеше за справка, когато ръководството към ALSA не беше "
 "достатъчно."
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA Изход"
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(няма описание)"
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr "PCM устройство по подразбиране"
 
-#: src/amidi-plug/amidi-plug.c:466
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr "Миксер устройство по подразбиране"
+
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr "PCM устройство:"
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr "Миксер:"
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr "Елемент на миксера:"
+
+#: src/amidi-plug/amidi-plug.cc:41
 msgid "AMIDI-Plug (MIDI Player)"
 msgstr "AMIDI-Plug (MIDI Плеър)"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Презапис на стандартното усилване:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Презапис на стандартната полифония:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Презапис на стандартното ехо"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Включено"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Презапис на стандартния хор:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Възпроизвеждане</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Транспозиции:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "полутонове"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Промяна на барабана:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Допълнителни</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Разархивиране на коментари от MIDI файл"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Разархивиране на текст от MIDI файл"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>Шрифт на звука</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Синтезатор</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Честота на дискретизация:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Хц"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Контакт - избор на файл за звуково изравняване"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Отказ"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Отваряне"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Име на файл"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Име на файла"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Размер (байтове)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Име:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI информация </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Формат:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Продължителност (милисекунди):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "№ на Записи:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "променливост"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "УВМ:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "УВМ (вълни):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Време Разд.:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Коментари и лирика </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* няма достъпни коментари за този MIDI файл *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* няма достъпна лирика за този MIDI файл *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Затваряне"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (невалиден UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Относно AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Вход"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"модулен MIDI плеър\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Написан от Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"искрени благодарности на...\n"
-"\n"
-"Clemens Ladisch и Jaroslav Kysela\n"
-"за страхотните им програми aplaymidi и amixer;\n"
-"те бяха наистина полезни, заедно с документацията за\n"
-"alsa-lib, във връзка със запознаването с ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"за хубавото клавиатурно midi лого\n"
-"\n"
-"Tony Vroon\n"
-"за помощта при алфа тестовете"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -570,154 +544,148 @@ msgstr ""
 "Базиран отчасти на Ghosd библиотеката на Evan Martin:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (прозорец в екрана)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Правоъгълник"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Правоъгълник със заоблени краища"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Вдлъбнат правоъгълник"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Без"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Начало на възпроизвеждането"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Задействане на OSD, когато започне възпроизвеждането"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Промяна на заглавие"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Задействане на OSD, когато, по време на възпроизвеждането, се промени името "
-"на заглавието, но името на файла остане непроменено. Това е най-полезно при "
-"извеждане на промените в заглавието за интернет потоците."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Временното спиране е активирано"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr ""
 "Задействане на OSD, когато\n"
 "възпроижзвеждането е в режим на временна пауза."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Временното спиране е деактивирано"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Задействане на OSD, когато възпроизвеждането продължи."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Местоположение"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Относителен отстъп за X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Относителен отстъп за Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Максимална ширина на OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Опции за много монитори"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Извеждай OSD, използвайки:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "всички монитори"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "монитор %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Времетраене (мс)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Екран:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Проясняване:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Избледняване:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Шрифтове"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Шрифт %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Сянка"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Създай свой стил"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Цветове"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Цвят %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Активиране на активатора"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Събитие"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Засечен е Композитен мениджър"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -727,112 +695,112 @@ msgstr ""
 "моля активирайте мениджъра, освен ако вече нямате стартиран, в противен "
 "случай OSD няма да работи правилно"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Не се изисква композитен мениджър за илюзийна прозрачност"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Прозрачност"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Илюзийна прозрачност"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Истинска прозрачност (изисква разширение за X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Композитното разширение не е заредено"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Композитното разширение не е налично"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - настройка"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Тест"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Задаване"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Позиция"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анимация"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Декорация"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Активатор"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Разни"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Тест"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 списъци за изпълнение"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 Списъци"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious Списъци (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Цвят</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Размит осцилоскоп"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Многозвучие-към-двузвучие (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Предложения:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Ниво на емисия:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Честота на срез:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Предложения:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Многозвучие-към-двузвучие (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Анализ на спектъра"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Аудио CD Приставка"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -855,171 +823,156 @@ msgstr ""
 "\n"
 "Това беше проект от Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Устройство</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Скорост на четене:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Презапис на устройството:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метаданни</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Използвай CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Използвай CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Използване на HTTP вместо CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сървър:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Път:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Порт:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Аудио CD Приставка"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Нуспех при откриване на cdio подсистема."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Невалиден Интернет адрес %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Запис %d не е намерен."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Записът %d е от данни."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Не може да бъде отворен аудио изхода."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Грешка при четене на audio CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Аудио Диск"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Запис %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Не може да бъде отворено CD устройство %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Не е намерено Audio CD устройство."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Неуспешно приключване на обозначаването на отвореното CD устройство."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Неуспех при извличане на първият/последният номер на запис."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Не може да прочете началото/края на LSN за запис %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Неуспех при създаване на cddb връзка."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Неуспешна заявка към CDDB сървър"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Неуспешна заявка към CDDB сървър: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Неуспешно прочитане на cddb информация: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Устройството е празно."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Неподдържан диск."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Елементи на меню тип Audio CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Възпроизвеждане на компакт диск"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Добавяне на компакт диск"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Елементи на меню тип Audio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Свиване</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Среда на звука:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамичен обхват:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Приставка за Свиване на динамичните честоти за Audacious\n"
-"Авторски права 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Свиване на динамичния обхват"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1035,207 +988,226 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Ниски:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Високи:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Ехо:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Стандартно времетраене за песен:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Преизчисляване</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Активиране на преизчисляване на звука"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Честота на преизчисляване:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Хц"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Незачитане на продължителността според SPC етикетите"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Увеличаване на ехото"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Звуково разкодиране за игрална конзола"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"Плавното преминаване несполучи, защото песните имат различен брой канали. "
-"Можете да използвате Смесителя на канали, за да превърнете броя им в общ за "
-"всички песни."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Плавното преминаване несполучи, защото песните имат различна честота. Можете "
-"да използвате Преобразувателя на честота, за да зададете обща честота за "
-"всички песни."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Приставка за плавно преминаване на Audacious\n"
-"Авторски права 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Плавно преминаване</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Застъпване:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Плавно преминаване"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Плавното преминаване несполучи, защото песните имат различен брой канали. "
+"Можете да използвате Смесителя на канали, за да превърнете броя им в общ за "
+"всички песни."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Плавното преминаване несполучи, защото песните имат различна честота. Можете "
+"да използвате Преобразувателя на честота, за да зададете обща честота за "
+"всички песни."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристализиране</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Наситеност:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристализатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Приставка за условности"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Изтриване на файлове"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Грешка при преместването на %s в коша: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Грешка при изтриването на %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Грешка при изтриването на %s: не е местен файл."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Искате ли да преместите избраните файлове в коша?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Преместване в Коша"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Искате ли окончателно да изтриете избраните файлове?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Изтриване"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Отказ"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Изтриване на файлове"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Изтриване на избраните файлове"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Начин на изтриване</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Премести в коша, вместо незабавно изтриване"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ехо</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Забавяне:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "мс"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Отзиви:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Сила на звука:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Приставка за Ехо\n"
-"От Johan Levin, 1999\n"
-"\n"
-"Обграждащо ехо от Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Ехо"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Приставка за FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1251,55 +1223,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Приставка за FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Приставка FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Формат на изходния файл:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Настройване"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Запамети в оригиналната директория"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Запамети на избрано място"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Папка на изходния файл:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Избор на папка"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Извличане на име от:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Генерирай име на файл от:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "маркери на оригиналния файл"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "оригинално име"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Оригинално име на файл"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Да не се изрязва разширението на файла"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Номерът на записа да предшества името му"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1329,165 +1301,169 @@ msgstr ""
 "ако не сте, пишете до Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Приставка FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Автоматично"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Общо Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 настройки"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Добре"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Алгоритъм за качество:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Изходна честота:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Изходна честота на дискретизация:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Хц)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Честота на сгъстяване:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Честота за бит (кбвс):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Честота на сгъстяване:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Режим на звука:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Разни:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Придържане към ISO съвместимост"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Грешна защита"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Качество"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Активиране VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Вид:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR Опции:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Минимална честота за бит (кбвс):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Максимална честота за бит (кбвс):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Придържане към минимална честота за бит"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR Опции:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Средна честота за бит (кбвс):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Ниво на качеството на VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Да не се записва титул за Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Стойности на рамката:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Маркер „Защитено от копиране“"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Маркер „Оригинал“"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Стойности на ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Принудително добавяне на маркер от 2-ра версия"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Добави само маркер 1-ва версия"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Добави само маркер 2-ра версия"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Маркери"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Настройка на Vorbis кодиране"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Ниво на качеството (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Разкодиране на FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "по-малко загуби"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1499,11 +1475,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Разкодиране на FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1511,11 +1483,19 @@ msgstr ""
 "Приставка GIO за Audacious\n"
 "Авторски права 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Приставка GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1535,534 +1515,607 @@ msgstr ""
 "\n"
 "Лиценз: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL осцилоскоп"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
-msgstr ""
-"Приставка Бързи клавиши на Gnome\n"
-"Позволява Ви да контролирате плеъра с бързите клавиши на Gnome.\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
 "\n"
-"Авторски права (C) 2007-2008 "
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr "Бързи клавиши за Gnome"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Номер на запис"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Заглавие"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Изпълнител"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Година"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Албум"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Изпълнител на албум"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Запис"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Позиция на опашката"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Времетраене"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Път до файла"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Име на файла"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Избрано заглавие"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Честота за бит"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Налични колони"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Показване колони"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Инструмент за търсене"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Панел вляво"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Панел вдясно"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Панел отгоре"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Панел отдолу"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Без панел"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Деактивиране"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Инструмент за търсене"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Отворяне на файлове..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "От_варяне на Интернет адрес..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Добавяне на файлове..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "_Добавяне на Интернет адрес..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "_Библиотека за търсене"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "О_тносно..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Настройки..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Изход"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "И_зпълнение"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "В_ременно спиране"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Спиране"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Предишен"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Следващ"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Повт_орение"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Разбърка_но"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_Без прескачане към следващо изпълнение"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Спри с_лед тази песен"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Информация за песен..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Пре_скачане до време..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Прескачане до п_есен..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Начална точка н_а повторение"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Крайна точка на повторе_ниe"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "Из_чистване на точките на повторение"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "По _Заглавие"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "По _име на файл"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "По Име на файл"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "По _път до файл"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "По _номер на запис"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "По _Изпълнител"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "По ал_бум"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "По Изпълнител на Албум"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "По _Дата на излизане"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "По _Жанр"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "По в_реметраене"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "По _Път до файл"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "По Избрано _заглавие"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "О_бръщане на подредбата"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Сл_учаен ред"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Изпълни този списък"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Изпълнение/Подновяване"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Опресняване"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Сортиране"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "По_дреждане на избраните"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Премахване на по_втарящи се"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Премахване на _липсващите файлове"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Нова"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Преименуване..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Премах_ване"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Внасяне..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Изнасяне..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "_Управление на списъка..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Управление на опашката..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Увеличаване на _звука"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Намаляване на з_вука"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Тонкоректор"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "Е_фекти..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Показване на панел с _меню"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Показване на лента с _информация"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Показване на представяне в стълба с информация"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Показване на лента на _състоянието"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Пока_жи оставащо време"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "Виз_уализации..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Файл"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Изпълнение"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Списък"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Услуги"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Изходящ поток"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Изглед"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Промяна на състоянието в опашката"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Отрязване"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Копиране"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Поставяне"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Избор на _всички"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "П_реименуване..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Подпрозорци в списъка</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Винаги да се показват подпрозорците"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Показване на брояч на записите"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Показване на бутони за затваряне"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Колони в списъка</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Показване на антетки"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Разни</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Превъртане със стрелките:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Превъртане при смяна на песента"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK Изглед"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Запълване..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "еднозвучие"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "многозвучие"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d канал"
 msgstr[1] "%d канали"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d кбвс"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Режим „Единичен“."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Режим „Списък“."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Спиране след песента."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Предишен запис"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Изпълнение"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Временно спиране/Възобновяване"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Спиране"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Следващ запис"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Напред с 5 секунди"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Назад с 5 секунди"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Заглушаване"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Увеличаване на звука"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Намаляване на звука"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Прескачане до файл"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Превключване между прозорците"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Показване на Прозорец върху екрана"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Превключване на повторение"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Превключване на разбъркване"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Превключване на спиране след текущият"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Издигане на прозорците"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(без)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2074,15 +2127,11 @@ msgstr ""
 "\n"
 "Искате ли да продължите?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Обвързани бутони на мишката"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Настройка на приставката за основни бързи клавиши"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2090,23 +2139,27 @@ msgstr ""
 "Наберете комбинация от клавиши в текстовото поле.\n"
 "Можете да включете и бутони от мишката."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Бързи клавиши:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Действие:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Обвързване на клавиш:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Добавяне"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Общи бързи клавиши"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2132,60 +2185,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Общи бързи клавиши"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK Изход"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Свързване към всички налични портове на jack"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Свързване само на изходящите портове"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Без свързване към никой порт"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Режим на свързване:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Активирай извеждане на дебъг"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Базиран на xmms-jack, от Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Пренаписан за Audacious от Giacomo Lozito"
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK Изход"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Настройки"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Настройки на LADSPA среда"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Пътища към модул:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2196,25 +2240,25 @@ msgstr ""
 "След добавяне на тези пътища, натиснете Ентер за сканиране за нови приставки."
 "</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Достъпни приставки:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Активиране"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Активирани приставки:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Настройки"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2222,47 +2266,15 @@ msgstr ""
 "Порт на LADSPA за Audacious\n"
 "Авторски права 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Среда"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: не може да се отбележи поддръжка на LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: не може да се прочете файла с настройка на LIRC\n"
-"%s: моля прочетете документацията на LIRC\n"
-"%s: как да създадем подходящ файл с настройки\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: опит за повторно свързване...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: неизвестна команда „%s“\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: прекъсната връзка от LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: опит за повторна връзка на всеки %d секунди...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Приставка LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2291,73 +2303,81 @@ msgstr ""
 "\n"
 "За повече информация относно LIRC, вижте http://lirc.org"
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Връзка</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Повторно свързване към LIRC сървъра"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Изчакайте преди да опитате повторно свързване:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Приставка LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Приставка LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Няма наличен текст"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Грешка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Неуспех при извличане на %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Грешка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Неуспех при разделяне на %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Търсене на текст..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Липсващи метаданни за песента"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Свързване към lyrics.wikia.com..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Приставка LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Приставка LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Списък M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Генератор на удари"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Генератор на удари: %d увм"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Генератор на удари: %d увм %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2371,11 +2391,11 @@ msgstr ""
 "напр. tact://77 за изпълняване на 77 удара в минута\n"
 "или tact://60*3/4 за изпълняване на 60 увм в такт 3/4"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Генератор на удари"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Смесител на канали"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2383,152 +2403,184 @@ msgstr ""
 "Приставка смесител на канали за Audacious\n"
 "Авторски права 2011-2012 John Lindgren и "
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Смесител на канали</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Изходни канали:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Смесител на канали"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Приставка MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Грешка при свързване към MMS сървър"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Модулен плеър)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Дълбочина</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-битов"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-битов"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Канали</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Най-близкият (най-бърз)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Линеен (бърз)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Шпонка (добър)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Многофазен (най-добър)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Честота на дискретизация</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 кХц"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 кХц"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 кХц"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 кХц"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Ниво:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Срез:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Ехо</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Усилване на ниските</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Обграждащ звук</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Предусилвател</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Надхвърляне на честотата на дискретизация"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Намаляване на шума"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Изпълняване на Amiga MODs"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Повторение</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Брой повторения:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "За непрекъснато повторение, задайте стойност -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Модулен плеър)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Обграждащ звук"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Приставка MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Допълнителни</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Обграждащ звук"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Услуга MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Приставка Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Грешка при пренасочването"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Неизвестна HTTP грешка"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Грешка при зареждане на URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Твърде много пренасочвания"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Спрян"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious не изпълнява нищо."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Уведомления на работния плот"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2563,55 +2615,64 @@ msgstr ""
 "You should have received a copy of the GNU General Public License along with "
 "this program. If not, see <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Показване на бутоните за управление"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Винаги да се показва известие"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Уведомления на работния плот"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Включи име на албум в уведомленията"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Показване"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Временно спиране"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Следващ"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Устройство по подразбиране"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Изход OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Изход OSS3"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Устройство по подразбиране"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Аудио устройство:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Използване на алтернативно устройство:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Запази нивотона звука между сесиите."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Активиране на формати, направени от OSS софтуер."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Активиране на ексклузивен режим, за предотвратяване на смесване."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2625,19 +2686,35 @@ msgstr ""
 "Бих искал да благодаря на хората от #audacious, особено на Tony Vroon и John "
 "Lindgren и, разбира се, на авторите на предишната версия на приставката."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Изход OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Мениджър на плейлиста"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Елементи"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Премахване"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Преименуван_е"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Списъци PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Разкодиране OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Изход PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2671,11 +2748,68 @@ msgstr ""
 "ако не сте, пишете до Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Изход PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Изход QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Работи ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Търсене"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Отваряне на Папка ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Добавяне на Папка ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Проверка на лог ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Отваряне на файлове"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Добавяне на файлове"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Предишен"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Повторение"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Прескачане"
 
-#: src/resample/resample.c:165
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt Изглед"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Преобразувател на честоти"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2683,99 +2817,107 @@ msgstr ""
 "Приставка за промяна на честотата за Audacious\n"
 "Авторски права 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Честотно прескачане/повтаряне"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Линейна интерполация"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Бързосинхронна интерполация"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Средносинхронна интерполация"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Най-добра синхронна интерполация"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Обръщане</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метод:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Честота:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Планирани честоти</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Използване на планирани честоти"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 кХц:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 кХц:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 кХц:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 кХц:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 кХц:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 кХц:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 кХц:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 кХц:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 кХц:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 кХц:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Преобразувател на честоти"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "Добре. Споделяне за потребител: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Нямате права"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Посетете връзката, за да позволите на Audacious, да споделя Вашите "
 "изпълнения:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Запазете този прозорец отворен и отново изберете „Проверка на права“.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2783,34 +2925,38 @@ msgstr ""
 "Не се притеснявайте. Вашите споделяния са запаметени на компютъра.\n"
 "Ще бъдат изпратени веднага след като на Audacious му бъде позволено."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Интернет проблем."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Възникна проблем при свързване с Last.fm. Опитайте по-късно."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Проверка..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "П_роверка на права"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Връщане на права"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Нужно е да позволите на Audacious да споделя записите във Вашият Last.fm "
 "профил.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Споделяне 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2818,7 +2964,7 @@ msgstr ""
 "Приставката Споделяне на песен не може да се стартира.\n"
 "Може би има проблем с инсталацията."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2835,11 +2981,7 @@ msgstr ""
 "Благодарности на John Lindgren за оказаната помощ в този проект.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Споделяне 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2847,7 +2989,11 @@ msgstr ""
 "Audacious използва подобрена версия на Споделяне на песни за Last.fm.\n"
 "Моля, проверете настройките на приставката за Споделяне на песни."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Изход SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2855,81 +3001,56 @@ msgstr ""
 "Изходна приставка SDL за Audacious\n"
 "Авторски права 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Изход SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Библиотека"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Непознат изпълнител"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Непознат албум"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" на %s от %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d резултат"
+msgstr[1] "%d резултати"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d албум"
-msgstr[1] "%d албуми"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d скрит)"
+msgstr[1] "(%d скрити)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d песен"
-msgstr[1] ""
-"%s\n"
-" %s, %d песни"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d песен от %s"
-msgstr[1] ""
-"%s\n"
-" %d песни от %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d песен"
+msgstr[1] "%d песни"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "на този жанр"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "на"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "от"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Създай списък"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Добавяне в списък"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Търсене в библиотека"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2937,679 +3058,769 @@ msgstr ""
 "За да внесете музикална библиотека в Audacious, изберете папка и кликнете на "
 "бутона \"Опресняване\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Моля изчакайте..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Избор на папка"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID Плеър"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Изход</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Канали:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Емулация</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Емулирай MOS 8580 (по подразбиране: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Не избирай автоматично модел на чип"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Емулация на филтър"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Скорост на часовника:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Не избирай автоматично скорост на часовника"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Време на възпроизвеждане</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Задай максимална продължителност на изпълнението:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Уведомление</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Таван:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "дБ"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Отваряне на файлове..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Отваряне на интернет адрес..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Търсене в библиотеката"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Възпроизвеждане"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Списък за изпълнение"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Изглед"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Услуги"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Относно..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Настройки..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Изход"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Информация за песен..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Повторение"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Прескачане"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Без продължаване в списъка"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Спиране след тази песен"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Предишен"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Задаване на А-Б повторение"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Изчистване на А-Б повторение"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Прескачане до песен..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Прескачане до време..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Възпроизвеждане на този списък"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Нов списък"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Преименуване на списък..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Премахване на списък..."
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Предишен списък"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Следващ списък"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Внасяне на списък..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Изнасяне на списък..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Мениджър на списъци..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Мениджър на опашките..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Опресняване на списък"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Показване на редактор на списъка"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Показване на тонкоректор"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Показвай оставащо време"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Винаги отгоре"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "На всички работни среди"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Свиване на плеър"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Свиване на редактора на списъци"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Свиване на тонкоректор"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Двоен Размер"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Добавяне на интернет адрес..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Добавяне на файлове..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "По заглавие"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "По име на файла"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "По Име на файл"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "По път до файл"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Премахване на всички"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Изчистване на опашката"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Премахване на липсващите файлове"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Премахване на повторения"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Премахване на неизбраните"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Премахване на избраните"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Търсене и избиране"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Обръщане на избраното"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Без избрани"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Избор на всички"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "По Албум"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "По номер на записа"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "По Изпълнител"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "По Албум"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "По Изпълнител на Албум"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "По дата на издаване"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "По номер на записа"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Случаен списък"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Обръщане на списъка"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Подреждане на избраните"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Подреждане на списъка"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Изрязване"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Копиране"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Поставяне"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "На опашка/без опашка"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Зареди подготвени..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Зареди автоматично подготвени..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Зареди стандартни"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Зареди файл с подготвени..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Зареди на EQF файл..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Запази подготвено..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Запази автоматично подготвено..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Запази стандартно"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Запази файл с подготвено..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Запамети EQF файл..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Изтрий подготвено..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Изтрий автоматично подготвено..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Внасяне на подготвени за Winamp..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Върни до нула"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Класически изглед на Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Запаметяване"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Зареждане"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Зареди файл с подготвени"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Зареди EQF файл"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Запази файл с подготвено"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Запамети EQF файл"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Внасяне на подготвени за Winamp"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Зададени"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Зареждане на предложение"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Зареждане на автоматично предложение"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Запазване на предложение"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Запазване на автоматично предложение"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Изтриване на предложение"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Изтриване на автоматично предложение"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Плеър:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Плеър:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Избор на основен шрифт за прозореца на плеъра:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Списък:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Плейлиста:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Избор на шрифт за списъка:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Кожа</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Шрифтове</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Избор на растерни шрифтове (поддържа само ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Превъртане на заглавието на песента"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Превъртане на заглавието на песента в двете посоки"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Анализатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Осцилоскоп"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Гласов отпечатък / VU-метър"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Изглючено"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Нормално"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Огън"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Вертикални линии"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Линии"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Стълбове"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Най-бавно"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Бавно"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Средно"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Бързо"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Най-бързо"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Точки"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Линия"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Плътно"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лед"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Размито"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Вид</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Вид на визуализация:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Анализатор</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Показвай пикове"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Оцветяване:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Стил:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Падане:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Падане на пиковете:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Осцилоскопичен стил:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Цвят на гласовия отпечатък:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Стил на VU-метър:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Общи"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Изобразяване"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Предусилвател"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Хц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Хц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Хц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Хц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Хц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 кХц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 кХц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 кХц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 кХц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 кХц"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Тонкоректор на Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Превъртане до %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Сила на звука: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Баланс: %d%% ляво"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Баланс: център"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Баланс: %d%% дясно"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Меню с опции"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Деактивиране на „Винаги отгоре“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Активиране на „Винаги отгоре“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Кутийка с информация за файла"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Визуализации"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Зададена е начална точка на повторение."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Зададена е крайна точка на повторение."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Точките на повторение са изчистени."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Режим „Единичен“."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Режим „Списък“."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Спиране след песента."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Търсене на записи в активния списък"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Търсене"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3621,57 +3832,61 @@ msgstr ""
 "буквата. Ако не знаете как работи този синтаксис, просто въведете част от "
 "това, което търсите."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Заглавие:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Албум:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Изпълнител:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr "Име на файл:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Изчистване на предишния избор преди търсене"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Автоматично превключване в опашката за съвпадащите елементи"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Създаване на нов списък със съвпадащите елементи"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious Редактор на списъка за изпълнение"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d от %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Архивирана кожа на Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Неархивирана кожа на Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Не може да се създаде директория (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Приставка Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3710,83 +3925,71 @@ msgstr ""
 "ако не сте, пишете до Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Приставка Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Относно изходна приставка Sndio"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Изходна приставка Sndio\n"
-"\n"
-"Написана от Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Неподдържан формат"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Запази и възтанови звука:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Бе поискан формат, който не се поддържа от устройството.\n"
-"\n"
-"Моля опитайте отново, но със стартиран sndiod(1) сървър."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio устройство"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(празно - означава по подразбиране)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Добре"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Промяна на песен"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Команда за изпълнение след започване на нова песен."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Стойностите, изпратени до обвивката, е добре да са в "
+"кавички. В противен случай се крие опасност за сигурността.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Команда:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Команди</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Команда за изпълнение след край на песен."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Команда за изпълнение при започване на нова песен:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Команда за изпълнение при достигане на края на списъка."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Команда за изпълнение при край на песен:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Команда за изпълнение при край на плейлиста."
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Команда за изпълнение при промяна на заглавието на песен (напр. при интернет "
-"поток)"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3800,35 +4003,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Можете да използвате следните букви,\n"
-"които ще бъдат заместени, преди изпълнението на командата\n"
-"(не всички са полезни за команда при край на списъка):\n"
-"\n"
-"%F: Честота (херцове)\n"
-"%c: Брой канали\n"
-"%f: Име на файла (пълен път)\n"
-"%l: Времетраене (милисекунди)\n"
-"%n или %s: Име на песен\n"
-"%r: Честота (битове в секунда)\n"
-"%t: Място в списъка (%02d)\n"
-"%p: В изпълнение (1 или 0)\n"
-"%a: Изпълнител\n"
-"%b: Албум\n"
-"%T: Заглавие на запис"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Стойностите, изпратени до обвивката, е добре да са в "
-"кавички. В противен случай се крие опасност за сигурността.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Команди"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Информация за песен (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Преизчислител SoX"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3842,51 +4026,51 @@ msgstr ""
 "Базиран на приставката за промяна на честотата:\n"
 "Авторски права 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Бързо"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Ниско"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Високо"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Много високо"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Качество:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Преизчислител SoX"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Скорост и нива"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Скорост и нива</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Скорост:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Нива:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Скорост и нива"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Икона на състоянието"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Настро_йки..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3904,39 +4088,39 @@ msgstr ""
 "Тази приставка предоставя икона на състоянието, разположена\n"
 "в зоната на системните известия на мениджъра на прозорците."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Действие при превъртане с мишка</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Промяна на силата на звука"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Промяна на изпълняваната песен"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Други настройки</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Деактивиране на изскачащ прозорец"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Затваряне в системната табла"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Напред в списъка при привъртане нагоре"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Икона на състоянието"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Допълнително съзвучие"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3946,24 +4130,24 @@ msgstr ""
 "\n"
 "От Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Допълнително многозвучие</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Допълнително съзвучие"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Генератор на удари"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Хц"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Генератор на удари:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3978,15 +4162,11 @@ msgstr ""
 "frequency3;...⏎\n"
 "напр. tone://2000;2005 за изпълняването на тон от 2000 Хц и тон от 2005 Хц"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Генератор на удари"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Премахване на глас"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4024,11 +4204,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Разгодиране на Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Подробности за %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Заглавие: %t\n"
+"Автор: %a\n"
+"От: %f\n"
+"Тракер: %T\n"
+"Коментар: %C\n"
+"Тип на чипа: %c\n"
+"Стерео: %s\n"
+"Контур: %l\n"
+"Честота на чипа: %F\n"
+"Честота на плеъра: %P\n"
+"Година: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Разкодиране VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4038,19 +4253,19 @@ msgstr ""
 "На основата на in_vtx.dll от Roman Sherbakov <v_soft at microfor.ru>\n"
 "Приставка за Audacious от Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Разкодиране VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Разкодиране WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "със загуби (смесено)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "със загуби"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4060,23 +4275,18 @@ msgstr ""
 "\n"
 "Част от кода е написана от Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Разкодиране WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Разкодиране 2SF"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "Споделяеми списъци XML (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 кХц:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Настройки на XSF</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 кХц:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Игнориране на дължината от файла"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 кХц:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "Споделяеми списъци XML (XSPF)"
diff --git a/po/ca.po b/po/ca.po
index 4cba10c5f79c..402f12b3f666 100644
--- a/po/ca.po
+++ b/po/ca.po
@@ -3,16 +3,16 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Adolfo Jayme Barrientos <fitoschido at ubuntu.com>, 2013
+# Adolfo Jayme Barrientos, 2013
 # Catalanoic <catalanoic at gmail.com>, 2012
-# frangor <frangor at frangor.info>, 2013
+# Francesc Gordillo i Cortínez <inactive+frangor at transifex.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Catalan (http://www.transifex.com/projects/p/audacious/"
 "language/ca/)\n"
 "Language: ca\n"
@@ -21,51 +21,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estèreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "envoltant"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "seqüenciat"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -88,7 +72,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -110,7 +94,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -124,360 +108,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Això és l'avís per despertar-se."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Recordatori"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Dilluns"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Dimarts"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Dimecres"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Dijous"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Divendres"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Dissabte"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Diumenge"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Paràmetres de l’alarma"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Hora"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma (per defecte) a les:"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Para al cap de:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "hores"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minuts"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Trieu els dies que ha de saltar l'alarma"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Dia"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Per defecte"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dies"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Fosa"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segons"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volum"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Comença a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Ordre addicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "activa"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Llista de reproducció (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opcions"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Què signifiquen aquestes opcions?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ajuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Art del àlbum"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Sortida ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositiu PCM per defecte"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositiu de mescla per defecte"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositiu PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositiu de mescla:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Element de mescla:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Evitar penjar-se per falta de recursos"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Sortida ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "Connector AMIDI-Plug - Seleccioneu un fitxer SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nom del fitxer"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Mida (octets)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nom:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Informació MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Durada (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Num. de pistes:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div temps:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Comentaris MIDI i lletres </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* aquest fitxer MIDI no té comentaris *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* aquest fitxer MIDI no té lletra *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Tan_car"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 no vàlid)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Quant a AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -488,153 +478,147 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectangle"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectangle arrodonit"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectangle còncau"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Cap"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Inici de la reproducció"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "Activa l'OSD quan es reprodueix una entrada de la llista de reproducció"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Canvi de títol"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Activa l'OSD quan, mentre s'està reproduint, el títol de la cançó canvia "
-"però el nom del fitxer no. Això és útil per a mostrar canvis de títol en "
-"fluxos d'Internet."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pausa On"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Activa l'OSD quan la reproducció està en pausa."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pausa Off"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Activa l'OSD quan la reproducció deixa d'estar en pausa."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Posició"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Desplaçament relatiu X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Desplaçament relatiu Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Amplada màxima de l'OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opcions multi-monitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Mostra l'OSD en:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "tots els monitors"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "el monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Durada (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Visible:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Fosa entrant:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Fosa sortint:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Foses"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Fosa %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Ombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estil de representació"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colors"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Color %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Habilita activador"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Esdeveniment"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "S'ha detectat un gestor Composite"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -644,112 +628,112 @@ msgstr ""
 "tret que sapigueu que ja n'està funcionant un, activeu un gestor Composite o "
 "l'OSD no funcionarà correctament"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "La transparència simulada no requereix un gestor Composite"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparència"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparència simulada"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparència real (requereix l'ext. X composite)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "L'extensió Composite no està carregada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "L'extensió Composite no està disponible"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>OSD de l'Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - Configuració"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posició"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animació"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Text"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoració"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Llançador"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Misc"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Color</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr "Nivell de canal:"
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
-msgstr "Tallar freqüència:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "Predefinits:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr "Nivell de canal:"
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Tallar freqüència:"
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analitzador d'espectre"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Connector de Àudio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -761,169 +745,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositiu</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocitat de lectura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadades</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usa CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Usa HTTP en lloc de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Camí:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Connector de Àudio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "L’URI %s no és vàlid."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "No s’ha trobat la pista %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD d'audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "La unitat està buida."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipus de disc no admès."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reprodueix CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Afegeix CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compressió</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar volum"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Marge dinàmic:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -933,195 +904,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Baixos:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Aguts:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Durada per defecte:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Activa el remostratge d'àudio"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Taxa de remostratge:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignora la durada indicada a les etiquetes SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Incrementa la reverberació"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Descodificador musical de videoconsola"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristal·litzador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensitat:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Elimina"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancel·la"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Retard:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retorn:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volum:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
 msgstr ""
 
-#: src/echo_plugin/echo.c:122
-msgid "Echo"
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1131,55 +1127,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Format del fitxer de sortida:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configuració"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Desa al directori original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Desa a un altre directori"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Directori de sortida:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Trieu un directori"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Agafa el nom del fitxer de:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "etiquetes del fitxer originals"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nom del fitxer original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Deixa l'extensió del fitxer"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Precedeix el nom del fitxer pel nombre de pista"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1197,165 +1193,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Estèreo conjunt"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estèreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuració d'MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Qualitat de l'algoritme:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Freqüència de mostra de sortida:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Flux de bits / Ràtio de compressió:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Flux de bits (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Ràtio de compressió:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Mode d'àudio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Força el compliment estricte de l'estàndard ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Protecció d'errors"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualitat"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Activa VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipus:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opcions VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Flux de bits mínim (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Flux de bits màxim (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Compliment estricte el flux de bit mínim"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opcions ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Flux de bits mitjà (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nivell de qualitat VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Omet escriure la capçalera VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marca com a copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marca com a original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Etiquetes ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Força l'afegit d'etiquetes ID3 versió 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Només etiquetes v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Només etiquetes v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiquetes"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuració del codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nivell de qualitat (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sense pèrdues"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1363,21 +1363,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Connector GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1389,530 +1393,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analitzador d’espectre OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Dreceras del Gnome"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número d'entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Títol"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Any"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Àlbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Gènere"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posició a la cua"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Durada"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Camí del fitxer"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nom del fitxer"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Títol personalitzat"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Flux de bits"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Eina de cerca"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Acoblador a l'esquerre"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Acoblador a la dreta"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Acoblador a la part superior"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Acoblador a la part inferior"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desacoblar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Desactivar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Eina de cerca"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Obrir Fitxers..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Obrir _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Afegir fitxers..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Afegir U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Quant a..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Surt"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "Repro_duir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Pausa"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Atura"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Anterior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Següent"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Repetir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Mesclar"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "No ava_nçar la llista de reproducció"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informació de la cançó..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_Salta al temps..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Salta a la _cançó..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Per _títol"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Pel número de _pista"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Per l'_artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Per la _data"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Per nom de _fitxer"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Per títol _personalitzat"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Ordre _invers"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Ordre alea_tori"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "A_ctualitzar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordenar"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Eliminar fitxers _no disponibles"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nou"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Gestor de _cues..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "P_ujar volum"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Baixar volum"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalitzador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Mostrar barra de menú"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar barra d'_informació"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostrar barra d'_estat"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Mostra el temps _restant"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fitxer"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reproducció"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Llista de reproducció"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servei"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Sorti_da"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Veure"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Enviar/Treure de la cua"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Re_tallar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Enganxar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleccionar _tot"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfície GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Gestió de memòria intermèdia..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estèreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canals"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Mode únic"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Mode de llista de reproducció"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Parar després de la cançó."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reprodueix"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausa/Represa"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Para"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silencia"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Puja el volum"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Baixa el volum"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Activa l'OSD (sobre-impressió)"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(cap)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1924,15 +2005,11 @@ msgstr ""
 "\n"
 "Voleu continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Vinculació dels botons del ratolí"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuració del connector de tecles ràpides globals"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1940,23 +2017,27 @@ msgstr ""
 "Premeu una combinació de tecles dins del camp de text.\n"
 "També podeu vincular botons del ratolí."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Tecles ràpides:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Acció:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Vinculació de tecles:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1971,127 +2052,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr ""
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Paràmetres %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Paràmetres del servidor LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Camí de mòduls:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Connectors disponibles: "
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Activa"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Connectors habilitats:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Configuració"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: no s'ha pogut inicialitzar el suport per a LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
 msgstr ""
-"%s: no s'ha pogut llegir el firxer de configuració de LIRC\n"
-"%s: si us plau, llegiu la documentació de LIRC, per a saber\n"
-"%s: com crear un fitxer de configuració adequat\n"
 
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: tractant de reconnectar...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: ordre desconeguda \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desconnectat del LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: s'intentarà reconnectar cada %d segons...\n"
-
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2107,73 +2151,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Reconnecta amb el servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Error"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Error"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Generador de compassos: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generador de compassos: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2182,162 +2234,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canals de sortida:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
 msgstr ""
 
-#: src/mms/mms.c:195
-msgid "MMS Plugin"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resolució</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8 bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Nivell:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Reducció de soroll"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repeteix</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Comptatge de repeticions:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Per repetir indefinidament, definiu el nombre a -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "So envolvent"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "So envolvent"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Aturat"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious no està reproduint."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2357,55 +2441,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Mostra"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausa"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Següent"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositiu per defecte"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositiu d'àudio:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Usa un dispositiu alternatiu:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Activar conversions de format realitzades pel programari OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2414,19 +2507,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2446,143 +2555,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repeteix"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Barreja"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertidor de taxa de mostratge"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolació lineal"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversió</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Mètode:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Taxa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22,05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44,1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertidor de taxa de mostratge"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Hi ha un problema de xarxa."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2593,93 +2771,72 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteca"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista desconegut"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Àlbum desconegut"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" a %s per %s"
-
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d àlbum"
-msgstr[1] "%d àlbums"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d cançó"
 msgstr[1] ""
-"%s\n"
-" %s, %d cançons"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crear llista de reproducció"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Afegir a la llista de reproducció"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Cercar biblioteca"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2687,679 +2844,769 @@ msgstr ""
 "Per importar la vostra col·lecció musical en l’Audacious, trieu una carpeta "
 "i feu clic a la icona «Actualitza»."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Esperi si us plau..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Seleccioneu un directori"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reproducció"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Llistes"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Finestres"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repeteix"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Barreja"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Discontinua la reproducció programada"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Llista de reproducció nova"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostra l'editor de llistes"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostra l'equalitzador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Sempre per sobre"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Per títol"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Per nom de fitxer"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Treu tots els elements"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Neteja la cua"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Treu els fitxers no disponibles"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Treu els duplicats"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Treu els no seleccionats"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Treu els seleccionats"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Cerca i selecciona"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverteix la selecció"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Selecciona no res"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Selecciona tots els elements"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Per àlbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Pel número de pista"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Per l'artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Per àlbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Pel número de pista"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Barreja la llista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Inverteix la llista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordena els seleccionats"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordena la llista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Retallar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Enganxar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interfície del Winamp clàssic"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Desa"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Carrega"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Perfils"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Carrega un perfil"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Carregar auto-predefinit"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Desa el perfil"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Desar auto-predefinit"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Esborra el perfil"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Suprimir auto-predefinit"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Reproductor:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Trieu la fosa de la finestra principal:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Llista de reproducció:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Trieu la fosa de la llista de reproducció:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Utilitzar tipografies de mapa de bits (nomes suporta ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Desplaçar el títol de la cançó en ambdues direccions "
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analitzador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Oscil·loscopi"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Apagat"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Foc"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Línies"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barres"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Mínim"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lent"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Mitjà"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Ràpid"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Al màxim"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Gel"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suau"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "General"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualització"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificació"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Equalitzador de l'Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Anar a la posició %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volum: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balanç: %d%% esquerra"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balanç: centrat"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balanç: %d%% dreta"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menú d'opcions"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desactiva 'Sempre per sobre'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Activa 'Sempre per sobre'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Informació del fitxer"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Mode únic"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Mode de llista de reproducció"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Parar després de la cançó."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Cerca elements en la llista de reproducció activa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3371,57 +3618,61 @@ msgstr ""
 "insensibles a la capitalització. Si no sabeu com funcionen les expressions "
 "regulars, podeu escriure literalment el text que busqueu."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Títol: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Àlbum:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nom del fitxer: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Neteja la selecció anterior abans de cercar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Posa o treu de la cua automàticament els elements trobats"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Crea una llista de reproducció nova amb els elements trobats"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de llistes de l'Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Decoració del Winamp 2.x arxivada"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Decoració del Winamp 2.x no arxivada"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "No s'ha pogut crear el directori (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3443,78 +3694,72 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "D’acord"
-
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Canvi de cançó"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Ordre a executar quan l'Audacious comença una nova cançó."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Els paràmetres passats a la shell s'han d'encapsular "
+"entre\n"
+"cometes. Altrament seria un risc per a la seguretat.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Ordre:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Ordre a executar cap al final de la cançó."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
-"Ordre a executar quan l'Audacious arriba al final de la llista de "
-"reproducció."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Ordre a executar quan canvia el títol d'una cançó (en fluxos de xarxa)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3529,20 +3774,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Els paràmetres passats a la shell s'han d'encapsular "
-"entre\n"
-"cometes. Altrament seria un risc per a la seguretat.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Ordres"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3551,51 +3791,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Ràpida"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Baixa"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alta"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Molt alta"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualitat:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocitat:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icona d’estat"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3606,63 +3846,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Canvia el volum"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Canvia la cançó"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desactiva la finestra emergent"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Tanca a la safata del sistema"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icona d’estat"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generador de tons:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3671,15 +3911,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3700,44 +3936,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "amb pèrdues (híbrid)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "amb pèrdues"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/cmn.po b/po/cmn.po
index f1d4192fbb81..6b073935dc15 100644
--- a/po/cmn.po
+++ b/po/cmn.po
@@ -4,14 +4,14 @@
 #
 # Translators:
 # Ruei-Yuan Lu <RueiYuan.Lu at gmail.com>, 2011
-# Wei-Lun Chao <bluebat at member.fsf.org>, 2013
+# 趙惟倫 <bluebat at member.fsf.org>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Chinese (Mandarin) (http://www.transifex.com/projects/p/"
 "audacious/language/cmn/)\n"
 "Language: cmn\n"
@@ -20,40 +20,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "單聲道"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "立體聲"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "環繞"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib 播放器)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "編曲機"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib 播放器)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "鬧鐘"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +51,7 @@ msgstr ""
 "\n"
 "原本是由 Adam Feakin 與 Daniel Stodden 編寫。"
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "鬧鐘"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -108,7 +92,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -148,7 +132,7 @@ msgstr ""
 "    鬧鐘觸發時執行這個指令。\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -172,384 +156,371 @@ msgstr ""
 "    若您希望它被顯示,請勾選並在欄\n"
 "    位中輸入訊息。"
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "這是您的喚醒。"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "您今天的提醒"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "提醒"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "星期一"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "星期二"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "星期三"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "星期四"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "星期五"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "星期六"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "星期日"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "鬧鐘設定"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "時間"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "鈴響於 (預設)"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "多久後靜音:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "小時"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "分鐘"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "選擇想要在哪幾天啟用鬧鐘"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "哪幾天"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "預設"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "週排程"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "淡出"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "秒"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "音量"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "初始音量"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "最終音量"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "目前音量"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "額外命令"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "啟用"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "播放列表 (選用)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "請選擇播放列表"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "選項"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "這些選項代表什麼意思?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "說明"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "專輯封面"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA 輸出"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Audacious 的 ALSA 輸出外掛程式\n"
+"著作權 2009-2012 John Lindgren\n"
+"\n"
+"感謝 William Pitcock,他是新一代 ALSA 輸出外掛程式的作者。當 ALSA 手冊有不足"
+"時,會以其程式碼做為參考。"
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "預設 PCM 裝置"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "預設混音器裝置"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM 裝置:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "混音器裝置:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "混音器元件:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "處理欠載鎖死"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI 播放器)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"Audacious 的 ALSA 輸出外掛程式\n"
-"著作權 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"感謝 William Pitcock,他是新一代 ALSA 輸出外掛程式的作者。當 ALSA 手冊有不足"
-"時,會以其程式碼做為參考。"
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA 輸出"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI 播放器)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - 選擇 SoundFont 檔案"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "檔案名稱"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "大小 (位元組)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "名稱:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI 資訊 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "格式:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "長度 (毫秒):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "音軌編號:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "變動的"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "時間分割:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI 備註與歌詞 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* 這個 MIDI 檔不包含備註資料 *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* 這個 MIDI 檔不包含歌詞資料 *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "關閉(_C)"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (無效的 UTF-8 字串)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "關於 AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"模組化 MIDI 音樂播放器\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"由 Giacomo Lozito 編寫\n"
-"<james at develia.org>\n"
-"\n"
-"特別感謝…\n"
-"\n"
-"Clemens Ladisch 與 Jaroslav Kysela\n"
-"所提供的軟體 aplaymidi 與 amixer;它們\n"
-"以及搭配的 alsa-lib 文件相當有助於\n"
-"更加瞭解 ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"所提供不錯的 midi 鍵盤圖標\n"
-"\n"
-"Tony Vroon\n"
-"所提供有用的測試協助"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -560,150 +531,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Audacious OSD)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "矩形"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "圓角矩形"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "角落凹陷的矩形"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "ç„¡"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "開始播放"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "當播放列表中的項目被播放時觸發 OSD"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "標題變更"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"當播放中歌曲標題改變但檔名不變時觸發 OSD。這對顯示網路串流的標題很有用。"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "暫停播放"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "當播放暫停時觸發 OSD"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "解除暫停"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "當解除暫停時觸發 OSD"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "放置位置"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X 軸相對位移:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y 軸相對位移:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "最大 OSD 寬度:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "多螢幕選項"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "顯示 OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "所有螢幕"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "螢幕 %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "計時 (毫秒)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "顯示:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "淡入:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "淡出:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "å­—åž‹"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "字型 %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "é™°å½±"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "呈現樣式"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "顏色"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "顏色 %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "啟用觸發器"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "事件"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "已偵測到合成特效管理程式"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -712,112 +679,112 @@ msgstr ""
 "未偵測到合成特效管理程式;\n"
 "除非您確定已經執行,否則 OSD 將無法正確啟用。"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "假的透明特效不需要 Composite manager"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "透明"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "假的透明特效"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "真的透明特效 (需要 X Composite 延伸功能)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite 延伸功能未載入"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite 延伸功能不存在"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - 設定"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "å‹•ç•«"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "文字"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "裝飾"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "觸發"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "雜項"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 播放列表"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious 播放列表 (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>色彩</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "模糊波形"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "樣式"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "饋送等級:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "截斷頻率:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "樣式"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "頻譜分析儀"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "音樂 CD 外掛程式"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -837,171 +804,156 @@ msgstr ""
 "\n"
 "這是 Google Summer of Code 2007 專案之一。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>裝置</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "讀取速度:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "覆載裝置:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>詮釋資料</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "使用 CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "使用 CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "使用 HTTP 而非 CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "伺服器:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "路徑:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "通訊埠:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "音樂 CD 外掛程式"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "無法初始化 cdio 子系統。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "無效的 URI %s。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "找不到音軌 %d。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "軌道 %d 是資料軌。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "無法開啟音訊輸出。"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "讀取音樂 CD 時發生錯誤。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "音樂 CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "無法開啟 CD 裝置 %s。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "找不到可以播放音訊的光碟機。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "開啟的光碟機無法完成初始化。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "無法取得第一個或最後的音軌編號。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "無法讀取音軌 %d 的起始/結束邏輯磁區編號。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "無法建立 cddb 的連線。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "無法查詢 CDDB 伺服器"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "無法查詢 CDDB 伺服器:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "無法讀取 cddb 資訊:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "光碟機是空的。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "未支援的光碟類型"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "音樂 CD 選單項目"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "播放 CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "加入 CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "音樂 CD 選單項目"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>壓縮</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "中央音量:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "動態範圍:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Audacious 的動態範圍壓縮外掛程式\n"
-"著作權 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "動態範圍壓縮"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1017,205 +969,224 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "低音"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "高音"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "預設歌曲長度:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>重取樣</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "啟用聲音重取樣"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "重取樣率"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "忽略 SPC 標籤裡記錄的長度"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "增加回音"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "遊戲主機音樂解碼器"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"因為歌曲間的聲道數不同,無法使用 Crossfade。您可以使用聲道混合將歌曲轉換至相"
-"同的聲道數量。"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"淡入淡出失敗,因為歌曲間的取樣率不同。您可以使用取樣率轉換功能來取得相同的取"
-"樣率。"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Audacious 的淡入淡出外掛程式\n"
-"著作權 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>淡入淡出</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "重疊:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "淡入淡出"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"因為歌曲間的聲道數不同,無法使用 Crossfade。您可以使用聲道混合將歌曲轉換至相"
+"同的聲道數量。"
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"淡入淡出失敗,因為歌曲間的取樣率不同。您可以使用取樣率轉換功能來取得相同的取"
+"樣率。"
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "效果強度:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet 外掛程式"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "刪除"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "取消"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>回音</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "延遲:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "毫秒"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "反饋:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "音量:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"回音外掛程式\n"
-"ç”± Johan Levin, 1999\n"
-"\n"
-"環繞回音是由 Carl van Schaik, 1999 編寫"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "回音"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg 外掛程式"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1231,55 +1202,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg 外掛程式"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "檔案輸出外掛程式"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "輸出檔案格式:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "設定"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "儲存到原始資料夾"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "儲存到自訂資料夾"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "輸出檔案資料夾:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "選擇一個資料夾"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "檔名來源:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "原始檔案標籤"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "原始檔名"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "不要去掉副檔名"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "在檔名前面加上音軌號碼"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1311,165 +1282,169 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "檔案輸出外掛程式"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "自動"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "聯合立體聲"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "立體聲"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "單聲道"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 設定"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "演算法品質:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "輸出取樣率:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "位元率/壓縮比率:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "位元率 (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "壓縮比率:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "音訊模式:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "雜項:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "強制嚴格相容於 ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "錯誤保護"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "品質"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "啟用 VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "類型:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR 選項:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "最小位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "最大位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "強制使用最小位元率"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR 選項:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "平均位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR 品質等級:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "不要寫入 Xing VBR 檔頭"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "音框參數:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "標示為著作權"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "標示為原創"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 參數:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "強制加入第二版標籤"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "只加入第一版標籤"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "只加入第二版標籤"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "標籤"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis 編碼器設定"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "品質等級 (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC 解碼器"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "無損"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1481,11 +1456,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC 解碼器"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1493,11 +1464,19 @@ msgstr ""
 "Audacious 的 GIO 外掛程式\n"
 "著作權 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO 外掛程式"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1509,533 +1488,606 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL 頻譜分析儀"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
-msgstr ""
-"Gnome 快捷鍵外掛程式\n"
-"讓您控制播放器與 Gnome 的快捷鍵。\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
 "\n"
-"著作權©2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"License: GPLv2+"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome 快捷鍵"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "項目編號"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "標題"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "演出者"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "年分"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "專輯"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "音軌"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "é¡žåž‹"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "佇列位置"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "長度"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "檔案路徑"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "檔案名稱"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "自訂標題"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "位元率"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "搜尋工具"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "嵌入左方"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "嵌入右方"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "嵌入頂端"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "嵌入底端"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "解除嵌入"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "關閉"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "搜尋工具"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "開啟檔案(_O)…"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "開啟網址(_U)…"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "加入檔案(_A)… "
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "加入網址(_R)…"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "關於(_B)…"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "離開(_Q)"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "播放(_P)"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "暫停(_E)"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "停止(_S)"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "上一首(_V)"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "下一首(_N)"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "重複"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "隨機"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "不要切換播放列表"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "播放完目前歌曲後停止(_F)"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "歌曲資訊(_I)…"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "跳至時間(_T)…"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "跳至歌曲(_J)…"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "設定重複點 _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "設定重複點 _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "清除重複點(_C)"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "標題(_T)"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "檔案名稱(_F)"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "檔案路徑(_P)"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "音軌編號(_N)"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "演出者(_A)"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "專輯(_B)"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "釋出日期(_D)"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "長度(_L)"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "檔案路徑(_F)"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "自訂標題(_C)"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "反向順序(_E)"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "隨機順序(_R)"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "播放此列表(_P)"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "重新整理(_R)"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "排序(_S)"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "排序所選(_L)"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "移除重複的項目(_D)"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "移除不存在的檔案(_U)"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "新增(_N)"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "重新命名(_A)…"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "匯入(_I)…"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "匯出(_E)…"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "播放列表管理(_M)…"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "佇列管理(_Q)…"
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "提高音量(_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "降低音量(_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "等化器(_E)"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "顯示選單列(_M)"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "顯示資訊列(_N)"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "顯示資訊列的視覺特效(_U)"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "顯示狀態列(_S)"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "顯示剩餘時間(_R)"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "檔案(_F)"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "播放(_P)"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "播放列表(_L)"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "服務(_S)"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "輸出(_O)"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "檢視(_V)"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "排入/移出佇列(_Q)"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "剪下(_T)"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "拷貝(_C)"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "貼上(_P)"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "選擇全部(_A)"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "重新命名(_R)…"
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>其他選項</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK 介面"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "緩衝中…"
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "單聲道"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "立體聲"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d 聲道"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "單一模式。"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "播放列表模式。"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "播放完成後停止。"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "上一個音軌"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "播放"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "暫停/回復"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "停止"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "下一個音軌"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "快轉五秒"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "倒轉五秒"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "靜音"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "提高音量"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "降低音量"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "跳至檔案"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "切換顯示播放器視窗"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "顯示 OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "切換重複播放"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "切換隨機播放"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "播放完目前歌曲後停止"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "將播放器視窗放到最上層"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ç„¡)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2046,15 +2098,11 @@ msgstr ""
 "\n"
 "您想要繼續嗎?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "綁定滑鼠按鈕"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "全域熱鍵外掛設定"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2062,23 +2110,27 @@ msgstr ""
 "請在輸入欄位中按下想要的按鍵組合。\n"
 "您也可以綁定滑鼠按鈕。"
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "熱鍵:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>動作:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>按鍵綁定:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "全域熱鍵"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2104,60 +2156,51 @@ msgstr ""
 " Jonathan A.Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "全域熱鍵"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK 輸出"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"基於 xmms-jack,由 Chris Morgan 編寫:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"由 Giacomo Lozito 移植到 Audacious"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK 輸出"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s 設定"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA 主控端設定"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "模組路徑:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2167,25 +2210,25 @@ msgstr ""
 "系統除了 LADSPA_PATH 之外也會搜尋這些路徑。\n"
 "加入新路徑之後請按 Enter 掃描新的外掛。</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "可用的外掛:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "啟用"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "啟用外掛:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "設定"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2193,47 +2236,15 @@ msgstr ""
 "Audacious 的 LADSPA 主控端\n"
 "著作權 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA 主控端"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s:無法初始化 LIRC 支援\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s:無法讀取 LIRC 組態檔\n"
-"%s:請閱讀 LIRC 的相關文件\n"
-"%s:如何建立一個適合的組態檔\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s:嘗試重新連線中…\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s:不明的命令「%s」\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s:已從 LIRC 離線\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s:將每 %d 秒嘗試重新連線一次…\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Linux 紅外線遙控器外掛程式"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2261,73 +2272,81 @@ msgstr ""
 "\n"
 "要獲得更多 LIRC 的相關資訊,請參看 http://lirc.org。"
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>連線</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "重新連線至 LIRC 伺服器"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "重新連線前的等待時間:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Linux 紅外線遙控器外掛程式"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki 歌詞外掛程式"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "無可用的歌詞"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "錯誤"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "無法取得 %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "錯誤"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "無法分析 %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "尋找歌詞中…"
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "找不到歌曲詮釋資料"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "連線至 lyrics.wikia.com 中…"
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki 歌詞外掛程式"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U 播放列表"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "節拍產生器"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "節拍產生器:%d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "節拍產生器:%d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2341,11 +2360,11 @@ msgstr ""
 "範例:tact://77 播放 77 BPM\n"
 "或 tact://60*3/4 以 3/4 拍播放 60 BPM"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "節拍產生器"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "聲道混合"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2353,152 +2372,184 @@ msgstr ""
 "Audacious 的頻道混音器外掛程式\n"
 "著作權 2011-2012 John Lindgren 與 Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>聲道混合</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "輸出聲道數目:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "聲道混合"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS 外掛程式"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (MOD 播放器)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>解析度</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>聲道</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "最近點取樣(最快)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "線性取樣(快)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "曲線函數(佳)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "多相位取樣(最佳)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>取樣率</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "強度:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "裁切:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>回音</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>重低音強化</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>環繞音效</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>前置放大</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "超取樣"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "降噪"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "播放 Amiga MOD 檔案"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>重複</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "重複次數:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "將重複次數設定為 -1 表示永遠重複播放。"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (MOD 播放器)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "環繞"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 外掛程式"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "環繞"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 伺服器"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS 外掛程式"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "已停止"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious 非播放中。"
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "桌面通知"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2531,55 +2582,64 @@ msgstr ""
 "您應該已經收到隨附於這個程式的 GNU 通用公共授權拷貝。 如果沒有,請參看 "
 "<http://www.gnu.org/licenses/>。"
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "顯示播放控制元件"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "永遠顯示通知"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "桌面通知"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "顯示"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "暫停"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "下一個"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1。預設裝置"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 輸出"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "音訊裝置:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "使用替代裝置:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "儲存不同工作階段的音量。"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "啟用格式轉換 (使用 OSS 軟體)。"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "啟用獨占模式以防止虛擬混音。"
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2587,25 +2647,41 @@ msgid ""
 "I would like to thank people on #audacious, especially Tony Vroon and John "
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
-"Audacious 的 OSS4 輸出外掛程式\n"
-"著作權 2010-2012 Michał Lipski\n"
-"\n"
-"我想要謝謝 #audacious 上的人們,特別是 Tony Vroon 與 John Lindgren,當然還有"
-"前一個 OSS 外掛程式的作者。"
+"Audacious 的 OSS4 輸出外掛程式\n"
+"著作權 2010-2012 Michał Lipski\n"
+"\n"
+"我想要謝謝 #audacious 上的人們,特別是 Tony Vroon 與 John Lindgren,當然還有"
+"前一個 OSS 外掛程式的作者。"
+
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 輸出"
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS 播放列表"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 解碼器"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio 輸出"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2641,11 +2717,68 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio 輸出"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "上一個"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "重複"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "隨機"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "取樣率轉換"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2653,96 +2786,104 @@ msgstr ""
 "Audacious 的取樣率轉換器外掛程式\n"
 "著作權 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "跳過/重複取樣"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "線性內插"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "快速 sinc 內插"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "中等 sinc 內插"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "最佳 sinc 內插"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>轉換</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "演算法:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "取樣率:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>取樣率映射</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "使用取樣率映射"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "取樣率轉換"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "確認。上傳使用者 %s 的播放資訊"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "存取被拒"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "點選下列鏈結允許 Audacious 上傳您的播放資訊:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "請保持這個視窗的開啟並再次點選「檢查權限」。\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2750,32 +2891,36 @@ msgstr ""
 "別擔心。您的資訊已經儲存在電腦上。\n"
 "Audacious 會在狀況允許下盡快地將它們上傳。"
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "網路發生問題。"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "存取 Last.fm 時發生問題。請稍候再試。"
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "檢查中…"
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "檢查權限(_H)"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "撤銷授權(_R)"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "您需要允許 Audacious 上傳音軌的播放資訊至您的 Last.fm 帳號。\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2783,7 +2928,7 @@ msgstr ""
 "無法啟動 Scrobbler 外掛。\n"
 "您的安裝可能有些問題。"
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2800,11 +2945,7 @@ msgstr ""
 "感謝 John Lindgren 在這個專案的開頭助我一臂之力。\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2812,7 +2953,11 @@ msgstr ""
 "Audacious 現在使用改良版的 Last.fm 播放資訊上傳功能。\n"
 "請參閱偏好設定中的播放資訊外掛。"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL 輸出"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2820,753 +2965,822 @@ msgstr ""
 "Audacious 的 SDL 輸出外掛程式\n"
 "著作權 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL 輸出"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "媒體櫃"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "不明的演出者"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "不明的專輯"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" 於「%s」由「%s」演唱"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d 張專輯"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s,%d 首歌曲"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d 首歌曲由「%s」演唱"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "建立播放列表(_C)"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "加入至播放列表(_A)"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "搜尋媒體櫃"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 "要將您的媒體櫃匯入至 Audacious,請選擇目標資料夾並且按下「重新整理」圖示。"
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "請稍候…"
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "選擇資料夾"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "播放"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "播放列表"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "檢視"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "重複"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "隨機"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "不要切換播放列表"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "上一個"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "新增播放列表"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "顯示播放列表編輯器"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "顯示等化器"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "永遠在最上層"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "標題"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "檔案名稱"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "全部移除"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "清除佇列"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "移除無法使用的檔案"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "移除重複的項目"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "移除未選擇的項目"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "移除選擇的項目"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "搜尋並選擇"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "反向選擇"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "取消選擇"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "選擇全部"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "專輯"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "音軌編號"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "演出者"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "專輯"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "音軌編號"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "列表隨機排序"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "列表反向排序"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "排序選擇的項目"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "排序列表"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "剪下"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "拷貝"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "貼上"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp 傳統介面"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "儲存"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "載入"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "樣式"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "載入樣式"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "讀取自動載入樣式"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "儲存樣式"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "儲存自動載入樣式"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "刪除樣式"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "刪除自動載入樣式"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "播放器(_P):"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "選擇播放器主視窗字型:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "播放列表(_P):"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "選擇播放列表字型:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "使用點陣字型 (只支援 ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "雙向捲動歌曲標題"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "分析儀"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "示波器"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "關閉"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "標準"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "火焰"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "線條"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "棒狀"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "最慢"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "æ…¢"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "中等"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "å¿«"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "最快"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "冰霜"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "平滑"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "一般"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "視覺特效"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "前置放大"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious 等化器"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "移動至 %d:%-2.2d/%d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "音量:%d%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "平衡:%d% 偏左"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "平衡:中間"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "平衡:%d% 偏右"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "選單選項"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "關閉置頂"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "啟用置頂"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "檔案資訊視窗"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "已設定重複點 A。"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "已設定重複點 B。"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "已清除重複點。"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "單一模式。"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "播放列表模式。"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "播放完成後停止。"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "在使用中的播放列表裡搜尋播放項目"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3576,57 +3790,61 @@ msgstr ""
 "填入一個或多個欄位以選擇播放列表中的項目。欄位使用正規表示法,大小寫視為不同"
 "字元。若您不知道如何使用正規表示法,請輸入您想搜尋的部分文字。"
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "標題:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "專輯:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "演出者:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "檔名:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "進行搜尋前清空上次的選擇項目"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "自動切換至符合項目的佇列"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "以符合的項目建立新的播放列表"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious 播放列表編輯器"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d/%d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "壓縮的 Winamp 2.x 面板"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "未壓縮的 Winamp 2.x skin"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "無法建立資料夾 (%s):%s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile 外掛程式"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3664,81 +3882,71 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile 外掛程式"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "關於 Sndio 輸出外掛程式"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio 輸出外掛\n"
-"\n"
-"作者:Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "未支援的格式"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"要求了未被音訊裝置支援的格式。\n"
-"\n"
-"請確認 sndiod(1) 伺服器已執行後重試。"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio 裝置"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(空白表示使用預設值)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "確認"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "歌曲切換"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "當 Audacious 開始播放新的歌曲時執行的指令。"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>傳給 shell 的參數應該用雙引號包起來,否則會有安全風險。</"
+"span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "命令:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "每當一首歌曲播放完時執行命令"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "每當 Audacious 播放達到列表尾端時執行命令"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "當一首歌的標題改變時執行命令。(網路串流的標題)"
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3752,35 +3960,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"您可以在命令中使用下列的格式字串。\n"
-"它們會在執行命令前被實際值取代。\n"
-"(不是全部都能在播放列表結束命令中使用)\n"
-"\n"
-"%F:頻率 (赫茲)\n"
-"%c:聲道數目\n"
-"%f:檔名 (完整路徑)\n"
-"%l:長度 (毫秒)\n"
-"%n 或 %s:歌曲名稱\n"
-"%r:位元率 (bps)\n"
-"%t:播放列表位置 (%02d)\n"
-"%p:播放中 (1 或 0)\n"
-"%a:演出者\n"
-"%b:專輯\n"
-"%T:音軌標題"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>傳給 shell 的參數應該用雙引號包起來,否則會有安全風險。</"
-"span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "命令"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX 重取樣"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3794,51 +3983,51 @@ msgstr ""
 "基於取樣率轉換器外掛程式:\n"
 "著作權 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "快速"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "低"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "高"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "非常高"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "品質:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX 重取樣"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "速度與音高"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>速度與音高</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "速度:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "音高:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "速度與音高"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "狀態圖示"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3855,39 +4044,39 @@ msgstr ""
 "\n"
 "這個外掛提供一個狀態圖示並放在系統通知區。"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>滑鼠滾輪動作</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "調整音量"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "切換播放歌曲"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>其他設定</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "關閉彈出式視窗"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "縮到系統列"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "以與滑鼠滾輪的反方向切換歌曲"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "狀態圖示"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "額外立體聲效果"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3897,24 +4086,24 @@ msgstr ""
 "\n"
 "由 Johan Levin,1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>額外立體聲效果</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "額外立體聲效果"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "音調產生器"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "音調產生器:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3928,15 +4117,11 @@ msgstr ""
 "用法:加入網址:tone://frequency1;frequency2;frequency3;…\n"
 "範例:tone://2000;2005 會播放 2000 HZ 和 2005HZ 的正弦波"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "音調產生器"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "人聲移除"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3974,11 +4159,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis 解碼器"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX 解碼器"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -3988,19 +4197,19 @@ msgstr ""
 "基於 invtx(_V).dll 編寫自 Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious 外掛程式編寫自 Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX 解碼器"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack 解碼器"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "失真 (混合)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "失真"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4010,14 +4219,18 @@ msgstr ""
 "\n"
 "其中一些外掛程式碼是由 Miles Egan 編寫。"
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack 解碼器"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF 解碼器"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML 可分享式播放列表 (XSPF)"
diff --git a/po/cs.po b/po/cs.po
index 4b635dbd4a9b..a3748995fb45 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -3,21 +3,24 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# jui <appukonrad at gmail.com>, 2012-2013
+# Jiří Vírava <appukonrad at gmail.com>, 2012-2013
 # Based on audacious-1.2.2.cs.po by Jan Nárovec <finn at sendmail.cz>, 2004
 # fri, 2012-2013
+# nd76er <nd76er at gmail.com>, 2014
+# nd76er <nd76er at gmail.com>, 2014-2015
+# fri, 2014
 # fri, 2012
 # Petr Pisar <petr.pisar at atlas.cz>, 2007-2012
-# petr.simacek <petr.simacek at gmail.com>, 2012
-# petr.simacek <petr.simacek at gmail.com>, 2012
-# petr.simacek <petr.simacek at gmail.com>, 2013
+# Petr Šimáček <petr.simacek at gmail.com>, 2012
+# Petr Šimáček <petr.simacek at gmail.com>, 2012
+# Petr Šimáček <petr.simacek at gmail.com>, 2013-2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-02-27 10:53+0000\n"
+"Last-Translator: nd76er <nd76er at gmail.com>\n"
 "Language-Team: Czech (http://www.transifex.com/projects/p/audacious/language/"
 "cs/)\n"
 "Language: cs\n"
@@ -26,40 +29,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "prostorový zvuk"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
-
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
-msgid "sequenced"
-msgstr "Sekvencován"
+msgstr "AAC (Raw) dekodér"
 
-#: src/adplug/plugin.c:14
+#: src/adplug/adplug-xmms.cc:42
 msgid "AdPlug (AdLib Player)"
 msgstr "AdPlug (AdLib přehrávač)"
 
-#: src/alarm/alarm.c:778
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "seřazen"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Budík"
+
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Nastavit budík"
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -69,11 +60,7 @@ msgstr ""
 "\n"
 "Původně napsal Adam Feakin a Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Budík"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -95,8 +82,25 @@ msgid ""
 "\n"
 "\n"
 msgstr ""
+"ÄŒas\n"
+"Budit v:\n"
+"Čas pro spuštění budíku.\n"
+"\n"
+"Ticho po:\n"
+"Zastavit budík po nastaveném čase.\n"
+"(jestliže dialog probuzení není zavřený)\n"
+"\n"
+"\n"
+"Dny\n"
+" Den:\n"
+"Nastavit dny, v kterých se má budík spouštět.\n"
+"\n"
+" ÄŒas:\n"
+"Vybrat čas budíku na každý den nebo zaškrtnout tlačítko pro  použití "
+"standardního času.\n"
+"\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -118,7 +122,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -131,366 +135,381 @@ msgid ""
 "    Type the reminder in the box and turn on the\n"
 "    toggle button if you want it to be shown."
 msgstr ""
+"Seznam skladeb:\n"
+"Nahraj tento seznam skladeb. Jestliže není\n"
+"žádný dán,  bude použit aktuální.\n"
+"URL mp3/ogg proudu se zde může také vložit.\n"
+"\n"
+"Upomínka:\n"
+"Zobraz upomínku, když se budík vypne.\n"
+"Napiš upomínku do rámečku a zapni přepínací tlačítko, \n"
+"jestli chceš aby se zobrazovala."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Toto je váš budící signál."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Vaše připomínka pro dnešek je..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Upomínání"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Pondělí"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Úterý"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Středa"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "ÄŒtvrtek"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Pátek"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sobota"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Neděle"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Nastavení budíku"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "ÄŒas"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Budit v (standardní):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Ticho po:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "h"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "min"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Vyberte dny, kdy má budík budit"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Den"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Standardní"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dny"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Zesilování"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekund"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Hlasitost"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Začít na"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Skončit na"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Současná"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Dodatečný příkaz"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "zapnout"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Seznam skladeb (volitelné)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Vybrat seznam skladeb"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Nastavení"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Co tyto volby znamenají?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Nápověda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Album"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Obal alba (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA výstup:"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA výstupní modul pro Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Mé díky patří Williamu Pitcockovy, autoru výstupního ALSA Zásuvného modulu "
+"NG, jehož kód sloužil jako reference, když použití ALSA mauálu nestačilo."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Implicitní PCM zařízení"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Implicitní směšovací zařízení"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Zařízení PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Zařízení směšovače:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Prvek směšovače:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Obejít zaseknutí při vyprazdňovaní"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI přehrávač)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"ALSA výstupní modul pro Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Mé díky patří Williamu Pitcockovy, autoru výstupního ALSA Zásuvného modulu "
-"NG, jehož kód sloužil jako reference, když použití ALSA mauálu nestačilo."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA výstup:"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI přehrávač)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Potlačit výchozí zesílení:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Potlačit výchozí vícehlas:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Potlačit výchozí dozvuk:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "On"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Potlačit výchozí sbor:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Playback</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
-msgstr ""
+msgstr "Transponovat: "
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "půltóny"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
-msgstr ""
+msgstr "Posun bubnu: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "čísla poznámek"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Přeskočit ticho na začátku"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Přeskočit ticho na konci"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Synthesizer</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Vzorkovací frekvence:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug – vyberte soundfontový soubor"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Zrušit"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Otevřít"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Jméno souboru"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Název souboru"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Velikost (v bajtech):"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Jméno:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"small\"> Podrobnosti o MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formát:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Délka (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "č. skladby"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "proměnlivé"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (váž.):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "ÄŒas. pom.:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"small\"> Komentáře a text MIDI skladby </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* v MIDI souboru se nenachází žádné komentáře *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* v MIDI souboru se nenachází text skladby *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Zavřít"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (neplatné UTF8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "O AMIDI-Pluginu"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -501,152 +520,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Obdélník"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Zaoblený obdélník"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Konkávní obdélník"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Žádný"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Zahájení přehrávání"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Spustí OSD, když se začne přehrávat skladba."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Změna názvu"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Spustí OSD, když se během přehrávaní změní název skladby, ale jméno souboru "
-"je stále stejné. To se hodí při přehrávání internetových proudů, v nichž se "
-"střídají skladby."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pozastavení"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Spustí OSD, když je přehrávání pozastaveno."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Obnovení přehrávání"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Spustí OSD, když přehrávání obnoveno."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Umístění"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relativní odsazení ve směru osy X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relativní odsazení ve směru osy Y"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maximální šířka OSD"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Nastavení pro více monitorů"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Zobrazit OSD na:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "všech monitorech"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitoru %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Časování (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Zobrazení:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Rozsvícení:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Pohasnutí:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Fonty"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Font %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Stín"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Styl vyobrazení"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Barvy"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Barvy %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Povolit spouštěč"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Událost"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Nalezen kompozitní správce"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -656,112 +669,112 @@ msgstr ""
 "Pokud nevíte, že byste jste již nějakého spustili, prosím, aktivujte "
 "kompozitního správce, jinak OSD nebude správně fungovat."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Při falešné průhlednosti není kompozitní správce potřeba"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Průhlednost"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Falešná průhlednost"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Skutečná průhlednost (vyžaduje kompozitní rozšíření X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Kompozitní rozšíření není nahráno"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Kompozitní rozšíření není dostupné"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>OSD Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "OSD pro Audacious – nastavení"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Umístění"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animace"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Text"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Výzdoba"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Spouštěč"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Různé"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Zkouška"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "Seznamy skladeb ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 seznamy skladeb"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious seszam skladeb (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Barva</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Rozsah rozostření"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Předvolby:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Úroveň přeslechu:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Ořezová frekvence:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Předvolby:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analyzátor spektra"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD Plugin"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -772,170 +785,165 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
+"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> a další.\n"
+"\n"
+"Hodně díků patří libcdio vývojářům <http://www.gnu.org/software/libcdio/>\n"
+"a libcddb vývojářům <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Také děkujeme Tony Vroon za mentorování a směrování.\n"
+"\n"
+"Toto byl projekt v rámci Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Zařízení</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Rychlost čtení:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Přepsat zařízení:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadata</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Použití CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Používat CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Použít HTTP místo CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Cesta:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD Plugin"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Nepodařilo se inicializovat cdio subsystému."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Neplatná URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Stopa %d nebyla nalezena."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Stopa %d je datová stopa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Nelze otevřít zvukový výstup"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Chyba při čtení zvukového CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Zvukové CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Nelze otevřít CD zařízení %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Nebyly nalezeny funkční CD mechaniky"
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Nepodařilo se dokončit inicializaci otevření CD mechaniky."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Nepodařilo se načíst první/poslední číslo skladby."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "nelze přečíst začátek/konec LSN pro skladbu %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Nepodařilo se vytvořit připojení k CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Nepodařil se dotaz na server CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Nepodařil se dotaz na server CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Nepodařilo se přečíst cddb info: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Mechanika je prázdná"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nepodporovaný druh disku."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Položky Audio CD menu"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Přehrát CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Přidat CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Položky Audio CD menu"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Komprese</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Hlasitost středu:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Rozsah dynamiky:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dynamický rozsah kompresoru"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -945,206 +953,227 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Hloubky:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Výšky:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Ozvěna:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Implicitní délka skladby:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Převzorkování</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Povolit převzorkování zvuku"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Převzorkovat na:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorovat délku z SPC popisků"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Prodloužit dozvuk"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Dekodér hudby pro herní konzole"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Prolínání se nezdařilo, protože písně měly různý počet kanálů.  Můžete "
-"použít Míchání kanálů a převést písně na stejný počet kanálů."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio výstup"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Prolínání se nezdařilo, protože písničky měly různé vzorkovací frekvence. "
-"Můžete použít Převádění vzorkovací frekvence pro převod skladeb na stejnou "
-"vzorkovací frekvenci."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Použij exkluzivní mód"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Prolínání zásuvný modul pro Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Crossfade výstupní modul for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Prolínání</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Při automatické změně skladby"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Přesah:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Tip<b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Prolínání"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Prolínání se nezdařilo, protože písně měly různý počet kanálů.  Můžete "
+"použít Míchání kanálů a převést písně na stejný počet kanálů."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Prolínání se nezdařilo, protože písničky měly různé vzorkovací frekvence. "
+"Můžete použít Převádění vzorkovací frekvence pro převod skladeb na stejnou "
+"vzorkovací frekvenci."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intenzita:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Krystalizér"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Smazat soubory"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Chyba při mazání %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Chyba při mazání %s: není to lokální soubor."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Chcete přesunout vybrané soubory do koše?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Přesunout do koše"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Opravdu chcete trvale odstranit vybrané soubory?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Smazat"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Zrušit"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Smazat vybrané soubory"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Metoda mazání<b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Presuň do koše místo okamžitého smazání"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ozvěna</ b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Zpoždění:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Zpětná vazba:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Hlasitost:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Ozvěna zásuvný modul \n"
-"Od Johna Levina, 1999\n"
-"\n"
-"Prostorová ozvěna od Carla van Schaika, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Ozvěna"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg Plugin"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1160,55 +1189,55 @@ msgstr ""
 "Williama Pitcocka <nenolod at nenolod.net>\n"
 "Matti Hämäläinena <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Přídavný modul FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formát výstupního souboru:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Nastavit"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Ukládat do původního adresáře"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Ukládat do vlastního adresáře"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Složka s výstupními soubory:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Vybrat složku"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Získat jméno souboru z:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Generuj jméno souboru z:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "původních značek v souboru"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "jména původního souboru"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Originální jméno souboru"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Nezkracovat příponu jména souboru"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Včetně originální přípony jména souboru"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Předřadit jménu souboru číslo stopy"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Předřadit číslo stopy k jménu souboru"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1240,165 +1269,169 @@ msgstr ""
 "Foundation, Inc, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Přídavný modul FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint-stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Nastavení MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Kvalita algoritmu:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Výstupní vzorkovací kmitočet"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Výstupní vzorkovací frekvence:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Datový tok / Kompresní poměr:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Bitrate / Kompresní poměr:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Datový tok (kb/s):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Kompresní poměr:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Zvukový režim:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Různé:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Vynutit přísnou shodu s ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Vynutit přísnou shodu s ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Ochrana před chybami"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kvalita"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Povolit VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Druh:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Nastavení VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Nejmenší datový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Největší datový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Přísně vynucovat nejmenší datový tok"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Nastavení ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Průměrný datový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Úroveň kvality VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Nezapisovat VBR hlavičku Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Vynechat Xing VBR hlavičku"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Parametry rámců:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Označit jako podléhající autorskému právu"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Označit jako původní"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Parametry ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr "ID3 Parametry:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Vynutit přidání popisků verze 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Přidávat jen popisky verze 1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Přidávat jen popisky verze 2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Popisky"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Nastavení vorbis kodéru"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Úroveň kvality (0–10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC Dekodér"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "Bezztrátová kvalita"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1410,11 +1443,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC Dekodér"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1422,11 +1451,19 @@ msgstr ""
 "GIO zásuvný modul pro Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO Plugin"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Neplatný způsob otvírání"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1437,451 +1474,522 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"OpenGL Analyzátor spektra pro Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren a Carlo Bramini\n"
+"\n"
+"Založeno na XMMS modulu:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson a "
+"4Front Technologies\n"
+"\n"
+"Licence: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL analyzátor spektra"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL analyzátor spektra (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME Klávesové zkratky"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Zásuvný modul pro klávesové zkratky v Gnome\n"
+"GNOME Zásuvný modul pro klávesové zkratky\n"
 "Umožňuje ovládat program pomocí klávesových Gnome\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Klávesové zkratky Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Číslo položky"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Název"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Umělec"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Rok"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Umělec alba"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Stopa"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Žánr"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Umístění ve frontě"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Délka"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Cesta k souboru"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Název souboru"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Vlastní název"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Datový tok"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Použitelné sloupce"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Zobrazené sloupce"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Vyhledávací nástroj"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Umístit vlevo"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Umístit vpravo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Umístit nahoru"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Umístit dolů"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Neumisťovat"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Zakázat"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Vyhledávací nástroj"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Otevřít soubory…"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Otevřít _URL…"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Přid_at soubory…"
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Přidat U_RL…"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Prohledej knihovnu"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_O programu… "
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Nastavení ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Konec"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Hrát"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "P_ozastavit"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "Za_stavit"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Před_chozí"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Další"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Opakovat"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Ná_hodné přehrávání"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Žádné p_okračování dle seznamu skladeb"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Zastavit _po této skladbě"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informace o skladbě…"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Přejí_t na čas…"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Pře_jít na skladbu…"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Nastavit bod opakování _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Nastavit bod opakování _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Vymazat body opakování"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Podle ná_zvu"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Podle _přípony"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Podle cesty k _souboru"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Podle čísla _stopy"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Podle _umělce"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Podle Al_ba"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Podle data vy_dání"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Podle _délky"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Podle _cesty k souboru"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "_Vlastní název"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Obrátit pořadí"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Ná_hodné pořadí"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Přehrát tento seznam skladeb"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Obnovit"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Seřadit"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Seřadit vy_brané"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Odstranit _duplikáty"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Odstranit nedost_upné soubory"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nový"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Přej_menovat"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "Odstraň"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importovat…"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportovat…"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Organizace seznamů skladeb"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Správce _fronty…"
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Ze_sílit"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Z_tišit"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ekvalizér"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "E_fekty ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Zobrazit h_lavní nabídku"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Zobrazit oblast i_nformací"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Zobrazit znázornění oblasti informací"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Zobrazit _stavový panel"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Ukázat _zbývající čas"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Vizualizace"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Soubor"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Přehrát"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "Seznam sk_ladeb"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Služby"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Výstup"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Zobrazení"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
-msgstr "Ode_brat/přidat z/do fronty"
+msgstr "Při_dat/odebrat do/z fronty"
+
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "V_yjmout"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopírovat"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "V_ložit"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Vybr_at vše"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Přejmenovat ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Panely seznamu skladeb</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Vždy zobrazovat panely"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Zobrazovat počet skladeb"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Zobrazovat zavírací tlačítko"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Sloupce seznamu skladeb</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Zobrazovat hlavičky sloupců"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Různé</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Klávesy šipek posouvají o:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Posun při změně skladby"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Rozhraní GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s – Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Plnění vyrovnávácí paměti…"
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1889,84 +1997,98 @@ msgstr[0] "%d kanál"
 msgstr[1] "%d kanály"
 msgstr[2] "%d kanálů"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kb/s"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Režim jedné skladby."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Režim seznamu skladeb."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Zastavuje po skladbÄ›."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Předchozí skladba"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Hrát"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pozastavit/Pokračovat"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Zastavit"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Další stopa"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Vpřed o 5 sekund"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Zpět o 5 sekund"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Vypnout zvuk"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Zvýšit hlasitost"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Snížit hlasitost"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Přejít na soubor"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Přepnout okno přehrávače"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Zobrazit OSD (nápis na obrazovce)"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Přepnout opakování"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Přepnout zamíchání"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Přepnout zastavení po současné skladbě"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Vyvolat okno přehrávače"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(žádné)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1977,15 +2099,11 @@ msgstr ""
 "\n"
 "Chcete pokračovat?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Přiřazuji tlačítka myši"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Hlavní nastavení modulu pro horké klávesy"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1993,23 +2111,27 @@ msgstr ""
 "Uvnitř textového pole stiskněte kombinaci kláves.\n"
 "Navázat lze také tlačítka myši."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Horké klávesy:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Akce</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Navázání kláves:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Přidat"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globální klávesové zkratky"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2024,60 +2146,56 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globální klávesové zkratky"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK výstup"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automaticky připojit k výstupním portům"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
+"Pouze %d JACK výstupních portů bylo nalezeno, ale %d je jich vyžadováno."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Nepodařilo se připojit na JACK port %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
+"JACK podporuje pouze floating-point audio. Musíte změnit výstupní bitovou "
+"hloubku na Plovoucí desetinnou čárku v nastavení JACK výstupu."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Nepodařilo se spojit s JACK servrem; běží?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Na základě xmms-jack, od Chrise Morgana:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Portováno pro Audacious od Giacomo Lozito"
+"JACK server vyžaduje vzorkovací kmitočet %d Hz, ale Audacious přehrává na %d "
+"Hz. Prosím použijte efekt Převodník vzorkovacího kmitočtu na opravu."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK výstup"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Nastavení %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Nastavení hostitele LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Cesta k modulům:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2088,25 +2206,25 @@ msgstr ""
 "Po té, co přidáte novou cestu, je třeba stisknout Enter, aby se vyhledaly "
 "nové moduly.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Dostupné moduly:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Povolit"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Povolené moduly:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Nastavení"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2114,47 +2232,15 @@ msgstr ""
 "LADSPA Host pro Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Host"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: nelze inicializovat podporu LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: nelze číst z konfiguračního souboru LIRC\n"
-"%s: prosím, přečtěte si dokumentaci k LIRC,\n"
-"%s: jak správně vytvořit konfigurační soubor\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: pokouším se znovu připojit…\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: neznámý příkaz „%s“\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: odpojeno od LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: pokus o připojení budu opakovat každých %d sekund…\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC Plugin"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2183,73 +2269,81 @@ msgstr ""
 "\n"
 "Pro více informací o LIRC, navštivte http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Připojení</ b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Znovu se připojit k serveru LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Vyčkat před opětovným připojením:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki Plugin"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Žádný text k dispozici"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Chyba"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Nelze načíst %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Chyba"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Nelze analyzovat %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Hledám texty ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Chybí metadata skladby"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Připojování k lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki Plugin (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U Playlisty"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Genetátor taktů"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Generátor taktu: %d dob/min"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generátor taktu: %d dob/min %d⁄%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2263,11 +2357,11 @@ msgstr ""
 "např. tact://77 pro přehrání 77 beatů za minutu\n"
 "nebo tact://60*3/4 pro přehrání 60 bpm v 3/4 taktu"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Genetátor taktů"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Míchání kanálů"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2275,152 +2369,184 @@ msgstr ""
 "Zásuvný modul kanáloveho mixeru pro Audacious\n"
 "Copyright 2011-2012 John Lindgren a Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Míchání kanálů</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Výstupní kanály:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Míchání kanálů"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS Plugin"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Chyba při připojení k MMS servru"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module Player)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Rozlišení</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8 bitů"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16 bitů"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanály</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Nejbližší (nejrychlejší)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineární (rychlé)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Křivka (dobré)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Vícefázové (nejlepší)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Vzorkovací kmitočet</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Úroveň:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Bod zkrácení:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Dozvuk</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Zdůraznění basů</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Prostorový zvuk</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Předzesílení</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Oblast vzorku"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Zmenšení šumu"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Přehrát Amiga MOD"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Opakovat</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Počet opakování:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Pro opakování navždy, nastavte počet opakování na -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Tyto nastavení se projeví až po restartu Audacious."
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Prostorový zvuk"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 Plugin"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Pokročilé</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Použij přesný výpočet délky (pomalé)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Prostorový zvuk"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 Server"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS Plugin"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Neznámá HTTP chyba"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Zastaveno"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious nyní nehraje."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Oznámení na plochu"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2440,55 +2566,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Ukázat ovládání přehrávání"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Vždy ukázat oznámení"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Oznámení na plochu"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Včetně jména alba v oznámení"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Ukázat"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pozastavit"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Další"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Implicitní zařízení"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 výstup"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 výstup"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Standardní zařízení"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Zvukové zařízení:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Použít jiné zařízení:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Uložit hlasitost mezi relacemi."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Zapnout převody formátu prostřednictvím OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Zabránit virtuálnímu směšování použitím výlučného režimu."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2502,19 +2637,35 @@ msgstr ""
 "Rád bych poděkoval lidem z #audacious, zejména Tonymu Vroonnovy a Johnu "
 "Lindgrennovy a samozřejmě také autorům předešlého OSS zásuvného modulu."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 výstup"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Správce seznamu skladeb"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Položky"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Odstranit"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Přejmenovat"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS seznamy skladeb"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 Dekodér"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio Výstup"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2534,144 +2685,213 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio Výstup"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Pracuji ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Hledej"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Otevřít složku ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Přidat složku"
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Inspektor logů."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Otevřít soubory"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Přidat soubory"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Předchozí"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Opakovat"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Náhodné přehrávání"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt rozhraní"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Převodník vzorkovacího kmitočtu"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Přeskočit/opakovat vzorky"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineární interpolace"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Rychlá sinc interpolace"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Střední sinc interpolace"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Nejlepší sinc interpolace"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Převod</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metoda:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Hodnocení:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Použít přiřazení frekvencí"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Převodník vzorkovacího kmitočtu"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Přístup odepřen"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
-msgstr ""
+msgstr "Ponech toto okno otevřené a klikni znovu na  'Check Permission'.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problém se sítí."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Objevil se problém při kontaktování Last.fm. Zkuste to prosím za chvíli."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Prověřuje se..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "Z_kontrolovat oprávnění"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Odvolání oprávnění"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "Musíte povolit Audacious scrobblovat skladby do Last.fm účtu.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2682,94 +2902,77 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL Výstup"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
+"SDL výstupní zásuvný modul pro Audacious\n"
+"Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL Výstup"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Knihovna"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Neznámý interpret"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Neznámé Album"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr "%s⏎ na %s od %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d alba"
-msgstr[2] "%d alb"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s⏎\n"
-" %s, %d skladba"
-msgstr[1] "%s⏎ %s, %d skladby"
-msgstr[2] "%s⏎ %s, %d skladeb"
+msgstr[1] ""
+msgstr[2] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-" %s⏎\n"
-" %d skladba od %s"
-msgstr[1] " %s⏎ %d skladby od %s"
-msgstr[2] " %s⏎ %d skladeb od %s"
+msgstr[1] ""
+msgstr[2] ""
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Vytvořit seznam skladeb"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "Přid_at do seznamu skladeb"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Prohledat knihovnu"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2777,679 +2980,771 @@ msgstr ""
 "Hudební knihovnu se do Audacious naimportuje tak, že vyberete složku a pak "
 "kliknete na ikonu „obnovit“."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Prosím, počkejte…"
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Vybrat složku"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID Přehrávač"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Výstup</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanály:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulace</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emuluj MOS 8580 (standardnÄ›: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
 msgstr ""
 
-#: src/skins/menus.c:57
-msgid "Open URL ..."
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emuluj filtr"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Čas přehrávání</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Nastavit nejdelší čas přehrávání:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Použij pouze když je délka skladby neznámá"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Nastavit nejkratší čas přehrávání:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Poznámka</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Odstranění ticha"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
 msgstr ""
+"Silence Removal zásuvný modul pro Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Odstranění ticha</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Práh:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Otevři soubory ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Otevři URL ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Prohledej knihovnu"
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Přehrát"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Seznam skladeb"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Zobrazení"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Služby"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "O programu ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Nastavení ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Ukončit"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Opakovat"
+msgstr "Informace o skladbÄ› ..."
 
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Náhodné přehrávání"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Žádné pokračování dle seznamu skladeb"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
+msgstr "Zastavit po této skladbě"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Předchozí"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
-msgstr ""
+msgstr "Nastavit A-B opakování"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
-msgstr ""
+msgstr "Smazat A-B opakování"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Přejít na skladbu ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Přejít na čas ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nový seznam skladeb"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Přejmenuj seznam skladeb"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Odstraň seznam skladeb"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Předchozí seznam skladeb"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Další seznam skladeb"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Importuj seznam skladeb ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Exportuj seznam skladeb ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Správce seznamu skladeb ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Správce fronty ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Obnov seznam skladeb"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Zobrazit editor seznamu skladeb"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Ukázat ekvalizér"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Ukaž zbývající čas"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Vždy na vrchu"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "Na všech pracovních plochách"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dvojitá velikost"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "Přidej URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Přidej soubory ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Podle názvu"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Podle jména souboru"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Odebrat všechny"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Vyprázdnit frontu"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Odstranit nedostupné soubory"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Odebrat duplikáty"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Odebrat neoznačené"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Odebrat označené"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Hledání a výběr"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertovat výběr"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Nevybrat žádné"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Vybrat vše"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Podle alba"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Podle čísla stopy"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Podle umělce"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Podle alba"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Podle čísla stopy"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Zamíchat pořadí"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Otočit seznam"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Seřadit vybrané"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Seřadit seznam"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Oříznout"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopírovat"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Vložit"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "Přidat/odebrat do/z fronty"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Nahraj předvolbu ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Nahraj standardní"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Nahraj soubor předvoleb ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Nahraj EQF soubor ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Ulož předvolbu ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Ulož standardní"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Ulož soubor předvoleb ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Ulož EQF soubor ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Smaž předvolbu ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Importuj Winamp předvolbu ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Rozhraní Winamp Classic "
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Uložit"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Načíst"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Nahraj soubor předvoleb"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Nahraj EQF soubor"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Ulož soubor předvoleb"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Ulož EQF soubor"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Importovat nastavení z Winampu"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Předvolby"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Načíst předvolbu"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Načíst souborovou předvolbu"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Uložit předvolbu"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Uložit automatickou předvolbu"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Smazat předvolbu"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Smazat souborovou předvolbu"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Přehrávač:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Přehrávač:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Font v hlavním okně přehrávače:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Seznamu skladeb:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Seznam skladeb:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Vyberte font pro seznam skladeb:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Písma</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Použít bitmapové fonty (podporuje pouze ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Posouvání názvu skladby"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Převíjet název skladby oběma směry"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyzátor"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Vlnovka"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Žádný"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normální"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Oheň"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Čáry"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Sloupce"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Nejpomalejší"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Pomalé"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Střední"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rychlé"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Nejrychlejší"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Led"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Plynulý"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Typ</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Typ vizualizace:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Analyzátor</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Zobrazovat zvukové špičky"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Styl:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
-msgstr ""
+msgstr "Styl VU metru."
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Obecné"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
-msgstr "Znázornění"
+msgstr "Vizualizace"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Předzesílení"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ekvalizér"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Přejít na %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Hlasitost: %d %%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Vyvážení: %d %% vlevo"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Vyvážení: střed"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Vyvážení: %d %% vpravo"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Nabídka nastavení"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Vypnout „Vždy na vrchu“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Zapnout „Vždy na vrchu“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Informace o souboru"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Vizualizace."
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
-msgstr ""
+msgstr "Nastavit bod opakování A."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
-msgstr ""
+msgstr "Nastavit bod opakování B."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Režim jedné skladby."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Režim seznamu skladeb."
+msgstr "A-B opakování smazáno."
 
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Zastavuje po skladbÄ›."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Vyhledat skladby v současném seznamu skladeb"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3461,57 +3756,61 @@ msgstr ""
 "regulárním výrazům nerozumíte, jednoduše vložte části textu, které chcete "
 "vyhledat."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Název: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Název:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Umělec: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Umělec:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Jméno souboru: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Jméno souboru:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Před hledáním vymazat předchozí výběr"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Shodující se položky automaticky zařadit/vyřadit z fronty"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Ze shodujících se položek vytvořit nový seznam skladeb"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Zobrazit editor seznamu skladeb"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d z %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Zabalený skin Winapmu 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Nezabalený skin Winampu 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Adresář („%s“) nebylo možné vytvořit: %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile modul"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3532,84 +3831,90 @@ msgid ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
-
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile modul"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "O výstupním pluginu Sndio"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
+"Založeno na xmms_sndfile pluginu:\n"
+"Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
 "\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio výstupní plugin\n"
+"Adaptováno pro Audacious - Tony Vroon <chainsaw at gentoo.org>\n"
+"\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"
-"napsal Thomas Pfaff <tpfaff at tp76.info>\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."
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nepodporovaný formát"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio Výstup"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Formát není podporován tímto zvukovým zařízením. ⏎ ⏎ Zkuste to prosím znovu "
-"s běžícím sndiod(1) serverem."
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Zařízení (prázdné pro standardní)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio zařízení"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Ulož a obnov hlasitost:"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(prázdné znamená výchozí)"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio chyba: Nepodporovaný zvukový formát (%d)"
+
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio chyba: sio_open() selhal"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Budiž"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio chyba: sio_setpar() selhal"
 
-#: src/song_change/song_change.c:54
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio chyba: sio_start() selhal"
+
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Změna skladby"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Příkaz, který se provede, když Audacious začne novou skladbu."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametry předávané shellu by měly být uzavřeny do "
+"uvozovek. Nerespektování této rady představuje bezpečnostní riziko.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Příkazy</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Příkaz:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Spusť příkaz při spuštění nové skladby:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Příkaz, který se provede na konci skladby."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Spusť příkaz po skončení skladby:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Příkaz, který se provede, když Audacious dosáhne konce seznamu skladeb."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Spusť příkaz po skončení přehrávání seznamu skladeb:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr ""
-"Příkaz, který se provede při změně názvu skladbu (tj. názvy v síťových "
-"proudech)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Spusť příkaz při změně názvu skladby (pro síťové proudy):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3624,19 +3929,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Parametry předávané shellu by měly být uzavřeny do "
-"uvozovek. Nerespektování této rady představuje bezpečnostní riziko.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Informace o skladbÄ› (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Příkazy"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Sox převzorkování"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3644,52 +3945,57 @@ msgid ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
+"SoX Resampler modul pro Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Založeno na Sample Rate Converter Plugin:\n"
+"Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rychle"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Nízká"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Vysoká"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Velmi vysoká"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Kvalita:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Sox převzorkování"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Rychlost a výška:"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Rychlost a výška</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
-msgstr "Rachlost:"
+msgstr "Rychlost:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Výška:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Rychlost a výška:"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Stavová ikona"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3700,39 +4006,39 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Reakce na rolování myší</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Změnit hlasitost"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Změnit hranou skladbu"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Ostatní nastavení</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Zakázat vyskakovací okno"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Zavřít do systémové oblasti"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Přecházet v seznamu skladeb, když se roluje nahoru"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Stavová ikona"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3742,24 +4048,24 @@ msgstr ""
 "\n"
 "Od Johana Levina, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generátor tónu"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generátor tónů:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3767,16 +4073,17 @@ msgid ""
 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
+"Generátor sinusového tónu Håvard Kvålen <havardk at xmms.org>\n"
+"Upraven Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"Návod: Použij URL: tone://frekvence1;frekvence2;frekvence3;...\n"
+"např. tone://2000;2005 přehraje 2000 Hz tón a 2005 Hz tón"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generátor tónu"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Odstranění hlasu"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3796,31 +4103,72 @@ msgid ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
+"Audacious Ogg Vorbis dekodér\n"
+"\n"
+"Založeno Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Originální kód:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Příspěvky od:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis Dekodér"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detaily o %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Dekodér"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX Dekodér"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack Dekodér"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "Ztrátové (hybridní)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "Ztrátové"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -3830,14 +4178,18 @@ msgstr ""
 "\n"
 "Některý kód pluginů vytvořil Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack Dekodér"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF Dekodér"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b> Konfigurace XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignoruj délku ze souboru"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML Shareable Playlists (XSPF)"
diff --git a/po/da.po b/po/da.po
index 1a0e4d06d104..5fadee1ac6f2 100644
--- a/po/da.po
+++ b/po/da.po
@@ -3,14 +3,14 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Joe Hansen <joedalton2 at yahoo.dk>, 2013
+# Joe Hansen <joedalton2 at yahoo.dk>, 2013-2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Danish (http://www.transifex.com/projects/p/audacious/"
 "language/da/)\n"
 "Language: da\n"
@@ -19,40 +19,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
-
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
-msgid "sequenced"
-msgstr ""
+msgstr "AAC (Raw)-afkoder"
 
-#: src/adplug/plugin.c:14
+#: src/adplug/adplug-xmms.cc:42
 msgid "AdPlug (AdLib Player)"
 msgstr "AdPlug (AdLib-afspiller)"
 
-#: src/alarm/alarm.c:778
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "sekventeret"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
+
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Angiv alarm ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +51,7 @@ msgstr ""
 "\n"
 "Oprindelig skrevet af Adam Feakin og Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -89,8 +73,26 @@ msgid ""
 "\n"
 "\n"
 msgstr ""
+"Tidspunkt\n"
+"  Alarmtidspunkt:\n"
+"    Tidspunktet alarme udløses på.\n"
+"\n"
+"  Stille efter:\n"
+"    Stop alarmen efter dette tidsforløb.\n"
+"       (hvis opvågningsdialogen ikke er lukket)\n"
+"\n"
+"\n"
+"Dage\n"
+"  Dag:\n"
+"    Vælg dagene for hvor alarmen skal være aktiv.\n"
+"\n"
+"  Tidspunkt:\n"
+"    Vælg tidspunkt for alarmen på hver dag,\n"
+"    eller vælg skift-knappen for at benytte standardtidspunktet.\n"
+"\n"
+"\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -111,8 +113,26 @@ msgid ""
 "    Run this command at the alarm time.\n"
 "\n"
 msgstr ""
+"Lydstyrke\n"
+"  Lydovergang:\n"
+"    øg lydstyrken til den valgte lydstyrke\n"
+"    via denne mængde tid.\n"
+"\n"
+"  Begynd ved:\n"
+"    Begynd lydovergang fra denne lydstyrke.\n"
+"\n"
+"  Endelig:\n"
+"    Lydstyrken hvor lydovergang stopper. Hvis lydovergangens\n"
+"    tid er 0 så angiv lydstyrken til dette og start\n"
+"    afspilning.\n"
+"\n"
+"\n"
+"Tilvalg:\n"
+"  Yderligere kommando:\n"
+"    Kør denne kommando på alarm-tidspunktet.\n"
+"\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -126,360 +146,371 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "SÃ¥ gik alarmen."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
-msgstr ""
+msgstr "Din huskeseddel for i dag er ..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "PÃ¥mindelse"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Mondag"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Tirsdag"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Onsdag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Torsdag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Fredag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Lørdag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Søndag"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarmindstillinger"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Tid"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarm (standard):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "t"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Stille efter:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "timer"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutter"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Vælg dagene hvor alarmen skal udløses"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Dag"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Standard"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dage"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Overgang"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekunder"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Lydstyrke"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Start"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Endelig"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Nuværende"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Yderligere kommando"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "aktiver"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Afspilningsliste (valgfri)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Vælg en afspilningsliste"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Indstillinger"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Hvad betyder disse indstillinger?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Hjælp"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Omslag"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Omslagskunst (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA-lydkanal"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Output Plugin for Audacious\n"
+"Ophavsret 2009-2012 John Lindgren\n"
+"\n"
+"Mange tak til William Pitcock, forfatter til ALSA Output Plugin NG, hvis "
+"kode fungerede som en reference når ALSA-manualen ikke var nok."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Standard-PCM-enhed"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Standardenhed for mikser"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM-enhed:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Mikserenhed:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mikserelement:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Arbejd uden om tømningsafbrydelse"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI-afspiller)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA-lydkanal"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI-afspiller)"
-
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Tilsidesæt standardforstærkning:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Tilsidesæt standardpolyfoni:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Tilsidesæt standardefterklang:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Tilsidesæt standardomkvæd:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Afspilning</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
-msgid "Drum shift:"
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
+msgstr "Trommeskift:"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Udelad foranstillet tavshed"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Udelad bagvedstillet tavshed"
+
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Synthesizer</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - vælg SoundFont-fil"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Afbryd"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Ã…bn"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Filnavn"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Størrelse (byte)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Navn:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI-information </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Længde (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Antallet af numre:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variabel"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI-kommentarer og sangtekster </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* ingen kommentarer tilgængelig i denne MIDI-fil *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* ingen sangtekster tilgængelige i denne MIDI-fil *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Luk"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(Ugyldig UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Om AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -489,153 +520,154 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Skrevet af Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Baseret delvist på Evan Martins Ghosd-bibliotek:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rektangel"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Afrundet rektangel"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Konkav rektangel"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ingen"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Start for afspilning"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Udløser OSD når et afspilningspunkt spilles."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Ændring af titel"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Udløser OSD når, under afspilning, sangens titel ændres men filnavnet er det "
-"samme. Det er hovedsagelig nyttigt til at vise små ændringer i "
-"internetudsendelser."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pause aktiveret"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Udløser OSD når afspilning sættes på pause."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pause deaktiveret"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Udløser OSD når pause fjernes fra afspilning "
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Placering"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relativ X-forskydning:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relativ Y-forskydning:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maks OSD-bredde:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Flerskærmsindstillinger"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Vis OSD med:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "alle skærme"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "skærm %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Timing (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Visning:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Ton ind:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Ton ud:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Skrifttyper"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Skrifttype %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Skygge"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Optegningsstil"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Farver"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Farve %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Aktiver udløser"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Hændelse"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Composite-håndtering detekteret"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -645,112 +677,112 @@ msgstr ""
 "med mindre du ved at du har en kørende, så aktiver en composite-håndtering "
 "ellers vil OSD'en ikke fungere korrekt"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Composite-håndtering er ikke krævet for falsk gennemsigtighed"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Gennemsigtighed"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Falsk gennemsigtighed"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Reel gennemsigtighed (kræver X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite-udvidelse er ikke indlæst"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite-udvidelse er ikke tilgængelig"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - konfiguration"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Position"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animation"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Tekst"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekoration"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Udløser"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Diverse"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Test"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "ASXv3-afspilningslister"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2-afspilningslister"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious-afspilningslister (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Farve</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Sløret omfang"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-til-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Forhåndsindstillinger:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nyhedskildeniveau:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Klip frekvens:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Forhåndsindstillinger:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-til-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektrumanalyseprogram"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Lyd-cd-udvidelsesmodul"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -761,172 +793,167 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
+"Ophavsret 2007-2012 Calin Crisan <ccrisan at gmail.com> og andre.\n"
+"\n"
+"Mange tak til libcdio-udviklerne <http://www.gnu.org/software/libcdio/>\n"
+"og til libcddb-udviklere <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Også tak til Tony Vroon for vejledning.\n"
+"\n"
+"Dette var et Google Summer of Code 2007-projekt."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Enhed</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Læs hastighed:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Tilsidesæt enhed:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadata</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Brug CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Brug CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Brug HTTP i stedet for CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Sti:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Lyd-cd-udvidelsesmodul"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
-msgstr ""
+msgstr "Kunne ikke initialisere cdio-undersystemet."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Ugyldig URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Nummeret %d blev ikke fundet."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Kunne ikke åbne lydudkanal"
+msgstr "Spor %d er et dataspor."
 
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Kunne ikke læse lyd-cd."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Lyd-cd"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Kunne ikke åbne cd-enhed %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Intet cd-drev med lyd blev fundet."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Kunne ikke afslutte initialisering af åbnet cd-drev."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Kunne ikke indhente første/sidste nummer."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Kan ikke læse start/slut LSN for spor %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Kunne ikke oprette cddb-forbindelsen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Kunne ikke forespørge CDDB-serveren"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Kunne ikke forespørge CDDB-serveren: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Kunne ikke læse cddb-informationen: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Drev er tomt."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Disktype er ikke understøttet."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Menupunkter for lyd-cd"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Afspil cd"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Tilføj cd"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Menupunkter for lyd-cd"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Komprimering</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Lydstyrke for centrum:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dynamisk interval:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Ophavsret 2010-2012 John Lindgren"
+"Ophavsret 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dynamisk intervalkomprimering"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -943,207 +970,232 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bas:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Diskant:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Ekko:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Standardlængde for sang:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Resampling</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Aktiver gensampling af lyd"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Gensamplingsfrekvens"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorer længde fra SPC-mærker"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Øg ekko"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Musikafkoder for spilkonsol"
 
-#: src/crossfade/crossfade.c:83
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio-udgang"
+
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Glidende overgang mislykkedes da sangene havde forskellige antal kanaler. Du "
-"kan bruge kanalmikseren til at konvertere sangene til det samme antal "
-"kanaler."
 
-#: src/crossfade/crossfade.c:90
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"Glidende overgang mislykkedes da sangene havde forskellige "
-"samplingshastigheder. Du kan bruge Konvertering af samplingshastighed til at "
-"konvertere sangene til den samme samplingshastighed."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Crossfade-udvidelsesmodul for Audacious\n"
-"Ophavsret 2010-2012 John Lindgren"
+"Crossfade Plugin for Audacious\n"
+"Ophavsret 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Glidende overgang</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Ved automatisk sangændring"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Ved søgning eller manuel sangændring"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Fif</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Glidende overgang"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Glidende overgang mislykkedes da sangene havde forskellige antal kanaler. Du "
+"kan bruge kanalmikseren til at konvertere sangene til det samme antal "
+"kanaler."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Glidende overgang mislykkedes da sangene havde forskellige "
+"samplingshastigheder. Du kan bruge Konvertering af samplingshastighed til at "
+"konvertere sangene til den samme samplingshastighed."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensitet:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet-udvidelsesmodul"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Slet filer"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
-msgstr ""
+msgstr "Kunne ikke flytte %s til papirkurven: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Kunne ikke slette %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Kunne ikke slette %s: ikke en lokal fil."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Ønsker du at flytte de valgte filer til papirkurven?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Flyt til papirkurven"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Ønsker du permanent at slette de valgte filer?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Slet"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Afbryd"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Slet valgte filer"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Slettemetode</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Flyt til papirkurven i stedet for at slette øjeblikkeligt"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
+"Echo Plugin\n"
+"Af Johan Levin, 1999\n"
+"Surround-ekko af Carl van Schaik, 1999\n"
+"Opdateret for Audacious af William Pitcock og John Lindgren, 2010-2014"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ekko</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Forsinkelse:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Tilbagemelding:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Lydstyrke:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo-udvidelsesmodul\n"
-"Af Johan Levin, 1999\n"
-"\n"
-"Surround echo af Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Echo"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg-udvidelsesmodul"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1152,56 +1204,62 @@ msgid ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
+"Lydafkodningsmodul til flere formater for Audacious der bruger\n"
+"FFmpeg-multimedierammen (http://www.ffmpeg.org/)\n"
+"\n"
+"Audacious-udvidelsesmodul af:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg-udvidelsesmodul"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter-udvidelsesmodul"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Filformat for lyden:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfigurer"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Gem i oprindelig mappe"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Gem i mappe efter eget valg"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Filmappe for lyd:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Vælg en mappe"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Hent filnavn fra"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Opret filnavnet fra:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "oprindelige filmærker"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Original filmærke"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "oprindelig filnavn"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Original filnavn"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Fjern ikke filnavnsendelsen"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Inkluder original navn på filendelsen"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr "Foranstil rækkefølge for numrene til filnavnet"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1219,187 +1277,201 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter-udvidelsesmodul"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Fælles stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3-konfiguration"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_O.k."
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmekvalitet"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Samplingsfrekvens for lydudgang:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bithastighed/komprimeringsforhold:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bithastighed (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Komprimeringsforhold:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Lydtilstand:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Diverse:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "Fremtving streng ISO-overholdelse"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Fejlbeskyttelse"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kvalitet"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Aktiver VBH/GBH"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Type:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBH-indstillinger:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimum for bithastighed (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksimum for bithastighed (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Fremtving strengt minimum for bithastighed"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "GBH-indstillinger:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Gennemsnitlig bithastighed (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR-kvalitetsniveau:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Skriv ikke Xing VBH-hoved"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Udelad Xing VBR-teksthoved"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBH/GBH"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Billedparametre:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marker som ophavsret"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marker som original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3-parametre:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Fremtving tilføjelse af version 2-mærke"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Tilføj kun v1-mærke"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Tilføj kun v2-mærke"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Mærker"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Konfiguration af Vorbiskoder"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Kvalitetsniveau (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC-afkoder"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "uden kvalitetstab"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
+"Original kode af\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC-afkoder"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
+"GIO-udvidelsesmodul for Audacious\n"
+"Ophavsret 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO-udvidelsesmodul"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Læs og tilføj-tilstand er ikke understøttet"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Ugyldig åbn-tilstand"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1410,531 +1482,629 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Ophavsret 2013 Christophe Budé, John Lindgren og Carlo Bramini\n"
+"\n"
+"Baseret på XMMS-udvidelsesmodulet:\n"
+"Ophavsret 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson og "
+"4Front Technologies\n"
+"\n"
+"Licens: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
-msgstr ""
+msgstr "OpenGL-spektrumanalyseprogram"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Ophavsret 2013 Christophe Budé, John Lindgren og Carlo Bramini\n"
+"Ophavsret 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Ophavsret 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson og "
+"4Front Technologies\n"
+"\n"
+"Licens: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL-spektrumanalyseprogram (Qt)"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr "Genvejstaster for GNOME"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"Udvidelsesmodul til genvejstaster for GNOME\n"
+"Gør at du kan kontrollere din afspiller med GNOME's genvejstaster.\n"
+"\n"
+"Ophavsret 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Postnummer"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Titel"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Kunstner"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Ã…r"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Kunstner"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Nummer"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Genre"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Køposition"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Længde"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Filsti"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Filnavn"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Tilpasset titel"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bithastighed"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Tilgængelige kolonner"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Viste kolonner"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Søgeværktøj"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Dok til venstre"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Dok til højre"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Dok øverst"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Dok nederst"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Fjern dok"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Deaktiver"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Søgeværktøj"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Ã…bn filer ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Ã…bn a_dresse ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Tilføj filer ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "_Tilføj adresse ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Søg _bibliotek"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Om ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Indstillinger ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Afslut"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Afspil"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Pause"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Stop"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Forrige"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Næste"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Gentag"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Bland"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_Ingen næste afspilningsliste"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Stop _Efter denne sang"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Sanginformation ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_Hop til tid ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Hop til sang ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
-msgstr ""
+msgstr "Angiv gentagelsespunkt _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
-msgstr ""
+msgstr "Angiv gentagelsespunkt _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Ryd gentagelsespunkter"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Efter _titel"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "Efter _filnavn"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Efter fil_sti"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Efter _rækkefølge for nummeret"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Efter _kunstner"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Efter al_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Efter _kunstner"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Efter _udgivelsesdato"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Efter _længde"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Efter _filsti"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Efter _tilpasset titel"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Omvendt rækkefølge"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Vilkårlig rækkefølge"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Start denne afspilningsliste"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Opdater"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Sorter"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr ""
+msgstr "Sorter _valgte"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Fjern dupletter"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Fjern _utilgængelige filer"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Ny"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Omdøb ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "_Fjern"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importer ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Eksporter ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "HÃ¥ndtering af _afspilningslister ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Køhåndtering ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Lydstyrke _op"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Lydstyrke _ned"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizer"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "_Effekter ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Vis _menubjælke"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Vis _informationsbjælke"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Vis _visualisering for informationsbjælken"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Vis _statusbjælke"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Vis _resterende tid"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Visualiseringer ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fil"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Afspilning"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Afspilningsliste"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Tjenester"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Lydudgang"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Vis"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Sæt i kø/fjern fra kø"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Klip"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopier"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Indsæt"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Vælg _alle"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Omdøb ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Afspilningslistefaneblade</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Vis altid faneblade"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Afspilningslistekolonner</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Vis teksthoveder for kolonner"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Diverse</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Rul ved sangændring"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK-grænseflade"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Mellemlagrer ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d kanal"
 msgstr[1] "%d kanaler"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Tilstand for én."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Afspilningstilstand."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Stopper efter sang."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Forrige nummer"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Afspil"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pause/genoptag"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Stop"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Næste nummer"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Fremad 5 sekunder"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Tilbage 5 sekunder"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Sluk lyden"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Lydstyrke op"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Lydstyrke ned"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Hop til fil"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Skift afspillervinduer"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Vis On-Screen-Display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Skift gentag"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Skift bland"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Skift stop efter nuværende"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
-msgstr ""
+msgstr "Hæv vinduer for afspiller"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ingen)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1945,15 +2115,11 @@ msgstr ""
 "\n"
 "Ønsker du at fortsætte?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Binding af museknapper"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Konfiguration af udvid.modul for globale genvejstaster"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1961,23 +2127,27 @@ msgstr ""
 "Tryk på en tastekombination i et tekstfelt.\n"
 "Du kan også binde museknapper."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Genvejstaster:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Handling:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Genvejstast:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Tilføj"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globale genvejstaster"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1992,56 +2162,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globale genvejstaster"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK-lydkanal"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Forbind automatisk til udgangsporte"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Kun %d JACK-udgangsporte blev fundet, men %d var krævet."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Kunen ikke forbinde til JACK-port %s"
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Kunne ikke forbinde til JACK-serveren; kører den?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK-lydkanal"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s-indstillinger"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Indstillinger for LADSPA-vært"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modulstier:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2052,68 +2217,41 @@ msgstr ""
 "Efter tilføjelse af nye stier, tryk Retur for at skanne for nye "
 "udvidelsesmoduler.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Tilgængelige udvidelsesmoduler:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Aktiver"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Aktiverede udvidelsesmoduler:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Indstillinger"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
+"LADSPA-vært for Audacious\n"
+"Ophavsret 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA-vært"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: Kunne ikke initiere LIRC-understøttelse\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: Forsøger at forbinde igen ...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: Ukendt kommando »%s«\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: Frakoblet fra LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: Vil forsøge at forbinde igen hver %d sekunder ...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC-udvidelsesmodul"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2128,74 +2266,95 @@ msgid ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
+"Et simpelt udvidelsesmodul til at kontrollere Audacious med LIRC's eksterne "
+"kontroldæmon\n"
+"\n"
+"Tilpasset Audacious af:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Baseret på XMMS LIRC-udvidelsesmodulet af:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"For yderligere information om LIRC, se http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Forbindelse</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Forbind igen til LIRC-serveren"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Vent før du forbinder igen:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC-udvidelsesmodul"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki-udvidelsesmodul"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Ingen sangtekster er tilgængelige"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Fejl"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Kunne ikke hente %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Fejl"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Kunne ikke fortolke %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Kigger efter sangtekster ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Manglende sangmetadata"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Forbinder til lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki-udvidelsesmodul"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki-udvidelsesmodul (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U-afspilningslister"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Tact-opretter: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Tact-opretter: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2204,162 +2363,196 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr ""
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanalmikser"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
+"Channel Mixer-udvidelsesmodul for Audacious\n"
+"Ophavsret 2011-2012 John Lindgren og Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanalmikser</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Kanaler for lydudgang:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanalmikser"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS-udvidelsemodul"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Der opstod en fejl under forbindelse til MMS-server"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module-afspiller)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Opløsning</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanaler</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
-msgstr ""
+msgstr "Nærmeste (hurtigste)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
-msgstr ""
+msgstr "Lineær (hurtig)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Niveau:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Ekko</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Støjreduktion"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Afspil Amiga MOD'er"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Gentag</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Antal gentagelser:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "For at gentage for evigt, så sæt antal gentagelser til -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module-afspiller)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Disse indstillinger vil træde i kraft når Audacious bliver genstartet"
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123-udvidelsesmodul"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avanceret</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Brug præcis længdeberegning (langsom)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2-server"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS-udvidelsesmodul"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Der opstod en fejl ved videresendelse af fortolkning"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Ukendt HTTP-fejl"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Der opstod en fejl ved fortolkning af adresse"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "For mange videresendelser"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Stoppet"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious afspiller ikke."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Skrivebordspåmindelser"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2379,55 +2572,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
-msgstr ""
+msgstr "Vis afspilningskontroller"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Vis altid påmindelse"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Skrivebordspåmindelser"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Inkluder albumnavn i påmindelse"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Vis"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pause"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Næste"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Standardenhed"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4-lydkanal"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3-udgang"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Standardenhed"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Lydenhed:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Brug anden enhed:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Gem lydstyrke mellem sessioner."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Aktiver formatkonvertering lavet af OSS-programmer."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Aktiver eksklusiv tilstand for at forhindre virtuel blanding."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2435,20 +2637,41 @@ msgid ""
 "I would like to thank people on #audacious, especially Tony Vroon and John "
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
+"OSS4 Output Plugin for Audacious\n"
+"Ophavsret 2010-2012 Michał Lipski\n"
+"\n"
+"Jeg vil gerne takke folk på #audacious, specielt Tony Vroon og John Lindgren "
+"og selvfølgelig forfatterne af det tidligere OSS-udvidelsesmodul."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4-lydkanal"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Afspilningshåndtering"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Poster"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Fjern"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Omdøb"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS-afspilningslister"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2-afkoder"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio-lydkanal"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2467,146 +2690,238 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
+"Audacious PulseAudio Output Plugin\n"
+"\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."
+
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia-udgang"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Ophavsret 2014 William Pitcock\n"
+"\n"
+"Baseret på  SDL Output Plugin for Audacious\n"
+"Ophavsret 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Arbejder ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Søg"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio-lydkanal"
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Loginspektør ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Ã…bn filer"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Tilføj filer"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Forrige"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Gentag"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Bland"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt-grænseflade"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Udelad/gentag samplinger"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineær interpolation"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Fast sinc-interpolation"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Medium sinc-interpolation"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Bedste sinc-interpolation"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
-msgstr ""
+msgstr "<b>Konvertering</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metode:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Hastighed:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Hastighedsoversættelser</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Brug hastighedsoversættelser"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32,0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88,2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176,4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Tilladelse nægtet"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
-msgstr ""
+msgstr "Hold dette vindue åben og klik så på »Kontroller rettighed« igen.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Netværksproblem."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Der opstod et problem under forsøget på at kontakte Last.fm. Prøv igen "
 "senere."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Kontrollerer ..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "_Kontroller rettighed"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Tilbagekald rettighed"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
+"Scrobbler-udvidelsesmodulet kunne ikke startes.\n"
+"Der er måske et problem med din installation."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2616,12 +2931,15 @@ msgid ""
 "project.\n"
 "\n"
 msgstr ""
+"Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
+"\n"
+"Ophavsret 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Tak til John Lindgren for at give mig en hånd i begyndelsen af dette "
+"projekt.\n"
+"\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2629,87 +2947,68 @@ msgstr ""
 "Audacious bruger nu en forbedret version af Last.fm Scrobbler.\n"
 "Kontroller præferencerne for Scrobbler-udvidelsesmodulet."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL-lydkanal"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
+"SDL Output Plugin for Audacious\n"
+"Ophavsret 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL-lydkanal"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Bibliotek"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Ukendt kunstner"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Ukendt album"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" på %s af %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultat"
+msgstr[1] "%d resultater"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d albummer"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d skjult)"
+msgstr[1] "(%d skjulte)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d sang"
-msgstr[1] ""
-"%s\n"
-" %s, %d sang"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d sang af %s"
-msgstr[1] ""
-"%s\n"
-" %d sange af %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d sang"
+msgstr[1] "%d sange"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "i denne genre"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "på"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "af"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Opret afspilningsliste"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Tilføj til afspilningsliste"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Søg bibliotek"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2717,679 +3016,771 @@ msgstr ""
 "For at importere dit musikbibliotek til Audacious skal du vælge en mappe og "
 "så klikke på ikonet »Opdater«."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Vent venligst ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Vælg mappe"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID-afspiller"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Lydudgang</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanaler:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulering</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emuler MOS 8580 (standard: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Vælg ikke automatisk chip-model"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emuler filter"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Ur-hastighed:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Vælg ikke automatisk ur-hastighed"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Afspilningstid</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
 msgstr ""
 
-#: src/skins/menus.c:57
-msgid "Open URL ..."
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Brug kun når sanglængden er ukendt"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Sæt minimum for afspilningstidspunkt:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Fjernelse af stilhed"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
 msgstr ""
+"Silence Removal Plugin for Audacious\n"
+"Ophavsret 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Fjernelse af stilhed</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Tærskel:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Ã…bn filer ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Ã…bn adresse ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Søg i biblioteket"
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Afspilning"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Afspilningsliste"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Vis"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Tjenester"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Om ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Indstillinger ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Afslut"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Gentag"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Bland"
+msgstr "Sanginformation ..."
 
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Ingen næste afspilningsliste"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
-
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Forrige"
+msgstr "Stop efter denne sang"
 
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "GÃ¥ til sang ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "GÃ¥ til tidspunkt ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Ny afspilningsliste"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Omdøb afspilningsliste ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Fjern afspilningsliste"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Forrige afspilningsliste"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Næste afspilningsliste"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Importer afspilningsliste ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Eksporter afspilningsliste ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "HÃ¥ndtering af afspilningslister ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Køhåndtering ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Opdater afspilningsliste"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Vis redigeringsprogram for afspilningslister"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Vis equalizer"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Vis tilbageværende tid"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Altid øverst"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "PÃ¥ alle arbejdsrum"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dobbelt størrelse"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "Tilføj adresse ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Tilføj filer ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Efter titel"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Efter filnavn"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "Efter filsti"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Fjern alle"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Ryd kø"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Fjern utilgængelige filer"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Fjern duplikater"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Fjern dem som ikke er valgt"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Fjern de valgte"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Søg og vælg"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Vend markering om"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Vælg ingen"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Vælg alle"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Efter album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Efter rækkefølge"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Efter kunstner"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Efter album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Efter kunster"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
+msgstr "Efter udgivelsesdato"
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Efter rækkefølge"
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Sæt listen i vilkårlig rækkefølge"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Vend listen om"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Sorter valgt"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Sorter listen"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Klip"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopier"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Indsæt"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "Tilføj/fjern fra kø"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Indlæs forhåndsindstilling ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
-msgstr ""
+msgstr "Indlæs autoamtisk forhåndsindstilling ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Indlæs standard"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Indlæs forhåndsindstillingsfil ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Indlæs EQF-fil ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Gem forhåndsindstilling ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
-msgstr ""
+msgstr "Gem automatisk forhåndsindstilling ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Gem standard"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Gem forhåndsindstillingsfil ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Gem EQF-fil ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Slet forhåndsindstilling ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
-msgstr ""
+msgstr "Slet automatisk forhåndsindstilling ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Importer WinAMP-forhåndsindstillinger ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "Nulstil til nul"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamps klassiske brugerflade"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Gem"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Indlæs"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Indlæs forhåndsindstillingsfil"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Indlæs EQF-fil"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Gem forhåndsindstillingsfil"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Gem EQF-fil"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Importer Winamp-forhåndsindstillinger"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Forhåndsindstillinger"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Indlæs forhåndsindstilling"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Indlæs automatisk forhåndsindstilling"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Gem forhåndsindstilling"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Gem automatisk forhåndsindstilling"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Slet forhåndsindstilling"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Slet automatisk forhåndsindstilling"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Afspiller:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Afspiller:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Vælg skrifttype for hovedafspillerens vindue:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Afspilningsliste:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Afspilningsliste:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Vælg skrifttype for afspilningslisten:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Tema</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Skrifttyper</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Brug bitmap-skrifttyper (understøtter kun ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Rul igennem sangtitel"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Rul sangtitel i begge retninger"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyseprogram"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Omfang"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Slukket"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Ild"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr ""
+msgstr "Lodrette linjer"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linjer"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Bjælker"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Langsomst"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Langsom"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Mellem"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Hurtig"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Hurtigst"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "Punktummer"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Linje"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Fast"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Is"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Blød"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Type</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Visualiseringstype:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Analyseprogram</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Vis toppunkter"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Farver:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Stil:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Generelt"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualisering"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious-equalizer"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Søg til %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Lydstyrke: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% venstre"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: centrum"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% højre"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu for indstillinger"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Deakiver »Altid øverst«"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Aktiver »Altid øverst«"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Filinformationsboks"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Tilstand for én."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Afspilningstilstand."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Stopper efter sang."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Søg i punkter i aktiv afspilningsliste"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3401,57 +3792,61 @@ msgstr ""
 "Hvis du ikke ved hvordan regulære udtryk fungerer, så indsæt bare en lille "
 "del af hvad du søger efter."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Titel:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Kunstner:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr "Filnavn:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Ryd forrige valg før søgning"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Skift automatisk kø for matchende punkter"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Opret en ny afspilningsliste med matchende punkter"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Redigeringsprogram for Audacious' afspilningslister"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d of %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Arkiveret Winamp 2.x-tema"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Winamp 2.x-tema der ikke er i arkiv"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Kunne ikke oprette mappe (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile-udvidelsesmodul"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3473,84 +3868,72 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile-udvidelsesmodul"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Om Sndio Output-udvidelsesmodulet"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio-lydudgang"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio Output-udvidelsesmodulet\n"
-"\n"
-"Skrevet af Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Enhed (tom for standard):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Format er ikke understøttet"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Gem og gendan lydstyrke:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Der blev forespurgt om et format der ikke understøttes af lydenheden.\n"
-"\n"
-"Prøv igen med sndiod(1)-serveren kørende."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio-fejl: Lydformat er ikke understøttet (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio-enhed"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio-fejl: sio_open() mislykkedes"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(tom er standard)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio-fejl: sio_setpar() mislykkedes"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "O.k."
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio-fejl: sio_start() mislykkedes"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Sangændring"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Kommando der skal køres når Audacious starter en ny sang."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametre sendt til skallen skal omsluttes af "
+"citationstegn. Alt andet er en sikkerhedsrisiko.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Kommandoer</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Kommando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Kommando til afvikling ved ny sang:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Kommando der skal køres mod slutningen af en sang."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Kommando til afvikling ved afsluting på sang:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Kommandoen der skal køres når Audacious når slutningen af afspilningslisten."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Kommando til afvikling ved slut på afspilningsliste:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Kommando der skal køres når titlen ændres sig for en sang (dvs. titler for "
-"netværksudsendelser)."
+"Kommando til afvikling når sangtitlen ændrer sig (for netværksudsendelser):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3564,35 +3947,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Du kan bruge de følgende formatsternge som\n"
-"vil blive erstattet før kommandoen kaldes\n"
-"(ikke alle er nyttige til kommandoen for slut på afspilningslisten)\n"
-"\n"
-"%F: Frekvens (i hertz)\n"
-"%c: Antallet af kanaler\n"
-"%f: Filnavn (fuld sti)\n"
-"%l: Længde (i milllisekunder)\n"
-"%n eller %s: Sangnavn\n"
-"%r: Hastighed (i bit per sekund)\n"
-"%t: Afspilningslsitens position (%02d)\n"
-"%p: Afspiller i øjeblikket (1 eller 0)\n"
-"%a: Kunstner\n"
-"%b: Album\n"
-"%T: Nummerets titel"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Parametre sendt til skallen skal omsluttes af "
-"citationstegn. Alt andet er en sikkerhedsrisiko.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Kommandoer"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3601,51 +3965,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Lav"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Høj"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Meget høj"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Kvalitet:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Hastighed og tonehøjde"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Hastighed og tonehøjde</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Hastighed:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tonehøjde:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Hastighed og tonehøjde"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Statusikon"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "_Indstillinger ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3655,40 +4019,47 @@ msgid ""
 "This plugin provides a status icon, placed in\n"
 "the system tray area of the window manager."
 msgstr ""
+"Status Icon Plugin\n"
+"\n"
+"Ophavsret 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Ophavsret 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"Dette udvidelsesmdoul tilbyder et statusikon, placeret i statusfeltet i "
+"vindueshåndteringen."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<br>Muserul-handling</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Ændr lydstyrke"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Ændr sang der afspilles"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Andre indstillinger</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Deaktiver pop op-vinduet"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Luk statusfeltet"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Gå fremad i afspilningslisten når der rulles opad"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Statusikon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Ekstra stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3698,24 +4069,24 @@ msgstr ""
 "\n"
 "Af Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Ekstra stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Ekstra stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Toneopretter"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Tonegenerator:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3723,16 +4094,18 @@ msgid ""
 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
+"Sine-toneopretter af Håvard Kvålen <havardk at xmms.org>\n"
+"Ændret af Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"For at bruge tilføjes en adresse: tone://frequency1;frequency2;"
+"frequency3;...\n"
+"f.eks. tone://2000;2005 for at spille en 2000 Hz tone og en 2005 Hz tone"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Toneopretter"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Stemmefjernelse"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3753,44 +4126,75 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis-afkoder"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detaljer om %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX-afkoder"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX-afkoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack-afkoder"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "kvalitetstab (hybrid)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "kvalitetstab"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
+"Ophavsret 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Lidt af udvidelsesmodulets kode blev udført af Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack-afkoder"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF-afkoder"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF-konfiguration</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorer længde fra fil"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML Shareable-afspilningslister (XSPF)"
diff --git a/po/de.po b/po/de.po
index 32b2f0d71dbf..c4ba4fa88853 100644
--- a/po/de.po
+++ b/po/de.po
@@ -3,18 +3,21 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Cooligan <ppt23 at lkj.hopto.org>, 2012
+# Chris <ppt23 at lkj.hopto.org>, 2012
+# Chris <ppt23 at lkj.hopto.org>, 2012
+# Ettore Atalan <atalanttore at googlemail.com>, 2014
 # Maximilian Vesper <maximilian at mail.com>, 2013
 # mschwendt <mschwendt at fedoraproject.org>, 2012
 # mschwendt <mschwendt at fedoraproject.org>, 2012
-# Cooligan <ppt23 at lkj.hopto.org>, 2012
+# Chris <ppt23 at lkj.hopto.org>, 2012
+# Thomas Lange <thomas-lange2 at gmx.de>, 2014-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:27+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-18 14:41+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: German (http://www.transifex.com/projects/p/audacious/"
 "language/de/)\n"
 "Language: de\n"
@@ -23,40 +26,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "Mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "Stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "Surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) Dekodierer"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) Dekodierer"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib-Spieler)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "Sequenziell"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib-Spieler)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Alarm setzen ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -67,11 +58,7 @@ msgstr ""
 "\n"
 "Ursprünglich geschrieben von Adam Feakin und Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -112,7 +99,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -152,7 +139,7 @@ msgstr ""
 "    Führe diesen Befehl bei Auslösung des Alarms aus.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -176,385 +163,391 @@ msgstr ""
 "    Aktivieren Sie dazu den Checkbutton und schreiben Sie\n"
 "    die Erinnerungsnachricht in die Textbox."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Dies ist Ihr Aufwachsignal."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Die Erinnerung für heute lautet..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Erinnerung"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Montag"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Dienstag"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Mittwoch"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Donnerstag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Freitag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Samstag"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Sonntag"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarm Einstellungen"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_OK"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Abbrechen"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Uhrzeit"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarm um (Standard):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "Uhr"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Still nach:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "Stunden"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "Minuten"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Tage wählen, an denen der Alarm ausgelöst werden soll"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Tag"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Standard"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Tage"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Ãœbergang"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "Sekunden"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Lautstärke"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Beginnen bei"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Schluss"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Momentan"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Zusätzlicher Befehl"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "aktivieren"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Wiedergabeliste (optional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Wiedergabeliste wählen"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Optionen"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Was bedeuten diese Einstellungen?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Hilfe"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Album-Cover"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Album-Cover (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA Ausgabe"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Ausgabeplugin für Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Mein Dank geht an William Pitcock, Autor des ALSA Ausgabeplugins NG, dessen "
+"Code als Referenz gedient hat, wenn die ALSA Dokumentation nicht ausreichend "
+"war."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(keine Beschreibung)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Standard-PCM-Gerät"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Standard-Mixer-Gerät"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM-Gerät:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Mixer-Gerät:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mixer-Element:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Workaround Drain-Hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI-Spieler)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA Ausgabeplugin für Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"Modularer MIDI Musikspieler\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Mein Dank geht an William Pitcock, Autor des ALSA Ausgabeplugins NG, dessen "
-"Code als Referenz gedient hat, wenn die ALSA Dokumentation nicht ausreichend "
-"war."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA Ausgabe"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI-Spieler)"
+"geschrieben von Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"besonderen Dank an...\n"
+"\n"
+"Clemens Ladisch und Jaroslav Kysela\n"
+"für ihre coolen Programme aplaymidi und amixer, welche\n"
+"neben der alsa-lib Dokumentation sehr hilfreich waren,\n"
+"um mehr über die ALSA API zu erfahren\n"
+"\n"
+"Alfredo Spadafina\n"
+"für das schöne MIDI Keyboard Logo\n"
+"\n"
+"Tony Vroon\n"
+"für die gute Hilfe beim Testen"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Standard Verstärkung überschreiben:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Standard Polyfonie überschreiben:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Standard Hall überschreiben:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "An"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Standard Refrain überschreiben:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Wiedergabe</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Transponieren:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "Halbtöne"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Drum-Shift:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Erweitert</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "Notennummern"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Kommentare aus MIDI-Datei extrahieren"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Stille am Anfang überspringen"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Liedtexte aus MIDI-Datei extrahieren"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Stille am Ende überspringen"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Synthesizer</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Resampling-Frequenz:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Abtastrate:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - SoundFont-Datei wählen"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Abbrechen"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "Ö_ffnen"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Dateiname"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Größe (Bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Name:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Info </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Länge (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Anzahl an Titeln:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variabel"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (Wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Zeitmultiplex:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Kommentare und Liedtexte </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* keine Kommentare in dieser MIDI-Datei verfügbar *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* keine Liedtexte in dieser MIDI-Datei verfügbar *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "S_chließen"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (ungültiges UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Ãœber AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Modularer MIDI Musikspieler\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"geschrieben von Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"besonderen Dank an...\n"
-"\n"
-"Clemens Ladisch und Jaroslav Kysela\n"
-"für ihre coolen Programme aplaymidi und amixer, welche\n"
-"neben der alsa-lib Dokumentation sehr hilfreich waren,\n"
-"um mehr über die ALSA API zu erfahren\n"
-"\n"
-"Alfredo Spadafina\n"
-"für das schöne MIDI Keyboard Logo\n"
-"\n"
-"Tony Vroon\n"
-"für die gute Hilfe beim Testen"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -572,152 +565,146 @@ msgstr ""
 "Zum Teil basierend auf der Ghosd Bibliothek von Evan Martin:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rechteck"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Abgerundetes Rechteck"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Konkaves Rechteck"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Kein"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Wiedergabebeginn"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Löst OSD beim Abspielen eines Wiedergabelisteneintrags aus."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Titeländerung"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"Löst OSD aus, wenn sich während der Wiedergabe der Liedtitel ändert, aber "
-"der Dateiname gleich bleibt. Das ist hauptsächlich nützlich, um "
-"Titeländerungen bei Internetstreams anzuzeigen."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Löst OSD aus, wenn sich der Liedtitel ändert (für Internetstreams)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pause An"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Löst OSD beim Pausieren der Wiedergabe aus."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pause Aus"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Löst OSD beim Fortsetzen der Wiedergabe aus."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Platzierung"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relative X-Verschiebung:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relative Y-Verschiebung:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maximale OSD-Breite:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Multi-Head-Optionen"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD anzeigen auf:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "allen Bildschirmen"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "Bildschirm %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Zeitablauf (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Anzeige:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Einblenden:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Ausblenden:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Schriftarten"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Schriftart %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Schatten"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Render-Stil"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Farben"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Farbe %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Auslöser aktivieren"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Ereignis"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Composite-Manager erkannt"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -727,112 +714,112 @@ msgstr ""
 "Sofern ein solcher nicht doch aktiv ist, bitte einen solchen aktivieren, "
 "ansonsten wird das OSD nicht funktionieren"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Composite-Manager nicht benötigt für vorgetäuschte Transparenz"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparenz"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Pseudo-Transparenz"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Echte Transparenz (benötigt X-Composite-Erweiterung)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite-Erweiterung nicht geladen"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite-Erweiterung nicht verfügbar"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious-OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious-OSD - Konfiguration"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Test"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Setzen"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Position"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animation"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Text"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekoration"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Auslöser"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Verschiedenes"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Test"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 Wiedergabelisten"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 Wiedergabelisten"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious Wiedergabelisten (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Farbe</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Oszilloskop"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereofonisch-zu-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Voreinstellungen:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Eingabepegel:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Grenzfrequenz:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Voreinstellungen:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereofonisch-zu-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektrumanalysator"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio-CD Plugin"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -853,171 +840,158 @@ msgstr ""
 "\n"
 "Dies war ein Google Summer of Code 2007 Projekt."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Gerät</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Lesegeschwindigkeit:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Gerät überschreiben:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadaten</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "CD-Text benutzen"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB benutzen"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "HTTP anstatt CDDBP benutzen"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Pfad:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio-CD Plugin"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Initialisieren des cdio Subsystems fehlgeschlagen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Ungültige URI »%s«."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Titel %d nicht gefunden."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Titel %d ist eine Datenspur."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Öffnen der Audioausgabe fehlgeschlagen."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Fehler beim Lesen der Audio-CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio-CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Titel %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Öffnen des CD-Laufwerks »%s« fehlgeschlagen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Kein geeignetes CD-Laufwerk gefunden."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Abschließen der Initialisierung des CD-Laufwerks fehlgeschlagen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Abfragen der ersten/letzten Titelnummer fehlgeschlagen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Kann Start/Ende LSN für Titel %d nicht lesen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Herstellen der CDDB Verbindung fehlgeschlagen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Abfragen des CDDB Servers fehlgeschlagen"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Abfragen des CDDB Servers fehlgeschlagen: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Lesen der CDDB Information fehlgeschlagen: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Laufwerk ist leer."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nicht unterstützter Disk-Typ."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audio-CD Menueinträge"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD wiedergeben"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "CD hinzufügen"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Audio-CD Menueinträge"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Kompression</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Center Lautstärke:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dynamischer Bereich:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Kompressor Plugin für Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Kompressor"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1033,207 +1007,239 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bass:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Höhe:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Echo:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Standard-Liedlänge:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Resampling</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Audio-Resampling aktivieren"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Resampling-Frequenz:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Länge von SPC-Tags ignorieren"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Hall verstärken"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Spielekonsolen-Musik Dekodierer"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Crossfading fehlgeschlagen, weil die Titel eine andere Anzahl an Kanälen "
-"hatten. Sie können den Kanal-Mixer benutzen, um die Lieder auf die selbe "
-"Anzahl an Kanälen zu konvertieren."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio Ausgabe"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Crossfading fehlgeschlagen, weil die Titel unterschiedliche Abtastraten "
-"hatten. Sie können den Abtastraten-Konverter benutzen, um die Lieder auf die "
-"selbe Abtastrate zu resamplen."
+"CoreAudio Ausgabeplugin für Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basierend auf dem SDL Ausgabeplugin für Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Benutze exklusiven Modus"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Crossfade Plugin für Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Crossfade</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Bei automatischem Titelwechsel"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Ãœberschneiden:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Beim Suchen oder manuellem Titelwechsel"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Hinweis</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Für besseres Crossfading, aktivieren Sie\n"
+"den Effekt »Stille entfernen«."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Crossfade"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Crossfading fehlgeschlagen, weil die Titel eine andere Anzahl an Kanälen "
+"hatten. Sie können den Kanal-Mixer benutzen, um die Lieder auf die selbe "
+"Anzahl an Kanälen zu konvertieren."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Crossfading fehlgeschlagen, weil die Titel unterschiedliche Abtastraten "
+"hatten. Sie können den Abtastraten-Konverter benutzen, um die Lieder auf die "
+"selbe Abtastrate zu resamplen."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensität:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cuesheet Plugin"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Dateien löschen"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Fehler beim Verschieben von »%s« in den Papierkorb: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Fehler beim Löschen von »%s«: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Fehler beim Löschen von »%s«: Datei nicht lokal gespeichert."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Möchten Sie die ausgewählten Dateien in den Papierkorb verschieben?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "In den Papierkorb verschieben"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Möchten Sie die ausgewählten Dateien dauerhaft löschen?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Löschen"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Dateien löschen"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Ausgewählte Dateien löschen"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Löschmethode</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "In den Papierkorb verschieben anstatt sofort zu löschen"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Echo Plugin\n"
+"Von Johan Levin, 1999\n"
+"Surround Echo von Carl van Schaik, 1999\n"
+"Aktualisiert für Audacious von William Pitcock und John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Echo</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Verzögerung:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Rückkopplung:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Lautstärke:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo Plugin\n"
-"Von Johan Levin, 1999\n"
-"\n"
-"Surround Echo von Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Echo"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg Plugin"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1249,55 +1255,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter Plugin"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Ausgabedateiformat:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfigurieren"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "In Ursprungsverzeichnis speichern"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "In benutzerdefiniertem Verzeichnis speichern"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Ausgabedateiverzeichnis:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Verzeichnis wählen"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Dateiname erhalten von:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Dateiname generieren von:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "ursprünglichen Datei-Tags"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Ursprünglichen Datei-Tags"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "ursprünglichen Dateinamen"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Ursprünglichem Dateiname"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Dateiendung nicht entfernen"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Ursprüngliche Dateiendung einbeziehen"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Titelnummer vor Dateinamen anhängen"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Titelnummer an Dateiname voranstellen"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1314,179 +1320,183 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"Dieses Programm ist freie Software. Sie können es unter den Bedingungen der "
-"GNU General Public License, wie von der Free Software Foundation "
-"veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 "
+"Dieses Programm ist freie Software. Sie können es unter den Bedingungen der\n"
+"GNU General Public License, wie von der Free Software Foundation\n"
+"veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2\n"
 "der Lizenz oder (nach Ihrer Option) jeder späteren Version.\n"
 "\n"
-"Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen "
-"von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die "
-"implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÃœR EINEN "
+"Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen\n"
+"von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die\n"
+"implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÃœR EINEN\n"
 "BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.\n"
 "\n"
-"Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem "
-"Programm erhalten haben. Falls nicht, schreiben Sie an die Free Software "
+"Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem\n"
+"Programm erhalten haben. Falls nicht, schreiben Sie an die Free Software\n"
 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter Plugin"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automatisch"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint-Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3-Konfiguration"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algorithmen-Qualität:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Ausgabe-Abtastfrequenz:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Ausgabe-Abtastrate:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "Bitrate / Kompressionsverhältnis:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Kompressionsverhältnis:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio-Modus:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Verschiedenes:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Sonstiges:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Strikte ISO-Erfüllung erzwingen"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Strikte ISO-Konformität erzwingen"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Fehlerschutz"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualität"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR aktivieren"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Typ:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR-Optionen:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimale Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maximale Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Minimale Bitrate erzwingen"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR-Optionen:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Durchschnittliche Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR-Qualitätsstufe:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing-VBR-Header nicht schreiben"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Xing-VBR-Header auslassen"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Frame-Parameter:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Als Copyright kennzeichnen"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Als Original kennzeichnen"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3-Parameter:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Hinzufügen von Version-2-Tags erzwingen"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Nur v1-Tag hinzufügen"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Nur v2-Tag hinzufügen"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tags"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis-Encoder-Konfiguration"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Qualitätsstufe (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC Dekodierer"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "Verlustfrei"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1498,11 +1508,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC Dekodierer"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1510,11 +1516,19 @@ msgstr ""
 "GIO Plugin für Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO Plugin"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "»Lesen-und-Anhängen«-Modus nicht unterstützt"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Ungültiger Modus zum Öffnen"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1534,534 +1548,620 @@ msgstr ""
 "\n"
 "Lizenz: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL Spektrumanalysator"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"OpenGL Spektrumanalysator für Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren und Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basierend auf dem XMMS Plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson und "
+"4Front Technologies\n"
+"\n"
+"Lizenz: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL Spektrumanalysator (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME-Tastenkürzel"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Gnome Tastenkürzel Plugin\n"
-"Ermöglicht die Kontrolle von Audacious mit Gnome Tastenkürzeln.\n"
+"GNOME Tastenkürzel Plugin\n"
+"Ermöglicht die Kontrolle von Audacious mit GNOME Tastenkürzeln.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome Tastenkürzel"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Eintragsnummer"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Titel"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Künstler"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Jahr"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Album-Künstler"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Titelnummer"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Genre"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Warteschlangenposition"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Länge"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Dateipfad"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Dateiname"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Benutzerdefinierter Titel"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitrate"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Verfügbare Spalten"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Angezeigte Spalten"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Suchwerkzeug"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Links andocken"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Rechts andocken"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Oben andocken"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Unten andocken"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Abdocken"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Deaktivieren"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Suchwerkzeug"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Dateien öffnen ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "_URL öffnen ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Dateien _hinzufügen ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL hinzufügen ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Durchsuche _Sammlung"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Info ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Einstellungen ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Beenden"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Wiedergabe"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Pause"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Stopp"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Vorheriger"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Nächster"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Wieder_holen"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Zufällige Wiedergabe"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Wiedergabeliste ni_cht weiterspielen"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Nach _diesem Titel stoppen"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Titel_info ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Zu Z_eitangabe springen ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Zu _Titel springen ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Wiederholpunkt _A setzen"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Wiederholpunkt _B setzen"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "Wiederholpunkte _löschen"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Nach _Titel"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "Nach _Dateinamen"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Nach Datei_pfad"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Nach Titel_nummer"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Nach _Künstler"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Nach _Album"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Nach Albu_m-Künstler"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Nach _Erscheinungsdatum"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Nach _Genre"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Nach _Länge"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Nach _Dateipfad"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Nach _benutzerdefiniertem Titel"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Vertausche Anordnung"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Zufällige Anordnung"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Wiedergabeliste abspielen"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Abspielen/Fortsetzen"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
-msgstr "_Aktualisieren"
+msgstr "Aktualisie_ren"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Sortieren"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Auswahl sor_tieren"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "_Duplikate entfernen"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Nicht _verfügbare Dateien entfernen"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Neu"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Umbenennen ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "_Löschen"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importieren ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportieren ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
-msgstr "Wiedergabe_listen-Manager ..."
+msgstr "_Wiedergabelisten-Manager ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Warteschlangen-_Manager ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Lautstärke er_höhen"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Lautstärke _verringern"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizer"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_ffekte ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Menüleiste anzeigen"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "I_nfobereich anzeigen"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Vis_ualisierungen im Infobereich"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_Statusleiste anzeigen"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Verbleibende _Zeit anzeigen"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Visualisierungen ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Datei"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Wiedergabe"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
-msgstr "Wiedergabe_liste"
+msgstr "Wiederga_beliste"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
-msgstr "Di_enste"
+msgstr "Die_nste"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Ausgabe"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "An_sicht"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "In/Aus _Warteschlange"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Beinhaltenden Ordner öffen"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Aus_schneiden"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopieren"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Einfügen"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_Alles auswählen"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Umbenennen ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Wiedergabelistenreiter</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Wiedergabelistenreiter immer anzeigen"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Titelanzahl anzeigen"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Schließen-Buttons anzeigen"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Wiedergabelistenspalten</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Spaltenüberschriften anzeigen"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Sonstiges</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Zeitspanne für Pfeiltasten:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Mit Titelwechsel scrollen"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK Interface"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Puffern ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "Mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "Stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d Kanal"
 msgstr[1] "%d Kanäle"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Single-Modus."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Wiedergabelistenmodus."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Nach Titel stoppen."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Vorheriger Titel"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Wiedergabe"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pause/Fortsetzen"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Stopp"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Nächster Titel"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 Sekunden vorspulen"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 Sekunden zurückspulen"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Stumm"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Lautstärke erhöhen"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Lautstärke verringern"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Zu Titel springen"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Fenster anzeigen/verstecken"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "On-Screen-Display anzeigen"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Wiederholen ein-/ausschalten"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Zufällige Wiedergabe ein-/ausschalten"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Nach diesem Titel stoppen ein-/ausschalten"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Fenster in den Vordergrund holen"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(keine)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2072,15 +2172,11 @@ msgstr ""
 "\n"
 "Möchten Sie trotzdem fortfahren?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Maustastenkombinationen"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Globale Tastenkürzel Einstellungen"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2088,23 +2184,27 @@ msgstr ""
 "Drücken Sie eine Tastenkombination innerhalb eines Textfeldes.\n"
 "Sie können auch Maustasten verwenden."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Tastenkürzel:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Aktion:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Tastenkombination:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Hinzufügen"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globale Tastenkürzel"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2130,60 +2230,56 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globale Tastenkürzel"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK Ausgabe"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Mit allen verfügbaren Ports verbinden"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automatisch mit Ausgabeports verbinden"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Nur mit Ausgabeports verbinden"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Nur %d JACK Ausgabeports gefunden, aber %d erforderlich."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Mit keinem Port verbinden"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Verbinden zu JACK Port %s fehlgeschlagen."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Verbindungsmodus:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK unterstützt nur Gleitkomma Audio. Sie müssen die Ausgabe Bittiefe in "
+"den Audacious Einstellungen auf »Gleitkomma« ändern."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Debug-Ausgaben aktivieren"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Verbinden zum JACK Server fehlgeschlagen. Ist er aktiv?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Basierend auf xmms-jack von Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Portiert für Audacious von Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK Ausgabe"
+"Der JACK Server erfordert eine Abtastrate von %d Hz, aber Audacious spielt "
+"mit %d Hz. Bitte benutzen Sie den Abtastraten-Konverter Effekt, um diese "
+"Diskrepanz zu korrigieren."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Einstellungen"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Einstellungen"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modulpfade:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2194,25 +2290,25 @@ msgstr ""
 "Drücken Sie nach dem Hinzufügen neuer Pfade Enter, um nach neuen Plugins zu "
 "suchen.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Verfügbare Plugins:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Aktivieren"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Aktive Plugins:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Einstellungen"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2220,47 +2316,15 @@ msgstr ""
 "LADSPA Host für Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Host"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: konnte LIRC Unterstützung nicht initialisieren\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: konnte LIRC Konfigurationsdatei nicht lesen\n"
-"%s: lesen Sie bitte in der Dokumentation von LIRC\n"
-"%s: wie man eine korrekte Konfigurationsdatei erstellt\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: versuche neu zu verbinden...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: unbekannter Befehl »%s«\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: von LIRC getrennt\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: versuche jede %d Sekunden neu zu verbinden...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC Plugin"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2288,73 +2352,81 @@ msgstr ""
 "\n"
 "Besuchen Sie http://lirc.org für weitere Informationen über LIRC."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Verbindung</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Zum LIRC Server wiederverbinden"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Zeitspanne bis zum Wiederverbinden:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki Plugin"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Keine Liedtexte verfügbar"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Fehler"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Abrufen von »%s« nicht möglich"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Fehler"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Parsen von »%s« nicht möglich"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Suche nach Liedtexten ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Fehlende Titel-Metadaten"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Verbinde zu lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki-Plugin (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U Wiedergabelisten"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Takt-Generator"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
-msgstr "Takt-Generator: %d bpm"
+msgstr "Takt-Generator: %d BPM"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
-msgstr "Takt-Generator: %d bpm %d/%d"
+msgstr "Takt-Generator: %d BPM %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2365,14 +2437,14 @@ msgstr ""
 "Ein Takt-Generator von Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
 "Um ihn zu benutzen, fügen Sie eine URL hinzu: tact://Schläge*Zähler/Nenner\n"
-"z.B. tact://77 zum Spielen von 77 Beats per minute\n"
-"oder tact://60*3/4 zum Spielen von 60 bpm im 3/4-Takt"
+"z.B. tact://77 zum Spielen von 77 BPM\n"
+"oder tact://60*3/4 zum Spielen von 60 BPM im 3/4-Takt"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Takt-Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanal-Mixer"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2380,152 +2452,184 @@ msgstr ""
 "Kanal-Mixer Plugin für Audacious\n"
 "Copyright 2011-2012 John Lindgren und Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanal-Mixer</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Ausgabekanäle:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanal-Mixer"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS Plugin"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Fehler beim Verbinden zum MMS Server"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Modulspieler)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Auflösung</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-Bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-Bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanäle</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Nächstliegend (am schnellsten)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linear (schnell)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (gute Qualität)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polyphase (beste Qualität)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Abtastfrequenz</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Abtastrate</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Pegel:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Grenzfrequenz:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Hall</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Bassverstärkung</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Vorverstärkung</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Oversampling"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Geräuschreduktion"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Amiga MOD abspielen"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Wiederholen</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Wiederholzahl:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Für eine endlose Wiederholung, den obigen Wert auf -1 setzen."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Modulspieler)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Diese Einstellungen treten in Kraft, wenn Audacious neugestartet wird."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 Plugin"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Erweitert</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Nutze exakte Längenberechnung (langsam)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 Server"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS Plugin"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Fehler beim Parsen der Weiterleitung"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Unbekannter HTTP Fehler"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Fehler beim Parsen der URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Zu viele Weiterleitungen"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Gestoppt"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious spielt gerade nichts ab."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Desktop-Benachrichtigungen"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2561,55 +2665,64 @@ msgstr ""
 "Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem "
 "Programm erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Bedienelemente für Wiedergabe anzeigen"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Benachrichtigungen immer anzeigen"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Desktop-Benachrichtigungen"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Albumname in Benachrichtigung einschließen"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Anzeigen"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pause"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Nächster"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Standardgerät"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 Ausgabe"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 Ausgabe"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Standardgerät"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audiogerät:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Alternatives Gerät benutzen:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Lautstärke zwischen Sitzungen speichern."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Formatkonvertierung durch OSS aktivieren."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Exklusivmodus aktivieren, um virtuelles Mischen zu verhindern."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2623,19 +2736,35 @@ msgstr ""
 "Ich möchte den Personen auf #audacious danken, vor allem Tony Vroon und John "
 "Lindgren sowie natürlich den Autoren des bisherigen OSS Plugins."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 Ausgabe"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Wiedergabelisten-Manager"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Einträge"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Löschen"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Umbenennen"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS Wiedergabelisten"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 Dekodierer"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio Ausgabe"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2656,25 +2785,87 @@ msgid ""
 msgstr ""
 "Audacious PulseAudio Ausgabeplugin\n"
 "\n"
-"Dieses Programm ist freie Software. Sie können es unter den Bedingungen der "
-"GNU General Public License, wie von der Free Software Foundation "
-"veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 "
+"Dieses Programm ist freie Software. Sie können es unter den Bedingungen der\n"
+"GNU General Public License, wie von der Free Software Foundation\n"
+"veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2\n"
 "der Lizenz oder (nach Ihrer Option) jeder späteren Version.\n"
 "\n"
-"Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen "
-"von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die "
-"implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÃœR EINEN "
+"Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen\n"
+"von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die\n"
+"implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÃœR EINEN\n"
 "BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.\n"
 "\n"
-"Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem "
-"Programm erhalten haben. Falls nicht, schreiben Sie an die Free Software "
+"Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem\n"
+"Programm erhalten haben. Falls nicht, schreiben Sie an die Free Software\n"
 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio Ausgabe"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia Ausgabe"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"QtMultimedia Ausgabeplugin für Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basierend auf dem SDL Ausgabeplugin für Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "In Bearbeitung ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Suchen"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Ordner öffnen ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "Ordner hin_zufügen ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Protoko_ll-Inspektor ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Dateien öffnen"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Dateien hinzufügen"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Vorheriger"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Wiederholen"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Zufällige Wiedergabe"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt Interface"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Abtastraten-Konverter"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2682,100 +2873,108 @@ msgstr ""
 "Abtastraten-Konverter Plugin für Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Ãœberspringen/Wiederholen der Samples"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineare Interpolation"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Schnelle Sinc-Interpolation"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Mittlere Sinc-Interpolation"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Beste Sinc-Interpolation"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Konvertierung</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Methode:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Abtastrate:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Rate-Mappings</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Nutze Rate-Mappings"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Abtastraten-Konverter"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Scrobbeln für Profil: »%s«"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Zugriff verweigert"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Besuchen Sie den folgenden Link, um Audacious das Scrobbeln Ihrer Titel zu "
 "erlauben:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Lassen Sie das Fenster geöffnet und klicken Sie erneut auf »Berechtigung "
 "überprüfen«.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2783,36 +2982,40 @@ msgstr ""
 "Keine Sorge, Ihre Scrobbels sind auf Ihrem Computer gespeichert.\n"
 "Sie werden übermittelt, sobald Audacious die Berechtigung dazu hat."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Netzwerkproblem."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Es gab ein Problem bei der Verbindung zu Last.fm. Bitte versuchen Sie es "
 "später noch einmal."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Überprüfen..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "_Berechtigung überprüfen"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "Berechtigung _entziehen"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Sie müssen Audacious erlauben, Titel zu Ihrem Last.fm Profil scrobbeln zu "
 "dürfen.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2820,7 +3023,7 @@ msgstr ""
 "Das Scrobbler Plugin konnte nicht gestartet werden.\n"
 "Es könnte sich dabei um ein Installationsproblem handeln."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2837,11 +3040,7 @@ msgstr ""
 "Danke an John Lindgren für die anfängliche Hilfe bei diesem Projekt.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2849,7 +3048,11 @@ msgstr ""
 "Audacious benutzt jetzt die verbesserte Version des Last.fm Scrobblers.\n"
 "Bitte prüfen Sie die Einstellungen für das Scrobbler Plugin."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL Ausgabe"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2857,81 +3060,56 @@ msgstr ""
 "SDL Ausgabeplugin für Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL Ausgabe"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Sammlung"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Unbekannter Künstler"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Unbekannes Album"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" aus %s von %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d Ergebnis"
+msgstr[1] "%d Ergebnisse"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d Album"
-msgstr[1] "%d Alben"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d versteckt)"
+msgstr[1] "(%d versteckt)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d Titel"
-msgstr[1] ""
-"%s\n"
-" %s, %d Titel"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d Titel von %s"
-msgstr[1] ""
-"%s\n"
-" %d Titel von %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d Titel"
+msgstr[1] "%d Titel"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "dieses Genres"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "in"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "von"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "Wiedergabeliste _erstellen"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "Zur Wiedergabeliste _hinzufügen"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Durchsuche Sammlung"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2939,679 +3117,771 @@ msgstr ""
 "Wählen Sie einen Ordner und klicken Sie auf »Aktualisieren«, um Ihre "
 "Musiksammlung in Audacious zu importieren."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Bitte warten ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Ordner auswählen"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID-Spieler"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Ausgabe</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanäle:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulation</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "MOS 8580 (Standard: MOS 6581) emulieren"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Chip-Modell nicht automatisch auswählen"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Filter emulieren"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Taktrate:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Taktrate nicht automatisch auswählen"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Wiedergabedauer</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Maximale Wiedergabedauer setzen:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Nur wenn Titellänge unbekannt ist aktivieren"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Minimale Wiedergabedauer setzen:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtunes</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Subtunes aktivieren"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Subtunes ignorieren, wenn kürzer als:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Hinweis</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Stille entfernen"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Stille entfernen Plugin für Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Stille entfernen</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Grenzbereich:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Dateien öffnen ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "URL öffnen ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Durchsuche Sammlung"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Wiedergabe"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Wiedergabeliste"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ansicht"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Dienste"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Info ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Einstellungen ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Beenden"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Titelinfo ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Wiederholen"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Zufällige Wiedergabe"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Wiedergabeliste nicht weiterspielen"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Nach diesem Titel stoppen"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Vorheriger"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "A-B Wiederholung setzen"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "A-B Wiederholung leeren"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Zu Titel springen ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Zu Zeitangabe springen ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Diese Wiedergabeliste spielen"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Abspielen/Fortsetzen"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Neue Wiedergabeliste"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Wiedergabeliste umbenennen ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Wiedergabeliste löschen"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Vorherige Wiedergabeliste"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Nächste Wiedergabeliste"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Wiedergabeliste importieren ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Wiedergabeliste exportieren ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Wiedergabelisten-Manager ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Warteschlangen-Manager ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Wiedergabeliste aktualisieren"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Wiedergabeliste anzeigen"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Equalizer anzeigen"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Verbleibende Zeit anzeigen"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Immer im Vordergrund"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Auf allen Arbeitsflächen"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Hauptfenster aufrollen"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Wiedergabeliste aufrollen"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Equalizer aufrollen"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Doppelte Größe"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "URL hinzufügen ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Dateien hinzufügen ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Nach Titel"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Nach Dateinamen"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Nach Dateipfad"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Alle entfernen"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Warteschlange löschen"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Nicht verfügbare Dateien entfernen"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Duplikate entfernen"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Nicht ausgewählte entfernen"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Auswahl entfernen"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Suchen und Auswählen"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Auswahl invertieren"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Keine auswählen"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Alle auswählen"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Nach Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Nach Titelnummer"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Nach Künstler"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Nach Album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Nach Album-Künstler"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Nach Erscheinungsdatum"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Nach Titelnummer"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Nach Genre"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Nach Länge"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Nach benutzerdefiniertem Titel"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Wiedergabeliste zufällig anordnen"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Wiedergabeliste umkehren"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Auswahl sortieren"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Wiedergabeliste sortieren"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Ausschneiden"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopieren"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Einfügen"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "In/Aus Warteschlange"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Lade Voreinstellung ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Lade automatische Voreinstellung ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Lade Standardwert"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Lade Voreinstellung aus Datei ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Lade EQF-Datei ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Speichere Voreinstellung ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Speichere automatische Voreinstellung ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Speichere Standardwert"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Speichere Voreinstellung in Datei ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Speichere EQF-Datei ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Lösche Voreinstellung ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Lösche automatische Voreinstellung ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importiere Winamp Voreinstellungen ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Setze Werte auf Null zurück"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp Interface"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Speichern"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Laden"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Lade Voreinstellung aus Datei"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Lade EQF-Datei"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Speichere Voreinstellung in Datei"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Speichere EQF-Datei"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importiere Winamp Voreinstellungen"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Voreinstellungen"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Lade Voreinstellung"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Lade automatische Voreinstellung"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Speichere Voreinstellung"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Speichere automatische Voreinstellung"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Lösche Voreinstellung"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Lösche automatische Voreinstellung"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Hauptfenster:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Hauptfenster:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Hauptfenster-Schrift auswählen:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Wiedergabeliste:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Wiedergabeliste:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Wiedergabelisten-Schrift auswählen:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Skin</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Schriftarten</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Benutze Bitmap-Schriftarten (nur ASCII-Unterstützung)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Titel scrollen"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Titel in beide Richtungen scrollen"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analysator"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Oszilloskop"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Spektrogramm"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Aus"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Feuer"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Vertikale Linien"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linien"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Balken"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Am langsamsten"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Langsam"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Schnell"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Am schnellsten"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Punkte"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Linie"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Beständig"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Eis"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Weich"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Modus</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Visualisierungsmodus:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analysator</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Spitzen anzeigen"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Farbgebung:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Stil:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Fallgeschwindigkeit:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Spitzen-Fallgeschwindigkeit:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Oszilloskop-Stil:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Spektrogramm-Farbgebung:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU-Meter-Stil:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Allgemein"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualisierung"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Vorverstaerkung"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious Equalizer"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Suche nach %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Lautstaerke: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% links"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: Mitte"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% rechts"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Optionen"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "'Immer im Vordergrund' aus"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "'Immer im Vordergrund' an"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Dateiinformationen"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualisierungen"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Wiederholpunkt A gesetzt."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Wiederholpunkt B gesetzt."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Wiederholpunkte geloescht."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Single-Modus."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Wiedergabelistenmodus."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Nach Titel stoppen."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Suche Einträge in aktiver Wiedergabeliste"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Suchen"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3624,57 +3894,61 @@ msgstr ""
 "Ausdrücke funktionieren, geben Sie einfach nur einen Teilbegriff für Ihre "
 "Suche ein."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Titel: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Titel:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Künstler: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Künstler:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Dateiname: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Dateiname:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Vorherige Auswahl vor dem Suchen löschen"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Automatisch zwischen passenden Einträgen wechseln"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Erstelle neue Wiedergabeliste mit passenden Einträgen"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious Wiedergabeliste"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d von %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Archivierter Winamp 2.x-Skin"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Nicht archivierter Winamp 2.x-Skin"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Konnte Ordner nicht erstellen (»%s«): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile Plugin"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3714,83 +3988,73 @@ msgstr ""
 "Programm erhalten haben. Falls nicht, schreiben Sie an die Free Software "
 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile Plugin"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Ãœber Sndio Ausgabe Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio-Ausgabe"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio Ausgabeplugin\n"
-"\n"
-"Geschrieben von Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Gerät (leer für Standard):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nicht unterstütztes Format"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Lautstärke speichern und wiederherstellen:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Ein Format, das nicht vom Audiogerät unterstützt wird, wurde angefordert.\n"
-"\n"
-"Bitte versuchen Sie es erneut mit laufenden sndiod(1) Server."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio-Fehler: Nicht unterstütztes Audioformat (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio Gerät"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio-Fehler: sio_open() fehlgeschlagen"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(Leer bedeutet Standard)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio-Fehler: sio_setpar() fehlgeschlagen"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio-Fehler: sio_start() fehlgeschlagen"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Titelwechsel"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Auszuführender Befehl, wenn Audacious einen neuen Titel startet."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parameter sollten zwischen Anführungszeichen stehen, "
+"ansonsten besteht ein Sicherheitsrisiko.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Befehle</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Befehl:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Auszuführender Befehl, wenn Audacious einen neuen Titel startet:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Auszuführender Befehl am Ende eines Titels."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Auszuführender Befehl am Ende eines Titels:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Auszuführender Befehl am Ende der Wiedergabeliste."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Auszuführender Befehl am Ende der Wiedergabeliste:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 "Auszuführender Befehl, wenn sich der Titel eines Lieds ändert (z.B. bei "
-"Netzwerkstreams)."
+"Netzwerkstreams):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3806,8 +4070,7 @@ msgid ""
 msgstr ""
 "Verwendbar sind folgende Zeichenketten, die ersetzt\n"
 " werden, bevor ein Befehl aufgerufen wird\n"
-"(es sind jedoch nicht alle nützlich für den »Ende-der-Wiedergabeliste«-"
-"Befehl):\n"
+"(nicht alle sind sinnvoll für den »Ende-der-Wiedergabeliste«-Befehl):\n"
 "\n"
 "%F: Frequenz (in Hertz)\n"
 "%c: Anzahl der Kanäle\n"
@@ -3821,19 +4084,15 @@ msgstr ""
 "%b: Album\n"
 "%T: Titelname"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Parameter sollten zwischen Anführungszeichen stehen, "
-"ansonsten besteht ein Sicherheitsrisiko.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Titelinfo (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Befehle"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3847,51 +4106,51 @@ msgstr ""
 "Basierend auf dem Abtastraten-Konverter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Schnell"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Niedrig"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Hoch"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Sehr hoch"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualität:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Geschwindigkeit und Tonhöhe"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Geschwindigkeit und Tonhöhe</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Geschwindigkeit:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tonhöhe:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Geschwindigkeit und Tonhöhe"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Status-Icon"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "_Einstellungen ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3909,39 +4168,39 @@ msgstr ""
 "Dieses Plugin stellt ein Status-Icon bereit, welches\n"
 "in der Taskleiste des Fenstermanagers angezeigt wird."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Maus-Scroll-Aktion</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Lautstärke ändern"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Aktiven Titel ändern"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Andere Einstellungen</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
-msgstr "PopUp-Fenster deaktivieren"
+msgstr "Popup-Fenster deaktivieren"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "In die Taskleiste minimieren"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Durch Hochscrollen in Wiedergabeliste fortschreiten"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Status-Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3951,24 +4210,24 @@ msgstr ""
 "\n"
 "Von Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Ton-Generator"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Ton-Generator: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3983,15 +4242,11 @@ msgstr ""
 "tone://frequenz1;frequenz2;frequenz3;...\n"
 "z.B. tone://2000;2005 für einen Ton mit 2000 Hz und einen mit 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Ton-Generator"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Stimmenaufhebung"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4029,11 +4284,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis Dekodierer"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Details über %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Titel: %t\n"
+"Autor: %a\n"
+"Aus: %f\n"
+"Tracker: %T\n"
+"Kommentar: %C\n"
+"Chiptyp: %c\n"
+"Stereo: %s\n"
+"Schleife: %l\n"
+"Chipfrequenz: %F\n"
+"Spielfrequenz: %P\n"
+"Jahr: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Dekodierer"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4043,19 +4333,19 @@ msgstr ""
 "Basierend auf in_vtx.dll von Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious Plugin von Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX Dekodierer"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack Dekodierer"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "Verlustbehaftet (Hybrid)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "Verlustbehaftet"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4065,23 +4355,18 @@ msgstr ""
 "\n"
 "Ein Teil des Plugin-Quelltextes war von Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack Dekodierer"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF Dekodierer"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "XML Wiedergabelisten (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF Konfiguration</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Länge aus Datei ignorieren"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "XML Wiedergabelisten (XSPF)"
diff --git a/po/el.po b/po/el.po
index fc0428fb3146..c7b79e004909 100644
--- a/po/el.po
+++ b/po/el.po
@@ -3,16 +3,17 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# noskamaru <jim.thomas.zks at gmail.com>, 2013
-# noskamaru <jim.thomas.zks at gmail.com>, 2013
+# DImitrios Zakas <jim.thomas.zks at gmail.com>, 2013
+# gis mapps <gismapps at gmail.com>, 2014
+# DImitrios Zakas <jim.thomas.zks at gmail.com>, 2013
 # Γιάννης Ανθυμίδης <yannanth at gmail.com>, 2012-2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Greek (http://www.transifex.com/projects/p/audacious/language/"
 "el/)\n"
 "Language: el\n"
@@ -21,51 +22,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "μονοφωνικό"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "στερεοφωνικό"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "περιφερειακό"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Αναπαραγωγή AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Αναπαραγωγή AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Ξυπνητήρι"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Ξυπνητήρι"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -88,7 +73,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -110,7 +95,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -124,360 +109,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Αυτή είναι η κλήση αφύπνισης."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Η υπενθύμιση σας για σήμερα είναι..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Υπενθύμιση"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Δευτέρα"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Τρίτη"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Τετάρτη"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Πέμπτη"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Παρασκευή"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Σάββατο"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Κυριακή"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Ρυθμίσεις Ξυπνιτηριού"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Χρόνος"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Κτύπα στις (προεπιλογή):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "ÏŽ"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Σίγαση μετά από"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "ώρες"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "λεπτά"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Διαλέξτε τις ημέρες που θα χτυπήσει το ξυπνητήρι"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Ημέρα"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Προεπιλογή"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Ημέρες"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Ξεθωριάζει"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "δευτερόλεπτα"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Ένταση"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Ξεκινάει στις"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Τελικό"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Τωρινό"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Επιπλέον Εντολή"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "ενεργοποίηση"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Λίστα αναπαραγωγής (προαιρετική)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Επιλέξτε μια λίστα αναπαραγωγής"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Επιλογές"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Τι σημαίνουν αυτές οι επιλογές;"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Βοήθεια"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Εξώφυλλο Άλμπουμ"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Έξοδος ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Προεπιλεγμένη συσκευή PCM "
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Προεπιλεγμένη συσκευή μείκτη"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Συσκευή PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Συσκευή μείκτη:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Στοιχείο μείκτη:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Έξοδος ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - επιλέξτε αρχείο SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Άκυρο"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Άνοιγμα"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Όνομα αρχείου"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Μέγεθος (byte)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Όνομα:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Πληροφορίες MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Μορφή:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Μήκος (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Αρ. Κομματιών"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "μεταβλητή"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Σχόλια και Στοίχοι MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* δεν υπάρχουν σχόλια σε αυτό το αρχείο MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* δεν υπάρχουν στοίχοι σε αυτό το αρχείο MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Κλείσιμο"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (μη έγκυρο UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Σχετικά με το AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -488,261 +479,258 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Απεικόνιση στην Οθόνη)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Ορθογώνιο"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Στρογγυλεμένο Ορθογώνιο"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Κοίλο Ορθογώνιο"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Κανένα"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Έναρξη αναπαραγωγής"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Αλλαγή Τίτλου"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Παύση Ενεργή"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Παύση Ανένεργη"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Τοποθέτηση"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Επιλογές για πολλαπλές οθόνες"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Προβολή OSD με χρήση:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "όλες οι οθόνες"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "οθόνη %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Συγχρονισμός (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Προβολή:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Ομαλή είσοδος:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Ξεθώριασμα:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Γραμματοσειρές"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Γραμματοσειρά %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Σκιά"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Χρώματα"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Χρώμα %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Συμβάν"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD won't work properly"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Διαφάνεια"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Ψεύτικη διαφάνεια"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Πραγματική διαφάνεια (χρειάζεται X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Διαμόρφωση OSD του Audacious"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Θέση"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Κίνηση"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Κείμενο"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Διακοσμήση"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Διάφορα"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Λίστες Αναπαραγωγής ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Λίστες Αναπαραγωγής Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Χρώμα</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr ""
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "Προεπιλογές:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr ""
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Αναλυτής Φάσματος"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Πρόσθετο Μουσικών CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -763,169 +751,156 @@ msgstr ""
 "\n"
 "Αυτό το πρόσθετο δημιουργήθηκε κατά το Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Συσκευή</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Ταχύτητα ανάγνωσης:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Παράκαμψη συσκευής:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Μεταδεδομένα</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Χρήση CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Χρήση CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Χρήση HTTP αντί CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Εξυπηρετητής:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Διαδρομή:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Θύρα:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Πρόσθετο Μουσικών CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Απέτυχε η αρχικοποίηση του υποσυστήματος cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Μη έγκυρο URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Το κομμάτι %d δεν βρέθηκε."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Μουσικό CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr ""
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Αναπαραγωγή CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Προσθήκη CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Συμπίεση</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr ""
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr ""
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -943,199 +918,220 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Μπάσο:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr ""
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr ""
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Ενεργοποίηση ανασχεδίασης ήχου"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Ρυθμός ανασχεδίασης:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr ""
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Αύξηση αντίχησης"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Αποκωδικοποιητής Μουσικής Κονσόλας Παιχνιδιών"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Ένταση:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Διαγραφή Αρχείων"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Θέλετε να μεταφέρετε τα επιλεγμένα στον κάδο ανακύκλωσης;"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Μετακίνηση στον κάδο"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Διαγραφή"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Ακύρωση"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Διαγραφή Επιλεγμένων Αρχείων"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ηχώ</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Καθυστέρηση:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Ανάδραση:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Ένταση:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Πρόσθετο Ηχού\n"
-"Του Johan Levin, 1999\n"
-"\n"
-"Περιφερειακή ηχώ από τον Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Ηχώ"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Πρόσθετο FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1145,55 +1141,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Πρόσθετο FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Πρόσθετο FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Διαμόρφωση"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr ""
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr ""
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Επιλογή φακέλου"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "αρχικές ετικέτες αρχείου"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "αρχικό όνομα αρχείου"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
 msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1211,165 +1207,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Πρόσθετο FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Αυτόματο"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Πολυπλεγμένο Στερεοφωνικό"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Στερεοφωνικό"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Μονοφωνικό"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Διαμόρφωση MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Ποιότητα Αλγόριθμου:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Αναλογία ρυθμού μετάδοσης / συμπίεσης:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Ρυθμός μετάδοσης δεδομένων (kb/s):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Λόγος συμπίεσης:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Λειτουργία Ήχου:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Διάφορα:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Εξαναγκασμός αυστηρής συμμόρφωσης με ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Προστασία σφαλμάτων"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Ποιότητα"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Ενεργοποίηση VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Τύπος:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Επιλογές VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Ελάχιστος ρυθμός μετάδοσης (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Μέγιστος ρυθμός μετάδοσης (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Αυστηρά εφάρμοσε ελάχιστο ρυθμό μετάδοσης"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Επιλογές ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Μέσος ρυθμός μετάδοσης (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Επίπεδο ποιότητας VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
 msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr ""
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr ""
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Παραμέτροι ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Πρόσθεσε μόνο ετικέτα v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Πρόσθεσε μόνο ετικέτα v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Ετικέτες"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Διαμόρφωση Κωδικοποιητή Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Επίπεδο ποιότητας (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Αποκωδικοποιητής FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1377,21 +1377,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Αποκωδικοποιητής FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Πρόσθετο GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1403,530 +1407,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Συντομεύσεις GNOME"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Τίτλος"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Καλλιτέχνης"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Έτος"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Άλμπουμ"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Κομμάτι"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Είδος"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Θέση ουράς"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Διάρκεια"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Διαδρομή αρχείου"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Όνομα αρχείου"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Προσαρμοσμένος τίτλος"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Ρυθμός μετάδοσης (bitrate)"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Εργαλέιο Αναζήτησης"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Απενεργοποίηση"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Εργαλέιο Αναζήτησης"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Άνοιγμα Αρχείων..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Άνοιγμα _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Προσθήκη Αρχείων..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Προσθήκη U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "Σ_χετικά ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Έξοδος"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Αναπαραγωγή"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Παύσ_η"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Διακοπή"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Προ_ηγούμενο"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Επόμενο"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Επανάληψη"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Α_νακάτεμα"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr ""
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr ""
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr ""
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr ""
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Κατά _Τίτλο"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Κατά Αριθμό_Κομματιού:"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Κατά _Καλλιτέχνη"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Κατά Ημερομηνία_Έκδοσης"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Κατά _Διαδρομή Αρχείου"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Κατά _Προσαρμοσμένο Τίτλο"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Α_ντίστροφη Σειρά"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Τυχαία Σειρά"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Ανανέωση"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ταξινόμηση"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
-msgstr ""
+msgstr "Αφαίρεση Διπλών"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Νέο"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Μετ_ονομασία ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Εισαγωγή..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Εξαγωγή..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Διαχειριστής Λιστών _Αναπαραγωγής ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Διαχειριστής Ουράς Αναμονής ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Αύξηση_Έντασης"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Μείωση_Έντασης"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ισοσταθμιστής"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Εμφάνιση _Γραμμής Μενού"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Εμφάνιση Π_λαισίου Πληροφοριών"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Εμφάνιση Απεικόνισης Πλαισίου Πλη_ροφοριών"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Εμφάνιση _Γραμμής Κατάστασης"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Αρχείο"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Αναπαραγωγή"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr ""
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Υπηρεσίες"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Έξοδος"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Προβολή"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Εισαγωγή/Αφαίρεση στην/από την Ουρά"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Αποκο_πή"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Αντιγραφή"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Επικόλληση"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Επιλογή _Όλων"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Μετονομασία..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Διάφορα</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Διεπαφή GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Γέμισμα ενδιάμεσης μνήμης..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "μονοφωνικό"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "στερεοφωνικό"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d κανάλι"
 msgstr[1] "%d κανάλια"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kb/s"
 
-#: src/hotkey/gui.c:70
-msgid "Previous track"
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Λειτουργία λίστας αναπαραγωγής."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Διακοπή στο τέλους του κομματιού."
+
+#: src/hotkey/gui.cc:71
+msgid "Previous track"
+msgstr "Προηγούμενο Κομμάτι"
+
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Αναπαραγωγή"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Παύση/Συνέχεια"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Διακοπή"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
-msgstr ""
+msgstr "Επόμενο Κομμάτι"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Μπροστά 5 δευτερόλεπτα"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Πίσω 5 δευτερόλεπτα"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Σίγαση"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Αύξηση έντασης"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Μείωση έντασης"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Μεταπήδηση στο αρχείο"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr ""
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(κανένα)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1934,37 +2015,37 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr ""
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr ""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Συντομεύσεις:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Ενέργεια:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
+msgstr "_Προσθήκη"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1979,124 +2060,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Έξοδος JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Έξοδος JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Ρυθμίσεις %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr ""
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr ""
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Διαθέσιμα πρόσθετα:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Ενεργοποίηση"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Ενεργοποιημένα πρόσθετα:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ρυθμίσεις"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: προσπαθεί να επανασυνδεθεί...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: άγνωστη εντολή «%s»\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: αποσύνδεση από LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: θα προσπαθήσει να επανασυνδεθεί κάθε %d δευτερόλεπτα...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Πρόσθετο LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2112,73 +2159,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Σύνδεση</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Επανασύνδεση με εξυπηρετητή LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Πρόσθετο LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Πρόσθετο LyricsWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Σφάλμα"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Σφάλμα"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Αναζήτηση για στοίχους ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Σύνδεση με lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Πρόσθετο LyricsWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Λίστες Αναπαραγωγής M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr ""
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr ""
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2187,162 +2242,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr ""
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Μείκτης Καναλιών"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Μείκτης Καναλιών:</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Κανάλια εξόδου:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Μείκτης Καναλιών"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Πρόσθετο MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Κανάλια</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Επίπεδο:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Αντίχηση</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Περιφερειακό</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Μείωση θορύβου"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Αναπαραγωγή MOD του Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Επανάληψη</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Μέτρηση επαναλήψεων:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Περιφερειακό"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Πρόσθετο MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Περιφερειακό"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Εξυπηρετητής MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Πρόσθετο Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Διακόπηκε"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Το Audacious δεν αναπαράγει."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2362,55 +2449,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Εμφάνιση"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Παύση"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Επόμενο"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Προεπιλεγμένη συσκευή"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Έξοδος OSS4"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Συσκευή ήχου:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Χρησιμοποίησε εναλλακτική συσκευή:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2419,19 +2515,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Έξοδος OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Λίστες Αναπαραγωγής PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Αποκωδικοποιητής OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Έξοδος PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2451,143 +2563,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Έξοδος PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Αναζήτηση"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Άνοιγμα αρχείων"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Προσθήκη αρχείων"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Προηγούμενο"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Επανάληψη"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Ανακάτεμα"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Μετατροπή</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Μέθοδος:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Ρυθμός:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Άρνηση Πρόσβασης"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Γίνεται έλεγχος..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2598,17 +2779,17 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Έξοδος SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2616,81 +2797,56 @@ msgstr ""
 "Πρόσθετο Εξόδου SDL για το Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Έξοδος SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Βιβλιοθήκη"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Άγνωστος Καλλιτέχνης"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Άγνωστο Άλμπουμ"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" στο %s του %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d δίσκος"
-msgstr[1] "%d δίσκοι"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d τραγούδι"
 msgstr[1] ""
-"%s\n"
-" %s, %d τραγούδια"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d τραγούδι από %s"
 msgstr[1] ""
-"%s\n"
-" %d τραγούδια από %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Δημιουργία Λίστας Αναπαραγωγής"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Προσθήκη στη Λίστα Αναπαραγωγής"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Αναζήτηση βιοθήκης"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2698,679 +2854,769 @@ msgstr ""
 "Για να εισάγεται τη συλλογή μουσικής σας στο Audacious, διαλέξτε έναν φάκελο "
 "και κάνετε κλικ στο εικονίδιο «ανανέωση»."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Παρακαλώ περιμένετε ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Επιλογή Φακέλου"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
 msgstr ""
 
-#: src/skins/menus.c:57
-msgid "Open URL ..."
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Άνοιγμα Aρχείων ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Άνοιγμα διεύθυνσης URL..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Αναζήτηση Βιβλιοθήκης"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Αναπαραγωγή"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Λίστα Αναπαραγωγής"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Προβολή"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Υπηρεσίες"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Ρυθμίσεις ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Έξοδος"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Επανάληψη"
+msgstr "Πληροφορίες τραγουδιού"
 
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Ανακάτεμα"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr ""
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Προηγούμενο"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Νέα Λίστα Αναπαραγωγής"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr ""
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
-msgid "Add URL ..."
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "Προσθήκη Διεύθυνσης URL ..."
+
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Προσθήκη Αρχείων..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Κατά Τίτλο"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Κατά Όνομα Αρχείου"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Αφαίρεση Όλων"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Εκκαθάριση Ουράς"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Αφαίρεση Μη Διαθέσιμων Αρχείων"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Αφαίρεση Διπλών"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Αφαίρεση Μη Επιλεγμένων"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Αφαίρεση Επιλεγμένων"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Αναζήτηση και Επιλογή"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Αντιστροφή Επιλογής"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Επιλογή Κανενός"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Επιλογή Όλων"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Κατά Δίσκο"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Κατά Αριθμό Κομματιού:"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Κατά Καλλιτέχνη"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Κατά Δίσκο"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Κατά Αριθμό Κομματιού:"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Τυχαιοποίηση Λίστας"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Αντίστροφη Λίστας"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ταξινόμηση Επιλεγμένων"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ταξινόμηση Λίστας"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Αποκοπή"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Αντιγραφή"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Επικόλληση"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Κλασσική Διεπαφή Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Αποθήκευση"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Φόρτωση"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Προρυθμίσεις"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Φόρτωση προρύθμισης"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Φόρτωση αυτόματης προρύθμισης"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Αποθήκευση προρύθμισης"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Αποθήκευση αυτόματης προρύθμισης"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Διαγραφή προρύθμισης"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Διαγραφή αυτόματης προρύθμισης"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Αναπαραγωγέας:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Επιλέξτε τη γραμματοσειρά του κύριου παραθύρου:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Λίστα αναπαραγωγής:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Επιλέξτε τη γραμματοσειρά της λίστας αναπαραγωγής:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr ""
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Αναλυτής"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Εμβέλεια"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Μακριά"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr ""
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr ""
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Γραμμές"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Μπάρες"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Αργότερο"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Αργό"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Μεσαίο"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Γρήγορο"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Γρηγορότερο"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr ""
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Ομαλό"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Γενικά"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Οπτικοποίηση"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Προενίσχυση"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ισοσταθμιτής Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr ""
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Ένταση: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Ισορροπία: %d%% αριστερά"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Ισορροπία: κέντρο"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Ισορροπία: %d%% δεξιά"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Μενού Επιλογών"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr ""
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Λειτουργία λίστας αναπαραγωγής."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Διακοπή στο τέλους του κομματιού."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr ""
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3378,57 +3624,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Τίτλος: "
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Δίσκος: "
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Καλλιτέχνης: "
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Όνομα αρχείου: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Όνομα Αρχείου:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr ""
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr ""
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d από %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Πρόσθετο Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3450,77 +3700,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Πρόσθετο Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Ο τύπος δεν υποστηρίζεται"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Εντάξει"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Αλλαγή Τραγουδιού"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Εντολή για εκτέλεση όταν το Audacious αρχίζει νέο τραγούδι."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Εντολή:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Εντολή για εκτέλεση πλησιάζωντας το τέλος ενός τραγουδιού."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
-"Εντολή για εκτέλεση όταν το Audacious φτάνει το τέλος της λίστας "
-"αναπαραγωγής."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3535,17 +3777,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Εντολές"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3554,51 +3794,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Ταχύτητα και Χροιά:"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Ταχύτητα και Χροιά</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Ταχύτητα:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Χροιά:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Ταχύτητα και Χροιά:"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3609,63 +3849,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Αλλαγή έντασης"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr ""
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Άλλες Ρυθμίσεις</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr ""
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Γεννήτρια Τόνων"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Γεννήτρια Τόνων: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3674,15 +3914,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Γεννήτρια Τόνων"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Αφαίρεση Φωνής"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3719,11 +3955,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Αποκωδικοποιητής Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Αποκωδικοποιητής VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -3733,19 +3993,19 @@ msgstr ""
 "Βασισμένο στο in_vtx.dll του Roman Sherbakov <v_soft at microfor.ru>\n"
 "Πρόσθετο για το Audacious από τον Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Αποκωδικοποιητής VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Αποκωδικοποιητής WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "με απώλεια (υβριδικός)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "με απώλεια"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -3755,14 +4015,18 @@ msgstr ""
 "\n"
 "Μερικός κώδικας εγγράφει από τον Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Αποκωδικοποιητής WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Αποκωδικοποιητής 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Διαμοιραζόμενες Λίστες Αναπαραγωγής ΧΜL (XSPF)"
diff --git a/po/en_GB.po b/po/en_GB.po
index ada5134c7030..8a82d50c0ad2 100644
--- a/po/en_GB.po
+++ b/po/en_GB.po
@@ -6,11 +6,11 @@
 # Andi Chandler <andi at gowling.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/"
 "audacious/language/en_GB/)\n"
 "Language: en_GB\n"
@@ -19,51 +19,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -86,7 +70,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -108,7 +92,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -122,360 +106,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "This is your wakeup call."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Reminder"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Monday"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Tuesday"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Wednesday"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Thursday"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Friday"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Saturday"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Sunday"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarm Settings"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Time"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarm at (default):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Quiet after:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "hours"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutes"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Choose the days for the alarm to come on"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Day"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Default"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Days"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Fading"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "seconds"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Start at"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Current"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Additional Command"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "enable"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Playlist (optional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Options"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "What do these options mean?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Help"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr ""
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr ""
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Default PCM device"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Default mixer device"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM device:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Mixer device:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mixer element:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - select SoundFont file"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "File name"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Size (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Name:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Info </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Length (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Time Div:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* no comments available in this MIDI file *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* no lyrics available in this MIDI file *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Close"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (invalid UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -486,152 +476,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectangle"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rounded Rectangle"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Concave Rectangle"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "None"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Playback Start"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Triggers OSD when a playlist entry is played."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Title Change"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in Internet "
-"streams."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pause On"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Triggers OSD when playback is paused."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pause Off"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Triggers OSD when playback is unpaused."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Placement"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relative X offset:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relative Y offset:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Max OSD width:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Multi-Monitor options"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Display OSD using:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "all monitors"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Timing (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Display:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Fade in:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Fade out:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Fonts"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Font %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Shadow"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Render Style"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colours"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Colour %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Enable trigger"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Event"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Composite manager detected"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -641,112 +625,112 @@ msgstr ""
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD will not work properly"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Composite manager not required for fake transparency"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparency"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Fake transparency"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Real transparency (requires X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite extension not loaded"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite extension not available"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - configuration"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Position"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animation"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Text"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoration"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Trigger"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Misc"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -758,169 +742,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Use HTTP instead of CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Drive is empty."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Unsupported disk type."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Play CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Add CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centre volume:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dynamic range:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -930,195 +901,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bass:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Treble:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Default song length:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Enable audio resampling"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Resampling rate:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignore length from SPC tags"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Increase reverb"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Game Console Music Decoder"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr ""
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancel"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr ""
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr ""
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
 msgstr ""
 
-#: src/echo_plugin/echo.c:122
-msgid "Echo"
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1128,55 +1124,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Output file format:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configure"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Save into original directory"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Save into custom directory"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Output file folder:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Pick a folder"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Get filename from:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "original file tags"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Do not strip file name extension"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1194,165 +1190,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 Configuration"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algorithm Quality:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Output Sample rate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Compression ratio:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio Mode:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Enforce strict ISO compliance"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Error protection"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Quality"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Enable VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Type:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR Options:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimum bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maximum bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Strictly enforce minimum bitrate"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR Options:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Average bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR quality level:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Don't write Xing VBR header"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Mark as copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Mark as original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Force addition of version 2 tag"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Only add v1 tag"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Only add v2 tag"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tags"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis Encoder Configuration"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Quality level (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1360,21 +1360,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1386,530 +1390,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Entry number"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Title"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artist"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Year"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Track"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Queue position"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Length"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "File path"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "File name"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Custom title"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitrate"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Dock at Left"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Dock at Right"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Dock at Top"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Dock at Bottom"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Undock"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Disable"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr ""
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Open Files ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Open _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Add U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "A_bout ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Quit"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Play"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Paus_e"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Stop"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Pre_vious"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Next"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Repeat"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "S_huffle"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_o Playlist Advance"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Song _Info ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Jump to _Time ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Jump to Song ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "By _Title"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "By Track _Number"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "By _Artist"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "By Release _Date"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "By _File Path"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "By _Custom Title"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "R_everse Order"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Random Order"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Refresh"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Sort"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_New"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Import ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Export ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Queue Manager ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Volume _Up"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Volume _Down"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equaliser"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Show _Menu Bar"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Show I_nfo Bar"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Show _Status Bar"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_File"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Playback"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "P_laylist"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Services"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Output"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_View"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Queue/Unqueue"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Cu_t"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copy"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Paste"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Select _All"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK Interface"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
-#, c-format
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
+#, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Single mode."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Playlist mode."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Stopping after song."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Play"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pause/Resume"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Stop"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Mute"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Show On-Screen-Display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(none)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1921,15 +2002,11 @@ msgstr ""
 "\n"
 "Do you want to continue?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Binding mouse buttons"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Global Hotkey Plugin Configuration"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1937,23 +2014,27 @@ msgstr ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Hotkeys:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Action:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Key Binding:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1968,56 +2049,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
-msgstr ""
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Settings"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Host Settings"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Module paths:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2027,68 +2103,39 @@ msgstr ""
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Available plugins:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Enable"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Enabled plugins:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Settings"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
 msgstr ""
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2104,73 +2151,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr ""
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Error"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Error"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Tact generator: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Tact generator: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2179,162 +2234,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Output channels:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
 msgstr ""
 
-#: src/mms/mms.c:195
-msgid "MMS Plugin"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Stopped"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious is not playing."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2354,55 +2441,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr ""
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr ""
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Default device"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audio device:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Use alternate device:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Enable format conversions made by the OSS software."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2411,19 +2507,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2443,143 +2555,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr ""
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repeat"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Shuffle"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Method:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2590,765 +2771,840 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr ""
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr ""
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr ""
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Playback"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr ""
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr ""
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repeat"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Shuffle"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "No Playlist Advance"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr ""
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr ""
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Show Playlist Editor"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Show Equaliser"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr ""
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr ""
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr ""
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr ""
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr ""
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr ""
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr ""
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr ""
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr ""
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr ""
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr ""
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr ""
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
 msgstr ""
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr ""
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr ""
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
 msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr ""
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr ""
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr ""
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr ""
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr ""
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr ""
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr ""
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr ""
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Presets"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr ""
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr ""
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr ""
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Player:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Select main player window font:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Playlist:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Select playlist font:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Use bitmap fonts (supports ASCII only)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Scroll song title in both directions"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr ""
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr ""
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr ""
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr ""
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr ""
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr ""
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr ""
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr ""
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr ""
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr ""
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr ""
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "General"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious Equaliser"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Seek to %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% left"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: centre"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% right"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Options Menu"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Disable 'Always On Top'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Enable 'Always On Top'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "File Info Box"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Single mode."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Playlist mode."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Stopping after song."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr ""
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3356,57 +3612,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr ""
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr ""
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3428,75 +3688,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
-
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr ""
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
 msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
 msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3511,17 +3765,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3530,51 +3782,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
 msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3585,63 +3837,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr ""
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr ""
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr ""
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3650,15 +3902,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3679,44 +3927,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/es.po b/po/es.po
index 5c30a9d21a27..d2b30fca2661 100644
--- a/po/es.po
+++ b/po/es.po
@@ -3,24 +3,32 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Adolfo Jayme Barrientos <fitoschido at ubuntu.com>, 2013
+# Adolfo Jayme Barrientos, 2013
+# Adolfo Jayme Barrientos <fito at libreoffice.org>, 2013-2014
+# Adolfo Jayme Barrientos, 2013
+# Adolfo Jayme Barrientos, 2015
 # Adrián Ramirez Escalante <buried.prophet at gmail.com>, 2012
 # Cosme Domínguez Díaz <cosme.ddiaz at gmail.com>, 2010
-# frangor <frangor at frangor.info>, 2013
-# Excelente <dny1020 at aol.com>, 2013
+# enjolras <yo at miguelrevilla.com>, 2012
+# Francesc Gordillo i Cortínez <inactive+frangor at transifex.com>, 2013
+# Francesc Gordillo i Cortínez <inactive+frangor at transifex.com>, 2013
+# Jack R. <dny1020 at aol.com>, 2013
 # Jorge Andrés <winninglero at gmail.com>, 2011
+# Juan Riquelme González <soulchainer at gmail.com>, 2015
 # Lucía Balsa <lucia.balsa.prados at gmail.com>, 2012
 # Marco Antonio Frias Butrón <inactive+smaug at transifex.com>, 2012
+# Marco Antonio Frias Butrón <inactive+smaug at transifex.com>, 2012
 # Matias Menich <und34d at gmail.com>, 2012
+# xukosky <xukosky at yahoo.es>, 2011-2012
 # xukosky <xukosky at yahoo.es>, 2011, 2012
 # enjolras <yo at miguelrevilla.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-13 07:28+0000\n"
+"Last-Translator: Adolfo Jayme Barrientos\n"
 "Language-Team: Spanish (http://www.transifex.com/projects/p/audacious/"
 "language/es/)\n"
 "Language: es\n"
@@ -29,51 +37,38 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estéreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "envolvente"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "Descodificador ACC (sin procesar)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Reproductor AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "secuenciado"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Reproductor AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Establecer alarma…"
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
+"Un complemento para iniciar la reproducción en un momento dado.\n"
+"\n"
+"Escrito originalmente por Adam Feakin y Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -95,8 +90,27 @@ msgid ""
 "\n"
 "\n"
 msgstr ""
+"Tiempo\n"
+"  Alarma a:\n"
+"    Hora a la que saltará la alarma.\n"
+"\n"
+"  Silencio tras:\n"
+"    La alarma se detendrá una vez pasado este tiempo.\n"
+"       (si no se cierra el diálogo de aviso)\n"
+"\n"
+"\n"
+"Días\n"
+"  Día:\n"
+"    Selecciona los días en los que saltará la alarma.\n"
+"\n"
+"  Tiempo:\n"
+"    Escoge cuando sonará la alarma cada día,\n"
+"    o marca «Predeterminado» para usar el\n"
+"    tiempo por defecto.\n"
+"\n"
+"\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -117,8 +131,27 @@ msgid ""
 "    Run this command at the alarm time.\n"
 "\n"
 msgstr ""
+"Volumen\n"
+"  Transición:\n"
+"    Tiempo que se invertirá en establecer,\n"
+"     gradualmente, el volumen final indicado.\n"
+"\n"
+"  Iniciar a:\n"
+"    Inicia la transición desde este volumen.\n"
+"\n"
+"  Final:\n"
+"    Alcanzado este volumen, se detendrá la\n"
+"    transición. Si el tiempo para la transición es 0,\n"
+"    se establecerá este volumen y se iniciará la\n"
+"    reproducción directamente.\n"
+"\n"
+"\n"
+"Opciones:\n"
+"  Comando adicional:\n"
+"    Ejecuta este comando cuando salte la alarma.\n"
+"\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -131,361 +164,402 @@ msgid ""
 "    Type the reminder in the box and turn on the\n"
 "    toggle button if you want it to be shown."
 msgstr ""
+"  Lista de reproducción:\n"
+"    Carga la lista de reproducción dada.\n"
+"    Si no se da ninguna, se usará la lista actual.\n"
+"    También puede indicarse aquí el URL de un\n"
+"    flujo de audio mp3/ogg.\n"
+"\n"
+"  Recordatorio:\n"
+"    Muestra un aviso cuando suena la alarma.\n"
+"    Escriba el recordatorio en el campo de texto y\n"
+"    marque «activar» si quiere que se muestre."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
-msgstr "Esta es su llamada para despertar."
+msgstr "Este es el aviso de su alarma."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
-msgstr ""
+msgstr "Tu recordatorio para hoy es..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Recordatorio"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Lunes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Martes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Miércoles"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Jueves"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Viernes"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Ajustes de Alarma"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Tiempo"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma a (predeterminado):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silencio tras:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Seleccione los días para que salte la alarma"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Día"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Predeterminado"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Días"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
-msgstr "Desvanecimiento"
+msgstr "Transición"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volumen"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Iniciar a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "activar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de reproducción (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Seleccione una lista de reproducción"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opciones"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "¿Qué significan estas opciones?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ayuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
-msgstr "Carátula del Álbum"
+msgstr "Carátula del álbum"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Carátula del álbum (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Salida ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Complemento «Salida ALSA» para Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Quiero expresar mi agradecimiento a William Pitcock, autor del complemento "
+"«Salida ALSA NG», cuyo código me sirvió de referencia en esos momentos en "
+"los que el manual de ALSA no era suficiente."
 
-#: src/alsa/config.c:210
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(sin descripción)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositivo PCM predeterminado"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositivo mezclador predeterminado"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositivo PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositivo mezclador:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemento mezclador:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Evitar los cuelgues por falta de recursos"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (reproductor MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Salida ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
+"AMIDI-Plug\n"
+"reproductor de música MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"escrito por Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"agradecimientos especiales...\n"
+"\n"
+"a Clemens Ladisch y Jaroslav Kysela\n"
+"por sus estupendos programas aplaymidi y amixer; \n"
+"me resultaron muy útiles, junto con la documentación\n"
+"de alsa-lib, para comprender mejor la API de ALSA\n"
+"\n"
+"a Alfredo Spadafina\n"
+"por ese logo tan bonito de un teclado midi\n"
+"\n"
+"a Tony Vroon\n"
+"por su inestimable ayuda probando la alfa"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Ignorar ganancia predeterminada:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Ignorar polifonía predeterminada:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Ignorar reverberación predeterminada:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Activado"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Ignorar coro predeterminado:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Reproducción</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
-msgstr ""
+msgstr "Transponer:"
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "semitonos"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
-msgstr ""
+msgstr "Cambio de batería:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "números de nota"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Omitir silencio del principio"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Omitir silencio del final"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Sintetizador</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Frecuencia de muestreo:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "Complemento AMIDI - seleccione un archivo SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Abrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nombre del archivo"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamaño (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nombre:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Información MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Longitud (mseg):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
-msgstr "Num. de Pistas:"
+msgstr "Núm. de pistas:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div tiempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Comentarios y letras MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* no hay comentarios disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* no hay letras disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Cerrar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 no válido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Acerca del AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -495,269 +569,272 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"Audacious OSD (información en pantalla)\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Escrito por Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Basado parcialmente en la librería ghosd de Evan Martin:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (información en pantalla)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectángulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectángulo redondeado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectángulo cóncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ninguno"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
-msgstr "Reproducción iniciada"
+msgstr "Inicio de reproducción"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Avisa cuando se reproduce un elemento de la lista de reproducción."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cambio de título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Avisa cuando, durante la reproducción, el título de la canción cambia pero "
-"el nombre de archivo es el mismo. Esto es principalmente útil para mostrar "
-"cambios de título en los flujos de Internet."
+"Avisa cuando el título de la canción cambia (para flujos de audio de "
+"Internet)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
-msgstr "Inicio de pausa"
+msgstr "Pausa"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
-msgstr "Avisa cuando la reproducción es pausada."
+msgstr "Avisa cuando se pausa la reproducción."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
-msgstr "Fin de pausa"
+msgstr "Fin de la pausa"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
-msgstr "Avisa cuando la reproducción se reanuda."
+msgstr "Avisa cuando se reanuda la reproducción."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
-msgstr "Colocación"
+msgstr "Ubicación"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
-msgstr "Desplazamiento X relativo:"
+msgstr "Desplazamiento horizontal relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
-msgstr "Desplazamiento Y relativo:"
+msgstr "Desplazamiento vertical relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
-msgstr "Ancho máximo:"
+msgstr "Anchura máxima:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
-msgstr "Opciones multi-monitor"
+msgstr "Opciones multimonitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Mostrar notificaciones utilizando:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "todos los monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
-msgstr "Temporización (ms)"
+msgstr "Tiempo (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Mostrar:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
-msgstr "Desvanecimiento de entrada:"
+msgstr "Aparición suave:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
-msgstr "Desvanecimiento de salida:"
+msgstr "Desvanecimiento suave:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Tipografías"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Tipografía %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo de renderizado"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Color %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Activar disparador"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
-msgstr "Administrador de composición detectado"
+msgstr "Gestor de composición detectado"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD won't work properly"
 msgstr ""
-"Administrador de composición no detectado;\n"
-"a menos que sepa que tiene uno ejecutándose, por favor active un "
-"administrador de composición o las notificaciones no funcionarán "
-"correctamente"
+"Gestor de composición no detectado;\n"
+"por favor, a no ser que esté seguro de que ya hay uno ejecutándose, active "
+"un gestor de composición, o las notificaciones no funcionarán correctamente"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
-msgstr "Administrador de composición no necesario para transparencia falsa"
+msgstr ""
+"No se necesita un gestor de composición para producir seudotransparencias"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparencia"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
-msgstr "Transparencia falsa"
+msgstr "Seudotransparencia"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
-msgstr "Transparencia real (requiere composición 3D)"
+msgstr "Transparencia (requiere extensión de composición)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Extensión de composición no cargada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Extensión de composición no disponible"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Notificaciones de Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Notificaciones de Audacious - configuración"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posición"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animación"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoración"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Disparador"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Varios"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Probar"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "Listas de reproducción ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de reproducción ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listas de reproducción de Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Color</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Borroso"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Conversor Bauer de estéreo a binaural(BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Preajustes:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nivel de alimentación:"
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
-msgstr "Cortar frecuencia:"
-
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Predefinidos:"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr ""
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Frecuencia de corte:"
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizador de espectro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Complemento de Audio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -768,170 +845,168 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
+"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> y otros.\n"
+"\n"
+"Muchas gracias a los desarrolladores de libcdio <http://www.gnu.org/software/"
+"libcdio/>\n"
+"y libcddb <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"También quiero dar las gracias a Tony Vroon por ser mi mentor y mi guía.\n"
+"\n"
+"Este fue un proyecto del «Google Summer of Code» de 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocidad de lectura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Reemplazar dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadatos</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Utilizar CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usar CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Usar HTTP en lugar de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Dirección:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Puerto:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Plugin de Audio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
-msgstr ""
+msgstr "No se pudo iniciar el subsistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
-msgstr ""
+msgstr "URI %s no válido."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Pista %d no encontrada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "No se puede abrir la salida de audio."
+msgstr "La pista %d es una pista de datos."
 
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Error al leer el CD de audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
-msgstr "CD de música"
+msgstr "CD de audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
-msgstr ""
+msgstr "No se pudo abrir el dispositivo de CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
-msgstr ""
+msgstr "No se encontró ningún lector compatible con CDs de audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
-msgstr ""
+msgstr "Ocurrió un error tratando de iniciar el lector de CDs."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
-msgstr ""
+msgstr "No se pudo recuperar el número de la primera/última pista."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
-msgstr ""
+msgstr "No se puede leer el LSN de inicio/fin de la pista %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
-msgstr ""
+msgstr "Error de establecimiento de conexión con el servidor CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
-msgstr ""
+msgstr "Error de consulta al servidor CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
-msgstr ""
+msgstr "Error de consulta al servidor CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
-msgstr ""
+msgstr "Error de lectura de información de la CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "La unidad está vacía."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco no soportado."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Ítems de menú de CD de audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproducir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Añadir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Elementos del Menú de audio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compresión</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar volumen:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Rango dinámico:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
+"Complemento «Compresor de rango dinámico» para Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compresor de rango dinámico"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -940,200 +1015,246 @@ msgid ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
+"Descodificador de música de videoconsola basado en Game_Music_Emu 0.5.2\n"
+"Formatos soportados: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"\n"
+"Complemento para Audacious escrito por:\n"
+"William Pitcock <nenolod at dereferenced.org>\n"
+"Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Graves:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
-msgstr "Longitud de canción predeterminada:"
+msgstr "Duración predeterminada de canción:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
-msgstr ""
+msgstr "<b>Remuestreo</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Activar el remuestreo de sonido"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Tasa de remuestreo:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorar longitud de etiquetas SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumentar la reverberación"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
-msgstr "Decodificador musical de videoconsola"
+msgstr "Descodificador de música de videoconsola"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Salida Core Audio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
+"Complemento «Salida Core Audio» para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el complemento «Salida SDL» para Audacious\n"
+"Copyright 2010 John Lindgren"
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Usar modo exclusivo"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
+"Complemento «Fundido de audio» para Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
-msgstr ""
+msgstr "<b>Fundido de audio</b>"
+
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "En cambio de pista automático"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
+msgstr "Solapar:"
+
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "En búsqueda o cambio de pista manual"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Consejo</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
 msgstr ""
+"Para obtener mejores resultados, active\n"
+"el efecto «Eliminación de silencios»."
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
+msgstr "Fundido de audio"
+
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
 msgstr ""
+"Fundido de audio fallido: las pistas no tienen el mismo número de canales. "
+"Puede usar el «Mezclador de canales» para igualar el número de canales de "
+"las pistas."
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Fundido de audio fallido: las pistas tienen distintas frecuencias de "
+"muestreo. Puede usar el «Convertidor de frecuencia de muestreo» para igualar "
+"la frecuencia de muestreo de las pistas."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidad:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
-msgstr ""
+msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
-msgstr ""
+msgstr "Complemento «Hojas cue»"
+
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Borrar archivos"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
-msgstr ""
+msgstr "Error moviendo %s a la papelera: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Error borrando %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Error borrando %s: no es un archivo local."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "¿Quiere mover los archivos seleccionados a la papelera?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Mover a la papelera"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "¿Quiere borrar de forma permanente los archivos seleccionados?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Borrar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Borrar archivos seleccionados"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Método de borrado</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Mover a la papelera en vez de borrar inmediatamente"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
+"Complemento «Eco»\n"
+"Creado por Johan Levin, 1999\n"
+"«Eco envolvente» escrito por Carl van Schaik, 1999\n"
+"Actualizado para Audacious por William Pitcock y John Lindgren, 2010-2014"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Retraso:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retorno:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volumen:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Complemento de Eco⏎\n"
-"Por Johan Levin, 1999⏎\n"
-"⏎\n"
-"Eco envolvente por Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Complemento de FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1142,56 +1263,62 @@ msgid ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
+"Complemento descodificador de múltiples formatos de audio,\n"
+"usando el framework multimedia FFmpeg (http://www.ffmpeg.org/)\n"
+"\n"
+"Complemento para Audacious creado por:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Complemento de FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Escribir archivo"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato del archivo de salida:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Guardar dentro del directorio original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Guardar dentro de directorio personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Carpeta de archivo de salida:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Elija una carpeta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obtener nombre de archivo desde:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Generar nombre a partir de:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "etiquetas del archivo original"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Etiqueta del archivo original"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nombre del archivo original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nombre del archivo original"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "No quitar la extensión del archivo"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Incluir la extensión del archivo original"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Anteponer el número de pista al nombre de archivo"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Anteponer el nº de pista al nombre del archivo"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1208,202 +1335,218 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"Este programa es software gratis, puede redistribuirlo y/o modificarlo ⏎\n"
-"bajo los términos de la Licencia Pública General GNU publicada por ⏎\n"
-"the Free Software Foundation; sea versión 2 de la Licencia, o ⏎\n"
-"(a su elección) cualquier versión posterior. ⏎\n"
-"⏎\n"
-"Este programa se distribuye con la esperanza de que sea útil, ⏎\n"
-"pero SIN NINGUNA GARANTÍA; incluso sin la garantía implícita de ⏎\n"
-"COMERCIALIZACIÓN o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la ⏎\n"
-"GNU General Public License para más detalles. ⏎\n"
-"⏎\n"
-"Debería haber recibido una copia de GNU General Public License ⏎\n"
-"junto con este programa, y si no, escriba a Free Software ⏎\n"
-"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,⏎\n"
+"Este programa es software libre: usted puede redistribuirlo y/o modificarlo\n"
+"bajo los términos de la Licencia Pública General GNU, publicada por\n"
+"la «Free Software Foundation» (Fundación para el software libre), ya\n"
+"sea la versión 2 de la Licencia, o (a su elección) cualquier versión "
+"posterior. \n"
+"\n"
+"Este programa se distribuye con la esperanza de que sea útil,\n"
+"pero SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita de\n"
+"COMERCIALIZACIÓN o IDONEIDAD PARA UN PROPÓSITO DETERMINADO. Consulte los\n"
+"detalles de la Licencia Pública General GNU para obtener una información más "
+"detallada.\n"
+"\n"
+"Debería haber recibido una copia de la Licencia Pública General GNU\n"
+"junto a este programa. En caso contrario, escriba a Free Software\n"
+"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Estéreo conjunto"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
-msgstr "Estereo"
+msgstr "Estéreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuración MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Aceptar"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Calidad del algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Frecuencia de muestreo de salida:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Frecuencia de muestreo:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Tasa de bits / Compresión:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Tasa de bits / Relación de compresión"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Tasa de bits (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
-msgstr "Compresión:"
+msgstr "Índice de compresión:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
-msgstr "Modo de sonido:"
+msgstr "Modo de audio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Varios:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Miscelánea:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Cumplir estrictamente la norma ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Forzar conformidad con normas ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Error de protección"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Calidad"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Activar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opciones VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Tasa de bits mínima (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Tasa de bits máxima (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
-msgstr "Aplicar estrictamente la tasa de bits mínima"
+msgstr "Aplicación estricta de la tasa de bits mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opciones ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
-msgstr "Tasa de bits promedio (kbps):"
+msgstr "Tasa media de bits (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nivel de calidad VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "No escribir la cabecera VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omitir cabecera VBR Xing"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parametros de Marco:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "Parámetros de trama:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
-msgstr "Marcar como derechos de autor"
+msgstr "Protegido por derechos de autor"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
-msgstr "Marcar como original"
+msgstr "Original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Parametros ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr "Parámetros ID3"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
-msgstr "Forzar adición de etiqueta de la versión 2"
+msgstr "Forzar uso de etiquetas de la versión 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
-msgstr "Solo agregar etiqueta v1"
+msgstr "Solo usar ID3v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
-msgstr "Solo agregar etiqueta v2"
+msgstr "Solo usar ID3v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuración de codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nivel de calidad (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Descodificador FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sin pérdida"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
+"Código original escrito por\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Decodificador FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
+"Complemento GIO para Audacious\n"
+"Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
-msgstr "Plugin GIO"
+msgstr "Complemento GIO"
+
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Modo leer-y-agregar no soportado"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Modo de acceso a ficheros no válido"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1414,531 +1557,629 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"Analizador de espectro OpenGL para Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, y Carlo Bramini\n"
+"\n"
+"Basado en el complemento para XMMS:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, y "
+"4Front Technologies\n"
+"\n"
+"Licencia: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
+msgstr "Analizador de espectro OpenGL"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
+"Analizador de espectro OpenGL para Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, y Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el complemento para XMMS:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, y "
+"4Front Technologies\n"
+"\n"
+"Licencia: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analizador de espectro OpenGL (Qt)"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Atajos de teclado GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
+"Complemento «Atajos de teclado de GNOME»\n"
+"Le permite controlar el reproductor con atajos de GNOME.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Atajos de Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número de entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Año"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
-msgstr "Album"
+msgstr "Álbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artista del álbum"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Género"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posición de la cola"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
-msgstr "Longitud"
+msgstr "Duración"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Ruta del archivo"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nombre del archivo"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Tasa de bits"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Columnas disponibles"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Columnas mostradas"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Herramienta de búsqueda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Acoplar a la izquierda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Acoplar a la derecha"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Acoplar arriba"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Acoplar abajo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desacoplar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Deshabilitar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Herramienta de búsqueda"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Abrir archivos ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
-msgstr "_Añadir archivos ..."
+msgstr "Aña_dir archivos ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Añadir U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Explorar _biblioteca"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "A_cerca de ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Preferencias ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Salir"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Reproducir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
-msgstr "Pa_usar"
+msgstr "_Pausar"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Detener"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "An_terior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
-msgstr "Si_guiente"
+msgstr "_Siguiente"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "R_epetir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Orden aleatorio"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "No avan_zar la lista de reproducción"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
-msgstr ""
+msgstr "Dete_ner después de esta canción"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Información de la canción ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
-msgstr "_Saltar en el tiempo ..."
+msgstr "Ir al _momento ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
-msgstr "Saltar a la _canción ..."
+msgstr "Ir a la _canción ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
-msgstr "Establecer Punto de Repetición _A"
+msgstr "Crear bucle (punto _A)"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
-msgstr "Establecer Punto de Repetición _B"
+msgstr "Crear bucle (punto _B)"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
-msgstr "_Borrar Punto de Repetición"
+msgstr "Borrar b_ucle"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Por _título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr ""
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Por _nombre de archivo"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
-msgstr ""
+msgstr "Por _ruta de archivo"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Por _número de pista"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Por _artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
-msgstr ""
+msgstr "Por ál_bum"
+
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Por artista del álbu_m"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
-msgstr "Por _fecha de estreno"
+msgstr "Por _fecha de lanzamiento"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Por _género"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
-msgstr "Por_Longitud"
+msgstr "Por _duración"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Por _ruta de archivo"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Por título _personalizado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Orden _inverso"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
-msgstr "Orden alea_torio"
+msgstr "_Orden aleatorio"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Reproducir esta lista"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Reproducir/Continuar"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
-msgstr "A_ctualizar"
+msgstr "_Actualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordenar"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr ""
+msgstr "Ordenar _seleccionados"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
-msgstr "Eliminar_Duplicados"
+msgstr "Eliminar _duplicados"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
-msgstr "Eliminar archivos _no disponibles"
+msgstr "_Eliminar archivos no disponibles"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nuevo"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
-msgstr "Reno_mbrar…"
+msgstr "Reno_mbrar …"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "_Borrar"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
-msgstr "_Exportar ..."
+msgstr "E_xportar ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
-msgstr "_Gestor de listas de reproducción…"
+msgstr "_Gestor de listas de reproducción …"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
-msgstr "Gestor de _colas ..."
+msgstr "Gestor de _cola ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Subir volumen"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Bajar volumen"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ecualizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "E_fectos ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Mostrar barra de menú"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar barra de _información"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
-msgstr "Mostrar Barra de Información de Vis_ualización"
+msgstr "Mostrar barra de información de vis_ualización"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostrar barra de _estado"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
-msgstr "Mostrar_Tiempo Restante"
+msgstr "Mostrar _tiempo restante"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "Visualizaciones ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Archivo"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reproducción"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de reproducción"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servicios"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Sali_da"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Ver"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
-msgstr "_Encolar/desencolar"
+msgstr "_A_gregar/Quitar de la cola"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "A_brir carpeta contenedora"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
-msgstr "Cor_tar"
+msgstr "C_ortar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Pegar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleccionar _todo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Renombrar ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Pestañas de listas de reproducción</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Mostrar pestañas siempre"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Mostrar número de pista"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Mostrar botón de cierre"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Columnas de lista de reproducción</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Mostrar cabecera de las columnas"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
-msgstr ""
+msgstr "<b>Miscelánea</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Las teclas de dirección (flechas) dan saltos de:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Desplazar al cambiar de canción"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfaz GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Gestión de memoria intermedia ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estéreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canales"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo único."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo de lista de reproducción."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Parar después de la canción."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
-msgstr ""
+msgstr "Pista anterior"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproducir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
-msgstr "Pausa/continuar"
+msgstr "Pausa/Continuar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Detener"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
-msgstr ""
+msgstr "Pista siguiente"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
-msgstr ""
+msgstr "Adelantar 5 segundos"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
-msgstr ""
+msgstr "Atrasar 5 segundos"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenciar"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Subir volumen"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Bajar volumen"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Ir al archivo"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
-msgstr ""
+msgstr "Minimizar/Restaurar ventana(s)"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar notificaciones"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
-msgstr ""
+msgstr "Alternar repetir"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
-msgstr ""
+msgstr "Alternar modo aleatorio"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
-msgstr ""
+msgstr "Parar/Continuar tras esta canción"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Elevar la(s) ventana(s)"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
-msgstr "(ninguno)"
+msgstr "(ninguna)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1950,15 +2191,11 @@ msgstr ""
 "\n"
 "¿Quiere continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Asociar botones del ratón"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuración de atajos de teclado"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1966,23 +2203,27 @@ msgstr ""
 "Pulse una combinación de teclas dentro del campo de texto.\n"
 "También puede asociar botones del ratón."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Atajos de teclado:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Acción:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Teclas asociadas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Añadir"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Atajos de teclado globales"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1996,132 +2237,114 @@ msgid ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
+"Complemento «Atajos de teclado globales»\n"
+"Controla el reproductor con combinaciones de teclado globales o teclas "
+"multimedia.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n"
+"\n"
+"Contribuidores:\n"
+"Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+"Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+" Bryn Davies <curious at ihug.com.au>,\n"
+" Jonathan A. Davis <davis at jdhouse.org>,\n"
+" Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Hotkeys Globales"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Salida JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Conectar automáticamente a los puertos de salida"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Sólo se encontraron %d puertos de salida JACK, pero se necesitan %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Error de conexión al puerto JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
+"JACK sólo soporta audio en coma flotante . Debe cambiar a «Coma flotante» la "
+"opción «Profundidad de bits» en los ajustes de salida de sonido."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Error de conexión al servidor JACK. ¿Está ejecutándose?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
+"El servidor JACK requiere una frecuencia de muestreo de %d Hz, pero "
+"Audacious está reproduciendo a %d Hz. Por favor, usa el efecto «Convertidor "
+"de frecuencia de muestreo» para corregir este desfase."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Salida JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Ajustes %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Ajustes del servidor LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Rutas de complementos:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
-"<small>Separe múltiples rutas por dos puntos.\n"
-"Estas rutas se utilizan además de LADSPA_PATH.\n"
+"<small>Separe múltiples rutas con dos puntos.\n"
+"El uso de estas rutas se suma al de la variable de entorno LADSPA_PATH.\n"
 "Tras añadir nuevas rutas, pulse Intro para buscar complementos nuevos.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Complementos disponibles:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Activar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
-msgstr "Complementos activos:"
+msgstr "Complementos habilitados:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ajustes"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
+"Host LADSPA para Audacious\n"
+"Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
-msgstr ""
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: No se puede iniciar soporte LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: no se pudo leer archivo de configuración LIRC\n"
-"%s: Por favor, lee la documentación de LIRC %s: cómo crear un archivo de "
-"configuración LIRC\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: intentando conectar de nuevo... \n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando desconocido \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desconectado de LIRC\n"
+msgstr "Host LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: se intentará reconectar cada %d segundos…\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Complemento LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2136,74 +2359,95 @@ msgid ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
+"Un complemento sencillo para controlar Audacious usando el demonio de "
+"control remoto LIRC\n"
+"\n"
+"Portado para Audacious por:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Basado en el complemento «XMMS LIRC», creado por:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"Para obtener más información sobre LIRC, visitar http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Conexión</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Volver a conectar con el servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Espera antes de reconectar:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr ""
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Complemento de LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "No hay letras disponibles."
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
-#, c-format
-msgid "Unable to fetch %s"
-msgstr "No es posible obtener %s"
-
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Error"
 msgstr "Error"
 
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
+#, c-format
+msgid "Unable to fetch %s"
+msgstr "No se pudo obtener %s"
+
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
-msgstr ""
+msgstr "No se pudo interpretar %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Buscando letras ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
-msgstr ""
+msgstr "Metadatos de canción ausentes"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Conectando con lyrics.wikia.com…"
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Complemento de LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Complemento LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
-msgstr "Listas M3U"
+msgstr "Listas de reproducción M3U"
+
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Marcador de compás"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
-msgstr "Generador de tacto: %d ppm"
+msgstr "Marcador de compás: %d ppm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
-msgstr "Generador de tacto: %d ppm %d/%d"
+msgstr "Marcador de compás: %d ppm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2211,163 +2455,205 @@ msgid ""
 "e.g. tact://77 to play 77 beats per minute\n"
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
+"Un marcador de compás, creado por Martin Strauss <mys at faveve.uni-stuttgart."
+"de>\n"
+"\n"
+"Emula un metrónomo. Para usarlo, añada un URL de la forma: tact://"
+"pulsos*numerador/denominador\n"
+"p.ej. tact://77 para generar 77 pulsos por minuto\n"
+"o tact://60*3/4  para generar 60 ppm con un compás de 3/4"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generador Tact"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mezclador de canales"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
+"Complemento «Mezclador de canales» para Audacious\n"
+"Copyright 2011-2012 John Lindgren y Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mezclador de canales</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canales de salida:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mezclador de canales"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
-msgstr "Plugin para MMS"
+msgstr "Complemento para MMS"
+
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Error de conexión al servidor MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (reproductor MOD)"
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
-msgstr ""
+msgstr "<b>Resolución</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
-msgstr ""
+msgstr "8 bits"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
-msgstr ""
+msgstr "16 bits"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canales</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Más cercano (más rápido)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineal (rápido)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
-msgstr ""
+msgstr "Spline (bueno)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
-msgstr ""
+msgstr "Polifásico (el mejor)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr ""
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Frecuencia de muestreo</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
-msgstr ""
+msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
-msgstr ""
+msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
-msgstr ""
+msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
-msgstr ""
+msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
-msgstr ""
+msgstr "Nivel:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
-msgstr ""
+msgstr "Corte:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
-msgstr ""
+msgstr "<b>Reverberación</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
-msgstr ""
+msgstr "<b>Refuerzo de graves</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
-msgstr ""
+msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
-msgstr ""
+msgstr "<b>Preamplificación</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
-msgstr ""
+msgstr "Sobremuestreo"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Reducción de ruido"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
-msgstr ""
+msgstr "Reproducir archivos MOD de Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repetir</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
-msgstr "Cuenta de repetición:"
+msgstr "Número de repeticiones:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
-msgstr "Para repetir siempre, establezca el número de repeticiones en -1."
-
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
 msgstr ""
+"Para repetir infinitamente, establezca el número de repeticiones en -1."
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Envolvente"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Estos ajustes tendrán efecto cuando se reinicie Audacious."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
-msgstr ""
+msgstr "Complemento MPG123"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avanzado</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Cálculo preciso de duración (lento)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
 
-#: src/mpris2/plugin.c:403
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
-msgstr ""
+msgstr "Servidor MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
-msgstr ""
+msgstr "Complemento Neon HTTP/HTTPS"
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Error procesando redirección"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Error HTTP desconocido"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Error procesando URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Demasiadas redirecciones"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Detenido"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious no está reproduciendo."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificaciones de escritorio"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2386,56 +2672,81 @@ msgid ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
+"Complemento «Notificaciones de escritorio» para Audacious\n"
+"Copyright (C) 2010 Maximilian Bogner\n"
+"Copyright (C) 2011-2013 John Lindgren y Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"Este complemento es software libre: usted puede redistribuirlo y/o "
+"modificarlo bajo los términos de la Licencia Pública General GNU, publicada "
+"por la «Free Software Foundation» (Fundación para el software libre), ya sea "
+"la versión 3 de la Licencia, o (a su elección) cualquier versión posterior.\n"
+"\n"
+"Este programa se distribuye con la esperanza de que sea útil, pero SIN "
+"GARANTÍA ALGUNA; ni siquiera la garantía implícita de COMERCIALIZACIÓN o "
+"IDONEIDAD APTITUD PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la "
+"Licencia Pública General GNU para obtener una información más detallada.\n"
+"\n"
+"Debería haber recibido una copia de la Licencia Pública General GNU junto a "
+"este programa. En caso contrario, consulte <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Mostrar controles de reproductor"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
-msgstr "Siempre demostrar notificaciónes"
+msgstr "Mantener siempre visible"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr ""
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Incluir nombre del álbum"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Mostrar"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausar"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Siguiente"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo predeterminado"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Salida OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Salida OSS3"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo predeterminado"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo de sonido:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Utilizar dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
-msgstr "Guadar la configuración de volumen de una sesión a otra."
+msgstr "Preservar la configuración de volumen entre sesiones."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Activar conversiones de formato realizadas por el software OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Activa el modo exclusivo para evitar la mezcla virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2443,20 +2754,42 @@ msgid ""
 "I would like to thank people on #audacious, especially Tony Vroon and John "
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
+"Complemento «Salida OSS4» para Audacious\n"
+"Copyright 2010-2012 Michał Lipski\n"
+"\n"
+"Quiero expresar mi agradecimiento a toda la gente de #audacious, "
+"especialmente a Tony Vroon y John Lindgren, y, por supuesto, a los autores "
+"del anterior complemento OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr ""
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Gestor de listas de reproducción"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Pistas"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Borrar"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Renombrar"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
-msgstr ""
+msgstr "Listas de reproducción PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
-msgstr ""
+msgstr "Descodificador OpenPSF PSF1/PSF2"
+
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Salida PulseAudio"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2475,149 +2808,247 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
+"Complemento «Salida PulseAudio» para Audacious\n"
+"\n"
+"Este programa es software libre: usted puede redistribuirlo y/o modificarlo\n"
+"bajo los términos de la Licencia Pública General GNU, publicada por la\n"
+"«Free Software Foundation» (Fundación para el software libre), ya sea la\n"
+" versión 2 de la Licencia, o (a su elección) cualquier versión posterior.\n"
+"\n"
+"Este programa se distribuye con la esperanza de que sea útil,\n"
+"pero SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita de\n"
+"COMERCIALIZACIÓN o IDONEIDAD PARA UN PROPÓSITO DETERMINADO.\n"
+"Consulte los detalles de la Licencia Pública General GNU para obtener\n"
+"una información más detallada.\n"
+"\n"
+"Debería haber recibido una copia de la Licencia Pública General GNU\n"
+"junto a este programa. En caso contrario, escriba a Free Software\n"
+"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
+"USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Salida QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
+"Complemento «Salida de audio QtMultimedia» para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el complemento «Salida SDL» para Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Trabajando ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Buscar"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "A_brir carpeta"
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "Añadi_r carpeta"
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Inspector de registro..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Abrir archivos"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Añadir archivos"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Orden aleatorio"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interfaz Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertidor de frecuencia de muestreo"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
+"Complemento «Convertidor de frecuencia de muestreo» para Audacious\n"
+"Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
-msgstr "Saltar/repetir muestras"
+msgstr "Saltar/Repetir muestras"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolación lineal"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
-msgstr ""
+msgstr "Interpolación sinc (rápida)"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
-msgstr ""
+msgstr "Interpolación sinc (media)"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
-msgstr ""
+msgstr "Interpolación sinc (la mejor)"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversión</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
-msgstr "Taza:"
+msgstr "Tasa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
-msgstr ""
+msgstr "<b>Mapeo de frecuencias</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
-msgstr ""
+msgstr "Usar mapeo de frecuencias"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Muestra de convertidor de frecuencia"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
-msgstr "Aprovado. Scrobbling para usario: %s"
+msgstr "Aprobado. Scrobbling para usario: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
-msgstr "Permiso Denegado"
+msgstr "Permiso denegado"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "Acceda a esta página para permitir scrobbling en Audacious:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
+"Mantenga esta ventana abierta y haga clic en «Comprobar el permiso» otra "
+"vez.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
+"No se preocupe: sus scrobbles se guardan en su equipo.\n"
+"Se enviarán tan pronto como Audacious reciba la autorización necesaria."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problema de la red"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Hubo un problema al contactar con Last.fm. Por favor inténtelo de nuevo más "
 "tarde."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Comprobando..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "C_omprobar el permiso"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
-msgstr "Revocar el Permiso"
+msgstr "Revocar el permiso"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
-"Usted necesidad permitir scrobbling a Audacious a su cuenta de Last.fm. ⏎\n"
+"Necesita autorizar a Audacious para hacer scrobbling a su cuenta de Last."
+"fm.\n"
+
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
-"El plugin Scrobbler no se pudo iniciar. ⏎\n"
+"No se pudo iniciar el complemento Scrobbler.\n"
 "Puede haber un problema con la instalación."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2627,844 +3058,921 @@ msgid ""
 "project.\n"
 "\n"
 msgstr ""
-"Complemento Audacious Scrobbler  2.0 por Pitxyoki, ⏎\n"
-"⏎\n"
-"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com> ⏎\n"
-"⏎\n"
-"Gracias a John Lindgren por darme una mano en el inicio de este proyecto. ⏎\n"
-"⏎\n"
-
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
+"Complemento «Scrobbler  2.0» de Audacious, creado por Pitxyoki,\n"
+"\n"
+"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Muchas gracias a John Lindgren por su ayuda en el comienzo de este "
+"proyecto.\n"
+"\n"
 
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
+"Audacious usa ahora una versión mejorada del Scrobbler de Last.fm.\n"
+"Busque «Scrobbler» en la sección de «Complementos» de las «Preferencias»."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Salida SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
+"Complemento «Salida SDL» para Audacious\n"
+"Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Salida SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteca"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista Desconocido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Álbum Desconocido"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr " %s⏎ en %s de %s "
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultado"
+msgstr[1] "%d resultados"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] "%d álbumes"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d oculto)"
+msgstr[1] "(%d ocultos)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s⏎\n"
-"%s, %d cancion"
-msgstr[1] ""
-"%s⏎\n"
-"%s, %d canciones"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s⏎\n"
-"%d cancion de %s"
-msgstr[1] ""
-"%s⏎\n"
-"%d canciones de %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d canción"
+msgstr[1] "%d canciones"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "de este género"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "en"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "por"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crear lista de reproducción"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Añadir a la lista de reproducción"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
-msgstr "Buscar biblioteca"
+msgstr "Explorar biblioteca"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 "Para importar su biblioteca musical en Audacious, seleccione una carpeta y "
-"pulse el botón «actualizar»."
+"pulse el botón «Actualizar»."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Espere por favor..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Seleccione un directorio"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Reproductor SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Salida</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canales:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulación</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emular MOS 8580 (predeterminado: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "No seleccionar automáticamente el chip"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emular filtro"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Frecuencia de reloj:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "No seleccionar automáticamente la frecuencia"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Tiempo de reproducción</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Establecer tiempo máximo de reproducción:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Sólo con pistas de duración desconocida"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Establecer tiempo mínimo de reproducción:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtonos</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Habilitar subtonos"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorar subtonos de menos de:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nota</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Eliminación de silencios"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
 msgstr ""
+"Complemento «Eliminación de silencios» para Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Eliminación de silencios</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Umbral:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Abrir archivos ..."
+
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
-msgstr ""
+msgstr "Abrir URL ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Explorar biblioteca"
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reproducción"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de reproducción"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Servicios"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Acerca de ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Preferencias ... "
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Salir"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
+msgstr "Información de la canción ..."
 
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Orden aleatorio"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "No avanzar la lista de reproducción"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
+msgstr "Detener después de esta canción"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
-msgstr ""
+msgstr "Crear bucle (puntos A-B)"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
-msgstr ""
+msgstr "Borrar bucle"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Ir a la canción ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Ir al momento ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr ""
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Reproducir/Continuar"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nueva lista de reproducción"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Renombrar lista ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Borrar lista ..."
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Lista anterior"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Lista siguiente"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Importar lista ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Exportar lista ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Gestor de listas ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Gestor de cola ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Actualizar lista de reproducción"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostrar el editor de listas de reproducción"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostrar el ecualizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Mostrar tiempo restante"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Siempre encima"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "En todas las áreas de trabajo "
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
-msgstr ""
+msgstr "Enrollar reproductor"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
-msgstr ""
+msgstr "Enrollar editor de lista de reproducción"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
-msgstr ""
+msgstr "Enrollar ecualizador"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Duplicar tamaño"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "Añadir URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Añadir archivos ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Por título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Por nombre de archivo"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "Por ruta de archivo"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Eliminar todo"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Limpiar la cola"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Eliminar los archivos no disponibles"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Eliminar duplicados"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Eliminar los no seleccionados"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Eliminar los seleccionados"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Buscar y seleccionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertir la selección"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "No seleccionar nada"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Seleccionar todo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Por álbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Por número de pista"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Por artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Por álbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Por artista del álbum"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
-msgstr ""
+msgstr "Por fecha de lanzamiento"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Por número de pista"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Por género"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Por duración"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Por título personalizado"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Ordenar aleatoriamente"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Invertir la lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordenar los seleccionados"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenar lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Pegar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "Agregar/Quitar de la cola"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Cargar preajuste ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
-msgstr ""
+msgstr "Cargar de Predefinidos ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Cargar predeterminado"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Cargar de archivo ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Cargar EQF ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Guardar preajuste ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
-msgstr ""
+msgstr "Añadir a Predefinidos ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Guardar como predeterminado ..."
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Guardar a archivo"
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Guardar como EQF ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Borrar preajuste ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
-msgstr ""
+msgstr "Borrar predefinido ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Importar de Winamp ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "Reiniciar"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
-msgstr "Interfaz Clásica de Winamp"
+msgstr "Interfaz clásica de Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Guardar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Cargar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Cargar archivo de preajuste"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Cargar archivo EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Guardar como archivo de preajuste"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Guardar como archivo EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Importar preajustes de Winamp"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
-msgstr "Predefinidos"
+msgstr "Preajustes"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
-msgstr "Cargar predefinido"
+msgstr "Cargar preajuste"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
-msgstr "Cargar auto-predefinido"
+msgstr "Cargar preajuste predefinido"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
-msgstr "Guardar predefinido"
+msgstr "Guardar preajuste"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
-msgstr "Guardar auto-predefinido"
+msgstr "Guardar preajuste como predefinido"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
-msgstr "Borrar predefinido"
+msgstr "Borrar preajuste"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
-msgstr "Borrar auto-predefinido"
+msgstr "Borrar preajuste predefinido"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Reproductor:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Reproductor:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Seleccione la tipografía para la ventana principal:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "Lista de reproducción:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lista:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Seleccione la tipografía de la lista de reproducción:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Tema</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Fuentes</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
-msgstr "Usar tipografías de mapa de bits (solo soporta ASCII)"
+msgstr "Usar fuentes de mapa de bits (sólo soporta ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Desplazar el título de la canción"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Desplazar el título de la canción en ambas direcciones"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Campo"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
-msgstr ""
+msgstr "Impresión vocal / Vúmetro"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Apagado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fuego"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr ""
+msgstr "Líneas verticales"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Líneas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Muy lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Medio"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Muy rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "Puntos"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Línea"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Sólido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Hielo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Tipo</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Visualización:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Analizador</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Mostrar picos"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Coloreado:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Estilo:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
-msgstr ""
+msgstr "Descenso:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
-msgstr ""
+msgstr "Descenso de los picos:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
-msgstr ""
+msgstr "Estilo de campo:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
-msgstr ""
+msgstr "Coloreado de impresión vocal:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
-msgstr ""
+msgstr "Estilo de vúmetro:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "General"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualización"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificador"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ecualizador de Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Ir a la posición %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volumen: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% izquierda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: centrado"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% derecha"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menú de opciones"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desactivar 'Siempre encima'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Activar 'Siempre encima'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caja de información de archivo"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualizaciones"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
-msgstr "Repetir punto de establecimiento A."
+msgstr "Punto A del bucle."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
-msgstr "Repetir punto de establecimiento B."
+msgstr "Punto B del bucle."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
-msgstr "Repetir punto de establecimiento borrados."
-
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo único."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo de lista de reproducción."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Parar después de la canción."
+msgstr "Borrar bucle."
 
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
-msgstr "Buscar entradas en la lista de reproducción activa"
+msgstr "Buscar en la lista de reproducción activa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "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."
 msgstr ""
-"Seleccione entradas en la lista de reproducción indicando uno o más campos. "
-"Los campos utilizan sintaxis de expresiones regulares, sin distinguir "
-"mayúsculas de minúsculas. Si no sabe como funcionan las expresiones "
-"regulares, tan solo escriba la parte del literal que quiere buscar."
+"Seleccione entradas de la lista de reproducción rellenando uno o más campos. "
+"Estos campos aceptan expresiones regulares. Si no comprende esto, tan sólo "
+"escriba el texto que desea buscar. No se distinguen mayúsculas de minúsculas."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Título: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Título:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Álbum: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Álbum:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artista:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nombre del archivo: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nombre de archivo:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Limpiar la selección previa antes de buscar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
-msgstr "Conmutar automáticamente la cola para las entradas coincidentes"
+msgstr "Reemplazar la cola actual por las entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
-msgstr "Crear una nueva lista de reproducción con las entradas coincidentes"
+msgstr "Crear una nueva lista de reproducción con las coincidencias"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de listas de reproducción de Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x archivado"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x no archivado"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "No se pudo crear el directorio (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Complemento Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3485,80 +3993,92 @@ msgid ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
+"Basado en el complemento xmms_sndfile:\n"
+"Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
+"\n"
+"Adaptado para Audacious por Tony Vroon <chainsaw at gentoo.org>\n"
+"\n"
+"Este programa es software libre: usted puede redistribuirlo y/o modificarlo "
+"bajo los términos de la Licencia Pública General GNU, publicada por la «Free "
+"Software Foundation» (Fundación para el software libre), ya sea la versión 2 "
+"de la Licencia, o (a su elección) cualquier versión posterior.\n"
+"\n"
+"Este programa se distribuye con la esperanza de que sea útil, pero SIN "
+"GARANTÍA ALGUNA; ni siquiera la garantía implícita de COMERCIALIZACIÓN o "
+"IDONEIDAD PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la "
+"Licencia Pública General GNU para obtener una información más detallada.\n"
+"\n"
+"Debería haber recibido una copia de la Licencia Pública General GNU junto a "
+"este programa. En caso contrario, escriba a Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr ""
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Acerca del complemento de salida Sndio"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Salida Sndio"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Dispositivo (en blanco por defecto):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato no soportado"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Guardar y restaurar volumen:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Error de sndio: formato de audio (%d) no soportado"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Error de sndio: sio_open() falló"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(Vacio significa por defecto)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Error de sndio: sio_setpar() falló"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Aceptar"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Error de sndio: sio_start() falló"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Cambio de canción"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando a ejecutar cuando Audacious reproduce una canción nueva."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Los parámetros enviados a la consola deberían encerrarse "
+"entre comillas. Hacer lo contrario supone un riesgo de seguridad.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Comandos</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando para ejecutar al final de una canción."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Comando a ejecutar al empezar una nueva canción:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Comando para ejecutar cuando Audacious llega al final de una lista de "
-"reproducción."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Comando a ejecutar al acabar una canción:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Comando a ejecutar al concluir la lista de reproducción:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Comando para ejecutar cuando el título cambia para una canción (es decir, "
-"títulos de flujos en red)"
+"Comando a ejecutar cuando el título de la canción cambie (para flujos de "
+"red):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3572,20 +4092,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
+"Puede usar las siguientes cadenas de formato, que serán sustituidas antes de "
+"invocar los comandos (algunas no son válidas para el comando de fin de lista "
+"de reproducción):\n"
+"\n"
+"%F: Frecuencia (en hercios)\n"
+"%c: Número de canales\n"
+"%f: Nombre de archivo (ruta completa)\n"
+"%l: Duración (en milisegundos)\n"
+"%n o %s: Nombre de la canción\n"
+"%r: Tasa (en bits por segundo)\n"
+"%t: Posición en la lista de reproducción (%02d)\n"
+"%p: Reproduciendo (1 o 0)\n"
+"%a: Artista\n"
+"%b: Álbum\n"
+"%T: Título de pista"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Información de la canción (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Remuestreador SoX"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Los parámetros enviados a la consola se deberían "
-"encapsular con comillas. De otra forma existe un riesgo de seguridad.</span>"
-
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandos"
-
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3593,52 +4124,57 @@ msgid ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
+"Complemento «Remuestreador SoX» para Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Basado en el complemento «Convertidor de frecuencia de muestreo»:\n"
+"Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
-msgstr "Rapido"
+msgstr "Rápido"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Bajo"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alto"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Muy Alto"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Calidad"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidad y tono"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
-msgstr "<b>Velocidad y Tono</b>"
+msgstr "<b>Velocidad y tono</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidad:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tono:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidad y tono"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icono de estado"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "Pre_ferencias ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3648,64 +4184,74 @@ msgid ""
 "This plugin provides a status icon, placed in\n"
 "the system tray area of the window manager."
 msgstr ""
+"Complemento «Icono de estado»\n"
+"\n"
+"Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Copyright 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"Este complemento proporciona un icono de estado, que se muestra\n"
+"en la bandeja del sistema del gestor de ventanas."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
-msgstr ""
+msgstr "<b>Acción al deslizar la rueda del ratón</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Cambiar el volumen"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Cambiar la canción en reproducción"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Otros parámetros</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desactivar la ventana emergente"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Cerrar a la bandeja del sistema"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avanzar en la lista de reproducción al desplazar arriba"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icono de estado"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra estéreo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
+"Complemento «Extra estéreo»\n"
+"\n"
+"Escrito por Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
-msgstr "<b>Extra Estéreo</b>"
+msgstr "<b>Extra estéreo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr ""
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generador de tonos"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generador de tonos: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3713,16 +4259,18 @@ msgid ""
 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
+"Generador de tonos sinusoidales creado por Håvard Kvålen <havardk at xmms.org>\n"
+"Modificado por Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"Para usarlo, añada un URL de la forma: tone://frecuencia1;frecuencia2;"
+"frecuencia3;...\n"
+"p.ej. tone://2000;2005 para reproducir un tono de 2000 Hz y otro de 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generador de tonos"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Eliminación de voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3742,45 +4290,107 @@ msgid ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
+"Descodificador Ogg Vorbis para Audacious\n"
+"\n"
+"Basado en el complemento «Ogg Vorbis» de la Fundación Xiph.org:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Código original escrito por:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Con contribuciones de:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
-msgstr "Decodificador Ogg Vorbis"
+msgstr "Descodificador Ogg Vorbis"
+
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detalles sobre %s"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Título: %t\n"
+"Autor: %a\n"
+"De: %f\n"
+"Secuenciador: %T\n"
+"Comentario: %C\n"
+"Tipo de chip: %c\n"
+"Estéreo: %s\n"
+"Bucle: %l\n"
+"Chip freq: %F\n"
+"Frecuencia de reproducción: %P\n"
+"Año: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Descodificador VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
+"Reproductor Vortex creado por Sashnov Alexander <sashnov at ngs.ru>\n"
+"Basado en in_vtx.dll, creado por Roman Sherbakov <v_soft at microfor.ru>\n"
+"Complemento para Audacious escrito por Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Decodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Descodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "con pérdida (híbrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "con pérdida"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Parte del código del complemento escrita por Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Decodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
-msgstr "Decodificador 2SF"
+msgstr "Descodificador 2SF"
+
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configuración XSF</b>"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorar duración del archivo"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
-msgstr ""
+msgstr "Listas de reproducción XML (XSPF)"
diff --git a/po/es_AR.po b/po/es_AR.po
index 18c98886dda1..73d2df99e58f 100644
--- a/po/es_AR.po
+++ b/po/es_AR.po
@@ -9,11 +9,11 @@
 # xukosky <xukosky at yahoo.es>, 2011
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/"
 "audacious/language/es_AR/)\n"
 "Language: es_AR\n"
@@ -22,40 +22,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estéreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "envolvente"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Reproductor AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Reproductor AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -66,11 +54,7 @@ msgstr ""
 "\n"
 "Escrito originalmente por Adam Feakin y Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -93,7 +77,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -115,7 +99,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -129,183 +113,156 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Esta es su llamada despertador"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Recordatorio"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Lunes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Martes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Miércoles"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Jueves"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Viernes"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Configuración de la alarma"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Tiempo"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma a (predeterminado):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silencio tras:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Seleccione los días para que salte la alarma"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Día"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Predeterminado"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Días"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Desvanecimiento"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volumen"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Iniciar a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "activar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de reproducción (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Elegir una lista de reproducción"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opciones"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "¿Qué significan estas opciones?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ayuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Arte de tapa"
 
-#: src/alsa/config.c:210
-msgid "Default PCM device"
-msgstr "Dispositivo PCM predeterminado"
-
-#: src/alsa/config.c:239
-msgid "Default mixer device"
-msgstr "Dispositivo mezclador predeterminado"
-
-#: src/alsa/config.c:428
-msgid "PCM device:"
-msgstr "Dispositivo PCM:"
-
-#: src/alsa/config.c:430
-msgid "Mixer device:"
-msgstr "Dispositivo mezclador:"
-
-#: src/alsa/config.c:432
-msgid "Mixer element:"
-msgstr "Elemento mezclador:"
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Evitar los cuelgues por falta de recursos"
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Salida ALSA"
 
-#: src/alsa/plugin.c:27
+#: src/alsa/config.cc:28
 msgid ""
 "ALSA Output Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren\n"
@@ -320,175 +277,208 @@ msgstr ""
 "quien se ha asistido con el código y la referencia cuando el manual de ALSA "
 "no era suficiente."
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Salida ALSA"
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr "Dispositivo PCM predeterminado"
 
-#: src/amidi-plug/amidi-plug.c:466
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr "Dispositivo mezclador predeterminado"
+
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr "Dispositivo PCM:"
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr "Dispositivo mezclador:"
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr "Elemento mezclador:"
+
+#: src/amidi-plug/amidi-plug.cc:41
 msgid "AMIDI-Plug (MIDI Player)"
 msgstr "Plug-AMIDI (Reproductor MIDI)"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "Complemento AMIDI - seleccione un archivo SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nombre del archivo"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamaño (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nombre:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Información MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Longitud (mseg):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Nro. de Pistas:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div tiempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Comentarios y letras MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* no hay comentarios disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* no hay letras disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Cerrar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 no válido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Acerca del Plug-MIDI"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -499,152 +489,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Visualización en pantalla)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectángulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectángulo redondeado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectángulo cóncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ninguno"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Reproducción iniciada"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Avisa cuando se reproduce un elemento de la lista de reproducción."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cambio de título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Avisa cuando, durante la reproducción, el título de la canción cambia pero "
-"el nombre de archivo es el mismo. Esto es principalmente útil para mostrar "
-"cambios de título en los flujos de Internet."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Inicio de pausa"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Avisa cuando la reproducción es pausada."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Fin de pausa"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Avisa cuando la reproducción se reanuda."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Colocación"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Desplazamiento X relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Desplazamiento Y relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Ancho máximo:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opciones multi-monitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Mostrar notificaciones utilizando:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "todos los monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Temporización (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Mostrar:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Desvanecimiento de entrada:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Desvanecimiento de salida:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Tipografías"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Tipografía %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo de renderizado"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Color %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Activar disparador"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Administrador de composición detectado"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -655,112 +639,112 @@ msgstr ""
 "administrador de composición o las notificaciones no funcionarán "
 "correctamente"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Administrador de composición no necesario para transparencia falsa"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparencia"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparencia falsa"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparencia real (requiere composición 3D)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Extensión de composición no cargada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Extensión de composición no disponible"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Notificaciones de Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Notificaciones de Audacious - configuración"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posición"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animación"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoración"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Disparador"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Varios"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de reproducciónASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listas de reproducción Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Color</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Niebla Borrosa"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Estereofónico-a-Binaural Bauer (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Predefinidos:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nivel de alimentación:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Cortar frecuencia:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Predefinidos:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Estereofónico-a-Binaural Bauer (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizador de Espectro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Plugin de CD de audio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -772,171 +756,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Leer velocidad:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Anular dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadatos</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Usar CD-Texto"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usar CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Usar HTTP en lugar de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Ruta:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Puerto:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Plugin de CD de audio"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Error en la inicialización del subsistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI inválido %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Pista %d no encontrada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Error al abrir la salida de audio."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD de audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Error al abrir la lectora de CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "No hay audio que se pueda reproducir en la lectora de CD localizada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Error al finalizar la lectora de CD inicializada oportunamente."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Error al obtener el primer/último número de pista."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "No se puede leer el LSN del comienzo/final de la pista %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Error al crear la conexión a cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Error al consultar el servidor CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Error al consultar el servidor CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Error al leer la información cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "La unidad está vacía."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco no soportado."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Items de menú del CD de audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproducir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Agregar CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Items de menú del CD de audio"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compresión</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar volumen:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Rango dinámico:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Plugin de Compresión de Rango Dinámico para Audacious\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compresor de Rango Dinámico"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -946,200 +915,225 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Graves:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Longitud de canción predeterminada:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Activar el remuestreo de sonido"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Tasa de remuestreo:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorar longitud de etiquetas SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumentar la reverberación"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Decodificador musical de videoconsola"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"El fundido de pistas falló porque las canciones tiene distintas cantidades "
-"de canales.  Puede usar el Mezclador de Canales para igualarlos."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"El fundido de pistas falló porque las canciones tiene distintas "
-"velocidades.  Puede usar el Convertidor de Muestreo de Velocidad para "
-"igualarlos."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Fundido de pistas</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Superposición:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Fundido de pistas:"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"El fundido de pistas falló porque las canciones tiene distintas cantidades "
+"de canales.  Puede usar el Mezclador de Canales para igualarlos."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"El fundido de pistas falló porque las canciones tiene distintas "
+"velocidades.  Puede usar el Convertidor de Muestreo de Velocidad para "
+"igualarlos."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidad:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Plugin para hoja cue"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Borrar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Retardo:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retroalimentación:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volumen:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Plugin FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1149,55 +1143,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Plugin FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Plugin FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato del archivo de salida:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Guardar dentro del directorio original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Guardar dentro de directorio personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Carpeta de archivo de salida:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Elija una carpeta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obtener nombre de archivo desde:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "etiquetas del archivo original"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nombre del archivo original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "No quitar la extensión del archivo"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Anteponer el número de pista al nombre de archivo"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1215,165 +1209,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Plugin FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Estéreo conjunto"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuración MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Calidad del algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Frecuencia de muestreo de salida:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Tasa de bits / Compresión:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Tasa de bits (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Compresión:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modo de sonido:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Varios:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Cumplir estrictamente la norma ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Error de protección"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Calidad"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Activar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opciones VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Tasa de bits mínima (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Tasa de bits máxima (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Aplicar estrictamente la tasa de bits mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opciones ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Tasa de bits promedio (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nivel de calidad VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "No escribir la cabecera VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parámetros del marco:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marcar como derechos de autor"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marcar como original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Parametros ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forzar adición de etiqueta de la versión 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Solo agregar etiqueta v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Solo agregar etiqueta v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuración de codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nivel de calidad (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Decodificador FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1381,21 +1379,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Decodificador FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Plugin GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1407,530 +1409,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Accesos directos para GNOME"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número de entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Año"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Género"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posición de la cola"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Longitud"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Ruta del archivo"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nombre del archivo"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Tasa de bits"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Herramienta de búsqueda"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Acoplar a la izquierda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Acoplar a la derecha"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Acoplar arriba"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Acoplar abajo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desacoplar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Deshabilitar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Herramienta de búsqueda"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Abrir archivos ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Añadir archivos ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Añadir U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "A_cerca de ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Salir"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Reproducir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Pa_usar"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Detener"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "An_terior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Si_guiente"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "R_epetir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Orden aleatorio"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "No avan_zar la lista de reproducción"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Información de la canción ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_Saltar en el tiempo ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Saltar a la _canción ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Por _título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Por _número de pista"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Por _artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Por _fecha de estreno"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Por _ruta de archivo"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Por título _personalizado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Orden _inverso"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Orden alea_torio"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Reproducir esta lista de reproducción"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "A_ctualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordenar"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Eliminar archivos _no disponibles"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nuevo"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Ren_ombrar..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Administrador_de listas de reproducción ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Gestor de _colas ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Subir volumen"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Bajar volumen"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ecualizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Mostrar barra de menú"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar barra de _información"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Mostrar la Barra Informativa de Vis_ualización"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostrar barra de _estado"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Archivo"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reproducción"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de reproducción"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servicios"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Sali_da"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Ver"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Encolar/desencolar"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Cor_tar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Pegar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleccionar _todo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Renombrar ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfaz GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Gestión de memoria intermedia ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estéreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canales"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo único."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo de lista de reproducción."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Parar después de la canción."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproducir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausa/continuar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Detener"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenciar"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar notificaciones"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ninguno)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1941,15 +2020,11 @@ msgstr ""
 "\n"
 "¿Quiere continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Asociar botones del mouse"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuración de atajos de teclado"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1957,23 +2032,27 @@ msgstr ""
 "Pulse una combinación de teclas dentro del campo de texto.\n"
 "También puede asociar botones del ratón."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Atajos de teclado:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Acción:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Teclas asociadas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Teclas abreviadas globales"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1988,56 +2067,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Teclas abreviadas globales"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Salida JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Salida JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Ajustes %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Ajustes del servidor LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Rutas de complementos:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2048,71 +2122,39 @@ msgstr ""
 "Tras añadir nuevas rutas, pulse Intro para buscar complementos nuevos.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Complementos disponibles:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Activar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Complementos activos:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ajustes"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "Servidor LADSPA"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: no se puede iniciar soporte LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: no se puede leer el archivo de configuración de LIRC\n"
-"%s: por favor lea la documentación de LIRC\n"
-"%s: en el tópico \"Cómo crear un archivo de configuración adecuado\"\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: tratando de reconectar...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando desconocido \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desconectando de LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: se intentará reconectar cada %d segundos...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Plugin LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2128,73 +2170,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Conexión</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Reconectar a servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Espera antes de reconectar:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Plugin LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Plugin LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "No se encontraron letras"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Error"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "No se puede obtener %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Error"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "No se puede analizar %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Buscando letras de la canción...."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "No hay metadatos de la canción"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Conectándose con lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Plugin LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listas de reproducción M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Generador de tacto"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Generador de tacto: %d ppm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generador de tacto: %d ppm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2203,162 +2253,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generador de tacto"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mezclador de canales"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mezclador de canales</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canales de salida:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mezclador de canales"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Plugin MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Módulo de reproducción)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Módulo de reproducción)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Envolvente"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 Plugin"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Envolvente"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 Server"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS Plugin"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Detenido"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious no está reproduciendo."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificaciones de escritorio"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2378,55 +2460,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notificaciones de escritorio"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausar"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Siguiente"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo predeterminado"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Salida OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo de sonido:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Utilizar dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Guardar volumen entre sesiones."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Activar conversiones de formato realizadas por el software OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Activa el modo exclusivo para evitar la mezcla virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2435,19 +2526,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Salida OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listas PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Abrir el decodificador PSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Salida de PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2467,143 +2574,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Salida de PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Orden aleatorio"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertidor de Velocidad de Muestra"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Saltear/repetir muestras"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolación lineal"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolación de sincronización rápida "
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolación de sincronización media"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Mejor interpolación de sincronización "
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversión</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Velocidad:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapeos de velocidad</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Usar mapeos de velocidad"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertidor de Velocidad de Muestra"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2614,97 +2790,72 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Salida SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Salida SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteca"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista Desconocido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Album Desconocido"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" en %s por %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] "%d álbumes"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d canción"
 msgstr[1] ""
-"%s\n"
-" %s, %d canciones"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d canción por %s"
 msgstr[1] ""
-"%s\n"
-" %d canciones por %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crear lista de reproducción"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Añadir a la lista de reproducción"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Buscar biblioteca"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2712,679 +2863,769 @@ msgstr ""
 "Para importar su colección musical en Audacious, elija una carpeta y pulse "
 "el botón «actualizar»."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Espere por favor..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Elija una carpeta"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reproducción"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de reproducción"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Orden aleatorio"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "No avanzar la lista de reproducción"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nueva lista de reproducción"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostrar el editor de listas de reproducción"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostrar el ecualizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Siempre encima"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Por título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Por nombre de archivo"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Eliminar todo"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Limpiar la cola"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Eliminar los archivos no disponibles"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Eliminar duplicados"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Eliminar los no seleccionados"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Eliminar los seleccionados"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Buscar y seleccionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertir la selección"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "No seleccionar nada"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Seleccionar todo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Por álbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Por número de pista"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Por artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Por álbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Por número de pista"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Ordenar aleatoriamente"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Invertir la lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordenar los seleccionados"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenar lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Pegar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface del Winamp Clásico"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Guardar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Cargar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Predefinidos"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Cargar predefinido"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Cargar auto-predefinido"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Guardar predefinido"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Guardar auto-predefinido"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Borrar predefinido"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Borrar auto-predefinido"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Reproductor:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Seleccione la tipografía para la ventana principal:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "Lista de reproducción:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Seleccione la tipografía de la lista de reproducción:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Usar tipografías de mapa de bits (solo soporta ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Desplazar el título de la canción en ambas direcciones"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Campo"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Apagado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fuego"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Líneas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Muy lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Medio"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Muy rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Hielo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "General"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualización"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificador"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ecualizador de Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Ir a la posición %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volumen: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% izquierda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: centrado"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% derecha"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menú de opciones"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desactivar 'Siempre encima'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Activar 'Siempre encima'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caja de información de archivo"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo único."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo de lista de reproducción."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Parar después de la canción."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Buscar entradas en la lista de reproducción activa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3396,57 +3637,61 @@ msgstr ""
 "mayúsculas de minúsculas. Si no sabe como funcionan las expresiones "
 "regulares, tan solo escriba la parte del literal que quiere buscar."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Título: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Álbum: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nombre del archivo: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Limpiar la selección previa antes de buscar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Conmutar automáticamente la cola para las entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Crear una nueva lista de reproducción con las entradas coincidentes"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de listas de reproducción de Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x archivado"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x no archivado"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "No se pudo crear el directorio (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Plugin Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3468,85 +3713,71 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Plugin Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Acerca del Plugin de Salida Sndio"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Plugin de Salida Sndio\n"
-"\n"
-"Escrito por Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "formato no soportado"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Un formato no soportado por el dispositivo de audio fue solicitado.\n"
-"\n"
-"Por favor,intente de nuevo con el servidor sndiod(1) ejecutándose."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(el vacío significa algo)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Aceptar"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Cambio de canción"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando a ejecutar cuando Audacious reproduce una canción nueva."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Los parámetros enviados a la consola se deberían "
+"encapsular con comillas. De otra forma existe un riesgo de seguridad.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando para ejecutar al final de una canción."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
-"Comando para ejecutar cuando Audacious llega al final de una lista de "
-"reproducción."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Comando para ejecutar cuando el título cambia para una canción (es decir, "
-"títulos de flujos en red)"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3560,35 +3791,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Puede usar los siguientes cadenas de formatos, las cuales\n"
-"serán reemplazadas antes de invocar al comando\n"
-"(no todos son útiles para el comando finalizar lista de reproducción):\n"
-"\n"
-"%F: Frecuencia (en hertz)\n"
-"%c: Número de canales\n"
-"%f: Nombre de archivo (ruta completa)\n"
-"%l: Duración (en milisegundos)\n"
-"%n o %s: Nombre de la canción\n"
-"%r: Velocidad (en bits por segundo)\n"
-"%t: Posición en la lista de reproducción (%02d)\n"
-"%p: Reproduciendo actualmente (1 or 0)\n"
-"%a: Artista\n"
-"%b: Album\n"
-"%T: Título de la pista"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Los parámetros enviados a la consola se deberían "
-"encapsular con comillas. De otra forma existe un riesgo de seguridad.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandos"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3597,51 +3809,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidad y amplitud"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocidad y amplitud</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidad:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Amplitud:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidad y amplitud"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icono de estado"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3652,63 +3864,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Acción al desplazar rueda del mouse<b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Cambiar el volumen"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Cambiar la canción en reproducción"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Otras Opciones<b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desactivar la ventana emergente"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Cerrar a la barra tray"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avanzar en la lista de reproducción al desplazar arriba"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icono de estado"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Esteréo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Estéreo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Esteréo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generador de Tono"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generador de tonos: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3717,15 +3929,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generador de Tono"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Quitar voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3746,44 +3954,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Decodificador Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Decodificador VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Decodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Decodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Decodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Decodificador 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Listas de reproducción compartidas XML (XSPF)"
diff --git a/po/es_MX.po b/po/es_MX.po
index d7c696e30ea6..f950c6fab813 100644
--- a/po/es_MX.po
+++ b/po/es_MX.po
@@ -3,14 +3,15 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Jorge A. García Sosa <jagsmd at gmail.com>, 2012-2014
+# Jorge A. García Sosa <kamesennin555 at icloud.com>, 2012-2014
+# Jorge A. García Sosa <kamesennin555 at icloud.com>, 2014-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-13 16:17+0000\n"
-"Last-Translator: Jorge A. García Sosa <jagsmd at gmail.com>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-08 19:38+0000\n"
+"Last-Translator: Jorge A. García Sosa <kamesennin555 at icloud.com>\n"
 "Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/"
 "audacious/language/es_MX/)\n"
 "Language: es_MX\n"
@@ -19,40 +20,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "monoaural"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estéreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "envolvente"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Descodificador AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr "Descodificador AAC(RAW)"
+msgstr "Decodificador AAC (RAW)"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Reproductor AdLib)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "secuencializado"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Reproductor AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Programar Alarma ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +52,7 @@ msgstr ""
 "\n"
 "Orignalmente escrito por Adam Feakin y Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -109,7 +94,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -149,7 +134,7 @@ msgstr ""
 "    Ejecuta este comando a la hora de la alarma.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -173,384 +158,390 @@ msgstr ""
 "    Escribe el recordatorio en la caja y enciende el\n"
 "    botón interruptor si quieres que se muestre."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Esta es tu llamada despertador."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Tu recordatorio para hoy es..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Recordatorio"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Lunes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Martes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Miércoles"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Jueves"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Viernes"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Ajustes de Alarma"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_OK"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Cancelar"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Tiempo"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma a las (predeterminado):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silenciar después de:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Escoge los días para que suene la alarma"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Día"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Predeterminado"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Días"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Desvanecimiento"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volumen"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Comenzar a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Finalizar a"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando Adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "habilitar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de Reproducción (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Selecciona una lista de reproducción"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opciones"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "¿Qué significan estás opciones?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ayuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Portada de Álbum"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Arte de Álbum (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Salida ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Plugin de salida ALSA\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Mis agradecimientos a William Pitcock, autor del plugin NG de salida ALSA, "
+"cuyo código sirvió como referencia cuando el manual ALSA no era suficiente."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(sin descripción)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositivo PCM predeterminado"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositivo mezclador predeterminado"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositivo PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositivo mezclador:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemento mezclador:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Evitar colapsos por falta de recursos"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Reproductor MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Plugin de salida ALSA\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"Reproductor modular de música MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Mis agradecimientos a William Pitcock, autor del plugin NG de salida ALSA, "
-"cuyo código sirvió como referencia cuando el manual ALSA no era suficiente."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Salida ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (Reproductor MIDI)"
+"escrito por Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"gracias especiales a...\n"
+"\n"
+"Clemens Ladisch y Jaroslav Kysela\n"
+"por sus chidos programas aplaymidi y amixer; estos\n"
+"fueron realmente útiles, junto con los docs alsa-lib, para\n"
+"aprender más sobre la API ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Anular ganancia predeterminada:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Anular polifonía predeterminada:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Anular reverberación predeterminada:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Encender"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Anular coro predeterminado:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Reproducir</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Transportar:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "semitonos"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Cambio de batería:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Avanzado</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "números de nota"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Extraer comentarios del archivo MIDI"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Saltar silencio inicial"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Extraer letras del archivo MIDI"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Saltar silencio final"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>SIntetizador</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Tasa de muestreo:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Tasa de bits:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - seleccionar archivo SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Abrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nombre del archivo"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamaño (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nombre:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Información MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Duración (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Núm. de Pistas:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div. tiempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Comentarios y Letras de canción MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* no hay comentarios disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* no hay letras de canción disponibles en este archivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Cerrar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 inválido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Acerca de AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"reproductor de música MIDI modular\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"escrito por Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"agradecimientos especiales a...\n"
-"\n"
-"Clemens Ladish y Jaroslav Kysela\n"
-"por sus chidos programas aplaymidi y amixer; fueron\n"
-"realmente útiles, junto con los documentos alsa-lib,\n"
-"para aprender más de la API ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"por el bonito logo de teclado midi\n"
-"\n"
-"Tony Vroon\n"
-"por la buena ayuda con las pruebas alfa."
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -568,154 +559,148 @@ msgstr ""
 "Basado en parte en la librería Ghosd de Evan Martin:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Mensaje en Pantalla)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectángulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectágulo Redondeado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectángulo Cóncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ninguno"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Iniciar Reproducción"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "Muestra Notificación en Pantalla cuando se reproduce un elemento de la lista "
 "de reproducción"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cambio de Título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"Muestra el Notificación en Pantalla cuando, en la reproducción, el título de "
-"la pista cambia pero el nombre del archivo es el mismo. Esto es muy útil "
-"para mostrar cambios de título en streams de internet."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Lanza OSD cuando el título de pista cambia (para streams de internet)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pausa Encendida"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Muestra Notificación en Pantalla cuando la reproducción está pausada."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pausa Apagada"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Muestra Notificación en Pantalla cuando la pausa termina."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Colocación"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Compensación relativa en X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Compensación relativa en Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Ancho máximo de OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opciones de varios monitores"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Mostrar OSD utilizando:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "Todos los monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Tiempo (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Mostrar:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Desvanecimiento al aparecer:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Desvanecimiento al desaparecer:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Fuentes"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Fuente %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo de Renderización"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Color %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Activar Aviso"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Administrador de composición detectado"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -726,112 +711,112 @@ msgstr ""
 "administrador de composición, de otra forma las  Notificaciones en Pantalla "
 "no funcionarán apropiadamente"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Administrador de composición no requerido para transparencia falsa"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparencia"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparencia falsa"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparencia real (requiere X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Extensión de composición no cargada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Extensión de composición no disponible"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - configuración"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Probar"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "E_stablecer"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posición"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animación"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoración"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Avisos"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Misc."
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Probar"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "Listas de reproducción ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de reproducción ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Lista de reproducción Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Color</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Predefinidos:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nivel de alimentación:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Frecuencia de corte:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Predefinidos:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizador de Espectro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Plugin CD de Audio  "
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -852,171 +837,158 @@ msgstr ""
 "\n"
 "Este fue un proyecto del Google Summer of Code 2007"
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocidad de lectura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Reemplazar dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadatos</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Usar CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usar CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Utilizar HTTP en vez de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Ruta de Acceso:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Puerto:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Plugin CD de Audio  "
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Falla al iniciar el susbsistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI %s no válido."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Pista %d no encontrada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Pista %d es una pista de datos."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Falló al abrir la salida de audio."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Error al leer CD de audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD de Audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Pista %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Fallo al abrir el dispositivo de CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "No se encontró drive de CD capaz de reproducir audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Fallo al terminar de preparar drive de CD  abierto."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Fallo al recuperar el primer/último número de pista."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "No se puede leer LSN inicio/final para la pista %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Fallo al crear la conexión cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Fallo al consultar el servidor CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Fallo al consultar el servidor CDDB: %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Fallo al leer la nformación cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "La unidad de disco está vacía."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco no soportado."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Entradas del Menú del CD de Audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproducir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Agregar CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Entradas del Menú del CD de Audio"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compresión</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar volumen:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Rango dinámico:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Plugin de Compresión de Rango Dinámico  para Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Plugin de Compresión de Rango Dinámico para Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compresor de Rango Dinámico"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1025,214 +997,246 @@ msgid ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
-"Motor de descodificador de música de consola basado en Game_Music_Emu 0.5.2\n"
+"Motor decodificador de música de consola basado en Game_Music_Emu 0.5.2\n"
 "Formatos soportados: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM,VGZ\n"
 "\n"
 "Plugin para Audacious por:\n"
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bajos: "
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Duración de pista predeterminada:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Resampling</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Habilitar resampling de audio"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Frecuencia de resampling:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorar duración proveniente de las etiquetas SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumentar reverberación"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
-msgstr "Descodificador de Música de Consolas de Juego"
+msgstr "Decodificador de Música de Consolas de Juego"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Los fundidos fallaron porque las pistas tienen un número diferente de "
-"canales.  Puedes usar el Mezclador de Canales para convertir las pistas al "
-"mismo número de canales."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Salida CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Los fundidos fallaron porque las pistas tienen diferentes tasas de bitis.  "
-"Puedes usar el Convertidos de Tasas de Bits para convertir las pistas a la "
-"misma tasa."
+"Plugin CoreAudio Output  para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el Plugin de Salida SDL para Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Usar modo exclusivo"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Crossfade Plugin para Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Plugin Crossfade para Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Fundido</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Al cambio automático de pista"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Encimar:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Al buscar o cambio manual de pista"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Tip</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Para mejor desvanecimiento, habilita\n"
+"el efecto Remover Silencio."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Fundir"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Los fundidos fallaron porque las pistas tienen un número diferente de "
+"canales.  Puedes usar el Mezclador de Canales para convertir las pistas al "
+"mismo número de canales."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Los fundidos fallaron porque las pistas tienen diferentes tasas de bitis.  "
+"Puedes usar el Convertidos de Tasas de Bits para convertir las pistas a la "
+"misma tasa."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidad:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Plugin Cue Sheet"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Borrar Archivos"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Error al mover %s a la bandeja: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Error al borrar %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Error mientras borraba %s: no es un archivo local."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "¿Quieres mover los archivos seleccionados a la bandeja?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Mover a la bandeja"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "¿Quieres borrar permanentemente los archivos seleccionados?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Borrar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Borrar Archivos"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Borrar Archivos Seleccionados"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Borrar Método</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Mover a la bandeja en vez de borrar inmediatamente"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Plugin Echo\n"
+"Por Johan Levin, 1999\n"
+"Surround echo por Carl van Schaik, 1999\n"
+"Actualizado para Audacious por William Pitcock y John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Retraso:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retroalimentación:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volumen:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Plugin Echo \n"
-"Por Johan Levin, 1999\n"
-"\n"
-"Eco envolvente by Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Plugin FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1241,62 +1245,62 @@ msgid ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
-"Plugin descodificador de audio multi-formato para Audacious usando\n"
+"Plugin decodificador de audio multi-formato para Audacious usando\n"
 "el marco multimedia FFmpeg (http://www.ffmpeg.org/)\n"
 "\n"
 "Plugin para Audacious por:\n"
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Plugin FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Plugin FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato del archivo de salida:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Guardar en el directorio original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Guardar en un directorio personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Carpeta del archivo de salida:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Escoge una carpeta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obtener el nombre del archivo desde:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Generar nombre de archivo de:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "etiquetas del archivo original"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Etiqueta original del archivo"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nombre del archivo original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nombre de archivo original"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "No quitar la extensión del archivo"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Incluir extensión original del archivo"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Colocar primero el número de pista en el nombre del archivo"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Agregar número de pista al nombre de archivo"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1328,165 +1332,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA \n"
 "02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Plugin FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Estéreo Unido"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estéreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Monoaural"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuración MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Calidad del algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Frecuencia de muestrei de salida:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Tasa de Muestreo de Salida:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Relación de Tasa de bits / Compresión:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Tasa de Bits / Relación de Compresión:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Tasa de bits (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Tasa de Compresión"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modo de audio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Misc.:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Otros:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Forzar conformidad ISO estricta"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Cumplir normas ISO estrictas"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Error de protección"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Calidad"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Habilitar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opciones VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Tasa de bits mínima (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Tasa de bits máxima (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Forzar estríctamente tasa de bits mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opciones ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Promedio de tasa de bits (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nivel de calidad VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "No escribir encabezado VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omitir encabezado VBR Xing"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parametros de Marco:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "Parámetros de Marco:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marcar como copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marcar como original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parámetros ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forzar adición de etiquetas versión 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Sólo agrega etiqueta v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Sólo agrega etiqueta v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuración del codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nivel de calidad (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Decodificador FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sin pérdida"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1498,11 +1506,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Descodificador FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1510,11 +1514,19 @@ msgstr ""
 "Plugin GIO para Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Plugin GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Modo leer-y-anexar no soportado"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "modo abierto invalido"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1534,534 +1546,620 @@ msgstr ""
 "\n"
 "Licencia: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analizador de Espectro OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"OpenGL Spectrum Analyzer para Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, y Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el plugin XMMS:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, y "
+"4Front Technologies\n"
+"\n"
+"Licencia: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analizador de Espectro OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Atajos GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Plugin de Atajos Gnome\n"
-"Te permite controlar el reproductor con los atajos de Gnome.\n"
+"Plugin de Atajos GNOME\n"
+"Te permite controlar el reproductor con atajos de GNOME's.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Atajos Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número de entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Año"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Álbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artista de Álbum"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Género"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posición en cola"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Duración"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Ruta del archivo"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nombre del archivo"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Tasa de bits"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Columnas disponibles"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Columnas mostradas"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Herramienta de Búsqueda"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Acoplar a la izquierda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Acoplar a la derecha"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Acoplar arriba"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Acoplar abajo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desacoplar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Dehabilitar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Herramienta de Búsqueda"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Abrir archivos..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "A_gregar archivos..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Agregar U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Buscar en Bib_lioteca"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "A_cerca..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Ajustes"
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Salir"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Reproducir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Pa_usa"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Detener"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Anterior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Siguie_nte"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Repe_tir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "A_leatorio"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_No avanzar Lista de Reprod."
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Detener D_espués de Esta Pista"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Información de pista..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Saltar al _tiempo"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Saltar a la _pista"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Configura Punto _A de Repetición"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Configura Punto _B de Repetición"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Borrar Puntos de Repetición"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Por _Título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "Por _Nombre de Archivo"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Por _Ruta de Archivo"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Por _Núm de pista"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Por_Artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Por Al_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Por Artista de Álbu_m"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Por _Fecha de Lanzamiento"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Por _Género"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Por _Duración"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Por _Ruta del Archivo"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Por Título _Personalizado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Invertir Orden"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "O_rden Aleatorio"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Reproducir esta Lista de Reproducción"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Reproducir/Reanudar"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "A_ctualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordenar"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Ordenar Se_leccionados"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Remover _Duplicados"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Remover Archivos No _Disponibles"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nuevo"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Ren_ombrar ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Remo_ver"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Ad_ministrador de Listas de Reproducción ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Administrador de _Colas ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Aumentar Volumen"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Disminuir Volumen"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ecualizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_fectos ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Mostrar Barra de _Menú"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar Barra de I_nformación"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Mostrar Barra de Información de Vis_ualización"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostrar Barra de E_stado"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Mostrar Tiempo _Restante"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Visualizaciones ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Archivo"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reproducción"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de Reproducción"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servicios"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Salida"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Ver"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Formar/Desformar"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "A_brir Carpeta Contenedora"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Cor_tar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Pegar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleccion_ar todo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Renombrar ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Pestañas de Listas de Reproducción</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Siempre mostrar pestañas"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Mostrar total de entradas"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Mostrar botones para cerrar"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Columnas de Listas de Reproducción</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Mostrar encabezados de columna"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Misceláneo</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Teclas de flechas buscan por:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Desplazar al cambiar de pista"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfaz GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Almacenando en buffer..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "monoaural"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estéreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canales"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo sencillo."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo Lista de Reproducción."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Detener después de la pista."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Pista previa"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproducir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausa/Continuar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Detener"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Pista siguiente"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avanza 5 segundos"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Retrocede 5 segundos"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenciar"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Aumentar volumen"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Disminuir volumen"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Saltar al archivo"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Cambiar ventana(s) del reproductor"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar Notificaciones en Pantalla"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Repetir"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Aleatorio"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Detener después de actual"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Aumentar ventanas(s) del reproductor"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ninguno)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2072,15 +2170,11 @@ msgstr ""
 "\n"
 "¿Quieres continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Asociar botones del ratón"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuración del Plugin Global Hotkey"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2088,23 +2182,27 @@ msgstr ""
 "Presiona una combinación de teclas dentro de un campo de texto.\n"
 "También puedes asociar botones del ratón."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Atajos del teclado:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Acción:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Asociación de Teclas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Agregar"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Hotkeys Globales"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2131,60 +2229,57 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Hotkeys Globales"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Salida JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Conectar a todos los puertos disponibles"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automáticamente conectar a puertos de salida"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Conectar solo a los puestos de salida"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
+"Solo %d puertos de salida JACK fueron encontrados pero %d son requeridos."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "No conectar a ningún puerto"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Falla al conectar al puerto JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Modo de conexión:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK solo soporta audio de punto flotante. Debes cambiar la profundidad de "
+"bit de salida a punto flotante en las preferencias de Audacious."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Habilitar impresión para depuración"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Falla al conectar al servidor JACK; ¿Se está ejecutando?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Basado en xmms-jack, por Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Llevado a Audacious por Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Salida JACK"
+"El servidor JACK requiere una tasa de muestra de %d Hz, pero audacious está "
+"reproduciendo a %d Hz. Por favor utiliza el efecto de Convertidor de Tasa de "
+"Muestra para corregir la discordancia."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Ajustes %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Ajustes del Host LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Rutas de Módulos:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2195,73 +2290,41 @@ msgstr ""
 "Después de agregar nuevas rutas, presiona Intro para buscar plugins nuevos.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Plugins disponibles:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Habilitar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Habilitar plugins:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ajustes"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
-"LADSPA Host for Audacious\n"
-"Copyright 2011 John Lindgren"
-msgstr ""
-"LADSPA Host para Audacious\n"
-"Copyright 2011 John Lindgren"
-
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "Huesped LADSPA"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: No se puede iniciar soporte LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: no se pudo leer archivo de configuración LIRC\n"
-"%s: Por favor, lee la documentación de LIRC\n"
-"%s: cómo crear un archivo de configuración LIRC adecuado\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: intentando reconectar...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando desconocido \"%s\"\n"
+"LADSPA Host for Audacious\n"
+"Copyright 2011 John Lindgren"
+msgstr ""
+"LADSPA Host para Audacious\n"
+"Copyright 2011 John Lindgren"
 
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desconectado de LIRC\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "Huesped LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: se intentará reconectar cada %d segundos...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Plugin LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2290,73 +2353,81 @@ msgstr ""
 "\n"
 "Para más información acerca de LIRC, ve a http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Conexión</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Reconectar a servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Espera entes de reconectar:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Plugin LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Plugin LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Letras de canción no disponibles"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Error"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Incapaz de traer %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Error"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Incapaz de analizar %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Buscando letras de canción ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Sin metadatos de pista"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Conectando a lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Plugin LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Plugin LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listas de Reproducción M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Generador Tact"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Generador de tact: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generador de tact: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2370,11 +2441,11 @@ msgstr ""
 "por ejemplo, tact://77 to reproducir 77 golpes por minuto\n"
 "o tact://60*3/4 para reproducir 60 bpm en ritmo 3/4"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generador Tact"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mezclador de Canales"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2382,152 +2453,184 @@ msgstr ""
 "Plugin Mezclador de Canales para Audacious.\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mezclador de Canales</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canales de salida:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mezclador de Canales"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Plugin MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Error al conectar al servidor MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (reproducor Module)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resolución</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canales</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Más cercano (más rápido)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linear (rápido)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Ranura (bueno)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifase (mejor)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Frecuencia de muestreo</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Tasa de Muestreo</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Nivel:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Corte:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverberación</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Bass Boost</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Envolvente</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Preamplificador</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Sobremuestra"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Reducción de ruido"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Reproducir MODs Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repetir</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Cuenta de repetición:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Para repetir por siempre, coloca la cuenta de repetición en -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (reproducor Module)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Envolvente"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Estos ajustes tomarán efecto cuando Audacious reinicie."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Plugin MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avanzado</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Usar el cálculo preciso de longitud (lento)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Envolvente"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Servidor MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Plugin Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Error al analizar redirección"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Error HTTP desconocido"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Error al analizar URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Demasiadas redirecciones"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Detenido"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious no está reproduciendo."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificaciones en Escritorio"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2563,55 +2666,64 @@ msgstr ""
 "Deberías haber recibido una copia de la GNU General Public License junto con "
 "este programa. Si no, mira en <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Mostrar los controles de reproducción"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Siempre mostrar la notificación"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notificaciones en Escritorio"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Incluir nombre del álbum en la notificación"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Mostrar"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausa"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Siguiente"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo predeterminado"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Salida OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Salida OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo por default"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo de audio:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Usar dispositivo alterno:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Guardar volumen entre sesiones."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Habilitar las conversiones de formato hechas por el software OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Habilitar modo exclusivo para prevenir mezclado virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2625,19 +2737,35 @@ msgstr ""
 "Me gustaría agradecer a la ente de #audacious, especialmente a Tony Vroon y "
 "John Lindgren y por supuesto a los autores del plugin OSS anterior."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Salida OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Administrador de Lista de Reproducción"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Entradas"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Remover"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Ren_ombrar"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listas de reproducción PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
-msgstr "Descodificador OpenPSF PSF1/PSF2"
+msgstr "Decodificador OpenPSF PSF1/PSF2"
+
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Salida PulseAudio"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2673,11 +2801,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA \n"
 "02110-1301, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Salida PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Salida QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Plugin de salida de Audio QtMultimedia para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basado en el Plugin de Salida SDL para Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Trabajando ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Buscar"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Abrir Carpeta ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Agregar Carpeta ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Inspector de Registro ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Abrir Archivos"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Agregar Archivos"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Aleatorio"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interface Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertidor de tasa de muestra"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2685,99 +2875,107 @@ msgstr ""
 "Plugin Sample Rate Converter para Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Saltar/repetir muestras"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolación linear"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolación de sincronización rápida"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolación de sincronización media"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Mejor Interpolación de sincronización"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversión</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Tasa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapeos de Tasas</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Usar mapeos de tasas"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertidor de tasa de muestra"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Agregando datos -scrobbling- para usuario: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Permiso Denegado"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Accede al siguiente vínculo para permitir que Audacious agregue datos -"
 "scrobble- a tus reproducciones:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Mantiene esta ventana abierta y da clic en  'Verificar Permiso' otra vez.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2785,34 +2983,38 @@ msgstr ""
 "No te preocupes. Tus datos agregados han sido guardados en tu computadora.\n"
 "Ellos serán enviados tan pronto como a Audacious le sea permitido hacerlo."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problema de Red."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Hay un problema contactando Last.fm. Por favor, intenta después."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Verificando..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "V_erificar Permiso"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Revocar Permiso"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Necesitas permitir que Audacious transfiera los metadatos  de las pistas "
 "\"scrobblee\" a tu cuenta Last.fm\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2820,7 +3022,7 @@ msgstr ""
 "El plugin Scrobbler no pudo ser iniciado.\n"
 "Puede haber un problema con tu instalación."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2837,11 +3039,7 @@ msgstr ""
 "Gracias a John Lindgren por echárme una mano al comienzo de este proyecto.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2849,7 +3047,11 @@ msgstr ""
 "Audacious está usando ahora una versión mejorada de Last.fm Scrobbler.\n"
 "Por favor revisa las Preferencias para el plugin Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Salida SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2857,81 +3059,56 @@ msgstr ""
 "Plugin de salida SDL para Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Salida SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Librería"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista Desconocido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Álbum Desconocido"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"en %s de %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultado"
+msgstr[1] "%d resultados"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] "%d álbumes"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d oculto)"
+msgstr[1] "(%d ocultos)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-"%s, %d pista"
-msgstr[1] ""
-"%s\n"
-"%s, %d pistas"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-"%d canción de %s"
-msgstr[1] ""
-"%s\n"
-"%d canciones de %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d pista"
+msgstr[1] "%d pistas"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "de este género"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "en"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "por"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crear Lista de Reproducción"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Agregar a la Lista de Reproducción"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Buscar librería"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2939,679 +3116,771 @@ msgstr ""
 "Para importar tu librería de música en Audacious, selecciona una carpeta y "
 "luego haz clic en el ícono \"actualizar\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Por favor espere..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Seleccione Carpeta"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Reproductor SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Salida</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canales:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulación</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emular MOS 8580 (default: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "No seleccionar automáticamente modelo de chip"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emular filtro"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Velocidad de reloj:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "No seleccionar automáticamente vel. de reloj"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Tiempo de reproducción</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Establecer tiempo máx. de reprod.:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Usar solo cuando la duración de pista es desconocida"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Establecer tiempo mínimo de reprod.:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtonos</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Habilitar subtonos"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorar subtonos más cortos que:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nota</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Remover Silencio"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Plugin Remover Silencio para Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Remover Silence</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Umbral:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Abrir Archivos ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Abrir URL ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Buscar Librería"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reproducción"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de Reproducción"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Servicios"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Acerca ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Ajustes ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Salir"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Información de Pista ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Aleatorio"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "No avanzar Lista de Reproducción"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Detener Al Terminar Esta Pista"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Establecer Repetición A-B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Limpiar Repetición A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Saltar a la Pista ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Saltar al Tiempo ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Reproducir Esta Lista de Reproducción"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Reproducir/Reanudar"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nueva Lista de Reproducción"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Renombrar Lista de Reproducción"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Remover Lista de Reproducción"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Lista de Reproducción Previa"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Siguiente Lista de Reproducción"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importar Lista de Reproducción ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Exportar Lista de Reproducción ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Administrador de Listas de Reproducción ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Administrador de Fila ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Refrescar Lista de Reproducción"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostrar Editor de Listas de Reproducción"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostrar Ecualizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Mostrar Tiempo Restante"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Siempre Encima"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "En Todas Las Áreas de Trabajo"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Enrollar Reproductor"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Enrollar Editor de Listas de Reproducción"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Enrollar Ecualizador"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Tamaño Doble"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Agregar URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Agregar Archivos ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Por Título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Por Nombre de Archivo"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Por Ruta de Archivo"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Quitar Todo"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Limpiar Cola de reproducción"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Remueve los Archivos No Disponibles"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Remover Duplicados"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Remover No Seleccionados"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Remover Seleccionados"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Buscar y Seleccionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertir Selección"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Selecciona ninguno"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Selecciona Todo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Por Álbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Por Número de Pista"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Por Artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Por Álbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Por Artista de Álbum"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Por Fecha de Lanzamiento"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Por Número de Pista"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Por Género"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Por Duración"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Por Título Personalizado"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Aleatorizar Lista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Invertir Lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordenar Seleccionado"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenar Lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Pegar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "A la Fila/Quitar de la Fila"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Cargar Preajuste ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Cargar Preajuste Automático ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Cargar Predeterminado"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Cargar Archivo de Preajuste ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Cargar Archivo EQF ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Guardar Preajuste ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Guardar Preajuste Automático ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Guardar Predeterminado"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Guardar Archivo de Preajuste ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Guardar Archivo EQF ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Borrar Preajuste ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Borrar Preajuste Automático ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importar Preajustes de Winamp ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Restablecer a Cero"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface Clásica de Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Guardar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Cargar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Cargar Archivo de Preajuste"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Cargar Archivo EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Guardar Archivo de Prejuste"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Guardar Archivo EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importar Preajuste de Winamp"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Presets"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Cargar preset"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Cargar auto-preset"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Guardar preset"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Guardar auto-preset"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Borrar preset"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Borrar auto-preset"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "Re_productor"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Reproductor:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Selecciona la fuente de la ventana principal del reproductor:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Lista de Reproducción:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lista de reproducción:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Selecciona la fuenta de la lista de reproducción:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Piel</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Fuentes</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Usar fuentes de mapa de bits (únicamente soporta ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Desplazar título de pista"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Desplaza el título de la pista en ambas direcciones"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizador de Espectro"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Osciloscopio"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Espectrograma vocal / medidor VU"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Apagado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fuego"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Líneas verticales"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Líneas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Muy lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Medio"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Muy rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Puntos"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Línea"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Sólido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Hielo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Tipo</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Tipo de visualización:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizador</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Mostrar picos"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Colorear:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Estilo:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Caída:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Caída de pico:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Estilo del Analizador de Espectro:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Color del Espectrograma vocal:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Estilo del medidor VU:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "General"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualización"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificación"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ecualizador de Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Saltar a %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volumen: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% izquierda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: central"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% derecha"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menú de Opciones"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Deshabilitar 'Siempre Encima'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Habilitar 'Siempre Encima'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caja de Información del Archivo"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualizaciones"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Repite punto A configurado."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Repite punto B configurado."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Repite puntos borrados."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo sencillo."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo Lista de Reproducción."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Detener después de la pista."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Buscar entradas en la lista de reproducción activa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Buscar"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3623,57 +3892,61 @@ msgstr ""
 "minísculas indiscriminadas. Si no sabes como trabajan las expresiones "
 "regulares, simplemente inserta una porción literal de lo que buscas."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Título: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Título:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Álbum: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Álbum:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artista:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nombre de Archivo: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nombre de Archivo:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Limpiar selección previa antes de buscar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Cambiar automáticamente la cola para las entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Crear una nueva lista de reproducción con las entradas coincidentes"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de Listas de Reproducción de Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Skin de Winamp 2.x comprimida"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Skin de winamp 2.x sin comprimir"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "No se puede crear el directorio (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Plugin Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3714,85 +3987,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA \n"
 "02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Plugin Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Acerca del Plugin de Salida Sndio"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Salida Sndio"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Plugin de Salida Sndio\n"
-"\n"
-"Escrito por Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Dispositivo (en blanco para predeterminado):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato no soportado"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Guardar y restaurar volumen:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Fue solicitado un formato no soportado por el dispositivo de audio.\n"
-"\n"
-"Por favor, intenta nuevamente con el servidor sndio(1) ejecutándose."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Error Sndio: Formato de audio no soportado (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Error Sndio: falló sio_open()"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(vacío significa predeterminado)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Error Sndio: falló sio_setpar()"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Error Sndio error: falló sio_start()"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Cambiar Pista"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando para ejecutar cuando Audacious comience una nueva pista."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parámetros enviados al shell deberán ser encapsulados en "
+"apóstrofes. Hacer otra cosa es un riesgo de seguridad.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Comandos</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Comando para ejecutar cuando inicie una nueva pista:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando para ejecutar al final de una pista."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Comando para ejecutar al finalizar una pista:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Comando para ejecutar cuando Audacious alcance el final de una lista de "
-"reproducción."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Comando para ejecutar al finalizar una lista de reproducción:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Comando para ejecutar cuando el título de una pista cambie (por ejemplo, "
-"títulos de flujos de red)."
+"Comando para ejecutar cuando el título de pista cambie (para transmisión por "
+"red):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3806,34 +4067,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Puedes usar las siguiente cadenas de formato las\n"
-"cuales serán sustituidas antes de llamar al comando\n"
-"(no todas son útiles para el comando end-of-playlist):\n"
+"Puedes usar los siguientes formatos de cadena que serán sustituidos antes de "
+"llamar\n"
+"al comando (no todos son útiles para el comando al finalizar lista de "
+"reproducción):\n"
 "%F: Frecuencia (en hertz)\n"
 "%c: Número de canales\n"
-"%f: Nombre de archivo (ruta completa)\n"
+"%f: Nombre del archivo (ruta completa)\n"
 "%l: Duración (en milisegundos)\n"
-"%n: o %s: Nombre de pista\n"
+"%n o %s: Nombre de pista\n"
 "%r: Tasa (en bits por segundo)\n"
-"%t: Posición en la lista de reproducción (%02d)\n"
+"%t: Posición en Lista de Reproducción (%02d)\n"
 "%p: Actualmente reproduciendo (1 ó 0)\n"
 "%a: Artista\n"
 "%b: Álbum\n"
 "%T: Título de pista"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Parámetros enviados al shell deberán ser encapsulados en "
-"apóstrofes. Hacer otra cosa es un riesgo de seguridad.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Info. de Pista (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandos"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3847,51 +4105,51 @@ msgstr ""
 "Basado en el Plugin Sample Rate Coverter\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rápido"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Bajo"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alto"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Muy Alto"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Calidad:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidad y Tono"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocidad y Tono</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidad:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tono:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidad y Tono"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ícono de Estado"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Ajus_tes ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3909,39 +4167,39 @@ msgstr ""
 "Este plugin provee un ícono de estado, colocado en el área \n"
 "de la bandeja del sistema del administrador de la ventana."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Acción de rueda central del mouse</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Cambiar volumen"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Cambiar pista en reproducción"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Otras Configuraciones</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Deshabilitar la ventana emergente"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Cerrar a la bandeja del sistema"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avanzar en la lista de reproducción cuando se desplace hacia arriba"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Ícono de Estado"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Estéreo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3951,24 +4209,24 @@ msgstr ""
 "\n"
 "Por Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Estéreo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Estéreo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generador de Tonos"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generador de tonos: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3983,15 +4241,11 @@ msgstr ""
 "por ejemplo, tone://2000;2005 to reproducir un tono de2000 Hz tone y un tono "
 "de 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generador de Tonos"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Removedor de Voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4011,7 +4265,7 @@ msgid ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
-"Descodificador Audacious Ogg Vorbis\n"
+"Decodificador Audacious Ogg Vorbis\n"
 "\n"
 "Basado en el Plugin Ogg Vorbis de Xiph.org Foundation:\n"
 "http://www.xiph.org/\n"
@@ -4029,11 +4283,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
-msgstr "Descodificador Ogg Vorbis"
+msgstr "Decodificador Ogg Vorbis"
+
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detalles sobre %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Título: %t\n"
+"Autor: %a\n"
+"De: %f\n"
+"Tracker: %T\n"
+"Comentario: %C\n"
+"Tipo de Chip: %c\n"
+"Estéreo: %s\n"
+"Loop: %l\n"
+"Frec. de Chip: %F\n"
+"Frec. de Reprod: %P\n"
+"Año: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Decodificador VTX"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4044,19 +4333,19 @@ msgstr ""
 "Basado en in_vtx.dll por Roman Sherbakov <v_soft at microfor.ru>\n"
 "Plugin para Audacious por Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Descodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Decodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "con pérdida (híbrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "con pérdida"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4066,23 +4355,18 @@ msgstr ""
 "\n"
 "Algo del código del plugin era de Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Descodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
-msgstr "Descodificador 2SF"
-
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "Listas de Reprod. XML Compartibles (XSPF)"
+msgstr "Decodificador 2SF"
 
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configuración XSF</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorar duración del archivo"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "Listas de Reprod. XML Compartibles (XSPF)"
diff --git a/po/et.po b/po/et.po
index 942eef4cc8e6..56859149b6e8 100644
--- a/po/et.po
+++ b/po/et.po
@@ -7,11 +7,11 @@
 # Ivar Smolin <okul at linux.ee>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Estonian (http://www.transifex.com/projects/p/audacious/"
 "language/et/)\n"
 "Language: et\n"
@@ -20,51 +20,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr ""
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Äratus"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Äratus"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -87,7 +71,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -109,7 +93,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -123,360 +107,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "See on sinu äratus."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Meeldetuletaja"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Esmaspäev"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Teisipäev"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Kolmapäev"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Neljapäev"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Reede"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Laupäev"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Pühapäev"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Äratuste sätted"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Aeg"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Vaikimisi äratuskell:"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr " "
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Vaigistamine pärast:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "tundi"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutit"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Vali päevad, mil äratus tööle hakkab"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Päev"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Vaikimisi"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Päevad"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Sumbumine"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekundit"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Valjus"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Alguses"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Lõpuks"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Praegune"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Täiendav käsk"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "lubatud"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Esitusnimekiri (valikuline)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Valikud"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Mida need valikud tähendavad?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Abi"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Albumi graafika"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr ""
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Vaikimisi PCM-seade"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Vaikimisi mikserseade"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM-seade:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Miksimisseade:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Miksimiselement:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - SoundFont faili valimine"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Failinimi"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Faili nimi"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Suurus (baitides)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nimi:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI-andmed </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Vorming:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Kestus (msek):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI kommentaarid ja laulusõnad </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* selles MIDI-failis pole kommentaare *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* selles MIDI-failis pole laulusõnu *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Sul_ge"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (vigane UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -487,263 +477,258 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Ristkülik"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Ümarnurkne ristkülik"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Nõgus ristkülik"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Puudub"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Esitamise alustamine"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "OSD käivitamine loo esitamisel esitusnimekirjast."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Pealkirja muutumine"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"OSD käivitamine kui esitamise ajal loo pealkiri muutub, kuid esitatav fail "
-"või andmevoog jääb samaks. See on kasulik internetiraadiote puhul."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pausimine"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "OSD käivitamine loo pausimisel."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pausi lõpetamine"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "OSD käivitamine pausitud loo jätkamisel."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Paigutus"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Suhteline nihe X-teljel:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Suhteline nihe Y-teljel:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Suurim OSD laius:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Mitme monitori valikud"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD kuvatakse:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "kõigil monitoridel"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "%i. monitoril"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Ajastus (millisekundites)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Kuvamine:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Sujuv näitamine:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Sujuv peitmine:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Kirjatüübid"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Kirjatüüp %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Vari"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Renderdamise laad"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Värvused"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Värvus %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Päästik on lubatud"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Sündmus"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD won't work properly"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Läbipaistvus"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Võltsitud läbipaistvus"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Tegelik läbipaistvus (vajab X Composite laiendust)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audaciouse OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - sätted"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Asukoht"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animatsioon"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Tekst"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Kaunistused"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Päästikud"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Muu"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2-esitusnimekirjad"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audaciouse esitusnimekirjad (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr ""
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "Valmisseadistused:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -755,169 +740,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP asemel kasutatakse HTTP-d"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio-CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Seade on tühi."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Plaadi liik pole toetatud."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audioplaadi menüüvalikud"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Esita CD-lt"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Lisa CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Audioplaadi menüüvalikud"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr ""
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr ""
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -927,195 +899,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Madalad:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Kõrged:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Loo vaikimisi kestus:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr ""
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr ""
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC-siltidest pärit pikkust tuleb eirata"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr ""
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Mängukonsooli muusikadekooder"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Kustuta"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Loobu"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Kaja</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Viivitus:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Kaja"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr ""
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1125,55 +1122,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Väljundfaili vorming:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Seadista..."
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Salvestatakse algkataloogi"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Salvestatakse kohandatud kataloogi"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Väljundkataloog:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Kataloogi valimine"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Failinimi tuletatakse lähtefaili:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "siltidest"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nimest"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Algse faili laiendit maha ei lõigata"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Failinime ette lisatakse loo number"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1191,165 +1188,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automaatne"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr ""
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 sätted"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmi kvaliteet:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Väljundi diskreetimissagedus:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitikiirus / pakkimistihedus:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitikiirus (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Pakkimistihedus"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audiorežiim:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Muu:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Veakaitse"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kvaliteet"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr ""
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Liik:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr ""
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Vähim bitikiirus (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Suurim bitikiirus (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr ""
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Keskmine bitikiirus (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
 msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr ""
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr ""
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr ""
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3-parameetrid:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Lisatakse ainult v1 silt"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Lisatakse ainult v2 silt"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Sildid"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis-kodeerija sätted"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Kvaliteedi tase (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1357,21 +1358,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO-plugin"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1383,530 +1388,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Kirje number"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Pealkiri"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Esitaja"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Aasta"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Lugu"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Žanr"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Asukoht järjekorras"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Kestus"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Faili rada"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Faili nimi"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Kohandatud pealkiri"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitikiirus"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Otsinguvahend"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Doki vasakule"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Doki paremale"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Doki üles"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Doki alla"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Keela"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Otsinguvahend"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Ava failid ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Ava _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Lisa faile ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Lisa U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Programmist lähemalt"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Välju"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Esita"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Peata"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Seiska"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Ee_lmine"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Järgmine"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Ko_rduv"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Se_gatud"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Esitusnimekirja ei _kasutata"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "L_oo andmed ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_Hüppa määratud ajale..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Vaheta lugu ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Peal_kirja järgi"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Loo _numbri järgi"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "_Esitaja järgi"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "_Väljalaske kuupäeva järgi"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "_Faili raja järgi"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Ko_handatud pealkirja järgi"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Pööra järjestus tagurpidi"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Järjestus juhuslikuks"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Esita selle _nimekirja lood"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Värskenda"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Sordi"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Ee_malda kättesaamatud failid"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Uus"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Muu_da nime"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Impordi ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Ekspordi ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Esitusnimekirjade _haldur.."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Halda _järjekorda ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Valjemaks"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Va_iksemaks"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ekvalaiser"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Menüüriba on nähtaval"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "_Teaberiba on nähtaval"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_Olekuriba on nähtaval"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fail"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Esitamine"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "E_situsnimekiri"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Teenused"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Väl_jund"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Vaade"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Järjekorda/järjekorrast maha"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Lõika"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopeeri"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Aseta"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Val_i kõik"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Muuda nime..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK liides"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Puhverdamine ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d kanal"
 msgstr[1] "%d kanalit"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Ühe loo režiim."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Esitusnimekirja režiim."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Seiskamine pärast loo lõppu."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Esita"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausimine/pausi lõpetamine"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Seiska"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Heli tummaks"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "OSD sisse-/väljalülitamine"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr ""
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1917,15 +1999,11 @@ msgstr ""
 "\n"
 "Kas soovid jätkata?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Hiirenuppude sidumine"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Globaalsete kiirklahvide plugina sätted"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1933,23 +2011,27 @@ msgstr ""
 "Vajuta tekstiväljal soovitud klahvikombinatsiooni.\n"
 "Samamoodi saab siduda ka hiirenuppe."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Kiirklahvid:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Tegevus:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Kiirklahv:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1964,56 +2046,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr ""
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s sätted"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA hosti sätted"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Moodulite rajad:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2024,71 +2101,39 @@ msgstr ""
 "radadelt.\n"
 "Pärast uute radade lisamist vajuta uute pluginate otsimiseks Enterit.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Saadaolevad pluginad:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Luba"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Lubatud pluginad:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Sätted"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC-tuge pole võimalik lähtestada\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC-seadistusfaili pole võimalik lugeda\n"
-"%s: korrektse seadistusfaili loomiseks\n"
-"%s: loe palun LIRC-dokumentatsiooni\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: tundmatu käsk \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC-plugin"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2104,73 +2149,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Ãœhendus</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Taasühendumine LIRC-serveriga"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Enne taasühendumist oodatakse"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC-plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Viga"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Viga"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Ãœhendumine saidiga lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U-esitusnimekirjad"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Taktigeneraator: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Taktigeneraator: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2179,162 +2232,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr ""
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanalimikser"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanalimikser</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Väljundkanalite arv:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanalimikser"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS-plugin"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Ruumiline heli"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Ruumiline heli"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS-plugin"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr ""
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Töölauateavitused"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2354,55 +2439,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Töölauateavitused"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausi"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Järgmine"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Vaikimisi seade"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audioseade:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Kasutatakse alternatiivset seadet:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2411,19 +2505,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS-esitusnimekirjad"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio väljund"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2443,143 +2553,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio väljund"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Eelmine"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Korduv"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Segatud"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Meetod:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22,05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44,1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2590,87 +2769,72 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL-väljund"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL-väljund"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Teek"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Tundmatu esitaja"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Tundmatu album"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d albumit"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "Loo _esitusnimekiri"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Lisa esitusnimekirja"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Otsing audiokogust"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2678,679 +2842,769 @@ msgstr ""
 "Oma audiokogu importimiseks Audaciousesse vali kataloog ja vajuta "
 "värskendamise ikoonile."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Palun oota..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Kataloogi valimine"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Esitamine"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Esitusnimekiri"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Vaade"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Korduv"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Segatud"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Esitusnimekirja ei kasutata"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Eelmine"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Uus esitusnimekiri"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Näita esitusnimekirja redaktorit"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Näita ekvalaiserit"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Alati pealmine"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Pealkirja järgi"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Failinime järgi"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Eemalda kõik"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Puhasta järjekord"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Eemalda kättesaamatud failid"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Eemalda korduvad kirjed"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Eemalda valimata kirjed"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Eemalda valik"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Otsi ja vali"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Vaheta valitud ja valimata"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Tühista valik"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Vali kõik"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Albumi järgi"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Loo numbri järgi"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Esitaja järgi"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Albumi järgi"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Loo numbri järgi"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Sega nimekiri"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Pööra järjestus ümber"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Valiku sortimine"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Nimekirja sortimine"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Lõika"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopeeri"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Aseta"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Salvesta"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Laadi"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Valmisseadistused"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Valmisseadistuste laadimine"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Valmisseadistuste salvestamine"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Valmisseadistuse kustutamine"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Esitaja:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Esitusnimekiri:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Esitusnimekirja kirjatüübi valimine:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Kasutatakse rasterkirja (toetab ainult ASCII kooditabelit)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Loo nime keritakse mõlemas suunas"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analüsaator"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Skoop"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Väljas"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Tavaline"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Tuli"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Jooned"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Tulbad"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Väga aeglane"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Aeglane"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Keskmine"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Kiire"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Väga kiire"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Jää"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Pehme"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Ãœldine"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualiseerimine"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audaciouse ekvalaiser"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr ""
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Valjus: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr ""
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr ""
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr ""
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Valikute menüü"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr ""
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr ""
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Ühe loo režiim."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Esitusnimekirja režiim."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Seiskamine pärast loo lõppu."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Otsimine aktiivsest esitusnimekirjast"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3361,57 +3615,61 @@ msgstr ""
 "kasutatakse tõstutundetut regulaaravaldise süntaksit. Kui sa pole "
 "regulaaravaldistega tuttav, siis sisesta lihtsalt otsitav sõnaosa."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Pealkiri: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Esitaja: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Failinimi: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Enne otsimist nullitakse eelmine valik"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Otsingule vastavatest kirjetest luuakse uus esitusnimekiri"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audaciouse esitusnimekirja redaktor"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d/%d-st)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Arhiveeritud Winamp 2.x rüü"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Arhiveerimata Winamp 2.x rüü"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Kataloogi (%s) pole võimalik luua: %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3433,77 +3691,72 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Olgu"
-
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Loovahetus"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Uue loo alustamisel käivitatav käsk:"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Käsureaprogrammile edastatavad parameetrid tuleks "
+"paigutada jutumärkide vahele. Selle tegematajätmine võib olla turvarisk.</"
+"span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Käsk:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Loo lõppemisel käivitatav käsk:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Esitusnimekirja lõppu jõudmisel käivitatav käsk:"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Loo pealkirja muutumisel käivitatav käsk (näiteks võrguraadio pealkirja "
-"muutumisel)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3518,20 +3771,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Käsureaprogrammile edastatavad parameetrid tuleks "
-"paigutada jutumärkide vahele. Selle tegematajätmine võib olla turvarisk.</"
-"span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Käsud"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3540,51 +3788,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Olekuikoon"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3595,63 +3843,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Hiireratta kerimine</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Muudab valjust"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Vahetab esitatavat lugu"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Muud sätted</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Hüpikaken on keelatud"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Sulgemine süsteemisalve"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Olekuikoon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr ""
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Toonigeneraator"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Toonigeneraator: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3660,15 +3908,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Toonigeneraator"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Hääle eemaldamine"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3689,44 +3933,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis dekooder"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX-dekooder"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX-dekooder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack dekooder"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack dekooder"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF-dekooder"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Jagatavad XML-esitusnimekirjad (XSPF)"
diff --git a/po/eu.po b/po/eu.po
index a5569c513157..4f20cc7ef02a 100644
--- a/po/eu.po
+++ b/po/eu.po
@@ -3,16 +3,16 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# asier <asier.fernandez.iribar at gmail.com>, 2013
+# asier fernandez iribar <asier.fernandez.iribar at gmail.com>, 2013
 # Iñaki Larrañaga Murgoitio <dooteo at euskalgnu.org>, 2009
 # Osoitz <oelkoro at gmail.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Basque (http://www.transifex.com/projects/p/audacious/"
 "language/eu/)\n"
 "Language: eu\n"
@@ -21,51 +21,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "monoa"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estereoa"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -88,7 +72,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -110,7 +94,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -124,360 +108,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Hau da zure esnatzeko deia:"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Gogorarazlea"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Astelehena"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Asteartea"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Asteazkena"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Osteguna"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Ostirala"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Larunbata"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Igandea"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarmaren ezarpenak"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Denbora"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma noiz (lehenetsia):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "o"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Isildu hau eta gero:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "orduak"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutuak"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Aukeratu alarmak jotzeko egunak"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Eguna"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Lehenetsia"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Egunak"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Progresioa"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundo"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Bolumena"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Hasi hemen "
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Bukaeran"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Oraingoa"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Komando gehigarria"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "gaitu"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Erreprodukzio-zerrenda (aukerazkoa)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Aukerak"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Zer esan nahi dute aukera hauek?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Laguntza"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Diskoaren azala"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr ""
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Lehenetsitako PCM gailua"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Lehenetsitako nahaslea"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM gailua:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Nahastailearen gailua:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Nahaslea:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - hautatu SoundFont fitxategia"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Fitxategi-Izena"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Fitxategi izena"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamaina (byte)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Izena:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI informazioa </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formatua:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Luzera (mseg.):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Pista kopurua:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "aldagaia"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Denbora zat:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI iruzkinak eta letrak </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* iruzkinik ez dago erabilgarri MIDI fitxategi honetan *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* letrarik ez dago erabilgarri MIDI fitxategi honetan *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 baliogabea)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -488,153 +478,147 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Laukizuzena"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Laukizuzen biribildua"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Laukizuzen ahurra"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Bat ere ez"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Erreprodukzioa hasi"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "OSDa abiarazten du erreprodukzio-zerrendako sarrera bat erreproduzitzean."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Titulu aldaketa"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"OSDa abiarazten du erreproduzitzean abestiaren titulua aldatzen bada, baina "
-"fitxategi-izena berdina bada. Interneteko korronteetan tituluen izenen "
-"aldaketak bistaratzeko da batizpat erabilgarria."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pausatuta"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "OSDa abiarazten du erreprodukzioa pausatzean."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Jarraitu"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "OSDa abiarazten du erreprodukzioa jarraitzean."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Kokalekua"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X desplazamendu erlatiboa:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y desplazamendu erlatiboa:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "OSDaren gehi. zabalera:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Pantaila anitzen aukerak"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Bistaratu OSDa hau erabiliz:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "pantaila guztiak"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "%i. pantaila"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Tenporizadorea (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Bistaratu:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Pixkanaka agertu:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Iraungitu:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Letra-tipoak"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "%i letra-tipoa:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Itzala"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Errendatze estiloa"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Koloreak"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "%i kolorea:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Gaitu abiarazlea"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Gertaera"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Kudeatzaile konposatua detektatuta"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -644,112 +628,112 @@ msgstr ""
 "Bat exekutatzen dagoela jakin ezean, aktibatu konposaketako kudeatzalea "
 "bestela OSDak ez du ongi funtzionatuko"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Gardentasun faltsua egiteko ez da konposaketako kudeaketak behar"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Gardentasuna"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Gardentasun faltsua"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Egitako gardentasuna (Xen konposaketa hed. behar da)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Konposaketako hedapena ez da kargatu"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Konposaketako hedapena ez dago erabilgarri"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSDa</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSDa - konfigurazioa"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posizioa"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animazioa"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Testua"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekorazioa"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Abiarazlea"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Hainbat"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD plugina"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -761,169 +745,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Gailua</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadatuak</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Erabili CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Erabili CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "HTTP erabili CDDBP ordez"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Zerbitzaria:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Bidea:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Portua:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD plugina"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CDa"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Unitatea hutsik dago"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Onartu gabeko disko mota."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Jo CDa"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Gehitu CDa"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Konpresioa</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Bolumen zentrala:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Bitarte dinamikoa:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -933,195 +904,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Baxua:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Altua:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Abestiaren luzera lehenetsia:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Gaitu audioa berriro lagintzea"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Birlagintze-tasa:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ezikusi egin SPCko etiketetako luzerari"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Handiagotu reverb-a"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Joko Kontsola Musika Deskodetzailea"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intentsitatea:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Ezabatu"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Utzi"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ekoa</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Berelikatzea:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Bolumena:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg plugina"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1131,55 +1127,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg plugina"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Irteerako fitxategi-formatua:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfiguratu"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Gorde jatorrizko direktorioan"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Gorde direktorio pertsonalizatuan"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Irteerako fitxategiaren karpeta:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Hautatu karpeta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Lortu fitxategi-izena hemendik:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "jatorrizko fitxategi-etiketak"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "jatorrizko fitxategi-izena"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Ez kendu fitxategi-izenaren luzapena"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Jarri pistaren zenbakia fitxategi-izenaren aurretik"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1197,165 +1193,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automatikoa"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr ""
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estereoa"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Monoa"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 konfigurazioa"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmoaren kalitatea:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Irteerako lagin-tasa:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bit-tasa / Konpresio-tasa:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bit-tasa (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Konpresio-tasa:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio modua:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Hainbat:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Derrigortu ISOa betetzen duela"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Erroreen aurkako babesa"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kalitatea"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Gaitu VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Mota:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR aukerak:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Gutxieneko bit-tasa (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Gehienezko bit-tasa (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Derrigortu gutxieneko bit-tasa"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR aukerak:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Batez besteko bit-tasa (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR kalitate-maila:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Ez idatzi Xing VBR goiburukoa"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Markatu copyright gisa"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Markatu jatorrizko gisa"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 parametroak:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Derrigortu v2 etiketa gehitzea"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Gehitu v1 etiketa soilik"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Gehitu v2 etiketa soilik"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiketak"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis kodetzailearen konfigurazioa"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Kalitate maila (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC Deskodetzailea"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1363,21 +1363,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC Deskodetzailea"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO plugina"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1389,530 +1393,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Sarera zenbakia"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Titulua"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Urtea"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Diskoa"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Ilara posizioa"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Iraupena"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Fitxategi bidea"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Fitxategi izena"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr ""
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bit-tasa:"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Desgaitu"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr ""
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Ireki fitxategiak"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Ireki BKU ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr ""
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr ""
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "I_rten"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "Erreproduzitu"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Pausatu"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "Gelditu"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Aurrekoa"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr ""
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr ""
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr ""
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr ""
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr ""
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr ""
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr ""
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr ""
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Pista zenbakiaren arabera"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr ""
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr ""
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr ""
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr ""
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr ""
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr ""
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr ""
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr ""
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr ""
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr ""
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr ""
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Ilara Kudeatzailea..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr ""
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr ""
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr ""
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr ""
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr ""
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr ""
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr ""
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr ""
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr ""
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr ""
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Ilararatu/Ilaratik kendu"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr ""
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr ""
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr ""
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr ""
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK Interfazea"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "monoa"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estereoa"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "kanal %d"
 msgstr[1] "%d kanal"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Single modua."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Erreprodukzio-zerrenda modua."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Kantuaren ostean geldituko da."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Erreproduzitu"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausatu/jarraitu"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Gelditu"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Mututu"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Erakutsi pantaila gaineko mezuak (OSD)"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(bat ere ez)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1923,15 +2004,11 @@ msgstr ""
 "\n"
 "Jarraitzea nahi duzu?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Saguaren botoiak lotzea"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Laster-tekla globalen pluginaren konfigurazioa"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1939,23 +2016,27 @@ msgstr ""
 "Sakatu tekla konbinazioa testu-eremuaren barruan.\n"
 "Saguaren botoiak ere lotu ditzakezu."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Laster-teklak"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Ekintza:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Tekla-konbinazioa:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1970,56 +2051,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr ""
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Ezarpenak"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Ostalari Ezarpenak"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modulo bideak:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2029,68 +2105,39 @@ msgstr ""
 "LADSPA_PATH bidean eta bide hauetan bilatuko da.\n"
 "Bide berria gehitu eta gero, sakatu Enter Plugin berriak bilatzeko.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Plugin eskuragarriak:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Gaitu"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Gaitutako pluginak:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ezarpenak"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC plugina"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2106,73 +2153,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Berkonektatu LIRC zerbitzarira"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Itxaron berkonektatu aurretik:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC plugina"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki plugina"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Errorea"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Errorea"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki plugina"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U Erreprodukzio-zerrendak"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Ukimen sortzailea: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Ukimen sortzailea: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2181,162 +2236,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Irteera kanalak:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr ""
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS Plugina"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 plugina"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS plugina"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Geldituta"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious ez da jotzen ari."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2356,55 +2443,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausatu"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Hurrengoa"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
 msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Soinu-gailua:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Erabili bestelako gailua:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2413,19 +2509,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 Deskodetzailea"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2445,143 +2557,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Aurrekoa"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Errepikatu"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Ausazkoa"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr ""
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2592,765 +2773,840 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista ezezaguna"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Disko ezezaguna"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr ""
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Erreprodukzioa"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Erreprodukzio-zerrenda"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ikusi"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Errepikatu"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Ausazkoa"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Erreprodukzio-zerrenda aurreraturik ez"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Aurrekoa"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Erreprodukzio-zerrenda berria"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Erakutsi erreprodukzio-zerrendaren editorea"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Erakutsi ekualizadorea"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Beti gainean"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Tituluaren arabera"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Fitxategi-izenaren arabera"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Kendu guztiak"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Garbitu ilara"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Kendu fitxategi erabilkaitzak"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Kendu bikoiztuak"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Kendu desautatutakoak"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Kendu hautatutakoak"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Bilatu eta hautatu"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Alderantzikatu hautapena"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Ez hautatu ezer"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Hautatu denak"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Diskoaren arabera"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Pista zenbakiaren arabera"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Artistaren arabera"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Diskoaren arabera"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Pista zenbakiaren arabera"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Nahastu ausaz zerrenda"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Alderantzikatu zerrenda"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordenatu hautatutakoak"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenatu zerrenda"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Moztu"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopiatu"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Itsatsi"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Gorde"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Kargatu"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Aurrezarpenak"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Kargatu aurrezarpena"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Gorde aurrezarpenak"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Ezabatu aurrezarpena"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Erreproduzitzailea:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Hautatu erreproduzitzaile nagusiaren leihoko letra-tipoa:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Erreprodukzio-zerrenda:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Hautatu erreprodukzio-zerrendaren letra-tipoa:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr ""
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizatzailea"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Esparrua"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Itzalita"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normala"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Sua"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Marrak"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barrak"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Motelena"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Motela"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Tartekoa"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Azkarra"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Azkarrena"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Izotza"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Leuna"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Orokorra"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Bisualizazioa"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Aurre-anp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious-en ekualizadorea"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Bilatu %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Bolumena: %% %d"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balantzea: %% %d ezkerrean"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balantzea: erdian"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balantzea: %% %d eskuinean"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Aukeren menua"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desgaitu 'Beti gainean'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Gaitu 'Beti gainean'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Fitxategi-informazioaren koadroa"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Single modua."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Erreprodukzio-zerrenda modua."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Kantuaren ostean geldituko da."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Bilatu sarrerak erreprodukzio-zerrenda aktiboan"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3362,57 +3618,61 @@ msgstr ""
 "minuskulak ez bereiztuz. Ez badakizu adierazpen erregularrak nola ibiltzen "
 "diren, sartu bilatzea nahi duzunaren zati literal bat."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Izenburua: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Diskoa: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Fitxategi-izena: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Garbitu aurreko hautapena bilatu aurretik"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Txandakatu automatikoki ilara bat datozen sarrerentzako"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Sortu erreprodukzio-zerrenda berria bat datozen sarrerekin"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious erreprodukzio-zerrendaren editorea"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Konprimitutako Winamp 2.x azala"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Deskonprimitutako Winamp 2.x azala"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Ezin izan da direktorioa (%s) sortu: %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile plugina"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3434,85 +3694,71 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile plugina"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio irteera pluginari buruz"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio irteera plugina\n"
-"\n"
-"Thomas Pfaff-ek idatzia <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Onartu gabeko formatua"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Audio gailuak onartzen ez duen formatua eskatu da.\n"
-"\n"
-"Mesedez berriro saiatu sndiod(1) zerbitzaria martxan dela"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio gailua"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(hutsik badago: lehenetsia)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Ados"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr ""
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Exekutatuko den komandoa audacious-ek abesti berria hastean."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Shell-ari emandako parametroak komatxoen artean kapsulatu "
+"behar dira. Bestela segurtasunezko arriskua izan daiteke.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Komandoa:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Exekutatuko den komandoa abestiaren amaierantz joatean."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
-"Exekutatuko den komandoa Audacious erreprodukzio-zerrendaren amaierara "
-"iristean."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Exekutatuko den komandoa abesti baten titulua aldatzean (adib. sareko "
-"korronteen tituluak)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3526,35 +3772,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Hurrengo formatu kateak erabili ditzazkezu \n"
-"eta komandoa deitu aurretik ordezaktuko dira\n"
-"(Denak ez dira erabilgarriak erreproduzkio-zerrenda bukaerako komanoan):\n"
-"\n"
-"%F: Frekuentzia (hertziotan)\n"
-"%c: Kanal kopurua\n"
-"%f: Fitxategi izena (bide osoa)\n"
-"%l: Iraupena (milisegunduetan)\n"
-"%n edo %s: Kantuaren izena\n"
-"%r:Bitartea (bit segunduko\n"
-"%t: Erreprodukzio-zerrendan posizioa (%02d)\n"
-"%p: Jotzen ari da (1 edo 0)\n"
-"%a: Artista\n"
-"%b: Diskoa\n"
-"%T: Pista izena"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Shell-ari emandako parametroak komatxoen artean kapsulatu "
-"behar dira. Bestela segurtasunezko arriskua izan daiteke.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Komandoak"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3563,51 +3790,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Abiadura eta Tonoa"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Abiadura eta Tonoa</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Abiadura:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tonoa:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Abiadura eta Tonoa"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3618,63 +3845,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Aldatu bolumena"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Aldatu erreprodukzioaren abestia"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Bestelako Ezarpenak</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Tonu-sortzailea: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3683,15 +3910,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3712,44 +3935,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis Deskodetzailea"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Deskodetzailea"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX Deskodetzailea"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack Deskodetzailea"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack Deskodetzailea"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF Deskodetzailea"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/fa_IR.po b/po/fa_IR.po
index 2aabf72b4095..7ac512602ecb 100644
--- a/po/fa_IR.po
+++ b/po/fa_IR.po
@@ -7,11 +7,11 @@
 # vandu <vandusoft at gmail.com>, 2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Persian (Iran) (http://www.transifex.com/projects/p/audacious/"
 "language/fa_IR/)\n"
 "Language: fa_IR\n"
@@ -20,51 +20,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "تک‌کاناله"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "دوکاناله"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "فراگیر"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/aac-raw/aac.c:476
-msgid "AAC (Raw) Decoder"
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "هشدار"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "هشدار"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -87,7 +71,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -109,7 +93,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -123,360 +107,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "این تماس بیدارباش شما است."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "یادآوری"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "دوشنبه"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "سه‌شنبه"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "چهارشنبه"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "پنج‌شنبه"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "جمعه"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "شنبه"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "یکشنبه"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "تنظیمات هشدار"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "زمان"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "هشدار در (پیش‌فرض):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "س"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "خاموش شود بعد از:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "ساعت"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "دقیقه"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "روزهای مورد نظر برای هشدار انتخاب شود"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "روز"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "پیش‌فرض"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "روزها"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "محو شدن"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "ثانیه‌ها"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "صدا"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "شروع از"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "پایان"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "جاری"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "فرمان تکمیلی"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "فعال‌سازی"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "لیست پخش (اختیاری)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr ""
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "گزینه‌ها"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "معنای این گزینه‌ها چیست؟"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "راهنمایی"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr ""
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr ""
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "ابزار PCM پیش‌فرض"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "ابزار میکسر پیش‌فرض"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "ابزار PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "ابزار میکسر:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "عنصر میکسر:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "کار حول اتمام تماس"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "هرتز"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - فایل SoundFont انتخاب شود"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "نام فابل"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "نام فایل"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "اندازه (بایت)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "نام:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> ‏اطلاعات MIDI ‏</span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "فرمت:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "مدت زمان (میلی‌ثانیه):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "متغیر"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "‎BPM (wavg)‎:"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "قسمت زمان:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> توضیحات و ترانه‌های MIDI‏ </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* توضیحاتی در این فایل MIDI وجود ندارد *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* ترانه‌ای در این فایل MIDI وجود ندارد *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "بستن"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(UTF-8 نامعتبر)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -487,151 +477,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "مستطیل"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "مستطیل گوشه‌گرد"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "مستطیل مقعر"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "هیچکدام"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "شروع پخش"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "وقتی یکی از گزینه‌های لیست پخش اجرا شد OSD اجرا شود."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "تغییر عنوان"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"هنگامی که در حال پخش عنوان فایل تغییر کرد، اما نام فایل عوض نشد، OSD اجرا "
-"شود. از این گزینه برای نمایش تغییر عنوان در استریم‌های اینترنتی استفاده می‌شود."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "توقف روشن"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "وقتی عملیات پخش متوقف شد OSD اجرا شود."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "توقف خاموش"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "وقتی از پخش از حالت توقف خارج شد OSD اجرا شود."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "محل قرارگیری"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "فاصله نسبی از عرض:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "فاصله نسبی از ارتفاع:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "حداکثر طول OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "گزینه‌های حالت چندنمایشگره"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "نمایش OSD بوسیله:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "همه نمایشگرها"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "نمایشگر ‎%i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "زمان‌بندی (برحسب میلی‌ثانیه)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "نمایش:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "نمایش تدریجی:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "خروج تدریجی:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "فونت‌ها"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "فونت ‎%i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "سایه"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "شیوه رندر"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "رنگ‌ها"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "رنگ ‎%i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "فعال‌سازی اجرا"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "رخداد"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "مدیرکامپوزیت یافت شد"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -641,112 +626,112 @@ msgstr ""
 "اگر می‌دانید در حال اجراست، لطفا یک مدیر کامپوزیت را فعال کنید، در غیراینصورت "
 "OSD‌ بدرسی نشان داده نمی‌شود"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "برای شفافیت ساختگی نیازی به مدیر کامپوزیت نیست"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "شفافیت"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "شفافیت ساختگی"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "شفافیت واقعی (به افزونه کامپوزیت X نیاز دارد)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "افزونه کامپوزیت بارگذاری نشده است"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "افزونه کامپوزیت در دسترس نیست"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "تنظیمات Audacious OSD"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "مکان"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "پویانمایی"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "متن"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "تزیینات"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "تریگر"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "متفرقه"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -758,169 +743,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "بجای CDDBP از HTTP استفاده کن"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "سی‌دی صوتی"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "درایو خالی است."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "نوع دیسک پشتیبانی نمی‌شود."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "اجرای سی‌دی"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "اضافه کردن سی‌دی"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "متمرکز کردن صدا:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "بازه متغیر:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -930,195 +902,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "باس:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "صدای زیر:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "طول پیش فرض آهنگ:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "نمونه‌گیری مجدد صدا انجام شود"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "نرخ نمونه‌گیری مجدد:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "هرتز"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "طول برچسب‌های SPC نادیده گرفته شود"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "افزایش انعکاس"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "دیکدر موسیقی کنسول بازی"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "حذف"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "انصراف"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr ""
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr ""
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
 msgstr ""
 
-#: src/echo_plugin/echo.c:122
-msgid "Echo"
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1128,55 +1125,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "فرمت فایل خروجی:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "پیکربندی"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "ذخیره در پوشه اصلی"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "ذخیره در پوشه شخصی"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "پوشه برای ذخیره‌سازی فایل:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "یک پوشه را انتخاب کنید"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "نام‌گذاری فایل از روی:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "برچسب‌های اصلی فایل"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "نام اصلی فایل"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "افزونه نام فایل از بین نرود"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "شماره آهنگ را به نام فایل نسبت بده"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1194,165 +1191,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "خودکار"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "یکی کردن دو کانال"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "دوکاناله"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "تک‌کاناله"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "پیکربندی MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "کیفیت الگوریتم:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "نرخ نمونه‌گیری خروجی:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(هرتز)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "نسبت نرخ بیت / فشرده‌سازی:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "نرخ بیت (کیلوبیت بر ثانیه):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "نسبت فشرده‌سازی:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "حالت صدا:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "متفرقه:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "اجبار در استفاده از قواعد ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "محافظت در برابر خطا"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "کیفیت"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "فعال‌سازی VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "نوع:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "گزینه‌های VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "حداقل نرخ بیت (کیلوبیت بر ثانیه):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "حداکثر نرخ بیت (کیلوبیت بر ثانیه):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "حداقل نرخ بیت بشدت اعمال شود"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "گزینه‌های ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "نرخ بیت میانگین (کیلوبیت بر ثانیه):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "سطح کیفیت VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "سرآیند Xing VBR‌ نوشته نشود"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR نرخ بیت متغیر/نرخ بیت میانگین"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "فایل کپی‌رایت دارد"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "فایل نسخه اصلی است"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "پارامترهای ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "برچسب‌های نسخه 2 حتما اضافه شود"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "فقط برچسب‌های نسخه 1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "فقط برچسب‌های نسخه 2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "برچسب‌ها"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "پیکربندی انکدر Vorbis:"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "سطح کیفیت (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1360,21 +1361,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1386,529 +1391,606 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "شماره گزینه"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "عنوان"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "هنرمند"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "سال انتشار"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "آلبوم"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "آهنگ"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "مکان در صف"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "مدت زمان"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "مسیر فایل"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "نام فایل"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "عنوان شخصی"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "نرخ بیت"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "به سمت چپ بچسبان"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "به سمت راست بچسبان"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "به بالا بچسبان"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "به پایین بچسبان"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "جدا کردن پنجره"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "غیرفعال‌سازی"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr ""
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_بازکردن فایل‌ها ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "بازکردن _آدرس اینترنتی ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "اضافه کردن آدرس _اینترنتی ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "د_رباره ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_خروج"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_پخش"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "تو_قف"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "پا_یان پخش"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_قبلی"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_بعدی"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_تکرار"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_بهم ریخته"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr ""
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "ا_طلاعات آهنگ ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "پرش به _زمان ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "پرش به _آهنگ ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "براساس _عنوان"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "براساس _شماره آهنگ"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "براساس _هنرمند"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "بر اساس _تاریخ انتشار"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "براساس _مسیر فایل"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "براساس عنوان شخصی"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "مرتب سازی معکوس"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "بهم ریختن مرتب‌سازی"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "تازه‌سازی لیست"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "مرتب کردن"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "جدید"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "وارد کردن ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "خروجی گرفتن ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "مدیر صف ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "افزایش صدا"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "کاهش صدا"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "اکولایزر"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "نمایش نوار منو"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "نمایش نوار اطلاعات"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "نمایش نوار وضعیت"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "فایل"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "پخش"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "لیست پخش"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "سرویس‌ها"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "خروجی"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "نما"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "وارد کردن به/خارج کردن از صف"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "برش"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "کپی"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "چسباندن"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "انتخاب همه"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "رابط GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "‎%s - Aduacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "تک‌کاناله"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "دوکاناله"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "‎%d کانال"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "‎%d کیلوبیت بر ثانیه"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "حالت تک‌فایل."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "حالت لیست پخش."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "توقف بعد از آهنگ."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "پخش"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "توقف/ادامه"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "اتمام پخش"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "قطع کردن صدا"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "نمایش اطلاعات بر روی صفحه"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(هیچکدام)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1919,15 +2001,11 @@ msgstr ""
 "\n"
 "آیا می‌خواهید ادامه دهید؟"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "تعریف گزینه برای کلیدهای ماوس"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "تنظیمات افزونه کلید میانبر عمومی"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1935,23 +2013,27 @@ msgstr ""
 "ترکیب مورد نظر را در جعبه متن از طریق فشردن کلیدها ایجاد کنید.\n"
 "می‌توان از کلیدهای ماوس هم استفاده کنید."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "کلیدهای میانبر:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>عمل:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>کلیدهای تعریف‌شده:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1966,56 +2048,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
 msgstr ""
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr ""
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "تنظیمات ‎%s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "تنظیمات هاست LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "مسیرهای ماژول:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2026,68 +2103,39 @@ msgstr ""
 "بعد از وارد کردن هر مسیر کلید اینتر را فشار دهید تا افزونه‌های جدید جستجو "
 "شوند.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "افزونه‌های موجود:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "فعال کردن"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "افزونه‌های فعال:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "تنظیمات"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
 msgstr ""
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2103,73 +2151,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr ""
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "خطا"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "خطا"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "مولد تکت: ‎%d بیت در دقیقه"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "مولد تکت: ‎%d بیت در دقیقه ‎%d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2178,162 +2234,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "کانال‌های خروجی:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
 msgstr ""
 
-#: src/mms/mms.c:195
-msgid "MMS Plugin"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "فراگیر"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "فراگیر"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "متوقف شده"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious در حال پخش نیست."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2353,55 +2441,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "متوقف"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "بعدی"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. ابزار پیش‌فرض"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "ابزار صوتی:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "از ابزار جایگزین استفاده کن:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "تغییر فرمت بوسیله نرم‌افزار نرم‌افزار OSS فعال شود."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2410,19 +2507,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2442,143 +2555,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "قبلی"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "تکرار"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "بهم‌ریختن"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "شیوه:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2589,762 +2771,837 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr ""
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr ""
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr ""
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "پخش"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "لیست پخش"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "نما"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "تکرار"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "بهم‌ریختن"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "لیست پخش به جلو نرود"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "قبلی"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "لیست پخش جدید"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "نمایش ویرایشگر لیست پخش"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "نمایش اکولایزر"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "همیشه در بالا"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "براساس عنوان"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "براساس نام فایل"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "حذف همه"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "پاکسازی صف"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "پاک کردن فایل‌های خارج از دسترس"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "پاک کردن فایل‌های تکراری"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "حذف انتخاب‌نشده‌ها"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "حذف انتخاب‌شده‌ها"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "جستجو و انتخاب"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "برعکس کردن انتخاب‌ها"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "انتخاب هیچ‌کدام"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "انتخاب همه"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "براساس آلبوم"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "براساس شماره آهنگ"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "براساس هنرمند"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "براساس آلبوم"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "براساس شماره آهنگ"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "بهم‌ریختن لیست"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "برعکس کردن ترتیب لیست"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "مرتب‌سازی انتخاب‌شده‌ها"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "مرتب‌سازی لیست"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "برش"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "کپی"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "چسباندن"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "ذخیره"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "بارگذاری"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "الگوها"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "بارگذاری الگو"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "ذخیره الگو"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "حذف الگو"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "پخش‌کننده:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "فونت اصلی پنجره پخش‌کننده را انتخاب کنید:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "لیست پخش:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "فونت لیست پخش را انتخاب کنید:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "انتخاب فونت‌های نقشه‌بیتی (فقط از اسکی پشتیبانی می‌شود)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "عنوان آهنگ در هر دو جهت حرکت کند"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "تحلیل‌کننده"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "محدوده"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "خاموش"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "نرمال"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "آتش"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "خط ها"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "میله‌ها"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "کندترین"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "کند"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "متوسط"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "تند"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "تندترین"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "یخ"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "نرم"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "عمومی"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "جلوه‌های تصویری"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "پیش‌تقویت‌کننده"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 هرتز"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 هرتز"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 هرتز"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 هرتز"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 هرتز"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 کیلوهرتز"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 کیلوهرتز"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 کیلوهرتز"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 کیلوهرتز"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 کیلوهرتز"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "اکولایزر Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "پیمایش به ‎%d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "صدا: ‎%d%%‎"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "بالانس: ‎%d%%‎ چپ"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "بالانس: مرکز"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "بالانس: ‎%d%%‎ راست"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "منوی گزینه‌ها"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "غیرفعال کردن 'همیشه در بالا'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "فعال کردن 'همیشه در بالا'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "جعبه اطلاعات فایل"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "حالت تک‌فایل."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "حالت لیست پخش."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "توقف بعد از آهنگ."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "گزینه‌های موجود در لیست پخش فعال را جستجو کن"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3355,57 +3612,61 @@ msgstr ""
 "پشتیبانی کرده، به بزرگی و کوچکی حروف حساس هستند. اگر نمی‌دانید عبارات منظم چه "
 "هستند، بخشی از عبارت موردنظر خود را وارد کنید."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "عنوان:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "آلبوم:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "هنرمند:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "نام فایل:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "قبل از جستجو انتخاب قبلی را پاک کن"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "گزینه‌های یافت شده را در صف نشان بده"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "لیست پخش براساس گزینه‌های یافت شده ایجاد کن"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "ویرایشگر لیست پخش Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "‎%s (%d of %d)‎"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "پوسته فشرده Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "پوسته غیرفشرده Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3427,75 +3688,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "قبول"
-
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr ""
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
 msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
 msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3510,17 +3765,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3529,51 +3782,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
 msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3584,63 +3837,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr ""
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr ""
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr ""
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3649,15 +3902,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3678,44 +3927,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/fi.po b/po/fi.po
index 1bb1ea0ba7a6..cd81d9abfd62 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -3,15 +3,16 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Jaergenoth <jstuomisto at gmail.com>, 2013
-# Jaergenoth <jstuomisto at gmail.com>, 2013
+# Jiri Grönroos <jiri.gronroos at iki.fi>, 2014-2015
+# J. S. Tuomisto <jstuomisto at gmail.com>, 2013
+# J. S. Tuomisto <jstuomisto at gmail.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 07:12+0000\n"
+"Last-Translator: Jiri Grönroos <jiri.gronroos at iki.fi>\n"
 "Language-Team: Finnish (http://www.transifex.com/projects/p/audacious/"
 "language/fi/)\n"
 "Language: fi\n"
@@ -20,40 +21,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "AAC (Raw) -dekooderi"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib-soitin)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sarjoitettu"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib-soitin)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Herätyskello"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Aseta hälytys..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +52,7 @@ msgstr ""
 "\n"
 "Alkuperäiset kehittäjät Adam Feakin ja Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Herätyskello"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -108,7 +93,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -147,7 +132,7 @@ msgstr ""
 "    Suoritetaan tämä komento kun hälytys alkaa.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -171,384 +156,371 @@ msgstr ""
 "    Kirjoita muistutus laatikkoon ja kytke\n"
 "    se päälle, jos haluat muistutuksen näkyvän."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Herätys!"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Muistutuksesi tälle päivälle on..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Muistutus"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Maanantai"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Tiistai"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Keskiviikko"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Torstai"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Perjantai"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Lauantai"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Sunnuntai"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Herätyskellon asetukset"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Aika"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Kellonaika (oletus):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Hiljennä, kun aikaa kulunut:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "tunnit"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minuutit"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Valitse päivät jolloin herätyskello on aktiivinen"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Päivä"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Oletus"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Päivät"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Häivytys"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekuntia"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Äänenvoimakkuus"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Aloita"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Lopullinen"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Nykyinen"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Lisäkomento"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "käytä"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Soittolista (valinnainen)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Valitse soittolista"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Asetukset"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Mitä nämä asetukset tarkoittavat?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ohje"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
-msgstr "Levyn kansitaide"
+msgstr "Albumin kansikuvitus"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Albumikuvitus (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA-lähtö"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA-lähdön liitännäinen Audacioukselle.\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Kiitokseni William Pitcock:lle (ALSA Output Plugin NG:n kehittäjä), jonka "
+"koodi toimi referenssinä silloin, kun ALSA:n manuaali ei riittänyt."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(ei kuvausta)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Oletus PCM-laite"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Oletus miksauslaite"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM-laite:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Miksauslaite:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Miksauskanava:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Korjaa \"drain hangup\""
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-liitännäinen (MIDI-soitin)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"ALSA-lähdön liitännäinen Audacioukselle.\n"
-"Copyright 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Kiitokseni William Pitcock:lle (ALSA Output Plugin NG:n kehittäjä), jonka "
-"koodi toimi referenssinä silloin, kun ALSA:n manuaali ei riittänyt."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA-lähtö"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-liitännäinen (MIDI-soitin)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Toisto</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
-msgid "Drum shift:"
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Ohita edeltävä hiljaisuus"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Ohita lopussa oleva hiljaisuus"
+
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-liitännäinen - valitse SoundFont-tiedosto"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Peru"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Avaa"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Tiedostonimi"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Koko (tavuina)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nimi:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI-tiedot </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Muoto:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Kesto (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Raitojen lukumäärä:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "muuttuja"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Aikajako:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI-kommentit ja -lyriikat </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* MIDI-tiedostossa ei ollut kommentteja *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* MIDI-tiedostossa ei ollut lyriikoita *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Sulje"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (virheellinen UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Tietoja AMIDI-liitännäisestä"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-liitännäinen"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"modulaarinen MIDI-soitin\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Luonut Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"Erityiskiitokset...\n"
-"\n"
-"Clemens Ladisch ja Jaroslav Kysela\n"
-"aplaymidi ja amixer olivat erittäin hyödyllisiä, \n"
-"alsa-lib dokumentaation ohella. Ne auttoivat\n"
-"oppimaan lisää ALSA:n ohjelmointirajapinnasta.\n"
-"\n"
-"Alfredo Spadafina\n"
-"hienosta MIDI-näppäimistö logosta\n"
-"\n"
-"Tony Vroon\n"
-"avusta alpha-testauksessa"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -559,151 +531,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Suorakulmio"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Pyöristetty suorakulmio"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Kovera suorakulmio"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ei mitään"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Toiston aloitus"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Näyttää OSD:n kun kappaleen toisto alkaa."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Nimen muutos"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Näyttää OSD:n kun kappaleen nimi muuttuu toiston aikana, mutta tiedostonimi "
-"pysyy samana. Hyödyllinen lähinnä internet-virroille."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Keskeytys"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Näyttää OSD:n kun toisto keskeytetään."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Toisto jatkuu"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Näyttää OSD:n kun toisto jatkuu."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Sijoitus"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Suhteellinen X:n poikkeama:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Suhteellinen Y:n poikkeama:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "OSD:n maksimileveys:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Monen näytön asetukset"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Näytä OSD käyttäen:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "kaikki näytöt"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "näyttö %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Ajoitus (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Näytä:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Häivytä sisään:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Häivytä ulos:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Kirjasimet"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Kirjasin %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Varjo"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Esitystyyli"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Värit"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Väri %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Käytä liipaisinta"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Tapahtuma"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Komposointimanageri havaittu"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -713,112 +680,112 @@ msgstr ""
 "Jos komposointimanageri ei ole vielä päällä, aktivoi se tai muutoin OSD ei "
 "toimi kunnolla."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Komposointimanageria ei tarvita jäljiteltyyn läpinäkyvyyteen"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Läpinäkyvyys"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Jäljitelty läpinäkyvyys"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Oikea läpinäkyvyys (vaatii X:n komposointilaajennuksen)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Komposointilaajennusta ei ole ladattu"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Komposointilaajennus ei ole saatavilla"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - asetukset"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Sijainti"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animaatio"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Teksti"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Koristeet"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Liipaisin"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Muut"
 
-#: src/asx3/asx3.c:179
-msgid "ASXv3 Playlists"
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx3/asx3.cc:35
+msgid "ASXv3 Playlists"
+msgstr "ASXv3-soittolistat"
+
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 -soittolistat"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious -soittolistat (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Väri</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Esiasetukset:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Syöttötaso:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Leikkaustaajuus:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Esiasetukset:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektrianalysaattori"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Ääni CD -liitännäinen"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -838,171 +805,156 @@ msgstr ""
 "\n"
 "Tämä oli Google Summer of Code 2007 -projekti."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Laite</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Lukunopeus:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Laite:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metatiedot</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Käytä CD-tekstiä"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Käytä CDDB:tä"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Käytä HTTP:tä CDDBP:n sijasta"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Palvelin:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Polku:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Portti:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Ääni CD -liitännäinen"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "cdio-alijärjestelmää ei voitu alustaa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Viallinen URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Raitaa %d ei löydetty."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Raita %d on dataraita."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Äänilähtöä ei voitu avata."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Virhe luettaessa ääni CD:tä."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Ääni CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Ei voitu avata CD-asemaa %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Ääneen kykenevää CD-asemaa ei löydetty."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Avatun CD-aseman alustaminen epäonnistui."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Ei voitu lukea ensimmäistä/viimeistä raitaa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Ei voida lukea alku/loppu LSN:ää raidalle %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "CDDB-yhteyden luonti epäonnistui."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "CDDB-palvelimen kysely epäonnistui."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "CDDB-palvelimen kysely epäonnistui: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Ei voitu lukea cddb-tietoa: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Asema on tyhjä."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Levytyyppiä ei tueta."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Ääni CD -valikkonimikkeet"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Toista CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Lisää CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Ääni CD -valikkonimikkeet"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Kompressio</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Keskikanava:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dynaaminen alue:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Dynaamisen alueen kompressori -liitännäinen Audacioukselle\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dynaamisen alueen kompressori"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1018,206 +970,225 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Basso:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Diskantti:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Kappaleen oletuskesto:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Uudelleennäytteistys</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Käytä äänen uudelleennäytteistystä"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Näytteenottotaajuus:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Sivuuta kesto SPC-tietueista"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Lisää kaikuefektiä"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Pelikonsoli-dekooderi"
 
-#: src/crossfade/crossfade.c:83
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio-lähtö"
+
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Ristiinhäivytys epäonnistui koska kappaleilla oli eri määrä kanavia.  Voit "
-"käyttää kanavamikseriä muuntaaksesi kappaleiden sisältämien kanavien määrää."
 
-#: src/crossfade/crossfade.c:90
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"Ristiinhäivytys epäonnistui koska kappaleilla oli eri "
-"näytteenottotaajuudet.  Voit käyttää uudelleennäytteistäjää muuntaaksesi "
-"kappaleiden näytteenottotaajuutta."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Ristiinhäivytys-liitännäinen Audacioukselle\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Ristiinhäivytys</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Limittäisyys:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Ristiinhäivytys"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Ristiinhäivytys epäonnistui koska kappaleilla oli eri määrä kanavia.  Voit "
+"käyttää kanavamikseriä muuntaaksesi kappaleiden sisältämien kanavien määrää."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Ristiinhäivytys epäonnistui koska kappaleilla oli eri "
+"näytteenottotaajuudet.  Voit käyttää uudelleennäytteistäjää muuntaaksesi "
+"kappaleiden näytteenottotaajuutta."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Vahvuus:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet -liitännäinen"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Poista tiedostot"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
-msgstr ""
+msgstr "Virhe siirrettäessä kohdetta %s roskakoriin: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Virhe poistaessa kohdetta %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Virhe poistaessa kohdetta %s: ei paikallinen tiedosto."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Haluatko siirtää valitut tiedostot roskakoriin?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Siirrä roskakoriin"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Haluatko poistaa seuraavat tiedostot pysyvästi?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Poista"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Peruuta"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Poista valitut tiedostot"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Poistamistapa</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Siirrä roskakoriin pysyvän poistamisen sijaan"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Kaikuefekti</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Viive:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Feedback:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Äänenvoimakkuus:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Kaikuefekti-liitännäinen\n"
-"Luonut Johan Levin, 1999\n"
-"\n"
-"Surround-kaiun luonut Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Kaikuefekti"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg-liitännäinen"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1233,55 +1204,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg-liitännäinen"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter-liitännäinen"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Tiedostoformaatti:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Muuta asetuksia"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Tallenna alkuperäiseen kansioon"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Tallenna muuhun kansioon"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Tiedoston kohdekansio:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Valitse kansio"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Hae tiedostonimi:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "alkuperäiset tiedoston tietueet"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "alkuperäinen tiedostonimi"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Pidä tiedoston pääte"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Lisää raidan numero tiedostonimeen"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1313,165 +1284,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter-liitännäinen"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automaattinen"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3-asetukset"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmin laatu:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Näytteenottotaajuus:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bittinopeus / Pakkaussuhde:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bittinopeus (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Pakkaussuhde:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Äänitila:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Muut:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Pakota tarkka ISO-yhteensopivuus"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Virhesuojaus"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Laatu"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Käytä VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tyyppi:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR-asetukset:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimi bittinopeus (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksimi bittinopeus (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Valvo tiukasti minimi bittinopeutta"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR-asetukset:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Bittinopeuden keskiarvo (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR:n laatutaso:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Älä kirjoita Xing VBR -otsaketta"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Kehyksen parametrit:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Merkitse tekijänoikeudeksi"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Merkitse alkuperäiseksi"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3-parametrit:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Pakota v2-tagin lisäys"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Lisää vain v1-tagi"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Lisää vain v2-tagi"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tagit"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis-enkooderin asetukset"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Laatutaso (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC-dekooderi"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "häviötön"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1483,11 +1458,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC-dekooderi"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1495,11 +1466,19 @@ msgstr ""
 "GIO-liitännäinen Audacioukselle\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO-liitännäinen"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1511,534 +1490,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL Spektrianalysaattori"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
-"Gnomen oikopolku -liitännäinen\n"
-"Ohjaa soitinta Gnomen oikopoluilla.\n"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Gnome-pikanäppäimet"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnomen oikopolut"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Numero"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Nimi"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Esittäjä"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Vuosi"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Albumi"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Raita"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Tyylilaji"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Sijainti jonossa"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Kesto"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Tiedostopolku"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Tiedostonimi"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Mukautettu nimi"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bittinopeus"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Käytettävissä olevat sarakkeet"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Näytettävät sarakkeet"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Etsintätyökalu"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Telakoi vasemmalle"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Telakoi oikealle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Telakoi ylhäälle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Telakoi alhaalle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Poista telakointi"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Poista käytöstä"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Etsintätyökalu"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Avaa tied_ostot..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Avaa _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Lisää tiedostoja..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Lisää U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "_Etsi kirjastosta"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Tietoja..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Asetukset..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Sulje"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Toista"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Keskeytä"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Pysäytä"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Edellinen"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Seuraava"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Kertaus"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "S_ekoitus"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Älä _etene soittolistalla"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "_Pysäytä tämän kappaleen jälkeen"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "K_appaleen tiedot..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Hyppää _aikaan..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Hyppää kappaleeseen..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Aseta kertauksen alkupiste A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Aseta kertauksen loppupiste B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Tyhjennä kertauspisteet"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "_Nimen mukaan"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "_Tiedostonimen mukaan"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Tiedosto_polun mukaan"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Ka_ppalenumeron mukaan"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "_Esittäjän mukaan"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Al_bumin mukaan"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "_Julkaisupäivämäärän mukaan"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "_Keston mukaan"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "_Tiedostopolun mukaan"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "_Mukautetun nimen mukaan"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Käänteinen järjestys"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Satunnainen järjestys"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Toista tämä soittolista"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Toista/jatka"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Päivitä"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Lajittele"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Järjestä _valitut"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Poista _kopiot"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Poista _ei saatavilla olevat tiedostot"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Uusi"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Nimeä _uudelleen..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "_Poista"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Tuo..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Vie..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Soittolistojen _hallinta..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Jonomanageri..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Nosta äänenvoimakkuutta"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Laske äänenvoimakkuutta"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Taajuuskorjain"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "_Tehosteet..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Näytä _valikkopalkki"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Näytä _tietopalkki"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Näytä tietopalkin vis_ualisaatio"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Näytä tila_rivi"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Näytä _jäljellä oleva aika"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Visualisoinnit..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Tiedosto"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "T_oisto"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Soittolista"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Palvelut"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Ääni"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Näkymä"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Lisää jonoon/Poista jonosta"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Avaa sisältävä kansio"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "L_eikkaa"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopioi"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Liitä"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Valitse _kaikki"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Nimeä uudelleen..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Soittolistan välilehdet</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Näytä aina välilehdet"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Näytä esiintymäkerrat"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Näytä sulkemispainikkeet"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Soittolistan sarakkeet</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Näytä sarakkeiden otsakkeet"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Sekalaiset</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Nuolinäppäimet siirtävät:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Vieritä kappaleen vaihtuessa"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK-käyttöliittymä"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Puskuroidaan..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d kanava"
 msgstr[1] "%d kanavaa"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Yksittäinen -tila."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Soittolista -tila."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Pysäytä kappaleen jälkeen."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Edellinen raita"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Toista"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Keskeytä/Jatka"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Pysäytä"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Seuraava raita"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 sekuntia eteenpäin"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 sekuntia taaksepäin"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Vaimenna"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Nosta äänenvoimakkuutta"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Laske äänenvoimakkuutta"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Hyppää tiedostoon"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Näytä/Piilota soittimen ikkunat"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Näytä OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Kertaus"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Sekoitus"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Pysäytä nykyisen jälkeen"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Nosta soittimen ikkunat"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ei mitään)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2049,15 +2101,11 @@ msgstr ""
 "\n"
 "Haluatko jatkaa?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Kytketään hiiren painalluksia"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Globaalit pikanäppäimet -liitännäisen asetukset"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2065,23 +2113,27 @@ msgstr ""
 "Paina näppäinyhdistelmää tekstikentän sisällä.\n"
 "Voit käyttää myös hiiren nappeja."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Pikanäppäimet:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Toiminto:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Näppäinsidos:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Lisää"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globaalit pikanäppäimet"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2107,60 +2159,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globaalit pikanäppäimet"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK-lähtö"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Yhteys JACK-porttiin %s epäonnistui."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Yhteys JACK-palvelimeen epäonnistui. Onhan se käynnissä?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Perustuu xmms-jack:iin, luonut Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Portannut Audacioukselle Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK-lähtö"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s asetukset"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA-isännän asetukset"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Moduulipolut:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2171,25 +2214,25 @@ msgstr ""
 "Uuden polun lisäämisen jälkeen paina entteriä hakeaksesi uusia liitännäisiä."
 "</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Saatavilla olevat liitännäiset:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Käytä"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Aktiiviset liitännäiset:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Asetukset"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2197,47 +2240,15 @@ msgstr ""
 "LADSPA-isäntä Audacioukselle\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA-isäntä"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: ei voida alustaa LIRC-tukea\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: ei voitu lukea LIRC:n asetustiedostoa\n"
-"%s: lue LIRC:n dokumentaatiosta\n"
-"%s: kuinka luoda kelvollinen asetustiedosto \n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: yritetään yhdistää uudelleen...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: tuntematon komento \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC-yhteys katkaistu\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: yritetään yhdistää uudelleen joka %d sekunti...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC-liitännäinen"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2265,73 +2276,81 @@ msgstr ""
 "\n"
 "Lisää tieto LIRC:stä http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Yhteys</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Yhdistä uudelleen LIRC-palvelimelle"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Odota ennen uudelleenyhdistämistä:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC-liitännäinen"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki-liitännäinen"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Lyriikoita ei saatavilla"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Virhe"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Ei voitu hakea %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Virhe"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Ei voida jäsentää %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Etsitään lyriikoita..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Kappaleen metatiedot puuttuvat"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Yhdistetään lyrics.wikia.com..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki-liitännäinen"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki-liitännäinen (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U-soittolistat"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Tahtigeneraattori"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Tahtigeneraattori: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Tahtigeneraattori: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2345,11 +2364,11 @@ msgstr ""
 "esim. tact://77 soittaaksesi 77 iskua minuutissa.\n"
 "Tai tact://60*3/4 soittaaksesi 60 iskua minuutissa tahdilla 3/4"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Tahtigeneraattori"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanavamikseri"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2357,152 +2376,184 @@ msgstr ""
 "Kanavamikseri-liitännäinen Audacioukselle\n"
 "Copyright 2011-2012 John Lindgren ja Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanavamikseri</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Kanavat:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanavamikseri"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS-liitännäinen"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Virhe MMS-palvelimeen yhdistäessä"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module Player)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resoluutio</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bittiä"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bittiä"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanavat</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Nearest (nopein)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linear (nopea)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (hyvä)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polyphase (paras)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Näytteenottotaajuus</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Taso:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Alaraja:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverb</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Bass Boost</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Preamp</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Ylinäytteistä"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Kohinan vähennys"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Toista Amigan MOD-tiedostoja"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Kertaus</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Kertojen määrä:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Jos haluat kerrata ikuisesti, aseta kertojen määräksi -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module Player)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Nämä asetukset tulevat voimaan, kun Audacious käynnistetään uudelleen."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123-liitännäinen"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Lisäasetukset</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Käytä tarkkaa keston laskentaa (hidas)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 -palvelin"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS -liitännäinen"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Tuntematon HTTP-virhe"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Liian monta uudelleenohjausta"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Pysäytetty"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious ei tällä hetkellä soita mitään."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Työpöytäilmoitukset"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2538,55 +2589,64 @@ msgstr ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Näytä toiston kontrollit"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Näytä ilmoitukset aina"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Työpöytäilmoitukset"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Sisällytä albumin nimi ilmoitukseen"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Näytä"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Keskeytä"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Seuraava"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Oletuslaite"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4-lähtö"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3-lähtö"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Oletuslaite"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Äänilaite:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Käytä vaihtoehtoista laitetta:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Tallenna äänenvoimakkuus eri sessioiden välillä."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Käytä OSS:n luomia formaatin muutoksia."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Kytke eksklusiivinen tila päälle virtuaalisen miksauksen estämiseksi."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2600,19 +2660,35 @@ msgstr ""
 "Haluaisin kiittää ihmisiä kanavalla #audacious, erityisesti Tony Vroonia "
 "sekä John Lindgreniä. Kiitokset myös edellisen OSS-liitännäisen kehittäjille."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4-lähtö"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Soittolistan hallinta"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Poista"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Nimeä uudelleen"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS-soittolistat"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 -dekooderi"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio-lähtö"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2648,11 +2724,68 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio-lähtö"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia-lähtö"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Etsi"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Avaa kansio..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Lisää kansio..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Avaa tiedostoja"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Lisää tiedostoja"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Edellinen"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Kertaus"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Sekoitus"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt-käyttöliittymä"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Uudelleenäytteistäjä"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2660,98 +2793,106 @@ msgstr ""
 "Uudelleenäytteistys-liitännäinen Audacioukselle\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Sivuuta/kertaa näytteet"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineaarinen interpolaatio"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Nopea sinc-interpolaatio"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Kohtalainen sinc-interpolaatio"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Paras sinc-interpolaatio"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Muunnos</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metodi:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Näytteenottotaajuus:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Kartoitus</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Käytä kartoituksia"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Uudelleenäytteistäjä"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Päivitetään raitoja käyttäjälle: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Lupa evätty"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Avaa seuraava linkki salliaksesi Audaciouksen päivittää soitettuja raitojasi:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Pidä tämä ikkuna auki ja paina \"Tarkista oikeudet\" -painiketta uudelleen.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2759,33 +2900,37 @@ msgstr ""
 "Soitettujen kappaleiden tiedot tallennetaan koneellesi.\n"
 "Tiedot lähetetään heti kun mahdollista."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Verkko-ongelma."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Last.fm -palveluun yhdistettäessä ilmeni ongelmia. Yritä uudelleen."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Tarkistetaan..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "_Tarkista oikeudet"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Kumoa oikeudet"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Sinun pitää sallia Audaciouksen päivittää raitoja Last.fm -tilillesi.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2793,7 +2938,7 @@ msgstr ""
 "Scrobbler -liitännäistä ei voitu käynnistää.\n"
 "Asennuksessasi saattaa olla jotain vikaa."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2810,11 +2955,7 @@ msgstr ""
 "Kiitos John Lindgrenille avusta projektin alussa.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2822,7 +2963,11 @@ msgstr ""
 "Audacious käyttää parannettua versiota Last.fm Scrobblerista.\n"
 "Scrobbler -liitännäinen löytyy asetuksista."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL-lähtö"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2830,81 +2975,56 @@ msgstr ""
 "SDL-lähdön liitännäinen Audacioukselle\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL-lähtö"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Kirjasto"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Tuntematon esittäjä"
+#: src/search-tool/search-tool.cc:394
+#, c-format
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d tulos"
+msgstr[1] "%d tulosta"
 
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Tuntematon albumi"
+#: src/search-tool/search-tool.cc:400
+#, c-format
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d piilotettu)"
+msgstr[1] "(%d piilotettua)"
 
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d kappale"
+msgstr[1] "%d kappaletta"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
 msgstr ""
-"%s\n"
-" albumilla %s esittäjältä %s"
 
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d albumi"
-msgstr[1] "%d albumia"
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d kappale"
-msgstr[1] ""
-"%s\n"
-" %s, %d kappaletta"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d kappale esittäjältä %s"
-msgstr[1] ""
-"%s\n"
-" %d kappaletta esittäjältä %s"
-
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Luo soittolista"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "L_isää soittolistalle"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Etsi kirjastosta"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2912,679 +3032,769 @@ msgstr ""
 "Tuodaksesi musiikkikirjastosi Audacioukseen, valitse kansio ja paina sen "
 "jälkeen päivitys painiketta."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Odota..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Valitse kansio"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
 msgstr ""
 
-#: src/skins/menus.c:57
-msgid "Open URL ..."
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanavat:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Hiljaisuuden poisto"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Hiljaisuuden poisto</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Raja-arvo:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Avaa tiedostoja..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Avaa URL..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Etsi kirjastosta"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Toisto"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Soittolista"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Näkymä"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Palvelut"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Tietoja..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Asetukset..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Lopeta"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
+msgstr "Kappaleen tiedot..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Kertaus"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Sekoitus"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Älä etene soittolistalla"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
-
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Edellinen"
+msgstr "Lopeta tämän kappaleen jälkeen"
 
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Siirry kappaleeseen..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Siirry kohtaan..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Uusi soittolista"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Nimeä uudelleen soittolista..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Poista soittolista"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Edellinen soittolista"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Seuraava soittolista"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Tuo soittolista..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Vie soittolista..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Soittolistan hallinta..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Jonohallinta..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Päivitä soittolista"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Näytä soittolistan muokkain"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Näytä taajuuskorjain"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Näytä jäljellä oleva aika"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Aina päällimmäisenä"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "Kaikissa työtiloissa"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
-msgid "Add URL ..."
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "Lisää URL..."
+
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Lisää tiedostoja..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Nimen mukaan"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Tiedostonimen mukaan"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Poista kaikki"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Tyhjennä jono"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Poista ei saatavilla olevat tiedostot"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Poista kopiot"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Poista ei valitut"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Poista valitut"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Etsi ja valitse"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Käänteinen valinta"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Ei mitään"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Valitse kaikki"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Albumin mukaan"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Raidan mukaan"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Esittäjän mukaan"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Albumin mukaan"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Raidan mukaan"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Sekoita lista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Käännä lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Järjestä valitut"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Lajittele lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Leikkaa"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopioi"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Liitä"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Lataa esiasetus..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Lataa oletus"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Lataa esiasetustiedosto..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Lataa EQF-tiedosto..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Tallenna esiasetus..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Tallenna oletus"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Tallenna esiasetustiedosto..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Tallenna EQF-tiedosto..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Poista esiasetus..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Tuo Winamp-esiasetukset..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winampin klassinen käyttöliittymä"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Tallenna"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Lataa"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Lataa esiasetustiedosto"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Lataa EQF-tiedosto"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Tallenna esiasetustiedosto"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Tallenna EQF-tiedosto"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Tuo Winamp-esiasetukset"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Esiasetukset"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Lataa esiasetus"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Lataa automaattinen esiasetus"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Tallenna esiasetukset"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Tallenna automaattinen esiasetus"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Poista esiasetus"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Poista automaattisesti ladattava esiasetus"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Soitin:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Soitin:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Valitse pääikkunan kirjasin:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Soittolista:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Soittolista:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Valitse soittolistan kirjasin:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Fontit</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Käytä bittikartta-kirjasimia (vain ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Vieritä kappaleen nimeä"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Vieritä kappaleen nimeä kumpaankin suuntaan"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyzer"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Scope"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Pois"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normaali"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Tuli"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Viivat"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Palkit"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Hitain"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Hidas"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Keskinkertainen"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Nopea"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Nopein"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Jää"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Tasainen"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Tyyppi</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Visualisoinnin tyyppi:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Näytä piikit"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Väritys:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Tyyli:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Yleiset"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualisaatio"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Esivahvistus"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audaciouksen taajuuskorjain"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Siirry kohtaan %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Äänenvoimakkuus: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Tasapaino: %d%% vasen"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Tasapaino: keskellä"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Tasapaino: %d%% oikea"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Asetusvalikko"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Poista käytöstä 'Aina päällimmäisenä'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Käytä 'Aina päällimmäisenä'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Tiedoston tietolaatikko"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Kertauksen alkupiste A asetettu."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Kertauksen loppupiste B asetettu."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Kertauspisteet tyhjennetty."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Yksittäinen -tila."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Soittolista -tila."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Pysäytä kappaleen jälkeen."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Etsi kappaleita aktiivisesta soittolistasta"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3596,57 +3806,61 @@ msgstr ""
 "merkitystä. Jos et tiedä kuinka säännöllisiä lausekkeita käytetään, kirjoita "
 "kenttään suoraan se mitä haluat etsiä."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Nimi:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Albumi:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Esittäjä:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr "Tiedostonimi:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Tyhjennä aiempi valinta ennen hakemista"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Lisää tai poista automaattisesti täsmäävät kappaleet jonosta"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Luo uusi soittolista täsmäävistä kappaleista"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audaciouksen soittolistan muokkain"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d / %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Pakattu Winamp 2.x skini"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Pakkaamaton Winamp 2.x skini"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Ei voitu luoda kansiota (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile-liitännäinen"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3686,82 +3900,74 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile-liitännäinen"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Tietoja Sndio Output -liitännäisestä"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
-"Sndio Output -liitännäinen\n"
-"\n"
-"Luonut Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formaattia ei tueta"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Laite (tyhjä oletusta varten):"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
-"Yritettiin toistaa formaattia jota äänilaite ei tue.\n"
-"\n"
-"Yritä uudelleen kun sndiod(1) palvelin on käynnissä."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio-laite"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio-virhe: äänimuoto ei ole tuettu (%d)"
+
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio-virhe: sio_open() epäonnistui"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(tyhjä tarkoittaa oletusta)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio-virhe: sio_setpar() epäonnistui"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio-virhe: sio_start() epäonnistui"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Kappaleen vaihtuminen"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Komento joka ajetaan kun kappaleen toisto alkaa."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Komentoriville syötettävät parametrit tulisi asettaa "
+"lainausmerkkien sisään. Lainausmerkkien käyttämättä jättäminen on "
+"tietoturvariski.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Komennot</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Komento:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Kappaleen alussa suoritettava komento:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Komento joka ajetaan kun kappale lähestyy loppua."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Kappaleen päättyessä suoritettava komento:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Komento joka ajetaan kun päästään soittolistan loppuun."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Soittolistan päättyessä suoritettava komento:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Komento joka ajetaan kun kappaleen nimi vaihtuu (esim. internet-virrat)."
+"Suoritettava komento, kun kappaleen nimi muuttuu (verkon suoratoistoja "
+"varten):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3775,36 +3981,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Voit käyttää seuraavia merkkijonoja jotka \n"
-"korvataan komentoa kutsuttaessa.\n"
-"(kaikki eivät välttämättä ole hyödyllisiä):\n"
-"\n"
-"%F: taajuus (hertseinä)\n"
-"%c: kanavien lukumäärä\n"
-"%f: tiedostopolku\n"
-"%l: kesto (millisekunteina)\n"
-"%n tai %s: kappaleen nimi\n"
-"%r: nopeus (bittejä/sekunti)\n"
-"%t: sija soittolistassa (%02d)\n"
-"%p: toistetaanko jotain (1 tai 0)\n"
-"%a: esittäjä\n"
-"%b: albumi\n"
-"%T: kappaleen nimi"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Komentoriville syötettävät parametrit tulisi asettaa "
-"lainausmerkkien sisään. Lainausmerkkien käyttämättä jättäminen on "
-"tietoturvariski.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Komennot"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Kappaletiedot (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3818,51 +4004,51 @@ msgstr ""
 "Perustuu Sample Rate Converter -liitännäiseen:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Nopea"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Matala"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Korkea"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Erittäin korkea"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Laatu:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Nopeus ja sävelkorkeus"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Nopeus ja sävelkorkeus</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Nopeus:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Sävelkorkeus:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Nopeus ja sävelkorkeus"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Tilaikoni"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "Ase_tukset..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3879,39 +4065,39 @@ msgstr ""
 "\n"
 "Tämä liitännäinen tarjoaa järjestelmäpalkkiin sijoitettavan ikonin."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Hiiren rullan vieritystoiminto</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Muuta äänenvoimakkuutta"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Vaihda kappaletta"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Muut asetukset</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Poista ponnahdusikkuna käytöstä"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Sulje järjestelmäpalkkiin"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Etene soittolistassa kun vieritetään ylöspäin"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Tilaikoni"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3921,24 +4107,24 @@ msgstr ""
 "\n"
 "By Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Sointugeneraattori"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Sointugeneraattori:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3952,15 +4138,11 @@ msgstr ""
 "Käyttääksesi, lisää URL: tone://frequency1;frequency2;frequency3;...\n"
 "esim. tone://2000;2005 toistaaksesi 2000 Hz:n ja 2005 Hz:n soinnun"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Sointugeneraattori"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Äänen poisto"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3998,11 +4180,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis -dekooderi"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX-dekooderi"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4012,19 +4218,19 @@ msgstr ""
 "Perustuu in_vtx.dll:ään, luonut Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious liitännäisen luonut Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX-dekooderi"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack-dekooderi"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "häviöllinen (hybridi)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "häviöllinen"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4034,14 +4240,18 @@ msgstr ""
 "\n"
 "Osan liitännäisen koodista kirjoittanut Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack-dekooderi"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF-dekooderi"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF-asetukset</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Älä huomioi tiedoston ilmoittamaa kestoa"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML jaettavat soittolistat (XSPF)"
diff --git a/po/fr.po b/po/fr.po
index 949af2b87aba..7cd058dec7d3 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -3,18 +3,18 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Alain-Olivier  Breysse, 2012-2013
-# Oxayotl <jagw40k at free.fr>, 2013
+# yahoe.001, 2012-2013
+# Oxayotl <jagw40k at free.fr>, 2013-2014
 # Oxayotl <jagw40k at free.fr>, 2011-2012
 # Jean-Alexandre Anglès d'Auriac <jagw40k at free.fr>, 2011
-# Alain-Olivier  Breysse, 2013-2014
+# yahoe.001, 2013-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:41+0000\n"
-"Last-Translator: Alain-Olivier  Breysse\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-03-15 20:32+0000\n"
+"Last-Translator: yahoe.001\n"
 "Language-Team: French (http://www.transifex.com/projects/p/audacious/"
 "language/fr/)\n"
 "Language: fr\n"
@@ -23,40 +23,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "son ambiophonique"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Décodeur AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Décodeur AAC (brut)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Lecteur AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "séquencé"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Lecteur AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarme"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Définir l'alarme..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -66,11 +54,7 @@ msgstr ""
 "\n"
 "Développé à l'origine par Adam Feakin et Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarme"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -110,7 +94,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -149,7 +133,7 @@ msgstr ""
 "    Exécute cette commande à l'heure de l'alarme.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -173,384 +157,390 @@ msgstr ""
 "    Saisir le rappel dans le champs de texte et cocher\n"
 "    la case pour que le rappel soit affiché."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Ceci est votre réveil."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Votre pense-bête pour aujourd'hui est…"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Pense-bête"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Lundi"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Mardi"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Mercredi"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Jeudi"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Vendredi"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Samedi"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Dimanche"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarm Settings"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_OK"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Annuler"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Heure"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarme à (par défaut) :"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silencieux après :"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "heures"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutes"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Choisir les jours où l'alarme se déclenche"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Jour"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Par défaut"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Jours"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Fondu"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "secondes"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Commencer à"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Finir à"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actuel"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Commande additionnelle"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "activer"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Liste de lecture (optionnelle)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Choisir une liste de lecture"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Options"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Que signifient ces options ?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Aide"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Illustration"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Illustration (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Sortie ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Greffon de sortie ALSA pour Audacious\n"
+"Tous droits réservés © 2009-2012 John Lindgren\n"
+"Mes remerciements à Wiliam Pitcock, auteur du greffon de sortie ALSA NG, "
+"dont le code a servi de référence lorsque la documentation d'ALSA n'était "
+"pas suffisante."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(aucune description)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Périphérique PCM par défaut"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Mélangeur audio par défaut"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Périphérique PCM :"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Canal de mélange audio :"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mélangeur :"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Contourner le problème d'interruption du flux"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Lecteur MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Greffon de sortie ALSA pour Audacious\n"
-"Tous droits réservés © 2009-2012 John Lindgren\n"
-"Mes remerciements à Wiliam Pitcock, auteur du greffon de sortie ALSA NG, "
-"dont le code a servi de référence lorsque la documentation d'ALSA n'était "
-"pas suffisante."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Sortie ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (Lecteur MIDI)"
+"AMIDI-Plug\n"
+"lecteur musical modulaire MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"écrit par Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"un grand merci à...\n"
+"\n"
+"Clemens Ladisch et Jaroslav Kysela\n"
+"pour leurs excellents programmes aplaymidi et amixer ;\n"
+"ils furent très utiles, avec les docs alsa-lib, afin d'en apprendre\n"
+"plus sur l'API ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"pour le beau logo de clavier MIDI\n"
+"\n"
+"Tony Vroon\n"
+"pour son aide appréciée durant les tests alpha"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Remplacer le gain par défaut :"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Remplacer la polyphonie par défaut :"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Remplacer la réverbération par défaut :"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Marche"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Remplacer le refrain par défaut :"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Lecture</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Transposer :"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "demi-tons tempérés"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Décalage des percussions :"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Avancé</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "numéros de note"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Extraire les commentaires des fichiers MIDI"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Ignorer le silence d'ouverture"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Extraire les paroles des fichiers MIDI"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Ignorer le silence de fermeture"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Synthétiseur</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Fréquence d'échantillonnage :"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Fréquence de l'échantillon :"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - choix du fichier SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Annuler"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Ouvrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Nom du fichier"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Nom de fichier"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Taille (octets)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nom :"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Infos MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format :"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Durée (ms) :"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Nombre de pistes :"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM :"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg) :"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Division du temps :"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Commentaires et paroles MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
-msgstr "* aucun commentaire disponible dans ce fichier MIDI *"
+msgstr "* aucun commentaire proposé dans ce fichier MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
-msgstr "* aucune parole disponible dans ce fichier MIDI"
+msgstr "* aucune parole proposée dans ce fichier MIDI"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Fermer"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 invalide)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "À propos d'AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"lecteur musical modulaire MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"développé par Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"un grand merci à...\n"
-"\n"
-"Clemens Ladisch et Jaroslav Kysela\n"
-"pour leurs excellents programmes aplaymidi et amixer ;\n"
-"ils furent très utiles, avec les docs alsa-lib, afin d'en apprendre\n"
-"plus à propos de l'interface de programmation ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"pour le beau logo de clavier MIDI\n"
-"\n"
-"Tony Vroon\n"
-"pour son aide appréciée durant les tests alpha"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -568,156 +558,151 @@ msgstr ""
 "Basé en partie sur la bibliothèque Ghosd de Evan Martin :\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Affichage à l'écran)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectangle"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectangle arrondi"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectangle concave"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Aucun"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Début de la lecture"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "Déclenche l'affichage à l'écran lorsqu'une entrée de la liste de lecture est "
 "jouée."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Changement de titre"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Déclenche l'affichage à l'écran si, pendant la lecture, le titre du morceau "
-"change alors que le nom du fichier est identique. Cette option est "
-"particulièrement utile pour afficher le changement de titre des flux "
-"Internet."
+"Déclenche l'affichage à l'écran lorsque le titre du morceau change (pour les "
+"flux Internet) :"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "En pause"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Déclenche l'affichage à l'écran lorsque la lecture est mise en  pause."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pause désactivée"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 "Déclenche l'affichage à l'écran lorsque la pause de lecture eest désactivée."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Position"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Décalage horizontal X :"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Décalage vertical Y :"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Largeur maximale d'affichage à l'écran :"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Options pour moniteurs multiples"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Affichage à l'écran avec :"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "tous les moniteurs"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "le moniteur %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Durée (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Affichage :"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Fondu d'entrée :"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Fondu de sortie :"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Polices"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Police %i :"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Ombre"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Style du rendu"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Couleurs"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Couleur %i :"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Activer le déclencheur"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Événement"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Gestionnaire composite détecté"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -728,112 +713,112 @@ msgstr ""
 "veuillez activer un gestionnaire composite sinon l'affichage à l'écran ne "
 "fonctionnera pas correctement."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "La fausse transparence ne nécessite pas de gestionnaire composite."
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparence"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Fausse transparence"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Véritable transparence (nécessite l'extension composite de X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "L'extension composite n'est pas chargée"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
-msgstr "L'extension composite n'est pas disponible"
+msgstr "L'extension composite n'est pas proposée"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Affichage à l'écran Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Affichage à l'écran Audacious - configuration"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Test"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Définir"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Arrangement"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animation"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texte"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Décoration"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Déclenchement"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Options diverses"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Test"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "Liste de lecture ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listes de lecture ASXv1 et ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listes de lecture au format Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Couleur</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Oscilloscope flou"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Stéréophonique-vers-binaural  Bauer (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Préréglages :"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Niveau d'entrée :"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Fréquence de coupure :"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Préréglages :"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Stéréophonique-vers-binaural  Bauer (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analyseur de spectre"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Greffon CD audio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -855,173 +840,160 @@ msgstr ""
 "\n"
 "Ceci était un projet Google « Summer of Code » de 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Lecteur</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Vitesse de lecture :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Forcer le lecteur :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Métadonnées</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Utiliser CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Utiliser CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Utiliser HTTP à la place de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Serveur :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Chemin :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Greffon CD audio"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Échec de l'initialisation du sous-système cdio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI %s invalide."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Piste %d non trouvée."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "La piste %d en est une de données."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Échec de l'ouverture de la sortie audio"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Erreur de lecture du CD audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Piste %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Échec de l'ouverture du lecteur de CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Aucun lecteur de CD audio n'a été trouvé."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "N'a pu finir d'initialiser le lecteur CD ouvert."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Échec de la récupération du premier et/ou du dernier numéro de piste"
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 "Impossible de lire le numéro de secteur logique (LSN) de début ou de fin "
 "pour la piste %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Échec de la connexion à CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Échec de la requête auprès du serveur CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Échec de la requête auprès du serveur CDDB : %s ."
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Échec de la lecture des informations cddb : %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Le lecteur est vide"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Type de disque non pris en charge."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Éléments du menu CD Audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Lire le CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Ajouter un CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Éléments du menu CD Audio"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compression</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Volume central :"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Plage dynamique :"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Greffon de compression d'étendue dynamique pour Audacious\n"
-"Tous droits réservés © 2010-2012 John Lindgren"
+"Tous droits réservés © 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compresseur de gamme dynamique"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1038,206 +1010,238 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Grave :"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Aigu :"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Écho :"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Durée par défaut du morceau :"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Rééchantillonnage</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Activer le rééchantillonnage"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Fréquence de rééchantillonnage :"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorer la durée des balises SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Augmenter la réverbération"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Décodeur « Game Console Music »"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Le fondu enchaîné a échoué car les morceaux avaient un nombre différents de "
-"canaux.  Tu peux utiliser le « Mélangeur de canaux » pour les uniformiser."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Sortie CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Le fondu enchaîné a échoué car les morceaux avaient des taux "
-"d’échantillonnage différents. Tu peux utiliser le « Convertisseur de taux "
-"d’échantillonnage » pour les uniformiser."
+"Greffon de sortie CoreAudio pour Audacious\n"
+"Tous droits réservés © 2014 William Pitcock\n"
+"\n"
+"Basé sur le greffon de sortie SDL pour Audacious\n"
+"Tous droits réservés © 2010 John Lindgren"
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Utiliser le mode exclusif"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Greffon de fondus pour Audacious\n"
-"Tous droits réservés © 2010-2012 John Lindgren"
+"Greffon de fondu enchaîné pour Audacious\n"
+"Tous droits réservés © 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Fondu enchaîné</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Lors d'un changement automatique de morceau"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Recouvrement:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Lors d'un positionnement ou d'un changement manuel de morceau"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Astuce</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Pour un meilleur fondu, activer\n"
+"l'effet Suppression des silences."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Fondu enchaîné"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Le fondu enchaîné a échoué car les morceaux avaient un nombre différents de "
+"canaux.  Tu peux utiliser le « Mélangeur de canaux » pour les uniformiser."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Le fondu enchaîné a échoué car les morceaux avaient des taux "
+"d’échantillonnage différents. Tu peux utiliser le « Convertisseur de taux "
+"d’échantillonnage » pour les uniformiser."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalliseur</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensité :"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalliseur "
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Greffon des fichiers .cue"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Supprimer les fichiers"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Erreur lors du déplacement de %s vers la corbeille : %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Erreur lors de la suppression de %s : %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Erreur lors de la suppression de %s : n'est pas un fichier local."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Voulez-vous déplacer les fichiers sélectionnés vers la corbeille ?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Déplacer vers la corbeille"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Voulez-vous supprimer définitivement les fichiers sélectionnés ?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Supprimer"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Annuler"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Supprimer les fichiers"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Supprimer les fichiers sélectionnés"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Méthode de suppression</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Déplacer vers la corbeille au lieu de supprimer immédiatement"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Greffon d'écho\n"
+"Par Johan Levin, 1999\n"
+"Écho ambiophonique par Carl van Schaik, 1999\n"
+"Mise à niveau pour Audacious par William Pitcock et John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Écho</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Retard :"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retour :"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volume :"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Effet d'écho\n"
-"Par Johan Levin, 1999\n"
-"\n"
-"Effet d'écho ambiophonique par Carl van Schalk, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Écho"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Greffon FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1253,55 +1257,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Greffon FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Greffon FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Format du fichier de sortie :"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurer"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Enregistrer dans le répertoire d'origine"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Enregistrer dans un répertoire personnalisé"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Dossier de destination :"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Choisir un dossier"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obtenir le nom du fichier à partir de :"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Générer le nom de fichier à partir de :"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "balises originales du fichier"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Balise originale du fichier"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nom du fichier original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nom original du fichier"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Conserver l'extension du nom de fichier"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Inclure l'extension originale du nom de fichier"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr "Ajouter le numéro de la piste au début du nom du fichier"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1332,165 +1336,169 @@ msgstr ""
 "temps que ce programme ; si ce n’est pas le cas, écrivez à la Free Software "
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Greffon FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Stéréo combinée"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stéréo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuration MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Qualité de l'algorithme :"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Fréquence d'échantillonnage de sortie :"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Fréquence de sortie de l'échantillon :"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Débit binaire / Taux de compression :"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Rapport débit binaire / compression :"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Débit binaire (kbps)"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Taux de compression :"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Mode audio :"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Divers :"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Forcer le respect strict des normes ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Respecter rigoureusement les normes ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Protection contre les erreurs"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualité"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
-msgstr "Activer DBV/DBM (Débit Binaire Variable/Débit Binaire Moyen)"
+msgstr "Activer DBV/DBM (débit binaire variable/débit binaire moyen)"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Type :"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Options DBV :"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Débit binaire minimal (kbps) :"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Débit binaire maximal (kbps) :"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Forcer de manière stricte le débit binaire minimal"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Options DBM :"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Débit binaire moyen (kbps) :"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
-msgstr "Niveau de qualité BDV (Débit Binaire Variable) :"
+msgstr "Niveau de qualité DBV (débit binaire variable) :"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Ne pas écrire l'en-tête BDV Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omettre l'en-tête DBV (débit binaire variable) Xing"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
-msgstr "DBV/DBM (Débit Binaire Variable/Débit Binaire Moyen)"
+msgstr "DBV/DBM (débit binaire variable/débit binaire moyen)"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Paramètres de trame :"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marquer comme soumis aux droits d'auteur"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marquer comme originale"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Paramètres ID3 :"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forcer l'ajout de la version 2 des balises"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Ajouter uniquement la version 1 des balises"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Ajouter uniquement la version 2 des balises"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Balises"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuration de l'encodeur Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Niveau de qualité (0 - 10) :"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Décodeur FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sans perte"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1502,11 +1510,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Décodeur FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1514,11 +1518,19 @@ msgstr ""
 "Greffon GIO pour Audacious\n"
 "Tous droits réservés © 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Greffon GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Le mode lecture-et-ajout n'est pas pris en charge"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Mode d'ouverture invalide"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1538,534 +1550,620 @@ msgstr ""
 "\n"
 "Licence : GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analyseur de spectre utilisant OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Analyseur de spectre OpenGL pour Audacious\n"
+"Tous droits réservés © 2013 Christophe Budé, John Lindgren et Carlo Bramini\n"
+"Tous droits réservés © 2014 William Pitcock\n"
+"\n"
+"Basé sur le greffon XMMS :\n"
+"Tous droits réservés © 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas "
+"Nilsson, et 4Front Technologies\n"
+"\n"
+"Licence : GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analyseur de spectre OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Raccourcis de GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Greffon de support des raccourcis de Gnome\n"
-"Permet de contrôler Audacious via les raccourcis de Gnome\n"
+"Greffon de prise en charge des raccourcis de GNOME\n"
+"Vous permet de contrôler le lecteur avec les raccourcis de GNOME\n"
 "\n"
 "Tous droits réservés © 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Raccourcis de Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Numéro de l'entrée"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Titre"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artiste"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Année"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artiste de l'album"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Numéro de piste"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Genre"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Position dans la file"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Durée"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Chemin du fichier"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nom du fichier"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Titre personnalisé"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Débit binaire"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr "Colonnes disponibles :"
+msgstr "Colonnes proposées :"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Colonnes affichées"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Outil de recherche"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Intégrer à gauche"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Intégrer à droite"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Intègrer en haut"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Intègrer en bas"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Séparer"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Désactiver"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Outil de recherche"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Ouvrir des fichiers..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Ouvrir une _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Ajouter des fichiers..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Ajouter une U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Rechercher dans _l'audiothèque"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "À propos _de..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Paramètres..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Quitter"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Lire"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Paus_e"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Arrêt"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Pré_cédent"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "S_uivant"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Répéter"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Lecture _aléatoire"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_Ne pas avancer dans la liste de lecture"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Arrêter après ce morceau"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Infos sur le morceau..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Sauter à la _position... (temps)"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Sauter au _morceau..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Point de répétition _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Point de répétition _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Effacer les points de répétition"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Par _titre"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Par nom de _fichier"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Par chemin de _fichier"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Par _chemin de fichier"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Par _numéro de piste"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Par _artiste"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Par al_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Par Artiste de l'albu_m"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Par _date de parution"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Par _Genre"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Par _durée"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
-msgstr "Par chemin d'accès de _fichier"
+msgstr "Par chemin de _fichier"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Par _titre personnalisé"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Ordre i_nversé"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Ordre _aléatoire"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Lire cette liste de lecture"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Lire/Reprendre"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Rafraîchir"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Trier"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Trier la sé_lection"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Enlever les _doublons"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
-msgstr "Retirer les fichiers _non disponibles"
+msgstr "Retirer les fichiers _absents"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nouvelle"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
-msgstr "Re_nommer ..."
+msgstr "Re_nommer..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Enle_ver"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importer"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exporter"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "_Gestionnaire de listes de lecture..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Gestionnaire de file d'_attente..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Augmenter le _volume"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Réduire le volume"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "Éga_liseur"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_ffets..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Afficher la barre de _menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Afficher la barre d'i_nfos"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Afficher la vis_ualisation « Barre d'infos »"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Afficher la _barre d'état"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Afficher le temps _restant"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Visualisations..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fichier"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Lecture"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "L_iste de lecture"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Services"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Sortie"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Affichage"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Ajouter / retirer de la file d'attente"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Ouvrir le dossier conteneur"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Cou_per"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copier"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Coller"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Sélectionner _tout"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
-msgstr "_Renommer  …"
+msgstr "_Renommer…"
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Onglets de la liste de lecture</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Toujours montrer les onglets"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Montrer le nombre d'entrées"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Montrer les boutons de fermeture"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Colonnes de la liste de lecture</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Montrer les en-têtes des colonnes"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Divers</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr "Avance/retour avec les flèches :"
+msgstr "Positionnement avec les flèches :"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Déplacer vers le morceau en cours"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interface GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Mise en mémoire tampon..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canaux"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Mode « Fichier unique »."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Mode « Liste de lecture »."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Arrêter après le morceau."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Piste précédente"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Lire"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pause/Reprise"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Arrêt"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Piste suivante"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avancer de 5 secondes"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Reculer de 5 secondes"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Muet"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Augmenter le volume"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Réduire le volume"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Sauter au fichier"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Montrer/cacher les fenêtres du lecteur"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Activer l'affichage à l'écran"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Activer/désactiver la répétition"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Activer/désactiver la lecture aléatoire"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Activer/désactiver l'arrêt après le morceau en cours"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Monter les fenêtres du lecteur au premier plan"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(aucun)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2077,15 +2175,11 @@ msgstr ""
 "\n"
 "Souhaitez-vous poursuivre ?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Association des boutons de la souris"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuration du greffon « Raccourcis universels »"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2094,23 +2188,27 @@ msgstr ""
 "Vous pouvez aussi créer des associations avec les boutons de la souris.\n"
 " "
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Raccourcis clavier :"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Action : </b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Association de touches :</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Ajouter"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Raccourcis universels"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2137,60 +2235,59 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Raccourcis universels"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Sortie JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Connecter à tous les ports Jack disponibles"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Se connecter automatiquement aux ports de sortie"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Connecter seulement aux ports de sortie"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
+"Seulement %d ports de sortie JACK ont été trouvés mais sont %d sont exigés."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Ne connecter à aucun port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Erreur lors de la connexion au port JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Mode de connexion :"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK ne prend en charge que l'audio à virgule flottante. Vous devez changer "
+"la profondeur de sortie binaire pour « virgule flottante » dans les "
+"paramètres d'Audacious."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Activer l'impression du débogage"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
+"Échec lors de la connexion au serveur JACK ; est-il en cours d'exécution ?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Basé sur xmms-jack, par Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Porté pour Audacious par Giacomo Lozito"
+"Le serveur JACK exige un taux d'échantillonnage de %d Hz, mais Audacious lit "
+"à %d Hz. Veuillez utiliser l'effet Convertisseur de taux d’échantillonnage "
+"pour corriger cette discordance."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Sortie JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Réglages %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Réglages de l'hôte ADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Chemins de recherche des greffons :"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2201,25 +2298,25 @@ msgstr ""
 "Après avoir ajouté de nouveaux chemins, presser sur Entrée pour rechercher "
 "des nouveaux greffons.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
-msgstr "Greffons disponibles :"
+msgstr "Greffons proposés :"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Activer"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Greffons activés :"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Paramètres"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2227,47 +2324,15 @@ msgstr ""
 "Hôte LADSPA pour Audacious\n"
 "Tous droits réservés © 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
-msgstr "Hôte LADSPA"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: n'a pas pu initialiser la prise en charge de LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: N'a pas pu lire le fichier de configuration de LIRC\n"
-"%s: veuillez lire la documentation de LIRC STP\n"
-"%s: comment créer un fichier de configuration valide\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: essaie de se reconnecter…\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: commande inconnue « %s »\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: déconnecté de LIRC\n"
+msgstr "Hôte LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: essaiera de se reconnecter toutes les %d secondes…\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Greffon LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2296,73 +2361,81 @@ msgstr ""
 "\n"
 "Pour plus d'information sur LIRC, se référer à http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Connexion</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Se reconnecter automatiquement au serveur LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Attendre avant de se reconnecter :"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Greffon LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Greffon LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
-msgstr "Aucune parole disponible"
+msgstr "Aucune parole proposée"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Erreur"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Impossible de récupérer %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Erreur"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Impossible d'analyser %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Recherche de paroles …"
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Métadonnées de morceau manquantes"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Connexion à lyrics.wikia.com …"
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Greffon LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Greffon LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listes de lecture M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Métronome"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Métronome : %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Métronome : %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2376,11 +2449,11 @@ msgstr ""
 "Par exemple. tact://77 pour battre 77 temps par minutes\n"
 "ou tact://60*3/4 pour battre 60 temps en mesures 3/4"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Métronome"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mélangeur de canaux"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2388,152 +2461,184 @@ msgstr ""
 "Greffon de mélange des canaux pour Audacious\n"
 "Tous droits réservés © 2011-2012 John Lindgren et Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mélangeur de canaux</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canaux de sortie :"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mélangeur de canaux"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Greffon MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Erreur lors de la connexion au serveur MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Lecteur de module)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Résolution</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bits"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bits"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canaux</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Le plus proche (le plus rapide)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linéaire (rapide)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Interpolation par segments (bon)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polyphasé  (le meilleur) "
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Fréquence d’échantillonnage</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Taux de l'échantillon</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr " Niveau :"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Coupure :"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Réverbération</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Amplificateur de basses</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Ambiophonique </b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Préampli</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Suréchantillonnage"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Réduction du bruit"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Jouer les MODs Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Répéter</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Comptage des répétitions :"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Pour répéter à l'infini, mettre le comptage des répétions à -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Lecteur de module)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Son ambiophonique"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Ces paramètres prendront effet lorsque Audacious sera redémarré."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Greffon MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avancé</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Utiliser un calcul précis de durée (lent)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Son ambiophonique"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Serveur MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Greffon HTTP/HTTPS neon"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Erreur lors de l'analyse de la redirection"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Erreur HTTP inconnue"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Erreur lors de l'analyse de l'URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Trop de redirections"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Arrêté"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious est inactif."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notifications du bureau"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2571,55 +2676,64 @@ msgstr ""
 "temps que ce programme ; si ce n’est pas le cas, écrivez à la Free Software "
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Permettre le contrôle d'Audacious depuis les notifications."
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Rendre les notifications persistantes."
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notifications du bureau"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Inclure le nom de l'album dans la notification"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Afficher"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pause"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Suivant"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Périphérique par défaut"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Sortie OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Sortie OSS3"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositif par défaut"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Périphérique audio :"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Utiliser un autre périphérique :"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Conserver le volume d'une session à l'autre"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Activer les conversions de format du logiciel OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Activer le mode exclusif pour empêcher le mixage virtuel."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2634,19 +2748,35 @@ msgstr ""
 "Tony Vroon and John Lindgren, et bien entendu les auteurs du précédent "
 "greffon OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Sortie OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Gestionnaire de listes de lecture"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Entrées"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Enlever"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Ren_ommer"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listes de lecture PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Décodeur OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Sortie PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2681,11 +2811,73 @@ msgstr ""
 "temps que ce programme ; si ce n’est pas le cas, écrivez à la Free Software "
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Sortie PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Sortie QtMultimédia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Sortie Audio QtMultimédia pour Audacious\n"
+"Tous droits réservés © 2014 Willian Pitcock\n"
+"\n"
+"Basé sur le greffon de sortie SDL pour Audacious\n"
+"Tous droits réservés © 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Je travaille..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Rechercher"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Ouvrir un dossier..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Ajouter un dossier..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Inspecteur de journaux..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Fichiers ouverts"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Ajouter des fichiers"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Précédent"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Répéter"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Lecture aléatoire"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interface Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertisseur de taux d’échantillonnage"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2693,100 +2885,108 @@ msgstr ""
 "Greffon de convertisseur de taux d’échantillonnage pour Audacious\n"
 "Tous droits réservés © 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Sauter/répéter les échantillons"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolation linéaire"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolation sinus cardinal rapide"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolation sinus cardinal moyenne"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Interpolation sinus cardinal la meilleure"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversion</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Méthode :"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Taux :"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mappage de taux</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Utiliser les mappages de taux"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz :"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz :"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22,05 kHz :"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32,0 kHz :"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz :"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz :"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88,2 kHz :"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz :"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176,4 kHz :"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz :"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertisseur de taux d’échantillonnage"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Scrobble pour l'utilisateur : %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Permission refusée."
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Accéder au lien suivant pour permettre à Audacious de scrobbler vos "
 "lectures :"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Garder cette fenêtre ouverte et cliquer sur « Vérifier les permissions » de "
 "nouveau.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2794,34 +2994,38 @@ msgstr ""
 "Pas d'inquiétude. Vos scrobbles sont sauvegardés sur votre ordinateur.\n"
 "Ils seront transmis dès qu'Audacious en aura la permission."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problème de réseau."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Il a eu un problème lors du contact de Last.fm. Ressayer plus tard."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
-msgstr "Vérification ..."
+msgstr "Vérification..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "Véri_fier les permissions"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Révoquer les permissions"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Vous devez autoriser Audacious à scrobbler vos pistes vers votre compte Last."
 "fm.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2829,7 +3033,7 @@ msgstr ""
 "Le greffon scrobbler n'a pu être démarré.\n"
 "Il y a peut-être un problème avec votre installation."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2848,11 +3052,7 @@ msgstr ""
 "ce projet.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2861,7 +3061,11 @@ msgstr ""
 "fm. \n"
 "Veuillez vérifier les propriétés du greffon Scrobbler 2.0."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Sortie SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2869,761 +3073,828 @@ msgstr ""
 "Greffon de sortie SDL pour Audacious\n"
 "Tous droits réservés © 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Sortie SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Audiothèque"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artiste inconnu"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Album inconnu"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" dans %s par %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d résultat"
+msgstr[1] "%d résultats"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d albums"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d caché)"
+msgstr[1] "(%d cachés)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d morceau"
-msgstr[1] ""
-"%s\n"
-" %s, %d morceaux"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d morceau par %s"
-msgstr[1] ""
-"%s\n"
-" %d morceaux par %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d morceau"
+msgstr[1] "%d morceaux"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "de ce genre"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "sur"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "par"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Créer une liste de lecture"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Ajouter à la liste de lecture"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Rechercher dans l'audiothèque"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
-"Pour importer votre audiothèque dans Audacious, choisir un dossier, puis "
-"utiliser l'icône de rafraîchissement."
+"Pour importer votre audiothèque dans Audacious, choisissez un dossier et "
+"cliquez ensuite sur l'icône de rafraîchissement."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Veuillez patienter…"
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Choisir un dossier"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Lecteur SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Sortie</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canaux :"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Émulation</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Émuler MOS 8580 (par défaut :  MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Ne pas choisir automatiquement le modèle de puce"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Émuler le filtre"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Vitesse d'horloge : "
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Ne pas choisir automatiquement la vitesse d'horloge"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Durée de lecture</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Définir une durée maximale de lecture :"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "À n'utiliser que si la longueur du morceau est inconnue"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Définir une durée minimum de lecture :"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Sous-morceaux</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Activer les sous-morceaux"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorer les sous-morceaux plus courts que :"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Note</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Suppression des silences"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Greffon de Suppression des silences pour Audacious\n"
+"Tous droits réservés © John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Suppression des silences</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Seuil :"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Ouvrir les fichiers..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Ouvrir l'URL..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Rechercher dans l'audiothèque"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Lecture"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Liste de lecture"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Affichage"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Services"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr "À propos de..."
+msgstr "À propos..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Paramètres..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Quitter"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Infos sur le morceau..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Répéter"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Lecture aléatoire"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Ne pas avancer dans la liste de lecture"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Arrêter après ce morceau"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Précédent"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Définir une répétition A-B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Effacer la répétition A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Sauter au morceau..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Sauter à la positon (temps)…"
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Jouer cette liste de lecture"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Lire/Reprendre"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nouvelle liste de lecture"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Renommer la liste de lecture..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Enlever la liste de lecture"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Liste de lecture précédente"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Liste de lecture suivante"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importer la piste de lecture..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Exporter la liste de lecture..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Gestionnaire de listes de lecture..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Gestionnaire de file d'attente..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Rafraîchir la liste de lecture"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Montrer l'éditeur de liste de lecture"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Montrer l'égaliseur"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Afficher le temps restant"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Toujours au premier plan"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Sur tous les espaces de travail"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Enrouler le lecteur"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Enrouler l'éditeur de listes de lecture"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Enrouler l'égaliseur"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Taille double"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Ajouter une URL..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Ajouter des fichiers..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Par titre"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Par nom de fichier"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Par chemin de fichier"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Tout enlever"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Vider la file d'attente"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
-msgstr "Effacer les fichiers non disponibles"
+msgstr "Effacer les fichiers absents"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Enlever les doublons"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Ne garder que la sélection"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Enlever la sélection"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Chercher et sélectionner"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverser la sélection"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Ne rien sélectionner"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Tout sélectionner"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Par album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Par numéro de piste"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Par artiste"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Par album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Par artiste de l'album"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Par date de parution"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Par numéro de piste"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Par Genre"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Par durée"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Par titre personnalisé"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Mélange aléatoirement la liste"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Inverser la liste"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Trier la sélection"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Trier la liste"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Couper"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copier"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Coller"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Mettre/enlever de la file d'attente"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Charger un préréglage..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Charger un préréglage automatique..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Charger la valeur par défaut"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Charger un fichier de préréglage..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Charger un fichier EQF..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Enregistrer le préréglage..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Enregistrer le préréglage automatique..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Enregistrer la valeur par défaut"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Enregistrer le fichier de préréglage..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Enregistrer le fichier EQF..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Supprimer le préréglage..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Supprimer le préréglage automatique..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importer les préréglages WinAMP..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Réinitialiser à zéro"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface Winamp Classic"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Enregistrer"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Charger"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Charger un fichier de préréglage"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Charger un fichier EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Enregistrer un fichier de préréglage"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Enregistrer un fichier EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importer les préréglages de WinAMP"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Préréglages"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Charger un préréglage"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Charger le réglage automatique"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Enregistrer le préréglage"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Enregistrer le réglage automatique"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Supprimer un préréglage."
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Supprimer le réglage automatique"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Lecteur :"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Lecteur :"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Choisir la police de la fenêtre principale du lecteur :"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Liste de lecture"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Liste de lecture :"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Choisir la police de la liste de lecture :"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Habillage</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Polices</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Utiliser des polices bitmap (seul ASCII est pris en charge)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Faire défiler le titre du morceau"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Faire défiler le titre dans les deux sens"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyseur"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Oscilloscope"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Spectrogramme/vumètre"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Arrêt"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Feu"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Lignes verticales"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Lignes"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barres"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "La plus lente"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lente"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Moyenne"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rapide"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "La plus rapide"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Points"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Lignes"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Plein"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Glace"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Lissé"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Type</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Type de visualisation :"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analyseur</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Afficher les crêtes"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Coloration :"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Style :"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Retombée :"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Retombée des crêtes :"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Style oscilloscope :"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Coloration du spectrogramme :"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Style vumètre :"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Général"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualisations"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Préampli"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Égaliseur d'Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
-msgstr "Aller à %d:%-2.2d/%d:%-2.2d"
+msgstr "Se positionner à %d:%-2.2d/%d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume : %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance : %d%% gauche"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance : centre"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance : %d%% droite"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu des options"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Désactiver « Toujours au premier plan »"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Activer « Toujours au premier plan »"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Boîte d'Infos sur le fichier"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualisations"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Point de répétition A activé."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Point de répétition B activé."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Points de répétition effacés."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Mode « Fichier unique »."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Mode « Liste de lecture »."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Arrêter après le morceau."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Chercher des entrées dans la liste de lecture active"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Rechercher"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3637,57 +3908,61 @@ msgstr ""
 "Si vous ne savez pas comment fonctionnent les expressions rationnelles, vous "
 "pouvez simplement indiquer une expression littérale de ce que vous cherchez."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Titre :"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Album :"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Artiste :"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nom du fichier :"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nom de fichier :"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Effacer la sélection précédente avant d'effectuer la recherche"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Mettre automatiquement dans la file d'attente les entrées trouvées"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Créer une nouvelle liste de lecture à partir des entrées trouvées"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Éditeur de liste de lecture d'Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d sur %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Habillage Winamp 2.x archivé"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Habillage Winamp 2.x non archivé"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Impossible de créer le répertoire (%s) : %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Greffon Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3727,84 +4002,73 @@ msgstr ""
 "temps que ce programme ; si ce n’est pas le cas, écrivez à la Free Software "
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Greffon Sndfile"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sortie sndio"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "À propos du greffon de sortie Sndio"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Greffon de sortie Sndio\n"
-"\n"
-"Développé par Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Périphérique (vide pour celui par défaut) :"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Format non pris en charge"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Enregistrer et restaurer le volume :"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Un format non pris en charge par le périphérique audio a été demandé.\n"
-"\n"
-"Veuillez essayer à nouveau avec le serveur sndiod(1) en fonction."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Erreur sndio : format audio non pris en charge (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "Périphérique sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Erreur sndio : échec de sio_open()"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(vide implique par défaut)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Erreur sndio : échec de sio_setpar()"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Erreur sndio : échec de sio_start()"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Changement de morceau"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Commande à exécuter lorsqu'Audacious commence un nouveau morceau."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Les arguments passés à la ligne de commande doivent être "
+"mis entre \" \". Ne pas le faire entraîne un risque de sécurité.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Commande :"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Commandes</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Commande à exécuter lorsque la lecture d'un morceau se termine."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Commande à exécuter lorsqu'un nouveau morceau commence :"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Commande à exécuter lorsqu'Audacious atteint la fin de la liste de lecture."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Commande à exécuter lorsqu'un morceau se termine :"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Commande à exécuter à la fin de la liste de lecture :"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Commande à exécuter lorsque le titre d'un morceau change (par exemple le "
-"titre d'un flux en réseau)."
+"Commande à exécuter lorsque le titre d'un morceau change (pour les flux "
+"réseau) :"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3818,35 +4082,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Vous pouvez utiliser les variables suivantes qui seront remplacées avant "
-"l'appel de la commande à exécuter (toutes ne sont pas utiles pour la "
-"fonction « fin de liste de lecture ») :\n"
-"\n"
-"%F : Fréquence (en Hertz)\n"
-"%c : Nombre de canaux\n"
-"%f : Nom du fichier (chemin complet)\n"
-"%l : Durée (en millisecondes)\n"
-"%n ou %s : Nom du morceau\n"
-"%r : Taux d'encodage (en bit par seconde)\n"
-"%t : Position dans la liste de lecture (%02d)\n"
-"%p : Lecture en cours (1 ou 0)\n"
-"%a : Artiste\n"
-"%b : Album\n"
-"%T : Titre de la piste"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Les arguments passés à la ligne de commande doivent être "
-"mis entre \" \". Ne pas le faire entraîne un risque de sécurité.</span>"
-
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Commandes"
+"Vous pouvez utiliser les chaînes de formatage suivantes qui seront\n"
+"remplacées avant l'appel de la commande (toutes ne sont pas utiles pour la "
+"commande fin-de-liste-de-lecture) :\n"
+"\n"
+"%F : fréquence (en hertz)\n"
+"%c : nombre de canaux\n"
+"%f : nom de fichier (chemin complet)\n"
+"%l : durée (en millisecondes)\n"
+"%n ou %s : nom du morceau\n"
+"%r : taux (en bits par seconde)\n"
+"%t : position dans la liste de lecture (%02d)\n"
+"%p : lecture en cours (1 ou 0)\n"
+"%a : artiste\n"
+"%b : album\n"
+"%T : titre de la piste"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Infos sur le morceau (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Ré-échantillonneur SoX"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3860,51 +4120,51 @@ msgstr ""
 "Basé sur le greffon de conversion du taux d'échantillonnage :\n"
 "Tous droits réservés © 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rapide"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Bas"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Haut"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Très haut"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualité :"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Ré-échantillonneur SoX"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Vitesse et hauteur"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Vitesse et hauteur</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Vitesse :"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Hauteur :"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Vitesse et hauteur"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icône d'état"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Pa_ramètres..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3922,39 +4182,39 @@ msgstr ""
 "Ce greffon ajoute une icône de contrôle d'Audacious dans la zone de "
 "notification de votre gestionnaire de fenêtre."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Action lors du défilement à la molette</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Changer le volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Changer le morceau en cours"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Autres paramètres</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Désactiver la fenêtre contextuelle"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Réduire dans la zone de notification"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avancer dans la liste de lecture en roulant la molette vers le haut"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icône d'état"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Stéréo additionnelle"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3964,24 +4224,24 @@ msgstr ""
 "\n"
 "Par Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Stéréo additionnelle</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Stéréo additionnelle"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Générateur de fréquences musicales"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Générateur de tonalités : "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3997,15 +4257,11 @@ msgstr ""
 "Par exemple. tone://2000;2005 pour jouer une note à 2 000 Hz en même temps "
 "qu'une note à 2 005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Générateur de fréquences musicales"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Suppression des voix"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4043,11 +4299,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Décodeur Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Détails à propos de %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Titre : %t\n"
+"Auteur : %a\n"
+"De : %f\n"
+"Tracker : %T\n"
+"Commentaire : %C\n"
+"Type de puce : %c\n"
+"Stéréo : %s\n"
+"Boucle : %l\n"
+"Fréq. de la puce : %F\n"
+"Fréq. du lecteur : %P\n"
+"Année : %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Décodeur VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4057,19 +4348,19 @@ msgstr ""
 "Basé sur in_vtx.dll par Roman Sherbakov <v_soft at microfor.ru>\n"
 "Greffon Audacious par Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Décodeur VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Décodeur WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr " avec perte (hybride)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "avec perte"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4079,23 +4370,18 @@ msgstr ""
 "\n"
 "Une partie du code du greffon a été développé par Miles Egan"
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Décodeur WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Décodeur 2SF"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "Listes de lecture XSPF"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32,0 kHz :"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configuration XFS</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88,2 kHz :"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorer la durée donnée par le fichier"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176,4 kHz :"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "Listes de lecture XSPF"
diff --git a/po/gl.po b/po/gl.po
index a38e454a42cc..2f5839cb757f 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -3,18 +3,18 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# antiparvos <marcoslansgarza at gmail.com>, 2014
-# mbouzada <mbouzada at gmail.com>, 2012
-# mbouzada <mbouzada at gmail.com>, 2013
-# mbouzada <mbouzada at gmail.com>, 2012
-# mbouzada <mbouzada at gmail.com>, 2012,2014
+# antiparvos <marcoslansgarza at gmail.com>, 2014-2015
+# Miguel Anxo Bouzada <mbouzada at gmail.com>, 2012
+# Miguel Anxo Bouzada <mbouzada at gmail.com>, 2013
+# Miguel Anxo Bouzada <mbouzada at gmail.com>, 2012
+# Miguel Anxo Bouzada <mbouzada at gmail.com>, 2012,2014-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:41+0000\n"
-"Last-Translator: antiparvos <marcoslansgarza at gmail.com>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 07:36+0000\n"
+"Last-Translator: Miguel Anxo Bouzada <mbouzada at gmail.com>\n"
 "Language-Team: Galician (http://www.transifex.com/projects/p/audacious/"
 "language/gl/)\n"
 "Language: gl\n"
@@ -23,40 +23,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estéreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "son envolvente"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Decodificador AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Decodificador AAC (en bruto)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (reprodutor AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "secuenciado"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (reprodutor AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarma"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Estabelecer a alarma ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -67,11 +55,7 @@ msgstr ""
 "\n"
 "Escrito orixinalmente por Adam Feakin e Stodden Daniel."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarma"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -113,7 +97,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -153,7 +137,7 @@ msgstr ""
 "     Executar esta orde no momento da alarma.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -177,384 +161,390 @@ msgstr ""
 "     escriba a mensaxe na caixa e acenda o\n"
 "     botón de activación se quere que se amose. "
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Esta é a súa chamada de atención."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "O seu recordatorio para hoxe é..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Lembranza"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "luns"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "martes"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "mércores"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "xoves"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "venres"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Configuración da alarma"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_Aceptar"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Cancelar"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Hora"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarma as (predeterminado):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silencio despois de:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Seleccione os días para que salte a alarma"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Día"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Predeterminado"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dias"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Esvaecemento"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Inicial"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Actual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Orde adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "activar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de reprodución (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Escolla a lista de reprodución"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opcións"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Que significan estas opcións?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Axuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Portada"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Portada (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Saída ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Engadido de saída ALSA para Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"O meu agradecemento para William Pitcock, autor do engadido de saída NG de "
+"ALSA, cuxo código serviu de referencia cando o manual de ALSA non foi abondo."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(sen descrición)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositivo PCM predeterminado"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositivo mesturador predeterminado"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositivo PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositivo mesturador:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemento mesturador:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Evitar as crebas por falta de recursos"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "Engadido AMIDI (Reprodutor MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Engadido de saída ALSA para Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"reprodutor musical MIDI modular\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"O meu agradecemento para William Pitcock, autor do engadido de saída NG de "
-"ALSA, cuxo código serviu de referencia cando o manual de ALSA non foi abondo."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Saída ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "Engadido AMIDI (Reprodutor MIDI)"
+"escrito por Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"agradecementos especiais a...\n"
+"\n"
+"Clemens Ladisch e Jaroslav Kysela\n"
+"polos seus excelentes programas aplaymidi e amixer; ambos\n"
+"realmente útiles, xunto coa documentación de alsa-lib, a fin\n"
+"de aprender máis sobre a API de ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"polo fermoso logotipo do teclado mididi\n"
+"\n"
+"Tony Vroon\n"
+"pola gran axuda coas probas da alfa"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Anular a ganancia predeterminada:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Anular a polifonía predeterminada:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Anular a reverberación predeterminada:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Acender"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Anular o coro predeterminado:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Reprodución</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Transposición:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "semitóns"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Cambio de batería:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Avanzado</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "números de nota"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Extraer comentarios desde o ficheiro MIDI"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Omitir o silencio principal"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Extraer letras desde o ficheiro MIDI"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Omitir o silencio posterior"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>Fonte de son</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Sintetizador</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "Taxa da mostraxe:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "Engadido AMIDI - seleccione un ficheiro SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Abrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nome de ficheiro"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamaño (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nome:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Información MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Duración (mseg.):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Num. de pistas"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variábel"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div. tempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\\\"smaller\\\"> Comentarios e letras MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* non hai comentarios dispoñíbeis neste ficheiro MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* non hai letras dispoñíbeis neste ficheiro MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Pechar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 incorrecto)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Sobre o engadido AMIDI"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "Engadido AMIDI"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Reprodutor musical modular MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Escrito por Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"O noso especial agradecemento a...\n"
-"\n"
-"Clemens Ladisch e Jaroslav Kysela\n"
-"polos magníficos programas aplaymidi e amixer; xa\n"
-"que eran moi necesarios xunto coa documentación\n"
-"de alsa-lib, a fin de coñecer mellor a API de ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"polo fermoso logotipo do teclado MIDI\n"
-"\n"
-"Tony Vroon\n"
-"pola gran axuda coas probas da alfa"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -572,156 +562,151 @@ msgstr ""
 "Baseado parcialmente na biblioteca Ghosd de Evan Marti:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Información en pantalla)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rectángulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rectángulo arredondado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rectángulo cóncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ningún"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Reprodución iniciada"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "Activa as notificacións OSD cando se reproduce un elemento da lista de "
 "reprodución."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cambio de título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Activa as notificacións OSD cando, durante a reprodución, o título da "
-"canción cambia mais o nome do ficheiro é o mesmo. Isto es útil, "
-"principalmente, para amosar os cambios de título nos fluxos da Internet"
+"Disparar OSD cando cambia o título da canción (para fluxos da Internet)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Inicio da pausa"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Activa as notificacións OSD cando a reprodución e posta en pausa"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Fin da pausa"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 "Activa as notificacións OSD cando a reinicia a reprodución despois dunha "
 "pausa"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Colocación"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Desprazamento X relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Desprazamento Y relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Largura máx. do OSD"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opcións de múltiple monitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Amosar as notificacións OSD utilizando:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "todos os monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Temporización (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Mostrar:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Esvaecemento de entrada:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Esvaecemento de saída:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Tipos de letra"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Tipo de letra %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo de debuxado"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Cores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Cor %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Activar disparador"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Actividade"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Detectouse un administrador de composición"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -731,113 +716,113 @@ msgstr ""
 "a non ser que saiba que ten un en execución, active un administrador de "
 "composición ou as notificacións OSD non funcionarán correctamente"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 "Para a falsa transparencia non fai falta un administrador de compòsición"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparencia"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparencia falsa"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparencia real (require composición 3D)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "A extensión de composición non está cargada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "A extensión de composición non está dispoñíbel"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Notificacións OSD de Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Notificacións OSD de Audacious - configuración"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Proba"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Estabelecer"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posición"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animación"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoración"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Disparador"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Miscelánea"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Proba"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "Listas de reprodución ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de reprodución ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listas de reprodución do Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Cor</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Alcance do desenfoque"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer estereofónico a Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Predefinicións:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nivel de alimentación:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Cortar frecuencia:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Predefinicións:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer estereofónico a Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizador de espectro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Engadido de CD de son"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -858,171 +843,158 @@ msgstr ""
 "\n"
 "Este foi un proxecto do Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocidade de lectura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Anular o dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadatos</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Empregar o CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Empregar a CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Empregar HTTP no canto de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Ruta:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Porto:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Engadido de CD de son"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Non foi posíbel iniciar o subsistema cdio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI incorrecto %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Non se atopa a pista %d"
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "A pista %d é unha pista de datos"
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Non foi posíbel abrir a saída de son."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Produciuse un erro ao ler o CD de son"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD de son"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Pista %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Non foi posíbel abrir o dispositivo do CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Non foi posíbel atopar unha unidade de CD de son."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Non foi posíbel rematar a inicialización da unidade de CD aberta."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Non foi posibel obter o primeiro/último número de la pista."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Non é posíbel ler o inicio/fin LSN para a pista %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Non foi posíbel crear a conexión coa CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Produciuse un erro ao consultar o servidor CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Produciuse un erro ao consultar o servidor CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Non foi posíbel ler a información de CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "A unidade está baleira."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco non admitido."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Elementos do menú do CD de son"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproducir o CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Engadir un CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Elementos do menú do CD de son"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compresión</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar o volume:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Intervalo dinámico:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Engadido de compresión de rango dinámico para Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Engadido de compresión de intervalo dinámico para Audacious\n"
+"Dereitos de autor 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compresor de intervalo dinámico"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1038,208 +1010,241 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Graves:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Duración predeterminada da canción:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Mostraxe múltipla</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Activar a múltipla mostraxe de son"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Taxa de múltipla mostraxe:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
-msgstr "Ignorar a lonxitude das etiquetas SPC"
+msgstr "Ignorar a duración desde as etiquetas SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumentar a reverberación"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Descodificador de música dunha consola de xogos"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Produciuse un fallo na atenuación cruzada xa que existen cancións cun número "
-"diferente de canles.  Pode empregar o «Mesturador de canles» para converter "
-"as cancións ao mesmo número de canle."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Saída CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Produciuse un fallo na atenuación cruzada xa que existen cancións con "
-"diferente taxa de mostraxe.  Pode empregar o «Convertedor de taxa de "
-"mostraxe» para converter as cancións á mesma taxa de mostraxe."
+"Engadido de saída CoreAudio para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Baseado no engadido de saída SDL para Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Usar o modo exclusivo"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Engadido Crossfade para Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Atenuación cruzada</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "No cambio automático de canción"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Sobreposición:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "No cambio manual, ou nas buscas, de canción"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Consello</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Para un mellor efecto de fundido, active\n"
+"o efecto de supresión do silencio."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Atenuación cruzada"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Produciuse un fallo na atenuación cruzada xa que existen cancións cun número "
+"diferente de canles.  Pode empregar o «Mesturador de canles» para converter "
+"as cancións ao mesmo número de canle."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Produciuse un fallo na atenuación cruzada xa que existen cancións con "
+"diferente taxa de mostraxe.  Pode empregar o «Convertedor de taxa de "
+"mostraxe» para converter as cancións á mesma taxa de mostraxe."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidade:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Engadido de plano de referencia"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Eliminar ficheiros"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Produciuse un erro ao enviar %s ao lixo: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Produciuse un erro ao eliminar %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Produciuse un erro ao eliminar %s: non é un ficheiro local."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Confirma que quere enviar ao lixo os ficheiros seleccionados?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Enviar ao lixo"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 "Confirma que quere eliminar permanentemente os ficheiros seleccionados?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Eliminar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Eliminar ficheiros"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Eliminar os ficheiros seleccionados"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Eliminar o método</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Enviar ao lixo no canto de eliminar inmediatamente"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Engadido Echo\n"
+"Por Johan Levin, 1999\n"
+"\n"
+"Surround echo por Carl van Schaik, 1999\n"
+"Actualizado para Audacious por William Pitcock e John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Atraso:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Realimentación"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volume:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Engadido Echo\n"
-"Por Johan Levin, 1999\n"
-"\n"
-"Surround echo por Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Engadido FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1255,55 +1260,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Engadido FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Engadido FileWrite"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato do ficheiro de saída:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Gardar no directorio orixinal"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Gardar nun directorio personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Cartafol do ficheiro de saída:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Escolla un cartafol"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obter o nome de ficheiro desde:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Xerar o nome de ficheiro desde:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "etiquetas do ficheiro orixinal"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Etiqueta do ficheiro orixinal"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
 msgstr "Nome do ficheiro orixinal"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Non quitar a extensión do ficheiro"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Incluír a extensión do nome do ficheiro orixinañ"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr "Antepor o número de pista ao nome de ficheiro"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1335,165 +1340,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Engadido FileWrite"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Estéreo solapado"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estéreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuración de MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Aceptar"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Calidade do algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "Frecuencia de mostraxe de saída:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "Taxa de bits / Relación de compresión:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Taxa de bits (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Relación de compresión:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modo do son:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Miscelánea:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Varios:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Forzar a compatibilidade estrita con ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Forzar o cumprimento estrito da norma ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Protección contra erros"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Calidade"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Activar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opcións VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Taxa de bits mínima (kbps)"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Taxa de bits máxima (kbps)"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Aplicar estritamente a taxa de bits mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opcións ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Taxa media de bits (kbps)"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nivel de calidade VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Non escribir a cabeceira VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omitir a cabeceira VBR Xing"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Parámetros do cadro:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Marcar con Dereitos de autoría"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Marcar como orixinal"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parámetros ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forzar o engadido da etiqueta da versión 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Engadir só a etiqueta v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Engadir só a etiqueta v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiquetas"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuración do codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nivel de calidade (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Descodificador FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sen perdas"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1505,11 +1514,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Descodificador FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1517,11 +1522,19 @@ msgstr ""
 "Engadido GIO para Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Engadido GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "O modo ler e engadir non está admitido"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Modo incorrecto de apertura"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1541,534 +1554,620 @@ msgstr ""
 "\n"
 "Liceza: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analizador de espectro OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Analizador de espectro OpenGL para Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren e Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Baseado no engadido de XMMS:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, e "
+"4Front Technologies\n"
+"\n"
+"Licencia: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analizador de espectro OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Atallos do GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Engadido de atallos do Gnome\n"
-"Permite controlar o reproductor cos atallos de GNOME.\n"
+"Engadido de atallos do GNOME\n"
+"Permite controlar o reprodutor cos atallos do GNOME.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Atallos do Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número de entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Interprete"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Ano"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Álbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Interprete do álbum"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Pista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Xénero"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posición na cola"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Duración"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Ruta ao ficheiro"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nome de ficheiro"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Taxa de bits"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Columnas dispoñíbeis"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Columnas amosadas"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Ferramenta de buscas"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Ancorar á esquerda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Ancorar á dereita"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Ancorar enriba"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Ancorar abaixo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desancorar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Desactivar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Ferramenta de buscas"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Abrir ficheiros..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir un _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Engadir ficheiros..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Engadir un U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Buscar unha _fonoteca"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "So_bre..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Axustes ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Saír"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Reproducir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Pausa"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Deter"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "A_nterior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Se_guinte"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Repe_tir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Ao c_hou"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_on avanzar na lista de reprodución"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Parar _despois desta canción"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Información da canción"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Saltar no _tempo"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Saltar á _canción"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Estabelecer o punto de repetición _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Estabelecer o punto de repetición _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Limpar os puntos de repetición"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Polo _título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Por_ nome de ficheiro"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Pola nome do _ficheiro"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Por _ruta do ficheiro"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Polo _número de pista"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Polo _interprete"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Por ál_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Polo interprete do álbu_m"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Pola _data de publicación"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Por _xénero"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Por _duración"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Pola _ruta do ficheiro"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Polo título _personalizado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Orden _inversa"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Ao c_hou"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Reproducir esta lista"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "Re_producir/Continuar"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Actualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordenar"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Ordenar a s_elección"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Retirar _duplicados"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Eliminar os ficheiros _non dispoñíbeis"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Novo"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Cambiar o _nome..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Re_tirar"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Xestor da _lista de reprodución:"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Xestor da _cola"
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Subir o volume"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Baixar o volume"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ecualizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_fectos ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Amosar a barra de _menú"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Amosar a barra de i_nformación"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Amosar a barra de vis_ualización"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Amosar a barra de e_stado"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Amosar o tempo _restante"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Visualizacións ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Ficheiro"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reproducir"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de reprodución"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servicios"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Saí_da"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Ver"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Por na cola/retirar da cola"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "Abrir o cartafol _contedor"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "C_ortar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Pegar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleccionar _todo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Cambiar o _nome..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Lapelas da lista de reprodución</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Amosar sempre as lapelas"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Amosar os contadores da entrada"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Amosar os botóns de peche"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Columnas da lista de reprodución</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Amosar as cabeceiras de columna"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Varios</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "As teclas de frecha buscan a través de:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Avanzar ao cambiar de canción"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interface GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Almacenando no búfer..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estéreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canle"
 msgstr[1] "%d canles"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo único."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo da lista de reprodución"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Parar despois da canción."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Pista anterior"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproducir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausar/Reiniciar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Parar"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Pista seguinte"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avanzar 5 segundos"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Retroceder 5 segundos"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenciar"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Subir o volume"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Baixar o volume"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Ir ao ficheiro"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Cambiar a(s) xanela(s) de reprodución"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar as notificacións OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
-msgstr "Conmutar a repetición"
+msgstr "Cambiar a repetición"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
-msgstr "Conmutar a reprodución ao chou"
+msgstr "Cambiar a reprodución ao chou"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
-msgstr "Conmutar a parada despois da actual"
+msgstr "Cambiar a parada despois da actual"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Elevar as xanelas do reprodutor"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ningún)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2079,15 +2178,11 @@ msgstr ""
 "\n"
 "Quere continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Asociar botóns do rato"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configuración global de atallos de teclado do engadido"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2095,23 +2190,27 @@ msgstr ""
 "Prema unha combinación de teclas dentro do campo de texto.\n"
 "Tamén pode asociar botóns do rato."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Teclas rápidas:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Acción</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Teclas asociadas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Engadir"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Teclas rápidas globais"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2138,60 +2237,56 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Teclas rápidas globais"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Saída JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Conectar todos os portos «jack» dispoñíbeis"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Conectar automaticamente os portos de saída"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Conectar só os portos de saída"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Só se atoparon %d portos de saída de JACK, son necesarios %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Non conectar ningún porto"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Produciuse un fallo ao conectar co porto JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Modo de conexión:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK só acepta son en punto flotante. Ten que cambiar o bit de profundidade "
+"da saída a punto flotante nos axustes do Audacious."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Activar a impresión da depuración"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Produciuse un fallo ao conectar co servidor JACK; está en execución?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Baseado en xmms-jack, por Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Portado a Audacious por Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Saída JACK"
+"O servidor JACK precisa dunha taxa de mostraxe de %d Hz, mais o Audacious "
+"está a reproducir cunha taxa de %d Hz. Use o efecto «Convertedor de taxa de "
+"mostraxe» para corrixir esta discordancia."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Configuración de %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Configuración do servidor LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Rutas dos módulos:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2201,25 +2296,25 @@ msgstr ""
 "Estas rutas empréganse ademais de LADSPA_PATH.\n"
 "Tras engadir as novas rutas, prema Intro para buscar novos engadidos.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Engadidos dispoñíbeis:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Activar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Engadidos activados:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Configuración"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2227,47 +2322,15 @@ msgstr ""
 "LADSPA Host para Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "Servidor LADSPA"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: a compatibilidade de LIRC non foi iniciada\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: non foi posíbel ler o ficheiro de configuración LIRC\n"
-"%s: consulte a documentación do LIRC\n"
-"%s: como crear un ficheiro de configuración válido\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: tentando volver a conectar...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: orde descoñecida «%s»\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desconectado de  LIRC\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "Servidor LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: tentará volver a conectar cada %d segundos...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Engadido LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2296,73 +2359,81 @@ msgstr ""
 "\n"
 "Para obter máis información sobre LIRC, consulte http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Conexión</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Volver conectar co servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Agardar antes de volver conectar:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Engadido LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Engadido LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Non hai letras dispoñíbeis"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Erro"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Non é posibel obter %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Erro"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Non é posíbel analizar %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Buscando letras ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Faltan os metadatos da canción"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Conectando con lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Engadido LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Engadido LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listas de reprodución M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Xerador de tacto"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Xerador de tacto: %d ppm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Xerador de tacto: %d ppm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2376,11 +2447,11 @@ msgstr ""
 "p.ex. tact://77 para reproducir a 77 pulsos por minuto\n"
 "ou tact://60*3/4 to para reproducir a 60 ppm en 3/4 tactos"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Xerador de tacto"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mesturador de canles"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2388,152 +2459,184 @@ msgstr ""
 "Engadido Channel Mixer para Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mesturador de canles</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canles de saída:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mesturador de canles"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Engadido MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Produciuse un erro ao conectar co servidor MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (modulo reprodutor)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resolución</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canles</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Máis próximo (o máis rápido)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineal (rápido)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (bo)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifase (o mellor)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Taxa da mostraxe</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Nivel:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "límite de corte:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverberación</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Énfase de graves</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Son envolvente</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Preamplificación</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Sobremostraxe"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Redución de ruído"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Reproducir os MOD de Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repetir</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Contador de repeticións:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Para repetir sempre, estabelecer o contador de repeticións en -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (modulo reprodutor)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Son envolvente"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Estes axustes terán efecto após que Audacious sexa reiniciado."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Engadido MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avanzado</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Utilizar o cálculo de duración exacta (lento)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Son envolvente"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Servidor MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Engadido Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Erro de análise de redireccionamento"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Erro HTTP descoñecido"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Erro de análise de URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Demasiadas redireccións"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Parado"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious non está a reproducir nada."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificacións de escritorio"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2569,55 +2672,64 @@ msgstr ""
 "Debería ter recibido unha copia da Licenza Pública Xeral de GNU xunto\n"
 "con este programa, de non ser así, consulte <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Amosar os controis de reprodución"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Amosar sempre a notificación"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notificacións de escritorio"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Incluír o nome do álbum na notificación"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Amosar"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausa"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Seguinte"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo predeterminado"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Saída OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Saída OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo predeterminado"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo de son:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Empregar un dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Gardar o volume entre sesións."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Activar as conversións de formato realizadas plo software OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Activar o modo exclusivo para impedir a mestura virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2631,19 +2743,35 @@ msgstr ""
 "Gustaríame darlle as grazas á xente de #audacious, sobre todo a Tony Vroon  "
 "e a John Lindgren e por suposto aos autores do anterior engadido de OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Saída OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Xestor da lista de reprodución:"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Entradas"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Retirar"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Re_nomear"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listas de reprodución PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Descodificador OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Saída PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2679,11 +2807,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Saída PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Saída QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Engadido de saída QtMultimedia Audio para Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Baseado no engadido de saída SDL para Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Traballando..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Busca"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Abrir o cartafol ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Engadir un cartafol ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Inspector do _rexistro ..."
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Abrir ficheiros"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Engadir ficheiros"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Ao chou"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interface Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertedor de taxa de mostraxe"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2691,99 +2881,107 @@ msgstr ""
 "Engadido Sample Rate Converter para Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Omitir/repetir as mostraxes"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolación lineal "
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolación de sincronía rápida"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolación de sincronía media"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Mellor interpolación de sincronía"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversión</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Taxa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Taxa de asignacións</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Empregar a taxa de asignacións"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertedor de taxa de mostraxe"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "Aceptar. Scrobbling para o usuario: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Permiso denegado"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Acceda á seguinte ligazón para permitirlle a Audacious enviar o rexistro das "
 "súas escoitas:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Manteña aberta esta xanela e prema outra vez en «Comprobación de permisos».\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2791,34 +2989,38 @@ msgstr ""
 "No se preocupe. Os seus rexistros de escoitas gardanse no seu computador.\n"
 "Só se enviarán se Audacious llelo permite."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problema na rede."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Houbo un problema ao contactar con Last.fm. Ténteo de novo máis tarde."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Comprobando..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "C_omprobación de permisos"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Revogar o permiso"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Ten que autorizar a súa conta en Last.fm para que poida seguir (scrobble) as "
 "súas pistas.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2826,7 +3028,7 @@ msgstr ""
 "Non foi posíbel iniciar o engadido de  Scrobbler.\n"
 "Semella que hai un problema de instalación."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2843,11 +3045,7 @@ msgstr ""
 "Gracias a John Lindgren por botarme unha man no comenzo deste proxecto.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2855,7 +3053,11 @@ msgstr ""
 "Audacious está a empregar unha versión mellorada do Scrobbler de Last.fm .\n"
 "Comprobe as preferencias para o engadido do Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Saída SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2863,81 +3065,56 @@ msgstr ""
 "Engadido SDL Output para Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Saída SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteca"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Interprete descoñecido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Álbum descoñecido"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" en %s por %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultado"
+msgstr[1] "%d resultados"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] "%d álbumes"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d agochado)"
+msgstr[1] "(%d agochados)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d canción"
-msgstr[1] ""
-"%s\n"
-" %s, %d cancións"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d canción por %s"
-msgstr[1] ""
-"%s\n"
-" %d cancións por %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d canción"
+msgstr[1] "%d cancións"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "deste xénero"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "en"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "por"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crear unha lista de reprodución"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Engadir á lista de reprodución"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Buscar unha fonoteca"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2945,679 +3122,771 @@ msgstr ""
 "Para importar a súa fonoteca en Audacious, escolla un cartafol e prema na "
 "icona «Actualizar»."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Agarde..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Escolla un cartafol"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Reprodutor SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Saída</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canles:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulación</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emular MOS 8580 (predeterminado: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Non seleccionar automaticamente o modelo de chip"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Filtro de emulación"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Velocidade do reloxo:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Non seleccionar automaticamente a velocidade do reloxo"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Tempo de reprodución</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Estabelecer o tempo máximo de reprodución:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Usar só cando a duración e descoñecida"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Estabelecer o tempo mínimo de reprodución:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtóns</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Activar subtóns"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorar os subtóns menores que:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nota</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Supresión do silencio"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Engadido de supresión do silencio para Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Supresión do silencio</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Limiar:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Abrir ficheiros ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Abrir un URL ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Buscar unha fonoteca"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reprodución"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de reprodución"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Servizos"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Sobre ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Axustes ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Saír"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Información da canción ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Ao chou"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Non avanzar na lista de reprodución"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Deter despois desta canción"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Estabelecer a repetición A-B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Limpar a repetición A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Saltar á canción ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Saltar no tempo ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Reproducir esta lista"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Reproducir/Continuar"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nova lista de reprodución"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Renomear a lista de reprodución ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Retirar a lista de reprodución"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Lista de reprodución anterior"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Seguinte lista de reprodución"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importar lista de reprodución ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Exportar lista de reprodución ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Xestor da lista de reprodución ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Xestor da cola ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Actualizar a lista"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Amosar o editor de listas de reprodución"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Amosar o ecualizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Amosar o tempo restante"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Sempre enriba"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "En todos os espazos de traballo"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Enrolar o reprodutor"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Enrolar o editor de listas de reprodución"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Enrolar o ecualizador"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dobre tamaño"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Engadir un URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Engadir ficheiros ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Polo título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Polo nome de ficheiro"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Pola ruta do ficheiro"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Retirar todo"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Limpar a cola"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Retirar os ficheiros non dispoñíbeis"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Retirar os duplicados"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Retirar os NON seleccionados"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Retirar os seleccionados"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Buscar e seleccionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverter a selección"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Non seleccionar nada"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Seleccionar todo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Polo álbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Polo número de pista"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Polo interprete"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Polo álbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Polo interprete do álbum"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Pola data de publicación"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Polo número de pista"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Por xénero"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Por duración"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Por título personalizado"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Lista ao chou"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Lista inversa"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordenar os seleccionados"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenar a lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Pegar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Poñer na cola/Quitar da cola"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Cargar o axuste ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Cargar o axuste automático ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Cargar o predeterminado"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Cargar o ficheiro de axustes ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Cargar o  ficheiro EQF ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Gardar os axustes ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Gardar o axuste automático ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Gardar o axuste predeterminado"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Gardar o  ficheiro de axustes ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Gardar o  ficheiro EQF ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Eliminar o axuste ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Eliminar o axuste automático ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importar os axustes do WinAMP ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Poñer a cero"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface clásica do Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Gardar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Cargar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Cargar o ficheiro de axustes"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Cargar o  ficheiro EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Gardar o  ficheiro de axustes"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Gardar o  ficheiro EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importar os axustes do WinAMP"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Axustes"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Cargar o axustes"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Cargar o axuste automático"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Gardar o axustes"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Gardar o axuste automático"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Eliminar o axuste"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Eliminar o axuste automático"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Reprodutor:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Reprodutor:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Seleccione o tipo de letra da xanela principal do reprodutor:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_lista de reprodución:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lista de reprodución:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Seleccione o tipo de letra da lista de reprodución:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Tema</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Tipos de letra</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Empregar tipos de letra de mapa de bits (só admiten ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Desprazar o título da canción"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Desprazar o título da canción en ambas direccións"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Campo"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Impresión vocal / Medidor de unidades de volume"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Apagado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Lume"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Liñas verticais"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Liñas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Máis lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Medio"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Máis rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Puntos"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Liña"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Sólido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Xeo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Tipo</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Tipo de visualización:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizador</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Amosar os picos"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Colorear:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Estilo:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Caída:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Caída dos picos:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Estilo de campo:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Coloreado da impresión vocal"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Estilo do medidor de UV:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Xeral"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualización"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificador"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ecualizador do Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Ir a %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balance: %d%% esquerda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balance: centro"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balance: %d%% dereita"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menú de opcións"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desactivar «Sempre enriba»"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Activar «Sempre enriba»"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caixa de información do ficheiro"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Vistas"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Repetir o punto de axuste A."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Repetir o punto de axuste B."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Repetir os puntos limpados"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo único."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo da lista de reprodución"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Parar despois da canción."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Buscar entradas na lista de reprodución activa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Busca"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3629,57 +3898,61 @@ msgstr ""
 "de minúsculas. Se non sabe como funcionan as expresións regulares, escriba "
 "só a parte del literal que quere buscar."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Título: "
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Álbum: "
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Interprete: "
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nome do ficheiro: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nome de ficheiro:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Limpar a selección previa antes de buscar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
-msgstr "Conmutar automaticamente a cola para as entradas coincidentes"
+msgstr "Cambiar automaticamente a cola para as entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Crear unha nova lista de reprodución coas entradas coincidentes"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de listas de reprodución do Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x arquivado"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Tema para Winamp 2.x sen arquivar"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Non foi posíbel crear o directorio (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Engadido Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3720,84 +3993,72 @@ msgstr ""
 "Inc.,\n"
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Engadido Sndfile"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Saída Sndio"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sobre o engadido de saída Sndio"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Engadido de saída Sndio Output\n"
-"\n"
-"Escrito por Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Dispositivo (baleiro como predeterminado):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato non admitido"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Gardar e restaurar o volume:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Foi solicitado un formato non admitido polo dispositivo de son.\n"
-"\n"
-"Tenteo de novo co servidor sndiod(1) en execución."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Produciuse un erro de Sndio: Formato de son non admitido (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "Dispositivo «sndio»"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Produciuse un erro de Sndio: fallou sio_open()"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(como predeterminado medio baleiro)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Produciuse un erro de Sndio: fallou sio_setpar()"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Aceptar"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Produciuse un erro de Sndio: fallou sio_start()"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Cambio de canción"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Orde que executar cando Audacious reproduce unha canción nova."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Os parámetros enviados á consola deberíanse delimitar con "
+"comiñas. Doutro xeito existe un risco de seguranza.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Orde:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Ordes</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Orde que executar na fin dunha canción."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Orde que executar cando comece unha nova canción:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Orde que executar cando Audacious chega á fin dunha lista de reprodución."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Orde que executar na fin dunha canción:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Orde que executar na fin dunha lista de reprodución:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Orde que executar cando o título cambia para una canción (é dicir, títulos "
-"de fluxos da rede)"
+"Orde que executar cando cambia o título dunha canción (para fluxos da rede):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3811,36 +4072,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Pode empregar os formatos descritos embaixo, que\n"
-"serán substituídos antes da invocación da orde\n"
-"(non todos poden ser empregados para a orde fin\n"
-"da lista de reprodución):\n"
-"\n"
-"%F: frecuencia (en hertzios)\n"
-"%c: número de canles\n"
-"%f: nome do ficheiro (ruta completa)\n"
-"%l: duración (em ms)\n"
-"%n ou %s: nome da canción\n"
-"%r: taxa (en bits por segundo)\n"
-"%t: posición na lista de reprodución (%02d)\n"
-"%p: reproducíndose actualmente (1 ou 0)\n"
-"%a: interprete\n"
-"%b: álbum\n"
-"%T: título da pista"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Os parámetros enviados á consola deberíanse delimitar con "
-"comiñas. Doutro xeito existe un risco de seguranza.</span>"
-
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Ordes"
+"Pode utilizar as seguintes cadeas de formato que serán substituídas antes de "
+"chamar a orde (non todas son útiles para a orde de fin de lista de "
+"reprodución)\n"
+"\n"
+"%F: Frecuencia (en hercios)\n"
+"%c: Número de canles\n"
+"%f: Nome de ficheiro (ruta completa)\n"
+"%l: Duración (en milisegundos)\n"
+"%n ou %s: Nome da canción\n"
+"%r: Taxa (en bits por segundo)\n"
+"%t: Posición da lista de reprodución (%02d)\n"
+"%p: Reproducíndose actualmente (1 ou 0)\n"
+"%a: Artista\n"
+"%b: Álbum\n"
+"%T: Título da pista"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Información da canción (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3854,51 +4110,51 @@ msgstr ""
 "Baseado no engadido Sample Rate Converter:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rápido"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Baixa"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alta"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Moi alta"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Calidade:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidade e ton"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocidade e ton</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidade:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Ton:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidade e ton"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icona de estado"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "A_xustes ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3916,39 +4172,39 @@ msgstr ""
 "Este engadido fornece unha icona de estado, situada na\n"
 "área de información do sistema do xestor de xanelas."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Acción coa roda do rato</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Cambiar o volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Cambiar a cancion que se está a reproducir"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Outras configuracións</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desactivar a xanela emerxente"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Pechar na área de notificación"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avanzar na lista de reprodución ao desprazar cara arriba"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icona de estado"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra estéreo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3958,24 +4214,24 @@ msgstr ""
 "\n"
 "Por Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra estéreo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra estéreo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Xerador de tons"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Xerador de tons: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3990,15 +4246,11 @@ msgstr ""
 "frecuencia3;...\n"
 "p.ex. tone://2000;2005 para reproducir un ton de 2000 Hz e un ton de 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Xerador de tons"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Supresión de voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4036,11 +4288,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Descodificador de Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detalles sobre %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Título: %t\n"
+"Autor: %a\n"
+"Desde: %f\n"
+"Localizador: %T\n"
+"Comentario: %C\n"
+"Tipo de chip: %c\n"
+"Estéreo: %s\n"
+"Bucle: %l\n"
+"Frecuencia do chip: %F\n"
+"Frecuencia do reprodutor: %P\n"
+"Ano: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Descodificador VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4051,19 +4338,19 @@ msgstr ""
 "Baseado no in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Engadido de Audacious por Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Descodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Descodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "con perdas (híbrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "con perdas"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4073,23 +4360,18 @@ msgstr ""
 "\n"
 "Unah parte do código do engadido foi feita por Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Descodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Descodificador 2SF"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "Lista de reprodución XML compartíbel (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configuración XSF</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorar a duración do ficheiro"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "Lista de reprodución XML compartíbel (XSPF)"
diff --git a/po/hu.po b/po/hu.po
index fb40b63d085f..ca0ac213a52b 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -3,15 +3,17 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# Ferenc Szabo <szaboferee at gmail.com>, 2015
+# Gergely Békési <bekesi.gergely at gmail.com>, 2014
 # Péter Polonkai <polesz at nedudu.hu>, 2010
-# Péter Polonkai <polesz at nedudu.hu>, 2011-2012
+# Péter Polonkai <polesz at nedudu.hu>, 2011-2012,2014-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-03-04 13:41+0000\n"
+"Last-Translator: Péter Polonkai <polesz at nedudu.hu>\n"
 "Language-Team: Hungarian (http://www.transifex.com/projects/p/audacious/"
 "language/hu/)\n"
 "Language: hu\n"
@@ -20,51 +22,38 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "sztereó"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "térhatású"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
-
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
-msgid "sequenced"
-msgstr ""
+msgstr "AAC (Nyers) Dekóder"
 
-#: src/adplug/plugin.c:14
+#: src/adplug/adplug-xmms.cc:42
 msgid "AdPlug (AdLib Player)"
 msgstr "AdPlug (AdLib Lejátszó)"
 
-#: src/alarm/alarm.c:778
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "soros"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Riasztás"
+
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Riasztás beállítása ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
+"Bővítmény a lejátszás időzített elindításához\n"
+"\n"
+"Eredetileg Adam Feakin és Daniel Stodden írta."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Riasztás"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -87,7 +76,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -109,7 +98,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -123,360 +112,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Ez egy ébresztési hívás."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
-msgstr ""
+msgstr "A mai emlékeztető.."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Emlékeztető"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Hétfő"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Kedd"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Szerda"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Csütörtök"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Péntek"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Szombat"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Vasárnap"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Riasztási beállítások"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Idő"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Riasztás (alapértelmezett):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Csendes ezután:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "óra"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "perc"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Válassza ki a riasztás napját a következőekből"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Nap"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Alapértelmezett"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Napok"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Elhalványulás"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "másodperc"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Hangerő"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Kezdjük a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Vége"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Jelenlegi"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "További parancs"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "engedélyez"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lejátszólista (opcionális)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Lejátszólista választása"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opciók"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Mit jelentenek ezek a lehetőségek?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Súgó"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Album borító"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Album borító (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA kimenet"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(nincs leírás)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Alapértelmezett PCM eszköz"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Alapértelmezett keverő eszköz"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM eszköz:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Keverő eszköz:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mixer elem:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr ""
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI Lejátszó)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA kimenet"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI Lejátszó)"
-
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Be"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Lejátszás</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
+msgstr "Transzponálás:"
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Mintavételi frekvencia:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - SoundFont fájl választás"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Mégsem"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Megnyitás"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Fájlnév"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Méret (byte)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Név"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Információ </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formátum:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Hossz (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Sáv sorszáma:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "változó"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Kezdeti idő"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Megjegyzések és Dalszövegek </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* nem található megjegyzés ehhez a MIDI fájlhoz *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* nem található dalszöveg ehhez a MIDI fájlhoz *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Bezár"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (érvénytelen UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -487,149 +482,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Téglalap"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Kerekített téglalap"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Konkáv téglalap"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Nincs"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Lejátszás kezdete"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "OSD használata ha a lejátszólista egy eleme elindul."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cím váltás"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Szünet Be"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "OSD használata ha megállítják a lejátszást."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Szünet Ki"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "OSD használata ha elindítják a lejátszást."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Elhelyezés"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relatív X pozíció:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relatív Y pozíció:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Max OSD szélesség:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Több monitoros opciók"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD képernyők használata:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "minden monitoron"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Időtartam (mp)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Képernyő:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Áttűnés be:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Áttűnés ki:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Betűkészletek"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Betűkészlet %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Árnyék"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Renderelési stílus"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Színek"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Szín %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Esemény engedélyezése"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Esemény"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Kompozit kezelő detektálva"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -639,112 +631,112 @@ msgstr ""
 "ha tudja, hogy van egy futó kompozít kezelő, kérjük aktiválja, egyébként az "
 "OSD nem fog megfelelően működni"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Kompozít kezelő nem szükséges a nem valódi átlátszósághoz"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Átlátszóság"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Nem valódi átlátszóság"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Valódi átlászóság (szükséges X Composite Ext.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Kompozit kiterjesztés nem tölthető be"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Kompozit kiterjesztés nem érhető el"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - beállítás"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Pozíció"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animáció"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Szöveg"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekoráció"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Esemény"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Egyéb"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Teszt"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "ASXv3 Lejátszólisták"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 lejátszólisták"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious lejátszólisták (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Szín</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Szolid szkóp"
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
-msgstr "Vágási frekvencia:"
-
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Vágási frekvencia:"
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektrum analizátor"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD bővítmény"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -755,170 +747,168 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
+"Copyright (c) 2007, by Calin Crisan <ccrisan at gmail.com> és az Audacious "
+"csapat.\n"
+"\n"
+"Sok köszönet a libcdio fejlesztőinek <http://www.gnu.org/software/libcdio/>\n"
+"és a libcddb fejlesztőinek <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Külön köszönet Tony Vroon részére aki a mentorunk és vezetőnk.\n"
+"\n"
+"Ez egy Google Summer of Code 2007 projekt.\n"
+"\n"
+"Copyright 2009 John Lindgren"
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Eszköz</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Olvasási sebesség:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Eszköz felülírása:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metaadat</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "CD-Text használata"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB használata"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Hasznájon HTTP helyett CDDBP protokollt"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Szerver:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Elérési út:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD bővítmény"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "A cdio alrendszer inicializálása sikertelen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Érvénytelen URI: %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "%d sáv nem található."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Ez adatsáv: %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Az audio kimenet megnyitása sikertelen."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Hiba az audio CD olvasásakor."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "A CD eszköz %s megnyitása sikertelen."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Sikertelen a cddb kapcsolat létrehozása."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "A meghajtó üres."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nem támogatott lemez típus."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audio CD menüelemek"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD lejátszása"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "CD Hozzáadása"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Audio CD menüelemek"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Tömörítés</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Közép hangerő:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dinamikus tartomány:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
-msgstr ""
+msgstr "Dinamikus tartomány kompresszió"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -928,199 +918,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Basszus:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Magas:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Visszhang:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Alapértelmezett szám hossz:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Engedélyezi az audio újra mintavételezést"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Újra mintavételezési arány:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr ""
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Visszhang növelése"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Játék Konzol Zene Dekóder"
 
-#: src/crossfade/crossfade.c:83
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio kimenet"
+
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Átfedés</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Automatikus számváltáskor"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
+msgstr "Átfedés:"
+
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Tekeréskor vagy kézi számváltáskor"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Tipp</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Átfedés"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intenzitás:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Fájlok törlése"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Hiba a törléskor %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Kukába helyez"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Véglegesen törli a kiválasztott fájlokat?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Törlés"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Mégsem"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Kijelölt fájlok törlése"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Törlési mód</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Visszhang</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Késleltetés:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Visszajelzés:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Hangerő:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Visszhang bővítmény\n"
-"Írta Johan Levin, 1999\n"
-"\n"
-"Surround visszhang írta Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Visszhang"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg bővítméyn"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1130,55 +1141,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg bővítméyn"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Fájlíró bővítmény"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Kimeneti fájl formátum:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Beállítás"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Mentés az eredeti könyvtárba"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Mentés egyéb könyvtárba"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Kimeneti fájl könyvtára:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Válasszon egy mappát"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Legyen a fájlnévből:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "eredeti fájl kiterjesztések"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Eredeti fájl kiterjesztés"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "eredeti fájlnév"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Eredeti fájlnév"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Ne vágja le a fájl kiterjesztést"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Az eredeti fájl kiterjesztés használata"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1196,165 +1207,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Fájlíró bővítmény"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automatikus"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Sztereó"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Monó"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 Beállítás"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Rendben"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmus minősége:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "Kimenet mintavétele:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "Bitráta / Tömörítési arány:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitráta (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Tömörítési arány:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio mód:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Egyéb:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Hiba védelem"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Minőség"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR engedélyezése"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Típus:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR beállítások:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimális bitsebesség (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maximális bitsebesség (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr ""
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR beállítások:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Átlagos bitráta (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR minőségi szint:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Ne írjon Xing VBR fejlécet"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Xing VBR fejléc elhagyása"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Megjelölés jogvédettként"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Megjelölés eredetiként"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3 paraméterek:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Mindig adja hozzá a 2-es verzió címkéit"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Csak v1 címkék hozzáadása"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Csak v2 címkék hozzáadása"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Címkék"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis kódoló beállítások"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Minőségi szint (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC dekódoló"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
-msgstr ""
+msgstr "veszteségmentes"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1366,11 +1381,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC dekódoló"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1378,11 +1389,19 @@ msgstr ""
 "GIO bővítmény az Audacious-hoz\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO bővítmény"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Olvas-és-hozzáad mód nem támogatott"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Érvénytelen megnyitási mód"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1394,530 +1413,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
-msgstr ""
+msgstr "OpenGL spektrum analizátor"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr "Gnome rövidítések"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Bejegyzés száma"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Cím"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Előadó"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Év"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Album előadó"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Sáv"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Műfaj"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Várakozási sor pozíció"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Hossz"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Fájl elérési útja"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Fájlnév"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Egyéni cím"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitráta"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Elérhető oszlopok"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Megjelenített oszlopok"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Kereső eszköz"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Balra rögzít"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Jobbra rögzít"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Felülre rögzít"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Alulra rögzít"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Rögzítés feloldása"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Letiltás"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr ""
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Fájl_ok megnyitása ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "_URL megnyitása ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Fájlok hozzá_adása ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL hozzáadása ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "_Keresés a gyűjteményben"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Névjegy ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Beállítások ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Kilépés"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Lejátszás"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Szünet"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Megállítás"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Elő_ző"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Következő"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Ismétlés"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Véletlenszerű"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "_Ne legyen léptetés a lejátszólistában"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
-msgstr ""
+msgstr "L_eállítás az aktuális dal után"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Dal _információ ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Ugrás _időre ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Ugrás _dalra ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
-msgstr ""
+msgstr "_Ismétlési pontok törlése"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Cím szerin_t"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr ""
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "_Fájlnév szerint"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
-msgstr ""
+msgstr "Fájl _elérési útja szerint"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Sáv szeri_nt"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Elő_adó szerint"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
-msgstr ""
+msgstr "Al_bum szerint"
+
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Albu_m előadó szerint"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "_Dátum szerint"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "_Műfaj szerint"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
-msgstr ""
+msgstr "_Hossz szerint"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "_Fájl útvonal szerint"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "_Egyedi cím szerint"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Fo_rdított sorrend"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Véletlensze_rű sorrend"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr ""
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Lejátszás/Szünet"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Frissítés"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "Rendezé_s"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr ""
+msgstr "Kije_löltek rendezése"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
-msgstr ""
+msgstr "Kettőzöttek eltávolítása"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "_Nem elérhető fájlok törlése"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Új"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Át_nevezés ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "Tö_rlés"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importálás ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportálás ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "_Lejátszólista kezelő ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Várakozási sor kezelő ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Hangerő _fel"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Hangerő _le"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Hangszínszabályzó"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "E_ffektusok ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Menü sor mutatása"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "I_nfo sor mutatása"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Inf_ormációs sáv mutatása"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_Státusz sor mutatása"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
-msgstr ""
+msgstr "Hát_ralévő idő mutatása"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Megjelenítés ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fájl"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "L_ejátszás"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lejátszólista"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Szervizek"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Kimenet"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Nézet"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
-msgstr ""
+msgstr "_Várólistára/Várólistáról ki"
+
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Tartalmazó mappa megnyitása"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Kivágás"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Másolás"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Beillesztés"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Mind kivál_aszt"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Átneve_zés ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Lejátszólista fülek</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Mindig mutassa a füleket"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Elemek számának mutatása"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Bezárás gomb mutatása"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Lejátszólista oszlopok</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Oszlop fejlécek mutatása"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
-msgstr ""
+msgstr "<b>Egyéb</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Nyíl billentyűk a tekeréshez:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Számváltáskor gördül"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK+ felület"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Pufferelés ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "sztereó"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d csatorna"
 msgstr[1] "%d csatorna"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Egyszerű mód."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Lejátszólista mód."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Leállítás az aktuális dal után."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
-msgstr ""
+msgstr "Előző szám"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Lejátszás"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Szünet/Folytatás"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Leállít"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
-msgstr ""
+msgstr "Következő szám"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
-msgstr ""
+msgstr "5 mp előre"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
-msgstr ""
+msgstr "5 mp vissza"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Némítás"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
-msgstr ""
+msgstr "Hangerő növelése"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
-msgstr ""
+msgstr "Hangerő csökkentése"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
-msgstr ""
+msgstr "Ugrás fájlhoz"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
-msgstr ""
+msgstr "Lejátszó ablak(ok) váltása"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "On-Screen-Display mutatása"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
-msgstr ""
+msgstr "Ismétlés bekapcsolása"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
-msgstr ""
+msgstr "Véletlenszerű lejátszás be"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
-msgstr ""
+msgstr "Játszott szám után állj"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
-msgstr ""
+msgstr "Lejátszó ablak(ok) kiemelése"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(nincs)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1925,37 +2021,39 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Egér gombok hozzárendelése"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr ""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
+"Adjon meg egy billentyűkombinációt a beviteli mezőben.\n"
+"Ez fog az egér gombjaihoz kötődni."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Gyorsbillentyűk:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Művelet:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Billentyű kötések:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Hozzáadás"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Általános gyorsbillentyűk"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1970,124 +2068,97 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Általános gyorsbillentyűk"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK kimenet"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automatikus csatlakozás a kimeneti portokhoz"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Sikertelen kapcsolódás a JACK porthoz: %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
+"A JACK csak a lebegőpontos audiót támogatja. Kérem állítsa át a kimeneti bit "
+"mélységet lebegőpontosra az Audacious beállításaiban."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Sikertelen kapcsolódás a JACK szerverhez; valóban fut?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
+"A JACK szerverhez szükséges mintavételi frekvencia %d Hz, de az Audacious "
+"csa %d Hz-en játszik le. Kérem használja a Mintavételi Frekvencia Konverter "
+"modult a hibák elkerülése érdekében."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK kimenet"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Beállítások"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr ""
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modul útvonalak:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Elérhető bővítmények:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Engedélyez"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Engedélyezett modulok:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Beállítások"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
+"LADSPA Host az Audacious részére\n"
+"Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA gép"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: nem sikerült a LIRC támogatás inicializálni\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: újracsatlakozás...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: ismeretlen parancs \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC bővítmény"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2102,74 +2173,94 @@ msgid ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
+"Egyszerű modul az Audacious LIRC távirányítón keresztüli vezérléséhez\n"
+"\n"
+"Az Audacious részére adoptálták:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Az eredeti XMMS LIRC modul írói:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"További információkért nézze meg a LIRC honlapját, http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Kapcsolat</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Újracsatlakozás a LIRC szerverhez"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Várjon az újracsatlakozás előtt:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC bővítmény"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki bővítmény"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Nincs elérhető zeneszöveg"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Hiba"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Nem sikerült letölteni: %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Hiba"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Nem sikerült értelmezni: %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Zeneszöveg keresése ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Érvénytelen a dal metaadata"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Kapcsolódás a lyrics.wikia.com helyhez ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki bővítmény"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U lejátszólisták"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Tact generátor"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Tact generátor: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Tact generátor: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2178,162 +2269,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr ""
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Csatorna keverő"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Csatorna keverő</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Kimeneti csatornák:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Csatorna keverő"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS bővítmény"
 
-#: src/modplug/plugin_main.c:55
-msgid "<b>Resolution</b>"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Modul lejátszó)"
+
+#: src/modplug/plugin_main.cc:53
+msgid "<b>Resolution</b>"
+msgstr "<b>Felbontás</b>"
+
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
-msgstr ""
+msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
-msgstr ""
+msgstr "16 bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
-msgstr ""
+msgstr "<b>Csatornák</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr ""
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Mintavételi ráta</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
-msgstr ""
+msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
-msgstr ""
+msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
-msgstr ""
+msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
-msgstr ""
+msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
-msgstr ""
+msgstr "Szint:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
-msgstr ""
+msgstr "<b>Basszus erősítés</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
-msgstr ""
+msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
-msgstr ""
+msgstr "Túlvételezés"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
-msgstr ""
+msgstr "Zajcsökkentés"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
-msgstr ""
+msgstr "AMIGA MOD fájlok lejátszása"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
-msgstr ""
+msgstr "<b>Ismétlés</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
-msgstr ""
+msgstr "Ismétlés száma:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
-msgstr ""
+msgstr "Ismétlés örökké, állítsd be az ismétlés számát -1-re"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Modul lejátszó)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Térhatású"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "A beállítások csak az Audacious újraindítása után érvényesülnek."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 bővítmény"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Haladó</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Térhatású"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 szerver"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS bővítmény"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Ismeretlen HTTP hiba"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Hiba az URL elemzésekor"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Túl sok átirányítás"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Leállítva"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Az Audacious nem játszik."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Asztali értesítések"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2353,55 +2476,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
-msgstr ""
+msgstr "Lejátszó vezérlők mutatása"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
-msgstr ""
+msgstr "Mindig mutasson értesítést"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Asztali értesítések"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Az album nevének megjelenítése az értesítésben"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
-msgstr ""
+msgstr "Mutat"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Szünet"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Következő"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Alapértelmezett eszköz"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 kimenet"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 kimenet"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Alapértelmezett eszköz"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audio eszköz:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Alternatív eszköz használata:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
-msgstr ""
+msgstr "Hangerő mentése munkamentek között"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Formátum konverzió engedélyezése az OSS szoftverben."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2410,19 +2542,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr ""
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Lejátszólista kezelő"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Elemek"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Eltávolítás"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Át_nevezés"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS lejásztólisták"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio kimenet"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2442,143 +2590,214 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio kimenet"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia Kimenet"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Dolgozom ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Keresés"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Mappa megnyitása ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "M_appa hozzáadása ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Napló ellenőr ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Fájlok megnyitása"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Fájlok hozzáadása"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Előző"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Ismétlés"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Véletlenszerű"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt felület"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Mintavételi konverter"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
+"Mintavételi Ráta Konverter modul az Audacioushoz\n"
+" Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineáris interpoláció"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Átalakítás</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Módszer: "
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
-msgstr ""
+msgstr "Ráta:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
-msgstr ""
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
+msgstr "192 kHz:"
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
-msgstr ""
+msgstr "Hozzáférés megtagadva"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
-msgstr ""
+msgstr "Hálózati probléma."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
-msgstr ""
+msgstr "Ellenőrzés..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
-msgstr ""
+msgstr "_Jogosultságok ellenőrzése"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2589,769 +2808,842 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL kimenet"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Gyűjtemény"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Ismeretlen Előadó"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Ismeretlen Album"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d találat"
+msgstr[1] "%d találat"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d album"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d rejtett)"
+msgstr[1] "(%d rejtett)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-"%s, %d dal"
-msgstr[1] ""
-"%s\n"
-"%s, %d dal"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-msgstr[1] ""
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d zeneszám"
+msgstr[1] "%d zeneszám"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "műfaj szerint"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "be"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "írta"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Lejátszólista létrehozása"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "Lejátszólistához hozzá_ad"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Keresés a gyűjteményben"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
+"Az Audacious zenekönyvtárába importáláshoz válaszd ki a mappát majd kattints "
+"a \"Frissítés\" ikonra."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Kérem várjon ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Mappa választás"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID lejátszó"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Kimenet</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Csatornák:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emuláció</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "MOS 8580 emulálása (alapértelmezett: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
 msgstr ""
 
-#: src/skins/menus.c:57
-msgid "Open URL ..."
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emuláció szűrő"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Óra sebesség:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Ne legyen automatikus óra sebesség állítás"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Lejátszási idő</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Maximális lejátszási idő beállítása:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Csak akkor ha a zeneszám hossza ismeretlen"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Minimális lejátszási idő beállítása:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Megjegyzés</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Csend eltávolítása"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Csend eltávolítása</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Fájlok megnyitása ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "URL megnyitása ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Keresés a gyűjteményben"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Lejátszás"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lejátszólista"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Nézet"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Szolgáltatások"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Névjegy ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Beállítások ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Kilépés"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
+msgstr "Dal információ ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Ismétlés"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Véletlenszerű"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Ne legyen léptetés a lejátszólistában"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
+msgstr "Leállítás az aktuális dal után"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Előző"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Ugrás a dalra ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Ugrás időpontra ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Új lejátszólista"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Lejátszólista átnevezése ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Lejátszólista törlése"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Előző lejátszólista"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Következő lejátszólista"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Lejátszólista importálása"
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Lejátszólista exportálása"
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Lejátszólista kezelő ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Várakozási sor kezelő ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Lejátszólista frissítése"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Lejátszólista szerkesztő mutatása"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Hangszínszabályzó mutatása"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Hátralévő idő mutatása"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Mindig felül"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "Minden munkaterületen"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
-msgstr ""
+msgstr "Lejátszó felgördítése"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
-msgstr ""
+msgstr "Lejátszólista szerkesztő felgördítése"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
-msgstr ""
+msgstr "Hangszínszabályzó felgördítése"
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dupla méret"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "URL hozzáadása ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Fájlok hozzáadása ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Cím szerint"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Fájlnév szerint"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "Fájl útvonal szerint"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Összes törlése"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Várólista törlése"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Elérhetetlen fájlok törlése"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Kettőzöttek eltávolítása"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Nem kiválasztottak törlése"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Kijelölt törlése"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Keresés és választ"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Kijelölés megfordítása"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Nincs kijelölés"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Mindet kijelöl"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Album szerint"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "A dal sorszáma szerint"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Előadó szerint"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Album szerint"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Album előadó szerint"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
-msgstr ""
+msgstr "Kiadás dátuma szerint"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "A dal sorszáma szerint"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Műfaj szerint"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Hossz szerint"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Egyéb cím szerint"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Véletlenszerű lista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Fordított lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Kijelöltek rendezése"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Lista rendezése"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Kivágás"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Másolás"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Beillesztés"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "Várólistára/Várólistáról ki"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Előre beállított betöltése"
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Alapértelmezett betöltése"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "EQF fájl betöltése ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Előre beállított mentése ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Alapértelmezettként ment"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "Minden érték nulla"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Mentés"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Betöltés"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Profilok"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Előre beállított betöltése"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr ""
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr ""
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Lejátszó:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Lejátszó:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Főablak betűtípus kiválasztás:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Lejátszólista:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lejátszólista:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Válassza ki a lejátszólista betűkészletét:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Felület</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Betűtípusok</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Bitmap fontok használata (csak ASCII támogatása)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "A dal címe mindkét irányba mozog"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizátor"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Szkóp"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Kikapcsolva"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Szokásos"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Tűz"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Vonalak"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Csíkok"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Lasabb"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lassú"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Közepes"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Gyors"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Leggyorsabb"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "Pontok"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Vonal"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Szolid"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Jég"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Sima"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Típus</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Megjelenítés típusa:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Analizátor</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Csúcsok mutatása"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Színezés:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Stílus:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
-msgstr ""
+msgstr "Szkóp stílusa:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Általános"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Megjelenítés"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious Equalizer"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Tekerés %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Hangerő: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balansz: %d%% bal"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balansz: közép"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balansz: %d%% jobb"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Beállítások menü"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Tiltja a 'Mindig felül' opciót"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Engedélyezi a 'Mindig felül' opciót"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Fájl Információs doboz"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Megjelenítés"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Egyszerű mód."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Lejátszólista mód."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Leállítás az aktuális dal után."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Elemek keresése az aktív lejátszólistában"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3359,57 +3651,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Cím:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Előadó:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr "Fájlnév:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Az előző kiválasztások törlése keresés előtt"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Automatikusan várólistára kerülnek a talált elemek"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Hozzon létre új lejátszólistát az egyező elemekből"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious lejátszólista szerkesztő"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d / %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Régi Winamp 2.x bőr"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Nem régi Winamp 2.x bőr"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Nem lehet létrehozni a könyvtárat (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile bővítmény"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3431,75 +3727,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr ""
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio kimenet"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Menti és helyreállítja a hangerőt:"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nem támogatott formátum"
-
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio hiba: Ismeretlen audió formátum (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio eszköz"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio hiba: sio_open() sikertelen"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr ""
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio hiba: sio_setpart() sikertelen"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio hiba: sio_start() sikertelen"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Szám váltás"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Parancs futtatása ha az Audacious elindít egy új számot."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Parancs:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Parancsok</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Parancs futtatása a dal végén."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Parancs ami lefut az új zeneszám indításakor:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Parancs futtatása amikor Audacious elér a lejátszási lista végéhez."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Parancs ami lefut amikor vége a zeneszámnak:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "Parancs futtatása ha a dal cím változik (pl. hálózati stream-címek)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Parancs ami lefut ha a lejátszólistának vége:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Parancs ami lefut a szám címének változásakor (hálózati folyamhoz):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3514,17 +3804,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Parancsok"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3533,51 +3821,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
-msgstr ""
+msgstr "Gyors"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
-msgstr ""
+msgstr "Alacsony"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
-msgstr ""
+msgstr "Magas"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
-msgstr ""
+msgstr "Nagyon magas"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
-msgstr ""
+msgstr "Minőség:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
-msgstr ""
+msgstr "Sebesség:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
-msgstr ""
+msgstr "Hangmagasság:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Státusz ikon"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "Beállí_tások ...."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3588,63 +3876,66 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Hangerő váltás"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Váltja a lejátszott dalt"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Egyéb beállítások</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Felugró ablakok tiltása"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
-msgstr ""
+msgstr "Bezáráskor az értesítési területen marad (a tálcán)"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr ""
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra sztereó"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
+"Extra Sztereó bővítmény\n"
+"\n"
+"Írta: Johan Levin 1999."
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Sztereó</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
 msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Hang generátor:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3653,15 +3944,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3682,44 +3969,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/id_ID.po b/po/id_ID.po
index bb3646bfb161..056470b09ae8 100644
--- a/po/id_ID.po
+++ b/po/id_ID.po
@@ -5,27 +5,28 @@
 # Translators:
 # Rahman Yusri Aftian <aftian at yahoo.com>, 2012
 # Andika Triwidada <andika at gmail.com>, 2012
-# Ardjuna <Asyura.x at gmail.com>, 2013
+# Ardjuna <Asyura.x at gmail.com>, 2013,2015
 # Ardjuna <Asyura.x at gmail.com>, 2012
-# mijortsa <astrojim.blankon at gmail.com>, 2012
+# abd azis ws <astrojim.blankon at gmail.com>, 2012
 #  <bu0ncu3 at yahoo.com>, 2012
-# mascatur <satyafree at gmail.com>, 2013
+# Catur Susetyo <satyafree at gmail.com>, 2013
 #  <kokabiel9 at gmail.com>, 2012
+# Liffindra Angga Zaaldian <findrakecil at gmail.com>, 2015
 # martadinata666 <martadinata666 at gmail.com>, 2012
-# Mohamad Hasan Al Banna, 2012-2013
+# Hasan Al Banna, 2012-2013
 #  <pri_yess at yahoo.com>, 2012
-# Rahman Yusri Aftian <aftian at yahoo.com>, 2012-2013
-# operamaniac <rizkiaulia.r at gmail.com>, 2013
+# Rahman Yusri Aftian <aftian at yahoo.com>, 2012-2014
+# Rizki Aulia Rachman <rizkiaulia.r at gmail.com>, 2013
 # xunilresu <xunilresu at gmail.com>, 2012
 #  <yudi.al at gmail.com>, 2012
 #  <yustrizal24 at gmail.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-03-05 11:08+0000\n"
+"Last-Translator: Ardjuna <Asyura.x at gmail.com>\n"
 "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/"
 "audacious/language/id_ID/)\n"
 "Language: id_ID\n"
@@ -34,51 +35,38 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "Dekoder AAC (orisinal)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
-msgid "sequenced"
-msgstr ""
-
-#: src/adplug/plugin.c:14
+#: src/adplug/adplug-xmms.cc:42
 msgid "AdPlug (AdLib Player)"
 msgstr "AdPlug (Pemutar AdLib)"
 
-#: src/alarm/alarm.c:778
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "telah diurutkan"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
+
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Setel Alarm..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
+"Sebuah plugin yang dapat digunakan untuk mulai bermain pada waktu tertentu\n"
+"\n"
+"Awalnya ditulis oleh Adam Feakin dan Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -100,8 +88,28 @@ msgid ""
 "\n"
 "\n"
 msgstr ""
+"Waktu\n"
+"  Alarm pada:\n"
+"    Waktu saat alarm aktif.\n"
+"\n"
+"  Diam saat:\n"
+"    Hentikan alarm saat waktu ini tiba.\n"
+"       (jika dialog pengingat tidak ditutup)\n"
+"\n"
+"\n"
+"Hari\n"
+"  Hari aktif:\n"
+"    Pilih hari saat alarm akan aktif.\n"
+"\n"
+"  Waktu:\n"
+"    Pilih waktu aktif alarm pada hari H,\n"
+"    atau tekan tombol untuk menggunakan\n"
+"    waktu standar.\n"
+"\n"
+"\n"
+"\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -123,7 +131,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -137,360 +145,372 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Ini adalah panggilan bangun Anda."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
-msgstr ""
+msgstr "Pengingat Anda untuk hari ini adalah..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Pengingat"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Senin"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Selasa"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Rabu"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Kamis"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Jumat"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sabtu"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Minggu"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Pengaturan Alarm "
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Waktu"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Bunyikan alarm pada (bawaan):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "j"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Diam setelah:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "jam"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "menit"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Pilih hari aktivasi alarm"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Hari"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Bawaan"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Hari"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Memudar"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "detik"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Dimulai dari"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Paripurna"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Sekarang"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Perintah Tambahan"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "gunakan"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Daftar lagu (pilihan)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Pilih daftar lagu"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Pilihan"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Apa yang dimaksud dengan opsi ini?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Bantuan"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Sampul Album"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Gambar Album (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Keluaran ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Pengaya Keluaran ALSA untuk Audacious\n"
+"Hak cipta 2009-2012 John Lindgren\n"
+"\n"
+"Terima kasih dari saya kepada William Pitcock, pencipta dari Pengaya "
+"Keluaran ALSA NG, yang kodenya telah disajikan sebagai sebuah rujukan ketika "
+"panduan ALSA tidak cukup memadai."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(tidak ada deskripsi)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Perangkat PCM standar"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Perangkat mixer standar"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Perangkat PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Perangkat mixer:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemen mixer:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Antisipasi pemutusan saluran"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Pemutar MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Keluaran ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (Pemutar MIDI)"
-
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Timpa peningkatan bawaan:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Timpa polyphony bawaan:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Timpa gema bawaan:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Nyala"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Timpa paduan suara bawaan:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Putar lagu</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
-msgstr ""
+msgstr "Tukar tempat"
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "nada setengah"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
-msgstr ""
+msgstr "Perpindahan drum: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "angka not"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Lompati hening di awal"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Lompati hening yang mengikuti"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Synthesizer</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Kadar contoh:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - pilih berkas SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Batal"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "Bu_ka"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Namaberkas"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Nama berkas"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Ukuran (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nama:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Info </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Panjang(milidetik)"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
-msgstr ""
+msgstr "Jumlah trek:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variable"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Waktu Div:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Info dan Lirik MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* tidak ada komentar yang tersedia di berkas MIDI ini *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* tidak ada lirik yang tersedia di berkas MIDI ini *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Keluar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 tidak cocok)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Tentang AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -501,152 +521,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
-msgstr ""
+msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Persegi panjang"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Persegi Bersudut Bundar"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Persegi Bersudut Cekung"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Tidak ada"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Mulai putar kembali"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Tampilkan OSD saat awalan lagu dimainkan."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Ubah judul"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Tampilkan OSD selama lagu diputar. Judul lagu akan diubah namun tidak dengan "
-"nama berkasnya. Umumnya berguna untuk menampilkan perubahan judul saat "
-"streaming melalui internet."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Jedah hidup"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Tampilkan OSD saat lagu dihentikan."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Jedah mati"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Tampilkan OSD saat lagu diputar kembali."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Penempatan"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Mengimbangi X relatif:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Mengimbangi Y relatif:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Lebar tampilan destop"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opsi Multi Monitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Menggunakan tampilan destop"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "Semua monitor"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "waktu (milidetik)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Tampilan:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Menghilang secara cepat:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Menghilang secara perlahan:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Huruf"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Huruf %i"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Bayangan"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Gaya Penggambaran"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Warna"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Warna %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Aktifkan pemicu"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Peristiwa"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Manajer komposisi terdeteksi"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -656,112 +670,112 @@ msgstr ""
 "kecuali kalau kamu tahu bahwa kamu punya satu yang berjalan, harap "
 "diaktifkan sebaliknya OSD tidak akan bekerja dengan baik"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Manajer komposisi tidak dibutuhkan untuk transparansi semu"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparansi"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparansi palsu"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparansi penuh (dibutuhkan Kompositor X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Ekstensi komposisi tidak digunakan"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Ekstensi komposisi tidak tersedia"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>OSD Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "OSD Audacious - Konfigurasi"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posisi"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animasi"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "teks"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekorasi"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Pemicu"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Misc"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Uji coba"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "Daftar putar ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
-msgstr ""
+msgstr "Daftar Putar ASXv1/ASXv2 "
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Daftar Putar Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
-msgstr ""
+msgstr "<b>Warna</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
-msgstr ""
-
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr ""
+msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
-msgstr ""
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
-msgstr ""
+msgstr "Aturan baku:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr ""
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr "Tingkat suapan:"
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Frekuensi potong:"
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
-msgstr ""
+msgstr "Penelaah spektrum"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Pengaya Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -772,170 +786,167 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
+"Hak cipta (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> dan kawan-kawan.\n"
+"\n"
+"Banyak terima kasih kepada para pengembang libcdio <http://www.gnu.org/"
+"software/libcdio/>\n"
+"dan kepada para pengembang libcddb <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Juga terima kasih kepada Tony Vroon karena telah mengajari dan membimbing "
+"saya.\n"
+"\n"
+"Ini adalah sebuah proyek Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
-msgstr ""
+msgstr "<b>Perangkat</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
-msgstr ""
+msgstr "Kecepatan membaca:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
-msgstr ""
+msgstr "Timpa perangkat:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadata</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Gunakan CD-Teks"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
-msgstr ""
+msgstr "Gunakan CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Gunakan HTTP daripada CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
-msgstr ""
+msgstr "Jalur:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Pengaya Audio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
-msgstr ""
+msgstr "Gagal memulai subsistem cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
-msgstr ""
+msgstr "URI Tidak Valid %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
-msgstr ""
+msgstr "Tidak menemukan trek %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
+msgstr "Trek %d adalah sebuah trek data."
 
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
-msgstr ""
+msgstr "Galat saat membaca audio CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
-msgstr ""
+msgstr "Gagal membuka perangkat CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Penggerak kosong."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipe diska tidak didukung."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Putar CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Tambah CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Volume tengah:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Jangkauan dinamis:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -945,195 +956,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bass:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Trebel:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Panjang standar lagu:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Aktifkan fitur sampel ulang"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Tingkat sampel ulang:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Abaikan panjang dari tag SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Tingkatkan reverb"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Dekoder Musik Konsol Game"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Hapus Berkas"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Pindah ke Tong Sampah"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Hapus"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Batal"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Hapus Berkas Dipilih"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Echo</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
-msgstr ""
+msgstr "Penundaan"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
-msgstr ""
-
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
+msgstr "Volume"
 
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Echo"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Pengaya FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1143,55 +1179,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Pengaya FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Format berkas keluaran:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfigurasi"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Simpan didalam original direktori"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Simpan dalam direktori tertentu"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Direktori berkas keluaran:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Ambil folder"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Dapatkan nama dari:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "berkas original tag"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nama berkas original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Jangan hilangkan ektensi file"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Tambahkan nomor jalur di nama berkas"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1209,165 +1245,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Otomatis"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Gabung stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Konfigurasi MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Kualitas Algoritma"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Keluaran Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitrate / Rasio kompresi:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Rasio kompresi:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Mode Otomatis:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Memaksakan dengan ketat pemenuhan ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Pengaman kesalahan"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kualitas"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Aktifkan VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipe:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opsi VBR"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimum bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksimal bitrate (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Memaksakan dengan ketat bitrate terendah"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opsi ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "bitrate rata-rata (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Tingkat kualitas VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Jangan menulis header Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Tandai sebagai hak cipta"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Tandai sebagai orisinil"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Parameter ID3"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Memaksa tambahan tag versi 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Hanya tambahkan tag v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Hanya tambahkan tag v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tags"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Pengaturan Enkoder Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Tingkat kualitas (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Dekoder FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1375,21 +1415,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Dekoder FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Pengaya GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1401,529 +1445,606 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Masukkan angka"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Judul"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artis"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Tahun"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Track"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Aliran"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posisi antri"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Panjang"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Tempat Berkas"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nama berkas"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Title pilihan"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitrate"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Kolom tersedia"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Tampilan kolom"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Alat Pencari"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Dok dikiri"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Dok dikanan"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Dok diatas"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Dok dibawah"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Tidak didok"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Nonaktifkan"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Alat Pencari"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Buka Berkas..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Buka _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Tambah Berkas ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Tambah U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Cari _Pustaka"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "Te_ntang..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Pengaturan...."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Keluar"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Putar"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Paus_e"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Stop"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Se_belumnya"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Sela_njutnya"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Ulangi"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Acak"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_o Kemajuan Playlist"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Informasi_Lagu..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Loncat ke _Waktu..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Loncat ke Lagu..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Oleh_Judul"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Oleh No_Track"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Oleh_Artis"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Oleh _Tanggal Release"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Berdasarkan tempat"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "By _Judul Terkustomisasi"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "B_alik Urutan"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Acak Urutan"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "Sega_rkan"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "Uru_tkan"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Baru"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "Hap_us"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Import..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Export..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Manajer Antrian ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Volume _Naik"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Volume _Turun"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizer"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Perlihatkan Bar _Menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Perlihatkan _Bar Info"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Perlihatkan Bar _Status"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Visualisasi"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Berkas"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Pemutaran"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "Daftar P_utar"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Layanan"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Keluaran"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Lihat"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Antre/Tidak Antre"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Potong"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Salin"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Tempel"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Pilih _Semua"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Ubah nama ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Tampilan GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d kanal"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "mode Single."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "mode Playlist."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Berhenti setelah lagu"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Putar"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Jeda/Mulai Lagi"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Berhenti"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Diam"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
-msgstr ""
+msgstr "Loncat ke berkas"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Tunjukkan On-Screen-Display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(kosong)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1934,15 +2055,11 @@ msgstr ""
 "\n"
 "Apakah anda ingin meneruskan?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Mengikat tombol mouse"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Konfigurasi Plugin Global Hotkey"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1950,23 +2067,27 @@ msgstr ""
 "Tekan kombinasi tombol didalam bidang teks.\n"
 "Kamu juga dapat mengikat tombol mouse."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Hotkeys:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Aksi:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Kunci Pengikat:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
+msgstr "T_ambah"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1981,56 +2102,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Keluaran Jack"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Keluaran Jack"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Pengaturan"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Pengaturan Host LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modul path:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2041,68 +2157,39 @@ msgstr ""
 "Setelah menambahkan path baru, tekan Enter untuk mengamati plugin baru.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Pengaya tersedia:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Gunakan"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Pengaya digunakan:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Pengaturan"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: mencoba menyambung...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: perintah tidak diketahui \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: terputus dari LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: mencoba menyambung tiap %d detik...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Pengaya LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2118,73 +2205,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Sambungan</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Menyambung kembali ke server LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Tunggu sebelum menyambung kembali:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Pengaya LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Tidak ada lirik tersedia"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Kesalahan"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Kesalahan"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Mencari lirik ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Menyambungkan ke lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
+msgstr "Daftar Putar M3U"
+
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Penghasil Tact: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Penghasil Tact: %d bpm %d%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2193,162 +2288,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Keluaran kanal:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr ""
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Pengaya MMS"
 
-#: src/modplug/plugin_main.c:55
-msgid "<b>Resolution</b>"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
-msgid "8-bit"
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:53
+msgid "<b>Resolution</b>"
+msgstr "<b>Resolusi</b>"
+
+#: src/modplug/plugin_main.cc:54
+msgid "8-bit"
+msgstr "8-bit"
+
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
-msgstr ""
+msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
-msgstr ""
+msgstr "<b>Cennel</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Pengaya MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Server MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Pengaya Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Berhenti"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious berhenti"
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Pemberitahuan Destop"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2368,55 +2495,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Pemberitahuan Destop"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Istirahat"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Selanjutnya"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1.  Alat bawaan"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Keluaran OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Perangkat suara:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Gunakan alat alternatif"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Izinkan pembuatan konversi format oleh perangkat lunak OSS"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2425,19 +2561,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Keluaran OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2457,143 +2609,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Cari"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Sebelumnya"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Ulang"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Acak"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr ""
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metode"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr ""
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2604,820 +2825,903 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
-msgstr ""
-
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artis Tidak Diketahui"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Album Tidak Diketahui"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
+msgstr "Pustaka"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Buat Daftar Putar"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Tambah ke Daftar Putar"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
-msgstr ""
+msgstr "Cari pustaka"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Mohon tunggu ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Pilih Folder"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Buka Berkas ..."
+
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
+msgstr "Buka URL...."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Putar Lagu"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Daftar Putar"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Lihat"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Servis"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Tentang"
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Pengaturan"
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Keluar"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Ulang"
+msgstr "Info Lagu"
 
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Acak"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Tidak ada kemajuan Playlist"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
+msgstr "Stop Setelah Lagu Ini"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Sebelumnya"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Lompat ke Lagu ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Lompat ke Waktu ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Daftar Lagu Baru"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Ganti Nama Daftar Putar ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Hapus Daftar Putar"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Daftar Putar Sebelumnya"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Daftar Putar Selanjutnya"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Impor Daftar Putar ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Ekspor Daftar Putar ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Manager Daftar Putar ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Segarkan Daftar Putar"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Munculkan Perubah Daftar Lagu"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Munculkan Equalizer"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Selalu di Atas"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
-msgid "Add URL ..."
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "Tambah URL"
+
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Tambah Berkas ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Dari Judul"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Dari Nama berkas"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "Oleh Path Berkas"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Hapus Semua"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Bersihkan Antrian"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Hapus File yang Tidak Tersedia"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Hapus Duplikat"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Hapus yang tidak Terpilih"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Hapus Yang Dipilih"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Cari dan Pilih"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Balik Pilihan"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Jangan Pilih Apapun"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Pilih Semua"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Dari Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Oleh Nomor Trek"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Dari Artis"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Dari Album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
+msgstr "Oleh Tanggal Rilis"
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Oleh Nomor Trek"
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Acak Daftar"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Balikkan Daftar"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Urutkan yang Terpilih"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Urutkan Daftar"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Potong"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Salin"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Tempel"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Simpan Berkas EQF ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Impor Preset-preset Winamp ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Tampilan Winamp Klasik"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Simpan"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Buka"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Presets"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Muat preset"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
-msgstr ""
+msgstr "Simpan preset"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
-msgstr ""
+msgstr "Hapus preset"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "Pemutar:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Pilih font jendela player utama:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Playlist:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Pilih huruf daftar putar"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Kulit</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Fonts</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Gunakan huruf bitmap (hanya dukungan ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Gulir judul lagu dalam kedua arah"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyzer"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Cakupan"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Mati"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Api"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Garis"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Batang"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Paling Lambat"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lambat"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Sedang"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Cepat"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Paling Cepat"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Garis"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Es"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Halus"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Tipe</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Gaya"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Umum"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualisasi"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious Equalizer"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
-msgstr ""
+msgstr "Berusaha untuk %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Keseimbangan: %d%% left"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Keseimbangan: tengah"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Keseimbangan: %d%% kanan"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu Opsi"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Nonaktifkan 'Always On Top'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Bolehkan 'Always On Top'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Kotak Info Berkas"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "mode Single."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "mode Playlist."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Berhenti setelah lagu"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
-msgstr ""
-
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
+msgstr "Cari catatan di daftar putar aktif"
 
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "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."
 msgstr ""
+"Pilih entri dalam daftar putar dengan mengisi satu atau lebih bidang. Fields "
+"menggunakan ekspresi reguler sintaks, case-insensitive. Jika Anda tidak tahu "
+"bagaimana ekspresi reguler bekerja, cukup memasukkan sebagian literal dari "
+"apa yang Anda cari."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Judul: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artis: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nama berkas: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr ""
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
-msgstr ""
+msgstr "Buat daftar putar baru dengan mencocokan entri"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
-msgstr ""
+msgstr "Audacious Daftar Putar Editor"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d of %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
-msgstr ""
+msgstr "Arsipkan Kulit Winamp 2.x "
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
-msgstr ""
+msgstr "Jangan Arsipkan Kulit Winam 2.x "
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
+msgstr "Tidak dapat membuat folder (%s): %s\n"
+
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3439,75 +3743,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Format tidak didukung"
-
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
+msgstr "Ubah Lagu"
+
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
 msgstr ""
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Perintah saat Audacious memainkan lagu baru."
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Perintah:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Perintah saat Audacious mencapai akhir daftar lagu."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3522,17 +3820,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Perintah"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3541,51 +3837,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
-msgstr ""
+msgstr "Cepat"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
-msgstr ""
+msgstr "Rendah"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
-msgstr ""
+msgstr "Tinggi"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
-msgstr ""
+msgstr "Sangat Tinggi"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
-msgstr ""
+msgstr "Kualitas"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Kecepatan dan Nada"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
-msgstr ""
+msgstr "Kecepatan"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
-msgstr ""
+msgstr "Nada"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ikon Status"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "Se_ttings ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3596,63 +3892,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
-msgstr ""
+msgstr "Ubah volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
-msgstr ""
+msgstr "Ubah lagu yang sedang diputar"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
-msgstr ""
+msgstr "<b>Pengaturan Lain</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr ""
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Ikon Status"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr ""
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3661,15 +3957,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3690,44 +3982,75 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Dekoder Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Dekoder VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Dekoder VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Dekoder WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
-msgstr ""
+msgstr "yang berkurang (gabungan)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
-msgstr ""
+msgstr "yang berkurang"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
+"Hak cipta 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Beberapa kode pengaya ditulis oleh Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Dekoder WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Dekoder 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Pengaturan XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Abaikan panjang dari berkas"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
-msgstr ""
+msgstr "XML Shareable Playlists (XSPF)"
diff --git a/po/it.po b/po/it.po
index 9da1799df177..e905f5939a68 100644
--- a/po/it.po
+++ b/po/it.po
@@ -3,21 +3,22 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# davros74 <davros74 at gmail.com>, 2012
-# Federico.Torsello <federico421 at hotmail.it>, 2013-2014
+# David Rossi <davros74 at gmail.com>, 2012
+# Federico <federico421 at hotmail.it>, 2013-2014
 # minderz <franketti at gmail.com>, 2014
 # Jacopo Lorenzetti <jacopo.jl at gmail.com>, 2011-2012
 # Jacopo Lorenzetti <jacopol at cyan.xubiq.com>, 2012-2013
-# Marco91, 2013
-# Nicola Manini <nicola.manini at fisica.unimi.it>, 2014
+# Marco Mangiacavalli, 2013
 # Nicola Manini <nicola.manini at fisica.unimi.it>, 2014
+# Nicola Manini <nicola.manini at fisica.unimi.it>, 2014-2015
+# Saverio <saverio.brancaccio at gmail.com>, 2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-12 21:08+0000\n"
+"Last-Translator: Nicola Manini <nicola.manini at fisica.unimi.it>\n"
 "Language-Team: Italian (http://www.transifex.com/projects/p/audacious/"
 "language/it/)\n"
 "Language: it\n"
@@ -26,40 +27,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Decoder AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Decoder AAC (Raw)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Riproduttore AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sequenziato"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Riproduttore AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Allarme"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Regola la sveglia ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -70,11 +59,7 @@ msgstr ""
 "\n"
 "Originariamente scritto da Adam Feakin e Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Allarme"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -116,7 +101,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -155,7 +140,7 @@ msgstr ""
 "Comando addizionale:\n"
 "Avvia questo comando al tempo di allarme.\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -179,385 +164,389 @@ msgstr ""
 "Seleziona l'allarme nella casella e accendi\n"
 "l'interruttore se vuoi che venga mostrato."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Questa è la tua sveglia."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Il tuo promemoria per oggi è..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Promemoria"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Lunedì"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Martedì"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Mercoledì"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Giovedì"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Venerdì"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sabato"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Domenica"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Impostazioni sveglia"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_OK"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Cancella"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Ora"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Sveglia alle (predefinita):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Ferma dopo:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "ore"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minuti"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Scegliere i giorni in cui attivare la sveglia"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Giorno"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Predefinita"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Giorni"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Dissolvenza"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "secondi"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Inizia a"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Finale"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Attuale"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando aggiuntivo"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "abilita"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Playlist (opzionale)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Seleziona una lista di riproduzione"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opzioni"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Cosa significano queste opzioni?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Aiuto"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Copertina Album"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Copertina dell'album (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Uscita ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"I miei ringraziamenti a William Pitcock, autore dell'ALSA Output Plugin NG, "
+"il cui codice serve come riferimento quando il manuale ALSA non è "
+"sufficiente."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(nessuna descrizione)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositivo PCM predefinito"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositivo mixer predefinito"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositivo PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositivo mixer:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemento mixer:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Aggira interruzione per esaurimento risorse"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "Plug-in AMIDI (Riproduttore MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"Connettore AMIDI\n"
+"lettore di musica modulare MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"I miei ringraziamenti a William Pitcock, autore dell'ALSA Output Plugin NG, "
-"il cui codice serve come riferimento quando il manuale ALSA non è "
-"sufficiente."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Uscita ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "Plug-in AMIDI (Riproduttore MIDI)"
+"scritto da Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"Si ringraziano in particolare...\n"
+"Clemens Ladisch e Jaroslav Kysela\n"
+"per i loro programmi eccezionali aplaymidi e amixer; e i\n"
+"documenti alsa-lib per usati per approfondire le conoscenze delle API ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"per il bel logo della tastiera midi\n"
+"\n"
+"Tony Vroon\n"
+"per l'aiuto fornito durante l'alpha testing"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Sovrascrivi l'amplificazione di default"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Sovrascrivi la polifonia di default"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Sovrascrivi il riverbero di default"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Acceso"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Sovrascrivi il chorus di default"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Playback</b><b>Riproduzione</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Trasponi:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "semitoni"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Trasla la batteria:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Opzioni avanzate</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "numeri di note"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Estrai i commenti da file MIDI"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Salta il silenzio iniziale"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Estrai i testi da file MIDI"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Salta il silenzio finale"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Sintetizzatore</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Frequenza di campionamento"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Frequenza di campionamento:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - seleziona file SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancella"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Apri"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nome del file"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Dimensioni (byte)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nome:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Informazioni MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Durata (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Numero di tracce: "
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variabile"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Suddivisione temporale:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Commenti e testi MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* nessun commento disponibile in questo file MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* nessun testo disponibile in questo file MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Chiudi"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 non valido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Informazioni sul plug-in AMIDI"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug "
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Riproduttore musicale MIDI modulare\n"
-"http://www.develia.org/projects.php?p=amidiplug⏎\n"
-"\n"
-"scritto da Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"Ringraziamenti speciali a...\n"
-"\n"
-"Clemens Ladisch e Jaroslav Kysela⏎\n"
-"per i loro bei programmi aplaymidi e amixer; questi\n"
-"erano realmente utili, insieme con alsa-lib docs, allo scopo di\n"
-"imparare di più sull'API ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"per il bel logo midi della tastiera\n"
-"\n"
-"Tony Vroon\n"
-"per il buono aiuto nell alfa test"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -575,152 +564,147 @@ msgstr ""
 "Parzialmente basato sulla libreria Ghosd scritta da Evan Martin\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Informazioni sullo schermo)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Rettangolo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Rettangolo arrotondato"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Rettangolo concavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Nessuno"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Avvio della riproduzione"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Visualizza l'OSD quando viene riprodotto un elemento della playlist."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Cambio titolo"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Visualizza l'OSD quando, durante la riproduzione, il titolo del brano cambia "
-"ma il nome del file è lo stesso. È utile principalmente per visualizzare i "
-"cambi di titolo negli stream su internet."
+"Attiva OSD quando cambia il titolo di una canzone (per gli stream in rete)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Attivazione pausa"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Visualizza l'OSD quando viene interrotta la riproduzione."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Disattivazione pausa"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Visualizza l'OSD quando viene ripresa la riproduzione."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Posizionamento"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Offset X relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Offset Y relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Larghezza massima OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opzioni multi-monitor"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Visualizza OSD su:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "tutti i monitor"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Temporizzazione (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Visualizza:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Dissolvi in ingresso:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Dissolvi in uscita:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Caratteri"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Carattere %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Ombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Stile di resa grafica"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Colori"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Colore %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Abilita visualizzazione in seguito all'evento"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Rilevato compositing manager"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -730,112 +714,112 @@ msgstr ""
 "a meno che tu non sappia di averne uno in esecuzione, per favore attiva un "
 "compositing manager altrimenti l'OSD non funzionerà correttamente"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Compositing manager non richiesto per la falsa trasparenza"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Trasparenza"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Falsa trasparenza"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Trasparenza reale (richiede est. Composite di X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Estensione Composite non caricata"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Estensione Composite non disponibile"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - configurazione"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Testa"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Regola"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posizione"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animazione"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Testo"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decorazione"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Eventi"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Varie"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Test"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "Playlists "
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Liste di riproduzione ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Lista di riproduzione Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Colore</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer da Stereofinico a Binaurale (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Preimpostazioni:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Livello di alimentazione:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Frequenza di taglio:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Preimpostazioni:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer da Stereofinico a Binaurale (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizzatore di spettro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Plugin CD Audio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -856,171 +840,158 @@ msgstr ""
 "\n"
 "Questo era un progetto Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocità di lettura: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Ignora dispositivo: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadati</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Usa CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usa CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Usa HTTP invece di CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Percorso: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Porta: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Plugin CD Audio"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Errore nell'inizializzazione del sottosistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI %s non valido."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Traccia %d non trovata."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "La traccia %d è una traccia dati."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Errore nell'apertura dell'output audio."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Errore durante la lettura del CD Audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD Audio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Brano %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Errore nell'apertura del lettore CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Nessuna unità CD audio adatta trovata."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Errore alla fine dell'inizializzazione dell'unità CD aperta."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Errore nella ricerca del primo/ultimo numero della traccia."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Impossibile leggere inizio/fine dell'LNS per la traccia %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Errore nella creazione della connessione al cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Errore nella richiesta al server CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Errore nella richiesta al server CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Errore nella lettura delle informazioni del cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Il drive è vuoto."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo di disco non supportato."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Voci di menu CD Audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Riproduci CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Aggiungi CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Voci di menu CD Audio"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compressione</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Volume centrale:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Gamma dinamica:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Dynamic Range Compression Plugin per Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Plugin Dynamic Range Compression per Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compressione gamma dinamica"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1036,207 +1007,239 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bassi:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Alti:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Durata brano predefinita:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Resampling</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Abilita ricampionamento audio"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Frequenza di ricampionamento:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignora durata specificata nei tag SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumenta riverbero"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Decodificatore musica console giochi"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"La dissolvenza incrociata non è riuscita poiché i brani avevano un numero di "
-"canali differente. Puoi usare il Mixer Canale per convertire i brani allo "
-"stesso numero di canali."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Uscita CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"La dissolvenza incrociata non è riuscita poiché i brani avevano differenti "
-"frequenze di campionamento. Puoi usare il Convertitore frequenza di "
-"campionamento per convertire i brani alla stessa frequenza."
+"Plugin CoreAudio Output per Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basato sul plugin SDL Output per Audacious\n"
+"Copyright 2010 John Lindgren"
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Usa la modalità esclusiva"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Crossfade Plugin per Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Plugin Crossfade per Audacious\n"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Dissolvenza incrociata</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Su cambiamento automatico della canzone"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Sovrapposizione:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Sulla ricerca o cambiamento manuale della canzone"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Suggerimento</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Per una dissolvenza migliore, abilitare\n"
+"l'effetto Rimozione del Silenzio"
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Dissolvenza incrociata"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"La dissolvenza incrociata non è riuscita poiché i brani avevano un numero di "
+"canali differente. Puoi usare il Mixer Canale per convertire i brani allo "
+"stesso numero di canali."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"La dissolvenza incrociata non è riuscita poiché i brani avevano differenti "
+"frequenze di campionamento. Puoi usare il Convertitore frequenza di "
+"campionamento per convertire i brani alla stessa frequenza."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensità: "
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Plugin Cue Sheet"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Cancella files"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Si è verificato un errore spostando %s nel cestino: %s"
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Si è verificato un errore eliminando %s: %s"
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Si è verificato un errore eliminando %s: file non locale"
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Vuoi spostare i files selezionati nel cestino?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Sposta nel cestino"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Vuoi cancellare permanentemente i files selezionati?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Elimina"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Annulla"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Cancella files"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Cancella files selezionati"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Metodo di cancellazione</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Sposta nel cestino invece di cancellare immediatamente"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Plugin Echo\n"
+"di Johan Levin, 1999\n"
+"Surround echo di Carl van Schaik, 1999\n"
+"Aggiornato per Audacious da William Pitcock e John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Ritardo: "
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Feedback: "
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volume: "
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo Plugin\n"
-"Realizzato da Johan Levin, 1999\n"
-"\n"
-"Echo surround realizzato da Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Echo"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Plugin FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1252,55 +1255,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Plugin FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Plugin FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato del file in uscita:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configura"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Salva nella directory originale"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Salva in directory personalizzata"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Cartella del file in uscita:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Seleziona una cartella"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Ottieni nome file da:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Genera il nome del file da:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "tag del file originale"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Tag del file originale"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nome del file originale"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nome del file originale"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Non togliere estensione dal nome del file"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Tieni l'estensione del nome originale del file"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr "Anteponi numero di traccia al nome del file"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1333,165 +1336,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Plugin FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configurazione MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Qualità dell'algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "Frequenza di campionamento in uscita:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitrate / fattore di compressione:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Rapporto bitrate / compressione:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitrate (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Fattore di compressione:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modalità audio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Varie:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Rispetta rigorosamente conformità ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Imponi rispetto rigoroso conformità ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Protezione dagli errori"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualità"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Abilita VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opzioni VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Bitrate minima (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Bitrate massima (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Rispetta rigorosamente bitrate minima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opzioni ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Bitrate media (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Livello di qualità VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Non scrivere intestazione VBR Xing"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Ometti l'intestazione VBR Xing"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parametri del frame: "
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "Parametri del frame:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Contrassegna come coperto da copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Contrassegna come originale"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parametri ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forza aggiunta del tag versione 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Aggiungi solo tag v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Aggiungi solo tag v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tag"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configurazione del codificatore Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Livello di qualità (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Decodificatore FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "senza perdita"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1503,11 +1510,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Decodificatore FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1515,11 +1518,19 @@ msgstr ""
 "GIO Plugin per Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Plugin GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Modalità Leggi-e-aggiungi non supportata"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Modalità di apertura non valida"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1539,535 +1550,620 @@ msgstr ""
 "\n"
 "Licenza: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL Spectrum Analyzer"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Analizzatore di Spettro OpenGL per Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basato sul plugin di XMMS\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, \n"
+"e 4Front Technologies\n"
+"\n"
+"Licenza: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analizzatore di Spettro OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Scorciatoie di GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Gnome Shortcut Plugin\n"
-"Ti permette di controllare il riproduttore con i tasti di scelta rapida di "
-"Gnome.\n"
+"Plugin GNOME Shortcut\n"
+"Permette di controllare il lettore con le scorciatoie di GNOME.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Scorciatoie Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Numero elemento"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Titolo"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Anno"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artista"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Traccia"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Genere"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posizione nella coda"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Durata"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Percorso del file"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nome del file"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Titolo personalizzato"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitrate"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Colonne disponibili"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Colonne visualizzate"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Tool di ricerca"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Aggancia a sinistra"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Aggancia a destra"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Aggancia in alto"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Aggancia in basso"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Sgancia"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Disabilita"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Tool di ricerca"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Apri file…"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Apri _URL…"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "A_ggiungi file…"
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Aggiungi U_RL…"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Cerca nella _Libreria"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "I_nformazioni su…"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Configurazione ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Esci"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Riproduci"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Interro_mpi"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Ferma"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Pre_cedente"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Successiva"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Ripe_ti"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "C_asuale"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_on avanzare nella playlist"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Ferma _dopo questo brano"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Informazioni sul _brano…"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Salta alla _posizione…"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Sa_lta al brano…"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Imposta Punto di Ripetizione _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Imposta Punto di Ripetizione _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Cancella Punti di Ripetizione"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Per _titolo"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Da _Nome del file"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Per nome _File"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Da _Percorso del File"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Per _numero di traccia"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Per _artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Da Al_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Per Albu_m artista"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Per _data di pubblicazione"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Per _Genere"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Da _Lunghezza"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Per percorso del _file"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Per titolo _personalizzato"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Ordine in_verso"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Ordine _casuale"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Riproduci questa lista"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "Ri_produci/Riparti"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "A_ggiorna"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Ordina"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Ordina i selezionati"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Rimuovi _Duplicati"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Ri_muovi file non disponibili"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nuova"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Rin_omina ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Elimina"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importa…"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Esporta…"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Gestione_Liste di riproduzione ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Gestione co_da…"
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Alza volume"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "A_bbassa volume"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizzatore"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "Effetti ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Mostra barra dei _menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostra barra i_nformazioni"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Mostra barra di vis_ualizzazione informazioni"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostra barra di _stato"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Mostra Tempo _Rimasto"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Visualizzazioni ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_File"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Riproduzione"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Playlist"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servizi"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Uscita"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Visualizza"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "Inserisci/rimuovi dalla _coda"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "Apri cartella"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "T_aglia"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "C_opia"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Incolla"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Seleziona _tutti"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Rinomina ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Schede di playlist</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Mostra sempre le schede"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Mostra i conteggi"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Mostra i bottoni di chiusura"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Colonne di playlist</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Mostra le intestazioni delle colonne"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Varie</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Tasti freccia cercano per:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Fa avanzare la lista quando cambia brano"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfaccia GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Buffering…"
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canale"
 msgstr[1] "%d canali"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modalità singolo."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modalità playlist."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "La riproduzione si fermerà alla fine del brano."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Traccia precedente"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Riproduci"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Interrompi/riprendi"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Ferma"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Traccia successiva"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avanza di 5 secondi"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Riavvolgi di 5 secondi"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenzia"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Alza volume"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Abbassa volume"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Salta al file"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Mostra/nascondi finestra(e) di riproduzione"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostra On-screen-display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Attiva/disattiva ripetizione"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Attiva/disattiva shuffle"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Attiva/Disattiva lo stop dopo la corrente"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Mostra finestra(e) di riproduzione"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(nessuno)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2079,15 +2175,11 @@ msgstr ""
 "\n"
 "Vuoi continuare?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Associazione pulsanti del mouse"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configurazione plugin Tasti di scelta rapida globali"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2095,23 +2187,27 @@ msgstr ""
 "Premi una combinazione di tasti all'interno di un campo di testo.\n"
 "Puoi anche associare i pulsanti del mouse."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Tasti di scelta rapida:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Azione:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Tasto associato:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Aggiungi"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Hotkeys globali"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2138,60 +2234,58 @@ msgstr ""
 "Jonathan A. Davis <davis at jdhouse.org>,\n"
 "Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Hotkeys globali"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Uscita JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Collegati a tutte le porte jack disponibili"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Connetti automaticamente alle porte di uscita"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Collega solo le porte in uscita"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
+"Sono state rilevate solo le porte di uscita %d JACK ma sono richieste le %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Non collegare alcuna porta"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Impossibile connettersi alla porta JACK %s"
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Metodo di connessione:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK supporta solo audio con profondità di bit in virgola mobile. Si deve "
+"cambiare la codifica di uscita nelle impostazioni di Audacious, alla voce "
+"profondità di bit: virgola mobile."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Attiva l'output di debug"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Impossibile connettersi al server JACK; è in esecuzione?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Basato su xmms-jack, da Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Converito per Audacious da Giacomo Lozito"
+"Il server JACK richiede una frequenza di campionamento pari a %d Hz mentre "
+"Audacious sta riproducendo a %d Hz. Si prega di usare l'effetto convertitore "
+"della frequenza di campionamento per correggere la discrepanza."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Uscita JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Impostazioni %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Impostazioni Host LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Percorsi dei moduli:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2202,73 +2296,41 @@ msgstr ""
 "Dopo aver aggiunto nuovi percorsi, premi Invio per ricercare nuovi plugin.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Plugin disponibili:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Abilita"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Plugin abilitati:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Impostazioni"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
-"LADSPA Host per Audacious\n"
-"Copyright 2011 John Lindgren"
-
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "Host LADSPA"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: non posso inizializzare il supporto LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: non posso leggere il file di configurazione LIRC\n"
-"%s: fare riferimento alla documentazione di LIRC\n"
-"%s: come creare un file di configurazione appropriato\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: tento la riconnessione...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando sconosciuto \"%s\"\n"
+"LADSPA Host per Audacious\n"
+"Copyright 2011 John Lindgren"
 
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: disconnesso da LIRC\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "Host LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: tento la riconnessione ogni %d secondi...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Plugin LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2297,73 +2359,81 @@ msgstr ""
 "\n"
 "Per maggiori informazioni su LIRC, vedi http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Connessione</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Riconnetti al server LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Attesa prima della riconnessione:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Plugin LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Plugin LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Nessun testo disponibile"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Errore"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Impossibile recuperare %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Errore"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Impossibile analizzare %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Ricerca testi ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Metadata brano mancante"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Connessione a lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Plugin LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Plugin LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Playlists M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Generatore Tact"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Metronomo: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Metronomo: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2378,11 +2448,11 @@ msgstr ""
 "ad esempio tact://77 per avviare 77 battiti al minuto\n"
 "o tact://60*3/4 per avviare 60 bpm in 3/4 tact"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generatore Tact"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mixer Canale"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2390,152 +2460,184 @@ msgstr ""
 "Channel Mixer Plugin per Audacious⏎\n"
 "Copyright 2011-2012 John Lindgren e Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mixer Canale</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canali in uscita:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mixer Canale"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Plugin MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Impossibile connettersi al server MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Riproduttore del Modulo)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Risoluzione</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canali</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Più vicino (più veloce)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineare (veloce)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (buono)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifase (il migliore)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Frequenza di Sampling</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Frequenza di campionamento</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz:"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz:"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Livello:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Taglio:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Riverbero</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Aumento del Basso</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Preamplificatore</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Sovracampionamento"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Riduzione del rumore"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Avvia MOD Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Ripeti</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Contatore di ripetizioni:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Per ripetere per sempre, imposta il contatore di ripetizioni a -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Riproduttore del Modulo)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Queste impostazioni avranno effetto al prossimo riavvio di Audacious."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Plugin MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Opzioni avanzate</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Utilizza il calcolo della lunghezza accurata (lento)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Server MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Plugin Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Impossibile elaborare la ridirezione"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Errore HTTP sconosciuto"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Impossibile elaborare l'URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Troppe ridirezioni"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Fermato"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious non sta riproducendo."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notifiche Desktop"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2571,55 +2673,64 @@ msgstr ""
 "Dovresti aver ricevuto una copia della licenza GNU General Public License "
 "insieme al programma; se così non fosse, vedi <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Mostra controlli di riproduzione"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Permette di mostrare le notifiche"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notifiche Desktop"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Includi il nome dell'album nella notifica"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Mostra"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Interrompi"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Successivo"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo predefinito"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Uscita OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Uscita OSS3"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo predefinito"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo audio:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Usa dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Mantieni volume tra le sessioni"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Abilita conversioni di formato effettuate dal software OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Abilita la modalità esclusiva per prevenire il missaggio virtuale."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2633,19 +2744,35 @@ msgstr ""
 "Vorrei ringrazire le persone su #audacious, specialmente Tony Vroon e John "
 "Lindgren e sicuramente gli autori del precedente OSS plugin."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Uscita OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Gestore delle playlist"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Voci"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Rimuovi"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Rin_omina"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Playlist PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Decodificatore OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Uscita PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2682,11 +2809,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Uscita PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Uscita QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Plugin QtMultimedia Audio per Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Basato sul plugin SDL Output per Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "In elaborazione ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Cerca"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "Apri cartella ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Aggiungi cartella ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Ispettore dei log ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Apri file"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Aggiungi file"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Precedente"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Ripeti"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Casuale"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interfaccia Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Convertitore Sample Rate"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2694,99 +2883,107 @@ msgstr ""
 "Sample Rate Converter Plugin per Audacious⏎\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Salta/ripeti gli esempi"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolazione lineare"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolazione di Shannon veloce"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolazione di Shannon media"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Interpolazione di Shannon migliore"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversione</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metodo:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Frequenza:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mappature della frequenza</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Usa le mappature della frequenza"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Convertitore Sample Rate"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Processo di scrobbling per l'utente: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Permesso Negato."
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Accedi al seguente link per permettere ad Audacious di eseguire lo "
 "scrobbling dei tuoi avvii:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Mantieni aperta questa finestra e clicca ancora su 'Controlla Permesso'.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2794,35 +2991,39 @@ msgstr ""
 "Non preoccuparti. I tuoi scrobble sono stati salvati sul tuo computer.\n"
 "Loro saranno inviati appena Audacious avrà il permesso di farlo."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problema di Rete."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "C'era un problema nel contattare Last.fm. Per favore riprova più tardi."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "In controllo..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "C_ontrolla Permesso"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Revoca Permesso"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Hai bisogno di permettere ad Audacious di eseguire lo scrobbling delle "
 "tracce al tuo account Last.fm.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2830,7 +3031,7 @@ msgstr ""
 "Lo Scrobbler plugin non può essere avviato.\n"
 "Ci potrebbe essere un problema con l'installazione."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2846,11 +3047,7 @@ msgstr ""
 "\n"
 "Grazie a John Lindgren per avermi dato una mano all'inizio del progetto.\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2859,7 +3056,11 @@ msgstr ""
 "fm.\n"
 "Per favore controlla le impostazioni per il plugin Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Uscita SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2867,81 +3068,56 @@ msgstr ""
 "SDL Output Plugin per Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Uscita SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Libreria"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista sconosciuto"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Album sconosciuto"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s \n"
-" su %s di %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d risultato"
+msgstr[1] "%d risultati"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d album"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d nascosto)"
+msgstr[1] "(%d nascosti)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d canzone"
-msgstr[1] ""
-"%s\n"
-" %s, %d canzoni"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d canzoni di %s"
-msgstr[1] ""
-"%s\n"
-" %d canzoni di %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d canzone"
+msgstr[1] "%d canzoni"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "di questo genere"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "in funzione"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "di"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Crea playlist"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Aggiungi alla playlist"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Cerca nella libreria"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2949,679 +3125,771 @@ msgstr ""
 "Per importare la tua musica in Audacious, scegli una cartella e clicca "
 "sull'icona \"aggiorna\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Attendi per favore…"
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Scegli una cartella"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Player SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Uscita</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canali:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulazione</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emula MOS 8580 (Predefinito: MOD 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Non selezionare in automatico il modello del chip"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emula il filtro"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Velocità del clock:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Non selezionare in automatico la velocità del clock"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Tempo di riproduzione</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Imposta il tempo massimo di riproduzione:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Da usare quando la lunghezza della canzone è sconosciuta"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Imposta il tempo minimo di riproduzione:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Bassi</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Abilita i bassi"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignora i bassi pù piccoli di:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nota</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Rimozione del silenzio"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Plugin Silence Removal per Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Rimozione del silenzio</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Soglia:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Apri files ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Apri URL ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Cerca nella libreria"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Riproduzione"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Playlist"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Visualizza"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Servizi"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Informazioni ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Impostazioni ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Esci"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Informazioni sul brano"
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Ripeti"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Casuale"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Non avanzare nella playlist"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Interrompi al termine di questo brano"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Precedente"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Setta ripetizione A-B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Elimina ripetizione A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Vai a brano ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Vai a istante di tempo ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Riproduci questa Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Riproduci/Riparti"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nuova playlist"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Cambia nome a Playlist"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Elimina Playlist"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Playlist precedente"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Playlist successiva"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importazione Playlist ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Esportazione Playlist ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Organizza Playlist ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Organizza Coda ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Aggiorna Playlist"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostra editor della playlist"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostra equalizzatore"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Mostra tempo rimanente"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Sempre in primo piano"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Su tutti gli spazi di lavoro"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Arrotola il Player"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Arrotola l'editor di Playlist"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Arrotola l'equalizzatore"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Doppia grandezza"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Aggiungi URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Aggiungi files ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Per titolo"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Per nome del file"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "Per nome File"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Per percorso file"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Rimuovi tutti"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Cancella coda"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Rimuovi i file non disponibili"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Rimuovi i duplicati"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Rimuovi deselezionati"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Rimuovi selezionati"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Cerca e seleziona"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverti selezione"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Deseleziona tutti"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Seleziona tutti"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Per album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Per numero di traccia"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Per artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Per album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Per album artista"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Per data di pubblicazione"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Per numero di traccia"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Per Genere"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Per Durata"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Per titolo personalizzato"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Riordina casualmente la lista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Inverti lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Ordina selezionati"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordina lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Taglia"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copia"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Incolla"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Metti in/togli da coda"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Carica predefiniti ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Carica predefiniti automatici ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Carica i default"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Carica un file di predefiniti ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Carica file EQF"
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Salva predefiniti"
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Salva predefiniti automatici"
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Salva default"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Salva file di predefiniti"
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Salva file EQF"
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Cancella predefiniti"
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Cancella predefiniti automatici"
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importa i predefiniti di Winamp"
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Resetta a zero"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interfaccia classica di Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Salva"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Carica"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Carica file di predefiniti"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Carica file EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Salva file di predefiniti"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Salva file EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importa i predefiniti di Winamp"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Preimpostazioni"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Carica preimpostazione"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Carica preimpostazione a caricamento automatico"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Salva preimpostazione"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Salva preimpostazione a caricamento automatico"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Elimina preimpostazione"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Elimina preimpostazione a caricamento automatico"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Lettore:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Lettore:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Seleziona il carattere della finestra principale del lettore:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Playlist:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Playlist:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Seleziona il carattere della playlist:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Pelle</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Caratteri</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Usa caratteri bitmap (supporta solo ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Fai sfilare il titolo del brano"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Scorri titolo brano in entrambe le direzioni"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizzatore"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Oscilloscopio"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Impronta vocale/VU meter"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Spento"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normale"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fuoco"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Linee verticali"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linee"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barre"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Molto lenta"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lenta"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Media"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Veloce"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Molto veloce"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Puntini"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Linea"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Solido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Ghiaccio"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Morbida"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Scrivi</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Tipo di visualizzazione:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizzatore</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Mostra picchi"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Colori:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Stile:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Decadimento:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Decadimento dei picchi:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Stile di oscilloscopio:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Colori dell'impronta vocale:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Stile del VU meter:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Generale"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualizzazione"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamplificazione"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Equalizzatore di Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Vai a %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Bilanciamento: sinistra %d%%"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Bilanciamento: centro"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Bilanciamento: destra %d%%"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu opzioni"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Disabilita 'Sempre in primo piano'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Abilita 'Sempre in primo piano'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Finestra informazioni file"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualizzazioni"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Punto di Ripetizione _A impostato"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Punto di Ripetizione _B impostato"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Punti di Ripetizione Cancellati"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modalità singolo."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modalità playlist."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "La riproduzione si fermerà alla fine del brano."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Cerca elementi nella playlist attiva"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Cerca"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3633,57 +3901,61 @@ msgstr ""
 "maiuscole e minuscole. Se non sai come funzionano le espressioni regolari, "
 "inserisci semplicemente una porzione letterale di quello che stai cercando."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Titolo: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Titolo:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artista:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nome del file: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nome del file:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Cancella la selezione precedente prima di effettuare la ricerca"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Inserisci automaticamente in coda gli elementi trovati"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Crea una nuova playlist con gli elementi trovati"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor della playlist di Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d di %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Skin Winamp 2.x archiviata"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Skin Winamp 2.x non archiviata"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Impossibile creare la directory (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Plugin Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3724,83 +3996,74 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, "
 "USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Plugin Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Informazioni sul plugin Sndio Output"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Uscita Sndio"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Plugin Sndio Output\n"
-"\n"
-"Scritto da Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Dispositivo (lasciare vuoto per usare quello predefinito):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato non supportato"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Salva e ripristina il volume:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"E' stato richiesto un formato non supportato dal dispositivo audio.\n"
-"\n"
-"Per favore, riprova con il server sndiod(1) attivato."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Errore Sndio: Formato audio non supportato (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Errore Sndio: sio_open() fallito"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(vuoto significa default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Errore Sndio: sio_setpar() fallito"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Errore Sndio: sio_start() fallito"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Cambio brano"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando da eseguire quando Audacious inizia un nuovo brano."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>I parametri passati alla shell dovrebbero essere "
+"racchiusi tra virgolette. Fare diversamente costituisce un rischio per la "
+"sicurezza.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Comandi</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Comando da lanciare quando si avvia una nuova canzone:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando da eseguire alla fine del brano."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Comando da lanciare al termine di una canzone:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Comando da eseguire quando Audacious raggiunge la fine della playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Comando da lanciare alla fine di una playlist:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Comando da eseguire quando cambia il titolo del brano (titoli degli stream "
-"di rete)."
+"Comando da lanciare quando cambia il titolo di una canzone (per gli stream "
+"in rete):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3814,36 +4077,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Puoi usare il seguente formato stringa che\n"
-"sarà sostituito prima di chiamare il comando\n"
-"(non tutti sono utili per il comando fine-playlist):\n"
+"Si possono usare i seguenti formati che verranno sostituiti prima di "
+"chiamare il comando (non tutti sono utili per il comando eseguibile alla "
+"fine della playlist):\n"
 "\n"
 "%F: Frequenza (in hertz)\n"
 "%c: Numero di canali\n"
-"%f: Nome file (full path)\n"
-"%l: Durata (in milliseconds)\n"
-"%n o %s: Nome Brano\n"
-"%r: Rate (in bits per secondi)\n"
-"%t: Posizione playlist (%02d)\n"
-"%p: In riproduzione (1 o 0)\n"
+"%f: Nome del file (path completo)\n"
+"%l: Lunghezza (in millisecondi)\n"
+"%n o %s: Nome della canzone\n"
+"%r: Rapporto (in bits al secondo)\n"
+"%t: Posizione nella playlist (%02d)\n"
+"%p: Attualmente in esecuzione (1 or 0)\n"
 "%a: Artista\n"
 "%b: Album\n"
-"%T: Nome brano"
+"%T: Titolo del brano"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>I parametri passati alla shell dovrebbero essere "
-"racchiusi tra virgolette. Fare diversamente costituisce un rischio per la "
-"sicurezza.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Informazioni sul brano (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandi"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3857,51 +4115,51 @@ msgstr ""
 "Basato sul Plugin Sample Rate Converter:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Veloce"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Basso"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alto"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Molto Alto"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualità:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocità e Tono"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocità e Tono</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocità: "
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tono:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocità e Tono"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Icona di stato"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Impostazioni ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3919,39 +4177,39 @@ msgstr ""
 "Questo plugin fornisce un'icona di stato, posizionata nell'\n"
 "area di notifica del gestore delle finestre di sistema."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "Azione Scroll Mouse"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Cambia volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Cambia brano in riproduzione"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Altre impostazioni</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Disabilita la finestra popup"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Chiudi nell'area di notifica (system tray)"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avanza nella playlist quando si scorre verso l'alto"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Icona di stato"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3961,24 +4219,24 @@ msgstr ""
 "\n"
 "Realizzato da Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generatore di toni"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generatore di toni: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3993,15 +4251,11 @@ msgstr ""
 "ad esempio tone://2000;2005 per avviare un tono di 2000 Hz e un tono di 2005 "
 "Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generatore di toni"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Rimozione voce"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4039,11 +4293,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Decodificatore Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Dettagli su %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Titolo: %t\n"
+"Autore: %a\n"
+"Da: %f\n"
+"Tracker: %T\n"
+"Commento: %C\n"
+"Tipo di chip: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Freq. del chip: %F\n"
+"Freq. player: %P\n"
+"Anno: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Decodificatore VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4054,19 +4343,19 @@ msgstr ""
 "Basato su in_vtx.dll realizzato da Roman Sherbakov <v_soft at microfor.ru>\n"
 "Plugin Audacious realizzato da Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Decodificatore VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Decodificatore WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "senza perdita (ibrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "con perdita"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4076,14 +4365,18 @@ msgstr ""
 "\n"
 "Una parte del codice del plugin era di Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Decodificatore WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Decodificatore 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configurazione XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignora la lunghezza dal file"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Liste di riproduzione condivisibili XML (XSPF)"
diff --git a/po/ja.po b/po/ja.po
index cf3ef9300956..72c4f6682840 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -3,20 +3,21 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# natird <dritan86 at gmail.com>, 2012
-# uǝsıɯoʎ(読み専) <hallconnen2+transifex at gmail.com>, 2013
-# uǝsıɯoʎ(読み専) <hallconnen2+transifex at gmail.com>, 2012
-# Shuuji TAKAHASHI <shuuji3 at gmail.com>, 2012-2014
+# natird zoto <dritan86 at gmail.com>, 2012
+# ABE Tsunehiko, 2013
+# ABE Tsunehiko, 2012
+# Mika Kobayashi, 2014-2015
+# Shuuji Takahashi <shuuji3 at gmail.com>, 2012-2014
 # Warui-chan  <>, 2012
-# uǝsıɯoʎ(読み専) <hallconnen2+transifex at gmail.com>, 2012
-# uǝsıɯoʎ(読み専) <hallconnen2+transifex at gmail.com>, 2013
+# ABE Tsunehiko, 2012
+# ABE Tsunehiko, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-20 17:34+0000\n"
+"Last-Translator: Mika Kobayashi\n"
 "Language-Team: Japanese (http://www.transifex.com/projects/p/audacious/"
 "language/ja/)\n"
 "Language: ja\n"
@@ -25,40 +26,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "モノラル"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "ステレオ"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "サラウンド"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) デコーダ"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) デコーダ"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib プレイヤー)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "シーケンス"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib プレイヤー)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "アラーム"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "アラームをセット"
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -66,13 +55,9 @@ msgid ""
 msgstr ""
 "設定した時間に再生を開始するためのプラグイン\n"
 "\n"
-"Originally written by Adam Feakin and Daniel Stodden."
-
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "アラーム"
+"元の作者: Adam Feakin および Daniel Stodden"
 
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -94,8 +79,25 @@ msgid ""
 "\n"
 "\n"
 msgstr ""
+"時刻\n"
+" アラーム時刻:\n"
+"  アラームが鳴る時刻。\n"
+"\n"
+" 静かになるまでの時間:\n"
+"  この時間が過ぎるとアラームが止まります。\n"
+"  (目覚ましダイアログを閉じなかった場合)\n"
+"\n"
+"曜日\n"
+" 曜日:\n"
+"  アラームを有効にする曜日を指定します。\n"
+"\n"
+" 時刻:\n"
+"  その曜日のアラームを鳴らす時刻を指定するか、\n"
+"  ボタンにチェックしてデフォルトを指定します。\n"
+"\n"
+"\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -133,7 +135,7 @@ msgstr ""
 "    アラームの時刻にこのコマンドを実行します。\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -157,384 +159,390 @@ msgstr ""
 "    表示たい場合には、テキストボックスにリマインダを入力し、\n"
 "    トグルボタンをオンにしてください。"
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "目覚ましです。"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "今日のリマインダ:"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "リマインダ"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "月曜日"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "火曜日"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "水曜日"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "木曜日"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "金曜日"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "土曜日"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "日曜日"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "アラームの設定"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "OK (_O)"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "キャンセル (_C)"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "時刻"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "アラーム時刻 (デフォルト)"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr " "
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "静かになるまでの時間:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "時間"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "分"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "アラームが鳴る曜日を選んでください"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
-msgstr "æ—¥"
+msgstr "曜日"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "デフォルト"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
-msgstr "æ—¥"
+msgstr "曜日"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "フェード"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "秒"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "音量"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "フェード開始音量"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "フェード終了音量"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "現在の音量"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "追加コマンド"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "有効"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "プレイリスト (オプション)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "プレイリストを選択"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "オプション"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "オプションの説明"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "ヘルプ"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "アルバムアート"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "アルバムアート (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA 出力"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA 出力プラグイン for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"ALSA 出力プラグイン NG の作者 William Pitcock に感謝します。ALSA のマニュアル"
+"では不十分な時に参考にさせてもらいました。"
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(説明なし)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "デフォルト PCM デバイス"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "デフォルトミキサデバイス"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM デバイス:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "ミキサデバイス:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "ミキサエレメント"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI プレイヤー)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA 出力プラグイン for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"モジュラー MIDI 音楽プレイヤ\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"ALSA 出力プラグイン NG の作者 William Pitcock に感謝します。ALSA のマニュアル"
-"では不十分な時に参考にさせてもらいました。"
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA 出力"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI プレイヤー)"
+"作者: Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"スペシャルサンクス...\n"
+"\n"
+"Clemens Ladisch および Jaroslav Kysela\n"
+"(彼らの創った素晴らしいプログラム aplaymidi  amixerについて。\n"
+"実に便利で、alsa-lib の文書に沿っており、\n"
+"ALSA API の習得に適っている)\n"
+"\n"
+"Alfredo Spadafina\n"
+"(彼の、素敵な MIDI キーボードのロゴについて)\n"
+"\n"
+"Tony Vroon\n"
+"(アルファテスト時にとてもよく手伝ってくれた)"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "デフォルトのゲインを上書き:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "デフォルトのポリフォニーを上書き:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "デフォルトのリバーブを上書き:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "オン"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "デフォルトのコーラスを上書き:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>再生</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "トランスポーズ: "
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "半音"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "ドラムシフト: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "ノートナンバー"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "MIDI ファイルからコメントを抽出する"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "先行する無音をスキップ"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "MIDI ファイルから歌詞を抽出する"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "後行する無音をスキップ"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>サウンドフォント</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>シンセサイザー</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "リサンプリングレート:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "サンプリングレート:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - サウンドフォント ファイルの選択"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "キャンセル (_C)"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "開く (_O)"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "ファイル名"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "サイズ (バイト)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "名前:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI 情報 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "形式:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "長さ (ミリ秒):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "トラック数:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "可変"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "時間軸:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI コメントと歌詞 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* MIDI ファイル中に有効なコメントがありません *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* MIDI ファイル中に有効な歌詞がありません *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "プレイリストを閉じる(_C)"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (不正な UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI-Plug について"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"modular MIDI 音楽プレイヤ\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"スペシャルサンクス\n"
-"\n"
-"Clemens Ladisch と Jaroslav Kysela\n"
-"彼らの作った aplaymidi とamixer という素晴らしいプログラムは、\n"
-"ALSA API について知るために、alsa-lib のドキュメントとともに、大変役に立ちま"
-"した。\n"
-"\n"
-"Alfredo Spadafina\n"
-"素敵な midi キーボードのロゴを作ってくれました。\n"
-"\n"
-"Tony Vroon\n"
-"アルファテストで大変助けてもらいました。"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -544,152 +552,155 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"作者 Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Evan Martin 作の Ghosd ライブラリに一部を基づく:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "矩形"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "角丸矩形"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "凹矩形"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "なし"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "再生開始"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "プレイリストの曲が再生されたときに OSD を表示します。"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "タイトル変更"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"再生中に、ファイル名が同じでも、曲のタイトルが変更されたときに OSD を表示しま"
-"す。これは、インターネットストリームのタイトル変更を表示するのに便利です。"
+"曲タイトルが替わったらOSDを発動させる (インターネットストリーミング用)。"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "一時停止"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "再生が停止したときに OSD を表示します。"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "再生の再開"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "再生が再開したときに OSD を表示します。"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "相対 X オフセット:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "相対 Y オフセット:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "最大 OSD 幅:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "マルチモニタ オプション"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD を表示するモニタ:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "全てのモニタ"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "モニタ %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "タイミング (ミリ秒)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "表示:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "フェードイン:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "フェードアウト:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "フォント"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "フォント %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "å½±"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "描画形式"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "色"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "色 %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "トリガー有効"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "イベント"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Composite マネージャが検出されました"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -699,112 +710,112 @@ msgstr ""
 "動作させているかわからなければ, Composite マネージャを有効にしてください. そ"
 "うしなければ OSD は正常に動作しないでしょう."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Composite マネージャは偽の透明化には必要ではありません"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "透明化"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "偽の透明化"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "真の透明化 (X Composite 拡張が必要)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite 拡張が読み込まれていません"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite 拡張が有効ではありません"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - 設定"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "テスト (_T)"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "設定 (_S)"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "アニメーション"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "文字"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "装飾"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "トリガー"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "その他"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "テスト"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 プレイリスト"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 プレイリスト"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious プレイリスト (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>色</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "ブラー・スコープ"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "バウアー ステレオ-バイノーラル変換 (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "プリセット:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "フェードレベル:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Cut 周波数"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "プリセット:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "バウアー ステレオ-バイノーラル変換 (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "スペクトラムアナライザ"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "オーディオ CD プラグイン"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -825,172 +836,159 @@ msgstr ""
 "\n"
 "このプラグインは、Google Summer of Code 2007 のプロジェクトです。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>デバイス</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "読み込み速度:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "上書きデバイス"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>メタデータ</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "CD-Text を使用する"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB を使用する"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP の代わりに HTTP を使う"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "サーバー:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "パス:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "ポート:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "オーディオ CD プラグイン"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "cdio サブシステムの初期化に失敗しました。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "次の URI は無効です。%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "トラック %d が見つかりません。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "トラック %d はデータトラックです。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "オーディオ出力のオープンに失敗しました。"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr " オーディオCDの読み込みでエラーが発生しました。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "オーディオ CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "トラック %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "CDデバイス %s のオープンに失敗しました。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "オーディオが利用可能なCDドライブが見つかりません。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "オープンされたCDドライブの初期化が完了できませんでした。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "最初または最後のトラックナンバを取得できませんでした。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 "トラック %d の LSN(論理セクタ番号) の開始または終了が読み取れませんでした。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "cddb コネクションの作成に失敗しました。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "CDDB サーバへのクエリに失敗しました。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "CDDB サーバへのクエリに失敗しました: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "cddb 情報の読み取りに失敗しました: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "ドライブにディスクがありません。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "非対応のディスクです。"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "オーディオ CD メニュー項目"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD を再生"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "プレイリストに CD を追加"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "オーディオ CD メニュー項目"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>コンプレッション</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "センター音量:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "ダイナミックレンジ:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "ダイナミックレンジ圧縮プラグイン for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "ダイナミックレンジコンプレッサ"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1006,207 +1004,239 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "ベース:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "トリバル:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "エコー:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "デフォルトの曲の長さ:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>リサンプリング</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "オーディオリサンプリングを有効にする"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "リサンプリングレート:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC タグからの長さを無視する"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "リバーブを増やす"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "ゲームコンソール音楽デコーダ"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"曲のチャンネル数が異なるため、クロスフェードが失敗しました。\n"
-"曲を同じチャンネル数にするためには、チャンネルミキサが利用できます。"
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio 出力"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"曲のサンプリング周波数が異なるため、クロスフェードが失敗しました。\n"
-"曲を同じサンプリング周波数にするために、サンプリング周波数ミキサが利用できま"
-"す。"
+"CoreAudio 出力プラグイン for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"派生元: SDL 出力プラグイン for Audacious\n"
+"Copyright 2010 John Lindgren"
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "排他モードを用いる"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "クロスフェードプラグイン for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>クロスフェード</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "曲が自動的に替わったとき"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "オーバーラップ:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "シークや任意に曲を替えたとき"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>参考</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"より効果的なクロスフェードを実現するには\n"
+"無音部の除去プラグインも有効に"
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "クロスフェード"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"曲のチャンネル数が異なるため、クロスフェードが失敗しました。\n"
+"曲を同じチャンネル数にするためには、チャンネルミキサが利用できます。"
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"曲のサンプリング周波数が異なるため、クロスフェードが失敗しました。\n"
+"曲を同じサンプリング周波数にするために、サンプリング周波数ミキサが利用できま"
+"す。"
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>クリスタライザ</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "明るさ:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "クリスタライザ"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue シートプラグイン"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "ファイルの削除"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "%s をゴミ箱に移動中に次のエラーが発生しました。%s。"
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "%s の削除中に次のエラーが発生しました。%s。"
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 "%s の削除中に次のエラーが発生しました。ローカルなファイルではありません。"
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "選択したファイルをゴミ箱に移動しますか?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "ゴミ箱に移動する"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "選択したファイルを完全に削除しますか?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "削除"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "キャンセル"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "ファイルの削除"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "選択したファイルの削除"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>削除の方法</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "一時的に削除するかわりにゴミ箱に移動"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"エコープラグイン\n"
+"By Johan Levin, 1999\n"
+"サラウンドエコー by Carl van Schaik, 1999\n"
+"Audacious用に更新 by William Pitcock and John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>エコー</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "遅延:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "フィードバック:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "音量:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"エコープラグイン\n"
-"By Johan Levin, 1999\n"
-"\n"
-"サラウンドエコー by Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "エコー"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg プラグイン"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1222,55 +1252,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg プラグイン"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "ファイル出力プラグイン"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "出力ファイルフォーマット:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "設定"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "元のディレクトリに保存する"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "指定のディレクトリに保存する"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "ファイル出力先ディレクトリ:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "ディレクトリの選択"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "ファイル名の取得元:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "ファイルネームを次から生成:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "元のファイルのタグ"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "元のファイルタグ"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
 msgstr "元のファイル名"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "ファイル名から拡張子を取り除かない"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "元のファイル拡張子を含める"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "ファイル名の先頭にトラック番号を付加する"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "ファイル名の前にトラック番号を付ける"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1287,180 +1317,183 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"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"
+"フリーソフトウェア財団によって発行された GNU 一般公衆利用許諾契約書\n"
+"(バージョン2か、希望によってはそれ以降のバージョンのうちどれか)の\n"
+"定める条件の下で再頒布または改変することができます。\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."
-
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "ファイル出力プラグイン"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+"このプログラムは有用であることを願って頒布されますが、*全くの無保証* \n"
+"です。商業可能性の保証や特定の目的への適合性は、言外に示されたものも\n"
+"含め全く存在しません。詳しくはGNU 一般公衆利用許諾契約書をご覧ください。\n"
+" \n"
+"あなたはこのプログラムと共に、GNU 一般公衆利用許諾契約書の複製物を\n"
+"1部受け取ったはずです。もし受け取っていなければ、フリーソフトウェア財団\n"
+"まで請求してください(宛先は the Free Software Foundation, Inc., \n"
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA)。"
+
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "自動"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "ジョイントステレオ"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "ステレオ"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "モノラル"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 設定"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "OK (_O)"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "アルゴリズム品質:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "出力サンプリングレート:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "ビットレート / 圧縮率:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "ビットレート (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "圧縮率:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "オーディオ モード:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "その他:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "厳格な ISO 遵守を強制する"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "厳密なISO適合を強制"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "エラー保護"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "音質"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR を有効にする"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "タイプ:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR オプション:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "最小ビットレート (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "最大ビットレート (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "最小ビットレートを厳格に強制する"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR オプション:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "平均ビットレート (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR 品質レベル:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR ヘッダを書き込まない"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Xing VBR ヘッダを除く"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "フレームパラメータ"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "フレームパラメータ:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "著作権物としてマーク"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "オリジナルとしてマーク"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3 パラメータ:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "バージョン 2 タグを強制的に付加する"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "v1 タグのみ付加する"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "v2 タグのみ付加する"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "ã‚¿ã‚°"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis エンコーダ設定"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "品質レベル (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC デコーダ"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "可逆"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1472,11 +1505,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC デコーダ"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1484,11 +1513,19 @@ msgstr ""
 "GIO プラグイン for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO プラグイン"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "リードアンドアペンドモードには対応していません"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "無効なオープンモード"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1499,542 +1536,628 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"OpenGL スペクトラムアナライザ for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"\n"
+"派生元: XMMS プラグイン:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"ライセンス: GPLv2+"
+
+#: src/gl-spectrum/gl-spectrum.cc:62
+msgid "OpenGL Spectrum Analyzer"
+msgstr "OpenGL スペクトラムアナライザ"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
 "Based on the XMMS plugin:\n"
 "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
 "4Front Technologies\n"
 "\n"
 "License: GPLv2+"
+msgstr ""
+"OpenGL スペクトラムアナライザ for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"派生元: XMMS プラグイン:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"ライセンス: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
-msgid "OpenGL Spectrum Analyzer"
-msgstr "OpenGL スペクトルアナライザ"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL スペクトラムアナライザ (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME ショートカット"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"Gnome ショートカットプラグイン\n"
-"Gnome ショートカットでプレイヤーをコントロールします。\n"
+"GNOME ショートカットプラグイン\n"
+"GNOME ショートカットでプレイヤーを制御可能にします。\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome ショートカット"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "リスト番号"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "タイトル"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "アーティスト"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "å¹´"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "アルバム"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "アルバムアーティスト"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "トラック"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "ジャンル"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "キュー番号"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "長さ"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "ファイルパス"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "ファイル名"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "カスタムタイトル"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "ビットレート"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "利用できる列"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "表示された列"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "検索ツール"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "左側にドッキング"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "右側にドッキング"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "上部にドッキング"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "下部にドッキング"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "ドッキングを解く"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "無効"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "検索ツール"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "ファイルを開く(_O)"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "URL を開く(_U)"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "ファイルを追加(_A)"
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "URL を追加(_R)"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "ライブラリを検索 (_L)"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "プログラムの情報(_B)"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "設定 (_S)"
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "終了(_Q)"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "再生(_P)"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "一時停止(_E)"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "停止(_S)"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "前の曲へ(_V)"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "次の曲へ(_N)"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "リピート(_R)"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "シャッフル(_H)"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "1曲リピート(_O)"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "曲の再生後に停止(_A)"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "曲の情報(_I)"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "指定した時間にジャンプ(_T)"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "指定した曲にジャンプ(_J)"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "リピートポイントAを設定(_A)"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "リピートポイントBを設定(_B)"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "リピートポイントをクリアする(_C)"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "タイトル(_T)"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "ファイル名(_F)"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "パス(_P)"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "トラックナンバー(_N)"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "アーティスト(_A)"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "アルバム(_L)"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "アルバムアーティスト(_M)"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "リリース日(_D)"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "ジャンル(_G)"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "曲の長さ(_L)"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "ファイルパス(_F)"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "カスタムタイトル(_C)"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "逆順にする(_E)"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "ランダムに並べる(_R)"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "このプレイリストを再生する(_P)"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "再生/再開(_P)"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "再読み込み(_R)"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "ソート(_S)"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "選択したトラックをソートする (_L)"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "重複している曲を削除(_D)"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "再生できないファイルを削除する(_U)"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "新しいプレイリスト(_N)"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "名前の変更(_A)"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "削除 (_V)"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "インポート(_I)"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "エクスポート(_E)"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "プレイリストマネージャ(_M)"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "キューマネージャ(_Q)"
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "音量を上げる(_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "音量を下げる(_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "イコライザ(_E)"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "エフェクト (_E)"
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "メニューバーを表示する(_M)"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "情報バーを表示する(_N)"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "情報バーに視覚効果を表示"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "ステータスバーを表示する(_S)"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "残り時間を表示する(_R)"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "視覚化 (_V)"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "ファイル(_F)"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "再生(_P)"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "プレイリスト(_L)"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "サービス(_S)"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "出力(_O)"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "表示(_V)"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "キュー / アンキュー(_Q)"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "このファイルを含むフォルダを追加(_O)"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "切り取り(_T)"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "コピー(_C)"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "貼り付け(_P)"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "すべて選択(_A)"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "名前の変更(_R)"
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>プレイリストのタブ</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "常にタブを表示する"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "項目総数を表示"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "閉じるボタンを表示する"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>プレイリスト列</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "列のヘッダーを表示する"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>その他</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "矢印キーでシークする時間:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "曲が変わったらスクロールする"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK インターフェイス"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "バッファ中 ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "モノラル"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "ステレオ"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d チャンネル"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "シングルモード"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "プレイリストモード"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "曲の再生後に停止する"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "前のトラック"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "再生"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "一時停止/再開"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "停止"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "次のトラック"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5秒進める"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5秒戻す"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "ミュート"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "音量を上げる"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "音量を下げる"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "指定したファイルへ移動"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "プレイヤウィンドウをトグル"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "On-Screen-Display を表示する"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "リピートをトグル"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "シャッフルをトグル"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "現在の曲の再生後に停止する"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "プレイヤウィンドウを表示する"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(なし)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2045,15 +2168,11 @@ msgstr ""
 "\n"
 "本当によろしいですか?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "マウスボタンの割り当て"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "グローバルホットキープラグインの設定"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2061,23 +2180,27 @@ msgstr ""
 "テキストフィールド内でキーコンビネーションを押してください。\n"
 "マウスボタンを組み合わせることもできます。"
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "ホットキー:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>動作:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>キーバインド:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "追加 (_A)"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "グローバルホットキー"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2103,60 +2226,56 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "グローバルホットキー"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK 出力"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "有効なすべての jack ポートに接続する"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "出力ポートに自動接続する"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "出力ポートにのみ接続する"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "%d 個の JACK 出力ポートが見つかりましたが、 %d 個が必要です。"
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "ポートに接続しない"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "JACK ポート %s への接続に失敗"
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "接続モード:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK は、浮動小数点のオーディオにしか対応していないのです。Audacious のオー"
+"ディオ出力の設定で、ビット深度を浮動小数点に変更する必要があります。"
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "デバッグ出力を有効にする"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "JACKサーバへの接続に失敗しました。JACKサーバは本当に動いていますか?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Audacious へのポート by Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK 出力"
+"JACK サーバには%d Hzのサンプリング周波数が必要です。ところが、 Audacious がい"
+"ま再生しているのは %d Hz です。サンプリング周波数コンバータのプラグインを用い"
+"て、出力する周波数を合わせるようにしてください。"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s の設定"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Host の設定"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "モジュールのパス:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2167,25 +2286,25 @@ msgstr ""
 "加した後は、新しいプラグインをスキャンするために、\n"
 "Enter キーを押してください。</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "利用可能なプラグイン:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "有効"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "有効なプラグイン:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "設定:"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2193,48 +2312,15 @@ msgstr ""
 "LADSPA ホスト for Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA ホスト"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC 機能を初期化できません\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC の設定ファイルを読み込めません\n"
-"%s: LIRC のドキュメントをお読みください\n"
-"%s: 正しい設定ファイルの書き方\n"
-"\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: 再接続を試みています...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: 不明なコマンド \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC から切断されました\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: %d 秒毎に再接続を試みます...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC プラグイン"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2251,84 +2337,92 @@ msgid ""
 msgstr ""
 "LIRC リモートコントロールデーモンを用いた、シンプルな Audacious コントロール"
 "プラグイン\n"
-"Adapted for Audacious by:\n"
+"Audacious 用に移植:\n"
 "Tony Vroon <chainsaw at gentoo.org>\n"
 "Joonas Harjumäki <jharjuma at gmail.com>\n"
 "\n"
-"Based on the XMMS LIRC plugin by:\n"
+"派生元: XMMS LIRC プラグイン、作者:\n"
 "Carl van Schaik <carl at leg.uct.ac.za>\n"
 "Christoph Bartelmus <xmms at bartelmus.de>\n"
 "Andrew O. Shadoura <bugzilla at tut.by>\n"
 "\n"
-"For more information about LIRC, see http://lirc.org."
+"LIRC についての詳細は http://lirc.org を参照"
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>接続</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "LIRC サーバーへ再接続する"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "再接続の待機時間:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC プラグイン"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki プラグイン"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "歌詞が見つかりません"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "エラー"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "%s が取得できません"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "エラー"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "%s が解析できません"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "歌詞を検索しています ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "曲のメタデータが見つかりません"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "lyrics.wikia.com に接続しています ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki プラグイン"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki プラグイン (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U プラグイン"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "タクトジェネレータ"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "タクトジェネレータ: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "タクトジェネレータ: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2347,11 +2441,11 @@ msgstr ""
 "tact://77 (77bpmのビートを作る)\n"
 "tact://60*3/4 (3/4 拍子で 60 bpmのビートを作る)"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "タクトジェネレータ"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "チャンネルミキサ"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2359,152 +2453,184 @@ msgstr ""
 "チャンネルミキサプラグイン for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>チャンネルミキサ</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "出力チャンネル:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "チャンネルミキサ"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS プラグイン"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "MMS サーバへの接続エラー"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module Player)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
-msgstr ""
+msgstr "<b>解像度</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>チャンネル</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
-msgstr ""
+msgstr "近傍 (最高速)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
-msgstr ""
+msgstr "リニア (高速)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
-msgstr ""
+msgstr "スプライン曲線 (高品質)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
-msgstr ""
+msgstr "ポリフェーズ (最高品質)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>サンプリングレート</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "レベル:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
-msgstr ""
+msgstr "カットオフ:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>リバーブ</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>バスブースト</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>サラウンド</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>プリアンプ</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
-msgstr ""
+msgstr "オーバーサンプリング"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "ノイズリダクション"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
-msgstr ""
+msgstr "Amiga MODを再生する"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>リピート</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "リピートカウント:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "ずっとリピートするにはリピート回数を-1に設定してください。"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "これらの設定は、Audaciousの再起動後に反映されます。"
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "サラウンド"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 プラグイン"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>高度</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "正確な長さを計算する(遅い)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "サラウンド"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 サーバ"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS プラグイン"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "リダイレクト処理のエラー"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "不明な HTTP エラー"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "URL処理のエラー"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "リダイレクトの過剰な繰返し"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "停止しました"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious は曲を再生していません。"
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "デスクトップ通知"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2523,57 +2649,85 @@ msgid ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
+"デスクトップ通知プラグイン for Audacious\n"
+"Copyright (C) 2010 Maximilian Bogner\n"
+"Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"このプログラムはフリーソフトウェアです。あなたはこれを、フリーソフ トウェア財"
+"団によって発行されたGNU一般公衆利用許諾書(バージョン3か、それ以降のバージョン"
+"のうちどれか)が定める条件の下で再頒布または改変することができます。\n"
+"\n"
+"このプログラムは有用であることを願って頒布されますが、*全くの無保証 *です。商"
+"業可能性の保証や特定目的への適合性は、言外に示されたものも含め、全く存在しま"
+"せん。詳しくはGNU一般公衆利用許諾書をご覧ください。\n"
+"\n"
+"あなたはこのプログラムと共に、GNU一般公衆利用許諾書のコピーを一部受け取ってい"
+"るはずです。もし受け取っていなければ、<http://www.gnu.org/licenses/> をご覧く"
+"ださい。\n"
+"\n"
+"(このGPLの翻訳は非公式なもので、フリーソフトウェアファウンデーションによって"
+"法的効力があると承認されたものではありません。何が許可されているか厳密に確認"
+"するためには、(英語で書かれた)オリジナルのGPLを参照してください。)"
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "再生コントロールを表示する"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "常に通知を表示する"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "デスクトップ通知"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "アルバムの名前も通知に含める"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "表示する"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "一時停止"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "次の曲"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. デフォルトデバイス"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 出力"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 出力"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "デフォルトデバイス"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "オーディオデバイス:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "代替デバイスを使用する:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "セッション間で音量を保存する"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "OSS ソフトウェアのフォーマット変換を有効にする"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 "バーチャルミキシングを防ぐために排他的モード (exclusive mode) を有効にする"
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2587,19 +2741,35 @@ msgstr ""
 "#audacious の人々、特に Tony Vroon および John Lindgren、そしてもちろん、OSS "
 "plugin の前作者に感謝します。"
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 出力"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "プレイリストマネージャ"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "エントリ"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "削除(_R)"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "名前の変更(_A)"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS プレイリスト"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 デコーダ"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio 出力"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2635,11 +2805,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio 出力"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia 出力"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"QtMultimedia Audio 出力プラグイン for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"派生元: SDL 出力プラグイン for Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "処理中 ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "検索"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "フォルダを開く(_O)"
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "フォルダを追加(_A)"
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "ログ検査 (_L)"
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "ファイルを開く"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "ファイルを追加"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "前の曲"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "リピート"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "シャッフル"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt インターフェイス"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "サンプリング周波数コンバータ"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2647,100 +2879,107 @@ msgstr ""
 "サンプルレート変換プラグイン for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "サンプルのスキップ/繰り返し"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "線形補間"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "高速 sinc 補間"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "sinc 補間"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "高品質 sinc 補間"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>変換</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "方法"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "レート:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>レートマッピング</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "レートマッピングを使用する"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "サンプリング周波数コンバータ"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "ユーザー %s の Scrobble に成功しました。"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "アクセス許可がありません"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Audacious に scrobble する許可を与えるには、以下のリンクにアクセスしてくださ"
 "い。"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
-"このウィンドウを開いたまま、もう一度「パーミッションを確認する」をクリックし"
-"てください。\n"
+"このウィンドウを開いたまま、もう一度「認証確認」をクリックしてください。\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2748,34 +2987,38 @@ msgstr ""
 "あなたの Scrobble はコンピュータに保存されています。\\n\n"
 "Audacious は投稿が可能になり次第、すぐに Scrobble を投稿します。"
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "ネットワークに問題があります。"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Last.fmへの接続に問題が発生しました。あとでもう一度試してください。"
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "チェックしています..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
-msgstr "パーミッションを確認する(_H)"
+msgstr "認証確認(_H)"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
-msgstr ""
+msgstr "認証取消(_R)"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Audacious があなたの Last.fm アカウントにトラックを scrobble できるように設定"
 "する必要があります。\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2783,7 +3026,7 @@ msgstr ""
 "Scrobbler プラグインを起動できませんでした。\\n\n"
 "インストール方法に問題がある可能性があります。"
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2797,11 +3040,7 @@ msgstr ""
 "Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\\n\\n\n"
 "プロジェクト開始時に手助けしてくれた John Lindgren に感謝します。\\n\\n\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2809,7 +3048,11 @@ msgstr ""
 "Audacious は Last.fm Scrobbler のバージョンを更新しました。\n"
 "Scrobbler プラグインの設定をご確認ください。"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL 出力"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2817,74 +3060,53 @@ msgstr ""
 "SDL 出力プラグイン for Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL 出力"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "ライブラリ"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "不明なアーティスト"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "不明なアルバム"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\\n\n"
-"アルバム: %s アーティスト: %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d の結果"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d albums"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d の隠し)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d songs"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d songs by %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d 曲"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "(このジャンル中で)"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "アルバム:"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "アーティスト:"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "プレイリストを作成(_C)"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "プレイリストに追加(_A)"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "ライブラリを検索"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2892,679 +3114,771 @@ msgstr ""
 "音楽ライブラリを Audacious へインポートするには、フォルダを選択し、\"再読み込"
 "み\" アイコンをクリックしてください。"
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "お待ちください..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "フォルダを選択"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID "
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>出力</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "チャンネル:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>エミュレーション</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "MOS 8580 をエミュレート (デフォルトは MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "チップ型式を自動選択させない"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "エミュレートフィルタ"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "クロック速度:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "クロック速度を自動選択させない"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>再生時間</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "再生時間の最長を設定"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "曲の長さが不明なときのみ適用する"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "再生時間の最短を設定"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtunes</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "subtunes を有効にする"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "次の時間よりも短いsubtunesを無視する"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>注意</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "無音部の除去"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"無音部除去プラグイン for Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>無音部の除去</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "しきい値:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "ファイルを開く"
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "URLを開く"
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "ライブラリを検索"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "演奏"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "プレイリスト"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "表示"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "サービス"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr "Audacious について"
+msgstr "情報"
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "設定"
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "終了"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "曲の情報"
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "リピート"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "シャッフル"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "次の曲に進まない"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "曲の再生後に停止"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "前の曲"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "A-B リピートをセット"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "A-B リピートをクリア"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "指定した曲にジャンプ"
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "指定した時間へジャンプ"
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "このプレイリストを再生"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "再生/再開"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "新しいプレイリスト"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "プレイリストの名前を変更"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "プレイリストを削除"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "前のプレイリスト"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "次のプレイリスト"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "プレイリストのインポート"
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "プレイリストのエクスポート"
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "プレイリストマネージャ"
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "キューマネージャ"
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "プレイリストの更新"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "プレイリストエディタを表示する"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "イコライザを表示する"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "残り時間を表示する"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "常に最前面に配置する"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "全ワークスペースに配置する"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
-msgstr ""
+msgstr "プレイヤーをたたむ"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
-msgstr ""
+msgstr "プレイリストエディターをたたむ"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
-msgstr ""
+msgstr "イコライザーをたたむ"
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "2倍の大きさで表示"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "URLを追加"
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "ファイルを追加"
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "タイトル"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "ファイル名"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "ファイルパス"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "全て削除"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "キューのクリア"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "利用できないファイルの削除"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "重複エントリの削除"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "選択していないエントリの削除"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "選択したエントリの削除"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "検索と選択"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "選択範囲の反転"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "未選択にする"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "全て選択"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "アルバム"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "トラック番号"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "アーティスト"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "アルバム"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "アルバムアーティスト"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "リリース日"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "トラック番号"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "ジャンル"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "長さ"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "カスタムタイトル"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "プレイリストをランダムにする"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "プレイリストを逆順にする"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "選択範囲のソート"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "プレイリストのソート"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "切り取り"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "コピー"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "貼り付け"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "キュー/アンキュー"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "プリセットの読み込み"
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "自動プリセットの読み込み"
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "デフォルトの読み込み"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "プリセットファイルの読み込み"
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "EQF ファイルの読み込み"
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "プリセットの保存"
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "自動プリセットの保存"
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "デフォルトを保存"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "プリセットファイルを保存"
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "EQF ファイルの保存"
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "プリセットを削除"
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "自動プリセットを削除"
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Winamp プリセットのインポート"
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "ゼロにリセット"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp クラシックインターフェイス"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "保存"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "読み込み"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "プリセットファイルを読込む"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "EQF ファイルをロード"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "プリセットファイルを保存"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "EQF ファイルを保存"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Winamp のプリセットをインポート"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "プリセット"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "プリセットの読み込み"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "自動プリセットの読み込み"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "プリセットの保存"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "自動プリセットの保存"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "プリセットの削除"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "自動プリセットの削除"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "プレイヤ(_P):"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "プレイヤ:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "メインウィンドウで使用するフォントの選択"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "プレイリスト(_P):"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "プレイリスト:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "プレイリストで使用するフォントの選択"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>スキン</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>フォント</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "ビットマップフォントを使用する (ASCII のみ対応)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "曲のタイトルをスクロール"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "曲のタイトルを両方向にスクロールする"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "アナライザ"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "スコープ"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
-msgstr ""
+msgstr "声紋 / VU メーター"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "オフ"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "標準"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "ファイア"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr ""
+msgstr "åž‚ç›´ç·š"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "ライン"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "バー"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "最も遅い"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "遅い"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "中"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "早い"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "最も早い"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "点"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "ç·š"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "ソリッド"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "アイス"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "スムーズ"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>タイプ</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "視覚化タイプ:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>アナライザ</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "ピークを表示"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "色付け:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "スタイル:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
-msgstr ""
+msgstr "降下速度:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
-msgstr ""
+msgstr "ピークの降下速度:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
-msgstr ""
+msgstr "スコープのスタイル:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
-msgstr ""
+msgstr "声紋の色付け:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
-msgstr ""
+msgstr "VU メーターのスタイル:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "一般"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "視覚化"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "プリアンプ"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious イコライザ"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "%d:%-2.2d / %d:%-2.2d へシークする"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "音量: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "バランス: %d%% 左"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "バランス: 中央"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "バランス: %d%% 右"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "オプションメニュー"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "「常に最前面に配置」無効"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "「常に最前面に配置」有効"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "ファイル情報ボックス"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "視覚化"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "リピートポイントAを設定します。"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "リピートポイントBを設定します。"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "リピートポイントがクリアされました。"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "シングルモード"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "プレイリストモード"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "曲の再生後に停止する"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "有効になっているプレイリストのエントリを検索"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "検索"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3575,57 +3889,61 @@ msgstr ""
 "表現が使え、大文字と小文字を区別しません。正規表現の動作がわからない場合は、"
 "検索したい文字をそのまま入力してください。"
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "タイトル: "
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "アルバム名: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "アルバム: "
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "アーティスト: "
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "ファイル名: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "ファイル名:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "検索前に前回の選択をクリアする"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "マッチしたエントリのキューを自動的にトグルする"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "マッチしたエントリで新しいプレイリストを作成する"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious プレイリストエディタ"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d / %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Archived Winamp 2.x スキン"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Unarchived Winamp 2.x スキン"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "ディレクトリ (%s) を作成できませんでした: %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile プラグイン"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3665,83 +3983,72 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile プラグイン"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio 出力"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio 出力プラグインについて"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio 出力プラグイン\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "デバイス (空白の場合はデフォルト)"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "対応していない形式"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "音量を保存し復元:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"オーディオデバイスで対応していない形式が要求されました。\n"
-"\n"
-"sndiod(1) サーバが起動してから、もう一度実行してください。"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio エラー: サポートしていないオーディオ形式 (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio デバイス"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio エラー: sio_open() に失敗"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(空の場合、デフォルトに設定します)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio エラー: sio_setpar() に失敗"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio エラー: sio_start() に失敗"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "楽曲の変更通知"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "新しい曲を再生したときに実行するコマンド"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>シェルに渡されるパラメータはクォートでくくってください。そ"
+"うしない場合、セキュリティ上の危険があります。</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "コマンド:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>コマンド</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "曲の再生が終わったときに実行するコマンド"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "新しい曲の再生時に実行するコマンド:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "プレイリストの最後に到達したときに実行するコマンド"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "曲の終了時に実行するコマンド:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "プレイリストの終了時に実行するコマンド:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"曲のタイトルが変わったときに実行するコマンド (ネットワークストリームのタイト"
-"ルなど)"
+"曲タイトルが替わったときに実行するコマンド (ネットワークストリーミング用):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3755,35 +4062,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"次のフォーマット文字列を使用できます。\n"
-"これらは、コマンドが呼ばれる前に置換されます。\n"
-"ただし、プレイリストの最後の曲の場合、無意味なものもあります\n"
+"次の形式の文字列を、コマンド実行前に評価されるものとして使用することができま"
+"す(この全てがプレイリストの最後のコマンドとして有用であるとは限りません"
+"が):\n"
 "\n"
-"%F: サンプリング周波数 (Hz)\n"
-"%c: チャンネル数\n"
+"%F: 周波数 (ヘルツ)\n"
+"%c: チャネル数\n"
 "%f: ファイル名 (フルパス)\n"
-"%l: 長さ (ms)\n"
+"%l: 長さ (ミリ秒)\n"
 "%n または %s: 曲名\n"
-"%r: ビットレート (bps)\n"
+"%r: レート (bps)\n"
 "%t: プレイリストの位置 (%02d)\n"
-"%p: 再生中か? (1 or 0)\n"
+"%p: 現在再生中かどうか (1 または 0)\n"
 "%a: アーティスト\n"
 "%b: アルバム\n"
-"%T: トラック名"
+"%T: トラックのタイトル"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>シェルに渡されるパラメータはクォートでくくってください。そ"
-"うしない場合、セキュリティ上の危険があります。</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "曲の情報 (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "コマンド"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX リサンプラー"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3791,52 +4094,57 @@ msgid ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
+"SoX リサンプラープラグイン for Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"派生元: サンプリング周波数コンバータプラグイン\n"
+"Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
-msgstr ""
+msgstr "高速"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
-msgstr ""
+msgstr "低品質"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
-msgstr ""
+msgstr "高品質"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
-msgstr ""
+msgstr "最高品質"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
-msgstr ""
+msgstr "品質:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "テンポとピッチ"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>テンポとピッチ</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "テンポ:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "ピッチ:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "テンポとピッチ"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "ステータスアイコン"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "設定 (_T)"
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3851,42 +4159,42 @@ msgstr ""
 "Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
 "Copyright 2010 Michał Lipski <tallica at o2.pl>\n"
 "\n"
-"This plugin provides a status icon, placed in\n"
-"the system tray area of the window manager."
+"このプラグインはステータスアイコンを\n"
+"ウインドウマネージャが定めるシステムトレイ内に表示する"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>マウススクロールアクション</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "音量の変更"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "再生曲の変更"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>その他の設定</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "ポップアップウィンドウを無効にする"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "システムトレイに収納する"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "上にスクロールしたらプレイリストを進める"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "ステータスアイコン"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "エクストラステレオ"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3896,24 +4204,24 @@ msgstr ""
 "\n"
 "By Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>エクストラステレオ</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "エクストラステレオ"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "トーンジェネレータ"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "トーンジェネレータ: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3932,15 +4240,11 @@ msgstr ""
 "例:\n"
 "tone://2000;2005 (2000Hz と 2005Hz のトーンを再生する)"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "トーンジェネレータ"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "ボーカルの除去"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3962,13 +4266,13 @@ msgid ""
 msgstr ""
 "Audacious Ogg Vorbis デコーダ\n"
 "\n"
-"Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+"派生元: Xiph.org Foundation の Ogg Vorbis プラグイン\n"
 "http://www.xiph.org/\n"
 "\n"
-"Original code by:\n"
+"元のコードの作者:\n"
 "Tony Arcieri <bascule at inferno.tusculum.edu>\n"
 "\n"
-"Contributions from:\n"
+"貢献者:\n"
 "Chris Montgomery <monty at xiph.org>\n"
 "Peter Alm <peter at xmms.org>\n"
 "Michael Smith <msmith at labyrinth.edu.au>\n"
@@ -3978,34 +4282,68 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis デコーダ"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "%s の詳細"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"タイトル: %t\n"
+"作者: %a\n"
+"由来: %f\n"
+"トラッカー: %T\n"
+"コメント: %C\n"
+"チップ型式: %c\n"
+"ステレオ: %s\n"
+"ループ: %l\n"
+"チップ周波数: %F\n"
+"プレイヤ周波数: %P\n"
+"å¹´: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX デコーダ"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
-"Sashnov Alexander <sashnov at ngs.ru> による Vortex ファイル形式プレイヤで"
-"す。\\n\n"
-"Roman Sherbakov <v_soft at microfor.ru> の in_vtx.dll を基にしています。\\n\n"
-"Audacious の実装は、Pavel Vymetalek <pvymetalek at seznam.cz> が行いました。"
+"Sashnov Alexander <sashnov at ngs.ru> による Vortex ファイル形式プレイヤです。\n"
+"Roman Sherbakov <v_soft at microfor.ru> の in_vtx.dll を基にしています。\n"
+"Audacious への実装は、Pavel Vymetalek <pvymetalek at seznam.cz> が行いました。"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX デコーダ"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack デコーダ"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "非可逆(ハイブリッド)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "非可逆"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4013,16 +4351,20 @@ msgid ""
 msgstr ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
-"Some of the plugin code was by Miles Egan."
-
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack デコーダ"
+"プラグインのコードの一部は Miles Egan が書いた"
 
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF デコーダ"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF の設定</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "ファイルに記録されている再生時間を無視"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "共有可能な XML プレイリスト (XSPF)"
diff --git a/po/ko.po b/po/ko.po
index 37a5a4b92ff0..7d720f2caca6 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -4,21 +4,21 @@
 #
 # Translators:
 # 		ChoSeongWoo <syn333 at gmail.com>, 2008
-# Darkcircle <darkcircle.0426 at gmail.com>, 2013
-# Darkcircle <darkcircle.0426 at gmail.com>, 2012-2013
+# Seong-ho Cho <darkcircle.0426 at gmail.com>, 2013
+# Seong-ho Cho <darkcircle.0426 at gmail.com>, 2012-2013
 #       Jaegeum Choe <baedaron at hananet.net>, 2001
 #       Man-Yong Lee <yong at linuxkorea.co.kr>, 2000
 #       Sang-Jin Hwang <accel at accellinux.org>, 1999
-# Darkcircle <darkcircle.0426 at gmail.com>, 2012
-# Darkcircle <darkcircle.0426 at gmail.com>, 2012
-# Darkcircle <darkcircle.0426 at gmail.com>, 2012-2014
+# Seong-ho Cho <darkcircle.0426 at gmail.com>, 2012
+# Seong-ho Cho <darkcircle.0426 at gmail.com>, 2012
+# Seong-ho Cho <darkcircle.0426 at gmail.com>, 2012-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-14 15:07+0000\n"
+"Last-Translator: Seong-ho Cho <darkcircle.0426 at gmail.com>\n"
 "Language-Team: Korean (http://www.transifex.com/projects/p/audacious/"
 "language/ko/)\n"
 "Language: ko\n"
@@ -27,40 +27,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "모노"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "스테레오"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "서라운드"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) 디코더"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) 디코더"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib 재생기)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "순차"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib 재생기)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "알림"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "알림 설정..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -70,11 +58,7 @@ msgstr ""
 "\n"
 "초기에 Adam Feakin과 Daniel Stodden이 작성했습니다."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "알림"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -116,7 +100,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -156,7 +140,7 @@ msgstr ""
 "    알람 시간에 이 명령을 실행합니다.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -180,382 +164,371 @@ msgstr ""
 "    상자에 약속을 입력하고 표시하려는\n"
 "    경우 전환 단추를 누르십시오."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "기상 알림입니다."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "오늘 약속은..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "약속 알리미"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "월요일"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "화요일"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "수요일"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "목요일"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "금요일"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "토요일"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "일요일"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "알림 설정"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "확인(_O)"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "취소(_C)"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "시계"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "다음 시간에 알림(기본):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "시"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "다음 시간후 조용히:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "시간"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "분"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "알림을 울릴 날짜를 선택합니다"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "요일"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "기본값"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "일"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "점진적 음량 변화 시간"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "ì´ˆ"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "음량"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "시작"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "끝"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "현재"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "추가 명령"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "활성화"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "재생 목록(선택)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "재생 목록 선택하기"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "옵션"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "이 옵션은 무엇을 의미하나요?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "도움말"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "앨범 표지"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "앨범 아트(Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA 출력"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"오데이셔스용 ALSA 출력 플러그인\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"ALSA 메뉴얼이 충분히 도움이 되지 않았을 때, 코드 참고서가 되어준 ALSA 출력 플"
+"러그인 NG의 저작자인 William Pitcock에게 감사드립니다."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "기본 PCM 장치"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "기본 음량 조절기 장치"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM 장치:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "음량 조절기 장치:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "음량 조절기 요소:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "드레인 행업을 피하며 작업"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI 재생기)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"오데이셔스용 ALSA 출력 플러그인\n"
-"Copyright 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"ALSA 메뉴얼이 충분히 도움이 되지 않았을 때, 코드 참고서가 되어준 ALSA 출력 플"
-"러그인 NG의 저작자인 William Pitcock에게 감사드립니다."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA 출력"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI 재생기)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "기본 게인 값 중복 적용:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "기본 화성 중복 적용:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "기본 리버브 중복 적용:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "켬"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "기본 코러스 중복 적용:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>재생</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "트랜스포스:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "드럼 쉬프트:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>고급</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "미디 파일에서 주석 추출"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "미디 파일에서 가사 추출"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>사운드 폰트</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>신디사이저</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "샘플 주파수:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - 사운드 폰트 파일 선택"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "취소(_C)"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "열기(_O)"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "파일 이름"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "크기(바이트)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "이름:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> 미디 정보 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "형식:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "길이(밀리초):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "트랙 번호:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "가변"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "빠르기(BPM):"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "빠르기(BPM, wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "박자:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> 미디 주석과 가사 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* 이 미디 파일에는 주석이 없습니다 *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* 이 미디 파일에는 가사가 없습니다 *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "닫기(_C)"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr " (잘못된 UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI-Plug ì •ë³´"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"모듈형 MIDI 음악 재생기\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Giacomo Lozito\n"
-"<james at develia.org>가 작성함\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"ALSA API를 좀 더 배우기 위한 alsa-lib 문서와\n"
-"정말 쓸모있는 aplaymidi, amixer라는 좋은 \n"
-"프로그램을 만든 Clemens Ladisch, Jaroslav Kysela\n"
-"\n"
-"괜찮은 미디 키보드 로고를 사용할 수 있게 해준\n"
-"Alfredo Spadafina\n"
-"\n"
-"알파 테스트에 많은 도움을 준 Tony Vroon"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -565,152 +538,154 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"오데이셔스 OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Giacomo Lozito <james at develia.org>가 작성\n"
+"\n"
+"Evan Martin's Ghosd 라이브러리 일부를 기반으로 함:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (화면에 표시)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "사각형"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "모서리가 둥근 사각형"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "오목한 사각형"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "없음"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "재생 시작"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "재생 목록의 항목을 재생할 때 OSD를 시작합니다."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "제목 바꾸기"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"재생할 때 OSD를 시작하면 곡 제목은 바뀌지만 파일 이름은 그대로 입니다. 인터"
-"넷 스트림의 제목을 바꾸어서 보여줄 대부분의 경우에 유용합니다."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "일시 정지 활성화"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "재생을 멈추었을 때 OSD를 시작합니다."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "일시 정지 활성화"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "멈춰진 재생 상태에서 복귀할 때 OSD를 시작합니다."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "위치"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "상대 X 오프셋:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "상대 Y 오프셋:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "최대 OSD 폭:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "다중 모니터 옵션"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD 사용중 표시:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "모든 모니터"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "%i번 모니터 "
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "타이밍(밀리초)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "디스플레이:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "나타내기 시간:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "사라지기 시간:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "글꼴"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "%i번 글꼴:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "섀도우"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "표현 방식"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "색"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "%i번 색:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "트리거 활성화"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "이벤드"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "합성 관리자를 삭제했습니다"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -720,112 +695,112 @@ msgstr ""
 "적어도 하나가 실행중인지 알지 못한다면, 합성 관리자를 활성화 해 주십시오. 그"
 "렇지 않으면 OSD가 제대로 동작하지 않습니다"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "투명도 속이기에 합성 관리자가 필요하지 않습니다"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "투명도"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "투명도 속이기"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "실제 투명도 ( X 합성 확장이 필요합니다 )"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "합성 확장을 불러오지 않았습니다"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "합성 확장을 사용할 수 없습니다"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>오데이셔스 OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "오데이셔스 OSD - 설정"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "시험(_T)"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "설정(_S)"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "위치"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "애니메이션"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "글자"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "장식"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "트리거"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "기타"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 재생 목록"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 재생 목록"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "오데이셔스 재생 목록(audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>색</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "흐림처리 스코프"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "설정 목록:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "피드 수준:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "주파수 잘라내기:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "설정 목록:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "스펙트럼 분석기"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "오디오 CD 플러그인"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -845,171 +820,156 @@ msgstr ""
 "\n"
 "이 프로젝트는 GSoC 2007에서 만들었습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>장치</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "읽기 속도:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "장치 대체:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>메타데이터</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "CD-Text 사용하기"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB 사용하기"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP 대신 HTTP 사용하기"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "서버:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "경로:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "포트:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "오디오 CD 플러그인"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "cdio 하위 시스템을 초기화하는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "잘못된 %s URI 입니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "%d 트랙이 없습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "%d 트랙은 데이터 트랙입니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "오디오 출력을 여는데 실패했습니다."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "오디오 CD 읽는중 오류가 발생했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "오디오 CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "트랙 %d번"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "%s CD 장치를 여는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "오디오를 재생할 수 있는 CD 드라이브가 없습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "열려 있는 CD 드라이브 초기화를 끝내는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "첫번째/마지막 트랙 번호를 검색하는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "%d번 트랙에 대한 시작/끝 LSN을 읽을 수 없습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "cddb 연결을 만드는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "CDDB 서버에 요청하는데 실패했습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "CDDB 서버에 요청하는데 실패했습니다: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "cddb 정보를 읽는데 실패했습니다: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "드라이브가 비어 있습니다."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "지원하지 않는 디스크 형식입니다."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "오디오 CD 메뉴 항목"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD 재생"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "CD 추가"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "오디오 CD 메뉴 항목"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>압축</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "중앙 음량:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "동적 범위:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"오데이셔스용 동적 범위 압축 플러그인\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "동적 범위 압축"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1025,205 +985,224 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "저음:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "고음:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "울림:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "기본 곡 길이:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>리샘플링</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "오디오 리샘플링 활성화"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "리샘플링 주파수:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC 태그의 길이 무시"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "리버브 증가"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "게임 콘솔 음악 디코더"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"곡이 다른 채널 수를 가지고 있어 크로스페이딩에 실패했습니다. 채널 믹서를 사용"
-"하여 동일한 채널 수를 가지도록 곡을 변환할 수 있습니다."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"곡이 다른 샘플 주파수를 가지고 있어 크로스페이딩에 실패했습니다. 샘플 주파수 "
-"변환기를 사용하여 동일한 샘플 주파수를 가지도록 곡을 변환 할 수 있습니다."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"오데이셔스용 교차 페이드 플러그인\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>크로스페이드</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "오버랩:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "크로스페이드"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"곡이 다른 채널 수를 가지고 있어 크로스페이딩에 실패했습니다. 채널 믹서를 사용"
+"하여 동일한 채널 수를 가지도록 곡을 변환할 수 있습니다."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"곡이 다른 샘플 주파수를 가지고 있어 크로스페이딩에 실패했습니다. 샘플 주파수 "
+"변환기를 사용하여 동일한 샘플 주파수를 가지도록 곡을 변환 할 수 있습니다."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>크리스털라이저</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "강도:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "크리스털라이저"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "큐 시트 플러그인"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "파일 삭제"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "%s을(를) 휴지통으로 이동하는 중 오류: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "%s을(를) 삭제하는 중 오류: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "%s을(를) 삭제하는 중 오류: 로컬 파일이 아닙니다."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "선택한 파일을 휴지통으로 이동하시겠습니까?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "휴지통으로 이동"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "선택한 파일을 완전히 삭제하시겠습니까?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "삭제"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "취소"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "파일 삭제"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "선택한 파일 삭제"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>삭제 방식</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "즉시 삭제하는 대신 휴지통으로 이동"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>울림</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "지연:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "반향:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "음량:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"에코 플러그인\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "울림"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg 플러그인"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1239,55 +1218,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg 플러그인"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter 플러그인"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "출력 파일 형식:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "설정하기"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "원본 디렉터리에 저장"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "사용자 정의 디렉터리에 저장"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "출력 파일 폴더:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "폴더 선택하기"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "다음으로부터 파일 이름 가져오기:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "원본 파일 태그"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "원본 파일 이름"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "파일 이름 확장자를 빼지 않기"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "트랙 번호를 파일 이름으로 간주하기"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1316,165 +1295,169 @@ msgstr ""
 "만약 사본이 없다면 자유 소프트웨어 재단에 요청하십시오.\n"
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter 플러그인"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "자동"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "통합 스테레오"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "스테레오"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "모도"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 설정"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "확인(_O)"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "알고리즘 품질:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "출력 샘플 주파수:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "비트전송율 / 압축율:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "비트 전송률/압축율:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "비트전송율(kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "압축율:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "오디오 모드:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "기타:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "엄격한 ISO 규격 강제"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "오류 방지"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "음질"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR 활성화"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "형식:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR 옵션:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "최소 비트레이트(kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "최대 비트레이트(kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "최소 비트전송율을 철저하게 강제"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR 옵션:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "평균 비트전송율(kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR 음질 수준:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR 헤더 기록하지 않기"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "프레임 인자:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "프레임 매개변수:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Copyright로 표시"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "원본으로 표시"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 인자:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr "ID3 매개변수:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "버전 2 태그 추가사항 강제"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "v1 태그만 추가"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "v2 태그만 추가"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "태그"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis 인코더 설정"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "음질 수준(0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC 디코더"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "무손실"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1486,11 +1469,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC 디코더"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1498,11 +1477,19 @@ msgstr ""
 "오데이셔스용 GIO 플러그인\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO 플러그인"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "잘못된 열기 모드"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1522,533 +1509,610 @@ msgstr ""
 "\n"
 "라이선스: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL 스펙트럼 분석기"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "그놈 바로가기"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"그놈 바로 가기 플러그인\n"
-"그놈 바로 가기를 통해 재생기를 제어할 수 있게 해줍니다.\n"
+"그놈 바로가기 플러그인\n"
+"그놈 바로가기로 플레이어를 제어할 수 있습니다.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "그놈 바로 가기"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "항목 번호"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "제목"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "음악가"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "연도"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "앨범"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "앨범 음악가"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "트랙"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "장르"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "대기 목록 위치"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "길이"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "파일 경로"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "파일 이름"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "사용자 정의 제목"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "비트 전송율"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "존재하는 내용"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "표시한 내용"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "검색 도구"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "왼편에 붙이기"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "오른편에 붙이기"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "상단에 붙이기"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "하단에 붙이기"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "떼어내기"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "비활성화"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "검색 도구"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "파일 열기(_O) ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "URL 열기(_U) ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "파일 추가(_A) ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "URL 추가(_R) ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "라이브러리 검색(_L)"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "ì •ë³´(_B) ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "설정(_S)..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "끝내기(_Q)"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "재생(_P)"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "일시정지(_E)"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "정지(_S)"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "이전(_V)"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "다음(_N)"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "반복(_R)"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "뒤섞기(_H)"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "재생 목록 미리 알리지 않음(_O)"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "이 노래 다음 멈춤(_F)"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "곡 정보(_I) ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "시간 건너뛰기(_T) ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "곡 건너뛰기(_J) ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "반복 시점 A 설정(_A)"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "반복 시점 B 설정(_B)"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "반복 시점 지우기(_C)"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "제목순(_T)"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "파일 이름순(_F)"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "파일 경로 순(_P)"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "트랙 번호순(_N)"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "음악가 이름순(_A)"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "앨범 이름순(_B)"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "앨범 작곡가순(_M)"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "출시 일자순(_D)"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "장르순(_G)"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "길이순(_L)"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "파일 경로순(_F)"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "사용자 정의 제목순(_C)"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "순서 뒤집기(_E)"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "임의 순서(_R)"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "이 재생 목록 재생(_P)"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "재생/복귀(_P)"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "새로 고침(_R)"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "ì •ë ¬(_S)"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "선택한 항목 정렬(_L)"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "중복 제거(_D)"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "사용할 수 없는 파일 제거(_U)"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "새 파일(_N)"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "이름 바꾸기(_A)..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "제거(_V)"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "가져오기(_I) ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "내보내기(_E) ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "재생 목록 관리자(_M) ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "대기 목록 관리자(_Q) ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "음량 크게(_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "음량 작게(_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "이퀄라이저(_E)"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "효과(_F)..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "메뉴 표시줄 표시(_M)"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "정보 표시줄 표시(_N)"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "정보 표시줄 시각화 표시(_U)"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "상태 표시줄 표시(_S)"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "남은 시간 표시(_R)"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "시각화(_V)..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "파일(_F)"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "재생(_P)"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "재생 목록(_L)"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "서비스(_S)"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "출력(_O)"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "보기(_V)"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "대기 목록에 넣기/빼기(_Q)"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "음악 포함 폴더 열기(_O)"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "잘라내기(_T)"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "복사(_C)"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "붙여넣기(_P)"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "모두 선택(_A)"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "이름 바꾸기(_R) ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>재생 목록 탭</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "항상 탭 표시"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "항목 갯수 표시"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "닫기 단추 표시"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>재생 목록 내용</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "내용 헤더 표시"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>기타</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "화살표 키로 탐색:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "곡 바뀔 때 스크롤"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK 인터페이스"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - 오데이셔스"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "버퍼링 ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "오데이셔스"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "모노"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "스테레오"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "채널 %d개"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "싱글 모드입니다."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "재생 목록 모드입니다."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "곡 재생 후 멈추는 중입니다."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "이전 트랙"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "재생"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "일시 정지/재개"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "정지"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "다음 트랙"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5초 빨리감기"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5초 되감기"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "음소거"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "음량 증가"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "음량 감소"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "파일로 건너뛰기"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "재생 창 전환"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "화면에 표시 보이기"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "반복 전환"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "임의재생 전환"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "현재 곡 이후 멈춤여부 전환"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "재생 창 복귀"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(없음)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2059,15 +2123,11 @@ msgstr ""
 "\n"
 "계속 진행하시겠습니까?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "마우스 단추 바인딩하기"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "전역 단축키 플러그인 설정"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2075,23 +2135,27 @@ msgstr ""
 "텍스트 필드에서 키 조합을 누르십시오.\n"
 "마우스 단추도 넣을 수 있습니다."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "단축키:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>동작:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>키 바인딩:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "추가(_A)"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "전역 단축키"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2117,60 +2181,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "전역 단축키"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK 출력"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "존재하는 모든 Jack 포트에 연결"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "출력 포트로 자동 연결"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "출력 포트에만 연결"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "어떤 포트에도 연결하지 않음"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "연결 방식:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "디버깅 출력 활성화"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"xmms-jack 기반. by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK 출력"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s 설정"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA 호스트 설정"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "모듈 경로:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2180,25 +2235,25 @@ msgstr ""
 "이 경로를 LADSPA_PATH에서도 찾았습니다.\n"
 "새 플러그인을 검색하려면 새 경로를 추가하고 Enter 키를 누르십시오.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "사용할 수 있는 플러그인:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "활성화"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "활성화한 플러그인:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "설정"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2206,47 +2261,15 @@ msgstr ""
 "오데이셔스용 LADSPA 호스트\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA 호스트"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC 지원을 초기화 할 수 없습니다\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC 설정 파일을 읽을 수 없습니다\n"
-"%s: 적당한 설정 파일을 어떻게 만드는지\n"
-"%s: LIRC 문서를 읽어주십시오\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: 다시 연결 시도 중...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: 알 수 없는 명령 \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC로부터 끊어졌습니다\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: 매 %d 초 후 다시 연결을 시도합니다...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC 플러그인"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2273,73 +2296,81 @@ msgstr ""
 "\n"
 "LIRC에 대한 자세한 내용은, http://lirc.org를 보십시오."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>ì—°ê²°</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "LIRC 서버에 다시 연결"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "다시 연결하기 전에 대기중:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC 플러그인"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki 플러그인"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "가사가 없습니다."
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "오류"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "%s을(를) 가져올 수 없습니다"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "오류"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "%s을(를) 해석할 수 없습니다"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "가사 검색중..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "곡 메타데이터가 빠졌습니다"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "lyrics.wikia.com에 연결 중..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki 플러그인"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U 재생 목록"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Tact 생성기"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Tact 생성기: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Tact 생성기: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2353,11 +2384,11 @@ msgstr ""
 "사용 예) tact://77은 분당 77 비트\n"
 "또는 tact://60*3/4는 3/4 tact에서 분당 60 bpm"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Tact 생성기"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "채널 믹서"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2365,152 +2396,184 @@ msgstr ""
 "오데이셔스용 채널 음량 조절기 플러그인\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>채널 믹서</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "출력 채널:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "채널 믹서"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS 플러그인"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (모듈 재생기)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>레졸루션</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8비트"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16비트"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>채널</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "근접(가장 빠름)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "선형(빠름)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "스플라인(좋음)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "다중 페이스(최상)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>샘플 주파수</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "레벨:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "컷-오프:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>리버브</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>저음 증폭</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>서라운드</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>프리앰프</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "오버샘플링"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "노이즈 감쇄"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Amiga MOD 재생"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>반복</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "반복 횟수:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "계속 반복하려면 반복 횟수를 -1로 설정하십시오."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (모듈 재생기)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "서라운드"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 플러그인"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>고급</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "서라운드"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 서버"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS 플러그인"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "알 수 없는 HTTP 오류"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "URL 해석 오류"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "정지함"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "오데이셔스가 재생중이 아닙니다."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "데스크톱 알림"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2544,55 +2607,64 @@ msgstr ""
 "이 프로그램과 함께 GNU 일반 공중 사용 허가서 사본을 받아야 합니다. 만약 사본"
 "이 없다면 <http://www.gnu.org/licenses/> 링크를 참조하십시오."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "재생 컨트롤 표시"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "항상 알림 표시"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "데스크톱 알림"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "보이기"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "일시 정지"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "다음"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. 기본 장치"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 출력"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 출력"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "기본 장치"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "오디오 장치:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "대체 장치 사용:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "각 세션의 볼륨을 저장합니다."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "OSS 소프트웨어가 만드는 형 변환을 활성화 합니다."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "가상 믹싱을 막는 베타적 모드를 활성화 합니다."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2606,19 +2678,35 @@ msgstr ""
 "#audacious 채널 사람, 특히 Tony Vroon, John Lindgren, 이전에 OSS 플러그인을 "
 "만든 저작자분께 감사드리고 싶습니다."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 출력"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "재생 목록 관리자"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "항목"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "제거(_R)"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "이름 바꾸기(_A)"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS 재생 목록"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 디코더"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio 출력"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2651,11 +2739,73 @@ msgstr ""
 "만약 사본이 없다면 자유 소프트웨어 재단에 요청하십시오.\n"
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio 출력"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia 출력"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"오데이셔스용 QtMultimedia 음성 출력 플러그인\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"오데이셔스용 SDL 출력 플러그인 기반임\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "동작중 ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "검색"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "폴더 열기(_O)..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "폴더 추가(_A)..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "로그 감시기(_L)..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "파일 열기"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "파일 추가"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "이전"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "반복"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "뒤섞기"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt 인터페이스"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "샘플 주파수 변환기"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2663,97 +2813,105 @@ msgstr ""
 "오데이셔스용 샘플 주파수 변환 플러그인\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "샘플 건너뛰기/반복하기"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "선형 보간"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "빠른 sinc함수 보간"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "중간 sinc함수 보간"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "최상의 sinc함수 보간"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>변환</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "방식:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "주파수:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>주파수 매핑</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "주파수 매핑 사용하기"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "샘플 주파수 변환기"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "네. %s 사용자의 스크로블링을 진행합니다"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "권한이 거부되었습니다"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "재생 항목을 오데이셔스에서 스크롤 하도록 하려면 다음 연결을 방문하십시오:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "이 창을 연 상태로 다시 '권한 확인'을 누르십시오.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2761,32 +2919,36 @@ msgstr ""
 "걱정하지 마십시오. 스크로블을 컴퓨터에 저장했습니다.\n"
 "오데이셔스가 동작할 수 있는대로 바로 제출합니다."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "네트워크에 문제가 있습니다."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Last.fm에 연결하는데 문제가 있습니다. 다시 시도해 주십시오."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "확인중..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "권한 확인(_H)"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "권한 취소(_R)"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "오데이셔스가 Last.fm 계정에 트랙을 추출할 수 있게 해야 합니다.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "스크로블러 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2794,7 +2956,7 @@ msgstr ""
 "스크로블러 플러그인을 시작할 수 없습니다.\n"
 "설치에 문제가 있는 것 같습니다."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2811,11 +2973,7 @@ msgstr ""
 "이 프로젝트를 시작하는데 도움을 준 John Lindgren에게 감사드립니다.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "스크로블러 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2823,7 +2981,11 @@ msgstr ""
 "Audacious가 이제부터 Last.fm 스크로블러 개선 버전을 사용중입니다.⏎\n"
 "스크로블러 플러그인의 기본 설정을 확인하십시오."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL 출력"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2831,74 +2993,53 @@ msgstr ""
 "오데이셔스용 SDL 출력 플러그인\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL 출력"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "라이브러리"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "알 수 없는 음악가"
+#: src/search-tool/search-tool.cc:394
+#, c-format
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "결과 %d개"
 
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "알 수 없는 앨범"
+#: src/search-tool/search-tool.cc:400
+#, c-format
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(숨긴 항목 %d개)"
 
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "노래 %d곡"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ": 이 장르에 해당"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
 msgstr ""
-"%3$s의\n"
-"%2$s에 있는 %1$s"
 
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "앨범 %d개"
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, 곡 %d개"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%1$s\n"
-"%3$s의 곡 %2$d개\t"
-
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "재생 목록 만들기(_C)"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "재생 목록 추가하기(_A)"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "라이브러리 검색"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2906,679 +3047,769 @@ msgstr ""
 "음악 라이브러리를 오데이셔스로 가져오려면 폴더를 선택하고 \"새로고침\"아이콘"
 "을 누르십시오."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "기다려 주십시오 ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "폴더 선택"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID 재생기"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>출력</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "채널:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>에뮬레이션</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "MOS 8580 에뮬레이션(기본: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "칩 모델 자동으로 선택하지 말 것"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "필터 에뮬레이션"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "클록 속도:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "클록 속도 자동으로 선택하지 말 것"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>재생 시간</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "최대 재생 시간 설정:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "곡 길이를 알 수 없을때만 사용"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "최소 재생 시간 설정:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "파일 열기..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "URL 열기..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "라이브러리 검색"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "재생"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "재생 목록"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "보기"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "서비스"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "ì •ë³´..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "설정..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "끝내기"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "곡 정보..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "반복"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "뒤섞기"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "이전 재생목록이 없습니다"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "이 곡 다음 멈춤"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "이전"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "A-B 반복 설정"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "A-B 반복 지우기"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "지정 곡으로 건너뛰기..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "지정 시간으로 건너뛰기..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "이 재생 목록 재생"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "재생/재개"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "새 재생 목록"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "재생 목록 제거..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "재생 목록 제거"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "이전 재생 목록"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "다음 재생 목록"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "재생 목록 가져오기..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "재생 목록 내보내기..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "재생 목록 관리자..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "큐 관리자..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "재생 목록 새로 고침"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "재생 목록 편집기 표시"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "이퀄라이저 표시"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "남은 시간 표시"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "항상 위"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "모든 작업 공간에 표시"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "재생 프로그램 말아 올리기"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "재생 목록 편집기 말아 올리기"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "이퀄라이저 말아 올리기"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "두배 길이"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "URL 추가..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "파일 추가..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "제목별"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "파일 이름별"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "파일 경로순"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "모두 제거"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "대기 목록 지우기"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "사용할 수 없는 파일 제거"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "복제본 제거"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "선택하지 않은 항목 제거"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "선택한 항목 제거"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "검색하고 선택"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "선택 반전"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "선택하지 않음"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "모두 선택"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "앨범 제목순"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "트랙 번호순"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "음악가순"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "앨범 제목순"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "앨범 음악가별"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "출시일자순"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "트랙 번호순"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "장르별"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "길이별"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "지정 제목별"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "목록 순서 뒤섞기"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "목록 순서 뒤집기"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "선택한 항목 정렬"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "목록 정렬"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "잘라내기"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "복사"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "붙여넣기"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "큐에 넣기/큐에서 빼기"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "설정 목록 불러오기..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "자동 설정 목록 불러오기..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "기본 설정 불러오기"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "설정 목록 파일 불러오기..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "EQF 파일 불러오기..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "설정 목록 저장..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "자동 설정 목록 저장..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "기본 설정 저장"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "설정 목록 파일 저장..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "EQF 파일 저장..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "설정 목록 삭제..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "자동 설정 목록 삭제..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "윈앰프 설정 목록 가져오기..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "0 값으로 초기화"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp 클래식 인터페이스"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "저장"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "불러오기"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "설정 목록 파일 불러오기"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "EQF 파일 불러오기"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "설정 목록 파일 저장"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "EQF 파일 저장"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "윈앰프 설정 목록 불러오기"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "설정 목록"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "설정 목록 불러오기"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "자동 설정 목록 불러오기"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "설정 목록 저장"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "자동 설정 목록 저장"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "설정 목록 삭제"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "자동 설정 목록 삭제"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "재생기(_P):"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "연주자:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "주 재생기 창 글꼴 선택:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "재생 목록(_P):"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "재생목록:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "재생 목록 글꼴 선택:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>스킨</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>글꼴</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "비트맵 글꼴 사용(아스키 전용 지원)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "곡 제목 스크롤"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "양방향으로 곡 제목 스크롤"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "분석기"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "표시기"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "보이스출력 / VU 메터"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "끄기"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "보통"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "불"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "수평선"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "ì„ "
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "막대"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "가장 느리게"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "느리게"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "중간"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "빠르게"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "가장 빠르게"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "점"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "ì„ "
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "ë©´"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "얼음"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "부드럽게"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>방식</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "시각화 방식:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>분석 프로그램</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "피크 표시"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "색상 적용:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "방식:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "폴 오프:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "최대 폴 오프:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "스코프 모양새:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "보이스 출력 색상 적용:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU 메터 모양새:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "일반"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "시각화"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "프리앰프"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "오데이셔스 이퀄라이저"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "%d 탐색:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "음량: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "균형: %d%% 왼쪽"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "균형: 가운데"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "균형: %d%% 오른쪽"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "옵션 메뉴"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "'항상 위' 비활성화"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "'항상 위' 활성화"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "파일 정보 상자"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "A 반복 시점을 설정했습니다."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "B 반복 시점을 설정했습니다."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "반복 시점을 지웠습니다."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "싱글 모드입니다."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "재생 목록 모드입니다."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "곡 재생 후 멈추는 중입니다."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "활성 재생 목록에서 항목 검색"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "검색"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3589,57 +3820,61 @@ msgstr ""
 "규표현식 문법을 사용합니다. 정규표현식이 어떻게 동작하는지 모르신다면 검색할 "
 "문장 일부를 넣으시면 됩니다."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "제목:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "앨범:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "음악가:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "파일 이름:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "검색하기 전에 이전 선택항목 지우기"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "일치하는 항목에 대해 자동으로 대기 목록을 전환하기"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "일치하는 항목에 대해 새 재생 목록 만들기"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "오데이셔스 재생 목록 편집기"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%1$s (%3$d중 %2$d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "압축한 Winamp 2.x 스킨"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "압축하지 않은 Winamp 2.x 스킨"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "(%s) 디렉터리를 만들 수 없습니다: %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile 플러그인"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3678,81 +3913,71 @@ msgstr ""
 "이 없다면 자유 소프트웨어 재단에 요청하십시오. 51 Franklin Street, Fifth "
 "Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile 플러그인"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio 출력 플러그인 정보"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio 출력 플러그인\n"
-"\n"
-"Thomas Pfaff <tpfaff at tp76.info>가 작성하였습니다\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "지원하지 않는 형식"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"오디오 장치가 지원하지 않는 형식을 요청했습니다.\n"
-"\n"
-"sndiod(1) 서버를 실행하고 다시 시도하십시오."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio 장치"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(빈 값은 기본 값을 의미)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "확인"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "곡 바꾸기"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "오데이셔스가 새 곡 재생을 시작할 때 실행할 명령입니다."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>쉘에 전달하는 인자는 따옴표로 감싸야 합니다. 그렇게 하지 "
+"않으면 보안 문제가 생깁니다.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "명령:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "곡의 끝 부분에 다다랐을때 실행할 명령입니다."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "재생 목록의 끝에 도달했을 때 실행할 명령입니다."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "곡의 제목(예: 네트워크 스트림 제목)을 바꿀 때 실행할 명령입니다."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3766,35 +3991,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"명령을 호출하기 전에 대체할 다음의 형식 문자열을\n"
-"사용할 수 있습니다\n"
-"(재생 목록 마지막 시점의 명령으로 다 쓸모 있는것은 아닙니다):\n"
-"\n"
-"%F: 주파수(Hz 단위)\n"
-"%c: 채널 번호\n"
-"%f: 파일 이름(전체 경로)\n"
-"%l: 곡 길이(밀리초 단위)\n"
-"%n or %s: 곡 이름\n"
-"%r: 비트전송율(bps 단위)\n"
-"%t: 재생 목록 위치(%02d)\n"
-"%p: 현재 재생중 여부(1 or 0)\n"
-"%a: 음악가\n"
-"%b: 앨범\n"
-"%T: 트랙 제목"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>쉘에 전달하는 인자는 따옴표로 감싸야 합니다. 그렇게 하지 "
-"않으면 보안 문제가 생깁니다.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "명령"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX 리샘플러"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3808,51 +4014,51 @@ msgstr ""
 "샘플 주파수 변환 플러그인을 기반으로 하였습니다:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "빠름"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "낮음"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "높음"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "매우 높음"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "음질:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX 리샘플러"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "속도와 피치"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>속도와 피치</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "속도:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "피치:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "속도와 피치"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "상태 아이콘"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "설정(_T)..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3870,39 +4076,39 @@ msgstr ""
 "이 플러그인은 창 관리자의 시스템 표시줄 영역에\n"
 "뜨는 상태 아이콘을 제공합니다."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>마우스 스크롤 동작</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "음량 조절하기"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "재생중인 곡 바꾸기"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>기타 설정</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "풍선 도움말 창 비활성화"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "시스템 트레이로 전환"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "재생목록을 위로 스크롤 할 때 미리 알림"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "상태 아이콘"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "엑스트라 스테레오"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3912,24 +4118,24 @@ msgstr ""
 "\n"
 "By Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>엑스트라 스테레오</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "엑스트라 스테레오"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "톤 생성기"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "톤 생성기:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3944,15 +4150,11 @@ msgstr ""
 "frequency3;...\n"
 "사용 예) tone://2000;2005는 2000 Hz 톤과 a 2005 Hz 톤으로 재생합니다."
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "톤 생성기"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "육성 제거"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3990,11 +4192,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis "
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX 디코더"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4004,19 +4230,19 @@ msgstr ""
 "Roman Sherbakov <v_soft at microfor.ru>의 in_vtx.dll을 기반으로 함\n"
 "Pavel Vymetalek <pvymetalek at seznam.cz>이 오데이셔스 플러그인 제작"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX 디코더"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack 디코더"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "손실(혼성)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "손실"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4026,14 +4252,18 @@ msgstr ""
 "\n"
 "플러그인 코드 일부는 Miles Egan이 작성했습니다."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack 디코더"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF 디코더"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML 공유 가능 재생 목록(XSPF)"
diff --git a/po/ky.po b/po/ky.po
index 276e9a906368..2dd609af38f2 100644
--- a/po/ky.po
+++ b/po/ky.po
@@ -7,11 +7,11 @@
 # chingis, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Kirgyz (http://www.transifex.com/projects/p/audacious/"
 "language/ky/)\n"
 "Language: ky\n"
@@ -20,51 +20,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "моно"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стерео"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "көлөмдүү тыбыш"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib ойноткучу)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib ойноткучу)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Ойготкуч саат"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Ойготкуч саат"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -87,7 +71,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -109,7 +93,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -123,360 +107,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr ""
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Эске салуу"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Дүйшөмбү"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Шейшемби"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Шаршемби"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Бейшемби"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Жума"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Ишемби"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Жекшемби"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Ойготкуч сааттын ырастоолору"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Убакыт"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr ""
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "с"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr ""
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "саат"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "мүнөт"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr ""
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Күн"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Жарыяланбас"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Күндөр"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Басаңчалоо"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунда"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Катуулук"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr ""
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Аяктоо"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Кезектеги"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Кошумча команда"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "күйгүзүү"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr ""
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Ойнотуу тизмесин тандаңыз"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опциялар"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr ""
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Жардам"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Альбом тышы"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA чыгышы"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Жарыяланбас PCM орнотмосу"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Жарыяланбас микшер орнотмосу"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM орнотмосу:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Микшер орнотмосу:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Микшер элементи:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA чыгышы"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Гц"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Файл аты"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Өлчөм (байт)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Аты:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI маалыматы </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Формат:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Узундук (мс):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "өзгөрмө"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Time Div:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI комментарийлер жана сөздөрү </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Жабуу"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (туура эмес UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI-Plug жөнүндө"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -487,261 +477,258 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Тик бурчтук"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Тоголоктолгон тик бурчтук"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Чуңкурайган тик бурчтук"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Жок"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Ойнотуунун башы"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Атын өзгөртүү"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Турган жери"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Шрифттер"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Көлөкө"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Түстөр"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Окуя"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
 "manager otherwise the OSD won't work properly"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Тунуктук"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Орун"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анимация"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Стиль"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr ""
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 ойнотуу тизмелери"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious ойнотуу тизмелери (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Түс</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Күңүрт диапазон"
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr ""
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "Пресеттер:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Спектр талдагычы"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Аудио CD плагини"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -753,169 +740,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Орнотмо</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Окуу ылдамдыгы:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метамаалымат</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "CD-Text колдонуу"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB колдонуу"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Жол:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Порт:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Аудио CD плагини"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Аудио чыгышын ачуу оңунан чыккан жок."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Аудио CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "%s CD орнотмосун ачуу оңунан чыккан жок."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr ""
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD ойнотуу"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "CD кошуу"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Кысылыш</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Борбор катуулугу:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамикалык диапазон:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -925,195 +899,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Бас:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr ""
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Жарыяланбас ыр узундугу:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr ""
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr ""
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Гц"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr ""
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr ""
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr ""
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристализатор</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Интенсивдүүлүк:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристализатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Өчүрүү"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Айнуу"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Жаңырык</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Кечигүү:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "мс"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Кербайланыш:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Катуулук:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Эхо"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg плагини"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1123,55 +1122,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg плагини"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Чыгыш файл форматы:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Ырастоо"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr ""
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Тапшырылма каталогго сактоо"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Чыгыш файл каталогу:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Каталогду тандоо"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
 msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
 msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
 msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1189,165 +1188,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Автоматтуу"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr ""
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr ""
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Алгоритм сапаты:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Чыгыш жыштыгы:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Гц)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Битрейт (кбит/с):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr ""
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Аудио режими:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Каталардан коргоо"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Сапат"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR күйгүзүү"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Түр:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR параметрлери:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Төмөнчек битрейти (кбит/с):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Жогорчек битрейти (кбит/с):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr ""
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR параметрлери:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Орточо битрейт (кбит/с):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR сапат деңгээли:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
 msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Кадр параметрлери:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Автордук укук менен корголгон деп белгилөө"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Оригинал деп белгилөө"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 параметрлери:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr ""
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Тегдер"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis кодегин ырастоо"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Сапат деңгээли (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC декодери"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1355,21 +1358,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC декодери"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO плагини"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1381,529 +1388,606 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Жазуунун номери"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Ат"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Аткаруучу"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Жыл"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Альбом"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Жол"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Кезектеги орду"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Узундук"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Файлга жол"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Файл аты"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Тапшырылма ат"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Битрейт"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Издөө аспабы"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr ""
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr ""
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Өчүрүү"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Издөө аспабы"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Файлдарды _ачуу ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "_URL ачуу ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Файлдарды _кошуу ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL кошуу ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "Программа _жөнүндө ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Чыгуу"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Ойнотуу"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Пауза"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Токтотуу"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Мурунку"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Кийинки"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Кайталоо"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Иретсиз"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Тизмеден жылдырбоо"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Ыр _маалыматы ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_Убакытка өтүү ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Ырга өтүү ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "_Ат боюнча"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Трек _номери боюнча"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "_Аткаруучу боюнча"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Чыгаруу _күнү боюнча"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "_Файлдын турган жери боюнча"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "_Тапшырылма ат боюнча"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Тескери тартип менен"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Аралаш тартип менен"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Ушул ойнотуу тизмесин _ойнотуу"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Жаңылоо"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Сорттоо"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "_Кол жеткис файлдарды өчүрүү"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Жаңы"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Атын _өзгөртүү..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Импорт ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Экспорт ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Ойнотуу тизмесинин _менеджери..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Кезек менеджери ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Катуулукту _көбөйтүү"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Катуулукту _азайтуу"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Эквалайзер"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Меню панелин көрсөтүү"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "М_аалымат панелин көрсөтүү"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_Абал панелин көрсөтүү"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Файл"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Ойнотуу"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Тизме"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Кызматтар"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Чыгыш"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "Кө_рүнүш"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Кезекке коюу/койбоо"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Ке_сүү"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Көчүрүү"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "К_оюу"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_Баарын тандоо"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Атын өзгөртүү ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK интерфейс"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Буферизация ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
-#, c-format
-msgid "%d channel"
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "моно"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стерео"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
+#, c-format
+msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d канал"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d кбит/с"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Бириндеген режим."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Ойнотуу тизмеси режими."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Ырдан кийин токтотуу."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Мурунку жолчо"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Ойнотуу"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Пауза/Улантуу"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Токтотуу"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Кийинки жолчо"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Үнүн басуу"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Файлга өтүү"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr ""
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(жок)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1911,37 +1995,37 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr ""
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr ""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Ысык клавишалар:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Аракет:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Клавиштик айкалыш:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1956,124 +2040,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK чыгышы"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK чыгышы"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Ырастоолор"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr ""
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr ""
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Кол жетердик плагиндер:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Күйгүзүү"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Күйгүзүлгөн плагиндер:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ырастоолор"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA түйүнү"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC плагини"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2089,73 +2139,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Туташтыруу</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr ""
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC плагини"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki плагини"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Ыр тексти кол жеткис"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Ката"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Ката"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Ыр текстин издөө ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Ыр метамаалыматтары жок болуу"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki плагини"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U ойнотуу тизмелери"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Такт генератору"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr ""
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr ""
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2164,162 +2222,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Такт генератору"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Канал микшери"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Канал микшери</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Чыгыш каналдары:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Канал микшери"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS плагини"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (модуль ойноткучу)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Чечим</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-бит"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-бит"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Каналдар</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 кГц"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 кГц"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 кГц"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 кГц"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Деңгээли:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Кайталоо</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Кайталоо саны:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (модуль ойноткучу)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Көлөмдүү тыбыш"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 плагини"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Көлөмдүү тыбыш"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 сервери"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS плагини"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Токтолгон"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious ойнотуп жаткан жок."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2339,55 +2429,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Пауза"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Кийинки"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Жарыяланбас орнотмосу"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 чыгышы"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Үн орнотмосу:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr ""
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2396,19 +2495,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 чыгышы"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS ойнотуу тизмелери"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 чыгышы"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio чыгышы"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2428,143 +2543,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio чыгышы"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Мурунку"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Кайталоо"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Иретсиз"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Сызыктык интерполяция"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Конверсия</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Ыкма:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Жыштык:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Жыштыктар картасы</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Жыштык картасын колдонуу"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 кГц:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 кГц:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 кГц:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 кГц:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 кГц:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 кГц:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 кГц:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Тармак көйгөйү."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Текшерилүүдө..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2575,84 +2759,69 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL чыгышы"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL чыгышы"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Абазкана"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Белгисиз аткаруучу"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Белгисиз альбом"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d альбом"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "Ойнотуу тизмесин _жаратуу"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "Ойнотуу тизмесине _кошуу"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Издөө абазканасы"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2660,679 +2829,769 @@ msgstr ""
 "Audacious абазканасына музыкаңызды импорт кылыш үчүн, биринчи каталогду "
 "тандаңыз, анан \"жаңыртуу\" деген иконканы басыңыз."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Каталогду тандаңыз"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Ойнотуу"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Ойнотуу тизмеси"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Көрүнүш"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Кайталоо"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Иретсиз"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr ""
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Мурунку"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Жаңы ойнотуу тизмеси"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Ойнотуу тизмесинин редакторун көрсөтүү"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "_Эквалайзерди көрсөтүү"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Дайыма үстүндө"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Ат боюнча"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Файл аты боюнча"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Баарын өчүрүү"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Кезекти тазалоо"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Кол жеткис файлдарды өчүрүү"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Дубликаттарды өчүрүү"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Тандалбагандарды өчүрүү"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Тандалгандарды өчүрүү"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Издеп анан тандоо"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Тандалганды тескерилетүү"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Тандоону алуу"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Баарын тандоо"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Альбом боюнча"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Жолчо номерлери боюнча"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Аткаруучу боюнча"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Альбом боюнча"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Жолчо номерлери боюнча"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Тизмени аралаштыруу"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Тизмени тескерилетүү"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Тандалгандарды сорттоо"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Тизмени сорттоо"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Кесүү"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Көчүрүү"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Коюу"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp классикалык интерфейси"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Сактоо"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Жүктөө"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Пресетти жүктөө"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Авто-пресетти жүктөө"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Пресетти сактоо"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Авто-пресетти сактоо"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Пресетти өчүрүү"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Авто-пресетти өчүрүү"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Ойноткуч:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Ойноткучтун негизги терезесинин шрифтин тандаңыз:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Ойнотуу тизмеси:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Ойнотуу тизмесинин шрифтин тандоо:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Ыр атын эки багытты карата айлантуу"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Анализатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Осциллограмма"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Өч."
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Жөнөкөй"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "От"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Сызыктар"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Тилкелер"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Жайыраак"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Жай"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Орточо"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Бат"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Батыраак"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Муз"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Тегиз"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Негизги"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Визуалдаштыруу"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Күчөтүү"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 кГц"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious эквалайзери"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr ""
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Катуулук: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Балансы: %d%% сол"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr ""
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Балансы: %d%% оң"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Параметрлер менюсу"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "\"Дайыма үстүндө\"нү өчүрүү"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "\"Дайыма үстүндө\"нү күйгүзүү"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Файл жөнүндө маалымат"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Бириндеген режим."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Ойнотуу тизмеси режими."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Ырдан кийин токтотуу."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Активдүү ойнотуу тизмесинен жазууларды издөө"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3340,57 +3599,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Ат: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Альбом: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Аткаруучу: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Файл аты: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr ""
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious ойнотуу тизмесинин редактору"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d / %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Архивделген Winamp 2.x темасы"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Архивделбеген Winamp 2.x темасы"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile плагини"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3412,75 +3675,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile плагини"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio чыгыш плагини жөнүндө"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Колдолбогон формат"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio орнотмосу"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Ыр которуу"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
 msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Команда:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3495,17 +3752,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Командалар"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3514,51 +3769,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Сапаты:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Ылдамдык жана бийиктик"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Ылдамдык жана бийиктик</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Ылдамдык:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Бийиктик:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Ылдамдык жана бийиктик"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Статус иконкасы"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3569,63 +3824,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Чычканды айлантуу аракети</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Катуулукту өзгөртүү"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Ойнотулуп жаткан ырды алмаштыруу"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Башка ырастоолор</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Калкыма терезени өчүрүү"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Системалык трейге жабуу"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Статус иконкасы"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Экстра стерео"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Экстра стерео</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Экстра стерео"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Тон генератору"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Гц"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Тон генератору: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3634,15 +3889,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Тон генератору"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr ""
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3663,44 +3914,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis декодери"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX декодери"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX декодери"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack декодери"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack декодери"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF декодери"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/lt.po b/po/lt.po
index e3033f4df6ed..3270d896587d 100644
--- a/po/lt.po
+++ b/po/lt.po
@@ -10,11 +10,11 @@
 # gymka <gymka at mail.ru>, 2011
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Lithuanian (http://www.transifex.com/projects/p/audacious/"
 "language/lt/)\n"
 "Language: lt\n"
@@ -24,40 +24,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
 "%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "erdvinis"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) Dekoderis"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) Dekoderis"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib grotuvas)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "nuoseklus"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib grotuvas)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Žadintuvas"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Nustatyti perspÄ—jimÄ…..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -67,11 +55,7 @@ msgstr ""
 "\n"
 "Originaliai parašė Adam Feakin ir Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Žadintuvas"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -113,7 +97,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -150,7 +134,7 @@ msgstr ""
 "atÄ—jus signalo laikui paleisti Å¡iÄ… komandÄ….\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -173,381 +157,371 @@ msgstr ""
 "    Įrašykite priminimą ir perjunkite mygtuką \n"
 "    jei norite jog jis būtų rodomas."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Tai pabudimo skambutis."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Å iandienos priminimas..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Priminimas"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Pirmadienis"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Antradienis"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Trečiadienis"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Ketvirtadienis"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Penktadienis"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Šeštadienis"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Sekmadienis"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Žadintuvo nustatymai"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_Gerai"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Atsisakyti"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Laikas"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Žadinti (numatyta):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "v"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Nutildyti po:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "valandos"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutÄ—s"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Pasirinkite dienas kuriomis žadinti"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Diena"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Numatytosios"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dienos"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "IÅ¡blukimas"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekundÄ—s"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Garsas"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "PradÄ—ti nuo"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Baigti"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Dabartinis"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Papildoma komanda"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "Įjungti"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Grojaraštis (nebūtina)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Pasirinkite grojaraštį"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Pasirinktys"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Ką šios pasirinktys reiškia?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Žinynas"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Albumo apipavadalinimas"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA išvestis"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA išvesties įskiepis skirtas Audacious\n"
+"AutorinÄ—s teisÄ—s 2009-2012 John Lindgren\n"
+"\n"
+"Dėkoju William Pitcock, „ALSA Output Plugin NG“ autoriui, jo kodas buvo kaip "
+"pagrindas kai ALSA žinynas negelbėdavo."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Numatytasis PCM įrenginys"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Numatytasis mikšerio įrenginys"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM įrenginys:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Mikšerio įrenginys:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Mikšerio elementas:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Apeiti sausÄ… pakibimÄ…"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI grotuvas)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"ALSA išvesties įskiepis skirtas Audacious\n"
-"AutorinÄ—s teisÄ—s 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Dėkoju William Pitcock, „ALSA Output Plugin NG“ autoriui, jo kodas buvo kaip "
-"pagrindas kai ALSA žinynas negelbėdavo."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA išvestis"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI grotuvas)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Perrašyti numatytąjį garsą:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Perrašyti numatytąją polifoniją:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Perrašyti numatytąjį aidą:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Įjungta"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Perrašyti numatytąjį chorą:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Atkūrimas</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "PerkÄ—limas:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Būgnų poslinkis:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>SudÄ—tingesni</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Išgauti komentarus iš MIDI failo"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Gauti žodžius iš MIDI failo"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Sintezatorius</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "Diskretizacijos dažnis:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - pasirinkite SoundFont failÄ…"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Atsisakyti"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Atverti"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Failo vardas"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Bylos vardas"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Dydis (bitais)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Pavadinimas:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Info </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formatas:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "TrukmÄ— (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Takelių:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "kintamasis"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Laiko div:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI komentarai ir žodžiai</span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* Šiame MIDI faile nėra komentarų *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* Šiame MIDI faile nėra žodžių *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Uždaryti"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (neteisingas UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Apie AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"moduliarinis MIDI muzikos grotuvas \n"
-"http://www.develia.org/projects.php?p=amidiplug sukūrė \n"
-"Giacomo Lozito <james at develia.org> \n"
-"\n"
-"ypatinga padÄ—ka...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela \n"
-"už jų puikias programas aplaymidi ir amixer; šios programos tikrai naudingos "
-"susipažįstant su ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"už gražų midi klaviatūros logotipą\n"
-"\n"
-"Tony Vroon\n"
-"už pagalbą testuojan alfa"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -565,152 +539,146 @@ msgstr ""
 "Paremta Evan Martin Ghosd biblioteka:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Rodymas ekrane)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Stačiakampis"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Apvalus stačiakampis"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Įgaubtas stačiakampis"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Joks"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Atkūrimo pradžia"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Sužadina OSD kai grojaraščio elementas grojamas."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Pavadinimo keitimas"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Sužadina OSD kai, atkūrimo metu, dainos pavadinimas pasikeičia, bet bylos "
-"vardas lieka tas pats. Å ita pasirinktis naudingiausia atvaizduojant "
-"interneto srauto dainos pavadinimo pokyčius. "
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "PauzÄ—"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Sužadina OSD kai atkūrimas sustabdomas"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pauzė išjungiama"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Sužadina OSD kai atkūrimas atkuriamas po pauzės."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "PadÄ—tis"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Reliatyvus X poslinkis:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Reliatyvus Y poslinkis:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Didžiausias OSD plotis:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Kelių vaizduoklių pasirinktys"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Vaizduoklis naudoja OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "visi vaizduokliai"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "vaizduoklis %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Laiko derinimas (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Monitorius:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Nustelbti:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "IÅ¡blukti:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Å riftai"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Å riftas %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Šešėlis"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Atvaizdavimo stilius"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Spalvos"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Spalva %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Sužadinti"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Įvykis"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Kompozicionavimo tvarkyklÄ— aptikta"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -719,112 +687,112 @@ msgstr ""
 "Kompozicionavimo tvarkyklÄ— nerasta;\n"
 "įjunkite kompozicionavimo tvarkyklę, nes OSD neveiks taip kaip priklauso"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Netikram permatomumui kompozicionavimo tvarkyklė nebūtina"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Permatomumas"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Netikras permatomumas"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Tikras permatomumas (reikalinga X kompozicionavimo plÄ—tinys)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Kompozicionavimo plėtinys neįkrautas"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Kompozicionavimo plÄ—tinys neprieinamas"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - konfigūracija"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Testas"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Nustatyti"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Pozicija"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animacija"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Tekstas"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekoracijos"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Sužadintojas"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Kita"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 Grojaraščiai"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 grojaraščiai"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious grojaraščiai (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Spalva</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "IÅ¡siliejimo sritis"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Profiliai:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Duoti lygį:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Nukirpti dažnius:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Profiliai:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektro analizatorius"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD įskiepis"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -844,171 +812,156 @@ msgstr ""
 "\n"
 "Tai buvo Google Summer Code 2007 projektas."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Įrenginys</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Skaitymo greitis:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Perrašyti įrenginį:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Meta duomenys</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Naudoti CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Naudoti CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Naudoti HTTP vietoj CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Serveris:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Kelias:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Prievadas:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD įskiepis"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Inicijuoti cdio posistemÄ—s nepavyko."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Netinkamas URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Takelis %d nerastas."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Takelis %d yra duomenų takelis."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Atverti audio išvesties nepavyko."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Klaida skaitant audio CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Takelis %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Atverti CD įrenginio %s nepavyko."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "CD įrenginio suderinamo su audio nerasta."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Nepavyko užbaigti inicijuoto atverto CD įrenginio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Gauti pirmo/paskutinio takelio numerio nepavyko."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Perskaityti LSN takelio %d pradžios/pabaigos nepavyko."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Sukurti cddb sujungimo nepavyko."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Užlausti CDDB serverio nepavyko"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Užlausti CDDB serverio nepavyko: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Perskaityti cddb informacijÄ… nepavyko: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Diskasukis tuščias."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nepalaikomas disko tipas."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audio CD Meniu elementai"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Groti CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "PridÄ—ti CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Audio CD Meniu elementai"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Glaudinimas</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centro garsas:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "DinaminÄ— sritis:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Dynamic Range Compression įskiepis skirtas Audacious\n"
-"AutorinÄ—s teisÄ—s 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dynamic Range Compressor"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1024,206 +977,225 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bosas:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Aukšti:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Aidas:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Numatyta dainos trukmÄ—:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Perdarymas (resampling)</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Įjungti garso diskretizaciją"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Diskretizacijos dažnis:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Nepaisyti trukmės iš SPC žymų"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Padidinti reverb"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Žaidimų konsolės muzikos dekoderis"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"Garso perėjimo efektas nepavyko, nes dainos turi skirtingą skaičių kanalų. "
-"Galite panaudoti kanalų mikšerio įrankį ir suvienodinti kanalų skaičių."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Garso perÄ—jimo efektas nepavyko, nes dainos turi skirtingus diskretizavimo "
-"dažnius.  Galite panaudoti diskretizacijos konvertavimo įrankį ir paversti "
-"dainas į tą patį dažnį."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Crossfade Plugin skirtas Audacious\n"
-"AutorinÄ—s teisÄ—s 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Persidengimas</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Perdengti:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Perdengimas"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Garso perėjimo efektas nepavyko, nes dainos turi skirtingą skaičių kanalų. "
+"Galite panaudoti kanalų mikšerio įrankį ir suvienodinti kanalų skaičių."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Garso perÄ—jimo efektas nepavyko, nes dainos turi skirtingus diskretizavimo "
+"dažnius.  Galite panaudoti diskretizacijos konvertavimo įrankį ir paversti "
+"dainas į tą patį dažnį."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensyvumas:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet įskiepis"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Pašalinti failus"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Klaida perkeliant %s į šiukšlinę: %s"
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Klaida Å¡alinant %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Klaida Å¡alinant %s: ne vietinis failas."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Ar tikrai norite perkelti pasirinktus failus į šiukšliadėžę?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Perkelti į šiukšlinę"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Ar tikrai norite negrįžtamai ištrinti pasirinktus failus?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "IÅ¡trinti"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Atšaukti"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Pašalinti failus"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Pašalinti pasirinktus failus"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Å alinimo metodas</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Perkelti į šiukšlinę, iškart nepašalinti"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Aidas</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Delsa:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Garsinis atsakas:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Garsumas:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo Plugin\n"
-"Sukūrė Johan Levin, 1999\n"
-"\n"
-"Surround echo sukūrė Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Aidas"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg įskiepis"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1239,55 +1211,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg įskiepis"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter įskiepis"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "IÅ¡vesties failo formatas:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfigūruoti"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "IÅ¡saugoti originalo aplanke"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "IÅ¡saugoti pasirinktame aplanke"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Paskirties aplankas:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Pasirinkite aplankÄ…"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Gauti failo vardą iš:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "originalios failo žymės"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "originalus failo vardas"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Neištrinti failo plėtinio"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Įdėti takelio numerį į failo vardą"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1319,165 +1291,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter įskiepis"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Sujungtas stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 konfigūravimas"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Gerai"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritmo kokybÄ—:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Išvesties diskretizavimo dažnis:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitų dažnis / Kompresijos santykis:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitų dažnis(kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Kompresijos santykis:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio režimas:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Kita:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Priversti griežtai laikytis ISO suderinamumo"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Apsauga nuo klaidų"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "KokybÄ—"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Įjungti VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipas:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR pasirinktys:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimalus bitų dažnis (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksimalus bitų dažnis (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Griežtai laikytis minimalaus bitų dažnio"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR pasirinktys:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Vidutinis bitų dažnis (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR kokybÄ—s lygis:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Nerašyti Xing VBR antraštės"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Kadro nustatymai:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Pažymėti kaip saugomą autorinių teisių"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Pažymėti kaip originalą"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 parametrai"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Priverstinai pridėti 2 versijos žymą"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Pridėti tik v1 žymą"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Pridėti tik v2 žymą"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Žymos"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis koduotojo konfigūracija"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "KokybÄ—s lygis (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC dekoderis"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "lossless"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1489,11 +1465,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC dekoderis"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1501,11 +1473,19 @@ msgstr ""
 "GIO įskiepis skirtas Audacious\n"
 "AutorinÄ—s teisÄ—s 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO įskiepis"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1525,450 +1505,509 @@ msgstr ""
 "\n"
 "License: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL spektro analizatorius"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
-msgstr ""
-"Gnome Shortcut įskiepis\n"
-"Suteikia galimybÄ™ valdyti grotuvÄ… su Gnome susiejimais.\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
 "\n"
-"AutorinÄ—s teisÄ—s (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome spartieji klavišai"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Įrašo numeris"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Pavadinimas"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "AtlikÄ—jas"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Metai"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Albumas"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Takelis"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Žanras"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Vieta eilÄ—je"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "TrukmÄ—"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Bylos kelias"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Bylos vardas"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Derintas pavadinimas"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitų seka"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Prieinami stulpeliai"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Rodomų stulpelių sąrašas"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Paieškos įrankis"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Sumažinti į kairę"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Sumažinti į dešinę"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Sumažinti į viršų"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Sumažinti apačioje"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Padidinti"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "IÅ¡jungti"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Paieškos įrankis"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Atverti failus ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Atverti _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_PridÄ—ti failus..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "PridÄ—ti U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Ieškoti _bibliotekoje"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "A_pie"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Nustatymai..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_IÅ¡eiti"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Groti"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Pauz_Ä—"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Sustabdyti"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Ankste_snis"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Sekantis"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Kartoti"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "S_umaišyti"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_esislinkti grojaraščiu"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Sustabdyti _po Å¡ios dainos"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Dainos _informacija ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Šokti į _laiką"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Pereiti prie dainos ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Nustatyti kartojimo tašką _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Nustatyti kartojimo tašką _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Išvalyti kartojimo taškus"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Pagal _pavadinimÄ…"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Pagal failo _vardÄ…"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Pagal failo _keliÄ…"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Pagal takelio _numerį"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Pagal _atlikÄ—jÄ…"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Pagal _albumÄ…"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Pagal išleidimo _datą"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Pagal _trukmÄ™"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Pagal _failo keliÄ…"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Pagal _derintÄ… eilutÄ™"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "A_tvirkštine tvarka"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Atsitiktine tvarka"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Groti šį grojaraštį"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Atnaujinti"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Rikiuoti"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Rikuoti _pasirinktus"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Pašalinti _dubliuotus"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Pašalinti _neprieinamus failus"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Naujas"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Pervadinti"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "_Å alinti"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Įkelti ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Eksportuoti ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Grojaraščio _redaktorius"
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_EilÄ—s redaktorius ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Pagarsi_nti"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Patil_dyti"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ekvalaizeris"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_fektai..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Rodyti _meniu juostÄ…"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Rodyti i_nfo juostÄ…"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Rodyti informacijos juostos _vizualizacijÄ…"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Rodyti _būsenos juostą"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "_Rodyti likusį laiką"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Vaizdiniai..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Failas"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Atkūrimas"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "G_rojaraštis"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Tarnybos"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_IÅ¡vestis"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Rodymas"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Ä® eilÄ™/IÅ¡ eilÄ—s"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "IÅ¡kirpt_i"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopijuoti"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Įklijuoti"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Pasirinkti _viskÄ…"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Pervadinti..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Grojaraščio kortelės</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Visada rodyti korteles"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Rodyti įvesčių skaičių"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Rodyti uždarymo mygtukus"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Grojaračio stulpeliai</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Rodyti stulpelio antraštes"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Kita</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Krypčių klavišai persuka:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Keičiantis dainai slinkti"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK naudotojo sÄ…saja"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Įkraunama į atmintį ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1976,84 +2015,98 @@ msgstr[0] "%d kanalas"
 msgstr[1] "%d kanalai"
 msgstr[2] "%d kanalų"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Vieno režimas."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Grojaraščio režimas."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Sustabdymas po dainos."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Ankstesnis takelis"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Groti"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Sustabdyti/Paleisti"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Stabdyti"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Kitas takelis"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 sekundes į priekį"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 sekundes atgal"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Nutildyti"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Pagarsinti"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Pritildyti"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Peršokti į failą"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Perjungti grotuvo langÄ… (-us)"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Rodyti On-Screen-Display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Perjungti kartojimÄ…"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Perjungti maišymą"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Perjungti sustabdymÄ… po dabartinÄ—s"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Pakelti grotuvÄ… langÄ… (-us)"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(joks)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2064,15 +2117,11 @@ msgstr ""
 "\n"
 "Tęsti?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Saistyti pelÄ—s mygtukus"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Global Hotkey įskiepio konfigūravimas"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2080,23 +2129,27 @@ msgstr ""
 "Paspauskite klavišų kombinaciją teksto lauke.\n"
 "Taip pat galima sieti ir pelÄ—s mygtukus."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Spartieji klavišai:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Veiksmas:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Klavišo susiejimas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_PridÄ—ti"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Bendri karštieji klavišai"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2122,60 +2175,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Bendri karštieji klavišai"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK išvestis"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Prisijungti prie visų prieinamų jack prievadų"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Prisijungti tik prie išvesties prievadų"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Nesijungti prie jokio prievado"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Prisijungimo režimas:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Įjungti derinimo pranešimus"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Paremta xmms-jack, kūrė Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"PritaikÄ— Audacious, Giacomo Lozito"
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK išvestis"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s nustatymai:"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Host nustatymai"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Modulio kelias:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2186,25 +2230,25 @@ msgstr ""
 "Kai pridedami nauji keliai, paspauskite ENTER naujų įskiepių paieškai.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Prieinami įskiepiai:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Įjungti"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Įjungti įskiepiai:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Nustatymai"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2212,47 +2256,15 @@ msgstr ""
 "LADSPA Host skirta Audacious\n"
 "AutorinÄ—s teisÄ—s 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Host"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: inicijuoti LIRC palaikymo nepavyko\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: nepavyko perskaityti LIRC konfigūracijos failo\n"
-"%s: paskaitykite LIRC dokumentacijÄ…\n"
-"%s: kaip sukurti tinkamą konfigūracijos failą\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: bandoma prisijungti iš naujo...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: nežinoma komanda „%s“\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: atsijungta nuo LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: bus bandoma prisijungti iš naujo kas %d sekundes...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC įskiepis"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2280,73 +2292,81 @@ msgstr ""
 "\n"
 "Apie LIRC galite sužinoti tinklalapy http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Prisijungimas</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "IÅ¡ naujo prisijungti prie LIRC serverio"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Prieš jungiantis iš naujo palaukti:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC įskiepis"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki įskiepis"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Nėra prieinamų dainų žodžių"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Klaida"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Gauti %s nepavyko"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Klaida"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Apdoroti %s nepavyko"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Ieškoma dainų žodžių"
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Trūksta dainos metaduomenų"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Jungiamasi prie lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki įskiepis"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U grojaraščiai"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Takto generatorius"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Takto generatorius: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Takto generatorius: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2359,11 +2379,11 @@ msgstr ""
 "pvz. tact://77 norint atkurt 77 dūžius per minutę\n"
 "ar tact://60*3/4 norint atkurti 60 bpm 3/4 taktu"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Takto generatorius"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanalų mikšeris"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2371,152 +2391,184 @@ msgstr ""
 "Channel Mixer įskiepis skirtas Audacious\n"
 "Autorinės teisės 2011-2012 John Lindgren ir Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanalų mikšeris</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "IÅ¡vesties kanalai:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanalų mikšeris"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS įskiepis"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module grotuvas)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Raiška</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bitai"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bitų"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanalai</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Arčiausias (greičiausia)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linijinis (greitas)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (gerai)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifazinis (geriausiai)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Diskretizacijos dažnis</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Lygis:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Nukirpimas:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverb</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Boso garsinimas</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Erdvinis</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Stiprinimas</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Oversample"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Triukšmo mažinimas"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Groti Amiga MOD"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Kartoti</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Kartojimų skaičius:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Norėdami kartoti amžinai, nustatykite „-1“."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module grotuvas)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Erdvinis garsas"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 įskiepis"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>SudÄ—tingesni</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Erdvinis garsas"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 Serveris"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS įskiepis"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Sustabdyta"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious negroja."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Darbastalio pranešimai"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2552,55 +2604,64 @@ msgstr ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Rodyti atkūrimo valdymą"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Visada rodyti pranešimą"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Darbastalio pranešimai"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Rodyti"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "PauzÄ—"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Sekantis"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Numatytasis įrenginys"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 išvestis"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audio įrenginys:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Naudoti alternatyvų įrenginį:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Išsaugoti garsą tarp sesijų"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Įgalinti formato keitimą kurį padarė OSS programinė įranga."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Įgalinti išskirtinį režimą, siekiant išvengti virtualaus maišymosi."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2614,19 +2675,35 @@ msgstr ""
 "Norėčiau padėkoti žmonėms #audacious kanale, ypatingai Tony Vroon ir John "
 "Lindgren ir savaime aišku ankstesnės OSS įskiepio versijos autoriams."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 išvestis"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS grojaraščiai"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 dekoderis"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio išvestis"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2662,11 +2739,68 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio išvestis"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Ieškoti"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Ankstesnis"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Kartoti"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Maišyti"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Diskretizavimo dažnio keitėjas"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2674,98 +2808,106 @@ msgstr ""
 "Sample Rate Converter Plugin for Audacious\n"
 "AutorinÄ—s teisÄ—s 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Praleisti/kartoti pavyzdžius"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "LinijinÄ— interpoliacija"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Greita interpoliacija"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "VidutinÄ— interpoliacija"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Geriausia interpoliacija"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Konvertavimas</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metodas:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Dažnis:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Dažnio nustatymai</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Naudoti dažnio nustatymus"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Diskretizavimo dažnio keitėjas"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "Gerai. Ieškoma informacijos naudotojui: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Neleidžiama"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Nueikite Å¡ia nuoroda ir leiskite Audacious gauti informacijÄ… apie dainas:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Palikite šį langą atvertą ir paspauskite „Tikrinti leidimus“ dar kartą.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2773,33 +2915,37 @@ msgstr ""
 "Nesijaudinkite. Jūsų informacija saugoma kompiuteryje.\n"
 "Ji bus išsiųsta kai tik Audacious leis tai padaryti."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Tinklo problema."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Bandant susisiekti su Last.fm įvyko klaida. Pabandykite vėliau."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Tikrinama..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "_Tikrinti leidimus"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Atšaukti leidimą"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Turite leisti Audacious perduoti takelių informaciją jūsų Last.fm paskyrai.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2807,7 +2953,7 @@ msgstr ""
 "Scrobbler įskiepio paleisti nepavyko.\n"
 "Gali būt jog yra problemų su jūsų įdiegimu."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2824,11 +2970,7 @@ msgstr ""
 "Dėkojame John Lindgren už pagalbą.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2836,7 +2978,11 @@ msgstr ""
 "Nuo Å¡iol audacious naudoja patobulintÄ… last.fm apdoroklio versijÄ….\n"
 "Pažiūrėkite apdoroklio nustatymuose."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL išvestis"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2844,88 +2990,59 @@ msgstr ""
 "SDL Output Plugin skirtas Audacious\n"
 "AutorinÄ—s teisÄ—s 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL išvestis"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Fonoteka"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Nežinomas atlikėjas"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Nežinomas albumas"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" ant %s su %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d albumas"
-msgstr[1] "%d albumai"
-msgstr[2] "%d albumų"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d daina"
 msgstr[1] ""
-"%s\n"
-" %s, %d dainos"
 msgstr[2] ""
-"%s\n"
-" %s, %d dainų"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d daina kurią sukūrė %s"
 msgstr[1] ""
-"%s\n"
-" %d dainos kurias sukūrė %s"
 msgstr[2] ""
-"%s\n"
-" %d dainų kurias sukūrė %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Sukurti grojaraštį"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Pridėti į grojaraštį"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Ieškoti fonotekoje"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2933,679 +3050,769 @@ msgstr ""
 "Norėdami importuoti muziką į Audacious fonoteką, pasirinkite aplanką ir "
 "paspauskite „atnaujinti“ piktogramą."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Palaukite..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Pasirinkite aplankÄ…"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Atverti failus..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Atverti URL..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Atkūrimas"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Grojaraštis"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Rodymas"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Tarnybos"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Apie..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Nustatymai..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Baigti"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Dainos informacija..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Kartoti"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Maišyti"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Nesislinkti grojaraščiu"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Sustabdyti po Å¡ios dainos"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Ankstesnis"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Nustatyti A-B kartojimÄ…"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "IÅ¡valyti A-B kartojimÄ…"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Pereiti prie dainos ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Šokti į laiką..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Groti šį grojaraštį"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Naujas grojaraštis"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Pervadinti grojaraštį..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Pašalinti grojaraštį"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Ankstesnis grojaraštis"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Sekantis grojaraštis"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Įkelti grojaraštį..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Eksportuoti grojaraštį..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Grojaraščių redaktorius..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "EilÄ—s redaktorius ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Atnaujinti grojaraštį"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Rodyti grojaraščio redaktorių"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Rodyti ekvalaizerį"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Rodyti likusį laiką"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Visada viršuje"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Visuose darbalaukiuose"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Sustumti grotuvÄ…"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Sustumti grojaraščio redaktorių"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Sustumti ekvalaizerį"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "PridÄ—ti URL..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "PridÄ—ti failus..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Pagal pavadinimÄ…"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Pagal failo vardÄ…"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Pagal failo keliÄ…"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Pašalinti visus"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "IÅ¡valyti eilÄ™"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Pašalina neprieinamus failus"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Pašalinti dubliuotus"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Pašalint nepažymėtus"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Pašalint pažymėtus"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Ieškoti ir pasirinkti"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertuoti pažymėjimą"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Nieko nepasirinkti"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Pasirinkti viskÄ…"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Pagal albumÄ…"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Pagal takelio numerį"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Pagal atlikÄ—jÄ…"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Pagal albumÄ…"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Pagal išleidimo datą"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Pagal takelio numerį"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Sumaišyti sąrašą"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Apversti sąrašą"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Rikuoti pasirinktus"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Rikiuoti sąrašą"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "IÅ¡kirpti"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopijuoti"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Įklijuoti"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Ä® eilÄ™/IÅ¡ eilÄ—s"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Įkrauti šabloną..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Įkrauti savaime įsikraunantį šabloną..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Įkelti numatytus"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Įkrauti šabloną iš failo..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Įkelti EQF failą..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "IÅ¡saugoti Å¡ablonÄ…..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Išsaugoti savaime įsikraunantį šabloną..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Įrašyti numatytuosius"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Išsaugoti šabloną į failą..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Išsaugoti šabloną į EQF failą..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Pašalinti šabloną..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Ištrinti savaime įsikraunantį šabloną..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importuoti WinAMP Å¡ablonus..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Atstatyti nulį"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "KlasikinÄ— Winamp sÄ…saja"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "IÅ¡saugoti"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Įkrauti"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Įkrauti šabloną iš failo"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Įkelti EQF failą"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Išsaugoti šabloną į failą"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Išsaugoti šabloną į EQF failą"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importuoti WinAMP Å¡ablonus"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Å ablonai"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Įkrauti šabloną"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Įkrauti auto išankstinius nustatymus"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "IÅ¡saugoti Å¡ablonus"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Išsaugoti auto išankstinius nustatymus"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "IÅ¡trinti Å¡ablonÄ…"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Ištrinti auto išankstinius nustatymus"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Grotuvas:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Pasirinkti pagrindinį lango šriftą:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Grojaraštis:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Pasirinkti grojaraščio šriftą:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>IÅ¡vaizda</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Å riftai</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Naudoti bitmap Å¡riftus (palaiko tik ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Slinkti pavadinimÄ…"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Slinkti pavadinimą į abi puses"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizatorius"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Sritis"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Voiceprint / VU meter"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "IÅ¡jungta"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normalus"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Ugnis"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Vertikalios linijos"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linijos"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Juostos"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Lėčiausias"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "LÄ—tas"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Vidutinis"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Greitas"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Greičiausias"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Taškai"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "EilutÄ— "
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Vientisa"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Ledas"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Tolygus"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Tipas</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Vaizdo efektų tipas:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizatorius</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Rodyti pikus"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Spalvinimas:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Stilius:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Pikų krytis:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Pikų krytis:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Srities stilius:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Voiceprint spalvojimas:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU Meter stilius:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "PagrindinÄ—s"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Vizualizacija"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious ekvalaizeris"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Eiti į %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Garsumas: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balansas: %d%% kairÄ—"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balansas: centras"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balansas: %d%% dešinė"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Pasirinkčių meniu"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Išjungti „Visada viršuje“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Įjungti „Visada viršuje“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Failo informacijos langas"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Kartojimo taškas A nustatytas."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Kartojimo taškas B nustatytas."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Kartojimo taškai išvalyti."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Vieno režimas."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Grojaraščio režimas."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Sustabdymas po dainos."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Ieškoti įrašų aktyviame grojaraštyje"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Ieškoti"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3617,57 +3824,61 @@ msgstr ""
 "nesvarbus. Jei nežinai kaip veikia reguliariosios išraiškos, paprasčiausiai "
 "įrašyk paraidžiui tai ko ieškai."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Pavadinimas:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Albumas:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "AtlikÄ—jas:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Failo vardas:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Prie ieškant, išvalyti buvusius pasirinkimus"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Atitinkantiems įrašams automatiškai perjungti eilę"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Iš surastų įrašų sukurti naują grojaraštį"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious grojaraščio redaktorius"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d iš %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Archyvuotas Winamp 2.x skin"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "IÅ¡archyvuotas Winamp 2.x skin"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Negaliu sukurti aplanko (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile įskiepis"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3707,83 +3918,71 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile įskiepis"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Apie Sndio Output įskiepį"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio Output Plugin\n"
-"\n"
-"Sukūrė Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nepalaikomas formatas"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Garso įrenginys šio formato nepalaiko.\n"
-"\n"
-"Pabandykite dar kartÄ… su paleistu sndiod(1) serveriu."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio įrenginys"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(tuščia reiškia numatytą)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Gerai"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Dainos keitimas"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Komanda kurią paleisti kai Audacious paleidžia naują dainą."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametrai pateikti komandų interpretatoriui turi būti "
+"kabutÄ—se. Darant kitaip rizikuojate savo saugumu.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Komanda:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Komanda kurią paleisti prieš pasibaigiant dainai."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Komanda kurią paleisti kai Audacious pasiekia grojaraščio pabaigą."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Komanda kurią paleisti kai dainos pavadinimas pasikeičia (t.y. interneto "
-"srautų pavadinimai)"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3797,35 +3996,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Galite naudoti tokio formato eilutes, kurios\n"
-"prieš kviečiant komandą bus pakeistos (ne visos\n"
-"tinka end-of-playlist komandai):\n"
-"\n"
-"%F: Dažnis (hercais)\n"
-"%c: Kanalų skaičius\n"
-"%f: Failo vardas (pilnas kelias)\n"
-"%l: TrukmÄ— (millisekundÄ—mis)\n"
-"%n ar %s: Dainos vardas\n"
-"%r: Dažnis (bitais per sekundę)\n"
-"%t: Grojaraščio vieta (%02d)\n"
-"%p: Å iuo metu grojama (1 arba 0)\n"
-"%a: AtlikÄ—jas\n"
-"%b: Albumas\n"
-"%T: Takelio pavadinimas"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Parametrai pateikti komandų interpretatoriui turi būti "
-"kabutÄ—se. Darant kitaip rizikuojate savo saugumu.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Komandos"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3836,51 +4016,51 @@ msgstr ""
 "SoX Resampler įskiepis skirtas Audacious⏎ Copyright 2013 Michał Lipski⏎ ⏎ "
 "Paremta Sample Rate Converter įskiepiu:⏎ Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Greita"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Žema"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Aukšta"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Labai aukšta"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "KokybÄ—:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Greitis ir žingsnis"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Greitis ir žingsnis</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Greitis:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Žingsnis:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Greitis ir žingsnis"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "BÅ«senos piktograma"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Nus_tatymai..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3898,39 +4078,39 @@ msgstr ""
 "Šis įskiepis suteikia būsenos piktogramą, kuri\n"
 "rodoma sistemos dÄ—kle."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>PelÄ—s slinkimo veiksmas</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Keisti garsÄ…"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Keisti grojančią dainą"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Kiti nustatymai</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Išjungti iššokantį langą"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Užverti į sistemos dėklą"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Slenkant aukštyn, žengti grojaraščiu"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "BÅ«senos piktograma"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3940,24 +4120,24 @@ msgstr ""
 "\n"
 "Sukūrė Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Tono generatorius"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Tono generatorius: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3971,15 +4151,11 @@ msgstr ""
 "Norėdami naudoti, pridėkite URL: tone://dažnis1;dažnis2;dažnis3;...\n"
 "pvz. tone://2000;2005 norint atkurti 2000 Hz tonÄ… ir 2005 Hz tonÄ…"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Tono generatorius"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Balso pašalinimas"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4017,11 +4193,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis dekoderis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Decoder"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4031,19 +4231,19 @@ msgstr ""
 "Paremta in_vtx.dll kurį sukūrė Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious įskiepį sukūrė Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack dekoderis"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "lossy (hibridinis)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "lossy"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4053,14 +4253,18 @@ msgstr ""
 "\n"
 "Dalį kodo parašė Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack dekoderis"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF dekoderis"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML viešinami grojaraščiai (XSPF)"
diff --git a/po/lv.po b/po/lv.po
index 9d248c9d960c..85f87fbd75cc 100644
--- a/po/lv.po
+++ b/po/lv.po
@@ -3,14 +3,14 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# hairy_latvian <einars8 at gmail.com>, 2013-2014
+# hairy_latvian <einars8 at gmail.com>, 2013-2015
 # hairy_latvian <einars8 at gmail.com>, 2009,2011-2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:49+0000\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-03-24 10:07+0000\n"
 "Last-Translator: hairy_latvian <einars8 at gmail.com>\n"
 "Language-Team: Latvian (http://www.transifex.com/projects/p/audacious/"
 "language/lv/)\n"
@@ -21,40 +21,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
 "2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "ieskaušana"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) dekodētājs"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (jēldati) dekodētājs"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib atskaņotājs)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sekvencēts"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib atskaņotājs)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Modinātājs"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Iestatīt signālu ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -64,11 +52,7 @@ msgstr ""
 "\n"
 "Sākotnējie autori: Adam Feakin un Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Modinātājs"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -109,7 +93,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -148,7 +132,7 @@ msgstr ""
 "    palaist šo komandu, noskanot modinātājam.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -172,384 +156,389 @@ msgstr ""
 "    pārslēgšanas pogu, ja vēlaties, lai atgādinājums\n"
 "    tiek parādīts."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Šis ir jūsu mošanās zvans."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Jūsu atgādinājums šodienai ir..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Atgādinājums"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Pirmdiena"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Otrdiena"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Trešdiena"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Ceturtdiena"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Piektdiena"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sestdiena"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Svētdiena"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Modinātājs iestatījumi"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_Labi"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Atcelt"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Laiks"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Modināt (noklusējums):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Kluss pēc:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "stundas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minūtes"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Izvēlieties dienas, kurās ieslēgsies modinātājs"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Diena"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Noklusētais"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dienas"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Izdzišana"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekundes"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Skaļums"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Sākumā"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Beigās"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Pašreizējais"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Papildu komanda"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "ieslēgt"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Repertuārs (neobligāts)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Izvēlieties repertuāru"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opcijas"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Ko šīs opcijas nozīmē?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Palīdzība"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Albuma vāks"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Albuma vāks (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA izvade"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA izvades spraudnis atskaņotājam Audacious\n"
+"Autortiesības 2009-2012 John Lindgren\n"
+"\n"
+"Paldies William Pitcock, ALSA NG izvades spraudņa autoram, kura kods kalpoja "
+"kā paraugs, kad ar ALSA rokasgrāmatu vien nepietika."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(bez apraksta)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Noklusētā PCM ierīce"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Noklusētā miksera ierīce"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM ierīce:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Miksera ierīce:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Miksera elements:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Apiet 'drain hangup' problēmai"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI atskaņotājs)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA izvades spraudnis atskaņotājam Audacious\n"
-"Autortiesības 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modulārs MIDI mūzikas atskaņotājs\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Paldies William Pitcock, ALSA NG izvades spraudņa autoram, kura kods kalpoja "
-"kā paraugs, kad ar ALSA rokasgrāmatu vien nepietika."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA izvade"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI atskaņotājs)"
+"Autors Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"Īpašs paldies...\n"
+"\n"
+"Clemens Ladisch un Jaroslav Kysela\n"
+"par viņu programmām aplaymidi and amixer; tās, līdz ar alsa-lib dokumentiem, "
+"bija ļoti noderīgas, mācoties par ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"par jauku midi klaviatūras logo\n"
+"\n"
+"Tony Vroon\n"
+"par palīdzību alfa testēšanā"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Aizstāt noklusēto pastiprinājumu:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Aizstāt noklusēto polifoniju:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Aizstāt noklusēto atbalsi: "
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Ieslēgts"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Aizstāt noklusēto kori:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Atskaņošana</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Pārlikt:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "pustoņi"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Bungu pārbīde:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Paplašināti</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "nošu numuri"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "izvilkt komentārus no MIDI faila"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Izlaist klusumu sākumā"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "izvilkt dziesmu vārdu tekstus no MIDI faila"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Izlaist klusumu beigās"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Sintezators</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "Iztveršanas temps:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug — izvēlieties SoundFont failu"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Atcelt"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Atvērt"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Faila nosaukums"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Izmērs (baitos)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nosaukums:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI informācija </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formāts:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Garums (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Celiņu skaits:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "mainīgais"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Laika dalītājs:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Komentāri un dziesmu vārdu teksti </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* komentāri šajā MIDI failā nav pieejami *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* dziesmu vārdu teksti šajā MIDI failā nav pieejami *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Ai_zvērt"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (nederīgs UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "About AMIDI spraudni"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI spraudnis"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"modulārs MIDI mūzikas atskaņotājs\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"autors Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"īpašs paldies...\n"
-"\n"
-"Clemens Ladisch un Jaroslav Kysela\n"
-"par viņu jaukajām programmām aplaymidi un amixer;\n"
-"šīs programmas, līdz ar alsa-lib dokumentāciju, bija ļoti\n"
-"noderīgas, lai uzzinātu vairāk par ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"par jauku midi klaviatūras logo\n"
-"\n"
-"Tony Vroon\n"
-"par palīdzību alfa-testēšanā"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -567,152 +556,146 @@ msgstr ""
 "Daļēji balstīts uz Evan Martin Ghosd bibliotēku:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (virsekrāna displejs)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Taisnstūris"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Noapaļots taisnstrūris"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Ieliekts taisnstrūris"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Neviens"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Atskaņošanas sākums"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Palaiž OSD, kad tiek atskaņots repertuāra ieraksts."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Nosaukuma maiņa"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"Palaiž OSD, kad, atskaņošanas laikā, dziesmas nosaukums mainās, bet faila "
-"nosaukums paliek nemainīgs. Tas galvenokārt ir noderīgi, lai attēlotu "
-"interneta straumju nosaukumu maiņu."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Palaiž OSD, izmainoties dziesmas nosaukumam (interneta straumēm)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pauze ieslēgta"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Palaiž OSD, kad tiek nopauzēta atskaņošana."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Pauze izslēgta"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Palaiž OSD, kad tiek atjaunota atskaņošana pēc pauzes."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Novietojums"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relatīvā X nobīde:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relatīvā Y nobīde:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maksimālais OSD platums:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Daudzmonitoru opcijas"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Rādīt OSD izmantojot:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "visi monitori"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "%i. monitors"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Ilgums (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Rādīt:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Parādīties:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Izgaist:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Fonti"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "%i. fonts:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Ä’na"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Renderēšanas stils"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Krāsas"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "%i. krāsa:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Ieslēgt palaidēju"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Notikums"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Kompozitēšanas pārvaldnieks atrasts"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -722,112 +705,112 @@ msgstr ""
 "ja vien esat pārliecināts, ka jums tas ir palaists, lūdzu, aktivizējiet "
 "kompozitēšanas pārvaldnieku, citādi OSD nefunkcionēs pareizi"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Viltus caurspīdībai kompozitēšanas pārvaldnieks nav nepieciešams"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Caurspīdība"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Viltus caurspīdība"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Īsta caurspīdība (nepieciešams X Composite paplašin.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite paplašinājums nav ielādēts"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite paplašinājums nav pieejams"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - konfigurācija"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Pārbaudīt"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "Ie_statīt"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Novietojums"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animācija"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Teksts"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Noformējums"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Palaidējs"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Dažādi"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Testēt"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 repertuāri"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 repertuāri"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious repertuāri (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Krāsa</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer stereofoniski-uz-binaurāli (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Gatavie regulējumi:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Barošanas līmenis:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Nogriešanas frekvence:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Gatavie regulējumi:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer stereofoniski-uz-binaurāli (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Spektra analizators"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD spraudnis"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -847,172 +830,159 @@ msgstr ""
 "\n"
 "Å is bija Google Summer of Code 2007 projekts."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Ierīce</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Lasīšanas ātrums:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Aizstāt ierīci:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadati</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Lietot CD-text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Lietot CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Lietot HTTP nevis CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Serveris:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Ceļš:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Ports:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD spraudnis"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Neizdevās inicializēt cdio apakšsistēmu."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Nederīgs URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Celiņš %d netika atrasts."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Celiņš %d ir datu celiņš."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Neizdevās atvērt audio izvadi."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Kļūda nolasot audio CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Celiņš %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Neizdevās atvērt CD ierīci %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Netika atrasts CD dzinis ar audio atskaņošanas iespēju."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Neizdevās pabeigt inicializēt atvērtu CD dzini."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Neizdevās saņemt pirmā/pēdējā celiņa numuru."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Neizdevās nolasīt LSN sākumu/beigas celiņam %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Neizdevās izveidot cddb savienojumu."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Neizdevās aptaujāt CDDB serveri."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Neizdevās aptaujāt CDDB serveri: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Neizdevās nolasīt cddb informāciju: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Dzinis ir tukšs."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Neatbalstīts diska tips."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audio CD izvēlnes elementi"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Atskaņot CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Pievienot CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Audio CD izvēlnes elementi"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Kompresija</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centra skaļums:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dinamiskais diapazons:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Dinamiskā diapozona kompresijas spraudnis atskaņotājam\n"
 "Audacious\n"
-"Autortiesības 2010-2012 John Lindgren"
+"Autortiesības 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dinamiskā diapazona kompresors"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1028,206 +998,239 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bass:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Augstie toņi:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Atbalss:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Noklusētais dziesmas garums:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Iztveršanas tempa pārveidošana</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Ieslēgt audio iztveršanas tempa pārveidošanu"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Iztveršanas temps:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorēt garums no SPC tagiem"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Palielināt atbalsi"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Spēļu konsoles mūzikas dekodētājs"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Sapludināšana neizdevās, jo dziesmām ir dažāds kanālu skaits. Varat izmantot "
-"kanālu mikseri, lai pārveidotu abas dziesmas uz vienādu kanālu skaitu."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio izvade"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Sapludināšana neizdevās, jo dziesmām ir dažādas diskretizācijas frekvences. "
-"Varat izmantot diskretizācijas frekvenču pārveidotāju, lai pārveidotu "
-"dziesmas uz vienu diskretizācijas frekvenci."
+"CoreAudio izvades spraudnis atskaņotājam Audacious\n"
+"Autortiesības 2014 William Pitcock\n"
+"\n"
+"Bāzēts uz Audacious SDL izvades spraudņa\n"
+"Autortiesības 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Izmantot ekskluzīvo režīmu"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Sapludināšanas spraudnis atskaņotājam Audacious\n"
-"Autortiesības 2010-2012 John Lindgren"
+"Autortiesības 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Sapludināšana</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Automātiski mainoties dziesmai"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Pārklāšanās:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Meklējot vai pašrocīgi mainot dziesmu"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Padoms</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Labākai sapludināšanai, ieslēdziet\n"
+"klusuma izņemšanas efektu."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Sapludināšana"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Sapludināšana neizdevās, jo dziesmām ir dažāds kanālu skaits. Varat izmantot "
+"kanālu mikseri, lai pārveidotu abas dziesmas uz vienādu kanālu skaitu."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Sapludināšana neizdevās, jo dziesmām ir dažādas diskretizācijas frekvences. "
+"Varat izmantot diskretizācijas frekvenču pārveidotāju, lai pārveidotu "
+"dziesmas uz vienu diskretizācijas frekvenci."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Kristalizators</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensitāte:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Kristalizators"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue lapas spraudnis"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Dzēst failus"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Kļūda pārvietojot %s uz miskasti: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Kļūda dzēšot %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Kļūda dzēšot %s: nav vietējais fails."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Vai vēlaties izvēlētos failus pārvietot uz miskasti?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Pārvietot uz miskasti"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Vai vēlaties izvēlētos failus dzēst uz visiem laikiem?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Dzēst"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Atcelt"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Dzēst failus"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Dzēst izvēlētos failus"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Dzēšanas metode</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Pārvietot uz miskasti nevis dzēst nekavējoties"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Atbalss spraudnis\n"
+"Autors Johan Levin, 1999\n"
+"Ieskaujošās atbalss autors Carl van Schaik, 1999\n"
+"Atskaņotājam Audacious atjauninājuši William Pitcock un John Londgren, "
+"2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Atbalss</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Aizture:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Atbilde:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Skaļums:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Atbalss spraudnis\n"
-"Autors Johan Levin, 1999\n"
-"\n"
-"Ieskaujošās atbalss autors Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Atbalss"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg spraudnis"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1243,55 +1246,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg spraudnis"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Failu rakstītāja spraudnis"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Izvades faila formāts:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfigurēt"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Saglabāt oriģinālajā mapē"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Saglabāt pielāgotā mapē"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Izvades faila mape:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Izvēlieties mapi"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Iegūt faila nosaukumu no:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Ģenerēt faila nosaukumu no:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "oriģinālajiem faila tagiem"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Oriģinālais faila tags"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "oriģinālā faila nosaukuma"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Oriģinālais faila nosaukums"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Neatmest faila paplašinājumu"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Iekļaut oriģinālo faila nosaukuma paplašinājumu"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Pievienot celiņa numuru pirms faila nosaukuma"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Pievienot celiņa numuru faila nosaukumam"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1321,165 +1324,169 @@ msgstr ""
 "Ja tā nav, rakstiet uz Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Failu rakstītāja spraudnis"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automātiski"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 konfigurācija"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Labi"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritma kvalitāte:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Izvades diskretizācijas frekvence:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Izvades iztveršanas temps:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bitātrums / Kompresijas attiecība:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Bitātrums/Kompresijas attiecība:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bitātrums (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Kompresijas attiecība:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Audio režīms:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Dažādi:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "Uzspiest stingru ISO savietojamību"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Kļūdu aizsardzība"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kvalitāte"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Ieslēgt VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tips:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR opcijas:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimālais bitātrums (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksimālais bitātrums (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Stingri uzspiest minimālo bitātrumu"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR opcijas:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Vidējais bitātrums (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR kvalitātes līmenis:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Nerakstīt Xing VBR galveni"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Atmest Xing VBR galveni"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Kadra parametri:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Atzīmēt kā autortiesībām aizsargātu"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Atzīmēt kā oriģinālu"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3 parametri:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Uzspiest 2. versijas tagu pievienošanu"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Pievienot tikai 1. versijas tagu"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Pievienot tikai 2. versijas tagu"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tagi"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis kodētāja konfigurācija"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Kvalitātes līmenis (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC dekodētājs"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "bezzudumu"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1491,11 +1498,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC dekodētājs"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1503,11 +1506,19 @@ msgstr ""
 "GIO spraudnis atskaņotājam Audacious\n"
 "Autortiesības 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO spraudnis"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Režīms lasīt-un-pievienot nav atbalstīts"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Neatļauts atvēršanas režīms"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1527,14 +1538,44 @@ msgstr ""
 "\n"
 "Licence: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL spektra analizators"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"OpenGL spektra analizators atskaņotājam Audacious\n"
+"Autortiesības 2013 Christophe Budé, John Lindgren un Carlo Bramini\n"
+"Autortiesības 2014 William Pitcock\n"
+"\n"
+"Balstīts uz XMMS spraudni:\n"
+"Autortiesības 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson "
+"un 4Front Technologies\n"
+"\n"
+"Licence: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL spektra analizators (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME īsceļi"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
@@ -1543,434 +1584,476 @@ msgstr ""
 "\n"
 "Autortiesības (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome īsceļi"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Ieraksta numurs"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Nosaukums"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Izpildītājs"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Gads"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Albums"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Albuma izpildītājs"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Celiņš"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Žanrs"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Novietojums rindā"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Ilgums"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Faila ceļš"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Faila nosaukums"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Pielāgots nosaukums"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bitātrums"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Pieejamās kolonnas"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Parādītās kolonnas"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Meklēšanas rīks"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Pietauvot pa kreisi"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Pietauvot pa labi"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Pietauvot augšā"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Pietauvot apakšā"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Attauvot"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Atslēgt"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Meklēšanas rīks"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Atvērt _failus ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Atvērt _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Pievienot f_ailus ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Pievienot U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Meklēt _bibliotēkā"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_Par ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "I_estatījumi ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "I_ziet"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "A_tskaņot"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Pauz_e"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Stop"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Iepriekšējais"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Nākamais"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Atkārtot"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Jaukt"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Ne_virzīties uz priekšu repertuārā"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Apt_urēt pēc šīs dziesmas"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Dziesmas _info ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Pāriet uz _laiku ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Pāriet uz _dziesmu ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Iestatīt atkārtojuma punktu _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Iestatīt atkārtojuma punktu _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Notīrīt atkārtojuma punktus"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "PÄ“c n_osaukuma"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "PÄ“c _faila nosaukuma"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Pēc _faila ceļa"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Pēc faila _ceļa"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Pēc celiņa _numura"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Pēc _izpildītāja"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "PÄ“c a_lbuma"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Pēc albu_ma izpildītāja"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Pēc izlaišanas _datuma"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Pē_c žanra"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "PÄ“c _ilguma"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Pēc _faila ceļa"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Pēc _pielāgota nosaukuma"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Apgri_eztā kārtībā"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Nejaušā _kārtībā"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Atskaņot šo repertuāru"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Atskaņot/Atsākt"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "A_tsvaidzināt"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Kārtot"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Kārtot izvē_lētos"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Izņemt _dublikātus"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Izņemt _nepieejamos failus"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Jauns"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Pā_rdēvēt ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Izņe_mt"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importēt ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Eksportēt ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Reper_tuāru pārvaldnieks ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Ri_ndas pārvaldnieks ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "_Palielināt skaļumu"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Samazināt skaļumu"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Balansieris"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_fekti ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Rādīt _izvēlnes joslu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Rādīt i_nfoapgabalu"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Rādīt infoapgabala viz_ualizāciju"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Rādīt _stāvokļjoslu"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Rādīt a_tlikušo laiku"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Vizualizācijas ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Fails"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Atskaņošana"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Repertuārs"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Servisi"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "I_zvade"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "S_kats"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "Ie_rindot/Izņ. no rindas"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Atvērt saturošo mapi"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Izgriezt"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopēt"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "I_elīmēt"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Iezīmēt _visu"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Pā_rdēvēt ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Repertuāru cilnes</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Vienmēr rādīt cilnes"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Rādīt ierakstu skaitu"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Rādīt aizvēršanas pogas"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Repertuāru kolonnas</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Rādīt kolonnu galvenes"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Dažādi</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Kursortaustiņi meklē pa:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Ritināt dziesmām mainoties"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK saskarne"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Buferizācija ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1978,84 +2061,98 @@ msgstr[0] "%d kanāls"
 msgstr[1] "%d kanāli"
 msgstr[2] "%d kanālu"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Vieninstances režīms."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Repertuāra režīms."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Aptur pēc pašreizējās dziesmas."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Iepriekšējais celiņš"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Atskaņot"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pauze/Atsākt"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Stop"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Nākamais celiņš"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Uz priekšu par 5 sekundēm"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Atpakaļ par 5 sekundēm"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Apklusināt"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Skaļāk"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Klusāk"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Pāriet uz failu"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Pārslēgt atskaņotāja logu(s)"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Parādīt virsekrāna displeju"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Pārslēgt atkārtošanu"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Pārslēgt jaukšanu"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Pārslēgt atkārtošanu pēc pašreizējā"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Pacelt atskaņotāja logu(s)"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(nekas)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2066,15 +2163,11 @@ msgstr ""
 "\n"
 "Vai vēlaties turpināt?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Piesaista peles pogas"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Globālo īsinājumtaustiņu spraudņa konfigurācija"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2082,23 +2175,27 @@ msgstr ""
 "Nospiediet taustiņu kombināciju teksta laukā.\n"
 "Jūs varat piesaistīt arī peles pogas."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Īsinājumtaustiņi:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Darbība:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Taustiņa piesaiste:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "Pi_evienot"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globālie īsinājumtaustiņi"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2125,60 +2222,56 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globālie īsinājumtaustiņi"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK izvade"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Pievienoties visiem pieejamajiem jack portiem"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automātiski pieslēgties izvades portiem"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Pievienot tikai izvades portus"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Tika atrasti tikai %d JACK izvades porti, bet vajadzīgi %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Nepievienoties nevienam portam"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Neizdevās pieslēgties JACK portam %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Savienojuma režīms:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK atbalsta tikai peldošā punkta audio. Jums Audacious iestatījumos "
+"jāizmaina izvades dziļums uz 'peldošā punkta'."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Ieslēgt atkļūdošanas izvadi"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Neizdevās pieslēgties JACK serverim, vai tas ir palaists?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Balstīts uz xmms-jack, autors Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Audacious ports — Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK izvade"
+"JACK serverim vajadzīga diskretizācijas frekvence %d Hz, bet Audacious "
+"atskaņo %d Hz. Lūdzu, izmantojiet diskretizācijas frekvences pārveidotāja "
+"efektu, lai izlabotu nesakritību."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s iestatījumi"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA saimnieka iestatījumi"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Moduļu ceļi:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2189,25 +2282,25 @@ msgstr ""
 "Pēc jauno ceļu pievienošanas nospiediet 'Enter', lai skenētu jaunos "
 "spraudņus.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Pieejamie spraudņi:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Ieslēgt"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Ieslēgtie spraudņi:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Iestatījumi"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2215,47 +2308,15 @@ msgstr ""
 "LADSPA saimnieks atskaņotājam Audacious\n"
 "Autortiesības 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "LADSPA saimnieks"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: neizdevās inicializēt LIRC atbalstu\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: neizdevās nolasīt LIRC konf. failu\n"
-"%s: lūdzu, lasiet LIRC dokumentācijā\n"
-"%s: kā izveidot pareizu konf. failu\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: mēģina pieslēgties vēlreiz...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: nezināma komanda \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: atvienots no LIRC\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "LADSPA saimnieks"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: tiks mēģināts pieslēgties vēlreiz katras %d sekundes...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC spraudnis"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2284,73 +2345,81 @@ msgstr ""
 "\n"
 "Papildu informācijai par LIRC skatiet http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Savienojums</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Pieslēgties vēlreiz LIRC serverim"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Gaidīt, pirms atkārtoti pieslēgties:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC spraudnis"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki spraudnis"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Dziesmu vārdu teksti nav pieejami"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Kļūda"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Neizdevās saņemt %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Kļūda"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Neizdevās parsēt %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Meklē dziesmas vārdu tekstu ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Trūkst dziesmas metadatu"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Pieslēdzas lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki spraudnis"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki spraudnis (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U repertuāri"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Takts ģenerators"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Takts ģenerators: %d sit./min."
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Takts ģenerators: %d sit./min. %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2364,11 +2433,11 @@ msgstr ""
 "piem., tact://77, lai atskaņotu 77 sitienus minūtē\n"
 "vai tact://60*3/4, lai atskaņotu 60 s/min 3/4 taktsmērā"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Takts ģenerators"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanālu mikseris"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2376,152 +2445,184 @@ msgstr ""
 "Kanālu miksera spraudnis atskaņotājam Audacious\n"
 "Autortiesības 2011-2012 John Lindgren un Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Kanālu mikseris</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Izvades kanāli:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Kanālu mikseris"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS spraudnis"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Kļūda pieslēdzoties MMS serverim"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (moduļu atskaņotājs)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Izšķirtspēja</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanāli</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Tuvākais (ātrākais)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineārs (ātrs)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Splaina (labs)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifāzes (labākais)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Iztveršanas temps</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "LÄ«menis:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Nogriešana:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Atbalss</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Basu pastiprinājums</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Ieskaušana</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Priekšpastiprinājums</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Pārdiskretizācija"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Trokšņu samazināšana"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Atskaņot Amiga MOD-us"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Atkārtot</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Atkārtojumu skaits:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Lai atkārtotu bezgalīgi, iestaties skaitu uz -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (moduļu atskaņotājs)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Ieskaušana"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Šie iestatījumi stāsies spēkā, pārstartējot Audacious."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 spraudnis"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Paplašināti</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Lietot precīzo ilguma aprēķināšanu (lēni)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Ieskaušana"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 serveris"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS spraudnis"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Kļūda parsējot pārvirzi"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Nezināma HTTP kļūda"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Kļūda parsējot URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Pārāk daudz pārviržu"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Apturēts"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious pašreiz neatskaņo."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Darbvirsmas paziņojumi"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2556,55 +2657,64 @@ msgstr ""
 "GNU Vispārējās Publiskās licences kopijai vajadzētu būt saņemtai kopā ar šo "
 "programmu. Ja tā nav, skatiet <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Rādīt atskaņošanas vadīklas"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Vienmēr rādīt paziņojumu"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Darbvirsmas paziņojumi"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Paziņojumā iekļaut albuma nosaukumu"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Rādīt"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pauze"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Nākamais"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. noklusētā ierīce"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 izvade"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 izvade"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Noklusētā ierīce"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Audio ierīce:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Lietot citu ierīci:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Saglabāt skaļumu starp sesijām."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Ieslēgt OSS programmatūras veiktās formāta pārveides."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Ieslēgt izņēmuma režīmu, lai novērstu virtuālo miksēšanu."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2618,19 +2728,35 @@ msgstr ""
 "Autors vēlas pateikties cilvēkiem kanālā #audacious, īpaši Tony Vroon un "
 "John Lindgren, un, protams, iepriekšējā OSS spraudņa autoriem."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 izvade"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Repertuāru pārvaldnieks"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Ieraksti"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Izņemt"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Pār_dēvēt"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS repertuāri"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 dekodētājs"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio izvade"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2664,11 +2790,73 @@ msgstr ""
 "Ja tā nav, rakstiet uz Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio izvade"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia izvade"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"QtMultimedia Audio izvades spraudnis atskaņotājam Audacious\n"
+"Autortiesības 2014 William Pitcock\n"
+"\n"
+"Bāzēts uz Audacious SDL izvades spraudņa\n"
+"Autortiesības 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Darbojas ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Meklēt"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Atvērt mapi ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Pievienot mapi ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Ž_urnāla inspektors ..."
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Atvērt failus"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Pievienot failus"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Iepriekšējais"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Atkārtot"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Jaukt"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt saskarne"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Diskretizācijas frekvences pārveidotājs"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2677,99 +2865,107 @@ msgstr ""
 "Audacious\n"
 "Autortiesības 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Izlaist/atkārtot paraugus"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineārā interpolācija"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Ātrā sinc interpolācija"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Vidējā sinc interpolācija"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Labākā sinc interpolācija"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Pārveidošana</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metode:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Temps:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Tempu kartējumi:</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Lietot tempu kartējumus"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Diskretizācijas frekvences pārveidotājs"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "Labi. Nosūta atskaņojumu lietotājam: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Pieeja liegta"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Nospiediet uz sekojošās saites, lai ļautu Audacious nosūtīt jūsu "
 "atskaņojumus:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Paturiet šo logu atvērtu un vēlreiz noklikšķiniet uz 'Pārbaudīt pieeju'.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2777,32 +2973,36 @@ msgstr ""
 "Neuztraucieties. Jūsu atskaņojumi ir saglabāti jūsu datorā.\n"
 "Tie tiks nosūtīti tiklīdz Audacious tiks dota atļauja."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Tīkla problēma."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Radās problēma, sazinoties ar Last.fm. Lūdzu, vēlāk mēģiniet vēlreiz."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Pārbauda..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "Pār_baudīt pieeju"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "At_celt pieeju"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "Jums jāatļauj Audacious nosūtīt atskaņojumu uz savu Last.fm kontu.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Atskaņojumu nosūtītājs 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2810,7 +3010,7 @@ msgstr ""
 "Neizdevās palaist atskaņojumu nosūtītāja spraudni.\n"
 "Iespējams, jūsu instalācijā radusies problēma."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2827,11 +3027,7 @@ msgstr ""
 "Paldies John Lindgren par palīdzību projekta sākumā.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Atskaņojumu nosūtītājs 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2839,7 +3035,11 @@ msgstr ""
 "Audacious pašlaik izmanto Last.fm atskaņojumu nosūtītāja uzlabotu versiju.\n"
 "Lūdzu, pārbaudiet atskaņojumu nosūtītāja spraudņa iestatījumus."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL izvade"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2847,88 +3047,59 @@ msgstr ""
 "SDL izvades spraudnis atskaņotājam Audacious\n"
 "Autortiesības 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL izvade"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Bibliotēka"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Nezināms izpildītājs"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Nezināms albums"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" albumā %s, izpilda %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d rezultātu"
+msgstr[1] "%d rezultāts"
+msgstr[2] "%d rezultāti"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d albums"
-msgstr[1] "%d albumi"
-msgstr[2] "%d albumu"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d paslēpti)"
+msgstr[1] "(%d paslēpts)"
+msgstr[2] "(%d paslēpti)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d dziesma"
-msgstr[1] ""
-"%s\n"
-" %s, %d dziesmas"
-msgstr[2] ""
-"%s\n"
-" %s, %d dziesmu"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d dziesma ar izpildītāju %s"
-msgstr[1] ""
-"%s\n"
-" %d dziesmas ar izpildītāju %s"
-msgstr[2] ""
-"%s\n"
-" %d dziesmu ar izpildītāju %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d dziesmu"
+msgstr[1] "%d dziesma"
+msgstr[2] "%d dziesmas"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "šajā žanrā"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "uz"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "izpilda"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "Iz_veidot repertuāru"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "Pi_evienot repertuāru"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Meklēt bibliotēkā"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2936,679 +3107,771 @@ msgstr ""
 "Lai importētu jūsu mūzikas bibleotēku atskaņotājā Audacious, izvēlieties "
 "mapi un nospiediet uz ikonas \"atsvaidzināt\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "LÅ«dzu, uzgaidiet ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Izvēlieties mapi"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID atskaņotājs"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Izvade</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanāli:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulācija</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emulēt MOS 8580 (noklusējums: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Neizdarīt automātisku čipa modeļa izvēli"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emulēt filtru"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Takts frekvence:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Neizdarīt automātisku takts frekvences izvēli"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Atskaņošanas laiks</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Iestatīt maksimālo atskaņošanas laiku:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Izmantot tikai, kad dziesmas ilgums nav zināms"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Iestatīt minimālo atskaņošanas laiku:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Apakšmelodijas</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Ieslēgt apakšmelodijas"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorēt apakšmelodijas, kas īsākas par:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nots</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Klusuma izņemšana"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Klusuma izņemšanas spraudnis atskaņotājam Audacious\n"
+"Autortiesības 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Klusuma izņemšana</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Slieksnis:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Atvērt failus ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Atvērt URL ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Meklēt bibliotēkā"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Atskaņošana"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Repertuārs"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Skatīt"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Servisi"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Par ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "iestatījumi ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Iziet"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Dziesmas info ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Atkārtot"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Jaukt"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Nevirzīties uz priekšu repertuārā"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Apturēt pēc pašreizējās dziesmas"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Iepriekšējais"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Uzstādīt A-B atkārtošanu"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Notīrīt A-B atkārtošanu"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Pāriet uz dziesmu ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Pāriet uz laiku ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Atskaņot šo repertuāru"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Atskaņot/Atsākt"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Jauns repertuārs"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Pārdēvēt repertuāru ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Izņemt repertuāru"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Iepriekšējais repertuārs"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Nākamais repertuārs"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importēt repertuāru ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Eksportēt repertuāru ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Repertuāru pārvaldnieks ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Rindas pārvaldnieks ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Atsvaidzināt repertuāru"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Rādīt repertuāra redaktoru"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Rādīt balansieri"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Rādīt atlikušo laiku"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Vienmēr virspusē"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Uz visām darbvirsmām"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Saritināt atskaņotāju"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Saritināt repertuāra redaktoru"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Saritināt balansieri"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dubultizmērs"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Pievienot URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Pievienot failus ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "PÄ“c nosaukuma"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "PÄ“c faila nosaukuma"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Pēc faila ceļa"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Izņemt visus"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Notīrīt ierindošanu"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Izņemt nepieejamos failus"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Izņemt dublikātus"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Izņemt neiezīmētos"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Izņemt iezīmētos"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Meklēt un iezīmēt"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Apgriezt iezīmēto"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Notīrīt iezīmējumu"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Iezīmēt visus"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "PÄ“c albuma"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Pēc celiņa numura"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Pēc izpildītāja"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "PÄ“c albuma"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Pēc albuma izpildītāja"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Pēc izlaišanas datuma"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Pēc celiņa numura"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Pēc žanra"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "PÄ“c ilguma"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Pēc pielāgotā nosaukuma"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Sajaukt repertuāru"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Apgriezt repertuāru"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Kārtot iezīmētos"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Kārtot repertuāru"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Izgriezt"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopēt"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Ielīmēt"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Ierindot/Izņemt no rindas"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Ielādēt sākumuzstādījumu ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Ielādēt auto-sākumuzstādījumu ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Ielādēt noklusēto"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Ielādēt sākumuzstādījumu no faila ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Ielādēt EQF failu ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Saglabāt sākumuzstādījumu ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Saglabāt auto-sākumuzstādījumu ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Saglabāt noklusēto"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Saglabāt sākumuzstādījumu failā ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Saglabāt EQF failu ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Dzēst sākumuzstādījumu ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Dzēst auto-sākumuzstādījumu ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importēt WinAMP sākumuzstādījumus ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Atstatīt uz nulli"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp klasiskā saskarne"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Saglabāt"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Ielādēt"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Ielādēt sākumuzstādījumu no faila"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Ielādēt EQF failu"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Saglabāt sākumuzstādījumu failā"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Saglabāt EQF failu"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importēt WinAMP sākumuzstādījumus"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Gatavie regulējumi"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Ielādēt sākumuzstādījumu"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Ielādēt auto-sākumuzstādījumu"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Saglabāt sākumuzstādījumu"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Saglabāt auto-sākumuzstādījumu"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Dzēst sākumuzstādījumu"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Dzēst auto-sākumuzstādījumu"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "A_tskaņotājs:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Atskaņotājs:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Izvēlieties galvenā atskaņotāja loga fontu:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "Re_pertuārs:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Repertuārs:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Izvēlieties repertuāra fontu:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Apdare</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Fonti</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Lietot bitmap fontus (atbalsta tikai ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Ritināt dziesmas nosaukumu"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Ritināt dziesmas nosaukumu abos virzienos"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizators"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Loks"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Balss vizualizēšana / VU mērītājs"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Izslēgts"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normāls"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Uguns"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Vertikālas līnijas"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "LÄ«nijas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Joslas"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Lēnākais"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "LÄ“ni"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Vidēji"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Ä€tri"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Ātrākais"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Punkti"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "LÄ«nijas"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Aizpildīts"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Ledus"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Gluds"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Tips</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Vizualizācijas tips:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizators</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Rādīt virsotnes"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Krāsa:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Stils:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Krišana:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Virsotņu krišana:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Loka stils:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Balss vizualizācijas krāsa:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU mērītāja stils:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Vispārīgi"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Vizualizēšana"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Priekšpastiprinājums"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious balansieris"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Pāriet uz %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Skaļums: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balanss: %d%% pa kreisi"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balanss: centrs"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balanss: %d%% pa labi"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Iestatījumu izvēlne"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Izslēgt 'Vienmēr virspusē'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Ieslēgt 'Vienmēr virspusē'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Faila info lodziņš"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Vizualizācijas"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Atkārtošanas punkts A iestatīts."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Atkārtošanas punkts B iestatīts."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Atkārtošanas punkti notīrīti."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Vieninstances režīms."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Repertuāra režīms."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Aptur pēc pašreizējās dziesmas."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Meklēt ierakstus aktīvajā repertuārā"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Meklēt"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3619,57 +3882,61 @@ msgstr ""
 "jāizmanto regulāro izteiksmju sintakse, reģistrnejutīga. Ja neziniet, kā "
 "regulārās izteiksmes darbojas, vienkārši nosaukuma daļu tam, ko meklējat."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Nosaukums: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Nosaukums:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Albums: "
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Izpildītājs: "
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Faila nosaukums: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Faila nosaukums:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Notīrīt iepriekšējo iezīmējumu pirms meklēšanas"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Automātiski pārslēgt ierindošanu atbilstošajiem ierakstiem"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Izveidot jaunu repertuāru no atbilstošajiem ierakstiem"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious repertuāra redaktors"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d of %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Arhivēta Winamp 2.x apdare"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Atarhivēta Winamp 2.x apdare"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Neizdevās izveidot mapi (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile spraudnis"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3708,82 +3975,71 @@ msgstr ""
 "Ja tā nav, rakstiet uz Free Software Foundation, Inc., 51 Franklin Street,\n"
 "Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile spraudnis"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Par Sndio izvades spraudni"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio izvade"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio izvades spraudnis\n"
-"\n"
-"Autors Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Ierīce (noklusētajai atstāt tukšu):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Neatbalstīts formāts"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Saglabāt un atjaunot skaļumu:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Tika pieprasīts formāts, ko neatbalsta audio ierīce.\n"
-"\n"
-"Lūdzu, mēģiniet vēlreiz ar palaistu sndiod(1) serveri."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio kļūda: neatbalstīts audio formāts (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio ierīce"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio kļūda: sio_open() neizdevās"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(tukšs nozīmē noklusētais)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio kļūda: sio_setpar() neizdevās"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Labi"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio kļūda: sio_start() neizdevās"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Dziesmas maiņa"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Komanda, ko palaist, kad Audacious sāk atskaņot jaunu dziesmu."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametrus, kuri tiek padoti čaulai, vajadzētu ietvert "
+"pēdiņās. Pretējā gadījumā rodas risks drošībai.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Komanda:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Komandas</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Komanda, ko palaist dziesmas beigās."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Komanda, ko palaist, sākot atskaņot jaunu dziesmu:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Komanda, ko palaist, kad Audacious sasniedz repertuāra beigas."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Komanda, ko palaist dziesmas beigās:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr ""
-"Komanda, ko palaist, kad nomainās dziesmas nosaukums (piem., tīkla plūsmas)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Komanda, ko palaist repertuāra beigās:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Komanda, ko palaist, kad nomainās dziesmas nosaukums (tīkla plūsmām):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3797,9 +4053,8 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Varat izmantot sekojoša formāta virknes, kuras\n"
-"pirms komandas izsaukšanas tiks aizvietotas\n"
-"(ne visas ir derīgas repertuāra-beigas komandai)\n"
+"Varat izmantot sekojoša formāta virknes, kuras pirms komandas izsaukšanas "
+"tiks aizvietotas (ne visas ir derīgas repertuāra-beigas komandai):\n"
 "\n"
 "%F: Frekvence (hercos)\n"
 "%c: Kanālu skaits\n"
@@ -3813,19 +4068,15 @@ msgstr ""
 "%b: Albums\n"
 "%T: Celiņa nosaukums"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Parametrus, kuri tiek padoti čaulai, vajadzētu ietvert "
-"pēdiņās. Pretējā gadījumā rodas risks drošībai.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Dziesmas info (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Komandas"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX diskretizācijas frekvences pārveidotājs"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3839,51 +4090,51 @@ msgstr ""
 "Balstīts uz diskretizācijas frekvences pārveidošanas spraudni:\n"
 "autortiesības 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Ä€tri"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Zema"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Augsta"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Ļoti augsta"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Kvalitāte:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX diskretizācijas frekvences pārveidotājs"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Ä€trums un augstums"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Ä€trums un augstums</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Ä€trums:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Augstums:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Ä€trums un augstums"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Statusa ikona"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Ies_tatījumi ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3901,39 +4152,39 @@ msgstr ""
 "Šis spraudnis nodrošina ar statusa ikonu, kas novietota\n"
 "sistēmas ikonu joslas apgabalā."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Peles rullīša darbība</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Mainīt skaļumu"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Mainīt atskaņojamo dziesmu"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Citi iestatījumi</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Atslēgt izlecošo logu"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Aizvērt sistēmas ikonu joslu"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Tinot uz augšu, pāriet uz priekšu repertuārā"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Statusa ikona"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Papildu stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3943,24 +4194,24 @@ msgstr ""
 "\n"
 "Autors Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Papildu stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Papildu stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Toņa ģenerators"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Toņa ģenerators: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3975,15 +4226,11 @@ msgstr ""
 "frekvence3;...\n"
 "piem., tone://2000;2005, lai atskaņotu 2000 Hz tonu un 2005 Hz toni"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Toņa ģenerators"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Balss izņemšana"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4020,11 +4267,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis dekodētājs"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detaļas par %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Nosaukums: %t\n"
+"Autors: %a\n"
+"No: %f\n"
+"Trakeris: %T\n"
+"Komentārs: %C\n"
+"ÄŒipa tips: %c\n"
+"Stereo: %s\n"
+"Cikls: %l\n"
+"ÄŒips frekvence: %F\n"
+"Atskaņotāja frekvence: %P\n"
+"Gads: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX dekodētājs"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4034,19 +4316,19 @@ msgstr ""
 "Balstīts uz in_vtx.dll, autors Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious spraudņa autors Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX dekodētājs"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack dekodētājs"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "zudumradošs (hibrīdais)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "zudumradošs"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4056,23 +4338,18 @@ msgstr ""
 "\n"
 "Daļai koda autors ir Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack dekodētājs"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF dekodētājs"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "XML kopīgojamie repertuāri (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF konfigurācija</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorēt ilgumu no faila"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "XML kopīgojamie repertuāri (XSPF)"
diff --git a/po/ml_IN.po b/po/ml_IN.po
index dcf4940d4566..747b462f566c 100644
--- a/po/ml_IN.po
+++ b/po/ml_IN.po
@@ -3,17 +3,17 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# nandakumar <nandakumar96 at gmail.com>, 2013
-# navaneeths52 <navaneeths52 at gmail.com>, 2013-2014
-# navaneeths52 <navaneeths52 at gmail.com>, 2013
-# STyM Alfaz, 2014
+# Nandakumar <nandakumar96 at gmail.com>, 2013
+# Navaneeth <inactive+navaneeths52 at transifex.com>, 2013-2014
+# Navaneeth <inactive+navaneeths52 at transifex.com>, 2013
+# ST Alfas, 2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Malayalam (India) (http://www.transifex.com/projects/p/"
 "audacious/language/ml_IN/)\n"
 "Language: ml_IN\n"
@@ -22,51 +22,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "മോണോ"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "സ്റ്റീരിയോ"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "സറൗണ്ട്"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib പ്ലേയര്‍)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "സീക്വന്‍സ്ഡ്"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib പ്ലേയര്‍)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "അലാം"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "അലാം"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -89,7 +73,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -111,7 +95,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -125,360 +109,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "ഇത് നിങ്ങളുടെ ഉണര്‍ത്തുപാട്ടാണ്."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "ഇന്നേയ്ക്കുള്ള നിങ്ങളുടെ സ്മാരകം: "
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "സ്മാരകം"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "തിങ്കളാഴ്ച"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "ചൊവ്വാഴ്ച"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "ബുധനാഴ്ച"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "വ്യാഴാഴ്ച"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "വെള്ളിയാഴ്ച"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "ശനിയാഴ്ച"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "ഞായറാഴ്ച"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "അലാം ക്രമീകരണങ്ങള്‍"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "സമയം"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "അലാം മുഴങ്ങേണ്ട സമയം (സ്വതവേയുള്ളത്):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "ശേഷം ശാന്തമാകൂ :"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "മണിക്കൂറുകള്‍"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "മിനിറ്റുകള്‍"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "അലാം മുഴങ്ങേണ്ട ദിനങ്ങള്‍ തെരെഞ്ഞെടുക്കുക"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "ദിവസം"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "സ്വതസ്സിദ്ധം"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "ദിവസങ്ങള്‍"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "മായുന്നു"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "സെക്കന്‍ഡുകള്‍"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "ഉച്ചത"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "ഇവിടെ തുടങ്ങുക"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "അവസാനത്തേത്"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "നിലവിലുള്ളത്"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "അധികകല്‍പ്പന"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "സാദ്ധ്യമാക്കുക"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "പ്ലേലിസ്റ്റ് (നിര്‍ബന്ധമില്ല)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "ഒരു പ്ലേലിസ്റ്റ് തിരഞ്ഞെടുക്കുക"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "ഓപ്ഷനുകള്‍"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "ഈ ഓപ്ഷനുകള്‍ എന്താണ് അര്‍ത്ഥമാക്കുന്നത്?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "സഹായം"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "ആല്‍ബം ആര്‍ട്ട്"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "അല്‍സ ഔട്പുട്ട്"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "സ്വതവേയുള്ള PCM ഉപകരണം"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "സ്വതവേയുള്ള മിക്സര്‍ ഉപകരണം"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM ഉപകരണം:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "മിക്സര്‍ ഉപകരണം:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "മിക്സര്‍ എലമെന്റ്:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "‍‍ഡ്രൈന്‍ ഹാങ്ങപ്പിന് ചുറ്റും പ്രവര്‍ത്തിക്കുക"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-പ്ലഗ്ഗ് (MIDI പ്ലേയര്‍)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "അല്‍സ ഔട്പുട്ട്"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-പ്ലഗ്ഗ് (MIDI പ്ലേയര്‍)"
-
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-പ്ലഗ്ഗ് - സൗണ്ട് ഫോണ്ട് തെരെഞ്ഞെടുക്കുക"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "ഫയല്‍നെയിം"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "ഫയല്‍ നെയിം"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "വലിപ്പം (ബൈറ്റുകള്‍)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "പേര്:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI വിവരങ്ങള്‍ </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "ഫോര്‍മാറ്റ്:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "നീളം (മില്ലി സെക്കന്‍ഡില്‍):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "ട്രാക്കുകളുടെ എണ്ണം:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "à´šà´°à´‚"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI വിവരണങ്ങളും വരികളും </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* ഈ MIDI ഫയലില്‍ നിലവിലുള്ള വിവരണങ്ങള്‍ ഒന്നുമില്ല *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* ഈ MIDI ഫയലില്‍ നിലവിലുള്ള വരികള്‍ ഒന്നുമില്ല *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_അടയ്ക്കുക"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(പ്രാബല്യമില്ലാത്ത UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI പ്ലഗ്ഗിനെപ്പറ്റി"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI പ്ലഗ്ഗ്"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -489,149 +479,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "ചതുരം"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "വക്കുവളഞ്ഞ ചതും"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "അവതലചതുരം"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "ശൂന്യം"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "പ്ലേബാക്ക് തുടങ്ങുക"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "തലക്കെട്ടിലെ മാറ്റം"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "പോസ് ഓണ്‍"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr ""
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "പോസ് ഓഫ്"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr ""
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "അവസ്ഥ"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "താരതമ്യേനയുള്ള X ഓഫ്‌സെറ്റ്"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "താരതമ്യേനയുള്ള Y ഓഫ്‌സെറ്റ്"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "പരമാവധി OSD നീളം"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "മള്‍ട്ടി മോണിറ്റര്‍ ക്രമീകരണങ്ങള്‍"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "എല്ലാ മോണിറ്ററുകളും"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "മോണിറ്റര്‍ %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr ""
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "ഡിസ്പ്ലേ:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "ഫെയ്ഡ് ഇന്‍:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "ഫെയ്ഡ് ഔട്ട്"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "ഫോണ്ടുകള്‍"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "ഫോണ്ട് %i"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "നിഴല്‍"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "റെന്‍ഡര്‍ സ്റ്റൈല്‍"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "നിറങ്ങള്‍"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "നിറം %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "കാഞ്ചി സാദ്ധ്യമാക്കുക"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "സംഭവം"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "കമ്പോസിറ്റ് മാനേജര്‍ ശ്രദ്ധയില്‍ പെട്ടു"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -641,112 +628,112 @@ msgstr ""
 "മറ്റൊന്ന് പ്രവര്‍ത്തിക്കുന്നത് നിങ്ങള്‍ക്കറിയാമെങ്കില്‍, ദയവ് ചെയ്ത് ഒരു കമ്പോസിറ്റ് മാനേജര്‍ "
 "പ്രാവര്‍ത്തികമാക്കുക അല്ലെങ്കില്‍ OSD പ്രവര്‍ത്തിച്ചില്ലെന്ന് വരാം"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "വ്യാജമായ സുതാര്യതയ്ക്ക് കമ്പോസിറ്റ് മാനേജര്‍ ആവശ്യമില്ല"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "സുതാര്യത"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "കപടസുതാര്യത"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "യഥാര്‍ത്ഥ സുതാര്യത (X composite Ext. ആവശ്യമുണ്ട്)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "കോമ്പോസിറ്റ് എക്സ്റ്റന്‍ഷന്‍ നിലവില്‍ വന്നിട്ടില്ല"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "കോമ്പോസിറ്റ് എക്സ്റ്റന്‍ഷന്‍ നിലവിലില്ല"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>ഒഡാഷ്യസ് OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "ഒഡാഷ്യസ് OSD ക്രമീകരണം"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "സ്ഥാനം"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "അനിമേഷന്‍"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "എഴുത്ത്"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "അലങ്കാരം"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "കാഞ്ചി"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "പലവക"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>നിറം</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "ബ്ലര്‍ സ്കോപ്പ്"
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
-msgstr "ഫീഡ് ലെവല്‍:"
-
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
-msgstr "ആവൃത്തി മുറിയ്ക്കുക:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr ""
 
-#: src/bs2b/plugin.c:166
+#: src/bs2b/plugin.cc:129
 msgid "Presets:"
 msgstr "പ്രീസെറ്റുകള്‍:"
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr "ഫീഡ് ലെവല്‍:"
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "ആവൃത്തി മുറിയ്ക്കുക:"
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "സ്പെക്ട്രം അനലൈസര്‍"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "ഓഡിയോ സി.ഡി. പ്ലഗ്ഗിന്‍"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -758,169 +745,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>ഉപകരണം</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "വായനയുടെ വേഗം:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>മെറ്റാഡേറ്റ</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "സി.ഡി.-ടെക്സ്റ്റ് ഉപയോഗിയ്ക്കുക"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB ഉപയോഗിയ്ക്കുക"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP യ്ക്ക് പകരം HTTP ഉപയോഗിക്കാം"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "സെര്‍വര്‍:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "പാത്ത്:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "പോര്‍ട്ട്:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "ഓഡിയോ സി.ഡി. പ്ലഗ്ഗിന്‍"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "അസാധുവായ URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "ട്രാക്ക് %d കണ്ടുകിട്ടിയില്ല."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "ട്രാക്ക് %d ഒരു ഡേറ്റാ ട്രാക്ക് ആണ്."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "ഓഡിയോ ഔട്പുട്ട് തുറക്കുന്നതില്‍ പരാജയപ്പെട്ടു."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "ഓഡിയോ സി.ഡി. വായിയ്ക്കുന്നതില്‍ പിശക്."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "ഓഡിയോ സി.ഡി."
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "സി.ഡി. ഉപകരണം %s തുറക്കുന്നതില്‍ പരാജയപ്പെട്ടു."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "ഓഡിയോ ശേഷിയുള്ള സി.ഡി. ഡ്രൈവ് കണ്ടുകിട്ടിയില്ല."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "cddb ബന്ധം സാദ്ധ്യമാക്കുന്നതില്‍ പരാജയപ്പെട്ടു."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "cddb ഇന്‍ഫോ വായിയ്ക്കുന്നതില്‍ പരാജയം: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "ഡ്രൈവ് ശൂന്യമാണ്."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "പിന്തുണയില്ലാത്ത തരം ഡിസ്ക്."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "ഓഡിയോ സി.ഡി. മെനു അംഗങ്ങള്‍"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "സി.ഡി. പാടുക"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "സി.ഡി. ചേര്‍ക്കുക"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "ഓഡിയോ സി.ഡി. മെനു അംഗങ്ങള്‍"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>കംപ്രഷന്‍</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "ഉറവിടത്തിലെ ഉച്ചത:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "ഡൈനാമിക് റെയ്ഞ്ച്:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -930,195 +904,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "ബേസ്:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "ട്രെബ്ള്‍:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "പാട്ടിന്റെ സ്വതസ്സിദ്ധമായ നീളം"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>റീസാംപ്ലിങ്</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "ഓഡിയോ റീസാംപ്ലിങ് സാദ്ധ്യമാക്കുക"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "റീസാംപ്ലിങ് നിരക്ക്:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC ഉപനാമങ്ങളില്‍ നിന്നും നീളം അവഗണിക്കുക"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "പ്രതിദ്ധ്വനി കൂട്ടുക"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "ഗെയിം കണ്‍സോള്‍ മ്യൂസിക് ഡീകോഡര്‍"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>ക്രോസ്‌ഫെയ്ഡ്</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "ഓവര്‍ലാപ്പ്:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "ക്രോസ്‌ഫെയ്ഡ്"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>ക്രിസ്റ്റലൈസര്‍</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "തീവ്രത:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "ക്രിസ്റ്റലൈസര്‍"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "നീക്കം ചെയ്യുക"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "റദ്ദാക്കുക"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>പ്രതിധ്വനി</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "താമസം:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr ""
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "അഭിപ്രായം:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "ശബ്ദോച്ചത:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "പ്രതിധ്വനി"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg പ്ലഗ്ഗിന്‍"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1128,55 +1127,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg പ്ലഗ്ഗിന്‍"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter പ്ലഗ്ഗിന്‍"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "ഔട്പുട്ട് ഫയല്‍ ഫോര്‍മാറ്റ്:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "ക്രമീകരിയ്ക്കുക"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "യഥാര്‍ത്ഥഡയറക്റ്ററിയിലേയ്ക്ക സേവ് ചെയ്യുക"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "സ്വേച്ഛയാലുള്ള ഡയറക്റ്ററിയിലേയ്ക്ക് സേവ് ചെയ്യുക"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "ഔട്പുട്ട് ഫയല്‍ ഫോള്‍ഡര്‍:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "ഒരു ഫോള്‍ഡര്‍ തിരഞ്ഞെടുക്കുക"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "ഫയല്‍നാമം ലഭിക്കുന്നത്:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "യഥാര്‍ത്ഥ ഫയല്‍ ടാഗുകള്‍"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "യഥാര്‍ത്ഥ ഫയല്‍നെയിം"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "ഫയല്‍നാമത്തിന്റെ വിപുലീകരണം ഭാഗിക്കരുത്"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "ട്രാക്ക് സംഖ്യ ഫയല്‍നാമത്തിന് മുന്നിലായി ചേർക്കുക"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1194,165 +1193,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter പ്ലഗ്ഗിന്‍"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "സ്വയം"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "കൂട്ടിച്ചേര്‍ത്ത സ്റ്റീരിയോ"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "സ്റ്റീരിയോ"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "മോണോ"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 ക്രമീകരണം"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "ഓല്‍ഗൊരിതം ഗുണമേന്മ:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "ഔട്പുട്ട് സാംപിള്‍നിരക്ക്:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "ബൈട്രേറ്റ് / കംപ്രഷന്‍ അനുപാതം"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "ബിറ്റ്‌റേറ്റ് (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "കംപ്രഷന്‍ നിരക്ക്:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "ഓഡിയോ മോഡ്:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "പലവക:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "ISO ഒതുക്കം കര്‍ശനമായി നിര്‍ബന്ധിക്കുക"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "സംരക്ഷണ പിശക്"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "ഗുണമേന്മ"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR സാദ്ധ്യമാക്കുക"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "തരം:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR ഓപ്ഷനുകള്‍"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "കുറഞ്ഞ ബിറ്റ്‌റേറ്റ് (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "പരമാവധി ബിറ്റ്‌റേറ്റ് (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "ചുരുങ്ങിയ ബൈട്രേറ്റ് കര്‍ശനമായി നിര്‍ബന്ധിക്കുക"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR ക്രമീകരണങ്ങള്‍:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "ശരാശരി ബിറ്റ്റേറ്റ് (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR ഗുണനിലവാരം:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR തലക്കെട്ട് എഴുതുന്നത് ഒഴിവാക്കാം"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "ഫ്രേം പരാമീറ്ററുകള്‍:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "കോപ്പിറൈറ്റടായി അടയാളപ്പെടുത്തുക"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "പ്രഥമമായി അടയാളപ്പെടുത്തുക"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 പാരംസ്"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "വെര്‍ഷന്‍ 2 ടാഗിന്റെ സംയോഗം നിര്‍ബന്ധിക്കുക"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "v1 ടാഗ് മാത്രം സംയോഗിക്കുക"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "v2 ടാഗ് മാത്രം സംയോഗിക്കുക"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "ടാഗുകള്‍"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "വോര്‍ബിസ് എന്‍കോഡര്‍ ക്രമീകരണം"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "ഗുണനിലവാരം ( 0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC ഡീകോഡര്‍"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "ലോസ്‌ലെസ്സ്"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1360,21 +1363,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC ഡീകോഡര്‍"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO പ്ലഗ്ഗിന്‍"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1386,530 +1393,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL സ്പെക്ട്രം അനലൈസര്‍"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "ഗ്നോം എളുപ്പവഴികള്‍"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "എന്‍ട്രി നമ്പര്‍"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "ടൈറ്റില്‍"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "ആര്‍ട്ടിസ്റ്റ്"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "വര്‍ഷം"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "ആല്‍ബം"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "ട്രാക്ക്"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "തരം"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "വരിയിലുള്ള സ്ഥാനം"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "നീളം"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "ഫയല്‍ പാത്ത്"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "ഫയല്‍ നെയിം"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "സ്വേച്ഛയാലുള്ള തലക്കെട്ട്"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "ബിറ്റ്‌റേറ്റ്"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "തിരച്ചില്‍ ടുള്‍"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "ഇടതുവശത്ത് ഡോക്ക് ചെയ്യുക"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "വലതുവശത്ത് ഡോക്ക് ചെയ്യുക"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "മുകളില്‍ ഡോക്ക് ചെയ്യുക"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "താഴെ ഡോക്ക് ചെയ്യുക"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "ഡോക്കിങ് ഒഴിവാക്കുക"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "അസാദ്ധ്യമാക്കുക"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "തിരച്ചില്‍ ടുള്‍"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "ഫയലുകള്‍ _തുറക്കുക ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "_URL തുറക്കുക"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_ഫയലുകള്‍ ചേര്‍ക്കുക"
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL ചേര്‍ക്കുക"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_ഇതേപ്പറ്റി ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_പുറത്തുകടക്കുക"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_പാടുക"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "പോ_സ് ചെയ്യുക"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_നിര്‍ത്തുക"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_മുമ്പത്തേത്"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_അടുത്തത്"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_ആവര്‍ത്തിയ്ക്കുക"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_കശക്കുക"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_o  പ്ലേലിസ്റ്റ് പുരോഗമനം"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "_ഈ പാട്ട് കഴിഞ്ഞാല്‍ നിര്‍ത്തുക"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "സോങ് ഇന്‍ഫോ ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_സമയത്തിലേക്ക് ചാടുക ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "പാട്ടിലേക്ക് _ചാടുക ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "_ടൈറ്റില്‍ അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "_ഫയല്‍നെയിം അനുസരിച്ച്"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "ഫയല്‍_പാത്ത് അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "ട്രാക്ക് _നമ്പര്‍ അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "_ആര്‍ട്ടിസ്റ്റിനനുസരിച്ച്"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "ആ_ല്‍ബമനുസരിച്ച്"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "റിലീസ് ഡേറ്റ് അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "_നീളമനുസരിച്ച്"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "ഫയല്‍ പാത്ത് അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "സ്വേച്ഛയാലുള്ള തലക്കെട്ട് അനുസരിച്ച്"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "നേ_ര്‍വിപരീത രീതി"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_ക്രമമില്ലാത്ത രീതി"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "ഈ പ്ലേലിസ്റ്റ് _പാടുക"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "പു_തുക്കുക"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_ക്രമത്തിലാക്കുക"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "_പകര്‍പ്പുകള്‍ നീക്കം ചെയ്യുക"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "_ലഭ്യമല്ലാത്ത ഫയലുകള്‍ നീക്കം ചെയ്യുക"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_പുതിയത്"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "പേര് _മാറ്റുക"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_ഇറക്കുമതി ചെയ്യുക ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_കയറ്റുമതി ചെയ്യുക ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "പ്ലേലിസ്റ്റ് _മാനേജര്‍ ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "ക്യൂ മാനേജര്‍ ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "ശബ്ദം കൂട്ടുക (_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "ശബ്ദം കുറയ്ക്കുക (_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_ഈക്വലൈസര്‍"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_മെനുബാര്‍ കാണിയ്ക്കുക"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "_ഇന്‍ഫോബാര്‍ കാണിയ്ക്കുക"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_സ്റ്റാറ്റസ്ബാര്‍ കാണിയ്ക്കുക"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "_അവശേഷിക്കുന്ന സമയം കാണിക്കുക"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_ഫയല്‍"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_പ്ലേബാക്ക്"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "പ്ലേ_ലിസ്റ്റ്"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_സേവനങ്ങള്‍"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_ഔട്പുട്ട്"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_കാഴ്ച"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_ക്യൂ/അണ്‍ക്യൂ"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_മുറിയ്ക്കുക"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_പകര്‍ത്തുക"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_ഒട്ടിയ്ക്കുക"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_എല്ലാം തിരഞ്ഞെടുക്കുക"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "പേര് _മാറ്റുക ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>പലവക</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK ഇന്‍ഡര്‍ഫേസ്"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - ഒഡാഷ്യസ്"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "ബഫര്‍ ചെയ്യുന്നു ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "ഒഡാഷ്യസ്"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "മോണോ"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "സ്റ്റീരിയോ"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d ചാനല്‍"
 msgstr[1] "%d ചാനലുകള്‍"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "സിംഗ്ള്‍ മോഡ്"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "പ്ലേലിസ്റ്റ് മോഡ്"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "പാട്ടിനു ശേഷം നിര്‍ത്തുന്നു."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "മുമ്പത്തെ ട്രാക്ക്"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "പാടുക"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "പോസ്/റെസ്യൂം"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "നിര്‍ത്തുക"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "അടുത്ത ട്രാക്ക്"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 സെക്കന്‍ഡ് മുന്നോട്ട്"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 സെക്കന്‍ഡ് പിന്നോട്ട്"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "നിശ്ശബ്ദമാക്കുക"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "ശബ്ദം കൂട്ടുക"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "ശബ്ദം കുറയ്ക്കുക"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "ഫയലിലേയ്ക്ക് ചാടുക"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "ഓണ്‍-സ്ക്രീന്‍-ഡിസ്‌പ്ലേ കാണിയ്ക്കുക"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ശൂന്യം)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1920,15 +2004,11 @@ msgstr ""
 "\n"
 "നിങ്ങള്‍ക്ക് തുടരാന്‍ താല്പര്യമുണ്ടോ ?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "മൗസ് ബട്ടണുകള്‍ ബൈന്റ് ചെയ്യുന്നു"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "ആഗോള ഹോട്ട് കീ പ്ലഗിന്‍ ക്രമീകരണം"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1936,23 +2016,27 @@ msgstr ""
 "ടെക്സ്റ്റ് ഫീല്‍ഡിനുള്ളില്‍ ഒരു കീ കോമ്പിനേഷന്‍ അമര്‍ത്തുക.\n"
 "മൗസ് ബട്ടണുകളും നിങ്ങള്‍ക്ക് ബൈന്‍ഡ് ചെയ്യാം."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "ഹോട്കീകള്‍"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>പ്രവൃത്തി:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>കീ ബൈന്റിങ്:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1967,124 +2051,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "ജാക്ക് ഔട്പുട്ട്"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "ജാക്ക് ഔട്പുട്ട്"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s ക്രമീകരണങ്ങള്‍"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA ഹോസ്റ്റ് ക്രമീകരണങ്ങള്‍"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "മൊഡ്യൂള്‍ പാത്തുകള്‍:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "ലഭ്യമായ പ്ലഗ്ഗിന്നുകള്‍:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "സാദ്ധ്യമാക്കുക"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "പ്ലഗ്ഗിനുകള്‍ സാദ്ധ്യമാക്കുക:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "ക്രമീകരണങ്ങള്‍"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA ഹോസ്റ്റ്"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: പുനര്‍ബന്ധനത്തിന് ശ്രമിക്കുന്നു...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s അജ്ഞാതമായ കമാന്റ് \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC യില്‍ നിന്നും ബന്ധം വേര്‍പെടുത്തി\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: എല്ലാ %d സെക്കന്‍ഡുകളിലും പുനര്‍ബന്ധത്തിന് ശ്രമിക്കും...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC പ്ലഗ്ഗിന്‍"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2100,73 +2150,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>ബന്ധം</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "LIRC സെര്‍വറുമായി വീണ്ടും ബന്ധിപ്പിയ്ക്കുക"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "പുനര്‍ബന്ധത്തിനു മുമ്പ് കാത്തിരിക്കുക:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC പ്ലഗ്ഗിന്‍"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki പ്ലഗ്ഗിന്‍"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "വരികള്‌ ലഭ്യമല്ല"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "പിശക്"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "പിശക്"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "വരികള്‍ക്കായി നോക്കുന്നു ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "ചില മെറ്റാഡേറ്റ ലഭ്യമല്ല"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki പ്ലഗ്ഗിന്‍"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U പ്ലേലിസ്റ്റുകള്‍"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "ടാക്റ്റ് ജനറേറ്റര്‍"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr ""
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr ""
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2175,162 +2233,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "ടാക്റ്റ് ജനറേറ്റര്‍"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "ചാനല്‍ മിക്സര്‍"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>ചാനല്‍ മിക്സര്‍</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "ഔട്പുട്ട് ചാനലുകള്‍:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "ചാനല്‍ മിക്സര്‍"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS പ്ലഗ്ഗിന്‍"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>റെസല്യൂഷന്‍</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-ബിറ്റ്"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-ബിറ്റ്"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>ചാനലുകള്‍</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "ഏറ്റവും അടുത്തുള്ളത് (ഏറ്റവും വേഗതയുള്ളത്)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>സാംപ്ലിങ് നിരക്ക്</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "തലം:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "കട്ടോഫ്:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b> പ്രതിധ്വനി </b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>ബേസ് ബൂസ്റ്റ്</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>സറൗണ്ട്</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>പ്രീആംപ്</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "ഓവര്‍സാമ്പ്ള്‍"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "നോയ്സ് റിഡക്ഷന്‍"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>ആവര്‍ത്തിയ്ക്കുക</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "ആവര്‍ത്തങ്ങളുടെ എണ്ണം:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "സറൗണ്ട്"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 പ്ലഗ്ഗിന്‍"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "സറൗണ്ട്"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 സെര്‍വര്‍"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "നിര്‍ത്തി"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "ഒഡാഷ്യസ് പ്രവര്‍ത്തിക്കുന്നില്ല."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "ഡെസ്ക്ടോപ്പ് അറിയിപ്പുകള്‍"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2350,55 +2440,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "പ്ലേബാക്ക് ക്രമീകരണങ്ങള്‍ കാണിക്കുക"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "എല്ലായ്പ്പോഴും വിജ്ഞാപനങ്ങള്‍ കാണിക്കുക"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "ഡെസ്ക്ടോപ്പ് അറിയിപ്പുകള്‍"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "കാണിയ്ക്കുക"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "പോസ് ചെയ്യുക"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "അടുത്തത്"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. സ്വതവേയുള്ള ഉപകരണം"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 ഔട്പുട്ട്"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "ഓഡിയോ ഉപകരണം:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "ബദല്‍ ഉപകരണം ഉപയോഗിയ്ക്കുക"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "സെഷനുകളുടെ ഇടയിലുള്ള ഉച്ചത സേവ് ചെയ്യുക."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "OSS സോഫ്റ്റ്വെയര്‍ തയ്യാറാക്കിയ ഫോര്‍മാറ്റ് മാറ്റങ്ങള്‍ സാധ്യമാക്കുക."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2407,19 +2506,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 ഔട്പുട്ട്"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS പ്ലേലിസ്റ്റുകള്‍"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "പള്‍സ്‌ഓഡിയോ ഔട്പുട്ട്"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2439,143 +2554,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "പള്‍സ്‌ഓഡിയോ ഔട്പുട്ട്"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "മുമ്പത്തേത്"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "ആവര്‍ത്തിയ്ക്കുക"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "കശക്കുക"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr ""
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>കണ്‍വേര്‍ഷന്‍</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "രീതി:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "തോത്:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr ""
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "അനുവാദം ഇല്ല"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "നെറ്റ്‌വര്‍ക്ക് കുഴപ്പം."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "പരിശോധിക്കുന്നു..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "സ്‌ക്രോബ്ബ്ലര്‍ 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2586,765 +2770,840 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "സ്‌ക്രോബ്ബ്ലര്‍ 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "ഗ്രന്ഥശാല"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "അജ്ഞാതനായ കലാകാരന്‍"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "അജ്ഞാതമായ പാട്ട്"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d പാട്ട്"
-msgstr[1] "%d പാട്ടുകള്‍"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "പ്ലേലിസ്റ്റ് _നിര്‍മിക്കുക"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "പ്ലേലിസ്റ്റിലേയ്ക്ക് _ചേര്‍ക്കുക"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "ഗ്രന്ഥശാല തിരയുക"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "ദയവായി കാത്തിരിക്കുക ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "ഫോള്‍ഡര്‍ തെരെഞ്ഞെടുക്കുക"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "പ്ലേബാക്ക്"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "പ്ലേലിസ്റ്റ്"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "കാണുക"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "ആവര്‍ത്തിയ്ക്കുക"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "കശക്കുക"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr ""
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "മുമ്പത്തേത്"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "പുതിയ പ്ലേലിസ്റ്റ്"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "പ്ലേലിസ്റ്റ് എഡിറ്റര്‍ കാണിക്കുക"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "ഈക്വലൈര്‍ പ്രദര്‍ശിപ്പിയ്ക്കുക"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "എപ്പോഴും മുകളില്‍"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "ടൈറ്റിലിനനുസരിച്ച്"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "ഫയല്‍നെയിമനുസരിച്ച്"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "എല്ലാം നീക്കം ചെയ്യുക"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "വരി വെടിപ്പാക്കുക"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "ലഭ്യമല്ലാത്ത ഫയലുകള്‍ നീക്കംചെയ്യുക"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "പകര്‍പ്പുകള്‍ ഒഴിവാക്കുക"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "തിരഞ്ഞെടുക്കാത്തവ നീക്കംചെയ്യുക"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "തിരഞ്ഞെടുത്തവ നീക്കംചെയ്യുക"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "തിരയുക, തിരഞ്ഞെടുക്കുക"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "തിരഞ്ഞെടുപ്പ് ഇന്‍വേര്‍ട്ട് ചെയ്യുക"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "ഒന്നും തിരഞ്ഞെടുക്കേണ്ട"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "എ​ല്ലാം തിരഞ്ഞെടുക്കുക"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "ആല്‍ബമനുസരിച്ച്"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "ട്രാക്ക് നമ്പര്‍ അനുസരിച്ച്"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "ആര്‍ട്ടസ്റ്റിനനുസരിച്ച്"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "ആല്‍ബമനുസരിച്ച്"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "ട്രാക്ക് നമ്പര്‍ അനുസരിച്ച്"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "ലിസ്റ്റ് ക്രമമില്ലാതെയാക്കുക"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "പട്ടിക തലതിരിയ്ക്കുക"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "തിരഞ്ഞെടുത്തവ ക്രമീകരിയ്ക്കുക"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "പട്ടിക അക്ഷരമാലാക്രമത്തിലാക്കുക"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "മുറിയ്ക്കുക"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "പകര്‍ത്തുക"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "ഒട്ടിയ്ക്കുക"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "സേവ്"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "ലോഡ് ചെയ്യുക"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "പ്രീസെറ്റുകള്‍"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "പ്രീസെറ്റ് ലോഡ് ചെയ്യുക"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "ഓട്ടോ-പ്രീസെറ്റ് ലോഡ് ചെയ്യുക"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "പ്രീസെറ്റ് സേവ് ചെയ്യുക"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "ഓട്ടോ പ്രീസെറ്റ് സേവ് ചെയ്യുക"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "പ്രീസെറ്റ് നീക്കംചെയ്യുക"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "ഓട്ടോ പ്രീസെറ്റ് നീക്കം ചെയ്യുക"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_പ്ലേയര്‍:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "പ്രധാനപ്പെട്ട പ്ലെയര്‍ വിന്‍ഡോയുടെ ഫോണ്ട് തെരെഞ്ഞെടുക്കുക:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "പ്ലേ_ലിസ്റ്റ്:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "പ്ലേലിസ്റ്റ് ഫോണ്ട് തെരെഞ്ഞെടുക്കുക:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "ബിറ്റ്മാപ് ഫോണ്ടുകള്‍ ഉപയോഗിക്കാം (ASCII മാത്രം പിന്‍തുണയ്ക്കും)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "രണ്ട് ദിശകളിലും പാട്ടിന്റെ ശീര്‍ഷകം സ്‌ക്രോള്‍ ചെയ്യുക"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "അനലൈസര്‍"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "സ്കോപ്പ്"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "ഓഫ്"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "സാധാരണം"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "തീ"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "വരകള്‍"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "നാടകള്‍"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "വളരെപ്പതുക്കെ"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "പതുക്കെ"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "പാകം"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "വേഗം"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "അതിദ്രുതം"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "ഐസ്"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "മൃദുലം"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "പൊതുവായവ"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "ദൃശ്യവത്കരണം"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "പ്രീആംപ്"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "ഒഡാഷ്യസ് ഈക്വലൈസര്‍"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "തിരയുക %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "ശബ്ദം: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "അവശേഷിക്കുന്നത്: %d%% വലത്"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "അവശേഷിക്കുന്നത്: നടുവില്‍"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "അവശേഷിക്കുന്നത്: %d%% ഇടത്"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "ഓപ്ഷന്‍സ് മെനു"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "'എപ്പോഴും മുകളില്‍' അസാദ്ധ്യമാക്കുക"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "'എപ്പോഴും മുകളില്‍' സാദ്ധ്യമാക്കുക"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "ഫയല്‍ ഇന്‍ഫോ ജാലകം"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "സിംഗ്ള്‍ മോഡ്"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "പ്ലേലിസ്റ്റ് മോഡ്"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "പാട്ടിനു ശേഷം നിര്‍ത്തുന്നു."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "സജീവമായ പ്ലേലിസ്റ്റിലെ എന്‍ട്രികള്‍ തിരയുക"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3352,57 +3611,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "ടൈറ്റില്‍:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "ആല്‍ബം:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "ആര്‍ട്ടിസ്റ്റ്:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "ഫയല്‍നാമം:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "തിരയുന്നതിനുമുമ്പ് മുമ്പുള്ള തിരഞ്ഞെടുപ്പ് വെടിപ്പാക്കുക"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "യോജിയ്ക്കുന്ന എന്‍ട്രികള്‍ ഉപയോഗിച്ച് പുതിയൊരു പ്ലേലിസ്റ്റ് ഉണ്ടാക്കുക"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "ഒഡാഷ്യസ് പ്ലേലിസ്റ്റ് എഡിറ്റര്‍"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d / %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "ശേഖരിക്കപ്പെട്ട വിനാമ്പ് 2.x രൂപം"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "ശേഖരിക്കാത്ത വിനാമ്പ് 2.x രൂപം"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "ഫോള്‍ഡര്‍ നിര്‍മാണം സാധ്യമല്ല (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile പ്ലഗ്ഗിന്‍"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3424,76 +3687,69 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile പ്ലഗ്ഗിന്‍"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "പിന്തുണയില്ലാത്ത ഫോര്‍മാറ്റ്"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(ശുന്യം എന്ന് അര്‍ത്ഥമാക്കുന്നത് സ്വതസ്സിദ്ധത്തെയാണ്)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "ശരി"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "പാട്ട് മാറ്റുക"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "ഒഡാഷ്യസ് പുതിയ പാട്ട് ആരംഭിക്കുമ്പോള്‍ പ്രവര്‍ത്തിപ്പിക്കാനുള്ള കമാന്റ്."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "കല്‍പ്പന:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "പാട്ടിന്റെ അവസാനത്തിലേക്ക് റണ്‍ ചെയ്യാന്‍ വേണ്ട കമാന്റ്."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "ഒഡാഷ്യസ് പ്ലേലിസ്റ്റിന്റെ അവസാനത്തിലേയ്ക്ക് എത്തുമ്പോള്‍ റണ്‍ ചെയ്യാന്‍ വേണ്ട കമാന്റ്."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"പാട്ടിന്റെ ശീര്‍ഷകം മാറുമ്പോള്‍ റണ്‍ ചെയ്യുന്ന കമാന്റ് (അതായത് നെറ്റ്‌വര്‍ക്ക് സ്‌ട്രീമുകളുടെ ശീര്‍ഷകങ്ങള്‍)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3508,17 +3764,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "കല്‍പ്പനകള്‍"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX റീസാംപ്ലര്‍"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3527,51 +3781,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "ദ്രുതം"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "താഴ്ന്നത്"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "ഉയര്‍ന്നത്"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "വളരെ ഉയര്‍ന്നത്"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "ഗുണമേന്മ:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX റീസാംപ്ലര്‍"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "വേഗവും ശ്രുതിയും"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>വേഗവും ശ്രുതിയും</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "വേഗം:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "ശ്രൂതി:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "വേഗവും ശ്രുതിയും"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "സ്റ്റാറ്റസ് ഐക്കണ്‍"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3582,63 +3836,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "ശബ്ദോച്ചത മാറ്റുക"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "പാടുന്ന പാട്ട് മാറ്റുക"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>മറ്റു ക്രമീകരണങ്ങള്‍</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "പോപ്പപ്പ് ജാലകം അസാദ്ധ്യമാക്കുക"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "സിസ്റ്റം ട്രേയിലേയ്ക്ക് അടച്ചിടുക"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "സ്റ്റാറ്റസ് ഐക്കണ്‍"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "എക്സ്ട്രാ സ്റ്റീരിയോ"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>എക്സ്ട്രാ സ്റ്റീരിയോ</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "എക്സ്ട്രാ സ്റ്റീരിയോ"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "ടോണ്‍ ജനറേറ്റര്‍"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "ടോണ്‍ ജനറേറ്റര്‍: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3647,15 +3901,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "ടോണ്‍ ജനറേറ്റര്‍"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "വോയ്സ് റിമൂവല്‍"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3676,44 +3926,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis ഡീകോഡര്‍"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX ഡീകോഡര്‍"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX ഡീകോഡര്‍"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack ഡീകോഡര്‍"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "ലോസി (സങ്കരം)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "ലോസി"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack ഡീകോഡര്‍"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF ഡീകോഡര്‍"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/ms.po b/po/ms.po
new file mode 100644
index 000000000000..9a99a85c84d7
--- /dev/null
+++ b/po/ms.po
@@ -0,0 +1,4352 @@
+# Malay translation for Audacious Plugins
+# Copyright (C) Audacious translators
+# This file is distributed under the same license as the Audacious Plugins package.
+#
+# Translators:
+# abuyop <abuyop at gmail.com>, 2014-2015
+# Mick The KN <f.seedsss at gmail.com>, 2012
+msgid ""
+msgstr ""
+"Project-Id-Version: Audacious Plugins\n"
+"Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-09 15:08+0000\n"
+"Last-Translator: abuyop <abuyop at gmail.com>\n"
+"Language-Team: Malay (http://www.transifex.com/projects/p/audacious/language/"
+"ms/)\n"
+"Language: ms\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
+msgstr "Penyahkod AAC (Raw)"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Pemain AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "berjujukan"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Penggera"
+
+#: src/alarm/alarm.cc:782
+msgid "Set Alarm ..."
+msgstr "Tetapkan Penggera ..."
+
+#: src/alarm/alarm.cc:810
+msgid ""
+"A plugin that can be used to start playing at a certain time.\n"
+"\n"
+"Originally written by Adam Feakin and Daniel Stodden."
+msgstr ""
+"Pemalam yang boleh digunakan untuk mula memainkan pada\n"
+"masa tertentu.\n"
+"\n"
+"Asalnya ditulis oleh Adam Feakin dan Daniel Stodden."
+
+#: src/alarm/interface.cc:28
+msgid ""
+"Time\n"
+"  Alarm at:\n"
+"    The time for the alarm to come on.\n"
+"\n"
+"  Quiet after:\n"
+"    Stop alarm after this amount of time.\n"
+"       (if the wakeup dialog is not closed)\n"
+"\n"
+"\n"
+"Days\n"
+"  Day:\n"
+"    Select the days for the alarm to activate.\n"
+"\n"
+"  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"
+msgstr ""
+"Masa\n"
+"  Penggera pada:\n"
+"    Masa untuk penggera bergerak.\n"
+"\n"
+"  Senyap selepas:\n"
+"    Hentikan penggera selepas amaum masa ini.\n"
+"       (jika dialog bangun tidak ditutup)\n"
+"\n"
+"\n"
+"Hari\n"
+"  Hari:\n"
+"    Pilih hari untuk penggera diaktifkan.\n"
+"\n"
+"  Masa:\n"
+"    Pilih masa untuk penggera pada setiap hari,\n"
+"    atau pilih butang togol untuk guna masa\n"
+"    lalai.\n"
+"\n"
+"\n"
+
+#: src/alarm/interface.cc:45
+msgid ""
+"Volume\n"
+"  Fading:\n"
+"    Fade the volume up to the chosen volume\n"
+"    for this amount of time.\n"
+"\n"
+"  Start at:\n"
+"    Start fading from this volume.\n"
+"\n"
+"  Final:\n"
+"    The volume to stop fading at.  If the fading\n"
+"    time is 0 then set volume to this and start\n"
+"    playing.\n"
+"\n"
+"\n"
+"Options:\n"
+"  Additional Command:\n"
+"    Run this command at the alarm time.\n"
+"\n"
+msgstr ""
+"Volum\n"
+"  Pelenyapan:\n"
+"    Lenyapkan volum mengikut volum pilihan\n"
+"    untuk amaun masa ini.\n"
+"\n"
+"  Mula pada:\n"
+"    Mula melenyap dari volum ini.\n"
+"\n"
+"  Akhir:\n"
+"    Volum berhenti melenyap.  Jika masa melenyap\n"
+"    adalah 0 maka tetapkan volum pada ini dan mula\n"
+"    main.\n"
+"\n"
+"\n"
+"Pilihan:\n"
+"  Perintah Tambahan:\n"
+"    Jalankan perintah ini pada masa penggera.\n"
+"\n"
+
+#: src/alarm/interface.cc:62
+msgid ""
+"  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"
+"    can also be entered here.\n"
+"\n"
+"  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."
+msgstr ""
+"  Senarai Main:\n"
+"    Muatkan senarai main ini. Jika tiada senarai main\n"
+"    diberi, yang semasa akan digunakan.\n"
+"    URL bagi strim mp3/ogg juga boleh digunakan\n"
+"    di sini.\n"
+"\n"
+"  Peringatan:\n"
+"    Papar peringatan bila penggera dimatikan.\n"
+"    Taip peringatan dalam kotak dan hidupkan\n"
+"    butang togol jika anda mahu ia ditunjukkan."
+
+#: src/alarm/interface.cc:81
+msgid "This is your wakeup call."
+msgstr "Ini adalah panggilan bangun tidur anda."
+
+#: src/alarm/interface.cc:99
+msgid "Your reminder for today is..."
+msgstr "Peringatan untuk hari ini ialah..."
+
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
+msgid "Reminder"
+msgstr "Peringatan"
+
+#: src/alarm/interface.cc:132
+msgid "Monday"
+msgstr "Isnin"
+
+#: src/alarm/interface.cc:132
+msgid "Tuesday"
+msgstr "Selasa"
+
+#: src/alarm/interface.cc:132
+msgid "Wednesday"
+msgstr "Rabu"
+
+#: src/alarm/interface.cc:133
+msgid "Thursday"
+msgstr "Khamis"
+
+#: src/alarm/interface.cc:133
+msgid "Friday"
+msgstr "Jumaat"
+
+#: src/alarm/interface.cc:133
+msgid "Saturday"
+msgstr "Sabtu"
+
+#: src/alarm/interface.cc:133
+msgid "Sunday"
+msgstr "Ahad"
+
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
+msgid "Time"
+msgstr "Masa"
+
+#: src/alarm/interface.cc:178
+msgid "Alarm at (default):"
+msgstr "Penggera pada (lalai):"
+
+#: src/alarm/interface.cc:200
+msgid "h"
+msgstr "h"
+
+#: src/alarm/interface.cc:203
+msgid "Quiet after:"
+msgstr "Tenang selepas:"
+
+#: src/alarm/interface.cc:215
+msgid "hours"
+msgstr "jam"
+
+#: src/alarm/interface.cc:226
+msgid "minutes"
+msgstr "minit"
+
+#: src/alarm/interface.cc:235
+msgid "Choose the days for the alarm to come on"
+msgstr "Pilih hari bagi penggera beraktif"
+
+#: src/alarm/interface.cc:242
+msgid "Day"
+msgstr "Hari"
+
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
+msgid "Default"
+msgstr "Lalai"
+
+#: src/alarm/interface.cc:288
+msgid "Days"
+msgstr "Hari"
+
+#: src/alarm/interface.cc:297
+msgid "Fading"
+msgstr "Pudar"
+
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
+msgid "seconds"
+msgstr "Saat"
+
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
+msgid "Volume"
+msgstr "Volum"
+
+#: src/alarm/interface.cc:317
+msgid "Start at"
+msgstr "Bermula pada"
+
+#: src/alarm/interface.cc:333
+msgid "Final"
+msgstr "Terakhir"
+
+#: src/alarm/interface.cc:346
+msgid "Current"
+msgstr "Semasa"
+
+#: src/alarm/interface.cc:359
+msgid "Additional Command"
+msgstr "Perintah Tambahan"
+
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
+msgid "enable"
+msgstr "Aktif"
+
+#: src/alarm/interface.cc:372
+msgid "Playlist (optional)"
+msgstr "Senarai Main (pilihan)"
+
+#: src/alarm/interface.cc:379
+msgid "Select a playlist"
+msgstr "Pilih satu senarai main"
+
+#: src/alarm/interface.cc:399
+msgid "Options"
+msgstr "Pilihan"
+
+#: src/alarm/interface.cc:404
+msgid "What do these options mean?"
+msgstr "Apa pilihan ini bermakna?"
+
+#: src/alarm/interface.cc:420
+msgid "Help"
+msgstr "Bantuan"
+
+#: src/albumart/albumart.cc:31
+msgid "Album Art"
+msgstr "Seni Album"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Seni Album (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Output ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Pemalam Output ALSA untuk Audacious\n"
+"Hakcipta 2009-2012 John Lindgren\n"
+"\n"
+"Terima kasih buat William Pitcock, pengarang Pemalam Output ALSA NG, yang "
+"mana kodnya dirujuk bila panduan ALSA tidak mencukupi."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(tiada keterangan)"
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr "Lalai peranti PCM"
+
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr "Lalai campuran peranti"
+
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr "peranti PCM:"
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr "Peranti campuran:"
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr "Elemen campuran:"
+
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Pemain MIDI)"
+
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
+"AMIDI-Plug\n"
+"Pemain muzik MIDI modular\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"ditulis oleh Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"terima kasih buat...\n"
+"\n"
+"Clemens Ladisch dan Jaroslav Kysela\n"
+"atas program hebat aplaymidi dan amixer mereka; ia\n"
+"sangat berguna, selain itu alsa-lib docs, untuk ketahui\n"
+"lebih lanjut mengenai API ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"atas logo papan kekunci midi yang cantik\n"
+"\n"
+"Tony Vroon\n"
+"atas bantuan pengujian alfa yang diberi"
+
+#: src/amidi-plug/i_configure.cc:94
+msgid "Override default gain:"
+msgstr "Batalkan gandaan lalai:"
+
+#: src/amidi-plug/i_configure.cc:102
+msgid "Override default polyphony:"
+msgstr "Batalkan polifoni lalai:"
+
+#: src/amidi-plug/i_configure.cc:110
+msgid "Override default reverb:"
+msgstr "Batalkan reverb lalai:"
+
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
+msgid "On"
+msgstr "Hidup"
+
+#: src/amidi-plug/i_configure.cc:118
+msgid "Override default chorus:"
+msgstr "Batalkan korus lalai:"
+
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
+msgid "<b>Playback</b>"
+msgstr "<b>Main Balik</b>"
+
+#: src/amidi-plug/i_configure.cc:129
+msgid "Transpose:"
+msgstr "Transsposisi:"
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "seminada"
+
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
+msgstr "Anjak dram:"
+
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "nombor nota"
+
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Langkau senyap hadapan"
+
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Langkau senyap belakang"
+
+#: src/amidi-plug/i_configure.cc:141
+msgid "<b>SoundFont</b>"
+msgstr "<b>SoundFont</b>"
+
+#: src/amidi-plug/i_configure.cc:143
+msgid "<b>Synthesizer</b>"
+msgstr "<b>Pensintesis</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Kadar sampel:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
+msgid "AMIDI-Plug - select SoundFont file"
+msgstr "AMIDI-Plug - pilih fail SoundFont"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Batal"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
+msgid "_Open"
+msgstr "_Buka"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Nama fail"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
+msgid "Size (bytes)"
+msgstr "Saiz (bait)"
+
+#: src/amidi-plug/i_fileinfo.cc:163
+msgid "Name:"
+msgstr "Nama:"
+
+#: src/amidi-plug/i_fileinfo.cc:181
+msgid "<span size=\"smaller\"> MIDI Info </span>"
+msgstr "<span size=\"smaller\"> Maklumat MIDI </span>"
+
+#: src/amidi-plug/i_fileinfo.cc:195
+msgid "Format:"
+msgstr "Format:"
+
+#: src/amidi-plug/i_fileinfo.cc:198
+msgid "Length (msec):"
+msgstr "Panjang (msaat):"
+
+#: src/amidi-plug/i_fileinfo.cc:201
+msgid "No. of Tracks:"
+msgstr "Nombor Trek:"
+
+#: src/amidi-plug/i_fileinfo.cc:207
+msgid "variable"
+msgstr "pembolehubah"
+
+#: src/amidi-plug/i_fileinfo.cc:209
+msgid "BPM:"
+msgstr "BPM:"
+
+#: src/amidi-plug/i_fileinfo.cc:217
+msgid "BPM (wavg):"
+msgstr "BPM (wavg):"
+
+#: src/amidi-plug/i_fileinfo.cc:220
+msgid "Time Div:"
+msgstr "Masa Div:"
+
+#: src/amidi-plug/i_fileinfo.cc:231
+msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
+msgstr "<span size=\"smaller\"> Ulasan dan Lirik MIDI </span>"
+
+#: src/amidi-plug/i_fileinfo.cc:278
+msgid "* no comments available in this MIDI file *"
+msgstr "* tiada ulasan tersedi dalam fail MIDI ini *"
+
+#: src/amidi-plug/i_fileinfo.cc:290
+msgid "* no lyrics available in this MIDI file *"
+msgstr "* tiada lirik didapati dalam fail MIDI ini *"
+
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
+msgid "_Close"
+msgstr "T_utup"
+
+#: src/amidi-plug/i_fileinfo.cc:325
+msgid "  (invalid UTF-8)"
+msgstr "(UTF-8 tidak sah)"
+
+#: src/aosd/aosd.cc:32
+msgid ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Written by Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Based in part on Evan Martin's Ghosd library:\n"
+"http://neugierig.org/software/ghosd/"
+msgstr ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Ditulis oleh Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Berdasarkan bahagian dalam  pustaka Ghosd Evan Martin:\n"
+"http://neugierig.org/software/ghosd/"
+
+#: src/aosd/aosd.h:37
+msgid "AOSD (On-Screen Display)"
+msgstr "AOSD (Paparan Atas-Skrin)"
+
+#: src/aosd/aosd_style.cc:54
+msgid "Rectangle"
+msgstr "Segiempat Tepat"
+
+#: src/aosd/aosd_style.cc:59
+msgid "Rounded Rectangle"
+msgstr "Bulatan Segiempat Tepat"
+
+#: src/aosd/aosd_style.cc:64
+msgid "Concave Rectangle"
+msgstr "Cekung Segiempat Tepat"
+
+#: src/aosd/aosd_style.cc:69
+msgid "None"
+msgstr "Tiada"
+
+#: src/aosd/aosd_trigger.cc:50
+msgid "Playback Start"
+msgstr "Mulakan Main Semula"
+
+#: src/aosd/aosd_trigger.cc:51
+msgid "Triggers OSD when a playlist entry is played."
+msgstr "Mencetus OSD apabila kemasukan senarai main dimainkan."
+
+#: src/aosd/aosd_trigger.cc:56
+msgid "Title Change"
+msgstr "Tukar Tajuk"
+
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Memicu OSD bila tajuk lagu berubah (untuk strim internet)."
+
+#: src/aosd/aosd_trigger.cc:62
+msgid "Pause On"
+msgstr "Aktifkan Jeda"
+
+#: src/aosd/aosd_trigger.cc:63
+msgid "Triggers OSD when playback is paused."
+msgstr "Mencetus OSD apabila main dijeda."
+
+#: src/aosd/aosd_trigger.cc:68
+msgid "Pause Off"
+msgstr "Matikan Jeda"
+
+#: src/aosd/aosd_trigger.cc:69
+msgid "Triggers OSD when playback is unpaused."
+msgstr "Mencetus OSD apabila main tidak dijeda"
+
+#: src/aosd/aosd_ui.cc:163
+msgid "Placement"
+msgstr "Penempatan"
+
+#: src/aosd/aosd_ui.cc:196
+msgid "Relative X offset:"
+msgstr "X relatif diimbangi:"
+
+#: src/aosd/aosd_ui.cc:203
+msgid "Relative Y offset:"
+msgstr "Y relatif diimbangi:"
+
+#: src/aosd/aosd_ui.cc:210
+msgid "Max OSD width:"
+msgstr "Max lebar OSD:"
+
+#: src/aosd/aosd_ui.cc:221
+msgid "Multi-Monitor options"
+msgstr "pilihan Pelbagai-Monitor"
+
+#: src/aosd/aosd_ui.cc:225
+msgid "Display OSD using:"
+msgstr "Paparkan OSD digunakan:"
+
+#: src/aosd/aosd_ui.cc:227
+msgid "all monitors"
+msgstr "semua monitor"
+
+#: src/aosd/aosd_ui.cc:230
+#, c-format
+msgid "monitor %i"
+msgstr "monitor %i"
+
+#: src/aosd/aosd_ui.cc:282
+msgid "Timing (ms)"
+msgstr "Masa (ms)"
+
+#: src/aosd/aosd_ui.cc:287
+msgid "Display:"
+msgstr "Paparan:"
+
+#: src/aosd/aosd_ui.cc:292
+msgid "Fade in:"
+msgstr "Pudar dalam:"
+
+#: src/aosd/aosd_ui.cc:297
+msgid "Fade out:"
+msgstr "Pudar luar:"
+
+#: src/aosd/aosd_ui.cc:361
+msgid "Fonts"
+msgstr "Font"
+
+#: src/aosd/aosd_ui.cc:368
+#, c-format
+msgid "Font %i:"
+msgstr "Font %i:"
+
+#: src/aosd/aosd_ui.cc:382
+msgid "Shadow"
+msgstr "Bayang"
+
+#: src/aosd/aosd_ui.cc:486
+msgid "Render Style"
+msgstr "Realisasi Gaya"
+
+#: src/aosd/aosd_ui.cc:502
+msgid "Colors"
+msgstr "Warna"
+
+#: src/aosd/aosd_ui.cc:513
+#, c-format
+msgid "Color %i:"
+msgstr "Warna %i:"
+
+#: src/aosd/aosd_ui.cc:600
+msgid "Enable trigger"
+msgstr "Aktifkan pencetus"
+
+#: src/aosd/aosd_ui.cc:627
+msgid "Event"
+msgstr "Acara"
+
+#: src/aosd/aosd_ui.cc:655
+msgid "Composite manager detected"
+msgstr "Pengurus komposit dikesan"
+
+#: src/aosd/aosd_ui.cc:662
+msgid ""
+"Composite manager not detected;\n"
+"unless you know that you have one running, please activate a composite "
+"manager otherwise the OSD won't work properly"
+msgstr ""
+"Pengurus komposit tidak dikesan\n"
+"melainkan anda tahu bahawa anda mempunyai satu berjalan, sila mengaktifkan "
+"pengurus komposit sebaliknya OSD tidak akan berfungsi dengan betul"
+
+#: src/aosd/aosd_ui.cc:670
+msgid "Composite manager not required for fake transparency"
+msgstr "Komposit pengurus tidak diperlukan untuk ketelusan palsu"
+
+#: src/aosd/aosd_ui.cc:706
+msgid "Transparency"
+msgstr "Ketelusan"
+
+#: src/aosd/aosd_ui.cc:712
+msgid "Fake transparency"
+msgstr "Ketelusan palsu"
+
+#: src/aosd/aosd_ui.cc:714
+msgid "Real transparency (requires X Composite Ext.)"
+msgstr "Ketelusan sebenar (minta X Composite Ext.)"
+
+#: src/aosd/aosd_ui.cc:756
+msgid "Composite extension not loaded"
+msgstr "Lanjutan komposit tidak dimuatkan"
+
+#: src/aosd/aosd_ui.cc:764
+msgid "Composite extension not available"
+msgstr "Sambungan komposit tidak tersedia"
+
+#: src/aosd/aosd_ui.cc:781
+#, c-format
+msgid "<span font_desc='%s'>Audacious OSD</span>"
+msgstr "<span font_desc='%s'>Audacious OSD</span>"
+
+#: src/aosd/aosd_ui.cc:844
+msgid "Position"
+msgstr "Kedudukan"
+
+#: src/aosd/aosd_ui.cc:849
+msgid "Animation"
+msgstr "Animasi"
+
+#: src/aosd/aosd_ui.cc:854
+msgid "Text"
+msgstr "Teks"
+
+#: src/aosd/aosd_ui.cc:859
+msgid "Decoration"
+msgstr "Hiasan"
+
+#: src/aosd/aosd_ui.cc:864
+msgid "Trigger"
+msgstr "Pemicu"
+
+#: src/aosd/aosd_ui.cc:869
+msgid "Misc"
+msgstr "Pelbagai"
+
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Uji"
+
+#: src/asx3/asx3.cc:35
+msgid "ASXv3 Playlists"
+msgstr "Senarai Main ASXv3"
+
+#: src/asx/asx.cc:33
+msgid "ASXv1/ASXv2 Playlists"
+msgstr "Senarai Main ASXv1/ASXv2"
+
+#: src/audpl/audpl.cc:33
+msgid "Audacious Playlists (audpl)"
+msgstr "Senarai Main Audacious (audpl)"
+
+#: src/blur_scope/blur_scope.cc:42
+msgid "<b>Color</b>"
+msgstr "<b>Warna</b>"
+
+#: src/blur_scope/blur_scope.cc:58
+msgid "Blur Scope"
+msgstr "Skop Kabur"
+
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Praset:"
+
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr "Aras suapan:"
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Frekuensi kerat:"
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
+msgid "Spectrum Analyzer"
+msgstr "Penganalisis Spektrum"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Pemalam CD Audio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
+msgid ""
+"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
+"\n"
+"Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/>\n"
+"and to libcddb developers <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Also thank you to Tony Vroon for mentoring and guiding me.\n"
+"\n"
+"This was a Google Summer of Code 2007 project."
+msgstr ""
+"Hakcipta (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> dan lain-lain.\n"
+"\n"
+"Terima kasih buat pembangun libcdio <http://www.gnu.org/software/libcdio/>\n"
+"dan pembangun libcddb <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Dan juga terima kasih kepada Tony Vroon atas pementoran dan panduan.\n"
+"\n"
+"Ini merupakan projek Google Summer of Code 2007."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:137
+msgid "<b>Device</b>"
+msgstr "<b>Peranti</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:138
+msgid "Read speed:"
+msgstr "Kelajuan baca:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:141
+msgid "Override device:"
+msgstr "Batalkan peranti:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:143
+msgid "<b>Metadata</b>"
+msgstr "<b>Data meta</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:144
+msgid "Use CD-Text"
+msgstr "Guna Teks-CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:146
+msgid "Use CDDB"
+msgstr "Guna CDDB"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:148
+msgid "Use HTTP instead of CDDBP"
+msgstr "Guna HTTP selain dari CDDBP"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:151
+msgid "Server:"
+msgstr "Pelayan:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:155
+msgid "Path:"
+msgstr "Laluan:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:159
+msgid "Port:"
+msgstr "Port:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:246
+msgid "Failed to initialize cdio subsystem."
+msgstr "Gagal mengawalkan subsistem cdio."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:281
+#, c-format
+msgid "Invalid URI %s."
+msgstr "URI %s tidak sah."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:283
+#, c-format
+msgid "Track %d not found."
+msgstr "Trek %d tidak ditemui."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:285
+#, c-format
+msgid "Track %d is a data track."
+msgstr "Trek %d adalah trek data."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:360
+msgid "Error reading audio CD."
+msgstr "Ralat membaca CD audio."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:429
+msgid "Audio CD"
+msgstr "CD Audio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
+#, c-format
+msgid "Failed to open CD device %s."
+msgstr "Gagal membuka peranti CD %s."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:472
+msgid "No audio capable CD drive found."
+msgstr "Tiada pemacu CD upaya audio ditemui."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:497
+msgid "Failed to finish initializing opened CD drive."
+msgstr "Gagal menyelesaikan pengawalan pemacu CD dibuka."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:510
+msgid "Failed to retrieve first/last track number."
+msgstr "Gagal mendapatkan nombor trek pertama/terakhir."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:531
+#, c-format
+msgid "Cannot read start/end LSN for track %d."
+msgstr "Tidak dapat baca/tamatkan LSN untuk trek %d."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:613
+msgid "Failed to create the cddb connection."
+msgstr "Gagal mencipta sambungan cddb."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:679
+msgid "Failed to query the CDDB server"
+msgstr "Gagal menanya pelayan CDDB"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:681
+#, c-format
+msgid "Failed to query the CDDB server: %s"
+msgstr "Gagal menanya pelayan CDDB: %s"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:705
+#, c-format
+msgid "Failed to read the cddb info: %s"
+msgstr "Gagal membaca maklumat cddb: %s"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:765
+msgid "Drive is empty."
+msgstr "Pemacu kosong."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:767
+msgid "Unsupported disk type."
+msgstr "Jenis cakera tidak disokong."
+
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Item Menu CD Audio"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Play CD"
+msgstr "Main CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Add CD"
+msgstr "Tambah CD"
+
+#: src/compressor/compressor.cc:45
+msgid "<b>Compression</b>"
+msgstr "<b>Pemampatan</b>"
+
+#: src/compressor/compressor.cc:46
+msgid "Center volume:"
+msgstr "Volum tengah:"
+
+#: src/compressor/compressor.cc:49
+msgid "Dynamic range:"
+msgstr "Julat dinamik:"
+
+#: src/compressor/compressor.cc:57
+msgid ""
+"Dynamic Range Compression Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+"Pemalam Pemampatan Julat dinamik untuk Audacious\n"
+"Hakcipta 2010-2014 John Lindgren"
+
+#: src/compressor/compressor.cc:64
+msgid "Dynamic Range Compressor"
+msgstr "Pemampat Jula Dinamik"
+
+#: src/console/plugin.cc:15
+msgid ""
+"Console music decoder engine based on Game_Music_Emu 0.5.2\n"
+"Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at dereferenced.org>\n"
+"Shay Green <gblargg at gmail.com>"
+msgstr ""
+"Enjin penyahkod muzik konsol berasaskan pada Game_Music_Emu 0.5.2\n"
+"Format disokong: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"\n"
+"Pemalam Audacious oleh:\n"
+"William Pitcock <nenolod at dereferenced.org>\n"
+"Shay Green <gblargg at gmail.com>"
+
+#: src/console/plugin.cc:30
+msgid "Bass:"
+msgstr "Bes:"
+
+#: src/console/plugin.cc:33
+msgid "Treble:"
+msgstr "Trebel:"
+
+#: src/console/plugin.cc:36
+msgid "Echo:"
+msgstr "Gema:"
+
+#: src/console/plugin.cc:39
+msgid "Default song length:"
+msgstr "Panjang lagu lalai:"
+
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
+msgid "<b>Resampling</b>"
+msgstr "<b>Persampelan Semula</b>"
+
+#: src/console/plugin.cc:43
+msgid "Enable audio resampling"
+msgstr "Benarkan persampelan semula audio"
+
+#: src/console/plugin.cc:49
+msgid "<b>SPC</b>"
+msgstr "<b>SPC</b>"
+
+#: src/console/plugin.cc:50
+msgid "Ignore length from SPC tags"
+msgstr "Abai panjang dari tag SPC"
+
+#: src/console/plugin.cc:52
+msgid "Increase reverb"
+msgstr "Tingkatkan reverb"
+
+#: src/console/plugin.h:26
+msgid "Game Console Music Decoder"
+msgstr "Penyahkod Muzik Konsol Permainan"
+
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Output CoreAudio"
+
+#: src/coreaudio/coreaudio.cc:131
+msgid ""
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Pemalam Output CoreAudio untuk Audacious\n"
+"Hakcipta 2014 William Pitcock\n"
+"\n"
+"Berdasarkan pada Pemalam Output SDL untukr Audacious\n"
+"Hakcipta 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Guna mod ekslusif"
+
+#: src/crossfade/crossfade.cc:44
+msgid ""
+"Crossfade Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+"Pemalam Resap Silang untuk Audacious\n"
+"Hakcipta 2010-2014 John Lindgren"
+
+#: src/crossfade/crossfade.cc:48
+msgid "<b>Crossfade</b>"
+msgstr "<b>Resap Silang</b>"
+
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Bila automatik lagu berubah"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
+msgid "Overlap:"
+msgstr "Tindih:"
+
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Bila jangkau atau ubah lagu secara manual"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Petua</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Untuk resap silang yang lebih baik,\n"
+"benarkan kesan Pembuangan Senyap."
+
+#: src/crossfade/crossfade.cc:72
+msgid "Crossfade"
+msgstr "Resap Silang"
+
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Peresapan silang gagal kerana lagu mempunyai bilangan saluran berbeza. Anda "
+"boleh guna Pengadun Saluran untuk tukarkan lagu ke bilangan saluran yang "
+"sama."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Peresapan silang gagal keran lagu mempunyai kadar sampel yang berlainan. "
+"Anda boleh guna Penukar Kadar Sampel untuk tukarkan lagu menjadi kadar "
+"sampel yang sama."
+
+#: src/crystalizer/crystalizer.cc:31
+msgid "<b>Crystalizer</b>"
+msgstr "<b>Crystalizer</b>"
+
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
+msgid "Intensity:"
+msgstr "Keamatan:"
+
+#: src/crystalizer/crystalizer.cc:43
+msgid "Crystalizer"
+msgstr "Crystalizer"
+
+#: src/cue/cue.cc:37
+msgid "Cue Sheet Plugin"
+msgstr "Pemalam Lembaran Isyarat"
+
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Padam Fail"
+
+#: src/delete-files/delete-files.cc:75
+#, c-format
+msgid "Error moving %s to trash: %s."
+msgstr "Ralat mengalih %s ke tong sampah: %s."
+
+#: src/delete-files/delete-files.cc:86
+#, c-format
+msgid "Error deleting %s: %s."
+msgstr "Ralat memadam %s: %s."
+
+#: src/delete-files/delete-files.cc:117
+#, c-format
+msgid "Error deleting %s: not a local file."
+msgstr "Ralat memadam %s: bukan fail setempat."
+
+#: src/delete-files/delete-files.cc:134
+msgid "Do you want to move the selected files to the trash?"
+msgstr "Anda mahu alih fail terpilih ke tong sampah?"
+
+#: src/delete-files/delete-files.cc:135
+msgid "Move to Trash"
+msgstr "Alih ke Tong Sampah"
+
+#: src/delete-files/delete-files.cc:140
+msgid "Do you want to permanently delete the selected files?"
+msgstr "Anda mahu padam fail terpilih secara kekal?"
+
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
+msgid "Delete"
+msgstr "Padam"
+
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
+msgid "Cancel"
+msgstr "Batal"
+
+#: src/delete-files/delete-files.cc:166
+msgid "Delete Selected Files"
+msgstr "Padam Fail Terpilih"
+
+#: src/delete-files/delete-files.cc:181
+msgid "<b>Delete Method</b>"
+msgstr "<b>Kaedah Padam</b>"
+
+#: src/delete-files/delete-files.cc:182
+msgid "Move to trash instead of deleting immediately"
+msgstr "Alih ke tong sampah selain dari memadam serta-merta"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Pemalam Gema\n"
+"Oleh Johan Levin, 1999\n"
+"Gema keliling oleh Carl van Schaik, 1999\n"
+"Dikemaskini untuk Audacious oleh William Pitcock dan John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
+msgid "<b>Echo</b>"
+msgstr "<b>Gema</b>"
+
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "Delay:"
+msgstr "Lengah:"
+
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "ms"
+msgstr "ms"
+
+#: src/echo_plugin/echo.cc:25
+msgid "Feedback:"
+msgstr "Maklumbalas:"
+
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
+msgid "Volume:"
+msgstr "Volum:"
+
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
+msgstr "Gema"
+
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Pemalam FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
+msgid ""
+"Multi-format audio decoding plugin for Audacious using\n"
+"FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
+msgstr ""
+"Pemalam penyahkodan audio format-berbilang menggunakan\n"
+"bingkai kerja multimedia FFmpeg (http://www.ffmpeg.org/)\n"
+"\n"
+"Pemalam Audacious oleh:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
+
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Pemalam FileWriter"
+
+#: src/filewriter/filewriter.cc:386
+msgid "Output file format:"
+msgstr "Format fail output:"
+
+#: src/filewriter/filewriter.cc:403
+msgid "Configure"
+msgstr "Konfigur"
+
+#: src/filewriter/filewriter.cc:413
+msgid "Save into original directory"
+msgstr "Simpan ke dalam direktori asal"
+
+#: src/filewriter/filewriter.cc:417
+msgid "Save into custom directory"
+msgstr "Simpan ke dalam direktori suai"
+
+#: src/filewriter/filewriter.cc:427
+msgid "Output file folder:"
+msgstr "Folder fail output:"
+
+#: src/filewriter/filewriter.cc:431
+msgid "Pick a folder"
+msgstr "Ambil satu folder"
+
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Jana nama fail dari:"
+
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Tag fail asal"
+
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nama fail asal"
+
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Sertakan sambungan nama fail asal"
+
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Tambah nombor trek ke nama fail"
+
+#: src/filewriter/filewriter.cc:484
+msgid ""
+"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."
+msgstr ""
+"Program adalah perisian bebas; anda boleh mengedarkannya dan/atau "
+"mengubahsuainya dibawah terma Pelesenan Awam Am GNU yang diterbitkan oleh "
+"Free Software Foundation; sama ada versi 2 dari lesen, atau (mengikut "
+"pilihan anda) mana-mana versi terkini.\n"
+"\n"
+"Program ini diedarkan dengan harapan ianya akan berguna, TANPA SEBARANG "
+"JAMINAN; termasuk juga KESESUAIAN UNTUK DIPASARKAN, JAMINAN KUALITI, atau "
+"JAMINAN ATAS APA JUA SEBAB. Sila lihat GNU General Public License untuk "
+"maklumat lanjut.\n"
+"\n"
+"Anda seharusnya menerima satu salinan Lesen Awam Am GNU bersama-sama dengan "
+"Gwibber; jika tidak, laporkannya ke Free Software Foundation, Inc., 51 "
+"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
+msgid "Auto"
+msgstr "Auto"
+
+#: src/filewriter/mp3.cc:40
+msgid "Joint Stereo"
+msgstr "Stereo Gabung"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
+msgid "Stereo"
+msgstr "Stereo"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
+msgid "Mono"
+msgstr "Mono"
+
+#: src/filewriter/mp3.cc:657
+msgid "MP3 Configuration"
+msgstr "Konfigurasi MP3"
+
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
+msgid "Algorithm Quality:"
+msgstr "Kualiti Algoritma:"
+
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Kadar Sampel Output:"
+
+#: src/filewriter/mp3.cc:733
+msgid "(Hz)"
+msgstr "(Hz)"
+
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Kadar Bit / Nisbah Pemampatan:"
+
+#: src/filewriter/mp3.cc:764
+msgid "Bitrate (kbps):"
+msgstr "Kadar bit (kbps):"
+
+#: src/filewriter/mp3.cc:796
+msgid "Compression ratio:"
+msgstr "Nisbah pemampatan:"
+
+#: src/filewriter/mp3.cc:820
+msgid "Audio Mode:"
+msgstr "Mod Audio:"
+
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Pelbagai:"
+
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Paksa turutan ISO ketat"
+
+#: src/filewriter/mp3.cc:867
+msgid "Error protection"
+msgstr "Pelindungan ralat"
+
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
+msgid "Quality"
+msgstr "Kualiti"
+
+#: src/filewriter/mp3.cc:888
+msgid "Enable VBR/ABR"
+msgstr "Benarkan VBR/ABR"
+
+#: src/filewriter/mp3.cc:898
+msgid "Type:"
+msgstr "Jenis:"
+
+#: src/filewriter/mp3.cc:931
+msgid "VBR Options:"
+msgstr "Pilihan VBR:"
+
+#: src/filewriter/mp3.cc:947
+msgid "Minimum bitrate (kbps):"
+msgstr "Kadar bit minimum (kbps):"
+
+#: src/filewriter/mp3.cc:973
+msgid "Maximum bitrate (kbps):"
+msgstr "Kadar bit maksimum (kbps):"
+
+#: src/filewriter/mp3.cc:995
+msgid "Strictly enforce minimum bitrate"
+msgstr "Paksa kadar bit minimum betul-betul"
+
+#: src/filewriter/mp3.cc:1007
+msgid "ABR Options:"
+msgstr "Pilihan ABR:"
+
+#: src/filewriter/mp3.cc:1017
+msgid "Average bitrate (kbps):"
+msgstr "Kadar bit purata (kbps):"
+
+#: src/filewriter/mp3.cc:1044
+msgid "VBR quality level:"
+msgstr "Aras kualiti VBR:"
+
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Buang pengepala VBR Xing"
+
+#: src/filewriter/mp3.cc:1076
+msgid "VBR/ABR"
+msgstr "VBR/ABR"
+
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "Parameter Bingkai:"
+
+#: src/filewriter/mp3.cc:1097
+msgid "Mark as copyright"
+msgstr "Tanda sebagai hakcipta"
+
+#: src/filewriter/mp3.cc:1108
+msgid "Mark as original"
+msgstr "Tanda sebagai asal"
+
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr "Parameter ID3:"
+
+#: src/filewriter/mp3.cc:1131
+msgid "Force addition of version 2 tag"
+msgstr "Paksa penambahan tag versi 2"
+
+#: src/filewriter/mp3.cc:1141
+msgid "Only add v1 tag"
+msgstr "Hanya tambah tag v1"
+
+#: src/filewriter/mp3.cc:1148
+msgid "Only add v2 tag"
+msgstr "Hanya tambah tag v2"
+
+#: src/filewriter/mp3.cc:1169
+msgid "Tags"
+msgstr "Tag"
+
+#: src/filewriter/vorbis.cc:196
+msgid "Vorbis Encoder Configuration"
+msgstr "Konfigurasi Pengekod Vorbis"
+
+#: src/filewriter/vorbis.cc:219
+msgid "Quality level (0 - 10):"
+msgstr "Aras kualiti (0 - 10):"
+
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Penyahkod FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
+msgid "lossless"
+msgstr "tak hilang"
+
+#: src/flacng/plugin.cc:169
+msgid ""
+"Original code by\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
+msgstr ""
+"Kod asal oleh\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
+
+#: src/gio/gio.cc:34
+msgid ""
+"GIO Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren"
+msgstr ""
+"Pemalam GIO untuk Audacious\n"
+"Hakcipta 2009-2012 John Lindgren"
+
+#: src/gio/gio.cc:42
+msgid "GIO Plugin"
+msgstr "Pemalam GIO"
+
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Mod baca-dan-tambah tidak disokong"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Mod buka tidak sah"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Penganalisis Spektrum OpenGL untuk Audacious\n"
+"Hakcipta 2013 Christophe Budé, John Lindgren, dan Carlo Bramini\n"
+"\n"
+"Berdasarkan pada pemalam XMMS:\n"
+"Hakcipta 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, dan "
+"4Front Technologies\n"
+"\n"
+"Lesen: GPLv2+"
+
+#: src/gl-spectrum/gl-spectrum.cc:62
+msgid "OpenGL Spectrum Analyzer"
+msgstr "Penganalisis Spektrum OpenGL"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Penganalisis Spektrum OpenGL untuk Audacious\n"
+"Hakcipta 2013 Christophe Budé, John Lindgren, dan Carlo Bramini\n"
+"Hakcipta 2014 William Pitcock\n"
+"\n"
+"Berdasarkan pada pemalam XMMS:\n"
+"Hakcipta 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, dan "
+"4Front Technologies\n"
+"\n"
+"Lesen: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Penganalisis Spektrum OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Pintasan GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"Pemalam Pintasan GNOME\n"
+"Membolehkan anda kawal pemain dengan pintasan GNOME.\n"
+"\n"
+"Hakcipta (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+
+#: src/gtkui/columns.cc:35
+msgid "Entry number"
+msgstr "Nombor masukan"
+
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
+msgid "Title"
+msgstr "Tajuk"
+
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
+msgid "Artist"
+msgstr "Artis"
+
+#: src/gtkui/columns.cc:38
+msgid "Year"
+msgstr "Tahun"
+
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
+msgid "Album"
+msgstr "Album"
+
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artis album"
+
+#: src/gtkui/columns.cc:41
+msgid "Track"
+msgstr "Trek"
+
+#: src/gtkui/columns.cc:42
+msgid "Genre"
+msgstr "Genre"
+
+#: src/gtkui/columns.cc:43
+msgid "Queue position"
+msgstr "Kedudukan baris gilir"
+
+#: src/gtkui/columns.cc:44
+msgid "Length"
+msgstr "Panjang"
+
+#: src/gtkui/columns.cc:45
+msgid "File path"
+msgstr "Laluan fail"
+
+#: src/gtkui/columns.cc:47
+msgid "Custom title"
+msgstr "Tajuk suai"
+
+#: src/gtkui/columns.cc:48
+msgid "Bitrate"
+msgstr "Kadar bit"
+
+#: src/gtkui/columns.cc:308
+msgid "Available columns"
+msgstr "Lajur tersedia"
+
+#: src/gtkui/columns.cc:334
+msgid "Displayed columns"
+msgstr "Lajur dipapar"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Alat Gelintar"
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Left"
+msgstr "Labuh di Kiri"
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Right"
+msgstr "Labuh di Kanan"
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Top"
+msgstr "Labuh di Atas"
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Bottom"
+msgstr "Labuh di Bawah"
+
+#: src/gtkui/layout.cc:168
+msgid "Undock"
+msgstr "Tanggalkan"
+
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
+msgid "Disable"
+msgstr "Lumpuhkan"
+
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
+msgid "_Open Files ..."
+msgstr "_Buka Fail ..."
+
+#: src/gtkui/menus.cc:127
+msgid "Open _URL ..."
+msgstr "Buka _URL ..."
+
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
+msgid "_Add Files ..."
+msgstr "T_ambah Fail ..."
+
+#: src/gtkui/menus.cc:129
+msgid "Add U_RL ..."
+msgstr "Tambah U_RL ..."
+
+#: src/gtkui/menus.cc:131
+msgid "Search _Library"
+msgstr "Gelintar _Pustaka"
+
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
+msgid "A_bout ..."
+msgstr "Per_ihal ..."
+
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
+msgid "_Settings ..."
+msgstr "T_etapan ..."
+
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
+msgid "_Quit"
+msgstr "_Keluar"
+
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
+msgid "_Play"
+msgstr "_Main"
+
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
+msgid "Paus_e"
+msgstr "_Jeda"
+
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
+msgid "_Stop"
+msgstr "_Henti"
+
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
+msgid "Pre_vious"
+msgstr "Ter_dahulu"
+
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
+msgid "_Next"
+msgstr "Ber_ikutnya"
+
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
+msgid "_Repeat"
+msgstr "_Ulang"
+
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
+msgid "S_huffle"
+msgstr "K_ocok"
+
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
+msgid "N_o Playlist Advance"
+msgstr "T_iada Senarai Main Pendahuluan"
+
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
+msgid "Stop A_fter This Song"
+msgstr "Henti Se_lepas Lagu Ini"
+
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
+msgid "Song _Info ..."
+msgstr "Mak_lumat Lagu ..."
+
+#: src/gtkui/menus.cc:151
+msgid "Jump to _Time ..."
+msgstr "Lompat ke Ma_sa ..."
+
+#: src/gtkui/menus.cc:152
+msgid "_Jump to Song ..."
+msgstr "L_ompat ke Lagu ..."
+
+#: src/gtkui/menus.cc:154
+msgid "Set Repeat Point _A"
+msgstr "Tetapkan Titik Ulang _A"
+
+#: src/gtkui/menus.cc:155
+msgid "Set Repeat Point _B"
+msgstr "Tetapkan Titik Ulang _B"
+
+#: src/gtkui/menus.cc:156
+msgid "_Clear Repeat Points"
+msgstr "_Kosongkan Titik Ulang"
+
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
+msgid "By _Title"
+msgstr "Mengikut _Tajuk"
+
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Mengikut Nama _Fail"
+
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
+msgid "By File _Path"
+msgstr "Mengikut _Laluan Fail"
+
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
+msgid "By Track _Number"
+msgstr "Mengikut _Nombor Trek"
+
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
+msgid "By _Artist"
+msgstr "Mengikut _Artis"
+
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
+msgid "By Al_bum"
+msgstr "Mengikut Al_bum"
+
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Mengikut Albu_m Artis"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
+msgid "By Release _Date"
+msgstr "Mengikut Tarik_h Keluaran"
+
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Mengikut _Genre"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
+msgid "By _Length"
+msgstr "Mengikut Pan_jang"
+
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
+msgid "By _File Path"
+msgstr "Mengikut Laluan _Fail"
+
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
+msgid "By _Custom Title"
+msgstr "Mengikut Tajuk _Suai"
+
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
+msgid "R_everse Order"
+msgstr "Tertib S_ongsang"
+
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
+msgid "_Random Order"
+msgstr "Tertib _Rawak"
+
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Main/Sambung Semula"
+
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
+msgid "_Refresh"
+msgstr "Se_gar Semula"
+
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
+msgid "_Sort"
+msgstr "_Isih"
+
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
+msgid "Sort Se_lected"
+msgstr "Isih T_erpilih"
+
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
+msgid "Remove _Duplicates"
+msgstr "Buang Pen_dua"
+
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
+msgid "Remove _Unavailable Files"
+msgstr "Buang Fail Yang _Tiada"
+
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
+msgid "_New"
+msgstr "_Baharu"
+
+#: src/gtkui/menus.cc:207
+msgid "Ren_ame ..."
+msgstr "N_ama Semula ..."
+
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
+msgid "Remo_ve"
+msgstr "B_uang"
+
+#: src/gtkui/menus.cc:210
+msgid "_Import ..."
+msgstr "_Import ..."
+
+#: src/gtkui/menus.cc:211
+msgid "_Export ..."
+msgstr "_Eksport ..."
+
+#: src/gtkui/menus.cc:213
+msgid "Playlist _Manager ..."
+msgstr "Pen_gurus Senarai Main ..."
+
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
+msgid "_Queue Manager ..."
+msgstr "Pengurus Baris _Gilir ..."
+
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
+msgid "Volume _Up"
+msgstr "Volum _Naik"
+
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
+msgid "Volume _Down"
+msgstr "Volum _Turun"
+
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
+msgid "_Equalizer"
+msgstr "Pen_yama"
+
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
+msgid "E_ffects ..."
+msgstr "K_esan ..."
+
+#: src/gtkui/menus.cc:227
+msgid "Show _Menu Bar"
+msgstr "Tunjuk Palang _Menu"
+
+#: src/gtkui/menus.cc:228
+msgid "Show I_nfo Bar"
+msgstr "Tunjuk Palang Ma_klumat"
+
+#: src/gtkui/menus.cc:229
+msgid "Show Info Bar Vis_ualization"
+msgstr "Tunjuk Peng_visualan Palang Maklumat"
+
+#: src/gtkui/menus.cc:230
+msgid "Show _Status Bar"
+msgstr "Tunjuk Palang _Status"
+
+#: src/gtkui/menus.cc:232
+msgid "Show _Remaining Time"
+msgstr "Tunjuk Masa _Berbaki"
+
+#: src/gtkui/menus.cc:234
+msgid "_Visualizations ..."
+msgstr "Pe_ngvisualan ..."
+
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
+msgid "_File"
+msgstr "_Fail"
+
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
+msgid "_Playback"
+msgstr "_Main Balik"
+
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
+msgid "P_laylist"
+msgstr "Se_narai Main"
+
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
+msgid "_Services"
+msgstr "Perk_hidmatan"
+
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
+msgid "_Output"
+msgstr "_Output"
+
+#: src/gtkui/menus.cc:243
+msgid "_View"
+msgstr "_Lihat"
+
+#: src/gtkui/menus.cc:248
+msgid "_Queue/Unqueue"
+msgstr "_Baris Gilir/Nyahbaris Gilir"
+
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Buka Folder Dikandungi"
+
+#: src/gtkui/menus.cc:253
+msgid "Cu_t"
+msgstr "Po_tong"
+
+#: src/gtkui/menus.cc:254
+msgid "_Copy"
+msgstr "Sa_lin"
+
+#: src/gtkui/menus.cc:255
+msgid "_Paste"
+msgstr "Tam_pal"
+
+#: src/gtkui/menus.cc:256
+msgid "Select _All"
+msgstr "Pilih Semu_a"
+
+#: src/gtkui/menus.cc:263
+msgid "_Rename ..."
+msgstr "_Nama Semula ..."
+
+#: src/gtkui/settings.cc:35
+msgid "<b>Playlist Tabs</b>"
+msgstr "<b>Tab Senarai Main</b>"
+
+#: src/gtkui/settings.cc:36
+msgid "Always show tabs"
+msgstr "Sentiasa tunjuk tab"
+
+#: src/gtkui/settings.cc:38
+msgid "Show entry counts"
+msgstr "Tunjuk kiraan masukan"
+
+#: src/gtkui/settings.cc:40
+msgid "Show close buttons"
+msgstr "Tunjuk butang tutup"
+
+#: src/gtkui/settings.cc:42
+msgid "<b>Playlist Columns</b>"
+msgstr "<b>Lajur Senarai Main</b>"
+
+#: src/gtkui/settings.cc:44
+msgid "Show column headers"
+msgstr "Tunjuk pengepala lajur"
+
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
+msgid "<b>Miscellaneous</b>"
+msgstr "<b>Pelbagai</b>"
+
+#: src/gtkui/settings.cc:47
+msgid "Arrow keys seek by:"
+msgstr "Kekunci anak panah jangkau:"
+
+#: src/gtkui/settings.cc:50
+msgid "Scroll on song change"
+msgstr "Tatal bila lagu berubah"
+
+#: src/gtkui/ui_gtk.cc:71
+msgid "GTK Interface"
+msgstr "Antaramuka GTK"
+
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
+#, c-format
+msgid "%s - Audacious"
+msgstr "%s - Audacious"
+
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
+msgid "Buffering ..."
+msgstr "Menimbal ..."
+
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
+msgid "Audacious"
+msgstr "Audacious"
+
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
+#, c-format
+msgid "%d channel"
+msgid_plural "%d channels"
+msgstr[0] "%d saluran"
+
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
+#, c-format
+msgid "%d kbps"
+msgstr "%d kbps"
+
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Mod tunggal."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Mod senarai main."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Dihentikan selepas lagu."
+
+#: src/hotkey/gui.cc:71
+msgid "Previous track"
+msgstr "Trek terdahulu"
+
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
+msgid "Play"
+msgstr "Main"
+
+#: src/hotkey/gui.cc:73
+msgid "Pause/Resume"
+msgstr "Jeda/Sambung Semula"
+
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
+msgid "Stop"
+msgstr "Henti"
+
+#: src/hotkey/gui.cc:75
+msgid "Next track"
+msgstr "Trek berikutnya"
+
+#: src/hotkey/gui.cc:76
+msgid "Forward 5 seconds"
+msgstr "Maju 5 saat"
+
+#: src/hotkey/gui.cc:77
+msgid "Rewind 5 seconds"
+msgstr "Undur 5 saat"
+
+#: src/hotkey/gui.cc:78
+msgid "Mute"
+msgstr "Senyap"
+
+#: src/hotkey/gui.cc:79
+msgid "Volume up"
+msgstr "Volum naik"
+
+#: src/hotkey/gui.cc:80
+msgid "Volume down"
+msgstr "Volum turun"
+
+#: src/hotkey/gui.cc:81
+msgid "Jump to file"
+msgstr "Lompat ke fail"
+
+#: src/hotkey/gui.cc:82
+msgid "Toggle player window(s)"
+msgstr "Togol tetingkap pemain"
+
+#: src/hotkey/gui.cc:83
+msgid "Show On-Screen-Display"
+msgstr "Tunjuk Paparan-Atas-Skrin"
+
+#: src/hotkey/gui.cc:84
+msgid "Toggle repeat"
+msgstr "Togol ulang"
+
+#: src/hotkey/gui.cc:85
+msgid "Toggle shuffle"
+msgstr "Togol kocok"
+
+#: src/hotkey/gui.cc:86
+msgid "Toggle stop after current"
+msgstr "Togol henti selepas semasa"
+
+#: src/hotkey/gui.cc:87
+msgid "Raise player window(s)"
+msgstr "Naik tetingkap pemain"
+
+#: src/hotkey/gui.cc:97
+msgid "(none)"
+msgstr "(tiada)"
+
+#: src/hotkey/gui.cc:234
+msgid ""
+"It is not recommended to bind the primary mouse buttons without "
+"modificators.\n"
+"\n"
+"Do you want to continue?"
+msgstr ""
+"Anda tidak disarankan mengikat butang tetikus utama dan pengubahsuai.\n"
+"\n"
+"Anda mahu teruskan?"
+
+#: src/hotkey/gui.cc:236
+msgid "Binding mouse buttons"
+msgstr "Pengikatan butang tetikus"
+
+#: src/hotkey/gui.cc:391
+msgid ""
+"Press a key combination inside a text field.\n"
+"You can also bind mouse buttons."
+msgstr ""
+"Tekan gabungan kekunci di dalam medan teks.\n"
+"Anda juga boleh mengikat butang tetikus."
+
+#: src/hotkey/gui.cc:396
+msgid "Hotkeys:"
+msgstr "Kekunci Panas:"
+
+#: src/hotkey/gui.cc:413
+msgid "<b>Action:</b>"
+msgstr "<b>Tindakan:</b>"
+
+#: src/hotkey/gui.cc:420
+msgid "<b>Key Binding:</b>"
+msgstr "<b>Pengikatan Kekunci:</b>"
+
+#: src/hotkey/gui.cc:468
+msgid "_Add"
+msgstr "T_ambah"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Kekunci Panas Sejagat"
+
+#: src/hotkey/plugin.cc:79
+msgid ""
+"Global Hotkey Plugin\n"
+"Control the player with global key combinations or multimedia keys.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n"
+"\n"
+"Contributers include:\n"
+"Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+"Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+" Bryn Davies <curious at ihug.com.au>,\n"
+" Jonathan A. Davis <davis at jdhouse.org>,\n"
+" Jeremy Tan <nsx at nsx.homeip.net>"
+msgstr ""
+"Pemalam Kekunci Panas Sejagat\n"
+"Kawal pemain dengan gabungan kekunci sejagat atau kekunci multimedia.\n"
+"\n"
+"Hakcopta (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n"
+"\n"
+"Penyumbang terlibat:\n"
+"Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+"Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+" Bryn Davies <curious at ihug.com.au>,\n"
+" Jonathan A. Davis <davis at jdhouse.org>,\n"
+" Jeremy Tan <nsx at nsx.homeip.net>"
+
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Output JEK"
+
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Sambung ke port output secara automatik"
+
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Hanya %d port output JACK ditemui tetapi %d yang diperlukan."
+
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Gagal menyambung ke port JACK %s."
+
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK hanya menyokong audio titik-apung. Anda mesti ubah kedalaman bit output "
+"ke titik-apung di dalam tetapan Audacious."
+
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Gagal bersambung dengan pelayan JACK; adakah ia berjalan?"
+
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
+msgid ""
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
+msgstr ""
+"Pelayan JACK memerlukan kadar sampel %d Hz, tetapi Audacious dimainkan pada "
+"%d Hz. Sila guna kesan Penukar Kadar Sampel untuk membetulkan ketidakpadanan "
+"ini."
+
+#: src/ladspa/plugin.cc:414
+#, c-format
+msgid "%s Settings"
+msgstr "Tetapan %s"
+
+#: src/ladspa/plugin.cc:478
+msgid "Module paths:"
+msgstr "Laluan Modul:"
+
+#: src/ladspa/plugin.cc:483
+msgid ""
+"<small>Separate multiple paths with a colon.\n"
+"These paths are searched in addition to LADSPA_PATH.\n"
+"After adding new paths, press Enter to scan for new plugins.</small>"
+msgstr ""
+"<small>Pisah laluan berbilang dengan tanda titk bertindih.\n"
+"Laluan ini digelintar sebagai tambahan ke LADSPA_PATH.\n"
+"Selepas menambah laluan baharu, tekan Enter untuk imbas pemalam baharu.</"
+"small>"
+
+#: src/ladspa/plugin.cc:499
+msgid "Available plugins:"
+msgstr "Pemalam tersedia:"
+
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
+msgid "Enable"
+msgstr "Benarkan"
+
+#: src/ladspa/plugin.cc:518
+msgid "Enabled plugins:"
+msgstr "Pemalam dibenarkan:"
+
+#: src/ladspa/plugin.cc:534
+msgid "Settings"
+msgstr "Tetapan"
+
+#: src/ladspa/plugin.cc:551
+msgid ""
+"LADSPA Host for Audacious\n"
+"Copyright 2011 John Lindgren"
+msgstr ""
+"Hos LADSPA untuk Audacious\n"
+"Hakcipta 2011 John Lindgren"
+
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "Hos LADSPA"
+
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Pemalam LIRC"
+
+#: src/lirc/lirc.cc:381
+msgid ""
+"A simple plugin to control Audacious using the LIRC remote control daemon\n"
+"\n"
+"Adapted for Audacious by:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Based on the XMMS LIRC plugin by:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"For more information about LIRC, see http://lirc.org."
+msgstr ""
+"Pemalam ringkas untuk mengawal Audacious menggunakan daemon kawalan jauh "
+"LIRC\n"
+"\n"
+"Diadaptasi untuk Audacious oleh:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Berdasarkan pada pemalam LIRC XMMS oleh:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"Untuk maklumat lanjut mengenai LIRC, sila rujuk http://lirc.org."
+
+#: src/lirc/lirc.cc:392
+msgid "<b>Connection</b>"
+msgstr "<b>Sambungan</b>"
+
+#: src/lirc/lirc.cc:393
+msgid "Reconnect to LIRC server"
+msgstr "Sambung semula ke pelayan LIRC"
+
+#: src/lirc/lirc.cc:395
+msgid "Wait before reconnecting:"
+msgstr "Tunggu sebelum disambung semula:"
+
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Pemalam LyricWiki"
+
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
+msgid "No lyrics available"
+msgstr "Tiada lirik tersedia"
+
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Ralat"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
+#, c-format
+msgid "Unable to fetch %s"
+msgstr "Tidak boleh dapatkan %s"
+
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
+#, c-format
+msgid "Unable to parse %s"
+msgstr "Tidak boleh hurai %s"
+
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
+msgid "Looking for lyrics ..."
+msgstr "Mencari lirik ..."
+
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Missing song metadata"
+msgstr "Data meta lagu hilang"
+
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
+msgid "Connecting to lyrics.wikia.com ..."
+msgstr "Menyambung ke lyrics.wikia.com ..."
+
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Pemalam LyricWiki (Qt)"
+
+#: src/m3u/m3u.cc:32
+msgid "M3U Playlists"
+msgstr "Senarai Main M3U"
+
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Penjana Rentak"
+
+#: src/metronom/metronom.cc:147
+#, c-format
+msgid "Tact generator: %d bpm"
+msgstr "Penjana rentak: %d bpm"
+
+#: src/metronom/metronom.cc:149
+#, c-format
+msgid "Tact generator: %d bpm %d/%d"
+msgstr "Penjana rentak: %d bpm %d/%d"
+
+#: src/metronom/metronom.cc:237
+msgid ""
+"A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
+"\n"
+"To use it, add a URL: tact://beats*num/den\n"
+"e.g. tact://77 to play 77 beats per minute\n"
+"or tact://60*3/4 to play 60 bpm in 3/4 tacts"
+msgstr ""
+"Penjana Rentak oleh Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
+"\n"
+"Untuk gunakanya, tambah URL: tact://beats*num/den\n"
+"cth. tact://77 untuk main 77 beat per minit\n"
+"atau tact://60*3/4 untuk main 60 bpm dalam tempo 3/4 rentak"
+
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Pengadun Saluran"
+
+#: src/mixer/mixer.cc:202
+msgid ""
+"Channel Mixer Plugin for Audacious\n"
+"Copyright 2011-2012 John Lindgren and Michał Lipski"
+msgstr ""
+"Pemalam Pengadun Saluran untuk Audacious\n"
+"Hakcipta 2011-2012 John Lindgren dan Michał Lipski"
+
+#: src/mixer/mixer.cc:206
+msgid "<b>Channel Mixer</b>"
+msgstr "<b>Pengadun Saluran</b>"
+
+#: src/mixer/mixer.cc:207
+msgid "Output channels:"
+msgstr "Saluran output:"
+
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
+msgstr "Pemalam MMS"
+
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Ralat menyambung ke pelayan MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Pemain Modul)"
+
+#: src/modplug/plugin_main.cc:53
+msgid "<b>Resolution</b>"
+msgstr "<b>Resolusi</b>"
+
+#: src/modplug/plugin_main.cc:54
+msgid "8-bit"
+msgstr "8-bit"
+
+#: src/modplug/plugin_main.cc:55
+msgid "16-bit"
+msgstr "16-bit"
+
+#: src/modplug/plugin_main.cc:56
+msgid "<b>Channels</b>"
+msgstr "<b>Saluran</b>"
+
+#: src/modplug/plugin_main.cc:60
+msgid "Nearest (fastest)"
+msgstr "Terdekat (terpantas)"
+
+#: src/modplug/plugin_main.cc:61
+msgid "Linear (fast)"
+msgstr "Linear (pantas)"
+
+#: src/modplug/plugin_main.cc:62
+msgid "Spline (good)"
+msgstr "Spline (baik)"
+
+#: src/modplug/plugin_main.cc:63
+msgid "Polyphase (best)"
+msgstr "Polifasa (terbaik)"
+
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Kadar sampel</b>"
+
+#: src/modplug/plugin_main.cc:65
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: src/modplug/plugin_main.cc:66
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: src/modplug/plugin_main.cc:67
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: src/modplug/plugin_main.cc:68
+msgid "96 kHz"
+msgstr "96 kHz"
+
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
+msgid "Level:"
+msgstr "Aras:"
+
+#: src/modplug/plugin_main.cc:78
+msgid "Cutoff:"
+msgstr "Pangkas:"
+
+#: src/modplug/plugin_main.cc:91
+msgid "<b>Reverb</b>"
+msgstr "<b>Reverb</b>"
+
+#: src/modplug/plugin_main.cc:94
+msgid "<b>Bass Boost</b>"
+msgstr "<b>Galak Bes</b>"
+
+#: src/modplug/plugin_main.cc:97
+msgid "<b>Surround</b>"
+msgstr "<b>Keliling</b>"
+
+#: src/modplug/plugin_main.cc:100
+msgid "<b>Preamp</b>"
+msgstr "<b>Praamp</b>"
+
+#: src/modplug/plugin_main.cc:107
+msgid "Oversample"
+msgstr "Oversampel"
+
+#: src/modplug/plugin_main.cc:108
+msgid "Noise reduction"
+msgstr "Pengurangan hingar"
+
+#: src/modplug/plugin_main.cc:109
+msgid "Play Amiga MODs"
+msgstr "Main MOD Amiga"
+
+#: src/modplug/plugin_main.cc:110
+msgid "<b>Repeat</b>"
+msgstr "<b>Ulang</b>"
+
+#: src/modplug/plugin_main.cc:111
+msgid "Repeat count:"
+msgstr "Kiraan ulang:"
+
+#: src/modplug/plugin_main.cc:112
+msgid "To repeat forever, set the repeat count to -1."
+msgstr "Untuk ulang selamanya, tetapkan kiraan ulang menjadi -1."
+
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Tetapan ini akan berkesan bila Audacious dimulakan semula."
+
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
+msgstr "Pemalam MPG123"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Lanjutan</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Guna pengiraan lebih tepat (perlahan)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Keliling"
+
+#: src/mpris2/plugin.cc:39
+msgid "MPRIS 2 Server"
+msgstr "Pelayan MPRIS 2"
+
+#: src/neon/neon.cc:97
+msgid "Neon HTTP/HTTPS Plugin"
+msgstr "Pemalam Neon HTTP/HTTPS"
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Ralat menghurai arah semula"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Ralat HTTP tidak diketahui"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Ralat menghurai URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Terlalu banyak arah semula"
+
+#: src/notify/event.cc:64
+msgid "Stopped"
+msgstr "Dihentikan"
+
+#: src/notify/event.cc:64
+msgid "Audacious is not playing."
+msgstr "Audacioud tidak dimainkan."
+
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Pemberitahuan Desktop"
+
+#: src/notify/notify.cc:60
+msgid ""
+"Desktop Notifications Plugin for Audacious\n"
+"Copyright (C) 2010 Maximilian Bogner\n"
+"Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"This plugin is free software: you can redistribute it and/or modify it under "
+"the terms of the GNU General Public License as published by the Free "
+"Software Foundation, either version 3 of the License, or (at your option) "
+"any later version.\n"
+"\n"
+"This plugin is distributed in the hope that 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, see <http://www.gnu.org/licenses/>."
+msgstr ""
+"Pemalam Pemberitahuan Desktop untuk Audacious\n"
+"Hakcipta (C) 2010 Maximilian Bogner\n"
+"Hakcipta (C) 2011-2013 John Lindgren dan Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"Pemalam adalah perisian bebas; anda boleh mengedarkannya dan/atau "
+"mengubahsuainya dibawah terma Pelesenan Awam Am GNU yang diterbitkan oleh "
+"Free Software Foundation, sama ada versi 3 lesen, atau (mengikut pilihan "
+"anda) mana-mana versi terkini.\n"
+"\n"
+"Pemalam ini diedarkan dengan harapan ianya akan berguna, TANPA SEBARANG "
+"JAMINAN; termasuk juga KESESUAIAN UNTUK DIPASARKAN, JAMINAN KUALITI, atau "
+"JAMINAN ATAS APA JUA SEBAB. Sila lihat GNU General Public License untuk "
+"maklumat lanjut.\n"
+"\n"
+"Anda seharusnya menerima satu salinan Lesen Awam Am GNU bersama-sama dengan "
+"pengurus skrip Nautilus; jika tidak, rujuk <http://www.gnu.org/licenses/>."
+
+#: src/notify/notify.cc:110
+msgid "Show playback controls"
+msgstr "Tunjuk kawalan main balik"
+
+#: src/notify/notify.cc:112
+msgid "Always show notification"
+msgstr "Sentiasa tunjuk pemberitahuan"
+
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Sertakan nama album dalam pemberitahuan"
+
+#: src/notify/osd.cc:58
+msgid "Show"
+msgstr "Tunjuk"
+
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
+msgid "Pause"
+msgstr "Jeda"
+
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
+msgid "Next"
+msgstr "Berikutnya"
+
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Output OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Output OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Peranti lalai"
+
+#: src/oss4/plugin.cc:77
+msgid "Audio device:"
+msgstr "Peranti audio:"
+
+#: src/oss4/plugin.cc:80
+msgid "Use alternate device:"
+msgstr "Guna peranti alternatif:"
+
+#: src/oss4/plugin.cc:84
+msgid "Save volume between sessions."
+msgstr "Simpan volum diantara sesi."
+
+#: src/oss4/plugin.cc:86
+msgid "Enable format conversions made by the OSS software."
+msgstr "Benarkan penukaran format yang dibuat oleh perisian OSS."
+
+#: src/oss4/plugin.cc:88
+msgid "Enable exclusive mode to prevent virtual mixing."
+msgstr "Benarkan mod ekslusif untuk menghindari pengadunan maya."
+
+#: src/oss4/plugin.cc:100
+msgid ""
+"OSS4 Output Plugin for Audacious\n"
+"Copyright 2010-2012 Michał Lipski\n"
+"\n"
+"I would like to thank people on #audacious, especially Tony Vroon and John "
+"Lindgren and of course the authors of the previous OSS plugin."
+msgstr ""
+"Pemalam Output OSS4 untuk Audacious\n"
+"Hakcipta 2010-2012 Michał Lipski\n"
+"\n"
+"Terima kasih buat individu di #audacious, terutamanya Tony Vroon dan John "
+"Lindgren serta bekas pengarang pemalam OSS."
+
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Pengurus Senarai Main"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Masukan"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Buang"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "N_ama Semula"
+
+#: src/pls/pls.cc:35
+msgid "PLS Playlists"
+msgstr "Senarai Main PLS"
+
+#: src/psf/plugin.cc:45
+msgid "OpenPSF PSF1/PSF2 Decoder"
+msgstr "Penyahkod OpenPSF PSF1/PSF2"
+
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Output PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
+msgid ""
+"Audacious PulseAudio Output Plugin\n"
+"\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."
+msgstr ""
+"Pemalam Output Audacious PulseAudio\n"
+"\n"
+"Program ini adalah perisian bebas; anda boleh mengedarkannya dan/atau\n"
+"mengubahsuainya dibawah terma Pelesenan Awam Am GNU yang\n"
+"diterbitkan oleh Free Software Foundation; sama ada versi 2 dari lesen, \n"
+"atau (mengikut pilihan anda) mana-mana versi terkini\n"
+"\n"
+"Program ini diedarkan dengan harapan ianya akan berguna, TANPA \n"
+"SEBARANG JAMINAN; termasuk juga KESESUAIAN UNTUK DIPASARKAN,\n"
+"JAMINAN KUALITI, atau JAMINAN ATAS APA JUA SEBAB. Sila lihat GNU\n"
+"General Public License untuk maklumat lanjut.\n"
+"\n"
+"Anda seharusnya menerima satu salinan Lesen Awam Am GNU \n"
+"bersama-sama dengan Gwibber; jika tidak, laporkannya ke Free Software\n"
+"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
+"USA."
+
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Output QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Pemalam Output Audio QtMultimedia untuk Audacious\n"
+"Hakcipta 2014 William Pitcock\n"
+"\n"
+"Berdasarkan pada Pemalam Output SDL untuk Audacious\n"
+"Hakcipta 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Berfungsi ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Gelintar"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Buka Folder ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Tambah Folder ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Pemeriksa _Log ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Buka Fail"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Tambah Fail"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Terdahulu"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Ulang"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Kocok"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Antaramuka Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Penukar Kadar Sampel"
+
+#: src/resample/resample.cc:183
+msgid ""
+"Sample Rate Converter Plugin for Audacious\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+"Pemalam Penukar Kadar Sampel untuk Audacious\n"
+"Hakcipta 2010-2012 John Lindgren"
+
+#: src/resample/resample.cc:187
+msgid "Skip/repeat samples"
+msgstr "Langkau/ulang sampel"
+
+#: src/resample/resample.cc:188
+msgid "Linear interpolation"
+msgstr "Interpolasi linear"
+
+#: src/resample/resample.cc:189
+msgid "Fast sinc interpolation"
+msgstr "Interpolasi sinc pantas"
+
+#: src/resample/resample.cc:190
+msgid "Medium sinc interpolation"
+msgstr "Interpolasi sinc sederhana"
+
+#: src/resample/resample.cc:191
+msgid "Best sinc interpolation"
+msgstr "Interpolasi sinc terbaik"
+
+#: src/resample/resample.cc:195
+msgid "<b>Conversion</b>"
+msgstr "<b>Penukaran</b>"
+
+#: src/resample/resample.cc:196
+msgid "Method:"
+msgstr "Kaedah:"
+
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
+msgid "Rate:"
+msgstr "Kadar:"
+
+#: src/resample/resample.cc:202
+msgid "<b>Rate Mappings</b>"
+msgstr "<b>Pemetaan Kadar</b>"
+
+#: src/resample/resample.cc:203
+msgid "Use rate mappings"
+msgstr "Guna pemetaan kadar"
+
+#: src/resample/resample.cc:205
+msgid "8 kHz:"
+msgstr "8 kHz:"
+
+#: src/resample/resample.cc:209
+msgid "16 kHz:"
+msgstr "16 kHz:"
+
+#: src/resample/resample.cc:213
+msgid "22.05 kHz:"
+msgstr "22.05 kHz:"
+
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
+msgid "44.1 kHz:"
+msgstr "44.1 kHz:"
+
+#: src/resample/resample.cc:225
+msgid "48 kHz:"
+msgstr "48 kHz:"
+
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
+msgid "96 kHz:"
+msgstr "96 kHz:"
+
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
+msgstr "192 kHz:"
+
+#: src/scrobbler2/config_window.cc:41
+#, c-format
+msgid "OK. Scrobbling for user: %s"
+msgstr "OK. Scrobble untuk pengguna: %s"
+
+#: src/scrobbler2/config_window.cc:54
+msgid "Permission Denied"
+msgstr "Keizinan Dinafikan"
+
+#: src/scrobbler2/config_window.cc:56
+msgid "Access the following link to allow Audacious to scrobble your plays:"
+msgstr "Capai pautan berikut untuk membolehkan Audacious scrobble lagu anda:"
+
+#: src/scrobbler2/config_window.cc:66
+msgid "Keep this window open and click 'Check Permission' again.\n"
+msgstr "Kekalkan tetingkap ini dibuka dan klik 'Semak Keizinan' lagi.\n"
+
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
+msgid ""
+"Don't worry. Your scrobbles are saved on your computer.\n"
+"They will be submitted as soon as Audacious is allowed to do so."
+msgstr ""
+"Jangan risau. Scrobble anda disimpan dalam komputer anda.\n"
+"Ia akan diserah sebaik sahaja Audacious dibenarkan membuatnya."
+
+#: src/scrobbler2/config_window.cc:77
+msgid "Network Problem."
+msgstr "Masalah Rangkaian."
+
+#: src/scrobbler2/config_window.cc:78
+msgid "There was a problem contacting Last.fm. Please try again later."
+msgstr "Terdapat masalah menghubungi Last.fm. Sila cuba lagi kemudian."
+
+#: src/scrobbler2/config_window.cc:110
+msgid "Checking..."
+msgstr "Memeriksa..."
+
+#: src/scrobbler2/config_window.cc:176
+msgid "C_heck Permission"
+msgstr "S_emak Keizinan"
+
+#: src/scrobbler2/config_window.cc:177
+msgid "_Revoke Permission"
+msgstr "_Batalkan Keizinan"
+
+#: src/scrobbler2/config_window.cc:220
+msgid ""
+"You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
+msgstr "Anda perlu benarkan Audacious scrobble trek ke akaun Last.fm anda.\n"
+
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
+msgid ""
+"The Scrobbler plugin could not be started.\n"
+"There might be a problem with your installation."
+msgstr ""
+"Pemalam Scrobbler tidak dapat dimulakan.\n"
+"Terdapat masalah dengan pemasangan anda."
+
+#: src/scrobbler2/scrobbler.cc:289
+msgid ""
+"Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
+"\n"
+"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Thanks to John Lindgren for giving me a hand at the beginning of this "
+"project.\n"
+"\n"
+msgstr ""
+"Pemalam Audacious Scrobbler 2.0 oleh Pitxyoki,\n"
+"\n"
+"hakcipta © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Terima kasih buat John Lindgren kerana membantu saya memulakan projek ini.\n"
+"\n"
+
+#: src/scrobbler2/scrobbler_communication.cc:642
+msgid ""
+"Audacious is now using an improved version of the Last.fm Scrobbler.\n"
+"Please check the Preferences for the Scrobbler plugin."
+msgstr ""
+"Audacious kini menggunakan versi dipertingkat Scrobbler Last.fm.\n"
+"Sila semak Keutamaan untuk pemalam Scrobbler."
+
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Output SDL"
+
+#: src/sdlout/sdlout.cc:77
+msgid ""
+"SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Pemalam Output SDL untuk Audacious\n"
+"Hakcipta 2010 John Lindgren"
+
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
+msgid "Library"
+msgstr "Pustaka"
+
+#: src/search-tool/search-tool.cc:394
+#, c-format
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d keputusan"
+
+#: src/search-tool/search-tool.cc:400
+#, c-format
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d tersembunyi)"
+
+#: src/search-tool/search-tool.cc:594
+#, c-format
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d lagu"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "dari genre ini"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "hidup"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "oleh"
+
+#: src/search-tool/search-tool.cc:643
+msgid "_Create Playlist"
+msgstr "_Cipta Senarai Main"
+
+#: src/search-tool/search-tool.cc:645
+msgid "_Add to Playlist"
+msgstr "T_ambah ke Senarai Main"
+
+#: src/search-tool/search-tool.cc:684
+msgid "Search library"
+msgstr "Gelintar pustaka"
+
+#: src/search-tool/search-tool.cc:688
+msgid ""
+"To import your music library into Audacious, choose a folder and then click "
+"the \"refresh\" icon."
+msgstr ""
+"Untuk mengimport pustaka muzik anda ke dalam Audacious, pilih satu folder "
+"dan kemudian klik pada ikon \"segar semula\"."
+
+#: src/search-tool/search-tool.cc:696
+msgid "Please wait ..."
+msgstr "Tunggu sebentar ..."
+
+#: src/search-tool/search-tool.cc:723
+msgid "Choose Folder"
+msgstr "Pilih Folder"
+
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Pemain SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Output</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Saluran:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulasi</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emulasi MOS 8580 (lalai: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Jangan pilih model cip secara automatik"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emulasi penapis"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Kelajuan jam:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Jangan pilih kelajuan jam secara automatik"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Masa main balik</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Tetapkan masa main balik maksimum:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Hanya guna bila panjang lagu tidak diketahui"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Tetapkan masa main balik minimum:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subnada</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Benarkan subnada"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Abai subnada lebih pendek dari:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Perhatian</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Pembuangan Senyap"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Pemalam Pembuangan Senyap untuk Audacious\n"
+"Hakcipta 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Pembuangan Senyap</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Ambang:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Buka Fail ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Buka URL ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Gelintar Pustaka"
+
+#: src/skins/menus.cc:68
+msgid "Playback"
+msgstr "Main Balik"
+
+#: src/skins/menus.cc:69
+msgid "Playlist"
+msgstr "Senarai Main"
+
+#: src/skins/menus.cc:70
+msgid "View"
+msgstr "Lihat"
+
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
+msgid "Services"
+msgstr "Perkhidmatan"
+
+#: src/skins/menus.cc:74
+msgid "About ..."
+msgstr "Perihal ..."
+
+#: src/skins/menus.cc:75
+msgid "Settings ..."
+msgstr "Tetapan ..."
+
+#: src/skins/menus.cc:76
+msgid "Quit"
+msgstr "Keluar"
+
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
+msgid "Song Info ..."
+msgstr "Maklumat Lagu ..."
+
+#: src/skins/menus.cc:84
+msgid "No Playlist Advance"
+msgstr "Tiada Senarai Main Pendahuluan"
+
+#: src/skins/menus.cc:85
+msgid "Stop After This Song"
+msgstr "Henti Selepas Lagu Ini"
+
+#: src/skins/menus.cc:93
+msgid "Set A-B Repeat"
+msgstr "Tetapkan Ulang A-B"
+
+#: src/skins/menus.cc:94
+msgid "Clear A-B Repeat"
+msgstr "Kosongkan Ulang A-B"
+
+#: src/skins/menus.cc:96
+msgid "Jump to Song ..."
+msgstr "Lompat ke Lagu ..."
+
+#: src/skins/menus.cc:97
+msgid "Jump to Time ..."
+msgstr "Lompat ke Masa ..."
+
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Main/Sambung Semula"
+
+#: src/skins/menus.cc:103
+msgid "New Playlist"
+msgstr "Senarai Main Baharu"
+
+#: src/skins/menus.cc:104
+msgid "Rename Playlist ..."
+msgstr "Nama Semula Senarai Main ..."
+
+#: src/skins/menus.cc:105
+msgid "Remove Playlist"
+msgstr "Buang Senarai Main"
+
+#: src/skins/menus.cc:107
+msgid "Previous Playlist"
+msgstr "Senarai Main Terdahulu"
+
+#: src/skins/menus.cc:108
+msgid "Next Playlist"
+msgstr "Senarai Main Berikutnya"
+
+#: src/skins/menus.cc:110
+msgid "Import Playlist ..."
+msgstr "Import Senarai Main ..."
+
+#: src/skins/menus.cc:111
+msgid "Export Playlist ..."
+msgstr "Eksport Senarai Main ..."
+
+#: src/skins/menus.cc:113
+msgid "Playlist Manager ..."
+msgstr "Pengurus Senarai Main ..."
+
+#: src/skins/menus.cc:114
+msgid "Queue Manager ..."
+msgstr "Pengurus Baris Gilir ..."
+
+#: src/skins/menus.cc:116
+msgid "Refresh Playlist"
+msgstr "Segar Semula Senarai Main"
+
+#: src/skins/menus.cc:120
+msgid "Show Playlist Editor"
+msgstr "Tunjuk Penyunting Senarai Main"
+
+#: src/skins/menus.cc:121
+msgid "Show Equalizer"
+msgstr "Tunjuk Penyama"
+
+#: src/skins/menus.cc:123
+msgid "Show Remaining Time"
+msgstr "Tunjuk Masa Berbaki"
+
+#: src/skins/menus.cc:125
+msgid "Always on Top"
+msgstr "Sentiasa di Atas"
+
+#: src/skins/menus.cc:126
+msgid "On All Workspaces"
+msgstr "Pada Semua Ruang Kerja"
+
+#: src/skins/menus.cc:128
+msgid "Roll Up Player"
+msgstr "Gulung Pemain"
+
+#: src/skins/menus.cc:129
+msgid "Roll Up Playlist Editor"
+msgstr "Gulung Penyunting Senarai Main"
+
+#: src/skins/menus.cc:130
+msgid "Roll Up Equalizer"
+msgstr "Gulung Penyama"
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Saiz Dua Kali Ganda"
+
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "Tambah URL ..."
+
+#: src/skins/menus.cc:139
+msgid "Add Files ..."
+msgstr "Tambah Fail ..."
+
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
+msgid "By Title"
+msgstr "Mengikut Tajuk"
+
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "Mengikut Nama Fail"
+
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
+msgid "By File Path"
+msgstr "Mengikut Laluan Fail"
+
+#: src/skins/menus.cc:151
+msgid "Remove All"
+msgstr "Buang Semua"
+
+#: src/skins/menus.cc:152
+msgid "Clear Queue"
+msgstr "Kosongkan Baris Gilir"
+
+#: src/skins/menus.cc:154
+msgid "Remove Unavailable Files"
+msgstr "Buang Fail Tidak Tersedia"
+
+#: src/skins/menus.cc:155
+msgid "Remove Duplicates"
+msgstr "Buang Pendua"
+
+#: src/skins/menus.cc:157
+msgid "Remove Unselected"
+msgstr "Buang Dinyahpilih"
+
+#: src/skins/menus.cc:158
+msgid "Remove Selected"
+msgstr "Buang Terpilih"
+
+#: src/skins/menus.cc:162
+msgid "Search and Select"
+msgstr "Gelintar dan Pilih"
+
+#: src/skins/menus.cc:164
+msgid "Invert Selection"
+msgstr "Songsangkan Pemilihan"
+
+#: src/skins/menus.cc:165
+msgid "Select None"
+msgstr "Pilih Tiada"
+
+#: src/skins/menus.cc:166
+msgid "Select All"
+msgstr "Pilih Semua"
+
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Mengikut Nombor Trek"
+
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
+msgid "By Artist"
+msgstr "Mengikut Artis"
+
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Mengikut Album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Mengikut Album Artis"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
+msgid "By Release Date"
+msgstr "Mengikut Tarikh Keluaran"
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Mengikut Genre"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Mengikut Panjang"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Mengikut Tajuk Suai"
+
+#: src/skins/menus.cc:198
+msgid "Randomize List"
+msgstr "Rawakkan Senarai"
+
+#: src/skins/menus.cc:199
+msgid "Reverse List"
+msgstr "Songsangkan Senarai"
+
+#: src/skins/menus.cc:201
+msgid "Sort Selected"
+msgstr "Isih Terpilih"
+
+#: src/skins/menus.cc:202
+msgid "Sort List"
+msgstr "Isih Senarai"
+
+#: src/skins/menus.cc:208
+msgid "Cut"
+msgstr "Potong"
+
+#: src/skins/menus.cc:209
+msgid "Copy"
+msgstr "Salin"
+
+#: src/skins/menus.cc:210
+msgid "Paste"
+msgstr "Tampal"
+
+#: src/skins/menus.cc:212
+msgid "Queue/Unqueue"
+msgstr "Baris Gilir/Nyahbaris Gilir"
+
+#: src/skins/menus.cc:218
+msgid "Load Preset ..."
+msgstr "Muat Praset ..."
+
+#: src/skins/menus.cc:219
+msgid "Load Auto Preset ..."
+msgstr "Muat Auto Praset ..."
+
+#: src/skins/menus.cc:220
+msgid "Load Default"
+msgstr "Muat Lalai"
+
+#: src/skins/menus.cc:221
+msgid "Load Preset File ..."
+msgstr "Muat Fail Praset ..."
+
+#: src/skins/menus.cc:222
+msgid "Load EQF File ..."
+msgstr "Muat Fail EQF ..."
+
+#: src/skins/menus.cc:224
+msgid "Save Preset ..."
+msgstr "Simpan Praset ..."
+
+#: src/skins/menus.cc:225
+msgid "Save Auto Preset ..."
+msgstr "Simpan Auto Praset ..."
+
+#: src/skins/menus.cc:226
+msgid "Save Default"
+msgstr "Simpan Lalai"
+
+#: src/skins/menus.cc:227
+msgid "Save Preset File ..."
+msgstr "Simpan Fail Praset ..."
+
+#: src/skins/menus.cc:228
+msgid "Save EQF File ..."
+msgstr "Simpan Fail EQF ..."
+
+#: src/skins/menus.cc:230
+msgid "Delete Preset ..."
+msgstr "Padam Praset ..."
+
+#: src/skins/menus.cc:231
+msgid "Delete Auto Preset ..."
+msgstr "Padam Auto Praset ..."
+
+#: src/skins/menus.cc:233
+msgid "Import Winamp Presets ..."
+msgstr "Import Praset Winamp ..."
+
+#: src/skins/menus.cc:235
+msgid "Reset to Zero"
+msgstr "Tetap Semula ke Sifar"
+
+#: src/skins/plugin.cc:48
+msgid "Winamp Classic Interface"
+msgstr "Antaramuka Klasik Winamp"
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
+msgid "Save"
+msgstr "Simpan"
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
+msgid "Load"
+msgstr "Muat"
+
+#: src/skins/preset-browser.cc:83
+msgid "Load Preset File"
+msgstr "Muat Fail Praset"
+
+#: src/skins/preset-browser.cc:100
+msgid "Load EQF File"
+msgstr "Muat Fail EQF"
+
+#: src/skins/preset-browser.cc:119
+msgid "Save Preset File"
+msgstr "Simpan Fail Praset"
+
+#: src/skins/preset-browser.cc:137
+msgid "Save EQF File"
+msgstr "Simpan Fail EQF"
+
+#: src/skins/preset-browser.cc:151
+msgid "Import Winamp Presets"
+msgstr "Import Praset Winamp"
+
+#: src/skins/preset-list.cc:285
+msgid "Presets"
+msgstr "Praset"
+
+#: src/skins/preset-list.cc:335
+msgid "Load preset"
+msgstr "Muat praset"
+
+#: src/skins/preset-list.cc:351
+msgid "Load auto-preset"
+msgstr "Muat auto-praset"
+
+#: src/skins/preset-list.cc:367
+msgid "Save preset"
+msgstr "Simpan praset"
+
+#: src/skins/preset-list.cc:382
+msgid "Save auto-preset"
+msgstr "Simpan auto-praset"
+
+#: src/skins/preset-list.cc:408
+msgid "Delete preset"
+msgstr "Padam praset"
+
+#: src/skins/preset-list.cc:424
+msgid "Delete auto-preset"
+msgstr "Padam auto-praset"
+
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Pemain:"
+
+#: src/skins/skins_cfg.cc:178
+msgid "Select main player window font:"
+msgstr "Pilih fon tetingkap pemain utama:"
+
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Senarai Main:"
+
+#: src/skins/skins_cfg.cc:181
+msgid "Select playlist font:"
+msgstr "Pilih fon senarai main:"
+
+#: src/skins/skins_cfg.cc:187
+msgid "<b>Skin</b>"
+msgstr "<b>Kulit</b>"
+
+#: src/skins/skins_cfg.cc:189
+msgid "<b>Fonts</b>"
+msgstr "<b>Fon</b>"
+
+#: src/skins/skins_cfg.cc:192
+msgid "Use bitmap fonts (supports ASCII only)"
+msgstr "Guna fon peta bit (sokong ASCII sahaja)"
+
+#: src/skins/skins_cfg.cc:194
+msgid "Scroll song title"
+msgstr "Tatal tajuk lagu"
+
+#: src/skins/skins_cfg.cc:196
+msgid "Scroll song title in both directions"
+msgstr "Tatal tajuk lagu dalam kedua-dua arah"
+
+#: src/skins/skins_cfg.cc:201
+msgid "Analyzer"
+msgstr "Penganalisis"
+
+#: src/skins/skins_cfg.cc:202
+msgid "Scope"
+msgstr "Skop"
+
+#: src/skins/skins_cfg.cc:203
+msgid "Voiceprint / VU meter"
+msgstr "Voiceprint / VU meter"
+
+#: src/skins/skins_cfg.cc:204
+msgid "Off"
+msgstr "Mati"
+
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
+msgid "Normal"
+msgstr "Biasa"
+
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
+msgid "Fire"
+msgstr "Api"
+
+#: src/skins/skins_cfg.cc:210
+msgid "Vertical lines"
+msgstr "Garis menegak"
+
+#: src/skins/skins_cfg.cc:214
+msgid "Lines"
+msgstr "Garis"
+
+#: src/skins/skins_cfg.cc:215
+msgid "Bars"
+msgstr "Palang"
+
+#: src/skins/skins_cfg.cc:219
+msgid "Slowest"
+msgstr "Paling lambat"
+
+#: src/skins/skins_cfg.cc:220
+msgid "Slow"
+msgstr "Lambat"
+
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
+msgid "Medium"
+msgstr "Sederhana"
+
+#: src/skins/skins_cfg.cc:222
+msgid "Fast"
+msgstr "Pantas"
+
+#: src/skins/skins_cfg.cc:223
+msgid "Fastest"
+msgstr "Paling pantas"
+
+#: src/skins/skins_cfg.cc:227
+msgid "Dots"
+msgstr "Titik"
+
+#: src/skins/skins_cfg.cc:228
+msgid "Line"
+msgstr "Garis"
+
+#: src/skins/skins_cfg.cc:229
+msgid "Solid"
+msgstr "Tegar"
+
+#: src/skins/skins_cfg.cc:235
+msgid "Ice"
+msgstr "Ais"
+
+#: src/skins/skins_cfg.cc:240
+msgid "Smooth"
+msgstr "Licin"
+
+#: src/skins/skins_cfg.cc:244
+msgid "<b>Type</b>"
+msgstr "<b>Jenis</b>"
+
+#: src/skins/skins_cfg.cc:245
+msgid "Visualization type:"
+msgstr "Jenis pengvisualan:"
+
+#: src/skins/skins_cfg.cc:248
+msgid "<b>Analyzer</b>"
+msgstr "<b>Penganalisis</b>"
+
+#: src/skins/skins_cfg.cc:249
+msgid "Show peaks"
+msgstr "Tunjuk puncak"
+
+#: src/skins/skins_cfg.cc:251
+msgid "Coloring:"
+msgstr "Pewarnaan:"
+
+#: src/skins/skins_cfg.cc:254
+msgid "Style:"
+msgstr "Gaya:"
+
+#: src/skins/skins_cfg.cc:257
+msgid "Falloff:"
+msgstr "Jatuhan:"
+
+#: src/skins/skins_cfg.cc:260
+msgid "Peak falloff:"
+msgstr "Jatuhan puncak:"
+
+#: src/skins/skins_cfg.cc:264
+msgid "Scope Style:"
+msgstr "Gaya Skop:"
+
+#: src/skins/skins_cfg.cc:267
+msgid "Voiceprint Coloring:"
+msgstr "Pewarnaan Voiceprint:"
+
+#: src/skins/skins_cfg.cc:270
+msgid "VU Meter Style:"
+msgstr "Gaya Meter VU:"
+
+#: src/skins/skins_cfg.cc:276
+msgid "General"
+msgstr "Am"
+
+#: src/skins/skins_cfg.cc:277
+msgid "Visualization"
+msgstr "Pengvisualan"
+
+#: src/skins/ui_equalizer.cc:282
+msgid "Preamp"
+msgstr "Praamp"
+
+#: src/skins/ui_equalizer.cc:286
+msgid "31 Hz"
+msgstr "31 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "63 Hz"
+msgstr "63 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "125 Hz"
+msgstr "125 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "250 Hz"
+msgstr "250 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "500 Hz"
+msgstr "500 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "1 kHz"
+msgstr "1 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "2 kHz"
+msgstr "2 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "4 kHz"
+msgstr "4 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "16 kHz"
+msgstr "16 kHz"
+
+#: src/skins/ui_equalizer.cc:330
+msgid "Audacious Equalizer"
+msgstr "Penyama Audacious"
+
+#: src/skins/ui_main.cc:688
+#, c-format
+msgid "Seek to %d:%-2.2d / %d:%-2.2d"
+msgstr "Jangkau ke %d:%-2.2d / %d:%-2.2d"
+
+#: src/skins/ui_main.cc:709
+#, c-format
+msgid "Volume: %d%%"
+msgstr "Volum: %d%%"
+
+#: src/skins/ui_main.cc:732
+#, c-format
+msgid "Balance: %d%% left"
+msgstr "Imbangan: %d%% kiri"
+
+#: src/skins/ui_main.cc:734
+msgid "Balance: center"
+msgstr "Imbangan: tengah"
+
+#: src/skins/ui_main.cc:736
+#, c-format
+msgid "Balance: %d%% right"
+msgstr "Imbangan: %d%% kanan"
+
+#: src/skins/ui_main.cc:842
+msgid "Options Menu"
+msgstr "Menu Pilihan"
+
+#: src/skins/ui_main.cc:846
+msgid "Disable 'Always On Top'"
+msgstr "Lumpuhkan 'Sentiasa Di Atas'"
+
+#: src/skins/ui_main.cc:848
+msgid "Enable 'Always On Top'"
+msgstr "Benarkan 'Sentiasa Di Atas'"
+
+#: src/skins/ui_main.cc:851
+msgid "File Info Box"
+msgstr "Kotak Maklumat Fail"
+
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Pengvisualan"
+
+#: src/skins/ui_main.cc:1336
+msgid "Repeat point A set."
+msgstr "Ulang titik A ditetapkan."
+
+#: src/skins/ui_main.cc:1341
+msgid "Repeat point B set."
+msgstr "Ulang titik B ditetapkan"
+
+#: src/skins/ui_main.cc:1350
+msgid "Repeat points cleared."
+msgstr "Ulang titik dikosongkan."
+
+#: src/skins/ui_playlist.cc:219
+msgid "Search entries in active playlist"
+msgstr "Gelintar masukan dalam senarai main aktif"
+
+#: src/skins/ui_playlist.cc:226
+msgid ""
+"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."
+msgstr ""
+"Pilih masukan dalam senarai main dengan mengisi satu atau lebih medan. Medan "
+"guna sintaks ungkapan nalar, tidak-sensitif-kata. Jika anda tidak tahu "
+"bagaimana ungkapan nalar berfungsi, hanya masukkan bahagian harfiah apa yang "
+"anda gelintar."
+
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Tajuk:"
+
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
+
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artis:"
+
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nama Fail:"
+
+#: src/skins/ui_playlist.cc:263
+msgid "Clear previous selection before searching"
+msgstr "Kosongkan pemilihan terdahulu sebelum menggelintar"
+
+#: src/skins/ui_playlist.cc:266
+msgid "Automatically toggle queue for matching entries"
+msgstr "Togol baris gilir secara automatik untuk pemadanan masukan"
+
+#: src/skins/ui_playlist.cc:269
+msgid "Create a new playlist with matching entries"
+msgstr "Cipta senarai main baharu dengan masukan sepadan"
+
+#: src/skins/ui_playlist.cc:717
+msgid "Audacious Playlist Editor"
+msgstr "Penyunting Senarai Main Audacious"
+
+#: src/skins/ui_playlist.cc:752
+#, c-format
+msgid "%s (%d of %d)"
+msgstr "%s (%d dar %d)"
+
+#: src/skins/ui_skinselector.cc:167
+msgid "Archived Winamp 2.x skin"
+msgstr "Kulit Winamp 2.x berarkib"
+
+#: src/skins/ui_skinselector.cc:172
+msgid "Unarchived Winamp 2.x skin"
+msgstr "Kulit Winamp 2.x tidak berarkib"
+
+#: src/skins/util.cc:430
+#, c-format
+msgid "Could not create directory (%s): %s\n"
+msgstr "Tidak dapat mencipta direktori (%s): %s\n"
+
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Pemalam Sndfile"
+
+#: src/sndfile/plugin.cc:336
+msgid ""
+"Based on the xmms_sndfile plugin:\n"
+"Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
+"\n"
+"Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\n"
+"\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."
+msgstr ""
+"Berdasarkan pada pemalam xmms_sndfile:\n"
+"Hakcipta (C) 2000, 2002 Erik de Castro Lopo\n"
+"\n"
+"Diadaptasi untuk Audacious oleh Tony Vroon <chainsaw at gentoo.org>\n"
+"\n"
+"Program ini adalah perisian bebas; anda boleh mengedarkannya dan/atau "
+"mengubahsuainya dibawah terma Pelesenan Awam Am GNU yang diterbitkan oleh "
+"Free Software Foundation; sama ada versi 2 dari lesen, atau (mengikut "
+"pilihan anda) mana-mana versi terkini.\n"
+"\n"
+"Program ini diedarkan dengan harapan ianya akan berguna, TANPA SEBARANG "
+"JAMINAN; termasuk juga KESESUAIAN UNTUK DIPASARKAN, JAMINAN KUALITI, atau "
+"JAMINAN ATAS APA JUA SEBAB. Sila lihat GNU General Public License untuk "
+"maklumat lanjut.\n"
+"\n"
+"Anda seharusnya menerima satu salinan Lesen Awam Am GNU bersama-sama dengan "
+"program; jika tidak, laporkannya ke Free Software Foundation, Inc., 51 "
+"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Output Sndio"
+
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Peranti (kosong untuk lalai):"
+
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Simpan dan pulihkan volum:"
+
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Ralat Sndio: Format audio tidak disokong (%d)"
+
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Ralat Sndio: sio_open() gagal"
+
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Ralat Sndio: sio_setpar() gagal"
+
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Ralat Sndio: sio_start() gagal"
+
+#: src/song_change/song_change.cc:33
+msgid "Song Change"
+msgstr "Lagu Berubah"
+
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parameter dilepasi ke shell seharusnya dikurungkan dalam "
+"petikan. Jika dibuat sebaliknya mengundang risiko keselamatan.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Perintah</b>"
+
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Perintah dijalankan bila memulakan lagu baharu:"
+
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Perintah dijalankan dipenghujung lagu:"
+
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Perintah dijalankan dipenghujung senarai main:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Perintah dijalankan bila tajuk lagu berubah (untuk strim rangkaian):"
+
+#: src/song_change/song_change.cc:376
+msgid ""
+"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"
+"%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"
+"%p: Currently playing (1 or 0)\n"
+"%a: Artist\n"
+"%b: Album\n"
+"%T: Track title"
+msgstr ""
+"Anda boleh guna rentetan format berikut yang diganti sebelum memanggil "
+"perintah (bukan emua berguna untuk perintah end-of-playlist):\n"
+"\n"
+"%F: Frekuensi (dalam hertz)\n"
+"%c: Bilangan saluran\n"
+"%f: Nama penuh (laluan penuh)\n"
+"%l: Panjang (dalam milisaat)\n"
+"%n atau %s: Nama lagu\n"
+"%r: Kadar (dalam bit per saat)\n"
+"%t: Kedudukan senarai main (%02d)\n"
+"%p: Dimain ketika ini (1 atau 0)\n"
+"%a: Artis\n"
+"%b: Album\n"
+"%T: Tajuk trek"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Maklumat Lagu (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Pensampel Semula SoX"
+
+#: src/sox-resampler/sox-resampler.cc:144
+msgid ""
+"SoX Resampler Plugin for Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Based on Sample Rate Converter Plugin:\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+"Pemlam Pensampel Semula SoX \n"
+"untuk Audacious\n"
+"Hakcipta 2013 Michał Lipski\n"
+"\n"
+"Berdasarkan pada Pemalam Penukar\n"
+"Kadar Sampel:\n"
+"Hakcipta 2010-2012 John Lindgren"
+
+#: src/sox-resampler/sox-resampler.cc:150
+msgid "Quick"
+msgstr "Pantas"
+
+#: src/sox-resampler/sox-resampler.cc:151
+msgid "Low"
+msgstr "Rendah"
+
+#: src/sox-resampler/sox-resampler.cc:153
+msgid "High"
+msgstr "Tinggi"
+
+#: src/sox-resampler/sox-resampler.cc:154
+msgid "Very High"
+msgstr "Sangat Tinggi"
+
+#: src/sox-resampler/sox-resampler.cc:158
+msgid "Quality:"
+msgstr "Kualiti:"
+
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Kelajuan dan Pic"
+
+#: src/speed-pitch/speed-pitch.cc:210
+msgid "<b>Speed and Pitch</b>"
+msgstr "<b>Kelajuan dan Pic</b>"
+
+#: src/speed-pitch/speed-pitch.cc:211
+msgid "Speed:"
+msgstr "Kelajuan:"
+
+#: src/speed-pitch/speed-pitch.cc:214
+msgid "Pitch:"
+msgstr "Pic:"
+
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ikon Status"
+
+#: src/statusicon/statusicon.cc:283
+msgid "Se_ttings ..."
+msgstr "_Tetapan ..."
+
+#: src/statusicon/statusicon.cc:372
+msgid ""
+"Status Icon Plugin\n"
+"\n"
+"Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Copyright 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"This plugin provides a status icon, placed in\n"
+"the system tray area of the window manager."
+msgstr ""
+"Pemalam Ikon Status\n"
+"\n"
+"Hakcipta 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Hakcipta 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"Pemalam ini menyediakan ikon status, terletak di\n"
+"dalam kawasan talam sistem pengurus tetingkap."
+
+#: src/statusicon/statusicon.cc:379
+msgid "<b>Mouse Scroll Action</b>"
+msgstr "<b>Tindakan Tatal Tetikus</b>"
+
+#: src/statusicon/statusicon.cc:380
+msgid "Change volume"
+msgstr "Ubah volum"
+
+#: src/statusicon/statusicon.cc:383
+msgid "Change playing song"
+msgstr "Ubah lagu dimainkan"
+
+#: src/statusicon/statusicon.cc:386
+msgid "<b>Other Settings</b>"
+msgstr "<b>Tetapan Lain</b>"
+
+#: src/statusicon/statusicon.cc:387
+msgid "Disable the popup window"
+msgstr "Lumpuhkan tetingkap timbul"
+
+#: src/statusicon/statusicon.cc:389
+msgid "Close to the system tray"
+msgstr "Tutup talam sistem"
+
+#: src/statusicon/statusicon.cc:391
+msgid "Advance in playlist when scrolling upward"
+msgstr "Dahulukan dalam senarai main bila menatal ke atas"
+
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Stereo Ekstra"
+
+#: src/stereo_plugin/stereo.cc:36
+msgid ""
+"Extra Stereo Plugin\n"
+"\n"
+"By Johan Levin, 1999"
+msgstr ""
+"Pemalam Stereo Extra\n"
+"\n"
+"Oleh Johan Levin, 1999"
+
+#: src/stereo_plugin/stereo.cc:44
+msgid "<b>Extra Stereo</b>"
+msgstr "<b>Stereo Ekstra</b>"
+
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Penjana Nada"
+
+#: src/tonegen/tonegen.cc:94
+#, c-format
+msgid "%s %.1f Hz"
+msgstr "%s %.1f Hz"
+
+#: src/tonegen/tonegen.cc:94
+msgid "Tone Generator: "
+msgstr "Penjana Nada:"
+
+#: src/tonegen/tonegen.cc:160
+msgid ""
+"Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
+"Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
+"e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
+msgstr ""
+"Penjana nada sin oleh Håvard Kvålen <havardk at xmms.org>\n"
+"Diubahsuai oleh Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"Untuk guna ia, tambah URL: tone://frequency1;frequency2;frequency3;...\n"
+"cth. tone://2000;2005 untuk mainkan nada 2000 Hz dan nada 2005 Hz"
+
+#: src/voice_removal/voice_removal.cc:28
+msgid "Voice Removal"
+msgstr "Pembuangan Suara"
+
+#: src/vorbis/vorbis.cc:465
+msgid ""
+"Audacious Ogg Vorbis Decoder\n"
+"\n"
+"Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Original code by:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Contributions from:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
+msgstr ""
+"Penyahkod Ogg Vorbis Audacious\n"
+"\n"
+"Berdasarkan pada Pemalam Ogg Vorbis Xiph.org Foundation:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Kod asal oleh:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Penyumbang:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
+
+#: src/vorbis/vorbis.h:18
+msgid "Ogg Vorbis Decoder"
+msgstr "Penyahkod Ogg Vorbis"
+
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Perincian mengenai %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Tajuk: %t\n"
+"Pengarang: %a\n"
+"Daripada: %f\n"
+"Penjejak: %T\n"
+"Ulasan: %C\n"
+"Jenis cip: %c\n"
+"Stereo: %s\n"
+"Gelung: %l\n"
+"Frek. cip: %F\n"
+"Frek. pemain: %P\n"
+"Tahun: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Penyahkod VTX"
+
+#: src/vtx/vtx.cc:184
+msgid ""
+"Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
+"Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
+"Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
+msgstr ""
+"Pemain format fail Vortex oleh Sashnov Alexander <sashnov at ngs.ru>\n"
+"Berdasarkan pada in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
+"Pemalam Audacious oleh Pavel Vymetalek <pvymetalek at seznam.cz>"
+
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Penyahkod WavPack"
+
+#: src/wavpack/wavpack.cc:211
+msgid "lossy (hybrid)"
+msgstr "hilang (hidbrid)"
+
+#: src/wavpack/wavpack.cc:213
+msgid "lossy"
+msgstr "hilang"
+
+#: src/wavpack/wavpack.cc:255
+msgid ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Some of the plugin code was by Miles Egan."
+msgstr ""
+"Hakcipta 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Sebahagian kod pemalam oleh Miles Egan."
+
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
+msgstr "Penyahkod 2SF"
+
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Konfigurasi XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Abai panjang dari fail"
+
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "Senarai Main Boleh Kongsi XML (XSPF)"
diff --git a/po/nl.po b/po/nl.po
new file mode 100644
index 000000000000..dff9fa0d01ac
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,4078 @@
+# Dutch translation for Audacious Plugins
+# Copyright (C) Audacious translators
+# This file is distributed under the same license as the Audacious Plugins package.
+#
+# Translators:
+# Bjorn Roesbeke <inbox at bjornroesbeke.be>, 2013
+# Dennis Klomp <c_klomp at epu-forum.net>, 2012
+# dragnadh <dragnadh at gmail.com>, 2015
+# Farioko <fabianbakkum at hotmail.com>, 2014
+# Freek1A <fjvluijt at hotmail.com>, 2012
+# shured <shured1 at gmail.com>, 2014
+msgid ""
+msgstr ""
+"Project-Id-Version: Audacious Plugins\n"
+"Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-17 17:53+0000\n"
+"Last-Translator: dragnadh <dragnadh at gmail.com>\n"
+"Language-Team: Dutch (http://www.transifex.com/projects/p/audacious/language/"
+"nl/)\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
+msgstr "AAC (Raw) Decoder"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Player)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr "gesequentieerd"
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
+
+#: src/alarm/alarm.cc:782
+msgid "Set Alarm ..."
+msgstr "Alarm instellen ..."
+
+#: src/alarm/alarm.cc:810
+msgid ""
+"A plugin that can be used to start playing at a certain time.\n"
+"\n"
+"Originally written by Adam Feakin and Daniel Stodden."
+msgstr ""
+"Een invoegtoepassing die gebruikt kan worden om het afspelen te starten op "
+"een bepaald tijdstip.\n"
+"\n"
+"Origineel geschreven door Adam Feakin en Daniel Stodden."
+
+#: src/alarm/interface.cc:28
+msgid ""
+"Time\n"
+"  Alarm at:\n"
+"    The time for the alarm to come on.\n"
+"\n"
+"  Quiet after:\n"
+"    Stop alarm after this amount of time.\n"
+"       (if the wakeup dialog is not closed)\n"
+"\n"
+"\n"
+"Days\n"
+"  Day:\n"
+"    Select the days for the alarm to activate.\n"
+"\n"
+"  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"
+msgstr ""
+"Tijd\n"
+"Alarm op:\n"
+"De tijd voor het alarm start.\n"
+"\n"
+"Stil na:\n"
+"Stop alarm na zolang.\n"
+"(als het opsta venster nog gesloten is)\n"
+"\n"
+"\n"
+"Dagen\n"
+"Dag:\n"
+"Selecteer de dagen voor wanneer het \n"
+"alarm actief moet zijn.\n"
+"\n"
+"Tijd:\n"
+"Kies de tijd voor het alarm elke dag,\n"
+"of klik op de pin knop om de standaardwaarde\n"
+"te gebruiken.\n"
+"\n"
+"\n"
+
+#: src/alarm/interface.cc:45
+msgid ""
+"Volume\n"
+"  Fading:\n"
+"    Fade the volume up to the chosen volume\n"
+"    for this amount of time.\n"
+"\n"
+"  Start at:\n"
+"    Start fading from this volume.\n"
+"\n"
+"  Final:\n"
+"    The volume to stop fading at.  If the fading\n"
+"    time is 0 then set volume to this and start\n"
+"    playing.\n"
+"\n"
+"\n"
+"Options:\n"
+"  Additional Command:\n"
+"    Run this command at the alarm time.\n"
+"\n"
+msgstr ""
+"Volume\n"
+"Vervaging:\n"
+"Vervaag het volume op het gekozen tijdstip.\n"
+"\n"
+"Start op:\n"
+"Start vervaging vanaf dit volume.\n"
+"\n"
+"Uiteindelijk:\n"
+"Stop met het vervagen wanneer,\n"
+"de tijd op 0 staat en start met afspelen.\n"
+"\n"
+"\n"
+"Opties:\n"
+"Overige commando's:\n"
+"Voer dit commando uit wanneer het\n"
+"alarm wordt geactiveerd.\n"
+
+#: src/alarm/interface.cc:62
+msgid ""
+"  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"
+"    can also be entered here.\n"
+"\n"
+"  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."
+msgstr ""
+"Afspeellijst:\n"
+"Laad deze afspeellijst. Als er\n"
+"geen afspeellijst gespecificeerd\n"
+"is, zal de huidige worden gebruikt.\n"
+"De URL van een mp3/ogg stream\n"
+"kan hier ook ingevoerd worden.\n"
+"\n"
+"Herinnering:\n"
+"Laat een herinnering zien wanneer het alarm afgaat.\n"
+"Schrijf een herinnering in dit vakje en activeer de\n"
+"pin knop als je het wilt laten weergeven."
+
+#: src/alarm/interface.cc:81
+msgid "This is your wakeup call."
+msgstr "Dit is uw opstaan melding"
+
+#: src/alarm/interface.cc:99
+msgid "Your reminder for today is..."
+msgstr "Uw herinnering voor vandaag is..."
+
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
+msgid "Reminder"
+msgstr "Herinnering"
+
+#: src/alarm/interface.cc:132
+msgid "Monday"
+msgstr "Maandag"
+
+#: src/alarm/interface.cc:132
+msgid "Tuesday"
+msgstr "Dinsdag"
+
+#: src/alarm/interface.cc:132
+msgid "Wednesday"
+msgstr "Woensdag"
+
+#: src/alarm/interface.cc:133
+msgid "Thursday"
+msgstr "Donderdag"
+
+#: src/alarm/interface.cc:133
+msgid "Friday"
+msgstr "Vrijdag"
+
+#: src/alarm/interface.cc:133
+msgid "Saturday"
+msgstr "Zaterdag"
+
+#: src/alarm/interface.cc:133
+msgid "Sunday"
+msgstr "Zondag"
+
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
+msgid "Time"
+msgstr "Tijd"
+
+#: src/alarm/interface.cc:178
+msgid "Alarm at (default):"
+msgstr "Alarm (op standaard)"
+
+#: src/alarm/interface.cc:200
+msgid "h"
+msgstr "h"
+
+#: src/alarm/interface.cc:203
+msgid "Quiet after:"
+msgstr "Stil na:"
+
+#: src/alarm/interface.cc:215
+msgid "hours"
+msgstr "uren"
+
+#: src/alarm/interface.cc:226
+msgid "minutes"
+msgstr "minuten"
+
+#: src/alarm/interface.cc:235
+msgid "Choose the days for the alarm to come on"
+msgstr "Kies de dag voor het alarm om aan te gaan"
+
+#: src/alarm/interface.cc:242
+msgid "Day"
+msgstr "Dag"
+
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
+msgid "Default"
+msgstr "Standaard"
+
+#: src/alarm/interface.cc:288
+msgid "Days"
+msgstr "Dagen"
+
+#: src/alarm/interface.cc:297
+msgid "Fading"
+msgstr "Vervagen"
+
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
+msgid "seconds"
+msgstr "Seconden"
+
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
+msgid "Volume"
+msgstr "Volume"
+
+#: src/alarm/interface.cc:317
+msgid "Start at"
+msgstr "Start bij"
+
+#: src/alarm/interface.cc:333
+msgid "Final"
+msgstr "Laatste"
+
+#: src/alarm/interface.cc:346
+msgid "Current"
+msgstr "Huidige"
+
+#: src/alarm/interface.cc:359
+msgid "Additional Command"
+msgstr "Extra Opdracht"
+
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
+msgid "enable"
+msgstr "Aan"
+
+#: src/alarm/interface.cc:372
+msgid "Playlist (optional)"
+msgstr "Afspeellijst (Hoeft niet)"
+
+#: src/alarm/interface.cc:379
+msgid "Select a playlist"
+msgstr "Selecteer een afspeellijst"
+
+#: src/alarm/interface.cc:399
+msgid "Options"
+msgstr "Opties"
+
+#: src/alarm/interface.cc:404
+msgid "What do these options mean?"
+msgstr "Wat betekenen deze opties"
+
+#: src/alarm/interface.cc:420
+msgid "Help"
+msgstr "Help"
+
+#: src/albumart/albumart.cc:31
+msgid "Album Art"
+msgstr "Albumhoes"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Albumhoes (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA Uitvoer"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Uitvoer Invoegtoepassing voor Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Met dank aan William Pitcock, schrijver van de ALSA Uitvoer Plugin NG,\n"
+"van wie zijn code werd gebruikt als handleiding wanneer de ALSA handleiding "
+"niet genoeg was."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(geen beschrijving)"
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr "Standaard PCM apparaat"
+
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr "Standaard mixer apparaat"
+
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr "PCM apparaat:"
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr "Mixer apparaat:"
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr "Mixer element:"
+
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI Speler)"
+
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:94
+msgid "Override default gain:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:102
+msgid "Override default polyphony:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:110
+msgid "Override default reverb:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
+msgid "On"
+msgstr "Aan"
+
+#: src/amidi-plug/i_configure.cc:118
+msgid "Override default chorus:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
+msgid "<b>Playback</b>"
+msgstr "<b>Afspelen</b>"
+
+#: src/amidi-plug/i_configure.cc:129
+msgid "Transpose:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "Noteer nummers"
+
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:141
+msgid "<b>SoundFont</b>"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:143
+msgid "<b>Synthesizer</b>"
+msgstr "<b>Synthesizer</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Sample rate:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
+msgid "AMIDI-Plug - select SoundFont file"
+msgstr "AMIDI-Plug - SoundFont bestand selecteren"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Sluiten"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
+msgid "_Open"
+msgstr "_Open"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Bestandsnaam"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
+msgid "Size (bytes)"
+msgstr "Groote (bytes)"
+
+#: src/amidi-plug/i_fileinfo.cc:163
+msgid "Name:"
+msgstr "Naam:"
+
+#: src/amidi-plug/i_fileinfo.cc:181
+msgid "<span size=\"smaller\"> MIDI Info </span>"
+msgstr "<span size=\"smaller\"> MIDI Info <span>"
+
+#: src/amidi-plug/i_fileinfo.cc:195
+msgid "Format:"
+msgstr "A"
+
+#: src/amidi-plug/i_fileinfo.cc:198
+msgid "Length (msec):"
+msgstr "Lengte (msec):"
+
+#: src/amidi-plug/i_fileinfo.cc:201
+msgid "No. of Tracks:"
+msgstr "Aantal Tracks:"
+
+#: src/amidi-plug/i_fileinfo.cc:207
+msgid "variable"
+msgstr "variabel"
+
+#: src/amidi-plug/i_fileinfo.cc:209
+msgid "BPM:"
+msgstr "BPM:"
+
+#: src/amidi-plug/i_fileinfo.cc:217
+msgid "BPM (wavg):"
+msgstr "BPM (wavg):"
+
+#: src/amidi-plug/i_fileinfo.cc:220
+msgid "Time Div:"
+msgstr "Time Div:"
+
+#: src/amidi-plug/i_fileinfo.cc:231
+msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
+msgstr "<span size=\"smaller\"> MIDI Commentaar en songtekst </span>"
+
+#: src/amidi-plug/i_fileinfo.cc:278
+msgid "* no comments available in this MIDI file *"
+msgstr "* geen commentaar beschikbaar in dit MIDI bestand *"
+
+#: src/amidi-plug/i_fileinfo.cc:290
+msgid "* no lyrics available in this MIDI file *"
+msgstr "* geen songtekst beschikbaar in dit MIDI bestand *"
+
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
+msgid "_Close"
+msgstr "_Sluit"
+
+#: src/amidi-plug/i_fileinfo.cc:325
+msgid "  (invalid UTF-8)"
+msgstr "  (onjuist UTF-8)"
+
+#: src/aosd/aosd.cc:32
+msgid ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Written by Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Based in part on Evan Martin's Ghosd library:\n"
+"http://neugierig.org/software/ghosd/"
+msgstr ""
+
+#: src/aosd/aosd.h:37
+msgid "AOSD (On-Screen Display)"
+msgstr "AOSD (On-Screen Display)"
+
+#: src/aosd/aosd_style.cc:54
+msgid "Rectangle"
+msgstr "Vierkant"
+
+#: src/aosd/aosd_style.cc:59
+msgid "Rounded Rectangle"
+msgstr "Vierkant met afgeronde hoeken"
+
+#: src/aosd/aosd_style.cc:64
+msgid "Concave Rectangle"
+msgstr "Concave vierkant"
+
+#: src/aosd/aosd_style.cc:69
+msgid "None"
+msgstr "Geen"
+
+#: src/aosd/aosd_trigger.cc:50
+msgid "Playback Start"
+msgstr "Start Afspelen"
+
+#: src/aosd/aosd_trigger.cc:51
+msgid "Triggers OSD when a playlist entry is played."
+msgstr "OSD starten wanneer een afspeellijst regel word afgespeeld."
+
+#: src/aosd/aosd_trigger.cc:56
+msgid "Title Change"
+msgstr "Titel verandering"
+
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr ""
+"OSD wordt geactiveerd wanneer een liedtitel verandert (voor internet "
+"streams)."
+
+#: src/aosd/aosd_trigger.cc:62
+msgid "Pause On"
+msgstr "Pause Aan"
+
+#: src/aosd/aosd_trigger.cc:63
+msgid "Triggers OSD when playback is paused."
+msgstr "OSD wordt geactiveerd wanneer afspelen wordt gepauzeerd."
+
+#: src/aosd/aosd_trigger.cc:68
+msgid "Pause Off"
+msgstr "Pause Uit"
+
+#: src/aosd/aosd_trigger.cc:69
+msgid "Triggers OSD when playback is unpaused."
+msgstr "OSD wordt geactiveerd wanneer afspelen wordt hervat."
+
+#: src/aosd/aosd_ui.cc:163
+msgid "Placement"
+msgstr "Plaatsing"
+
+#: src/aosd/aosd_ui.cc:196
+msgid "Relative X offset:"
+msgstr "Relatieve X verplaatsing:"
+
+#: src/aosd/aosd_ui.cc:203
+msgid "Relative Y offset:"
+msgstr "Relatieve Y verplaatsing:"
+
+#: src/aosd/aosd_ui.cc:210
+msgid "Max OSD width:"
+msgstr "Max OSD breedte:"
+
+#: src/aosd/aosd_ui.cc:221
+msgid "Multi-Monitor options"
+msgstr "Multi-Monitor opties"
+
+#: src/aosd/aosd_ui.cc:225
+msgid "Display OSD using:"
+msgstr "Toon OSD op:"
+
+#: src/aosd/aosd_ui.cc:227
+msgid "all monitors"
+msgstr "alle monitors"
+
+#: src/aosd/aosd_ui.cc:230
+#, c-format
+msgid "monitor %i"
+msgstr "monitor %i"
+
+#: src/aosd/aosd_ui.cc:282
+msgid "Timing (ms)"
+msgstr "Timing (ms)"
+
+#: src/aosd/aosd_ui.cc:287
+msgid "Display:"
+msgstr "Weergeven:"
+
+#: src/aosd/aosd_ui.cc:292
+msgid "Fade in:"
+msgstr "Fade in:"
+
+#: src/aosd/aosd_ui.cc:297
+msgid "Fade out:"
+msgstr "Fade uit:"
+
+#: src/aosd/aosd_ui.cc:361
+msgid "Fonts"
+msgstr "Lettertypen"
+
+#: src/aosd/aosd_ui.cc:368
+#, c-format
+msgid "Font %i:"
+msgstr "Lettertype %i:"
+
+#: src/aosd/aosd_ui.cc:382
+msgid "Shadow"
+msgstr "Schaduw"
+
+#: src/aosd/aosd_ui.cc:486
+msgid "Render Style"
+msgstr "Weergavestijl"
+
+#: src/aosd/aosd_ui.cc:502
+msgid "Colors"
+msgstr "Kleuren"
+
+#: src/aosd/aosd_ui.cc:513
+#, c-format
+msgid "Color %i:"
+msgstr "Kleur %i:"
+
+#: src/aosd/aosd_ui.cc:600
+msgid "Enable trigger"
+msgstr "Trekker inschakelen"
+
+#: src/aosd/aosd_ui.cc:627
+msgid "Event"
+msgstr "Gebeurtenis"
+
+#: src/aosd/aosd_ui.cc:655
+msgid "Composite manager detected"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:662
+msgid ""
+"Composite manager not detected;\n"
+"unless you know that you have one running, please activate a composite "
+"manager otherwise the OSD won't work properly"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:670
+msgid "Composite manager not required for fake transparency"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:706
+msgid "Transparency"
+msgstr "Doorzichtigheid"
+
+#: src/aosd/aosd_ui.cc:712
+msgid "Fake transparency"
+msgstr "Valse doorzichtigheid"
+
+#: src/aosd/aosd_ui.cc:714
+msgid "Real transparency (requires X Composite Ext.)"
+msgstr "Echte doorzichtigheid (vereist X Composiet uitbreiding)"
+
+#: src/aosd/aosd_ui.cc:756
+msgid "Composite extension not loaded"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:764
+msgid "Composite extension not available"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:781
+#, c-format
+msgid "<span font_desc='%s'>Audacious OSD</span>"
+msgstr "<span font_desc='%s'>Audacious OSD</span>"
+
+#: src/aosd/aosd_ui.cc:844
+msgid "Position"
+msgstr "Positie"
+
+#: src/aosd/aosd_ui.cc:849
+msgid "Animation"
+msgstr "Animatie"
+
+#: src/aosd/aosd_ui.cc:854
+msgid "Text"
+msgstr "Tekst"
+
+#: src/aosd/aosd_ui.cc:859
+msgid "Decoration"
+msgstr "Decoratie"
+
+#: src/aosd/aosd_ui.cc:864
+msgid "Trigger"
+msgstr "Trekker"
+
+#: src/aosd/aosd_ui.cc:869
+msgid "Misc"
+msgstr "Divers"
+
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Test"
+
+#: src/asx3/asx3.cc:35
+msgid "ASXv3 Playlists"
+msgstr "ASXv3 Afspeellijsten"
+
+#: src/asx/asx.cc:33
+msgid "ASXv1/ASXv2 Playlists"
+msgstr "ASXv1/ASXv2 Afspeellijsten"
+
+#: src/audpl/audpl.cc:33
+msgid "Audacious Playlists (audpl)"
+msgstr "Audacious Afspeellijsten (audpl)"
+
+#: src/blur_scope/blur_scope.cc:42
+msgid "<b>Color</b>"
+msgstr "<b>Kleur</b>"
+
+#: src/blur_scope/blur_scope.cc:58
+msgid "Blur Scope"
+msgstr ""
+
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr ""
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Presets:"
+
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr ""
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr "Knip frequentie:"
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
+msgid "Spectrum Analyzer"
+msgstr "Spectrum Analyseerder"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD Plugin"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
+msgid ""
+"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
+"\n"
+"Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/>\n"
+"and to libcddb developers <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Also thank you to Tony Vroon for mentoring and guiding me.\n"
+"\n"
+"This was a Google Summer of Code 2007 project."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:137
+msgid "<b>Device</b>"
+msgstr "<b>Apparaat</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:138
+msgid "Read speed:"
+msgstr "Lees snelheid:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:141
+msgid "Override device:"
+msgstr "Override apparaat:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:143
+msgid "<b>Metadata</b>"
+msgstr "<b>Metadata</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:144
+msgid "Use CD-Text"
+msgstr "Gebruik CD-Tekst"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:146
+msgid "Use CDDB"
+msgstr "Gebruik CDDB"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:148
+msgid "Use HTTP instead of CDDBP"
+msgstr "Gebruik HTTP in plaats van CDDBP"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:151
+msgid "Server:"
+msgstr "Server:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:155
+msgid "Path:"
+msgstr "Pad:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:159
+msgid "Port:"
+msgstr "Poort:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:246
+msgid "Failed to initialize cdio subsystem."
+msgstr "Fout bij initialiseren cdio subsysteem."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:281
+#, c-format
+msgid "Invalid URI %s."
+msgstr "Ongeldige URI %s"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:283
+#, c-format
+msgid "Track %d not found."
+msgstr "Track %d niet gevonden."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:285
+#, c-format
+msgid "Track %d is a data track."
+msgstr "Track %d is alleen data."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:360
+msgid "Error reading audio CD."
+msgstr "Fout bij lezen audio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:429
+msgid "Audio CD"
+msgstr "Audio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
+#, c-format
+msgid "Failed to open CD device %s."
+msgstr "Het openen van CD apparaat %s is mislukt."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:472
+msgid "No audio capable CD drive found."
+msgstr "Geen CD speler met audio mogelijkheid gevonden."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:497
+msgid "Failed to finish initializing opened CD drive."
+msgstr "Het  Initialiseren van de geopende CD Drive is mislukt."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:510
+msgid "Failed to retrieve first/last track number."
+msgstr "Het herstellen van de eerste/laatste tracknummer is mislukt."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:531
+#, c-format
+msgid "Cannot read start/end LSN for track %d."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:613
+msgid "Failed to create the cddb connection."
+msgstr "Fout bij verbinden met de cddb"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:679
+msgid "Failed to query the CDDB server"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:681
+#, c-format
+msgid "Failed to query the CDDB server: %s"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:705
+#, c-format
+msgid "Failed to read the cddb info: %s"
+msgstr "Fout bij lezen van cddb info: %s"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:765
+msgid "Drive is empty."
+msgstr "Schijfstation is leeg."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:767
+msgid "Unsupported disk type."
+msgstr "Niet-ondersteund schijftype."
+
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Audio CD Menu Items"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Play CD"
+msgstr "CD afspelen"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Add CD"
+msgstr "CD toevoegen"
+
+#: src/compressor/compressor.cc:45
+msgid "<b>Compression</b>"
+msgstr "<b>Compressie</b>"
+
+#: src/compressor/compressor.cc:46
+msgid "Center volume:"
+msgstr "Centrum volume:"
+
+#: src/compressor/compressor.cc:49
+msgid "Dynamic range:"
+msgstr "Dynamisch bereik:"
+
+#: src/compressor/compressor.cc:57
+msgid ""
+"Dynamic Range Compression Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+
+#: src/compressor/compressor.cc:64
+msgid "Dynamic Range Compressor"
+msgstr ""
+
+#: src/console/plugin.cc:15
+msgid ""
+"Console music decoder engine based on Game_Music_Emu 0.5.2\n"
+"Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at dereferenced.org>\n"
+"Shay Green <gblargg at gmail.com>"
+msgstr ""
+
+#: src/console/plugin.cc:30
+msgid "Bass:"
+msgstr "Bas:"
+
+#: src/console/plugin.cc:33
+msgid "Treble:"
+msgstr "Treble:"
+
+#: src/console/plugin.cc:36
+msgid "Echo:"
+msgstr "Echo:"
+
+#: src/console/plugin.cc:39
+msgid "Default song length:"
+msgstr "Standaard lied lengte:"
+
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
+msgid "<b>Resampling</b>"
+msgstr ""
+
+#: src/console/plugin.cc:43
+msgid "Enable audio resampling"
+msgstr ""
+
+#: src/console/plugin.cc:49
+msgid "<b>SPC</b>"
+msgstr "<b>SPC</b>"
+
+#: src/console/plugin.cc:50
+msgid "Ignore length from SPC tags"
+msgstr "Negeer lengte van SPC tags"
+
+#: src/console/plugin.cc:52
+msgid "Increase reverb"
+msgstr ""
+
+#: src/console/plugin.h:26
+msgid "Game Console Music Decoder"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:131
+msgid ""
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
+msgid ""
+"Crossfade Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:48
+msgid "<b>Crossfade</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
+msgid "Overlap:"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Tip</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
+msgid "Crossfade"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
+msgid "<b>Crystalizer</b>"
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
+msgid "Intensity:"
+msgstr "Intensiteit:"
+
+#: src/crystalizer/crystalizer.cc:43
+msgid "Crystalizer"
+msgstr ""
+
+#: src/cue/cue.cc:37
+msgid "Cue Sheet Plugin"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Verwijder Bestanden"
+
+#: src/delete-files/delete-files.cc:75
+#, c-format
+msgid "Error moving %s to trash: %s."
+msgstr "Fout bij verplaatsen %s naar de prullenbak: %s."
+
+#: src/delete-files/delete-files.cc:86
+#, c-format
+msgid "Error deleting %s: %s."
+msgstr "Fout bij verwijderen %s: %s."
+
+#: src/delete-files/delete-files.cc:117
+#, c-format
+msgid "Error deleting %s: not a local file."
+msgstr "Fout bij verwijderen %s: is geen lokaal bestand."
+
+#: src/delete-files/delete-files.cc:134
+msgid "Do you want to move the selected files to the trash?"
+msgstr "Wilt u de geselecteerde bestanden verplaatsen naar de prullenbak?"
+
+#: src/delete-files/delete-files.cc:135
+msgid "Move to Trash"
+msgstr "Verplaats naar Prullenbak"
+
+#: src/delete-files/delete-files.cc:140
+msgid "Do you want to permanently delete the selected files?"
+msgstr "Wilt u de geselecteerde bestanden definitief verwijderen?"
+
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
+msgid "Delete"
+msgstr "Verwijder"
+
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
+msgid "Cancel"
+msgstr "Annuleren"
+
+#: src/delete-files/delete-files.cc:166
+msgid "Delete Selected Files"
+msgstr "Verwijder Geselcteerde Bestanden"
+
+#: src/delete-files/delete-files.cc:181
+msgid "<b>Delete Method</b>"
+msgstr "<b>Verwijder Methode</b>"
+
+#: src/delete-files/delete-files.cc:182
+msgid "Move to trash instead of deleting immediately"
+msgstr "Verplaats naar de prullenbak ipv onmiddellijk verwijderen"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
+msgid "<b>Echo</b>"
+msgstr "<b>Echo</b>"
+
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "Delay:"
+msgstr "Vertraging:"
+
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "ms"
+msgstr "ms"
+
+#: src/echo_plugin/echo.cc:25
+msgid "Feedback:"
+msgstr "Terugkoppeling:"
+
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
+msgid "Volume:"
+msgstr "Volume:"
+
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
+msgstr "Echo"
+
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg Plugin"
+
+#: src/ffaudio/ffaudio-core.cc:571
+msgid ""
+"Multi-format audio decoding plugin for Audacious using\n"
+"FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter Plugin"
+
+#: src/filewriter/filewriter.cc:386
+msgid "Output file format:"
+msgstr "Uitvoer bestandsformaat:"
+
+#: src/filewriter/filewriter.cc:403
+msgid "Configure"
+msgstr "Configureer"
+
+#: src/filewriter/filewriter.cc:413
+msgid "Save into original directory"
+msgstr "Opslaan in oorspronkelijke map"
+
+#: src/filewriter/filewriter.cc:417
+msgid "Save into custom directory"
+msgstr "Opslaan in aangepaste map"
+
+#: src/filewriter/filewriter.cc:427
+msgid "Output file folder:"
+msgstr "Bestandsuitvoer map:"
+
+#: src/filewriter/filewriter.cc:431
+msgid "Pick a folder"
+msgstr "Kies een map"
+
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Oorspronkelijke bestandslabel"
+
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Oorspronkelijke bestandsnaam"
+
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Omvat originele bestandsnaam extensie"
+
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:484
+msgid ""
+"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."
+msgstr ""
+
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
+msgid "Auto"
+msgstr "Auto"
+
+#: src/filewriter/mp3.cc:40
+msgid "Joint Stereo"
+msgstr "Samengevoegd stereo"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
+msgid "Stereo"
+msgstr "Stereo"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
+msgid "Mono"
+msgstr "Mono"
+
+#: src/filewriter/mp3.cc:657
+msgid "MP3 Configuration"
+msgstr "MP3 Configuratie"
+
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Ok"
+
+#: src/filewriter/mp3.cc:681
+msgid "Algorithm Quality:"
+msgstr "Algoritme kwaliteit:"
+
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Sample Rate Uitvoer:"
+
+#: src/filewriter/mp3.cc:733
+msgid "(Hz)"
+msgstr "(Hz)"
+
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Bitrate / Compressie Ratio:"
+
+#: src/filewriter/mp3.cc:764
+msgid "Bitrate (kbps):"
+msgstr "Bitrate (kbps):"
+
+#: src/filewriter/mp3.cc:796
+msgid "Compression ratio:"
+msgstr "Compressie ratio:"
+
+#: src/filewriter/mp3.cc:820
+msgid "Audio Mode:"
+msgstr "Audio Modus:"
+
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Diversen:"
+
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
+
+#: src/filewriter/mp3.cc:867
+msgid "Error protection"
+msgstr "Foutbescherming"
+
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
+msgid "Quality"
+msgstr "Kwaliteit"
+
+#: src/filewriter/mp3.cc:888
+msgid "Enable VBR/ABR"
+msgstr "VBR/ABR inschakelen"
+
+#: src/filewriter/mp3.cc:898
+msgid "Type:"
+msgstr "Type:"
+
+#: src/filewriter/mp3.cc:931
+msgid "VBR Options:"
+msgstr "VBR Opties:"
+
+#: src/filewriter/mp3.cc:947
+msgid "Minimum bitrate (kbps):"
+msgstr "Minimale bitrate (kbps):"
+
+#: src/filewriter/mp3.cc:973
+msgid "Maximum bitrate (kbps):"
+msgstr "Maximale bitrate (kbps):"
+
+#: src/filewriter/mp3.cc:995
+msgid "Strictly enforce minimum bitrate"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1007
+msgid "ABR Options:"
+msgstr "ABR Opties:"
+
+#: src/filewriter/mp3.cc:1017
+msgid "Average bitrate (kbps):"
+msgstr "Gemiddelde bitrate (kbps):"
+
+#: src/filewriter/mp3.cc:1044
+msgid "VBR quality level:"
+msgstr "VBR kwaliteitsniveau:"
+
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1076
+msgid "VBR/ABR"
+msgstr "VBR/ABR"
+
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1097
+msgid "Mark as copyright"
+msgstr "Markeer als auteursrecht"
+
+#: src/filewriter/mp3.cc:1108
+msgid "Mark as original"
+msgstr "Markeer als origineel"
+
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr "ID3 Parameters:"
+
+#: src/filewriter/mp3.cc:1131
+msgid "Force addition of version 2 tag"
+msgstr "Forceer het toevoegen van een versie 2 tag"
+
+#: src/filewriter/mp3.cc:1141
+msgid "Only add v1 tag"
+msgstr "Alleen v1 tag toevoegen"
+
+#: src/filewriter/mp3.cc:1148
+msgid "Only add v2 tag"
+msgstr "Alleen v2 tag toevoegen"
+
+#: src/filewriter/mp3.cc:1169
+msgid "Tags"
+msgstr "Tags"
+
+#: src/filewriter/vorbis.cc:196
+msgid "Vorbis Encoder Configuration"
+msgstr "Vorbis Encoder Configuratie"
+
+#: src/filewriter/vorbis.cc:219
+msgid "Quality level (0 - 10):"
+msgstr "Kwaliteitsniveau (0 - 10):"
+
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC Decoder"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
+msgid "lossless"
+msgstr "lossless"
+
+#: src/flacng/plugin.cc:169
+msgid ""
+"Original code by\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
+msgstr ""
+"Originele code door\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
+
+#: src/gio/gio.cc:34
+msgid ""
+"GIO Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren"
+msgstr ""
+"GIO Plugin voor Audicious\n"
+"Copyright 2009-2012 John Lindgren"
+
+#: src/gio/gio.cc:42
+msgid "GIO Plugin"
+msgstr "GIO Plugin"
+
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:62
+msgid "OpenGL Spectrum Analyzer"
+msgstr "OpenGL Spectrum Analyseerder"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME Snelkoppeling"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
+msgid "Entry number"
+msgstr "Invoer nummer"
+
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
+msgid "Title"
+msgstr "Titel"
+
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
+msgid "Artist"
+msgstr "Artiest"
+
+#: src/gtkui/columns.cc:38
+msgid "Year"
+msgstr "Jaar"
+
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
+msgid "Album"
+msgstr "Album"
+
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Album Artiest"
+
+#: src/gtkui/columns.cc:41
+msgid "Track"
+msgstr "Nummer"
+
+#: src/gtkui/columns.cc:42
+msgid "Genre"
+msgstr "Genre"
+
+#: src/gtkui/columns.cc:43
+msgid "Queue position"
+msgstr "Positie in wachtrij"
+
+#: src/gtkui/columns.cc:44
+msgid "Length"
+msgstr "Lengte"
+
+#: src/gtkui/columns.cc:45
+msgid "File path"
+msgstr "Bestandspad"
+
+#: src/gtkui/columns.cc:47
+msgid "Custom title"
+msgstr "Aangepaste titel"
+
+#: src/gtkui/columns.cc:48
+msgid "Bitrate"
+msgstr "Bitrate"
+
+#: src/gtkui/columns.cc:308
+msgid "Available columns"
+msgstr "Beschikbare kolommen"
+
+#: src/gtkui/columns.cc:334
+msgid "Displayed columns"
+msgstr "Weergegeven kolommen"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Zoek hulpmiddel"
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Left"
+msgstr "Vastkoppelen aan linkerzijde"
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Right"
+msgstr "Vastkoppelen aan rechterzijde"
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Top"
+msgstr "Vastkoppelen aan bovenkant"
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Bottom"
+msgstr "Vastkoppelen aan onderkant"
+
+#: src/gtkui/layout.cc:168
+msgid "Undock"
+msgstr "Loskoppelen"
+
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
+msgid "Disable"
+msgstr "Uitschakelen"
+
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
+msgid "_Open Files ..."
+msgstr "_Open bestanden ..."
+
+#: src/gtkui/menus.cc:127
+msgid "Open _URL ..."
+msgstr "Open _URL ..."
+
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
+msgid "_Add Files ..."
+msgstr "_Bestanden Toevoegen ..."
+
+#: src/gtkui/menus.cc:129
+msgid "Add U_RL ..."
+msgstr "U_RL toevoegen ..."
+
+#: src/gtkui/menus.cc:131
+msgid "Search _Library"
+msgstr "Doorzoek_Bibliotheek"
+
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
+msgid "A_bout ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
+msgid "_Settings ..."
+msgstr "In_stellingen ..."
+
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
+msgid "_Quit"
+msgstr "_Afsluiten"
+
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
+msgid "_Play"
+msgstr ""
+
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
+msgid "Paus_e"
+msgstr ""
+
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
+msgid "_Stop"
+msgstr "_Stop"
+
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
+msgid "Pre_vious"
+msgstr "Vo_rige"
+
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
+msgid "_Next"
+msgstr "_Volgende"
+
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
+msgid "_Repeat"
+msgstr "_Herhaal"
+
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
+msgid "S_huffle"
+msgstr ""
+
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
+msgid "N_o Playlist Advance"
+msgstr ""
+
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
+msgid "Stop A_fter This Song"
+msgstr ""
+
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
+msgid "Song _Info ..."
+msgstr "Lied_Informatie ..."
+
+#: src/gtkui/menus.cc:151
+msgid "Jump to _Time ..."
+msgstr "Spring naar _Tijd ..."
+
+#: src/gtkui/menus.cc:152
+msgid "_Jump to Song ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:154
+msgid "Set Repeat Point _A"
+msgstr ""
+
+#: src/gtkui/menus.cc:155
+msgid "Set Repeat Point _B"
+msgstr ""
+
+#: src/gtkui/menus.cc:156
+msgid "_Clear Repeat Points"
+msgstr ""
+
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
+msgid "By _Title"
+msgstr "Volgens _Titel"
+
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
+
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
+msgid "By File _Path"
+msgstr ""
+
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
+msgid "By Track _Number"
+msgstr "Volgens _Nummer"
+
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
+msgid "By _Artist"
+msgstr "Volgens _Artiest"
+
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
+msgid "By Al_bum"
+msgstr ""
+
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
+msgid "By Release _Date"
+msgstr "Volgens uitgave_datum"
+
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
+msgid "By _Length"
+msgstr ""
+
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
+msgid "By _File Path"
+msgstr "Volgens _Bestandspad"
+
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
+msgid "By _Custom Title"
+msgstr "Volgens _Aangepaste titel"
+
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
+msgid "R_everse Order"
+msgstr "R_angschikking omkeren"
+
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
+msgid "_Random Order"
+msgstr "_Willekeurige volgorde"
+
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
+
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
+msgid "_Refresh"
+msgstr "_Vernieuw"
+
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
+msgid "_Sort"
+msgstr "_Sorteer"
+
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
+msgid "Sort Se_lected"
+msgstr ""
+
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
+msgid "Remove _Duplicates"
+msgstr ""
+
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
+msgid "Remove _Unavailable Files"
+msgstr ""
+
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
+msgid "_New"
+msgstr "_Nieuw"
+
+#: src/gtkui/menus.cc:207
+msgid "Ren_ame ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
+msgid "Remo_ve"
+msgstr "_Verwijder"
+
+#: src/gtkui/menus.cc:210
+msgid "_Import ..."
+msgstr "_Importeer ..."
+
+#: src/gtkui/menus.cc:211
+msgid "_Export ..."
+msgstr "_Exporteer ..."
+
+#: src/gtkui/menus.cc:213
+msgid "Playlist _Manager ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
+msgid "_Queue Manager ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
+msgid "Volume _Up"
+msgstr "Volume _Hoger"
+
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
+msgid "Volume _Down"
+msgstr "Volume _Lager"
+
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
+msgid "_Equalizer"
+msgstr "_Equalizer"
+
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
+msgid "E_ffects ..."
+msgstr "E_ffecten ..."
+
+#: src/gtkui/menus.cc:227
+msgid "Show _Menu Bar"
+msgstr "Toon _Menubalk"
+
+#: src/gtkui/menus.cc:228
+msgid "Show I_nfo Bar"
+msgstr "Show I_nfobalk"
+
+#: src/gtkui/menus.cc:229
+msgid "Show Info Bar Vis_ualization"
+msgstr ""
+
+#: src/gtkui/menus.cc:230
+msgid "Show _Status Bar"
+msgstr "Toon _Statusbalk"
+
+#: src/gtkui/menus.cc:232
+msgid "Show _Remaining Time"
+msgstr ""
+
+#: src/gtkui/menus.cc:234
+msgid "_Visualizations ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
+msgid "_File"
+msgstr "_Bestand"
+
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
+msgid "_Playback"
+msgstr ""
+
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
+msgid "P_laylist"
+msgstr "Spee_llijst"
+
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
+msgid "_Services"
+msgstr ""
+
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
+msgid "_Output"
+msgstr "_Uitvoer"
+
+#: src/gtkui/menus.cc:243
+msgid "_View"
+msgstr "_Bekijk"
+
+#: src/gtkui/menus.cc:248
+msgid "_Queue/Unqueue"
+msgstr "In/uit _wachtrij"
+
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
+msgid "Cu_t"
+msgstr ""
+
+#: src/gtkui/menus.cc:254
+msgid "_Copy"
+msgstr "_Kopieer"
+
+#: src/gtkui/menus.cc:255
+msgid "_Paste"
+msgstr "_Plak"
+
+#: src/gtkui/menus.cc:256
+msgid "Select _All"
+msgstr "Selecteer _Alles"
+
+#: src/gtkui/menus.cc:263
+msgid "_Rename ..."
+msgstr "He_rnoem ..."
+
+#: src/gtkui/settings.cc:35
+msgid "<b>Playlist Tabs</b>"
+msgstr ""
+
+#: src/gtkui/settings.cc:36
+msgid "Always show tabs"
+msgstr "Laat tabbladen altijd zien"
+
+#: src/gtkui/settings.cc:38
+msgid "Show entry counts"
+msgstr "Toon entree tellingen"
+
+#: src/gtkui/settings.cc:40
+msgid "Show close buttons"
+msgstr "Toon sluitknoppen"
+
+#: src/gtkui/settings.cc:42
+msgid "<b>Playlist Columns</b>"
+msgstr "<b>Afspeellijst Kolommen</b>"
+
+#: src/gtkui/settings.cc:44
+msgid "Show column headers"
+msgstr "Toon kolomkoppen"
+
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
+msgid "<b>Miscellaneous</b>"
+msgstr "<b>Diversen</b>"
+
+#: src/gtkui/settings.cc:47
+msgid "Arrow keys seek by:"
+msgstr ""
+
+#: src/gtkui/settings.cc:50
+msgid "Scroll on song change"
+msgstr ""
+
+#: src/gtkui/ui_gtk.cc:71
+msgid "GTK Interface"
+msgstr "GTK Interface"
+
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
+#, c-format
+msgid "%s - Audacious"
+msgstr "%s - Audacious"
+
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
+msgid "Buffering ..."
+msgstr ""
+
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
+msgid "Audacious"
+msgstr "Audacious"
+
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
+#, c-format
+msgid "%d channel"
+msgid_plural "%d channels"
+msgstr[0] "%d kanaal"
+msgstr[1] "%d kanalen"
+
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
+#, c-format
+msgid "%d kbps"
+msgstr "%d kbps"
+
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Speellijst modus."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr ""
+
+#: src/hotkey/gui.cc:71
+msgid "Previous track"
+msgstr "Vorig liedje"
+
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
+msgid "Play"
+msgstr "Afspelen"
+
+#: src/hotkey/gui.cc:73
+msgid "Pause/Resume"
+msgstr "Pauzeer/Hervat"
+
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
+msgid "Stop"
+msgstr "Stop"
+
+#: src/hotkey/gui.cc:75
+msgid "Next track"
+msgstr "Volgend liedje"
+
+#: src/hotkey/gui.cc:76
+msgid "Forward 5 seconds"
+msgstr "Vijf seconden naar voren"
+
+#: src/hotkey/gui.cc:77
+msgid "Rewind 5 seconds"
+msgstr "Vijf seconden terug"
+
+#: src/hotkey/gui.cc:78
+msgid "Mute"
+msgstr "Dempen"
+
+#: src/hotkey/gui.cc:79
+msgid "Volume up"
+msgstr "Volume Harder"
+
+#: src/hotkey/gui.cc:80
+msgid "Volume down"
+msgstr "Volume zachter"
+
+#: src/hotkey/gui.cc:81
+msgid "Jump to file"
+msgstr "Spring naar bestand"
+
+#: src/hotkey/gui.cc:82
+msgid "Toggle player window(s)"
+msgstr ""
+
+#: src/hotkey/gui.cc:83
+msgid "Show On-Screen-Display"
+msgstr "Show On-Screen-Display"
+
+#: src/hotkey/gui.cc:84
+msgid "Toggle repeat"
+msgstr "Herhaal Aan/Uit"
+
+#: src/hotkey/gui.cc:85
+msgid "Toggle shuffle"
+msgstr "Shuffle Aan/Uit"
+
+#: src/hotkey/gui.cc:86
+msgid "Toggle stop after current"
+msgstr ""
+
+#: src/hotkey/gui.cc:87
+msgid "Raise player window(s)"
+msgstr ""
+
+#: src/hotkey/gui.cc:97
+msgid "(none)"
+msgstr "(geen)"
+
+#: src/hotkey/gui.cc:234
+msgid ""
+"It is not recommended to bind the primary mouse buttons without "
+"modificators.\n"
+"\n"
+"Do you want to continue?"
+msgstr ""
+
+#: src/hotkey/gui.cc:236
+msgid "Binding mouse buttons"
+msgstr ""
+
+#: src/hotkey/gui.cc:391
+msgid ""
+"Press a key combination inside a text field.\n"
+"You can also bind mouse buttons."
+msgstr ""
+
+#: src/hotkey/gui.cc:396
+msgid "Hotkeys:"
+msgstr "Sneltoetsen:"
+
+#: src/hotkey/gui.cc:413
+msgid "<b>Action:</b>"
+msgstr "<b>Actie:</b>"
+
+#: src/hotkey/gui.cc:420
+msgid "<b>Key Binding:</b>"
+msgstr ""
+
+#: src/hotkey/gui.cc:468
+msgid "_Add"
+msgstr "_Toevoegen"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globale Sneltoetsen"
+
+#: src/hotkey/plugin.cc:79
+msgid ""
+"Global Hotkey Plugin\n"
+"Control the player with global key combinations or multimedia keys.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n"
+"\n"
+"Contributers include:\n"
+"Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+"Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+" Bryn Davies <curious at ihug.com.au>,\n"
+" Jonathan A. Davis <davis at jdhouse.org>,\n"
+" Jeremy Tan <nsx at nsx.homeip.net>"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK Uitvoer"
+
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
+msgid ""
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
+msgstr ""
+
+#: src/ladspa/plugin.cc:414
+#, c-format
+msgid "%s Settings"
+msgstr "%s Instellingen"
+
+#: src/ladspa/plugin.cc:478
+msgid "Module paths:"
+msgstr "Module paden:"
+
+#: src/ladspa/plugin.cc:483
+msgid ""
+"<small>Separate multiple paths with a colon.\n"
+"These paths are searched in addition to LADSPA_PATH.\n"
+"After adding new paths, press Enter to scan for new plugins.</small>"
+msgstr ""
+
+#: src/ladspa/plugin.cc:499
+msgid "Available plugins:"
+msgstr "Beschikbare plugins:"
+
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
+msgid "Enable"
+msgstr "Inschakelen"
+
+#: src/ladspa/plugin.cc:518
+msgid "Enabled plugins:"
+msgstr "Ingeschakelde plugins:"
+
+#: src/ladspa/plugin.cc:534
+msgid "Settings"
+msgstr "Instellingen"
+
+#: src/ladspa/plugin.cc:551
+msgid ""
+"LADSPA Host for Audacious\n"
+"Copyright 2011 John Lindgren"
+msgstr ""
+"LADSPA Host voor Audacious\n"
+"Copyright 2011 John Lindgren"
+
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "LADSPA Host"
+
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC Plugin"
+
+#: src/lirc/lirc.cc:381
+msgid ""
+"A simple plugin to control Audacious using the LIRC remote control daemon\n"
+"\n"
+"Adapted for Audacious by:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Based on the XMMS LIRC plugin by:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"For more information about LIRC, see http://lirc.org."
+msgstr ""
+
+#: src/lirc/lirc.cc:392
+msgid "<b>Connection</b>"
+msgstr "<b>Verbinding</b>"
+
+#: src/lirc/lirc.cc:393
+msgid "Reconnect to LIRC server"
+msgstr ""
+
+#: src/lirc/lirc.cc:395
+msgid "Wait before reconnecting:"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki Plugin"
+
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
+msgid "No lyrics available"
+msgstr "Geen song-tekst beschikbaar"
+
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Fout"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
+#, c-format
+msgid "Unable to fetch %s"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
+#, c-format
+msgid "Unable to parse %s"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
+msgid "Looking for lyrics ..."
+msgstr "Zoeken naar teksten ..."
+
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Missing song metadata"
+msgstr "Ontbrekende metadata"
+
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
+msgid "Connecting to lyrics.wikia.com ..."
+msgstr "Verbinden met lyrics.wikia.com ..."
+
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
+
+#: src/m3u/m3u.cc:32
+msgid "M3U Playlists"
+msgstr "M3U Afspeellijsten"
+
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
+#, c-format
+msgid "Tact generator: %d bpm"
+msgstr ""
+
+#: src/metronom/metronom.cc:149
+#, c-format
+msgid "Tact generator: %d bpm %d/%d"
+msgstr ""
+
+#: src/metronom/metronom.cc:237
+msgid ""
+"A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
+"\n"
+"To use it, add a URL: tact://beats*num/den\n"
+"e.g. tact://77 to play 77 beats per minute\n"
+"or tact://60*3/4 to play 60 bpm in 3/4 tacts"
+msgstr ""
+
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Kanaal Mixer"
+
+#: src/mixer/mixer.cc:202
+msgid ""
+"Channel Mixer Plugin for Audacious\n"
+"Copyright 2011-2012 John Lindgren and Michał Lipski"
+msgstr ""
+
+#: src/mixer/mixer.cc:206
+msgid "<b>Channel Mixer</b>"
+msgstr "<b>Kanalen Mixer</b>"
+
+#: src/mixer/mixer.cc:207
+msgid "Output channels:"
+msgstr "Uitvoerkanalen:"
+
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
+msgstr "MMS Plugin"
+
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlus (Module Player)"
+
+#: src/modplug/plugin_main.cc:53
+msgid "<b>Resolution</b>"
+msgstr "<b>Resolutie</b>"
+
+#: src/modplug/plugin_main.cc:54
+msgid "8-bit"
+msgstr "8-bit"
+
+#: src/modplug/plugin_main.cc:55
+msgid "16-bit"
+msgstr "16-bit"
+
+#: src/modplug/plugin_main.cc:56
+msgid "<b>Channels</b>"
+msgstr "<b>Kanalen</b>"
+
+#: src/modplug/plugin_main.cc:60
+msgid "Nearest (fastest)"
+msgstr "Dichtstbijzijnd (snelst)"
+
+#: src/modplug/plugin_main.cc:61
+msgid "Linear (fast)"
+msgstr "Lineair (snel)"
+
+#: src/modplug/plugin_main.cc:62
+msgid "Spline (good)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:63
+msgid "Polyphase (best)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:65
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: src/modplug/plugin_main.cc:66
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: src/modplug/plugin_main.cc:67
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: src/modplug/plugin_main.cc:68
+msgid "96 kHz"
+msgstr "96 kHz"
+
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
+msgid "Level:"
+msgstr "Level:"
+
+#: src/modplug/plugin_main.cc:78
+msgid "Cutoff:"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:91
+msgid "<b>Reverb</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:94
+msgid "<b>Bass Boost</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:97
+msgid "<b>Surround</b>"
+msgstr "<b>Surround</b>"
+
+#: src/modplug/plugin_main.cc:100
+msgid "<b>Preamp</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:107
+msgid "Oversample"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:108
+msgid "Noise reduction"
+msgstr "Ruisonderdrukking"
+
+#: src/modplug/plugin_main.cc:109
+msgid "Play Amiga MODs"
+msgstr "Speel Amiga MOD's"
+
+#: src/modplug/plugin_main.cc:110
+msgid "<b>Repeat</b>"
+msgstr "<b>Herhaal</b>"
+
+#: src/modplug/plugin_main.cc:111
+msgid "Repeat count:"
+msgstr "Herhaal teller:"
+
+#: src/modplug/plugin_main.cc:112
+msgid "To repeat forever, set the repeat count to -1."
+msgstr ""
+
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
+
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
+msgstr "MPG123 Plugin"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Geadvanceerd</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
+msgid "MPRIS 2 Server"
+msgstr "MPRIS 2 Server"
+
+#: src/neon/neon.cc:97
+msgid "Neon HTTP/HTTPS Plugin"
+msgstr "Neon HTTP/HTTPS Plugin"
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Onbekende HTTP fout"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Teveel redirects"
+
+#: src/notify/event.cc:64
+msgid "Stopped"
+msgstr "Gestopt"
+
+#: src/notify/event.cc:64
+msgid "Audacious is not playing."
+msgstr "Audacious is niets aan het afspelen."
+
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Desktop Notificaties"
+
+#: src/notify/notify.cc:60
+msgid ""
+"Desktop Notifications Plugin for Audacious\n"
+"Copyright (C) 2010 Maximilian Bogner\n"
+"Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"This plugin is free software: you can redistribute it and/or modify it under "
+"the terms of the GNU General Public License as published by the Free "
+"Software Foundation, either version 3 of the License, or (at your option) "
+"any later version.\n"
+"\n"
+"This plugin is distributed in the hope that 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, see <http://www.gnu.org/licenses/>."
+msgstr ""
+
+#: src/notify/notify.cc:110
+msgid "Show playback controls"
+msgstr ""
+
+#: src/notify/notify.cc:112
+msgid "Always show notification"
+msgstr "Laat altijd de notificaties zien"
+
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
+
+#: src/notify/osd.cc:58
+msgid "Show"
+msgstr "Laat zien"
+
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
+msgid "Pause"
+msgstr "Pauze"
+
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
+msgid "Next"
+msgstr "Volgende"
+
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 Uitvoer"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 Uitvoer"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Standaard Apparaat"
+
+#: src/oss4/plugin.cc:77
+msgid "Audio device:"
+msgstr "Audio apparaat:"
+
+#: src/oss4/plugin.cc:80
+msgid "Use alternate device:"
+msgstr "Gebruik alternatief apparaat:"
+
+#: src/oss4/plugin.cc:84
+msgid "Save volume between sessions."
+msgstr "Bewaar het volume tussen twee sessies."
+
+#: src/oss4/plugin.cc:86
+msgid "Enable format conversions made by the OSS software."
+msgstr ""
+
+#: src/oss4/plugin.cc:88
+msgid "Enable exclusive mode to prevent virtual mixing."
+msgstr ""
+
+#: src/oss4/plugin.cc:100
+msgid ""
+"OSS4 Output Plugin for Audacious\n"
+"Copyright 2010-2012 Michał Lipski\n"
+"\n"
+"I would like to thank people on #audacious, especially Tony Vroon and John "
+"Lindgren and of course the authors of the previous OSS plugin."
+msgstr ""
+"OSS4 Output Plugin voor Audacious\n"
+"Copyright 2010-2012 Michał Lipski\n"
+"\n"
+"Ik wil graag de mensen op #audacious bedanken. Speciaal Tony Vroon en John "
+"Lindgren en natuurlijk de auteurs van de vorige OSS plugin."
+
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Invoer"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Verwijderen"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
+msgid "PLS Playlists"
+msgstr "PLS Afspeellijsten"
+
+#: src/psf/plugin.cc:45
+msgid "OpenPSF PSF1/PSF2 Decoder"
+msgstr "OpenPSF PSF1/PSF2 Decoder"
+
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio Uitvoer"
+
+#: src/pulse_audio/pulse_audio.cc:611
+msgid ""
+"Audacious PulseAudio Output Plugin\n"
+"\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."
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia Uitvoer"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Werken ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Zoeken"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Map Openen ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Map Toevoegen ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Bestanden Openen"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Bestanden Toevoegen"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Vorige"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Herhaal"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Shuffle"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt Interface"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
+msgid ""
+"Sample Rate Converter Plugin for Audacious\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+
+#: src/resample/resample.cc:187
+msgid "Skip/repeat samples"
+msgstr ""
+
+#: src/resample/resample.cc:188
+msgid "Linear interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:189
+msgid "Fast sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:190
+msgid "Medium sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:191
+msgid "Best sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:195
+msgid "<b>Conversion</b>"
+msgstr "<b>Conversie</b>"
+
+#: src/resample/resample.cc:196
+msgid "Method:"
+msgstr "Methode:"
+
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
+msgid "Rate:"
+msgstr "Rate:"
+
+#: src/resample/resample.cc:202
+msgid "<b>Rate Mappings</b>"
+msgstr ""
+
+#: src/resample/resample.cc:203
+msgid "Use rate mappings"
+msgstr ""
+
+#: src/resample/resample.cc:205
+msgid "8 kHz:"
+msgstr "8 kHz:"
+
+#: src/resample/resample.cc:209
+msgid "16 kHz:"
+msgstr "16 kHz:"
+
+#: src/resample/resample.cc:213
+msgid "22.05 kHz:"
+msgstr "22.05 kHz:"
+
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32,0 kHz:"
+
+#: src/resample/resample.cc:221
+msgid "44.1 kHz:"
+msgstr "44.1 kHz:"
+
+#: src/resample/resample.cc:225
+msgid "48 kHz:"
+msgstr "48 kHz:"
+
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
+msgid "96 kHz:"
+msgstr "96 kHz:"
+
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
+msgstr "192 kHz:"
+
+#: src/scrobbler2/config_window.cc:41
+#, c-format
+msgid "OK. Scrobbling for user: %s"
+msgstr "OK. Scrobbling voor gebruiker: %s"
+
+#: src/scrobbler2/config_window.cc:54
+msgid "Permission Denied"
+msgstr "Toegang Geweigerd"
+
+#: src/scrobbler2/config_window.cc:56
+msgid "Access the following link to allow Audacious to scrobble your plays:"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:66
+msgid "Keep this window open and click 'Check Permission' again.\n"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
+msgid ""
+"Don't worry. Your scrobbles are saved on your computer.\n"
+"They will be submitted as soon as Audacious is allowed to do so."
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:77
+msgid "Network Problem."
+msgstr "Netwerk Probleem."
+
+#: src/scrobbler2/config_window.cc:78
+msgid "There was a problem contacting Last.fm. Please try again later."
+msgstr ""
+"Er is een probleem om met Last.fm te verbinden. Probeer het later nog eens."
+
+#: src/scrobbler2/config_window.cc:110
+msgid "Checking..."
+msgstr "Controleren..."
+
+#: src/scrobbler2/config_window.cc:176
+msgid "C_heck Permission"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:177
+msgid "_Revoke Permission"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:220
+msgid ""
+"You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
+msgid ""
+"The Scrobbler plugin could not be started.\n"
+"There might be a problem with your installation."
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:289
+msgid ""
+"Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
+"\n"
+"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Thanks to John Lindgren for giving me a hand at the beginning of this "
+"project.\n"
+"\n"
+msgstr ""
+
+#: src/scrobbler2/scrobbler_communication.cc:642
+msgid ""
+"Audacious is now using an improved version of the Last.fm Scrobbler.\n"
+"Please check the Preferences for the Scrobbler plugin."
+msgstr ""
+
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL Uitvoer"
+
+#: src/sdlout/sdlout.cc:77
+msgid ""
+"SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"SDL Output Plugin voor Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
+msgid "Library"
+msgstr "Bibliotheek"
+
+#: src/search-tool/search-tool.cc:394
+#, c-format
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultaat"
+msgstr[1] "%d resultaten"
+
+#: src/search-tool/search-tool.cc:400
+#, c-format
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d verborgen)"
+msgstr[1] "(%d verborgen)"
+
+#: src/search-tool/search-tool.cc:594
+#, c-format
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d lied"
+msgstr[1] "%d liedjes"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "van deze genre"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "op"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "volgens"
+
+#: src/search-tool/search-tool.cc:643
+msgid "_Create Playlist"
+msgstr "_Creëer Afspeellijst"
+
+#: src/search-tool/search-tool.cc:645
+msgid "_Add to Playlist"
+msgstr "Voeg toe _Aan Afspeellijst"
+
+#: src/search-tool/search-tool.cc:684
+msgid "Search library"
+msgstr "Zoek bibliotheek"
+
+#: src/search-tool/search-tool.cc:688
+msgid ""
+"To import your music library into Audacious, choose a folder and then click "
+"the \"refresh\" icon."
+msgstr ""
+
+#: src/search-tool/search-tool.cc:696
+msgid "Please wait ..."
+msgstr "Aub wachten ..."
+
+#: src/search-tool/search-tool.cc:723
+msgid "Choose Folder"
+msgstr "Kies Map"
+
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID Speler"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanalen:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Kloksnelheid:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Open Bestanden ..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Open URL ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Doorzoek Bibliotheek"
+
+#: src/skins/menus.cc:68
+msgid "Playback"
+msgstr ""
+
+#: src/skins/menus.cc:69
+msgid "Playlist"
+msgstr "Speellijst"
+
+#: src/skins/menus.cc:70
+msgid "View"
+msgstr ""
+
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
+msgid "Services"
+msgstr ""
+
+#: src/skins/menus.cc:74
+msgid "About ..."
+msgstr "Over ..."
+
+#: src/skins/menus.cc:75
+msgid "Settings ..."
+msgstr "Instellingen ..."
+
+#: src/skins/menus.cc:76
+msgid "Quit"
+msgstr ""
+
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
+msgid "Song Info ..."
+msgstr ""
+
+#: src/skins/menus.cc:84
+msgid "No Playlist Advance"
+msgstr ""
+
+#: src/skins/menus.cc:85
+msgid "Stop After This Song"
+msgstr "Stop Na Dit Liedje"
+
+#: src/skins/menus.cc:93
+msgid "Set A-B Repeat"
+msgstr "Set A-B Herhaling"
+
+#: src/skins/menus.cc:94
+msgid "Clear A-B Repeat"
+msgstr "Wis A-B Herhaling"
+
+#: src/skins/menus.cc:96
+msgid "Jump to Song ..."
+msgstr "Spring naar Liedje ..."
+
+#: src/skins/menus.cc:97
+msgid "Jump to Time ..."
+msgstr "Spring naar Tijd ..."
+
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr ""
+
+#: src/skins/menus.cc:103
+msgid "New Playlist"
+msgstr "Nieuwe afspeellijst"
+
+#: src/skins/menus.cc:104
+msgid "Rename Playlist ..."
+msgstr "Hernoem Afspeellijst ..."
+
+#: src/skins/menus.cc:105
+msgid "Remove Playlist"
+msgstr "Verwijder Afspeellijst"
+
+#: src/skins/menus.cc:107
+msgid "Previous Playlist"
+msgstr "Vorige Afspeellijst"
+
+#: src/skins/menus.cc:108
+msgid "Next Playlist"
+msgstr "Volgende Afspeellijst"
+
+#: src/skins/menus.cc:110
+msgid "Import Playlist ..."
+msgstr "Importeer Afspeellijst ..."
+
+#: src/skins/menus.cc:111
+msgid "Export Playlist ..."
+msgstr "Exporteer Afspeellijst ..."
+
+#: src/skins/menus.cc:113
+msgid "Playlist Manager ..."
+msgstr ""
+
+#: src/skins/menus.cc:114
+msgid "Queue Manager ..."
+msgstr ""
+
+#: src/skins/menus.cc:116
+msgid "Refresh Playlist"
+msgstr ""
+
+#: src/skins/menus.cc:120
+msgid "Show Playlist Editor"
+msgstr ""
+
+#: src/skins/menus.cc:121
+msgid "Show Equalizer"
+msgstr "Toon Equalizer"
+
+#: src/skins/menus.cc:123
+msgid "Show Remaining Time"
+msgstr ""
+
+#: src/skins/menus.cc:125
+msgid "Always on Top"
+msgstr "Altijd bovenaan"
+
+#: src/skins/menus.cc:126
+msgid "On All Workspaces"
+msgstr ""
+
+#: src/skins/menus.cc:128
+msgid "Roll Up Player"
+msgstr ""
+
+#: src/skins/menus.cc:129
+msgid "Roll Up Playlist Editor"
+msgstr ""
+
+#: src/skins/menus.cc:130
+msgid "Roll Up Equalizer"
+msgstr ""
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Dubbele Grootte"
+
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "URL Toevoegen ..."
+
+#: src/skins/menus.cc:139
+msgid "Add Files ..."
+msgstr "Bestanden Toevoegen ..."
+
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
+msgid "By Title"
+msgstr "Volgens titel"
+
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "Volgens Bestandsnaam"
+
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
+msgid "By File Path"
+msgstr "Volgens Bestandspad"
+
+#: src/skins/menus.cc:151
+msgid "Remove All"
+msgstr "Verwijder Alles"
+
+#: src/skins/menus.cc:152
+msgid "Clear Queue"
+msgstr "Wachtrij leegmaken"
+
+#: src/skins/menus.cc:154
+msgid "Remove Unavailable Files"
+msgstr "Verwijder onbeschikbare bestanden"
+
+#: src/skins/menus.cc:155
+msgid "Remove Duplicates"
+msgstr "Verwijder duplicaten"
+
+#: src/skins/menus.cc:157
+msgid "Remove Unselected"
+msgstr "Verwijder niet geselecteerde"
+
+#: src/skins/menus.cc:158
+msgid "Remove Selected"
+msgstr "Verwijder geselecteerde"
+
+#: src/skins/menus.cc:162
+msgid "Search and Select"
+msgstr "Zoek en selecteer"
+
+#: src/skins/menus.cc:164
+msgid "Invert Selection"
+msgstr "Selectie omkeren"
+
+#: src/skins/menus.cc:165
+msgid "Select None"
+msgstr "Selecteer geen enkele"
+
+#: src/skins/menus.cc:166
+msgid "Select All"
+msgstr "Selecteer alles"
+
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Volgens nummer"
+
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
+msgid "By Artist"
+msgstr "Volgens artiest"
+
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Volgens album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Volgens Album Artiest"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
+msgid "By Release Date"
+msgstr "Volgens Uitgave Datum"
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Volgens Genre"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Volgens Lengte"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Volgens Aangepaste Titel"
+
+#: src/skins/menus.cc:198
+msgid "Randomize List"
+msgstr "Herschik lijst in willekeurige volgorde"
+
+#: src/skins/menus.cc:199
+msgid "Reverse List"
+msgstr "Lijst omkeren"
+
+#: src/skins/menus.cc:201
+msgid "Sort Selected"
+msgstr "Sorteer het geselecteerde"
+
+#: src/skins/menus.cc:202
+msgid "Sort List"
+msgstr "Sorteer lijst"
+
+#: src/skins/menus.cc:208
+msgid "Cut"
+msgstr "Knip"
+
+#: src/skins/menus.cc:209
+msgid "Copy"
+msgstr "Kopieer"
+
+#: src/skins/menus.cc:210
+msgid "Paste"
+msgstr "Plak"
+
+#: src/skins/menus.cc:212
+msgid "Queue/Unqueue"
+msgstr "Queue/Unqueue"
+
+#: src/skins/menus.cc:218
+msgid "Load Preset ..."
+msgstr "Laad Presets ..."
+
+#: src/skins/menus.cc:219
+msgid "Load Auto Preset ..."
+msgstr "Laad Auto Preset ..."
+
+#: src/skins/menus.cc:220
+msgid "Load Default"
+msgstr "Laad Standaard"
+
+#: src/skins/menus.cc:221
+msgid "Load Preset File ..."
+msgstr "Laad Presets Bestand"
+
+#: src/skins/menus.cc:222
+msgid "Load EQF File ..."
+msgstr "Laad EQF Bestand"
+
+#: src/skins/menus.cc:224
+msgid "Save Preset ..."
+msgstr "Bewaar Presets ..."
+
+#: src/skins/menus.cc:225
+msgid "Save Auto Preset ..."
+msgstr "Bewaar Auto Preset ..."
+
+#: src/skins/menus.cc:226
+msgid "Save Default"
+msgstr "Bewaar Standaard"
+
+#: src/skins/menus.cc:227
+msgid "Save Preset File ..."
+msgstr "Bewaar Presets Bestand ..."
+
+#: src/skins/menus.cc:228
+msgid "Save EQF File ..."
+msgstr "Bewaar EQF Bestand ..."
+
+#: src/skins/menus.cc:230
+msgid "Delete Preset ..."
+msgstr "Verwijder Preset ..."
+
+#: src/skins/menus.cc:231
+msgid "Delete Auto Preset ..."
+msgstr "Verwijder Auto Preset ..."
+
+#: src/skins/menus.cc:233
+msgid "Import Winamp Presets ..."
+msgstr "Importeer Winaps Presets ..."
+
+#: src/skins/menus.cc:235
+msgid "Reset to Zero"
+msgstr "Terug naar Nul"
+
+#: src/skins/plugin.cc:48
+msgid "Winamp Classic Interface"
+msgstr "Winamp Klassieke Interface"
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
+msgid "Save"
+msgstr "Opslaan"
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
+msgid "Load"
+msgstr "Laad"
+
+#: src/skins/preset-browser.cc:83
+msgid "Load Preset File"
+msgstr "Laad Presets Bestand"
+
+#: src/skins/preset-browser.cc:100
+msgid "Load EQF File"
+msgstr "Laad EQF Bestand"
+
+#: src/skins/preset-browser.cc:119
+msgid "Save Preset File"
+msgstr "Bewaar Presets Bestand"
+
+#: src/skins/preset-browser.cc:137
+msgid "Save EQF File"
+msgstr "Bewaar EQF Bestand"
+
+#: src/skins/preset-browser.cc:151
+msgid "Import Winamp Presets"
+msgstr "Importeer Winamp Instellingen"
+
+#: src/skins/preset-list.cc:285
+msgid "Presets"
+msgstr "Presets"
+
+#: src/skins/preset-list.cc:335
+msgid "Load preset"
+msgstr "Laad Presets"
+
+#: src/skins/preset-list.cc:351
+msgid "Load auto-preset"
+msgstr "Laad auto-preset"
+
+#: src/skins/preset-list.cc:367
+msgid "Save preset"
+msgstr "Bewaar Presets"
+
+#: src/skins/preset-list.cc:382
+msgid "Save auto-preset"
+msgstr "Bewaar auto-preset"
+
+#: src/skins/preset-list.cc:408
+msgid "Delete preset"
+msgstr "Verwijder preset"
+
+#: src/skins/preset-list.cc:424
+msgid "Delete auto-preset"
+msgstr "Verwijder auto-preset"
+
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Speler:"
+
+#: src/skins/skins_cfg.cc:178
+msgid "Select main player window font:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Afspeellijst:"
+
+#: src/skins/skins_cfg.cc:181
+msgid "Select playlist font:"
+msgstr "Selecteer lettertype van de speellijst:"
+
+#: src/skins/skins_cfg.cc:187
+msgid "<b>Skin</b>"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:189
+msgid "<b>Fonts</b>"
+msgstr "<b>Lettertypes</b>"
+
+#: src/skins/skins_cfg.cc:192
+msgid "Use bitmap fonts (supports ASCII only)"
+msgstr "Gebruik bitmap lettertypen (ondersteunt alleen ASCII)"
+
+#: src/skins/skins_cfg.cc:194
+msgid "Scroll song title"
+msgstr "Scrol titel "
+
+#: src/skins/skins_cfg.cc:196
+msgid "Scroll song title in both directions"
+msgstr "Scrol titel in beide kanten"
+
+#: src/skins/skins_cfg.cc:201
+msgid "Analyzer"
+msgstr "Analyseerder"
+
+#: src/skins/skins_cfg.cc:202
+msgid "Scope"
+msgstr "Scope"
+
+#: src/skins/skins_cfg.cc:203
+msgid "Voiceprint / VU meter"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:204
+msgid "Off"
+msgstr "Uit"
+
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
+msgid "Normal"
+msgstr "Normaal"
+
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
+msgid "Fire"
+msgstr "Vuur"
+
+#: src/skins/skins_cfg.cc:210
+msgid "Vertical lines"
+msgstr "Verticale Strepen"
+
+#: src/skins/skins_cfg.cc:214
+msgid "Lines"
+msgstr "Lijnen"
+
+#: src/skins/skins_cfg.cc:215
+msgid "Bars"
+msgstr "Horizontale Strepen"
+
+#: src/skins/skins_cfg.cc:219
+msgid "Slowest"
+msgstr "Traagst"
+
+#: src/skins/skins_cfg.cc:220
+msgid "Slow"
+msgstr "Traag"
+
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
+msgid "Medium"
+msgstr "Matig"
+
+#: src/skins/skins_cfg.cc:222
+msgid "Fast"
+msgstr "Snel"
+
+#: src/skins/skins_cfg.cc:223
+msgid "Fastest"
+msgstr "Snelst"
+
+#: src/skins/skins_cfg.cc:227
+msgid "Dots"
+msgstr "Punten"
+
+#: src/skins/skins_cfg.cc:228
+msgid "Line"
+msgstr "Lijn"
+
+#: src/skins/skins_cfg.cc:229
+msgid "Solid"
+msgstr "Solide"
+
+#: src/skins/skins_cfg.cc:235
+msgid "Ice"
+msgstr "IJs"
+
+#: src/skins/skins_cfg.cc:240
+msgid "Smooth"
+msgstr "Glad"
+
+#: src/skins/skins_cfg.cc:244
+msgid "<b>Type</b>"
+msgstr "<b>Type</b>"
+
+#: src/skins/skins_cfg.cc:245
+msgid "Visualization type:"
+msgstr "Visualisatie type:"
+
+#: src/skins/skins_cfg.cc:248
+msgid "<b>Analyzer</b>"
+msgstr "<b>Analyseerder</b>"
+
+#: src/skins/skins_cfg.cc:249
+msgid "Show peaks"
+msgstr "Laat pieken zien"
+
+#: src/skins/skins_cfg.cc:251
+msgid "Coloring:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:254
+msgid "Style:"
+msgstr "Stijl:"
+
+#: src/skins/skins_cfg.cc:257
+msgid "Falloff:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:260
+msgid "Peak falloff:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:264
+msgid "Scope Style:"
+msgstr "Scope Stijl:"
+
+#: src/skins/skins_cfg.cc:267
+msgid "Voiceprint Coloring:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:270
+msgid "VU Meter Style:"
+msgstr "VU Meter Stijl:"
+
+#: src/skins/skins_cfg.cc:276
+msgid "General"
+msgstr "Algemeen"
+
+#: src/skins/skins_cfg.cc:277
+msgid "Visualization"
+msgstr "Visualisatie "
+
+#: src/skins/ui_equalizer.cc:282
+msgid "Preamp"
+msgstr "Voorversterker"
+
+#: src/skins/ui_equalizer.cc:286
+msgid "31 Hz"
+msgstr "31 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "63 Hz"
+msgstr "63 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "125 Hz"
+msgstr "125 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "250 Hz"
+msgstr "250 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "500 Hz"
+msgstr "500 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "1 kHz"
+msgstr "1 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "2 kHz"
+msgstr "2 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "4 kHz"
+msgstr "4 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "16 kHz"
+msgstr "16 kHz"
+
+#: src/skins/ui_equalizer.cc:330
+msgid "Audacious Equalizer"
+msgstr "Audacious Equalizer"
+
+#: src/skins/ui_main.cc:688
+#, c-format
+msgid "Seek to %d:%-2.2d / %d:%-2.2d"
+msgstr ""
+
+#: src/skins/ui_main.cc:709
+#, c-format
+msgid "Volume: %d%%"
+msgstr "Volume: %d%%"
+
+#: src/skins/ui_main.cc:732
+#, c-format
+msgid "Balance: %d%% left"
+msgstr "Balans: %d%% links"
+
+#: src/skins/ui_main.cc:734
+msgid "Balance: center"
+msgstr "Balans: gecentreerd"
+
+#: src/skins/ui_main.cc:736
+#, c-format
+msgid "Balance: %d%% right"
+msgstr "Balans: %d%% rechts"
+
+#: src/skins/ui_main.cc:842
+msgid "Options Menu"
+msgstr "Opties menu"
+
+#: src/skins/ui_main.cc:846
+msgid "Disable 'Always On Top'"
+msgstr "'Altijd bovenaan' uitschakelen"
+
+#: src/skins/ui_main.cc:848
+msgid "Enable 'Always On Top'"
+msgstr "'Altijd bovenaan' inschakelen"
+
+#: src/skins/ui_main.cc:851
+msgid "File Info Box"
+msgstr "Bestandsinformatie Box"
+
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualisatie "
+
+#: src/skins/ui_main.cc:1336
+msgid "Repeat point A set."
+msgstr "Herhaal ingesteld punt A."
+
+#: src/skins/ui_main.cc:1341
+msgid "Repeat point B set."
+msgstr "Herhaal ingesteld punt B."
+
+#: src/skins/ui_main.cc:1350
+msgid "Repeat points cleared."
+msgstr ""
+
+#: src/skins/ui_playlist.cc:219
+msgid "Search entries in active playlist"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:226
+msgid ""
+"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."
+msgstr ""
+
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Titel:"
+
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
+
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artiest:"
+
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Bestadsnaam:"
+
+#: src/skins/ui_playlist.cc:263
+msgid "Clear previous selection before searching"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:266
+msgid "Automatically toggle queue for matching entries"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:269
+msgid "Create a new playlist with matching entries"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:717
+msgid "Audacious Playlist Editor"
+msgstr "Audacious Afspeellijst Bewerker"
+
+#: src/skins/ui_playlist.cc:752
+#, c-format
+msgid "%s (%d of %d)"
+msgstr "%s (%d van %d)"
+
+#: src/skins/ui_skinselector.cc:167
+msgid "Archived Winamp 2.x skin"
+msgstr ""
+
+#: src/skins/ui_skinselector.cc:172
+msgid "Unarchived Winamp 2.x skin"
+msgstr ""
+
+#: src/skins/util.cc:430
+#, c-format
+msgid "Could not create directory (%s): %s\n"
+msgstr "Kon de map (%s) niet aanmaken: %s\n"
+
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile Plugin"
+
+#: src/sndfile/plugin.cc:336
+msgid ""
+"Based on the xmms_sndfile plugin:\n"
+"Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
+"\n"
+"Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\n"
+"\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."
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio Uitvoer"
+
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Apparaat (leeg voor standaardwaarde):"
+
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Volume opslaan en herstellen:"
+
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
+
+#: src/song_change/song_change.cc:33
+msgid "Song Change"
+msgstr ""
+
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Opdrachten</b>"
+
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Opdracht uitvoeren wanneer een nieuw lied start:"
+
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Opdracht uitvoeren aan het eind van een lied:"
+
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Opdracht uitvoeren aan het eind van een afspeellijst:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
+"Opdracht uitvoeren wanneer de songtitel verandert (voor netwerk streams):"
+
+#: src/song_change/song_change.cc:376
+msgid ""
+"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"
+"%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"
+"%p: Currently playing (1 or 0)\n"
+"%a: Artist\n"
+"%b: Album\n"
+"%T: Track title"
+msgstr ""
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Lied Informatie (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
+
+#: src/sox-resampler/sox-resampler.cc:144
+msgid ""
+"SoX Resampler Plugin for Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Based on Sample Rate Converter Plugin:\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+"SoX Resampler Plugin voor Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Gebaseerd op de Sample Rate Converter Plugin:\n"
+"Copyright 2010-2012 John Lindgren"
+
+#: src/sox-resampler/sox-resampler.cc:150
+msgid "Quick"
+msgstr "Snel"
+
+#: src/sox-resampler/sox-resampler.cc:151
+msgid "Low"
+msgstr "Laag"
+
+#: src/sox-resampler/sox-resampler.cc:153
+msgid "High"
+msgstr "Hoog"
+
+#: src/sox-resampler/sox-resampler.cc:154
+msgid "Very High"
+msgstr "Erg Hoog"
+
+#: src/sox-resampler/sox-resampler.cc:158
+msgid "Quality:"
+msgstr "Kwaliteit:"
+
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Snelheid en Pitch"
+
+#: src/speed-pitch/speed-pitch.cc:210
+msgid "<b>Speed and Pitch</b>"
+msgstr "<b>Snelheid en Pitch</b>"
+
+#: src/speed-pitch/speed-pitch.cc:211
+msgid "Speed:"
+msgstr "Snelheid:"
+
+#: src/speed-pitch/speed-pitch.cc:214
+msgid "Pitch:"
+msgstr "Pitch:"
+
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Status Icoon"
+
+#: src/statusicon/statusicon.cc:283
+msgid "Se_ttings ..."
+msgstr "Ins_tellingen"
+
+#: src/statusicon/statusicon.cc:372
+msgid ""
+"Status Icon Plugin\n"
+"\n"
+"Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Copyright 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"This plugin provides a status icon, placed in\n"
+"the system tray area of the window manager."
+msgstr ""
+
+#: src/statusicon/statusicon.cc:379
+msgid "<b>Mouse Scroll Action</b>"
+msgstr "<b>Muis Scroll Actie</b>"
+
+#: src/statusicon/statusicon.cc:380
+msgid "Change volume"
+msgstr "Verander Volume"
+
+#: src/statusicon/statusicon.cc:383
+msgid "Change playing song"
+msgstr "Verander het huidige lied dat wordt afgespeeld"
+
+#: src/statusicon/statusicon.cc:386
+msgid "<b>Other Settings</b>"
+msgstr "<b>Ander Instellingen</b>"
+
+#: src/statusicon/statusicon.cc:387
+msgid "Disable the popup window"
+msgstr "Het pop-up venster uitschakelen"
+
+#: src/statusicon/statusicon.cc:389
+msgid "Close to the system tray"
+msgstr "In de buurt van het systeemvak"
+
+#: src/statusicon/statusicon.cc:391
+msgid "Advance in playlist when scrolling upward"
+msgstr ""
+
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
+
+#: src/stereo_plugin/stereo.cc:36
+msgid ""
+"Extra Stereo Plugin\n"
+"\n"
+"By Johan Levin, 1999"
+msgstr ""
+"Extra Stereo Plugin\n"
+"\n"
+"Door Johan Levin, 1999"
+
+#: src/stereo_plugin/stereo.cc:44
+msgid "<b>Extra Stereo</b>"
+msgstr "<b>Extra Stereo"
+
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Toon Generator"
+
+#: src/tonegen/tonegen.cc:94
+#, c-format
+msgid "%s %.1f Hz"
+msgstr "%s %.1f Hz"
+
+#: src/tonegen/tonegen.cc:94
+msgid "Tone Generator: "
+msgstr "Toon Generator:"
+
+#: src/tonegen/tonegen.cc:160
+msgid ""
+"Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
+"Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
+"e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
+msgstr ""
+
+#: src/voice_removal/voice_removal.cc:28
+msgid "Voice Removal"
+msgstr "Stem Opheffing"
+
+#: src/vorbis/vorbis.cc:465
+msgid ""
+"Audacious Ogg Vorbis Decoder\n"
+"\n"
+"Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Original code by:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Contributions from:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
+msgstr ""
+
+#: src/vorbis/vorbis.h:18
+msgid "Ogg Vorbis Decoder"
+msgstr "Ogg Vorbis Decoder"
+
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Details over %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Decoder"
+
+#: src/vtx/vtx.cc:184
+msgid ""
+"Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
+"Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
+"Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
+msgstr ""
+
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack Decoder"
+
+#: src/wavpack/wavpack.cc:211
+msgid "lossy (hybrid)"
+msgstr ""
+
+#: src/wavpack/wavpack.cc:213
+msgid "lossy"
+msgstr ""
+
+#: src/wavpack/wavpack.cc:255
+msgid ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Some of the plugin code was by Miles Egan."
+msgstr ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Enkele regels code van de plugin zijn door Miles Egan."
+
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
+msgstr "2SF Decoder"
+
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF Configuratie</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Negeer de lengte van het bestand"
+
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr ""
diff --git a/po/pl.po b/po/pl.po
index 81bc8383ad7f..bf131d5bba33 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -3,27 +3,29 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# CH <259095+transifex at gmail.com>, 2012
-# CH <259095+transifex at gmail.com>, 2012
+# Chris <259095+transifex at gmail.com>, 2012
+# Chris <259095+transifex at gmail.com>, 2012
+# Chris <259095+transifex at gmail.com>, 2012
 # felikstayson <felikstayson at o2.pl>, 2012
 # felikstayson <felikstayson at o2.pl>, 2012
 # mkkot <marcin2006 at gmail.com>, 2013
-# mgrvnwald <marco at mgrvnwald.com>, 2013
-# mgrvnwald <marco at mgrvnwald.com>, 2013
-# mgrvnwald <marco at mgrvnwald.com>, 2013
+# Marco Oliver Grunwald <m at mgrvnwald.com>, 2013
+# Marco Oliver Grunwald <m at mgrvnwald.com>, 2013
+# Marco Oliver Grunwald <m at mgrvnwald.com>, 2013
 # mkkot <marcin2006 at gmail.com>, 2013-2014
 # Piotr Sokół <psokol at jabster.pl>, 2012
+# Piotr Strębski <strebski at o2.pl>, 2014-2015
 # Szymon Weihs <sz.weihs at gmail.com>, 2011
 # Szymon Weihs <sz.weihs at gmail.com>, 2011-2012
-# vojcek <vojcek at tlen.pl>, 2013
-# vojcek <vojcek at tlen.pl>, 2013
+# Wojciech Myrda <vojcek at tlen.pl>, 2013
+# Wojciech Myrda <vojcek at tlen.pl>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 12:12+0000\n"
+"Last-Translator: Piotr Strębski <strebski at o2.pl>\n"
 "Language-Team: Polish (http://www.transifex.com/projects/p/audacious/"
 "language/pl/)\n"
 "Language: pl\n"
@@ -33,40 +35,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
 "|| n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "Dźwięk przestrzenny"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Dekoder AAC (MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Dekoder AAC (surowe dane)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Odtwarzacz AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sekwencjonowane"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Odtwarzacz AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Ustaw alarm..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -75,11 +65,7 @@ msgstr ""
 "Wtyczka do zaplanowania odtwarzania w określonym czasie.\n"
 "Pierwotni autorzy: Adam Feakin i Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -121,7 +107,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -161,7 +147,7 @@ msgstr ""
 "    Uruchom tÄ… komendÄ™ podczas alarmu.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -185,383 +171,390 @@ msgstr ""
 "    Wpisz informację do wyświetlenia przy alarmie\n"
 "    oraz zaznacz przycisk gdy chcesz by się ukazała."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "To jest twój sygnał budzenia."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Twoje przypomnienie na dzisiaj to..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Przypominacz"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Poniedziałek"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Wtorek"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Åšroda"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Czwartek"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "PiÄ…tek"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sobota"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Niedziela"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Ustawienia alarmu"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_OK"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Anuluj"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Czas"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Domyślnie alarm o:"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "[hh:mm]"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Wyciszenie po:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "godziny"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minuty"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Wybierz dni, w których alarm będzie aktywny"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Dzień"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Domyślny"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dni"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Czas przejścia"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekundy"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Głośność"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "PoczÄ…tkowa"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Końcowa"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Bieżąca"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Dodatkowe polecenie"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "włącz"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista odtwarzania (opcjonalnie)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Wybierz listÄ™ odtwarzania"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Ustawienia"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Co oznaczajÄ… te ustawienia?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Pomoc"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
-msgstr "Okładka Albumu"
+msgstr "Okładka albumu"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Okładka albumu (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Wyjście ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Wtyczka wyjścia ALSY dla Audaciousa\n"
+"Prawa autorskie: 2009-2012 John Lindgren\n"
+"\n"
+"Podziękowania kieruję do Williama Pitcocka, autora ALSA Output Plugin NG, "
+"którego kod służył za odniesienie, gdy podręcznik ALSY nie wystarczał."
 
-#: src/alsa/config.c:210
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(brak opisu)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Domyślne urządzenie PCM"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Domyślne urządzenie miksera"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "UrzÄ…dzenie PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "UrzÄ…dzenie miksera:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Element miksera:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Obejdź rozłączenie"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Odtwarzacz MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modułowy odtwarzacz MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (Odtwarzacz MIDI)"
+"autorstwa Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"szczególne podziękowania kieruję do:\n"
+"\n"
+"Clemensa Ladischa and Jaroslava Kysela\n"
+"za ich świetne programy aplaymidi i amixer; były one\n"
+"naprawdę pomocne wraz z alsa-lib docs, które przydały się\n"
+"do nauki ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"za logo klawiatury MIDI\n"
+"\n"
+"Tony'ego Vroona\n"
+"za pomoc w testowaniu wersji alfa"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Zmień domyślną głośność:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Zmień domyślną polifonię:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Zmień domyślne echo:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "WÅ‚Ä…czone"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Zmień domyślny chorus:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Odtwarzanie</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Przesunięcie:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "półtony"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Przesunięcie perkusji:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Zaawansowane</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "numery nut"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Wydobądź komentarze z pliku MIDI"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Przeskocz ciszÄ™ na wprowadzeniu"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Wydobądź słowa z pliku MIDI"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Przeskocz ciszę na zakończeniu"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>Czcionka</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Syntezator</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "Częstotliwość próbkowania:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - wybierz plik czcionki"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Anuluj"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Otwórz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nazwa pliku"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Wielkość (w bajtach)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nazwa:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
-msgstr "<span size=\"smaller\"> Info MIDI </span>"
+msgstr "<span size=\"smaller\"> Informacje MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Format:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Długość (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Liczba utworów:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "zmienna"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "Uderzenia na minutÄ™:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "Uderzenia na minutę (średnia ważona):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Podział czasu:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Komentarze i teksty utworów MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* brak dostępnych komentarzy w tym pliku MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* brak dostępnych tekstów utworów w tym pliku MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Zamknij"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (niepoprawne kodowanie UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "O Pluginie AMIDI"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"odtwarzacz modularny muzyki MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"napisany przez Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"specjalne podziękowania dla...\n"
-"\n"
-"Clemens Ladisch i Jaroslav Kysela\n"
-"za ich wspaniałe programy aplaymidi i amixer; były bardzo pomocne wraz "
-"dokumentacją alsa-lib, która pozwoliła dowiedzieć się więcej o ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"za loga klawiatur midi\n"
-"\n"
-"Tony Vroon\n"
-"za pomoc przy testowaniu wersji alpha"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -579,152 +572,149 @@ msgstr ""
 "Wykorzystano fragmenty kodu biblioteki Ghosd Evana Martina:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (informacja ekranowa)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "ProstokÄ…t"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "ZaokrÄ…glony prostokÄ…t"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Wklęsły prostokąt"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Brak"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Rozpocznij odtwarzanie"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr ""
 "Wyświetla informację ekranową po zmianie pozycji na liście odtwarzania."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Zmiana tytułu"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Wyświetla informację ekranową po zmianie tytułu ścieżki, bez zmiany "
-"odtwarzanego pliku. Użyteczne podczas odtwarzania strumieni internetowych."
+"Wyzwala OSD, gdy następuje zmiana tytułu piosenki (dla strumieniowania "
+"internetowego)"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Wstrzymaj"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Wyświetla informację ekranową po wstrzymaniu odtwarzania."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Wznów"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Wyświetla informację ekranową po wznowieniu odtwarzania."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Rozmieszczenie"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Przesunięcie wzdłuż osi X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Przesunięcie wzdłuż osi Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maksymalna szerokość informacji:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Wiele ekranów"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Wyświetlanie informacji ekranowej na:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "wszystkie ekrany"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "ekran %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Czas (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Wyświetlanie:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Pojawianie siÄ™:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Zanikanie:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Czcionki"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Czcionka %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Cień"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Kształt"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Kolory"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Kolor %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "WÅ‚Ä…czenie"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Zdarzenia"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Wykryto menedżer okien obsługujący kompozycje"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -734,114 +724,114 @@ msgstr ""
 "Aby menu ekranowe było wyświetlanie prawidłowo, należy uruchomić menedżer "
 "okien obsługujący kompozycje (np. Compiz)."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 "Menedżer okien obsługujący kompozycje nie jest wymagany dla udawanej "
 "przezroczystości"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Przezroczystość"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Udawana przeźroczystość"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Prawdziwa przezroczystość (wymaga rozszerzenia X Composite)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Nie wczytano rozszerzenia kompozycji"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Rozszerzenie kompozycji jest niedostępne"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Ustawienia menu ekranowego Audacious"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Przetestuj"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Ustaw"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Pozycja"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animacja"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Tekst"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Obramowanie"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Wyzwalanie"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Różne"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Przetestuj"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "Lista odtwarzania ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listy odtwarzania ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listy odtwarzania Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Kolor</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Rozmyty zakres"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Profile ustawień:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Poziom sygnału wejściowego:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Częstotliwość obcięcia:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Profile ustawień:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analizator spektrum"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Wtyczka Audio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -852,178 +842,168 @@ msgid ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 msgstr ""
-"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
-"Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/> and "
-"to libcddb developers <http://libcddb.sourceforge.net/>.\n"
+"Prawa autorskie: (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> i inni.\n"
+"\n"
+"Podziękowania kieruję do programistów libcdio <http://www.gnu.org/software/"
+"libcdio/>\n"
+"oraz libcddb <http://libcddb.sourceforge.net/>.\n"
 "\n"
-"Also thank you to Tony Vroon for mentoring and guiding me. This was a Google "
-"Summer of Code 2007 project."
+"Dziękuję także Tony'emu Vroonowi za opiekę i wskazówki.\n"
+"\n"
+"Zrealizowano w ramach programu Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>UrzÄ…dzenie</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Prędkość odczytu:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "ZastÄ…p urzÄ…dzenie:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadane</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Użyj CD-Tekstu"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Użyj CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Używanie protokołu HTTP zamiast CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Serwer:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Ścieżka:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Wtyczka Audio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Nie udało się zainicjalizować podsystemu cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Nieprawidłowy URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Ścieżka %d nie znaleziona."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Ścieżka %d jest ścieżką danych."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Nie udało się otworzyć wyjścia audio."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Wystąpił błąd przy odczycie płyty CD Audio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Ścieżka %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Nie udało się otworzyć urządzenia CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Nie znaleziono napędu CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Nie udało się zainicjalizować otwarcia napędu CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Nie udało się odzyskać pierwszego/ostatniego numeru ścieżki."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Nie mogę odczytać LSN początku/końca ścieżki %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Nie udało się połączyć z cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Nie udało się uzyskać odpowiedzi z serwera cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Nie udało się uzyskać odpowiedzi z serwera cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Nie udało się odczytać informacji z cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Brak płyty w napędzie."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nieobsługiwany rodzaj płyty."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Pozycje menu Audio CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Odtwórz płytę CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Dodaj płytę CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Pozycje menu Audio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Kompresja</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centralna głośność:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Zakres dynamiki:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Wtyczka kompresora zakresu dynamicznego dla Audacious\n"
+"Prawa autorskie 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Kompresor zakresu dynamicznego"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1032,216 +1012,249 @@ msgid ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
-"Console music decoder engine based on Game_Music_Emu 0.5.2\n"
-"Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"Odtwarzacz muzyki z konsol do gier bazowany na Game_Music_Emu 0.5.2\n"
+"Obsługiwane formaty: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
 "\n"
-"Audacious plugin by:\n"
+"Wtyczka dla Audaciousa:\n"
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Basy:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Soprany:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Echo:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Domyślny czas trwania ścieżki:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 "<b>Konwersja częstotliwości\n"
 "próbkowania</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "WÅ‚Ä…czenie"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Częstotliwość:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorowanie czasu trwania w etykietach SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Zwiększenie pogłosu"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Dekoder muzyki z konsol gier"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Przenikanie ścieżek zawiodło, ponieważ piosenki miały różną liczbę kanałów. "
-"Możesz użyć Miksera kanałów, by przekonwertować piosenki do tej samej liczby "
-"kanałów."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Wyjście CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Wtyczka przenikania ścieżek zawiodła, gdyż utwory posiadają różną "
-"częstotliwość próbkowania. Możesz użyć konwertera częstotliwości "
-"próbkowania, aby sprowadzić utwory do tej samej częstotliwości."
+"Wtyczka wyjście CoreAudio dla Audacious\n"
+"Prawa autorskie 2014 William Pitcock\n"
+"\n"
+"Oparta na wtyczce wyjścia SDL dla Audacious\n"
+"Prawa autorskie 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Użyj trybu wyłączności"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Przenikanie ścieżek dla Audaciousa\n"
-"Prawa autorskie 2010-2012 John Lindgren"
+"Wtyczka przenikania ścieżek dla Audacious\n"
+"Prawa autorskie 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Przenikanie ścieżek</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Przy automatycznej zmianie piosenki"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Nakładanie się:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Przy wyszukiwaniu lub ręcznej zmianie piosenki"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Podpowiedź</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Dla lepszego przenikania ścieżek, \n"
+"włącz efekt usuwania ciszy."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Przenikanie ścieżek"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Przenikanie ścieżek zawiodło, ponieważ piosenki miały różną liczbę kanałów. "
+"Możesz użyć Miksera kanałów, by przekonwertować piosenki do tej samej liczby "
+"kanałów."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Wtyczka przenikania ścieżek zawiodła, gdyż utwory posiadają różną "
+"częstotliwość próbkowania. Możesz użyć konwertera częstotliwości "
+"próbkowania, aby sprowadzić utwory do tej samej częstotliwości."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Krystaliczność</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensywność:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Krystalizator"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Wtyczka Cue Sheet"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Usuń pliki"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Nie udało się przenieść %s do kosza: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Nie udało się usunąć %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Nie udało się usunąć %s: to nie jest plik lokalny."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Czy chcesz usunąć zaznaczone pliki do kosza?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Przesuń do kosza"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Czy chcesz całkowicie usunąć zaznaczone pliki?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Usuń"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Anuluj"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Usuń pliki"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Usuń zaznaczone pliki"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Sposób usuwania</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Przesuń do kosza zamiast kasować"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Wtyczka echa\n"
+"Autor: Johan Levin, 1999\n"
+"OtaczajÄ…ce echo autorstwa Carla van Schaika, 1999\n"
+"Zaktualizowano dla potrzeb Audacious przez Williama Pitcocka i Johna "
+"Lindgrena, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Echo</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Opóźnienie:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Sprzężenie zwrotne:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Głośność:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Wtyczka echa\n"
-"Autor: Johan Levin, 1999\n"
-"\n"
-"Przestrzenne echo, autor: Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Echo"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Wtyczka FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1257,55 +1270,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Wtyczka FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Zapis do pliku"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Format pliku wyjściowego:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Konfiguruj"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Zapisywanie w pierwotnym położeniu"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Zapisywanie we własnym położeniu"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Położenie pliku docelowego:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Wybór katalogu"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Uzyskanie nazwy pliku z:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Utwórz nazwę pliku z:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "załączonych etykiet"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Pierwotny znacznik pliku"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nazwy pliku"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Pierwotna nazwa pliku"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Pozostawienie rozszerzenia nazwy pierwotnego pliku"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Dołączenie rozszerzenia pierwotnej nazwy pliku"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Dodanie do nazwy pliku numer ścieżki"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Dodanie do nazwy pliku numeru ścieżki"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1322,205 +1335,219 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"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"
+"Niniejszy program jest wolnym oprogramowaniem; możesz go \n"
+"rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej\n"
+"Licencji Publicznej GNU, wydanej przez FundacjÄ™ Wolnego\n"
+"Oprogramowania - według wersji 2-giej tej Licencji lub którejś\n"
+"z późniejszych wersji.\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"
+"Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on \n"
+"użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej \n"
+"gwarancji PRZYDATNOÅšCI HANDLOWEJ albo PRZYDATNOÅšCI DO OKREÅšLONYCH \n"
+"ZASTOSOWAŃ. W celu uzyskania bliższych informacji - Powszechna \n"
+"Licencja Publiczna GNU.\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."
-
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Wtyczka FileWriter"
+"Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz \n"
+"Powszechnej Licencji Publicznej GNU (GNU General Public License);\n"
+"jeśli nie - napisz do Free Software Foundation, Inc., 51 Franklin Street, "
+"Fifth Floor, Boston, MA 02110-1301,\n"
+"USA."
 
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automatycznie"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Połączone stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Konfiguracja kodera MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Jakość algorytmu:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "Wyjściowa częstotliwość próbkowania:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Tempo transmisji/współczynnik kompresji:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Tempo bitowe / współczynnik kompresji:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Tempo transmisji (kb/s):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Współczynnik kompresji:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Kanały:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Różne:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "Wymuszenie ścisłej zgodności z ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Zabezpieczenie przed błędami"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Jakość"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "WÅ‚Ä…czenie"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
-msgstr "Typ:"
+msgstr "Rodzaj:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Zmienne tempo transmisji (VBR):"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Minimalna wartość (kb/s):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Maksymalna wartość (kb/s):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Wymuszenie wartości minimalnej"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Åšrednie tempo transmisji (ABR):"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Średnia wartość (kb/s):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Jakość algorytmu VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Pominięcie zapisywania nagłówka Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Pominięcie nagłówka Xing VBR"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Parametry klatek:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Oznaczenie prawem autorskim"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Oznaczenie jako oryginalne"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parametry ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Wymuś dodawanie tagów wersji 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Dodawanie tagów tylko wersji 1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Dodawanie tagów tylko wersji 2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
-msgstr "Tagi"
+msgstr "Znaczniki"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Konfiguracja kodera Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Jakość (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Dekoder FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "bezstratna"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
-"Original code by Ralf Ertzinger <ralf at skytale.net>\n"
+"Oryginalny kod autorstwa\n"
+"Ralfa Ertzingera <ralf at skytale.net>\n"
+"\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Dekoder FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
-"Wtyczka GIO Audaciousa\n"
-"Copyright 2009-2012 John Lindgren"
+"Wtyczka GIO dla Audaciousa\n"
+"Prawa autorskie 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Wtyczka GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Tryb odczytu i dołączania nie jest obsługiwany"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Nieprawidłowy tryb otwierania"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1540,448 +1567,522 @@ msgstr ""
 "\n"
 "Licencja: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analizator spektrum OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"GIO Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren"
+"Analizator spektrum OpenGL dla Audaciousa\n"
+"Prawa autorskie: 2013 Christophe Budé, John Lindgren i Carlo Bramini\n"
+"Prawa autorskie 2014 William Pitcock\n"
+"\n"
+"Na podstawie wtyczki XMMS-a:\n"
+"Prawa autorskie 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas "
+"Nilsson i 4Front Technologies\n"
+"\n"
+"Licencja: GPL wersja 2 i późniejsze"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Skróty Gnome"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analizator spektrum OpenGL (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Skróty GNOME"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"Wtyczka skrótów GNOME\n"
+"Umożliwia obsługę odtwarzacza za pomocą skrótów GNOME.\n"
+"\n"
+"Prawa autorskie (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Numer porzÄ…dkowy"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Tytuł"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Wykonawca"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Rok"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artysta albumu"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Numer ścieżki"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Gatunek"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Pozycja w kolejce"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Czas trwania"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Położenie pliku"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nazwa pliku"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Własny tytuł (z ustawień)"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Tempo transmisji"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Dostępne kolumny"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Wyświetlane kolumny"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Narzędzie wyszukiwania"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Zaczep po lewej"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Zaczep po prawej"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Zaczep na górze"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Zaczep na dole"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Odczep"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Wyłącz"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Narzędzie wyszukiwania"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Otwórz pliki ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Otwórz adres _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Dodaj pliki ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Dodaj adres U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "_Wyszukaj w bibliotece"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "O _programie ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Ustawienia"
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "Za_kończ"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Odtwarzaj"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Wstrzymaj"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Zatrzymaj"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "P_oprzednie"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Następne"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Powta_rzanie"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Losowo"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Odtwarzaj _pojedynczo"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Z_atrzymaj odtwarzanie po tym utworze"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informacje o ścieżce..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Przejdź do _czasu..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Przejdź do ścież_ki..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Ustaw punkt początkowy pętli"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Ustaw punkt końcowy pętli"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Resetuj punkty graniczne pętli"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "według _tytułu"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "według _nazwy pliku"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Według _nazwy pliku"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "według ścieżki _pliku"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "według _numeru ścieżki"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "według _wykonawcy"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "według al_bumu"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "według wykonawcy albu_mu"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
-msgstr "według _daty wydania"
+msgstr "według daty w_ydania"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Według _gatunku"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "według _długości"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "według p_ołożenia pliku"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "według wła_snego tytułu"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_Odwróć kolejność"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Wy_losuj kolejność"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Odtwórz listę odtwarzania"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Odtwórz/Ponów"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Wczytaj ponownie"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Sortuj"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Sortuj _wybrane"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Usuń _duplikaty"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "_Usuń niedostępne pliki"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nowa"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Z_mień nazwę..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "_Usuń"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importuj..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Eksportuj..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Menedżer _listy odtwarzania..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Menedżer _kolejki..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Z_większ głośność"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Z_mniejsz głośność"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Korektor graficzny"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "E_fekty..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Pasek _menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Pasek _informacji"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Pokaż pasek wiz_ualizacji"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Pokaż pasek _stanu"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Pokaż _pozostały czas"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Wizualizacje"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Plik"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "Odt_warzanie"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "W_tyczki"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Dźwięk"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Widok"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Dodaj/usuń kolejkę"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Otwórz katalog zawierający"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Wytnij"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "K_opiuj"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "Wk_lej"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_Zaznacz wszystko"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Z_mień nazwę ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Karty listy odtwarzania</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Zawsze pokazuj karty"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Pokaż statystykę nagrań"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Pokaż przyciski zamykania"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Kolumny listy odtwarzania</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Pokaż nagłówki listy odtwarzania"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Różne</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Przyciski strzałki przesuwają o:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Przewiń przy zmianie piosenki"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interfejs GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Buforowanie ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1989,84 +2090,98 @@ msgstr[0] "%d kanał"
 msgstr[1] "%d kanały"
 msgstr[2] "%d kanałów"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kb/s"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Tryb prosty."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Tryb listy odtwarzania."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Zatrzymaj po tym utworze."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Poprzedni utwór"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Odtwarzaj"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Wstrzymaj/wznów"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Zatrzymaj"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Następny utwór"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Przewiń o 5 sekund do przodu"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Przewiń o 5 sekund do tyłu"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Wyciszenie dźwięku"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Zwiększ głośność"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Zmniejsz głośność"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Przejdź do pliku"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Przełącz okno(a) odtwarzacza"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Pokaż menu ekranowe"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Włącz/Wyłącz powtarzanie"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Włącz/Wyłącz odtwaranie losowe"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Zatrzymanie po bieżącej ścieżce"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Przesuń na wierzch okno(a) odtwarzacza"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(brak)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2078,15 +2193,11 @@ msgstr ""
 "\n"
 "Kontynuować?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Przyciski dowiązań myszy"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Ustawienia wtyczki Global Hotkey"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2094,23 +2205,27 @@ msgstr ""
 "Proszę wcisnąć kombinację klawiszy wewnątrz pola\n"
 "tekstowego. Można również użyć przycisków myszy."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Skróty klawiszowe:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Czynność:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Kombinacja klawiszy:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Dodaj"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globalne skróty klawiszowe"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2124,7 +2239,7 @@ msgid ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
-"Globalne skróty klawiszowe\n"
+"Wtyczka globalnych skrótów klawiszowych\n"
 "Steruj odtwarzaniem przy użyciu globalnych skrótów klawiszowych lub "
 "przycisków multimedialnych.\n"
 "\n"
@@ -2137,59 +2252,56 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globalne skróty klawiszowe"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Wyjście JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Podłącz się do wszystkich dostępnych portów jacka"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Automatycznie połącz z portami wyjścia"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Podłącz się tylko do portów wyjściowych"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Odnaleziono tylko %d portów wyjścia JACK, ale wymaganych jest %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Nie podłączaj się do portów"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Wystąpił błąd przy połączeniu z portem JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Tryb podłączenia"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK obsługuje tylko dźwięk zmiennoprzecinkowy. Musisz zmienić rozdzielczość "
+"bitową w ustawieniach dźwięku Audaciousa na tryb zmiennopozycyjny."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Włącz wyjście błędów"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Wystąpił błąd przy połączeniu z serwerem JACK. Czy jest uruchomiony?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Napisano na podstawie xmms-jack, prawa autorskie Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"Port dla Audaciousa: Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK"
+"Serwer JACK wymaga częstotliwości próbkowania %d HZ, a Audacious odtwarza %d "
+"Hz. Użyj proszę Konwertera częstotliwości próbkowania (wtyczki) aby usunąć "
+"niezgodność."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Ustawienia %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Ustawienia wtyczki LADSPA Host"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Położenia modułów:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2200,82 +2312,41 @@ msgstr ""
 "Po dodaniu nowych ścieżek proszę wcisnąć Enter, aby wyszukać nowe wtyczki.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Dostępne wtyczki:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "WÅ‚Ä…cz"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "WÅ‚Ä…czone wtyczki:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ustawienia"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
-"LADSPA Host for Audacious\n"
-"Copyright 2011 John Lindgren"
+"Serwer LADSPA dla Audacious\n"
+"Prawa autorskie 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
-msgstr "Host LADSPA"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-"%s: nie można zainicjować wsparcia LIRC\n"
-"\n"
-"\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: nie udało się odczytać pliku konfiguracji LIRC\n"
-" %s: proszę przeczytać dokumentację LIRC\n"
-" %s: jak stworzyć prawidłowy plik konfiguracji\n"
-"\n"
-"\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-"%s: próba ponownego podłączenia...\n"
-"\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr ""
-"%s: nienzana komenda \"%s\"\n"
-"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: rozłączono z LIRC\n"
+msgstr "Serwer LADSPA"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: próbuj ponownie połączyć co %d sekund...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Wtyczka LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2290,85 +2361,95 @@ msgid ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
-"A simple plugin to control Audacious using the LIRC remote control daemon\n"
-"Adapted for Audacious by: \n"
+"Prosta wtyczka do kontroli Audaciousa za pomocÄ… demona zdalnej kontroli "
+"LIRC.\n"
+"\n"
+"Port na Audaciousa:\n"
 "Tony Vroon <chainsaw at gentoo.org>\n"
 "Joonas Harjumäki <jharjuma at gmail.com>\n"
 "\n"
-"Based on the XMMS LIRC plugin by: \n"
+"Stworzono na podstawie wtyczki LIRC dla XMMS-a autorstwa:\n"
 "Carl van Schaik <carl at leg.uct.ac.za>\n"
 "Christoph Bartelmus <xmms at bartelmus.de>\n"
 "Andrew O. Shadoura <bugzilla at tut.by>\n"
 "\n"
-"For more information about LIRC, see http://lirc.org."
+"Więcej informacji LIRC-u, znajdziesz na stronie: http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Połącznenie</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Podłącz ponownie do serwera LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Odczekaj przed ponownym połączeniem:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Wtyczka LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Wtyczka LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Nie znaleziono tekstu piosenki"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "BÅ‚Ä…d"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Nie można pobrać %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "BÅ‚Ä…d"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Nie można odczytać %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Szukanie tekstu piosenk i ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "BrakujÄ…ce metadane utworu"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Łączenie z lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Wtyczka LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Wtyczka LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Lista odtwarzania M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Generator taktu"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
-msgstr "Generator taktu: %d bpm"
+msgstr "Generator taktu: %d uderzeń na minutę"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generator taktu: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2376,169 +2457,204 @@ msgid ""
 "e.g. tact://77 to play 77 beats per minute\n"
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
-"A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
+"Generator taktu autorstwa Martina Straussa <mys at faveve.uni-stuttgart.de>\n"
 "\n"
-"To use it, add a URL: tact://beats*num/den e.g. tact://77 to play 77 beats "
-"per minute or tact://60*3/4 to play 60 bpm in 3/4 tacts"
+"Instrukcja: wprowadź adres URL: tact://uderzenia*liczba jednostek "
+"metrycznych/jednostka metryczna\n"
+"na przykład tact://77 aby wygenerować 77 uderzeń na minutę\n"
+"lub tact://60*3/4 aby wygenerować 60 uderzeń na minutę w metrum 3/4."
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generator taktu"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Mikser kanałów"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
-"Channel Mixer Plugin for Audacious\n"
-"Copyright 2011-2012 John Lindgren and Michał Lipski"
+"Wtyczka miksera kanałów dla Audacious\n"
+"Prawa autorskie 2011-2012 John Lindgren i Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Mikser kanałów</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Ilość kanałów wyjściowych:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Mikser kanałów"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Wtyczka MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Błąd połączenia z serwerem MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (odtwarzacz modułów)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Rozdzielczość bitowa</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8 bitów"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16 bitów"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Kanały</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Najbliższa (najszybsza)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Liniowa (szybka)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Krzywa (dobra)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Przesunięcie fazowe (najlepsza)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Częstotliwość próbkowania</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Poziom:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Odcięcie:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Echo</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Podbicie basów</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Dźwięk przestrzenny</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Przedwzmacniacz</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Próbkowanie nadmiarowe"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Redukcja szumów"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Odtwórz MOD-y Amigi"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Powtórz</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Ilość powtórzeń:"
 
-#: src/modplug/plugin_main.c:141
-msgid "To repeat forever, set the repeat count to -1."
-msgstr "By powtarzać bez końca ustaw -1."
+#: src/modplug/plugin_main.cc:112
+msgid "To repeat forever, set the repeat count to -1."
+msgstr "By powtarzać bez końca ustaw -1."
+
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
+"Poniższe ustawienia zostaną wprowadzone w życie po restarcie Audaciousa."
+
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
+msgstr "Wtyczka MPG123"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Zaawansowane</b>"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (odtwarzacz modułów)"
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Użyj dokładnego obliczania długości (wolne)"
 
-#: src/mpg123/mpg123.c:210
+#: src/mpg123/mpg123.cc:248
 msgid "Surround"
 msgstr "Dźwięk przestrzenny"
 
-#: src/mpg123/mpg123.c:412
-msgid "MPG123 Plugin"
-msgstr "Wtyczka MPG123"
-
-#: src/mpris2/plugin.c:403
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Serwer MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Wtyczka Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "BÅ‚Ä…d przetwarzania przekierowania"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Nieznany błąd HTTP"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "BÅ‚Ä…d przetwarzania adresu URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Za dużo przekierowań"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Zatrzymany"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious nie odtwarza."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Powiadomienia na pulpicie"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2557,9 +2673,9 @@ msgid ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
-"Wtyczka powiadomień pulpitowych Audaciousa\n"
+"Wtyczka powiadomień pulpitowych dla Audaciousa\n"
 "Prawa autorskie (C) 2010: Maximilian Bogner\n"
-"Prawa autorskie (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès "
+"Prawa autorskie (C) 2011-2013 John Lindgren i Jean-Alexandre Anglès "
 "d'Auriac\n"
 "\n"
 "Niniejsza wtyczka jest wolnym oprogramowaniem; można ją rozprowadzać dalej i/"
@@ -2576,55 +2692,64 @@ msgstr ""
 "Publicznej GNU (GNU General Public License); jeśli nie, odwiedź <http://www."
 "gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Pokaż kontrolki odtwarzania"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Zawsze pokazuj powiadomienia"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Powiadomienia na pulpicie"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Dołącz nazwę albumu do powiadomienia"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Pokaż"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Wstrzymaj"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Następne"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Domyślne urządzenie"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Wyjście OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Wyjście OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Domyślne urządzenie"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Urządzenie dźwiękowe:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Użyj alternatywnego urządzenia:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Zapisz poziom głośności."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "WÅ‚Ä…cz konwersje formatu poprzez oprogramowanie OSS"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Włącz tryb wyłączności, aby wyłączyć programowe miksowanie."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2632,25 +2757,42 @@ msgid ""
 "I would like to thank people on #audacious, especially Tony Vroon and John "
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
-"OSS4 Output Plugin for Audacious\n"
-"Copyright 2010-2012 Michał Lipski\n"
+"Wtyczka wyjścia OSS4 dla Audaciousa Prawa autorskie: 2010-2012 Michał "
+"Lipski\n"
 "\n"
-"I would like to thank people on #audacious, especially Tony Vroon and John "
-"Lindgren and of course the authors of the previous OSS plugin."
+"Chciałbym wyrazić wdzięczność bywalcom kanału #audacious, szczególnie "
+"Tony'emu Vroonowi oraz Johnowi Lindgrenowi, a także, naturalnie, autorom "
+"poprzedniej wtyczki OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Menedżer list odtwarzania"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Wpisy"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Usuń"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Zmień nazwę"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listy odtwarzania PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Dekoder OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Wyjście PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2669,121 +2811,197 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"Audacious PulseAudio Output Plugin\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"
-"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"
-"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"
+"Wtyczka wyjścia PulseAudio dla Audaciousa\n"
+"Niniejszy program jest wolnym oprogramowaniem; możesz go\n"
+"rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej\n"
+"Licencji Publicznej GNU, wydanej przez FundacjÄ™ Wolnego\n"
+"Oprogramowania - według wersji 2-giej tej Licencji lub którejś\n"
+"z późniejszych wersji. \n"
+"\n"
+"Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on \n"
+"użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej \n"
+"gwarancji PRZYDATNOÅšCI HANDLOWEJ albo PRZYDATNOÅšCI DO OKREÅšLONYCH \n"
+"ZASTOSOWAŃ. W celu uzyskania bliższych informacji - Powszechna \n"
+"Licencja Publiczna GNU. \n"
+"\n"
+"Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz \n"
+"Powszechnej Licencji Publicznej GNU (GNU General Public License);\n"
+"jeśli nie - napisz do Free Software Foundation, Inc., 51 Franklin Street, "
+"Fifth Floor, Boston, MA 02110-1301,\n"
+"USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Wyjście QtMultimedia"
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
 msgid ""
-"Sample Rate Converter Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
+"Wtyczka wyjścia dźwiękowego QtMultimedia dla Audacious\n"
+"Prawa autorskie 2014 William Pitcock\n"
+"\n"
+"Oparta na wtyczce wyjścia SDL dla Audacious\n"
+"Prawa autorskie 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Działanie..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Szukaj"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Otwórz katalog..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Dodaj katalog..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Dziennik programu"
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Otwórz pliki"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Dodaj pliki"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Poprzednie"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Powtarzaj"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Losowa kolejność"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interfejs Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Konwerter częstotliwości próbkowania"
+
+#: src/resample/resample.cc:183
+msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
+msgstr ""
+"Wtyczka konwertera częstotliwości próbkowania dla Audacious\n"
+"Prawa autorskie 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Pomiń/powtórz próbki"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Liniowa interpolacja"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Szybka interpolacja funkcji sinc"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Pośrednia interpolacja funkcji sinc"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Najlepsza interpolacja funkcji sinc"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Konwersja</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metoda:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Klasa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapowanie klasy</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Użyj klasy mapowania"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Konwerter częstotliwości próbkowania"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK, Scrobblowanie dla użytkownika: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Brak zezwolenia"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "Użyj tego linku by zezwolić Audacious na scrobblowanie twoich utworów."
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "Pozostaw to okno otwarte i naciśnij ponownie 'Sprawdź Uprawnienia'.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2792,43 +3010,47 @@ msgstr ""
 "Będą przekazane do Audacious tak szybko jak tylko będzie miał na to "
 "pozwolenie."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
-msgstr "Problem sieciowy."
+msgstr "Problem z sieciÄ…."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Wystąpił problem przy skontaktowaniu się z Last.fm. Proszę spróbuj ponownie."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Sprawdzanie..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "S_prawdź zezwolenia"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "U_nieważnij pozwolenia"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Musisz zezwolić Audacious na scrobblowanie utworów do twojego konta Last."
 "fm.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
-"Plugin Scrobbler nie mógł zostać uruchomiony.\n"
-"Prawdopodobnie ma miejsce problem z twojÄ… instalacjÄ…."
+"Wtyczka Scrobbler nie mogła zostać uruchomiona.\n"
+"Prawdopodobnie wystąpił problem z Twoją instalacją."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2838,18 +3060,14 @@ msgid ""
 "project.\n"
 "\n"
 msgstr ""
-"Plugin Scrobbler dla Audacious 2.0 przez Pitxyoki,\n"
+"Wtyczka Scrobbler dla Audacious 2.0, przez Pitxyoki,\n"
 "\n"
-"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"Prawa autorskie © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
 "\n"
-"Podziękowania dla John Lindgren za wsparcie a początku projektu.\n"
+"Podziękowania dla John Lindgren za wsparcie na początku projektu.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2857,96 +3075,71 @@ msgstr ""
 "Audacious używa obecnie poprawionej wersji Scrobblera Last.fm.\n"
 "Proszę sprawdź ustawienia dla wtyczki Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Wyjście SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
-"SDL Output Plugin for Audacious\n"
-"Copyright 2010 John Lindgren"
-
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL"
+"Wtyczka wyjścia SDL dla Audacious\n"
+"Prawa autorskie 2010 John Lindgren"
 
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteka"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Nieznany artysta"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Nieznany album"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" na %s przez %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d wynik"
+msgstr[1] "%d wyniki"
+msgstr[2] "%d wyników"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d albumy"
-msgstr[2] "%d albumów"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d ukryty)"
+msgstr[1] "(%d ukryte)"
+msgstr[2] "(%d ukrytych)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d piosenka"
-msgstr[1] ""
-"%s\n"
-" %s, %d piosenki"
-msgstr[2] ""
-"%s\n"
-" %s, %d piosenek"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d piosenka przez %s"
-msgstr[1] ""
-"%s\n"
-" %d piosenek przez %s"
-msgstr[2] ""
-"%s\n"
-" %d piosenek przez %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d piosenka"
+msgstr[1] "%d piosenki"
+msgstr[2] "%d piosenek"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "tego gatunku"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "na"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "przez"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Utwórz listę odtwarzania"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Dodaj do listy odtwarzania"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Przeszukaj bibliotekÄ™"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2954,679 +3147,771 @@ msgstr ""
 "Aby zaimportować kolekcję muzyczną, proszę wybrać katalog i kliknąć przycisk "
 "ponownego wczytywania."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Proszę czekać ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Wybierz katalog"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Odtwarzacz SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Wyjście</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Kanały:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulacja</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emuluj MOS 8580 (domyślnie: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Nie wybieraj automatycznie modela czipu"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emuluj filtr"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Taktowanie zegara:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Nie wybieraj automatycznie taktowania zegara"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Czas odtwarzania</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Ustaw najdłuższy czas odtwarzania:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Użyj tylko, jeśli długość piosenki jest nieznana"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Ustaw najkrótszy czas odtwarzania:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Tony pośrednie</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Włącz tony pośrednie"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Pomijaj tony pośrednie krótsze niż:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Uwaga</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Usuwanie ciszy"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Wtyczka usuwania ciszy dla Audacious\n"
+"Prawa autorskie 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Usuwanie ciszy</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Próg:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Otwórz pliki..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Otwórz URL..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Przeszukaj bibliotekÄ™"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Odtwarzanie"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista odtwarzania"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Widok"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Usługi"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "O..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Ustawienia..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Zakończ"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Informacje o piosence..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Powtarzaj"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Losowa kolejność"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Odtwarzaj pojedynczo"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Zatrzymaj odtwarzanie po tym utworze"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Poprzednie"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Ustaw powtarzanie od punktu A do punktu B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Usuń powtarzanie A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Przejdź do piosenki..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Przejdź do czasu..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Odtwórz tę listę odtwarzania"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Odtwórz/Ponów"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nowa lista odtwarzania"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Zmień nazwę listy odtwarzania..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Usuń listę odtwarzania"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Poprzednia lista odtwarzania"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Następna lista odtwarzania"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Importuj listÄ™ odtwarzania..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Eksportuj listÄ™ odtwarzania..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Menedżer list odtwarzania..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Menedżer kolejki..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Odśwież listę odtwarzania"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Okno listy odtwarzania"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Okno korektora graficznego"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Pokaż pozostały czas"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Zawsze na wierzchu"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Na wszystkich pulpitach"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Zwiń odtwarzacz"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Zwiń okno listy odtwarzania"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Zwiń okno korektora graficznego"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Podwójny rozmiar"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Dodaj adres URL..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Dodaj pliki..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
-msgstr "według tytułu"
+msgstr "Według tytułu"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "według nazwy pliku"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "Według nazwy pliku"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Według ścieżki dostępu"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Usuń wszystkie"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Wyczyść kolejkę"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Usuń niedostępne"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Usuń duplikaty"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Usuń niezaznaczone"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Usuń zaznaczone"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Szukaj i wybierz"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Odwróć zaznaczenie"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Wyczyść zaznaczenie"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Zaznacz wszystko"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "według albumu"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "według numeru ścieżki"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "według wykonawcy"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "według albumu"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "według wykonawcy albumu"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "według daty wydania"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "według numeru ścieżki"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Według gatunku"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Według długości"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Według własnego tytułu"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Wymieszaj listÄ™ odtwarzania"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Odwróć kolejność listy odtwarzania"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Posortuj zaznaczone"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Sortuj"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Wytnij"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
-msgstr "Skopiuj"
+msgstr "Kopiuj"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Wklej"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Przełącz kolejkę"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Wczytaj ustawienia..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Wczytaj automatyczne ustawienia"
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Wczytaj domyślne"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Wczytaj plik ustawień..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Wczytaj plik EQF..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Zapisz ustawienia..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Zapisz automatyczne ustawienia"
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Zapisz domyślne"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Zapisz plik ustawień..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Zapisz plik EQF..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Usuń ustawienia"
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Usuń automatyczne ustawienia..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Importuj ustawienia Winampa..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Wyzeruj"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Klasyczny interfejs Winampa"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Zapisz"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Wczytaj"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Wczytaj plik ustawień"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Wczytaj plik EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Zapisz plik ustawień"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Zapisz plik EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Importuj ustawienia Winampa"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Profile ustawień"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Wczytaj ustawienia"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Wczytaj automatyczne ustawienia"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Zapisz ustawienia"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Zapisz automatyczne ustawienia"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Usuń ustawienia"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Usuń automatyczne ustawienia"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "Odtwa_rzacz:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Odtwarzacz:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
-msgstr "Wybór czcionki okna odtwarzacza"
+msgstr "Wybór czcionki okna odtwarzacza:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Lista odtwarzania:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lista odtwarzania:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Wybór czcionki listy odtwarzania"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Skórka</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Czcionki</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Czcionki bitmapowe (obsługuje tylko kodowanie ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Przewijaj tytuł piosenki"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Przewijanie tytułu utworu w obydwu kierunkach"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analizator"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Zakres"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Spektogram / wskaźnik wysterowania"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Wyłączony"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Zwykły"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Ognisty"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Pionowe linie"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linie"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Kolumny"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Najwolniejszy"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Wolny"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Åšredni"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Szybki"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Najszybszy"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Kropki"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Linia"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Zwykły"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Lodowy"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Wygładzony"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Sposób</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Sposób wizualizacji:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Analizator</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Pokaż wartości szczytowe"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Kolorowanie:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Styl: "
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Upadanie:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Upadanie wartości szczytowych:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Stylistyka kształtu:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Kolor spektogramu:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Styl wskaźnika wysterowania:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Ogólne"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Wizualizacja"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Przedwzmacniacz"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Korektor graficzny Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Skocz do: %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Głośność: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Balans: %d%% lewy"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Balans: centralny"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Balans: %d%% prawy"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu opcji"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Wyłącz 'Zawsze na wierzchu'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "WÅ‚Ä…cz 'Zawsze na wierzchu'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Obszar informacji o pliku"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Wizualizacje"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Ustawiono punkt początkowy pętli."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Ustawiono punkt końcowy pętli."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Zresetowano punkty graniczne pętli."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Tryb prosty."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Tryb listy odtwarzania."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Zatrzymaj po tym utworze."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Wyszukaj wpisy w aktywnej playliście"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Szukaj"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3638,57 +3923,61 @@ msgstr ""
 "nie wiesz, jak działają wyrażenia regularne, wpisz po prostu to, czego "
 "szukasz."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Tytuł: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Tytuł:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Album:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Wykonawca: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Artysta:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nazwa pliku: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nazwa pliku:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Wyczyść poprzednie zaznaczenie przed szukaniem"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Automatycznie przełącz kolejkę dla pasujących wpisów"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Utwórz nową playlistę z pasującymi wpisami"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Edytor listy odtwarzania Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d z %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Zarchiwizowany styl programu Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Styl programu Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Nie można utworzyć katalogu (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Wtyczka Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3709,96 +3998,93 @@ msgid ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
-"Based on the xmms_sndfile plugin: Copyright (C) 2000, 2002 Erik de Castro "
-"Lopo\n"
-"Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\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"
-"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"
-"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."
-
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Wtyczka Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "O wtyczce wyjścia Sndio"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
+"Stworzono na podstawie wtyczki xmms_sndfile:\n"
+"Prawa autorskie (C) 2000, 2002 Erik de Castro Lopo\n"
 "\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Wtyczka wyjścia Sndio\n"
+"Port na Audaciousa: Tony Vroon <chainsaw at gentoo.org>\n"
 "\n"
-"Autorstwo Thomas Pfaff <tpfaff at tp76.info>\n"
-
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nieobsługiwany format pliku"
-
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
+"Niniejszy program jest wolnym oprogramowaniem; możesz go rozprowadzać dalej "
+"i/lub modyfikować na warunkach PowszechnejLicencji Publicznej GNU, wydanej "
+"przez Fundację WolnegoOprogramowania - według wersji 2-giej tej Licencji lub "
+"którejśz późniejszych wersji.\n"
 "\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Format jest nieobsługiwany przez urządzenie.\n"
+"Niniejszy program rozpowszechniany jest z nadzieją, iż będzie on użyteczny - "
+"jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji PRZYDATNOŚCI "
+"HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu uzyskania "
+"bliższych informacji - Powszechna Licencja Publiczna GNU.\n"
 "\n"
-"Spróbuj ponownie z uruchomionym serwerem sndiod(1)."
+"Z pewnością wraz z niniejszym programem otrzymałeś też egzemplarz "
+"Powszechnej Licencji Publicznej GNU (GNU General Public License);jeśli nie - "
+"napisz do Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, "
+"Boston, MA 02110-1301, USA."
+
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Wyjście Sndio"
+
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Urządzenie (puste oznacza domyślne):"
+
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Zapisz i przywróć głośność:"
+
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Błąd Sndio: Nieobsługiwany format dźwięku (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "urzÄ…dzenie sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Błąd Sndio: funkcja sio_open() zwróciła błąd"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(pusty oznacza domyślne)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Błąd Sndio: funkcja sio_setpar() zwróciła błąd"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Błąd Sndio: funkcja sio_start() zwróciła błąd"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Polecenie przy zmianie ścieżki"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Wykonaj polecenie kiedy uruchamiasz odtwarzanie."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametry przekazywane do powłoki powinny być zawarte w "
+"cudzysłowach. Ich brak jest zagrożeniem dla bezpieczeństwa systemu.</span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Polecenie:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Polecenia</b>"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Kończ odtwarzanie ścieżki."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Polecenie do uruchomienia przy rozpoczęciu nowej piosenki:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Zakończenie odtwarzania listy odtwarzania."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Polecenie do uruchomienia przy zakończeniu piosenki:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "Zmień tytułu ścieżki (np. użyteczne dla internetowych strumieni)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Polecenie do uruchomienia przy zakończeniu listy odtwarzania:"
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
+"Polecenie do uruchomienia, gdy zmieni się tytuł piosenki (dla "
+"strumieniowania sieciowego):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3812,35 +4098,31 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Możesz użyć następujących ciągów formatowania, które\n"
-"zostaną zastąpione przez wywołaniem komendy\n"
-"(nie wszystkie są użyteczne przy komendach 'koniec playlisty'):\n"
+"Możesz użyć poniższych symboli, które zostaną zastąpione przed wywołaniem "
+"polecenia (nie wszystkie są użyteczne jeśli chodzi o polecenie wywoływane po "
+"zakończeniu listy odtwarzania):\n"
 "\n"
-"%F: Częstotliwość (Hz)\n"
+"%F: Częstotliwość (w hercach)\n"
 "%c: Liczba kanałów\n"
-"%f: Nazwa pliku (pełna ścieżka)\n"
-"%l: Długość (ms)\n"
-"%n lub %s: Nazwa piosenki\n"
-"%r: Szybkość (b/s)\n"
-"%t: Pozycja playlisty (%02d)\n"
-"%p: Aktualnie odtwarzane (1 or 0)\n"
-"%a: Artysta\n"
+"%f: Pełna nazwa (ze ścieżką dostępu)\n"
+"%l: Długość (w milisekundach)\n"
+"%n lub %s: Nazwa nagrania\n"
+"%r: Przepływność (w bitach na sekundę)\n"
+"%t: Pozycja na liście odtwarzania (%02d)\n"
+"%p: Aktualnie odtwarzane (1 lub 0)\n"
+"%a: Wykonawca\n"
 "%b: Album\n"
-"%T: Tytuł utworu"
+"%T: Nazwa ścieżki"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Parametry przekazywane do powłoki powinny być zawarte w "
-"cudzysłowach. Ich brak jest zagrożeniem dla bezpieczeństwa systemu.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Informacje o utworze (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Polecenia"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Konwerter częstotliwości SoX"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3848,57 +4130,57 @@ msgid ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
-"Plugin SoX Resampler dla Audacious\n"
-"Copyright 2013 Michał Lipski\n"
+"Wtyczka SoX Resampler dla Audacious\n"
+"Prawa autorskie 2013 Michał Lipski\n"
 "\n"
-"Bazowany na wtyczce Sample Rate Converter:\n"
-"Copyright 2010-2012 John Lindgren"
+"Oparty na wtyczce Sample Rate Converter:\n"
+"Prawa autorskie 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Szybki"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Wolny"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Wysoki"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Bardzo wysoki"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Jakość:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Konwerter częstotliwości SoX"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Szybkość i wysokość tonu"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Szybkość i wysokość tonu</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Szybkość:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Wysokość tonu:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Szybkość i wysokość tonu"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ikona statusu"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "_Ustawienia..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3914,39 +4196,39 @@ msgstr ""
 "Wtyczka wyświetla ikonę statusu, umieszczoną w obszarze ikon powiadomienia "
 "menedżera okien."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Akcja dla przewijania kółkiem myszy</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Zmiana głośności"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Zmiana bieżącej ścieżki"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Inne ustawienia</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Wyłączenie wyskakujących komunikatów"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Zamknij do zasobnika systemowego"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Przejdź do następnej ścieżki przewijając w górę"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Ikona statusu"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Dodatkowe stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3955,24 +4237,24 @@ msgstr ""
 "Wtyczka generujÄ…ca dodatkowy efekt stereo\n"
 "Autor: Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Dodatkowe stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Dodatkowe stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generator sygnałów"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generator sygnałów: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3980,21 +4262,19 @@ msgid ""
 "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
-"Sine tone generator by Håvard Kvålen <havardk at xmms.org> \n"
-"Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"Autor generatora sinusoidalnego: Håvard Kvålen <havardk at xmms.org>\n"
+"Poprawki: Daniel J. Peng <danielpeng at bigfoot.com>\n"
 "\n"
-"To use it, add a URL: tone://frequency1;frequency2;frequency3;... e.g. "
-"tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
-
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generator sygnałów"
+"Instrukcja użytkowania: wprowadź URL tone://częstotliwość1;częstotliwość2;"
+"częstotliwość3;...\n"
+"przykładowo wprowadzenie: tone://2000;2005 wytworzy dźwięk o częstotliwości "
+"2000 Hz oraz 2005 Hz."
 
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Usuwanie głosu (karaoke)"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4016,7 +4296,7 @@ msgid ""
 msgstr ""
 "Dekoder OGG Vorbis dla Audaciousa\n"
 "\n"
-"Bazowany na kodzie wtyczki Ogg Vorbis fundacji Xiph.org:\n"
+"Oparty na kodzie wtyczki Ogg Vorbis fundacji Xiph.org:\n"
 "http://www.xiph.org/\n"
 "\n"
 "Autor oryginalnego kodu:\n"
@@ -4032,11 +4312,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Dekoder Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Szczegóły o %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Tytuł: %t\n"
+"Autor: %a\n"
+"Z: %f\n"
+"Tropiciel: %T\n"
+"Komentarz: %C\n"
+"Rodzaj układu: %c\n"
+"Stereo: %s\n"
+"Pętla: %l\n"
+"Częstotliwość układu: %F\n"
+"Częstotliwość odtwarzacza: %P\n"
+"Rok: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Dekoder VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4047,19 +4362,19 @@ msgstr ""
 "ru>\n"
 "Wtyczka Audaciousa napisana przez Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Dekoder VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Dekoder WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "stratna (hybryda)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "stratna"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4069,14 +4384,18 @@ msgstr ""
 "\n"
 "Część kodu napisana przez Milesa Egana."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Dekoder WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Dekoder 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Konfiguracja XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorowanie czasu trwania z pliku"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
-msgstr "Współdzielone playlisty XML (XSPF)"
+msgstr "Współdzielone listy odtwarzania XML (XSPF)"
diff --git a/po/process-transifex-po b/po/process-transifex-po
index afdd1bb46598..4a29c2ff91e9 100755
--- a/po/process-transifex-po
+++ b/po/process-transifex-po
@@ -85,6 +85,9 @@ lt.po)
 lv.po)
     LANGUAGE="Latvian"
     ;;
+ms.po)
+    LANGUAGE="Malay"
+    ;;
 nl.po)
     LANGUAGE="Dutch"
     ;;
@@ -118,8 +121,8 @@ sr.po)
 sr_RS.po)
     LANGUAGE="Serbian (Serbia)"
     ;;
-sr at latin.po)
-    LANGUAGE="Serbian (Latin)"
+sv.po)
+    LANGUAGE="Swedish"
     ;;
 ta.po)
     LANGUAGE="Tamil"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index c23974aa422f..b459197ec590 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -3,23 +3,25 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# salmora8 <shorterfire at gmail.com>, 2013
+# Alexandro Casanova <shorterfire at gmail.com>, 2013
+# Conservador Ressurge, 2014
+# Eudes Soares <eudes.sp2007 at gmail.com>, 2014
 # Fuad Saud <fuadksd at gmail.com>, 2012
 # mcnd2 <glauber_gf at hotmail.com>, 2012
 # John_Norum <john.norum4 at gmail.com>, 2012
 # Bruno Bacelar <mail2buy8 at gmail.com>, 2012
 # Rafael Ferreira <rafael.f.f1 at gmail.com>, 2012
 # Rodrigo Macedo <rodrigomacedo at rmsolucoeseminformatica.com>, 2012
-# salmora8 <shorterfire at gmail.com>, 2012-2013
+# Alexandro Casanova <shorterfire at gmail.com>, 2012-2013
 # vitorgatti <vitorgatti at yahoo.com.br>, 2012
-# salmora8 <shorterfire at gmail.com>, 2012
+# Alexandro Casanova <shorterfire at gmail.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
 "audacious/language/pt_BR/)\n"
 "Language: pt_BR\n"
@@ -28,40 +30,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "Decodificador AAC(Bruto)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Player)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sequenciado"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib Player)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarme"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Definir Alarme ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -72,11 +62,7 @@ msgstr ""
 "\n"
 "Originalmente escrito por Adam Feakin e Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarme"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -117,7 +103,7 @@ msgstr ""
 "    padrão.\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -156,7 +142,7 @@ msgstr ""
 "  Comando Adicional:\n"
 "    Executar esse comando no momento do alarme.\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -181,183 +167,156 @@ msgstr ""
 "    Digite o lembrete na caixa e ligue-o\n"
 "    botão habilitar/desabilitar, se você quer que ele seja mostrado."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Este é o seu alerta."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Seu lembrete para hoje é..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Lembrete"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Segunda-feira"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Terça-feira"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Quarta-feira"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Quinta-feira"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Sexta-feira"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Configurações do Alarme"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Horário"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarme às (padrão):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silenciar após:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Escolha os dias para o alarme tocar"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Dia"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Padrão"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dias"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Enfraquecimento"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Começar no"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Final"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Atual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando Adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "habilitar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de Reprodução (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Selecionar uma Lista de Reprodução"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opções"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "O que significam estas opções?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ajuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Imagem do Álbum"
 
-#: src/alsa/config.c:210
-msgid "Default PCM device"
-msgstr "Dispositivo PCM padrão"
-
-#: src/alsa/config.c:239
-msgid "Default mixer device"
-msgstr "Dispositivo mixer padrão"
-
-#: src/alsa/config.c:428
-msgid "PCM device:"
-msgstr "Dispositivo PCM:"
-
-#: src/alsa/config.c:430
-msgid "Mixer device:"
-msgstr "Dispositivo mixer:"
-
-#: src/alsa/config.c:432
-msgid "Mixer element:"
-msgstr "Elemento mixer:"
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Arte do Álbum (Qt)"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Solução para impedir a suspensão"
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Saída ALSA"
 
-#: src/alsa/plugin.c:27
+#: src/alsa/config.cc:28
 msgid ""
 "ALSA Output Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren\n"
@@ -373,194 +332,208 @@ msgstr ""
 "cujo código serviu como referencia quando a documentação ALSA não era o "
 "suficiente."
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Saída ALSA"
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr "Dispositivo PCM padrão"
+
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr "Dispositivo mixer padrão"
 
-#: src/amidi-plug/amidi-plug.c:466
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr "Dispositivo PCM:"
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr "Dispositivo mixer:"
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr "Elemento mixer:"
+
+#: src/amidi-plug/amidi-plug.cc:41
 msgid "AMIDI-Plug (MIDI Player)"
 msgstr "AMIDI-Plug (Player MIDI)"
 
-#: src/amidi-plug/i_configure.c:96
-msgid "Override default gain:"
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:94
+msgid "Override default gain:"
+msgstr "Sobrescrever ganho padrão:"
+
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Sobrescrever polifonia padrão:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Sobrescrever reverberação padrão:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Ativo"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Sobrescrever coro padrão:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
-msgid "Drum shift:"
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "número de notas"
+
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Sintetizador</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Taxa de amostragem:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - Selecione o arquivo SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Abrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Nome do arquivo"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Nome do Arquivo"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamanho (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nome:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\">Informações MIDI</span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Duração (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "N.º de Faixas;"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variável"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div. de tempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Comentários de MIDI e Letras </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* Sem comentários disponíveis neste arquivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* Sem letras disponíveis neste arquivo MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Fechar"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 invalido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Sobre o AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Player de música modular MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Escrito por Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"Agradecimentos especias para...\n"
-"\n"
-"Clemens Ladisch e Jaroslav Kysela\n"
-"pelos excelentes programas aplaymidi e amixer; foram\n"
-"realmente úteis, juntamente com a documentação alsa-lib, de modo\n"
-"a aprender mais sobre a API ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"pelo bonito logotipo do teclado midi\n"
-"\n"
-"Tony Vroon\n"
-"pela boa ajuda como um testador alpha."
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -571,151 +544,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (OSD)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Retângulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Retângulo Arredondado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Retângulo Côncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Nada"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Iniciar Reprodução"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Ativar OSD ao reproduzir uma faixa da lista de reprodução"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Mudança de Título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Ativar OSD quando, durante a reprodução, o título da faixa for alterado, mas "
-"o nome do ficheiro permanecer igual. Útil nas reproduções de emissões web."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pausar"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Ativar OSD se a reprodução for colocada em pausa"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Despausar"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Ativar OSD ao retomar a reprodução"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Localização"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y Relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Largura máxima do OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opções de múltiplos monitores "
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Exibir uso do OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "todos os monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Duração (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Exibição:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Aparecer gradual:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Desaparecer gradual:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Tipo de letra"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Tipo de letra %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo de renderização"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Cores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Cor %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Habilitar gatilho"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento "
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Gerenciador Composite detectado"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -725,112 +693,112 @@ msgstr ""
 "ao menos que você saiba que tenha executado, por favor ative um gerenciador "
 "composite, caso contrario o OSD não vai funcionar corretamente "
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Não é necessário o gerenciador Composite para falsa transparência."
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparência  "
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Falsa transparência  "
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparência Real (requer a Extensão X Composite.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Extensão Composite não carregada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Extensão Composite não disponível"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - configuração"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posição"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animação"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoração"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Gatilho"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Vários"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Teste"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de Reproduções ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listas de Reproduções Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Cor</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Ofuscar Escopo"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Estereofônico Bauer para Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Pré-ajuste:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nível alimentar:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Frequência de corte:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Pré-ajuste:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Estereofônico Bauer para Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analisador Espectro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Plugin de CD de Áudio"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -851,171 +819,156 @@ msgstr ""
 "\n"
 "Este foi um projeto do Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocidade de Leitura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Substituir dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadados</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Utilizar CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Usar CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Use HTTP em vez de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Caminho:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Porta:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Plugin de CD de Áudio"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Falha ao iniciar o subsistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI Inválido %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Faixa %d não encontrada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "A faixa %d é uma faixa de dados."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Falha ao abrir a saída de áudio."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Erro ao ler CD de áudio. "
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD "
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Falha ao abrir dispositivo de CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Não se encontrou drive de CD capaz de reproduzir áudio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Falha ao terminar de inicializar drive de CD aberto."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Falha ao recuperar primeiro/ultimo número de faixa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Não foi possível começar/terminar LSN da faixa %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Falha ao criar a conexão cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Falha ao consultar o servidor CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Falha ao consultar o servidor CDDB: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Falha ao ler as informações cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Unidade está vazia."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco não suportado."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Itens do Menu do Áudio CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproduzir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Adicionar CD "
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Itens do Menu do Áudio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compressão</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Volume Central:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Latitude de exposição:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Plugin Latitude de Exposição do Compressor para Audacious\n"
-"Copyright 2010-2012 John Lindgren."
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Latitude de Exposição do Compressor"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1031,206 +984,225 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>."
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Graves:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Duração da música:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Reamostragem</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Ativar reamostragem de audio"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Taxa de reamostragem:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorar duração de tags SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Acrescentar \"reverb\""
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Decodificador Game Console Music"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"A sobreposição falhou porque existem faixas com um número de canais "
-"diferente. Pode utilizar o canal mixer para converter o número das faixas."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"Crossfading falhou porque as musicas tinham diferentes taxas de amostragem. "
-"Você pode usar o Conversor de Taxa de Amostragem para converter as músicas "
-"para a mesma taxa de amostragem."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Plugin Crossfade para Audacious\n"
-"Copyright 2010-2012 John Lindgren."
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Crossfade</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Sobrepor:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Crossfade"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"A sobreposição falhou porque existem faixas com um número de canais "
+"diferente. Pode utilizar o canal mixer para converter o número das faixas."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Crossfading falhou porque as musicas tinham diferentes taxas de amostragem. "
+"Você pode usar o Conversor de Taxa de Amostragem para converter as músicas "
+"para a mesma taxa de amostragem."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizar</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidade:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Plugin Cue Sheet"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Deletar Arquivos"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Erro apagando %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Erro apagando %s: não é um arquivo local."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Deseja mover os arquivos selecionados para a lixeira?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Mover para Lixeira"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Deseja excluir permanentemente os arquivos selecionados?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Apagar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Deletar Arquivos Selecionados"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Atraso:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Comentários:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volume:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Plugin Eco\n"
-"Por Johan Levin, 1999\n"
-"\n"
-"Eco evolvente por Carl van Schaik, 1999."
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Plugin FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1247,55 +1219,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>."
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Plugin FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Plugin FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato de saída do arquivo:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Salvar no diretório original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Salvar em diretório personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Pasta de destino:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Escolha uma pasta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obter nome de arquivo:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Gerar nome de arquivo a partir de:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "Tags originais do arquivo"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Etiqueta do arquivo original"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "nome do arquivo original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nome do arquivo original"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Não tirar a extensão do nome do arquivo"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Acrescentar número de faixa ao nome do arquivo"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1326,165 +1298,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Plugin FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automático"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Configuração MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Qualidade do Algorítimo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Saída de taxa de amostragem:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Taxa de Amostragem de Saída:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Taxa de dados /Taxa de compreensão:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Taxa de compressão:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Taxa de dados (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Taxa de compressão:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modo de áudio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Diversos:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Assegurar o cumprimento estrito ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Proteção de erros"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualidade"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Ativar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opções VBR"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Taxa mínima (kbps)"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Taxa máxima (kbps)"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Cumprir rigorosamente taxa de bits mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opções ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Taxa média (kbps)"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Nível de qualidade VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Não gravar cabeçalho VBR Xing "
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omitir cabeçalho Xing VBR"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parâmetros:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Assinalar como copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Assinalar como original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parâmetros ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forçar adição de tag, versão 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Somente adicionar tag v1 "
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Somente adicionar tag v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Tags"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Configuração do codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Nível de Qualidade (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Decodificador FLAG"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sem perdas"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1496,11 +1472,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Decodificador FLAG"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1508,11 +1480,19 @@ msgstr ""
 "Plugin GIO para Audacious\n"
 "Copyright 2009-2012 John Lindgren."
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Plugin GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Modo de abertura inválido"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1524,533 +1504,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analisador Spectrum OpenGl"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"Plugin Atalhos GNOME\n"
-"Permite controlar o player com atalhos do gnome.\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>."
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Atalhos Gnome"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "Atalhos do GNOME"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número de entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Ano"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Álbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Faixa"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Gênero"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posição na fila"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Duração"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Caminho do arquivo"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nome do Arquivo"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Taxa de dados"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Colunas disponíveis"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Colunas visíveis"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Ferramenta de Busca"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Apontar na esquerda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Apontar na direita"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Apontar no topo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Apontar na parte inferior"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desencaixar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Desabilitar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Ferramenta de Busca"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Abrir Arquivo(s) ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Adicionar Arquivo(s) ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Adicionar U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Pesquisar _Biblioteca"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "S_obre ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Configurações ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Sair"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Reproduzir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Paus_ar"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Parar"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "An_terior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Próxima"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Repetir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "E_mbaralhar"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "N_ão avançar faixa"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Parar D_epois Desta Faixa"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informações da faixa ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Ir para posição _temporal ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Ir para a faixa ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Definir Ponto de Repetição _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Definir Ponto de Repetição _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Limpar Pontos de Repetição"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Por _Título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Por _Nome do Arquivo"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Por _Nome de Arquivo"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Por Arquivo de _Diretório"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Por _Número da Faixa"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Por _Artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Por Ál_bum "
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Por _Artista de Álbum"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Por _Data de Lançamento"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Por _Duração"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Por _Arquivo de Diretório"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Por _Título Personalizado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "I_nverter Ordem"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Aleatório"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Reproduzir esta Lista de Reprodução"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Atualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Organizar Lista de Reprodução"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Organizar Se_lecionado"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Remover _Duplicatas"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Remover _Arquivos Indisponíveis"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Novo"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Re_nomear ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Gerenciador de _Lista de Reprodução ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Gerenciador de _Fila de Reprodução ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Aumentar _Volume"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Abaixar _Volume"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "E_feitos"
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Mostrar Barra de _Menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar Barra de _Informação"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Mostrar vis_ualização da barra de informaçoes"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mostrar Barra de _Status"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Mostrar _Tempo Restante"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Visualizações"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Arquivo"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Reprodução"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de Reprodução"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Serviços"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Saída"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Visualizar"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "Colocar/Retirar da fila"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Recor_tar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Colar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Selecionar _Tudo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Renomear ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Mostrar botão fechar"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Mostrar cabeçalho das colunas"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Diversos</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interface GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "A processar ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canais"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo simples."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo Lista de Reprodução."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Parar após faixa"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Faixa anterior"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproduzir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausa/Retornar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Parar"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Próxima faixa"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avançar 5 segundos"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Retroceder 5 segundos"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Mudo"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Aumentar volume"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Diminuir volume"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Ir para o arquivo"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Habilitar/Desabilitar janela(s) do player"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Habilitar/Desabilitar repetir"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Habilitar/Desabilitar embaralhar"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Habilitar/Desabilitar parar depois da atual"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Aumentar janela(s) do player"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(nada)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2062,15 +2116,11 @@ msgstr ""
 "\n"
 "Continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Associação do botão do mouse"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Configurações Plugin Global Hotkey"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2078,23 +2128,27 @@ msgstr ""
 "Pressionar uma combinação de teclas no campo de texto.\n"
 "Você também pode associar os botoes do mouse."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Hotkeys:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Ação:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Combinação de Teclas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Adicionar"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Global Hotkeys"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2120,60 +2174,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>."
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Global Hotkeys"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Saída JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Falha ao conectar a porta JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Baseado no xmms-jack, por Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Portado para Audacious por Giacomo Lozito."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Saída JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Configurações de %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Configurações LADSPA Host"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Diretório do Modulo:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2184,25 +2229,25 @@ msgstr ""
 "Após a adição dos caminhos, pressione Enter para procurar os novos plugins.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Plugins disponíveis:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Habilitar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Plugins ativos:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Configurações"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2210,55 +2255,15 @@ msgstr ""
 "LADSPA Host para Audacious\n"
 "Copyright 2011 John Lindgren."
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Host"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-"%s: suporte LIRC não iniciado\n"
-"\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: não foi possível ler o arquivo de configuração LIRC\n"
-"%s: consulte a documentação do LIRC\n"
-"%s: como criar um arquivo de configuração válido\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-"%s: tentando nova reconexão...\n"
-"\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando desconhecido %s\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr ""
-"%s: LIRC desconectado\n"
-"\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr ""
-"%s: tentara reconectar %d segundos...\n"
-"\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Plugin LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2288,73 +2293,81 @@ msgstr ""
 "\n"
 "Para mais informações sobre LIRC, veja http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Conexão</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Reconectar ao servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Espere antes de reconectar:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Plugin LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Plugin RyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "A letra da faixa não está disponível"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Erro"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Não foi possível obter %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Erro"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Não foi possível analisar %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Procurando a letra da faixa ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Metadados da música faltando"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Conectando no lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Plugin RyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listas de Reproduções M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Gerador Tacto"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Gerador Tacto: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Gerador Tacto: %d bpm %d%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2368,11 +2381,11 @@ msgstr ""
 "Exemplo: tact://77 para reproduzir 77 bpm (batidas por minuto)\n"
 "ou tact://60*3/4 para reproduzir 60 bpm em 3/4 tactos."
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Gerador Tacto"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Canal Mixer"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2380,152 +2393,184 @@ msgstr ""
 "Plugin Canal Mixer para Audacious\n"
 "Copyright 2011-2012 John Lindgren e Michał Lipski."
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Canal Mixer</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canais de saída:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Canal Mixer"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Plugin MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Modulo Player)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resolução</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canais</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "O mais próximo (mais rápido)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linear (rápido)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (bom)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polifásico (melhor)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Taxa de amostragem</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Nível:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Atalho:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverberação</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Bass Boost</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Cercar</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Pré-amplificador</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Sobreamostra"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Redução de ruído"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Reproduzir Amiga MODs"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repetir</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Contagem de repetição:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Para repetir para sempre, definir a contagem de repetição para -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Modulo Player)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Plugin MPG 123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avançado</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Servidor MPRIS 2"
 
-#: src/neon/neon.c:1056
-msgid "Neon HTTP/HTTPS Plugin"
-msgstr "Plugin Neon HTTP/HTTPS"
+#: src/neon/neon.cc:97
+msgid "Neon HTTP/HTTPS Plugin"
+msgstr "Plugin Neon HTTP/HTTPS"
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Erro HTTP desconhecido"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Erro validando URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Muitos redirecionamentos"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Parado"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious não está tocando."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificações do Desktop"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2560,55 +2605,64 @@ msgstr ""
 "Você poderá receber uma copia de GNU General Public License junto a esse "
 "programa, se não, veja <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Mostrar controles de reprodução"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Sempre exibir notificação"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notificações do Desktop"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Exibir"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausa"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Próxima"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo padrão"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Saída OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Saída OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo padrão"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo de áudio:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Usar dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Salve volume entre sessões."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Permitir conversões de formatos com programa OSS"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Ativar modo exclusivo para evitar mistura virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2622,19 +2676,35 @@ msgstr ""
 "Gostaria de agradecer as pessoas em #audacious, especialmente Tony Vroon e "
 "John Lindgren e a todos os autores anteriores do plugin OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Saída OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Entradas"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Remover"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Ren_omear"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listas de Reproduções PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Decodificador OpenPSF PDF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Saída PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2670,11 +2740,68 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Saída PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Processando ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Pesquisar"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Abrir arquivos"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Adicionar arquivos"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Embaralhar"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Conversor de Taxa de Amostragem"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2682,99 +2809,107 @@ msgstr ""
 "Plugin Conversor de Taxa de Amostragem para Audacious\n"
 "Copyright 2010-2012 John Lindgren."
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Pular/Repetir amostras"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolação linear"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolação sinc rápida"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolação sinc normal"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Interpolação sinc máxima"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversão</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Taxa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapeamento de Taxa</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Usar mapeamento de taxas"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Conversor de Taxa de Amostragem"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Scrobbling para o usuário: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Permissão Negada"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Acesse o link a seguir para permitir Audacious no scrobble em suas "
 "reproduções:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Mantenha esta janela aberta e clique em \"Verificar permissão' novamente.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2782,36 +2917,40 @@ msgstr ""
 "Não se preocupe. Seus scrobbles são salvos no seu computador.\n"
 "Eles serão apresentados logo que Audacious é permitido fazê-lo."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Problema de Rede."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Houve um problema ao contactar Last.fm. Por favor, tente novamente mais "
 "tarde."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Verificando..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "V_erificar Permissão"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Revogar Permissão"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Você precisa permitir Audacious para a reprodução de faixas scrobble na sua "
 "conta Last.fm.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2819,7 +2958,7 @@ msgstr ""
 "O plugin Scrobbler não pôde ser iniciado.\n"
 "Pode haver um problema com a sua instalação."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2837,11 +2976,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2849,7 +2984,11 @@ msgstr ""
 "Audacious agora está usando uma versão melhorada do Last.fm Scrobbler.\n"
 "Por favor, verifique as Preferências do plugin Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Saída SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2857,82 +2996,56 @@ msgstr ""
 "Plugin SDL Output para Audacious\n"
 "Copyright 2010 John Lindgren."
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Saída SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Biblioteca"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista Desconhecido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Album Desconhecido"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"em\n"
-"%s de %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] " %d álbuns"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-"%s, %d faixa"
 msgstr[1] ""
-"%s\n"
-"%s, %d faixas"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-"%d faixa de %s"
 msgstr[1] ""
-"%s\n"
-"%d faixas de %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "por"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Criar Lista de Reprodução"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Adicionar à Lista de Reprodução"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Procurar biblioteca"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2940,679 +3053,769 @@ msgstr ""
 "Para importar sua biblioteca de música no Audacious, escolha uma pasta e em "
 "seguida no ícone \"atualizar\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Por favor aguarde ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Escolha pasta"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Saída</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canais:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulação</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Emular filtro"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reprodução:"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de Reprodução"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Sobre ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Sair"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Embaralhar"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Não Avançar a Lista de Reprodução"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nova Lista de Reprodução"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostrar editor do Player"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostrar Equalizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Sempre no Topo"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Por Título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Por Nome do Arquivo"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Remover Todos"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Apagar Fila de Reprodução"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Remover Arquivos Indisponíveis"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Remover Duplicatas"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Remover Desmarcada"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Remover Selecionados"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Pesquisar e Selecionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverter Seleção"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Não Selecionar"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Selecionar Tudo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Por Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Por Número da Faixa"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Por Artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Por Album"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Por Número da Faixa"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Randomizar Lista"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Reverter Lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Organizar Selecionado"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Organizar Lista"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Colar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface Clássica Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Salvar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Carregar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Pré-ajuste"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Carregar pré-ajuste"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Carregar pré-ajuste automático"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Salvar pré-ajuste"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Salvar pré-ajuste automático"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Deletar pré-ajuste"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Deletar pré-ajuste automático"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Player:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Selecionar o tipo de letra do player:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Lista de Reprodução:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Selecionar o tipo de letra da lista de reprodução:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Usar letras bitmap (suporta ASCII somente)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Título da musica rola em ambas as direções"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analisador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Escopo"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Desligado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fogo"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linhas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Mais Lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Médio"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Muito Rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Linha"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Solido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Gelo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Geral"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualização"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Amplificador"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Esqualizador do Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Ir para %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Equilíbrio: %d%% esquerda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Equilíbrio centro"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Equilíbrio: %d%% direita"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu de Opções"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desativar 'Sempre No Topo'"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Ativar 'Sempre No Topo'"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caixa de Informações do Arquivo"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Repetir ponto de definição A."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Repetir ponto de definição B."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Repetir pontos apagados."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo simples."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo Lista de Reprodução."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Parar após faixa"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Procurar entradas na lista de reprodução ativa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3624,58 +3827,62 @@ msgstr ""
 "minúsculas. Se não sabe o que são expressões regulares, basta inserir uma "
 "parte do que pretende procurar."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Titulo:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Álbum:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artista:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nome do Arquivo:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Apagar seleção anterior antes de pesquisar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 "Automaticamente habilitar/desabilitar fila para as entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Criar uma nova lista de reprodução com as entradas correspondentes"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de lista de reprodução do Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Tema Winamp 2.x arquivado"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Tema Winamp 2.x não arquivado"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Não foi possível criar o diretório (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Plugin Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3716,84 +3923,71 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Plugin Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sobre Sndio Plugin de saída"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Plugin de Saída Sndio\n"
-"\n"
-"Escrito por Thomas Plaff <tpfaff at tp76.info>.\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato não suportado"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Um formato não suportado pelo dispositivo foi solicitado.\n"
-"\n"
-"Por favor tente novamente com o servidor sndiod(1) em execução."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(vazio significa os padrões)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Mudar Faixa"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando a executar quando Audacious iniciar uma nova faixa."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parâmetros enviados ​​para o console devem ser colocados em "
+"aspas. Caso contrário corre risco de segurança.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando a executar ao terminar uma faixa."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
-"Comando a executar quando Audacious atinge o fim de uma lista de reprodução."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Comando a executar quando o titulo da música for modificado (Exemplo: "
-"títulos de redes stream)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3807,35 +4001,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Você pode utilizar os formatos descritos em baixo, que\n"
-"serão substituído antes de chamar o comando\n"
-"(nem todos podem ser utilizados para o comando fim da lista de reprodução):\n"
-"\n"
-"%F: Frequência (em hertz)\n"
-"%c: Números de canais\n"
-"%f Nome do arquivo (diretório completo)\n"
-"%l: Duração (em milissegundos)\n"
-"%n ou %s Nome da faixa\n"
-"%r: Taxa (em bits por segundo)\n"
-"%t Posição da lista de reprodução (%02d)\n"
-"%p A reproduzir atualmente (1 ou 0)\n"
-"%a: Artista\n"
-"%b Álbum\n"
-"%T: Faixa de titulo"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Parâmetros enviados ​​para o console devem ser colocados em "
-"aspas. Caso contrário corre risco de segurança.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandos"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Reamostrador SoX"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3849,51 +4024,51 @@ msgstr ""
 "Baseado no Plugin Conversor de Taxa de Amostragem:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rápido"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Baixo"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alto"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Muito Alto"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualidade:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Reamostrador SoX"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidade e Tom"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocidade e Tom</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidade:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Tom:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidade e Tom"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ícone de Status"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3911,39 +4086,39 @@ msgstr ""
 "Esse plugin fornece um ícone de status, colocado na\n"
 "área de notificação do sistema no gerenciador de janelas."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Ação do Mouse no botão do meio</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Alterar volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Mudar de faixa"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Outras Configuraçoes</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desativar janelas pop-up"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Fechar para a bandeja do sistema"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avançar lista de reprodução ao rolar para cima"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Ícone de Status"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Stereo Extra"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3953,24 +4128,24 @@ msgstr ""
 "\n"
 "Por Johan Levin, 1999."
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Stereo Extra</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Stereo Extra"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Gerador de Tons"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Gerador de Tons:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3985,15 +4160,11 @@ msgstr ""
 "frequência3;...\n"
 "Exemplo: tone://2000;2005 para reproduzir um tom 2000 Hz e outro de 2005 Hz."
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Gerador de Tons"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Remoção de voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4031,11 +4202,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>."
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Decodificador Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Decodificador VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4046,19 +4241,19 @@ msgstr ""
 "Baseado em in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Plugin Audacious por Pavel Vymetalek <pvymetalek at seznam.cz>."
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Decodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Decodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "com perdas (híbrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "com perdas"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4068,14 +4263,18 @@ msgstr ""
 "\n"
 "Parte do código do plugin foi por Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Decodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Decodificador 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Lista de Reprodução Compartilhável XML (XSPF)"
diff --git a/po/pt_PT.po b/po/pt_PT.po
index 6d5ab250c511..cfb5da9d20b8 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -3,17 +3,19 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# Alexandro Casanova <shorterfire at gmail.com>, 2012
 # Bruno Martins <bmomartins at gmail.com>, 2011
 # Pitxyoki <Pitxyoki at gmail.com>, 2013
-# Sérgio Marques <smarquespt at gmail.com>, 2012-2013
-# salmora8 <shorterfire at gmail.com>, 2012
+# Pitxyoki <Pitxyoki at gmail.com>, 2013
+# Sérgio Marques <smarquespt at gmail.com>, 2012-2015
+# Alexandro Casanova <shorterfire at gmail.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 13:02+0000\n"
+"Last-Translator: Sérgio Marques <smarquespt at gmail.com>\n"
 "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
 "audacious/language/pt_PT/)\n"
 "Language: pt_PT\n"
@@ -22,40 +24,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "estéreo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "surround"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "Descodificador AAC (RAW)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (Reprodutor AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sequencial"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (Reprodutor AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarme"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Definir alarme..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -65,11 +55,7 @@ msgstr ""
 "\n"
 "Versão original desenvolvida por Adam Feakin e Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarme"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -111,7 +97,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -151,7 +137,7 @@ msgstr ""
 "    Executar este comando ao tocar o alarme.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -175,385 +161,391 @@ msgstr ""
 "    Escreva o lembrete na caixa e ative o botão\n"
 "    para alternar se o quiser mostrar."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Este é o seu alerta."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "O seu lembrete de hoje é:"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Lembrete"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "segunda"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "terça"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "quarta"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "quinta"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "sexta"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "sábado"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "domingo"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Definições do alarme"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Horário"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarme às (pré-definido):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Silenciar após:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "horas"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minutos"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
-msgstr "Escolha os dias para o alarme"
+msgstr "Escolha os dias para o alarme tocar"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Dia"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Pré-definido"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dias"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Desvanecimento"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "segundos"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Volume"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Ao iniciar"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Ao terminar"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Atual"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Comando adicional"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "ativar"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Lista de reprodução (opcional)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
-msgstr "Escolha uma lista de reprodução"
+msgstr "Escolha a lista de reprodução"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Opções"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "O que significam estas opções?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Ajuda"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Imagem de álbum"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Imagem do álbum (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Sistema ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Suplemento ALSA\n"
+"Direitos de autor 2009-2012 John Lindgren\n"
+"\n"
+"Os meus agradecimentos a William Pitcock, autor do suplemento ALSA Output "
+"NG, cujo código serviu de base nas situações em que a documentação ALSA não "
+"cumpria os requisitos."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(sem descrição)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Dispositivo PCM pré-definido"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Dispositivo misturador pré-definido"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Dispositivo PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Dispositivo misturador:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Elemento misturador:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Solução para impedir a suspensão"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (Reprodutor MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Suplemento ALSA\n"
-"Direitos de autor 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"Reprodutor de música MIDI\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Os meus agradecimentos a William Pitcock, autor do suplemento ALSA Output "
-"NG, cujo código serviu de base nas situações em que a documentação ALSA não "
-"cumpria os requisitos."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Sistema ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (Reprodutor MIDI)"
+"desenvolvido por Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"um especial obrigado a...\n"
+"\n"
+"Clemens Ladisch e Jaroslav Kysela\n"
+"pelos programas aplaymidi e amixer uma vez que\n"
+"foram muito úteis, bem como a documentação alsa-lib\n"
+"que disponibiliza as informações da API ALSA\n"
+"\n"
+"Alfredo Spadafina\n"
+"pela imagem do teclado midi\n"
+"\n"
+"Tony Vroon\n"
+"pela ajuda nos testes"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Substituir ganho pré-definido:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Substituir polifonia pré-definido:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Substituir reverb pré-definido:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Ligado"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Substituir coro pré-definido:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Reprodução</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
-msgstr ""
+msgstr "Transposição:"
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "semitons"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
-msgstr ""
+msgstr "Drum shift:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "número da nota"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Ignorar silêncio inicial"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Ignorar silêncio final"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
+msgstr "<b>Sintetizador</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "Frequência:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
-msgstr "Amidi - selecione o ficheiro SoundFont"
+msgstr "AMIDI-Plug - selecione o ficheiro SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Abrir"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Nome do ficheiro"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Tamanho (bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Nome:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
-msgstr "<span size=\"smaller\">Informações Midi</span>"
+msgstr "<span size=\"smaller\">Informações MIDI</span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formato:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Duração (mseg):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "N.º de faixas:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "variável"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Div. de tempo:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
-msgstr "<span size=\"smaller\">Comentários e letras das faixas midi</span>"
+msgstr "<span size=\"smaller\">Comentários e letras das faixas MIDI</span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
-msgstr "* sem comentários para este ficheiro midi *"
+msgstr "* sem comentários para este ficheiro MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
-msgstr "* sem letra da música para este ficheiro midi *"
+msgstr "* sem letra da música para este ficheiro MIDI *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Fe_char"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (UTF-8 inválido)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Sobre o AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Reprodutor de faixas MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Desenvolvido por Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"Um especial obrigado a...\n"
-"\n"
-"Clemens Ladisch e Jaroslav Kysela\n"
-"pelas aplicações aplaymidi e amixer e\n"
-"à documentação alsa-lib que me ajudou a\n"
-"descobrir as especificações da API ALSA.\n"
-"\n"
-"Alfredo Spadafina\n"
-"pelo logótipo do teclado midi.\n"
-"\n"
-"Tony Vroon\n"
-"por me ajudar nos testes."
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -563,152 +555,154 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Dsesenvolvido por Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Baseado na biblioteca Ghosd criada por Evan Martin:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Notificação no ecrã)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Retângulo"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Retângulo arredondado"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Retângulo côncavo"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Nenhum"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Ao iniciar reprodução"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Ativar OSD ao reproduzir uma faixa da lista de reprodução."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
-msgstr "Ao alterar o título"
+msgstr "Ao mudar o título"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"Ativar OSD se, durante a reprodução, o título da faixa for alterado mas o "
-"nome do ficheiro permanecer igual. Útil nas reproduções de emissões web."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Ativar OSD ao mudar o título da faixa (para emissões web)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
-msgstr "Ao colocar em pausa"
+msgstr "Ao pausar"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Ativar OSD se a reprodução for colocada em pausa."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Ao retirar da pausa"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Ativar OSD ao retomar a reprodução."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Posicionamento"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X relativo:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y relativo:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Largura máxima do OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Opções de monitores múltiplos"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Mostrar OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "em todos os monitores"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "no monitor %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Duração (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Exibição:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Aparecer gradual:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Desaparecer gradual:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Tipo de letra"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Tipo de letra %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Sombra"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Estilo"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Cores"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Cor %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Ativar"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Evento"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Detetado um gestor de composição."
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -718,112 +712,112 @@ msgstr ""
 "A menos que tenha a certeza que o gestor está ativo, tem que ativar um "
 "gestor de composição para mostrar o OSD."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
-msgstr "O gestor de composição não é necessário para a transparência fictícia."
+msgstr "A transparência fictícia não precisa de um gestor de composição"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Transparência"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Transparência fictícia"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Transparência efetiva (requer a extensão X Composite)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
-msgstr "Extensão Composite não carregada"
+msgstr "Extensão de composição não carregada"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
-msgstr "Extensão Composite não disponível"
+msgstr "Extensão de composição não disponível"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Definições do OSD Audacious"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Posição"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animação"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Texto"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Decoração"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Ativador"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
-msgstr "Diversos"
+msgstr "Outras"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Teste"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "Listas de reprodução ASXv3"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Listas de reprodução ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Listas de reprodução Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Cor</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Blur Scope"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Pré-ajuste:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Nível:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Frequência de corte:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Pré-ajuste:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analisador de espetro"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Suplemento Áudio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -836,179 +830,166 @@ msgid ""
 msgstr ""
 "Direitos de autor (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> e outros.\n"
 "\n"
-"Os meus agradecimentos aos programadores da libcdio <http://www.gnu.org/"
-"software/libcdio/>\n"
+"O meu obrigado aos programadores da libcdio <http://www.gnu.org/software/"
+"libcdio/>\n"
 "e da libcddb <http://libcddb.sourceforge.net/>.\n"
 "\n"
 "Agradeço também a Tony Vroon pelo apoio concedido.\n"
 "\n"
 "Este foi um projeto do Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Dispositivo</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Velocidade de leitura:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Sobrepor dispositivo:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Detalhes</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Utilizar CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Utilizar CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Utilizar HTTP em vez de CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Servidor:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Caminho:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Porta:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Suplemento Áudio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Ocorreu um erro ao iniciar o sistema cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "URI %s inválido."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Faixa %d não encontrada."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "A faixa %d é uma faixa de dados."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Ocorreu um erro ao abrir o sistema de som."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Ocorreu um erro ao ler o CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "CD áudio"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Ocorreu um erro ao abrir o dispositivo %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Não foi encontrada uma unidade de CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Ocorreu um erro ao iniciar a unidade de CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Ocorreu um erro ao obter o número da primeira/última faixa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Não foi possível ler inicio/fim LSN da faixa %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Ocorreu um erro ao criar a ligação à cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Ocorreu um erro ao consultar o servidor cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Ocorreu um erro ao consultar o servidor cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Ocorreu um erro ao ler as informações cddb: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Unidade vazia."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Tipo de disco não suportado."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Itens de menu do Áudio CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Reproduzir CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Adicionar CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Itens de menu do Áudio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Compressão</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Centrar volume:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Intervalo dinâmico:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Suplemento Dynamic Range Compression\n"
-"DIreitos de autor 2010-2012 John Lindgren."
+"Direitos de autor 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Compressor de intervalo dinâmico"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1017,213 +998,245 @@ msgid ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
-"Suplemento Console music decoder baseado no Game_Music_Emu 0.5.2\n"
+"Suplemento Console Music Decoder baseado no Game_Music_Emu 0.5.2\n"
 "Formatos suportados: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
 "\n"
-"Adaptação para o Audacious por:\n"
+"Adaptação ao Audacious por:\n"
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Graves:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Agudos:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Eco:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Duração pré-definida da faixa:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
-msgstr "<b>Resampling</b>"
+msgstr "<b>Remistura</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Ativar remistura áudio"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Frequência:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorar duração das \"tags\" SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Aumentar \"reverb\""
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Descodificador Game Console Music"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"A sobreposição falhou porque existem faixas com um número de canais "
-"diferente. Pode utilizar o gestor de canais para converter o número de "
-"canais das faixas."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Suplemento CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"A sobreposição falhou porque existem faixas com frequências diferentes. Pode "
-"utilizar o Conversor de frequências para converter a frequência das faixas."
+"Suplemento CoreAudio Output\n"
+"Direitos de autor 2014 William Pitcock\n"
+"\n"
+"Baseado no suplemento SDL Output\n"
+"Direitos de autor 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Usar modo exclusivo"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Suplemento Crossfade\n"
-"Direitos de autor 2010-2012 John Lindgren"
+"Direitos de autor 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Sobreposição</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "Ao mudar automaticamente de faixa"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Sobreposição:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "Ao procurar ou mudar manualmente a faixa"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Dica</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"Para um melhor desempenho, ative\n"
+"o efeito Remoção de silêncio."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Sobreposição"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"A sobreposição falhou porque existem faixas com um número de canais "
+"diferente. Pode utilizar o gestor de canais para converter o número de "
+"canais das faixas."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"A sobreposição falhou porque existem faixas com frequências diferentes. Pode "
+"utilizar o Conversor de frequências para converter a frequência das faixas."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Cristalizador</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intensidade:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Cristalizador"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
-msgstr "Suplemento Cue"
+msgstr "Suplemento Cue Sheet"
+
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Eliminar ficheiros"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
-msgstr ""
+msgstr "Erro ao mover %s para o lixo: %s"
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Erro ao eliminar %s: %s"
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Erro ao eliminar %s: não é ficheiro local"
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Pretende mover os ficheiros selecionados para o lixo?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Mover para o lixo"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Pretende eliminar permanentemente os ficheiros selecionados?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Eliminar"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Eliminar ficheiros selecionados"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Método de eliminação</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Mover para o lixo em vez de os eliminar"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
+"Suplemento Echo\n"
+"Por Johan Levin, 1999\n"
+"Surround echo por Carl van Schaik, 1999\n"
+"Atualizado para o Audacious por William Pitcock e John Lindgren, 2010-2014"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Eco</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Atraso:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Retorno:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Volume:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Suplemento Echo\n"
-"Po Johan Levin, 1999\n"
-"\n"
-"Surround echo por Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Eco"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Suplemento FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1232,62 +1245,61 @@ msgid ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
-"Suplemento de descodificação através da infraestrutura\n"
-"FFmpeg (http://www.ffmpeg.org/)\n"
+"Suplemento FFmpeg (http://www.ffmpeg.org/)\n"
 "\n"
 "Adaptação ao Audacious por:\n"
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Suplemento FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Suplemento FileWriter"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formato de saída:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Configurar"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Gravar no diretório original"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Gravar num diretório personalizado"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Pasta de destino:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Escolha a pasta"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Obter nome do ficheiro:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Gerar nome de ficheiro de:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "das \"tags\" originais"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Etiqueta orifinal"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "do nome de ficheiro original"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Nome de ficheiro original"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Não remover extensão do ficheiro"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Incluir extensão de ficheiro original"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Prefixar n.º da faixa ao nome do ficheiro"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Adicionar número de faixa ao nome do ficheiro"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1304,180 +1316,184 @@ msgid ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 msgstr ""
-"Este suplemento é um programa livre. Pode redistribui-lo e/ou modificá-lo "
-"nos termos da GNU General Public License, tal como publicada pela Free "
-"Software Foundation, tanto na versão 3 ou (por opção) qualquer versão mais "
-"recente.\n"
+"Este suplemento é um programa livre. Pode redistribui-lo e/ou modificá-lo\n"
+"nos termos da GNU General Public License, tal como publicada pela\n"
+"Free Software Foundation, tanto na versão 3 ou (por opção)\n"
+"qualquer versão mais recente.\n"
 "\n"
-"Este programa é disponibilizado com o intuito de ser útil mas NÃO POSSUI "
-"QUALQUER GARANTIA. Nem mesmo a garantia implícita de comercialização ou "
-"adequação a um propósito concreto.  Consulte a GNU General Public License "
-"para mais detalhes.\n"
+"Este programa é disponibilizado com o intuito de ser útil mas\n"
+"NÃO POSSUI QUALQUER GARANTIA. Nem mesmo a garantia implícita\n"
+"de comercialização ou adequação a um propósito concreto.\n"
+"Consulte a GNU General Public License para mais detalhes.\n"
 "\n"
-"Deve ter recebido uma cópia da GNU General Public License junto com o "
-"programa. Se tal não aconteceu, escreva uma carta para Free Software\n"
-"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
-"USA."
+"Deve ter recebido uma cópia da GNU General Public License\n"
+"com o programa. Se tal não aconteceu, escreva uma carta para\n"
+"Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor\n"
+"Boston, MA 02110-1301, USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Suplemento FileWriter"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Automático"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint estéreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Estéreo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Definições MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Aceitar"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Qualidade do algoritmo:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "Frequência de saída:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "Taxa de dados/compressão:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Taxa de dados (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Rácio de compressão:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Modo áudio:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Diversos:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "Diversos"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "Forçar conformidade ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Proteção de erros"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Qualidade"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Ativar VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tipo:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Opções VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Taxa mínima (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Taxa máxima (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Forçar taxa de dados mínima"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Opções ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Taxa média (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Qualidade VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Não gravar cabeçalho Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Omitir cabeçalho Xing VBR"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Parâmetros:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
-msgstr "Assinalar como copyright"
+msgstr "Marcar como copyright"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
-msgstr "Assinalar como original"
+msgstr "Marcar como original"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Parâmetros ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Forçar adição de \"tags\" v2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Apenas \"tags\" v1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Apenas \"tags\" v2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "\"Tags\""
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Definições do codificador Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Qualidade (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Descodificador FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "sem perda"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1489,11 +1505,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Descodificador FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1501,11 +1513,19 @@ msgstr ""
 "Suplemento GIO\n"
 "Direitos de autor 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Suplemento GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Modo \"read-and-append\" não suportado"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Modo inválido de abertura"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1516,535 +1536,629 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"Analisador de espetro OpenGL\n"
+"Direitos de autor 2013 Christophe Budé, John Lindgren e Carlo Bramini\n"
+"\n"
+"Baseado no suplemento XMMS:\n"
+"Direitos de autor 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas "
+"Nilsson e 4Front Technologies\n"
+"\n"
+"Licença: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "Analisador de espetro OpenGL"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"Suplemento Gnome Shortcut\n"
-"Permite-lhe controlar o Audacious com as teclas de atalho Gnome.\n"
+"Analisador de espetro OpenGL\n"
+"Direitos de autor 2013 Christophe Budé, John Lindgren e Carlo Bramini\n"
+"Direitos de autor 2014 William Pitcock\n"
 "\n"
-"Direitos de autor (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Baseado no suplemento XMMS:\n"
+"Direitos de autor 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas "
+"Nilsson e 4Front Technologies\n"
+"\n"
+"Licença: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "Analisador de espetro OpenGL (Qt)"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Atalhos Gnome"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME Shortcuts"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"Suplemento GNOME Shortcut\n"
+"Permite controlar a aplicação através dos atalhos GNOME.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Número da entrada"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Título"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Artista"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Ano"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Álbum"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Artista do álbum"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Faixa"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Género"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Posição na fila"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Duração"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Caminho do ficheiro"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Nome do ficheiro"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Título personalizado"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Taxa de dados"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Colunas disponíveis"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Colunas mostradas"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Ferramenta de procura"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Doca à esquerda"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Doca à direita"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Doca em cima"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Doca em baixo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Desacoplar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Desativar"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Ferramenta de procura"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Abrir ficheir_os..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Abrir _URL..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Adicionar ficheiros..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Adicionar U_RL..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Procurar co_leção"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "So_bre..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "Definiçõe_s..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Sair"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "Re_produzir"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Paus_a"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "Pa_rar"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "An_terior"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "Segui_nte"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Repetir"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Baral_har"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Sem avanç_o na lista de reprodução"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Parar após esta fai_xa"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informações da faixa..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Ir para posição _temporal..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "I_r para a faixa..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Definir ponto de repetição _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Definir ponto de repetição _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "Remover pontos de rep_etição"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Por _título"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "Por nome de _ficheiro"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "Por nome do _ficheiro"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Por caminho do fic_heiro"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Por _número de faixa"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Por _artista"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Por ál_bum"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Por artista do álbu_m"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Por _data de disponibilização"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Por _género"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
-msgstr "Por _duração"
+msgstr "Por d_uração"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Por caminho do _ficheiro"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
-msgstr "Por tít_ulo personalizado"
+msgstr "Por título personali_zado"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Inv_erter ordem"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Aleató_rio"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Re_produzir esta lista de reprodução"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "Re_produzir/Retomar"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Atualizar"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Organização"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr ""
+msgstr "Organizar se_leção"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Remover _duplicados"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Remover ficheiros indisponívei_s"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nova"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Mud_ar nome..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "Remo_ver"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importar..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportar..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "_Gestão da lista de reprodução..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
-msgstr "_Gestão da fila de reprodução"
+msgstr "_Gestão da fila de reprodução..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "A_umentar volume"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "_Diminuir volume"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Equalizador"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "E_feitos..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_Mostrar barra de menu"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Mostrar barra de i_nformações"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
-msgstr "Mostrar visualização da barra de informações"
+msgstr "Mostrar vis_ualização da barra de informações"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Mo_strar barra de estado"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Mostrar tempo _restante"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Visualizações..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Ficheiro"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "Re_produção"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Lista de reprodução"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Serviços"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "S_aída"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Ver"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Colocar/retirar da fila"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Abrir pasta respetiva"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Cor_tar"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Copiar"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "Co_lar"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Selecion_ar tudo"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Muda_r nome..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Separadores da lista de reprodução</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Mostrar sempre"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Mostrar número de entradas"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Mostrar botão Fechar"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Colunas da lista de reprodução</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Mostrar título das colunas"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Diversos</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Teclas de seta procuram por:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Deslocar ao mudar de faixa"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Interface GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "A processar..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "estéreo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d canal"
 msgstr[1] "%d canais"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Modo simples"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Modo lista de reprodução"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Para após a faixa"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Faixa anterior"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Reproduzir"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pausa/Retomar"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Parar"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Faixa seguinte"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Avançar 5 segundos"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Recuar 5 segundos"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Silenciar"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Aumentar volume"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Diminuir volume"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Ir para ficheiro"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Ativar/desativar janela(s) do reprodutor"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Mostrar OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Ativar/desativar repetição"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Ativar/desativar desorganização"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Ativar/desativar paragem após a faixa atual"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Mostrar janela(s) do reprodutor"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(nada)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2055,15 +2169,11 @@ msgstr ""
 "\n"
 "Continuar?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Associação dos botões do rato"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Definições das Teclas globais"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2071,23 +2181,27 @@ msgstr ""
 "Prima a combinação de teclas no campo de texto.\n"
 "Também pode associar os botões do rato."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Teclas de atalho:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Ação:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Associação de teclas:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Adicionar"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Atalhos globais"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2114,60 +2228,57 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Atalhos globais"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Sistema Jack"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Ligar automaticamente às portas de saída"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Apenas foram encontradas %d portas de saída JACK e são precisas %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Falha ao estabelecer ligação à porta %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
+"O JACK apenas tem suporte a áudio de vírgula flutuante. Deve alterar a "
+"profundidade para vírgula flutuante nas definições."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
+"Falha ao estabelecer ligação ao servidor JACK. O servidor está em execução?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Baseado no suplemento xmms-jack, de Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Adaptação ao Audacious por Giacomo Lozito"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Sistema Jack"
+"O servidor JACK requer uma frequência de %d Hz, mas o Audacious está a "
+"reproduzir a %d Hz. Utilize o efeito Sample Rate Converter para corrigir a "
+"diferença."
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Definições de %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Definições LADSPA "
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Caminhos do módulo:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2178,25 +2289,25 @@ msgstr ""
 "Após a adição dos caminhos, prima Enter para procurar os novos suplementos.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Suplemento disponíveis:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Ativar"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Suplementos ativos:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Definições"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2204,47 +2315,15 @@ msgstr ""
 "Suplemento LADSPA Host\n"
 "Direitos de autor 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: suporte LIRC não iniciado.\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: não foi possível ler o ficheiro de configuração LIRC.\n"
-"%s: consulte a documentação do LIRC.\n"
-"%s: como criar um ficheiro de configuração válido.\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: a tentar nova ligação...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: comando desconhecido \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: desligado do servidor LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: nova tentativa de ligação a cada %d segundos...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Suplemento LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2259,8 +2338,7 @@ msgid ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
-"Um suplemento para controlar o Audacious através do serviço de controlo "
-"remoto LIRC.\n"
+"Um suplemento para controlar o Audacious através do serviço LIRC.\n"
 "\n"
 "Adaptação ao Audacious por:\n"
 "Tony Vroon <chainsaw at gentoo.org>\n"
@@ -2273,73 +2351,81 @@ msgstr ""
 "\n"
 "Para mais informações, consulte http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Ligação</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Nova ligação ao servidor LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Intervalo entre ligações:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Suplemento LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Suplemento LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "A letra da faixa não está disponível."
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Erro"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Não foi possível obter %s."
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Erro"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Não foi possível processar %s."
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "A procurar letra da faixa..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Detalhes em falta"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Ligação a lyrics.wikia.com..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Suplemento LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Suplemento LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Listas de reprodução M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Gerador Tact"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Gerador Tact: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Gerador Tact: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2353,11 +2439,11 @@ msgstr ""
 "exemplo: tact://77 para reproduzir 77 batidas por minuto\n"
 "ou tact://60*3/4 para reproduzir 60 batidas por minuto em 3/4 tacts"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Gerador Tact"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Gestor de canais"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2365,152 +2451,184 @@ msgstr ""
 "Suplemento Channel Mixer\n"
 "Direitos de autor 2011-2012 John Lindgren e Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Gestor de canais</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Canais de saída:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Gestor de canais"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Suplemento MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Erro ao estabelecer ligação ao servidor MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Reprodutor Module)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Resolução</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Canais</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Nearest (mais rápido)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Linear (rápido)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Spline (bom)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Polyphase (melhor)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Frequência</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Nível:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Corte:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Reverb</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Amplificação de graves</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Surround</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Amplificador</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Oversample"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Redução de ruído"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Reproduzir Amiga MODs"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Repetição</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "N.º de repetições:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
-msgstr "Para repetir eternamente, defina o valor para -1."
+msgstr "Para repetir eternamente, defina o valor -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Reprodutor Module)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Estas definições serão aplicadas após reiniciar o Audacious."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Suplemento MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Avançado</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Usar cálculo preciso de duração (lento)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Servidor MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Suplemento Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Erro ao redirecionar"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Erro HTTP desconhecido"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Erro ao processar URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Demasiados redirecionamentos"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Parado"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "O Audacious não está a reproduzir."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Notificações do ambiente de trabalho"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2547,55 +2665,64 @@ msgstr ""
 "Deve ter recebido uma cópia da GNU General Public License com esta "
 "aplicação.  Se tal não ocorreu consulte <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Mostrar controlos de reprodução"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Mostrar sempre notificação"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Notificações do ambiente de trabalho"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Incluir nome do álbum na notificação"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Mostrar"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pausa"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Seguinte"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Dispositivo pré-definido"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Sistema OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Saída OSS3"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Dispositivo pré-definido"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Dispositivo áudio:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Utilizar dispositivo alternativo:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Memorizar volume entre sessões."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Ativar conversão de formatos com o programa OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Ativar modo exclusivo para prevenir mistura virtual."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2609,19 +2736,35 @@ msgstr ""
 "Gostaria de agradecer às pessoas em #audacious, especialmente a Tony Vroon, "
 "a John Lindgren e a todos os anteriores autores do suplemento OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Sistema OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Gestor de lista de reprodução"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Entradas"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Remover"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Mud_ar nome"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Listas de reprodução PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Descodificador OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Sistema PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2652,16 +2795,78 @@ msgstr ""
 "adequação a um propósito concreto.  Consulte a GNU General Public License "
 "para mais detalhes.\n"
 "\n"
-"Deve ter recebido uma cópia da GNU General Public License junto com o "
-"programa. Se tal não aconteceu, escreva uma carta para Free Software\n"
-"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
-"USA."
+"Deve ter recebido uma cópia da GNU General Public License junto com o "
+"programa. Se tal não aconteceu, escreva uma carta para Free Software\n"
+"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
+"USA."
+
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Saída QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Suplemento QtMultimedia Audio Output\n"
+"Direitos de autor 2014 William Pitcock\n"
+"\n"
+"Baseado no suplemento SDL Output\n"
+"Direitos de autor 2010 John Lindgren"
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Sistema PulseAudio"
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Execução..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Procura"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "A_brir pasta..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Adicionar pasta..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Insp_etor de registos..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Abrir ficheiros"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Adicionar ficheiros"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Anterior"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Repetir"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Baralhar"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Interface Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Conversor de frequências"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2669,99 +2874,107 @@ msgstr ""
 "Suplemento Sample Rate Converter\n"
 "Direitos de autor 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Ignorar/repetir frequências"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Interpolação linear"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Interpolação rápida"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Interpolação normal"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Interpolação máxima"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Conversão</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Método:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Taxa:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapeamentos de taxa</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Utilizar mapeamento de taxa"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Conversor de frequências"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. A fazer scrobble para o utilizador: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
-msgstr "Sem Permissão"
+msgstr "Permissão recusada"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Aceda a esta ligação para permitir que o Audacious faça scrobble das "
 "reproduções:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Mantenha esta janela aberta e clique novamente em \"Verificar permissões\".\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2769,34 +2982,38 @@ msgstr ""
 "Não se preocupe. Os seus scrobbles estão gravados no computador.\n"
 "Serão enviados assim que o Audacious tiver permissão."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
-msgstr "Erro na Rede."
+msgstr "Erro na rede"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Ocorreu um erro ao contactar com a Last.fm. Por favor tente novamente."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
-msgstr "A Verificar..."
+msgstr "A verificar..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
-msgstr "Verific_ar Permissão"
+msgstr "Verific_ar permissão"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
-msgstr "_Revogar Permissão"
+msgstr "_Revogar permissão"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
-"Tem de dar permissão ao Audacious para poder fazer scrobble das faixas para "
-"a sua conta Last.fm.\n"
+"Tem de dar permissão ao Audacious para fazer scrobble das faixas para a sua "
+"conta Last.fm.\n"
+
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2804,7 +3021,7 @@ msgstr ""
 "O suplemento Scrobbler não foi iniciado.\n"
 "Pode haver um problema com a sua instalação."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2814,27 +3031,27 @@ msgid ""
 "project.\n"
 "\n"
 msgstr ""
-"Audacious Scrobbler 2.0 por Pitxyoki,\n"
+"Suplemento Audacious Scrobbler 2.0 por Pitxyoki.\n"
 "\n"
-"Direitos de Autor © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail."
+"Direitos de autor © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail."
 "com>\n"
 "\n"
-"Obrigado ao John Lindgren por me ter ajudado no início deste projecto.\n"
+"Obrigado ao John Lindgren por me ter ajudado no início deste projeto.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
-"O Audacious passou a usar uma nova versão do Scrobbler para a Last.fm.\n"
-"Por favor verifique as Preferências do suplemento Scrobbler."
+"O Audacious passou a usar uma nova versão do scrobbler Last.fm.\n"
+"Por favor verifique as definições do suplemento Scrobbler."
+
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Sistema SDL"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2842,81 +3059,56 @@ msgstr ""
 "Suplemento SDL\n"
 "Direitos de autor 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Sistema SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Coleção"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Artista desconhecido"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Álbum desconhecido"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"em %s de %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d resultado"
+msgstr[1] "%d resultados"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d álbum"
-msgstr[1] "%d álbuns"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d oculto)"
+msgstr[1] "(%d ocultos)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d faixa"
-msgstr[1] ""
-"%s\n"
-" %s, %d faixas"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d faixa de %s"
-msgstr[1] ""
-"%s\n"
-" %d faixas de %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d faixa"
+msgstr[1] "%d faixas"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "deste género"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "em"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "por"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Criar lista de reprodução"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Adicionar à lista de reprodução"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Procurar coleção"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2924,679 +3116,771 @@ msgstr ""
 "Para importar a coleção de músicas para o Audacious, escolha a pasta e "
 "clique no ícone \"Atualizar\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Aguarde..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Escolha a pasta"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Reprodutor SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Saída</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Canais:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Emulação</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Emular MOS 8580 (pré-definição: MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Não escolher modelo automaticamente"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Filtro de emulação"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Velocidade do relógio:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Não escolher automaticamente a velocidade do relógio"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Tempo de reprodução</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Definir tempo máximo de reprodução:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Apenas se a duração da faixa for desconhecida"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Definir o tempo mínimo de reprodução"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtunes</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Ativar subtunes"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Ignorar subtunes inferiores a:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Nota</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Remoção de silêncio"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
 msgstr ""
+"Suplemento Silence Removal\n"
+"Direitos de autor 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Remoção de silêncio</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Limite:"
 
-#: src/skins/menus.c:57
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Abrir ficheiros..."
+
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
-msgstr ""
+msgstr "Abrir URL..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Procurar na coleção"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Reprodução"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Lista de reprodução"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Ver"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Serviços"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Sobre..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Definições..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Sair"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
-
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Repetir"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Baralhar"
+msgstr "Informações da faixa..."
 
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Sem avanço na lista de reprodução"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
-
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Anterior"
+msgstr "Parar após esta faixa"
 
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
-msgstr ""
+msgstr "Definir repetição A-B"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
-msgstr ""
+msgstr "Remover repetição A-B"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Ir para a faixa..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Ir para posição temporal..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr ""
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Reproduzir/Retomar"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nova lista de reprodução"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Mudar nome da lista de reprodução..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Remover lista de reprodução..."
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Lista de reprodução anterior"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Próxima lista de reprodução"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Importar lista de reprodução..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Exportar lista de reprodução..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Gestão da lista de reprodução..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Gestão da fila de reprodução..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Atualizar lista de reprodução"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Mostrar editor de listas de reprodução"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Mostrar equalizador"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Mostrar tempo restante"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Sempre visível"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "Em todas as áreas de trabalho"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
-msgstr ""
+msgstr "Recolher reprodutor"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
-msgstr ""
+msgstr "Recolher editor de listas"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
-msgstr ""
+msgstr "Recolher equalizador"
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Tamanho duplo"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "Adicionar URL..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Adicionar ficheiros..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Por título"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Por nome de ficheiro"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "Por caminho"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Remover tudo"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Limpar fila de reprodução"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Remover ficheiros indisponíveis"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Remover duplicados"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Remover desmarcadas"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Remover seleção"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Procurar e selecionar"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Inverter seleção"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Não selecionar"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Selecionar tudo"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Por álbum"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Por número de faixa"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Por artista"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Por álbum"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Por artista do álbum"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
-msgstr ""
+msgstr "Por data de lançamento"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Por número de faixa"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Por género"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Por duração"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Por título personalizado"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Lista aleatória"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Inverter lista"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
-msgstr "Ordenar seleção"
+msgstr "Organizar seleção"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Ordenação"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Cortar"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Copiar"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Colar"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "Colocar/retirar da fila"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Carregar pré-ajuste..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
-msgstr ""
+msgstr "Carregar pré-ajuste automático"
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Carregar pré-definido"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Carregar ficheiro de pré-ajuste..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Carregar ficheiro EQF..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Gravar pré-ajuste..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
-msgstr ""
+msgstr "Gravar pré-ajuste automático..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Gravar pré-definido"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Gravar ficheiro de pré-ajuste..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Gravar ficheiro EQF..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Eliminar pré-ajuste..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
-msgstr ""
+msgstr "Eliminar pré-ajuste automático..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Importar pré-ajuste Winamp..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "Repor para zero"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Interface clássica Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Gravar"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Carregar"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Carregar ficheiro de pré-ajuste"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Carregar ficheiro EQF"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Gravar ficheiro de pré-ajuste"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Gravar ficheiro EQF"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Importar pré-ajuste Winamp"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Pré-ajuste"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Carregar pré-ajuste"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Carregar pré-ajuste automático"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Gravar pré-ajuste"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Gravar pré-ajuste automático"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Eliminar pré-ajuste"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Eliminar pré-ajuste automático"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "Re_produtor:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Reprodutor:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Selecione o tipo de letra do reprodutor:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Lista de reprodução:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Lista de reprodução:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Escolha o tipo de letra da lista de reprodução:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Tema</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Tipos de letra</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Utilizar letras bitmap (só para ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Deslocar título da faixa"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Deslocar título em ambas as direções"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analisador"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Scope"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
-msgstr ""
+msgstr "Voiceprint/Medidor VU"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Desligado"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Fogo"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr ""
+msgstr "Linhas verticais"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Linhas"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Barras"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Mais lento"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Lento"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rápido"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Mais rápido"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "Pontos"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Linha"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Sólido"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Gelo"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Suave"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Tipo</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Tipo de visualização:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Analisador</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Mostrar picos"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Coloração:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Estilo:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
-msgstr ""
+msgstr "Recurso:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
-msgstr ""
+msgstr "Recurso de picos:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
-msgstr ""
+msgstr "Estilo de scope:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
-msgstr ""
+msgstr "Coloração Voiceprint:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
-msgstr ""
+msgstr "Estilo do medidor VU:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Geral"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Visualização"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Amplificador"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Equalizador do Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Ir para %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Volume: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Equilíbrio: %d%% à esquerda"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Equilíbrio: centro"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Equilíbrio: %d%% à direita"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Menu de opções"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Desativar \"Sempre visível\""
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Ativar \"Sempre visível\""
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Caixa de informações de ficheiro"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Visualizações"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Ponto de repetição A definido"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Ponto de repetição B definido"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
-msgstr "Pontos de repetição eliminados"
-
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Modo simples"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Modo lista de reprodução"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Para após a faixa"
+msgstr "Pontos de repetição removidos"
 
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Procurar entradas na lista de reprodução ativa"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3608,57 +3892,61 @@ msgstr ""
 "minúsculas. Se não sabe o que são expressões regulares, basta inserir uma "
 "parte do que pretende procurar."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "Título:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "Álbum: "
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "Artista: "
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Nome do ficheiro:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Nome de ficheiro:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Limpar seleção anterior antes de procurar"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Alternar fila automaticamente para as entradas coincidentes"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Criar lista de reprodução com as entradas coincidentes"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor de listas de reprodução"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d de %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Tema Winamp 2.x arquivado"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Tema Winamp 2.x não arquivado"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Não foi possível criar o diretório (%s): %s.\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Suplemento Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3699,82 +3987,71 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Suplemento Sndfile"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Saída Sndio"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sobre o Sndio"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Suplemento Sndio\n"
-"\n"
-"Desenvolvido por Thomas Pfaff <tpfaff at tp76.info>.\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Dispositivo (vazio para predefinição):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Formato não suportado"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Gravar e restaurar volume:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Foi solicitado um formato não suportado pelo dispositivo.\n"
-"\n"
-"Tente novamente com o servidor sndiod(1) em execução."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Erro Sndio: formato áudio não suportado (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "Dispositivo sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Erro Sndio: falha sio_open()"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(vazio significa as predefinições)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Erro Sndio: falha sio_setpar()"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Aceitar"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Erro Sndio: falha sio_start()"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Alteração de faixa"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Comando a executar ao iniciar uma nova faixa."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Os parâmetros enviados à consola devem ser envolvidos em "
+"aspas. Se não o fizer corre riscos de segurança.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Comandos</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Comando:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Comando a executar ao inicar uma nova faixa:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Comando a executar ao terminar uma faixa."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Comando a executar ao terminar uma faixa:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Comando a executar ao atingir o fim de uma lista de reprodução."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Comando a executar no final de uma lista de reprodução:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr ""
-"Comando a executar se o título da faixa for alterado (para emissões web)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Comando a executar ao mudar o título da faixa (para emissões web):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3788,9 +4065,9 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Pode utilizar os formatos descritos em baixo, que\n"
-"serão substituídos antes da invocação do comando\n"
-"(nem todos podem ser utilizados como comando end-of-playlist).\n"
+"Pode utilizar os formatos descritos em baixo, que  serão substituídos antes "
+"de invocar o comando (nem todos podem ser utilizados como comando end-of-"
+"playlist).\n"
 "\n"
 "%F: frequência (em hertz)\n"
 "%c: número de canais\n"
@@ -3799,24 +4076,20 @@ msgstr ""
 "%n ou %s: nome da faixa\n"
 "%r: taxa (em bits por segundo)\n"
 "%t: posição na lista de reprodução (%02d)\n"
-"%p: a reproduzir atualmente (1 ou 0)\n"
+"%p: reprodução atual (1 ou 0)\n"
 "%a: artista\n"
 "%b: álbum\n"
 "%T: título da faixa"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Os parâmetros enviados à consola devem ser envolvidos em "
-"aspas. Se não o fizer corre riscos de segurança.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Informações da faixa (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Comandos"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Resampler"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3824,57 +4097,57 @@ msgid ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
-"SoX Resampler para o Audacious\n"
+"Suplemento SoX Resampler\n"
 "Direitos de autor 2013 Michał Lipski\n"
 "\n"
 "Baseado no suplemento Sample Rate Converter\n"
 "Direitos de autor 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Rápida"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Baixa"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Alta"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Muito alta"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Qualidade:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Velocidade e pitch"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Velocidade e pitch</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Velocidade:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Pitch:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Velocidade e pitch"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Ícone de estado"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "De_finições..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3892,39 +4165,39 @@ msgstr ""
 "Este suplemento disponibiliza um ícone de estado na área de notificação do "
 "seu gestor de janelas."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Ação da roda do rato</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Alterar volume"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Alterar faixa reproduzida"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Outras definições</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Desativar janela emergente"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Fechar para a área de notificação"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Avançar na lista de reprodução ao rolar para cima"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Ícone de estado"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra estéreo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3934,24 +4207,24 @@ msgstr ""
 "\n"
 "Por Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra estéreo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra estéreo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Gerador de tons"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Gerador de tons:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3967,15 +4240,11 @@ msgstr ""
 "exemplo: tone://2000;2005 para reproduzir um tom de 2000 Hz e outro de 2005 "
 "Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Gerador de tons"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Remoção de voz"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4014,11 +4283,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Descodificador Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Detalhes para %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Título: %t\n"
+"Autor: %a\n"
+"De: %f\n"
+"Tracker: %T\n"
+"Comentário: %C\n"
+"Tipo de chip: %c\n"
+"Estéreo: %s\n"
+"Loop: %l\n"
+"Frequência do chip: %F\n"
+"Frequência do reprodutor: %P\n"
+"Ano: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Descodificador VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4028,19 +4332,19 @@ msgstr ""
 "Baseado em in_vtx.dll de Roman Sherbakov <v_soft at microfor.ru>\n"
 "Adaptação ao Audacious por Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Descodificador VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Descodificador WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "com perda (híbrido)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "com perda"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4050,14 +4354,18 @@ msgstr ""
 "\n"
 "Parte do código foi desenvolvido por Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Descodificador WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Descodificador 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Configuração XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Ignorar duração do ficheiro"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "Listas de reprodução XML Shareable (XSPF)"
diff --git a/po/ru.po b/po/ru.po
index 9bcfc4feb0f0..d5cfc84395d5 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -4,37 +4,39 @@
 #
 # Translators:
 # Alexander Orlov <alxorlov at pochta.ru>, 2007
-# dane <alpi_bel at mail.ru>, 2014
+# Денис <alpi_bel at mail.ru>, 2014
+# Andrei Stepanov, 2014
 # Someonefree <drag-sasha at mail.ru>, 2013-2014
 # arinov <i.arinov at iht.kz>, 2014
 # iavojd <iavojd at gmail.com>, 2013
 # iavojd <iavojd at gmail.com>, 2013
 # joshuazzz <joshuazzz at yandex.ru>, 2012
 # joshuazzz <joshuazzz at yandex.ru>, 2012
-# StreamThreaedr <kvantarium at gmail.com>, 2012
-# Maxim Musatov <m1kc at yandex.ru>, 2012
-# Maxim Musatov <m1kc at yandex.ru>, 2012
+# Oleg <kvantarium at gmail.com>, 2012
+# Max Musatov <m1kc at yandex.ru>, 2012
+# Max Musatov <m1kc at yandex.ru>, 2012
 # NaiLi (aka jamesjames) Rootaerc <theism at mail.ru>, 2012-2013
 # NaiLi (aka jamesjames) Rootaerc <theism at mail.ru>, 2012
-# NEKURIM <kvadrocu7 at gmail.com>, 2013
+# Алексей <kvadrocu7 at gmail.com>, 2013
+# Lowrider <pams at imail.ru>, 2014-2015
 # Rax Garfield <admin at dvizho.ks.ua>, 2012
 #   <sejava at mail.ru>, 2012
-# senyalutyi <senyalutyi at ya.ru>, 2013
-# senyalutyi <senyalutyi at ya.ru>, 2013
+# Senya <senyalutyi at ya.ru>, 2013
+# Senya <senyalutyi at ya.ru>, 2013
 # serg0 <sergo at bk.ru>, 2010
 # Sergey V. Mironov <serg0 at ulx.ru>, 2009
 # serg0 <sergo at bk.ru>, 2010
 # Someonefree <drag-sasha at mail.ru>, 2013
-# StreamThreaedr <kvantarium at gmail.com>, 2012
+# Oleg <kvantarium at gmail.com>, 2012
 # Victor Ponomarev <victor.a.ponomarev at gmail.com>, 2013
-# NEKURIM <kvadrocu7 at gmail.com>, 2013
+# Алексей <kvadrocu7 at gmail.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Russian (http://www.transifex.com/projects/p/audacious/"
 "language/ru/)\n"
 "Language: ru\n"
@@ -44,40 +46,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "моно"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стерео"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "объёмное звучание"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "Декодер AAC(MP4)"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "Декодер AAC(Raw)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (проигрыватель AdLib)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "последовательный"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (проигрыватель AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Будильник"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Установить Будильник,,,,"
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -87,11 +77,7 @@ msgstr ""
 "определенное время.\n"
 "Изначально написан Adam Feakin и Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Будильник"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -131,7 +117,7 @@ msgstr ""
 "или выберите переключатель для времени по умолчанию.\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -170,7 +156,7 @@ msgstr ""
 "Дополнительные команды:\n"
 "Выполнить эту команду при срабатывании сигнала.\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -193,385 +179,390 @@ msgstr ""
 "Введите в поле напоминание и включите\n"
 "- переключатель, если вы хотите, чтобы это было показано."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Это ваш звонок будильника"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Напоминание на сегодняшний день..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Напоминание"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Понедельник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Вторник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Среда"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Четверг"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Пятница"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Суббота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Воскресенье"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Настройки будильника"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "_ОК"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "Закончить"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Время"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Будильник в (по умолчанию):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "ч"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Перестать звонить после:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "часы"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "минуты"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Выберите дни, в которые будет срабатывать будильник"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "День"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "По умолчанию"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дни"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Плавное нарастание громкости"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунд"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Громкость"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Начать c"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "В конце"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Текущее"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Дополнительная команда"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "включить"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
-msgstr "Список воспроизведения (необязательно)"
+msgstr "Плейлист (необязательно)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Выберите список воспроизведения"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Параметры"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Что означают эти опции?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Справка"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Обложка альбома"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Иллюстрация альбома (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Вывод ALSA"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Плагин вывода для Audacious\n"
+"Авторство 2009-2012 John Lindgren\n"
+"\n"
+"Моя благодарность Уильяму Pitcock, автор Вывода ALSA NG, чей код служил "
+"ориентиром, когда руководства по ALSA было недостаточно."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Устройство PCM по умолчанию"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Микшер по умолчанию"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "Устройство PCM:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Микшер:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Компонент микшера:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Обходить ошибку зависания \"drain\" в ALSA"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "Плагин AMIDI (проигрыватель MIDI)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA Плагин вывода для Audacious\n"
-"Авторство 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"модульный музыкальный MIDI проигрыватель\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Моя благодарность Уильяму Pitcock, автор Вывода ALSA NG, чей код служил "
-"ориентиром, когда руководства по ALSA было недостаточно."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Вывод ALSA"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "Плагин AMIDI (проигрыватель MIDI)"
+"создатель Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"особые благодарности...\n"
+"\n"
+"Clemens Ladisch и Jaroslav Kysela\n"
+"за их прикольные программы aplaymidi и amixer; они\n"
+"реально полезны, также как руководства alsa-lib, позволяющие\n"
+"узнать больше о ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"за хорошо нарисованный логотип MIDI клавиатуры\n"
+"\n"
+"Tony Vroon\n"
+"за помощь при альфа-тестировании"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Заменить дефолтный усилитель на:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "Изменить полифонию по умолчанию:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Заменить ревербацию по умолчанию на:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "На"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Заменить хор по умолчанию на:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Воспроизведение</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Транспонирование: "
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "полутона"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Смещение ударных: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Расширенные</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "номера нот"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Считывать комментарии из MIDI-файлов"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Пропускать тишину"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Считывать тексты из MIDI-файлов"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Пропускать тишину в конце"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>Шрифт</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Синтезатор</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "Частота дискретизации:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Гц"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - выбор SoundFont файла"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "Закончить"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Открыть"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Имя файла"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Размер (байт)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Имя:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\">Информация MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Формат:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Длительность (мс):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Количество дорожек:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "переменный"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Time Div:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\">Комментарии и тексты MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* в этом MIDI-файле нет комментариев *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* в этом MIDI-файле нет текстов *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "Закрыть"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (неверный UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Об AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "Модуль AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"модульный проигрыватель MIDI\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"написан Giacomo Lozito\n"
-"< james at develia.org >\n"
-"\n"
-"\n"
-"отдельные благодарности...\n"
-"\n"
-"Clemens Ladisch и Jaroslav Kysela\n"
-"за их отличные программы aplaymidi и amixer; они\n"
-"действительно полезные, как и документация alsa-lib для того,\n"
-"чтобы узнать больше об интерфейсе библиотеки ALSA\n"
-"\n"
-"Alfredo Spadafina\n"
-"за прекрасный логотип миди-клавиатуры\n"
-"\n"
-"Tony Vroon\n"
-"за большую помощь в альфа-тестировании"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -589,152 +580,148 @@ msgstr ""
 "В основе библиотека Ghosd Evan Martin'а:\n"
 " http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (всплывающие сообщения)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Прямоугольник"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Скруглённый прямоугольник"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Вогнутый прямоугольник"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Нет"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Начало воспроизведения"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Показать OSD в начале воспроизведения."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Изменение названия"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Показать OSD, если в процессе воспроизведения меняется название, но имя "
-"файла остаётся прежним. Полезно для отображения названий при воспроизведении "
-"из сети."
+"Переключает экранное меню, когда название композиции меняется (для интернет "
+"потоков)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Пауза вкл."
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Показать OSD, когда воспроизведение приостанавливается."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Пауза выкл."
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Показать OSD, когда воспроизведение возобновляется."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Расположение"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Смещение по оси X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Смещение по оси Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Максимальная ширина OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Параметры для систем с несколькими мониторами"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Показать OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "на всех мониторах"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "на мониторе %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Время (мс)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "отображения:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "появления:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "затухания:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Шрифты"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Шрифт %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Тень"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Стиль отображения"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Цвета"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Цвет %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Включить событие"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Событие"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Найден композитный менеджер"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -744,113 +731,113 @@ msgstr ""
 "Пожалуйста, запустите композитный менеджер; в противном случае\n"
 "OSD не будет работать корректно."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr ""
 "Для режима \"Имитированная прозрачность\" композитный менеджер не требуется."
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Прозрачность"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Имитированная прозрачность"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Настоящая прозрачность (требуется расширение X Composite)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Расширение X Composite не загружено"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Расширение X Composite недоступно"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Параметры модуля Audacious OSD"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Тест"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Сделать"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Положение"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анимация"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Стиль"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "События"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Прочее"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Тест"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 Плейлисты"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "Списки воспроизведения ASXv1/ASXv2"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Списки воспроизведения Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Цвет</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Размывающийся уровень"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Стереофонический в бинауральный по Бауэру (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Заготовки:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Уровень смешивания каналов:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 дБ"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Частота среза:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Заготовки:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Стереофонический в бинауральный по Бауэру (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Анализатор спектра"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Плагин Audio CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -874,171 +861,158 @@ msgstr ""
 "\n"
 "Copyright 2009 John Lindgren"
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Устройство</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Скорость чтения:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Переопределить устройство:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метаданные</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Использовать CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Использовать CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Использовать HTTP вместо CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Пусть:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Порт:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Плагин Audio CD"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Ошибка при инициализации CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Некорректный URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Трек %d не найден."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Дорожка %d это данные дорожки."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Не удалось задействовать аудио-вывод."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Ошибка чтения Аудио CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Audio CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Дорожка %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Не удалось открыть устройство CD %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Не найдено совместимого CD-устройства."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Ошибка при инициализации CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Failed to retrieve first/last track number."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Невозможно считать начало/конец LSN для трека %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Не удалось создать cddb соеденения."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Не удалось выполнить запрос к базе CDDB сервера"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Не удалось выполнить запрос к базе CDDB сервера: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Не удалось прочитать cddb информацию: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Привод пуст."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Неподдерживаемый тип диска."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Пункты меню Audio CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Воспроизвести CD-диск"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Добавить CD-диск"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Пункты меню Audio CD"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Сжатие</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Центр громкости:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамический диапазон:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Сжатие динамического Диапазона Плагин для Audacious\n"
-"Авторство 2010-2012 Джон Линдгрен"
+"Надстройка сжатия динамического диапазона для Audacious\n"
+"Авторское право 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Компрессор широкого диапозона"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1055,207 +1029,226 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>⏎\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Бас:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Высокие:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Эхо"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Длительность композиции по умолчанию:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Передискретизация</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Включить преобразование"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Преобразование частоты:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Гц"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Игнорировать длительность из тегов SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Увеличить реверберацию"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Декодер звука игровой консоли"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Кроссфэйдер столкнулся с ошибкой, потому что песня имеет другое количество "
-"каналов.  Вы можете использовать микшер каналов, чтобы конвертировать песню "
-"в то же количество каналов."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Выход CoreAudio"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Кроссфэйдер столкнулся с ошибкой, потому что песня имеет другую частоту "
-"дискретизации. Вы можете использовать конвертер частоты дискретизации для "
-"конвертирования песни в ту же частоту."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Эксклюзивный режим"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Плагин перекрестного затухания для Audacious⏎\n"
-"Авторство 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Плавный переход</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "При автоматической смене композиции"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Перекрытие:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "При поиске или самостоятельной смене композиции"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Совет</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Плавный переход"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Кроссфэйдер столкнулся с ошибкой, потому что песня имеет другое количество "
+"каналов.  Вы можете использовать микшер каналов, чтобы конвертировать песню "
+"в то же количество каналов."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Кроссфэйдер столкнулся с ошибкой, потому что песня имеет другую частоту "
+"дискретизации. Вы можете использовать конвертер частоты дискретизации для "
+"конвертирования песни в ту же частоту."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристализатор</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Интенсивность:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристализатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Плагин Cue листов"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Удалить файлы"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Ошибка при перемещении %s в корзину: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "ошибка удаления %s: %s"
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Ошибка удаления %s: это не локальный файл."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Вы хотите удалить  выбранные файлы в корзину?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Удалить в Корзину"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Вы хотите удалить без восстановления выбранные файлы”?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Удалить"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Отмена"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Удалить файлы"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Удалить выбранный файлы"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Метод Удаления</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Перемещать в корзину вместо немедленного удаления"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Эхо</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Задержка:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "мс"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Обратная связь:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Громкость:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Модуль Эхо\n"
-"Автор Johan Levin, 1999.\n"
-"\n"
-"Объёмное эхо добавил Carl van Schaik 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Эхо"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Плагин FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1271,55 +1264,55 @@ msgstr ""
 "            William Pitcock <nenolod at nenolod.net>,\n"
 "            Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Плагин FFmpeg"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Плагин записи в файл"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Формат записываемого файла:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Настройка"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Сохранить в тот же каталог"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Сохранить в другой каталог"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Каталог для записываемых файлов:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Выбор каталога"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Получить название файла из:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Создавать имя файла из:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "имеющихся тегов файла"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Метка исходного файла"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "имеющегося имени файла"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Исходное имя файла"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Не удалять расширение имени файла"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Добавлять расширение к исходному имени файла"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Вписать до названия файла номер дорожки"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Добавить в начало названия файла номер дорожки"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1352,165 +1345,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "США."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Плагин записи в файл"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Автоматически"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Объединённое стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Параметры MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_ОК"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Качество алгоритма:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Выходная частота:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Частота дискретизации на выходе:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Гц)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Битрейт / Степень сжатия:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "Качество звука и степень сжатия:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Битрейт (кб/с)"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Степень сжатия:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Аудио режим:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Прочее:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "Строгое соответствие ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Защита от ошибок"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Качество"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Включить VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Тип:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Параметры VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Минимальный битрейт (кб/с):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Максимальный битрейт (кб/с):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Строгое соблюдение минимального битрейта"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Параметры ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Средний битрейт (кбит/с):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Уровень качества VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Не записывать заголовки Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Параметры кажра:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr "Параметры кадра:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Пометить как защищённое авторским правом"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Пометить как оригинальное"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "Параметры ID3:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Принудительное добавление тегов 2-й версии"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Только 1-я версия тегов"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Только 2-я версия тегов"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Теги"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Настройка кодека Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Уровень качества (0 – 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Декодер FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "lossless"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1522,11 +1519,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Декодер FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1534,11 +1527,19 @@ msgstr ""
 "GIO Плагин для Audacious⏎\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Плагин GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Недопустимый метод открытия"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1558,451 +1559,509 @@ msgstr ""
 "\n"
 "Лицензия: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL Спектральный Анализатор"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"Модуль \"Горячие клавиши\" для Gnome\n"
-"Управление проигрывателем при помощи \"горячих\n"
-"клавиш\", указанных в настройках Gnome.\n"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL Спектральный Анализатор (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Горячие клавиши Gnome"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Номер записи"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Название"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Исполнитель"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Год"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Альбом"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Исполнитель альбома"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Дорожка"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Положение в очереди"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Длительность"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Путь к файлу"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Имя файла"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Задать название"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Битрейт"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Доступные колонки"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Показанные колонки"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Поиск"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Прикрепить слева"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Прикрепить справа"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Прикрепить наверху"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Прикрепить внизу"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Открепить"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Отключить"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Поиск"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Открыть файлы ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Открыть _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Добавить файлы ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Добавить U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Поиск в библиотеке"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "О_ программе ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Настройки"
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Выход"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Воспроизведение"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Пауз_а"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Стоп"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Пре_дыдущий"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Следующий"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Повтор"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "В_разброс"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Н_е передвигаться по списку"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
-msgstr "Остановка после етой песни"
+msgstr "Остановка после этой песни"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Информация о _песне"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Перейти ко _времени ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_Перейти к песне ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Повтор установки _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Повтор установки _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Повтор чистых пунктов"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "По _названию"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "По _Имени"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "По _имени файла"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Путь к файлу"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "По _номеру трека"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "По _исполнителю"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "По Альбому"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "По исполнителю"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "По _дате выпуска"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "По _жанру"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "По _Длинне"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "По расположению _файла"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "По _заданному названию файла"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "В _обратном порядке"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "В _случайном порядке"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Воспроизвести этот список"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Воспроизвести/продолжить"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "Обновить"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Сортировать"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Сортировать выбранные"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Удалить _Дубликаты"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Убрать _недоступные файлы"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Новый"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Пере_именовать"
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "Убрать"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Импортировать ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Экспортировать ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "_Управление списками..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_Управление очередью ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Увеличить громкость"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Уменьшить громкость"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Эквалайзер"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "Э_ффекты"
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Показывать _панель меню"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Показывать п_анель информации"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Показывать Info Bar Vis_ualization"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Показывать _строку состояния"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Показать _Оставшееся время"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Визуализация..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Файл"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Воспроизведение"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "С_писок"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Службы"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Вывод"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Вид"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Элемент очереди"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Открыть расположение файла"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Вырезать"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Копировать"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Вставить"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Выбрать _всё"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Пере_именовать..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Вкладки плейлиста</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Всегда показывать вкладки"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Показывать счетчик элементов"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Показывать кнопки закрытия"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Колонки плейлиста</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Показывать заголовки столбцов"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Разное</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Поиск стрелками:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Прокручивать при смене песни"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Интерфейс GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Буферизация ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "моно"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стерео"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -2010,84 +2069,98 @@ msgstr[0] "%d канал"
 msgstr[1] "%d канала"
 msgstr[2] "%d каналов"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d кбит/с"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Одиночный режим"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Режим списка воспроизведения"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Остановить после дорожки"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Предыдущая дорожка"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Воспроизвести"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Пауза/Продолжить"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Остановить"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Следующая дорожка"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Перемотать вперёд на 5 сек"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Перемотать назад на 5 сек"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Приглушить"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Увеличить громкость"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Уменьшить громкость"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Перейти к файлу"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Переключить состояние окон проигрывателя"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Отобразить экранное сообщение (OSD)"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Повтор"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Перетасовка"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Остановить после текущего"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Поднять окно(а) плеера"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(нет)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2099,15 +2172,11 @@ msgstr ""
 "\n"
 "Продолжить?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Привязки к кнопкам мыши"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Параметры модуля Глобальные \"горячие клавиши\""
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2115,23 +2184,27 @@ msgstr ""
 "Нажмите комбинацию клавиш в текстовом поле.\n"
 "Можно также сделать привязки к кнопкам мыши."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Горячие клавиши:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Действие:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Привязка клавиш:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "Добавить"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Глобальные горячие клавиши"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2158,60 +2231,54 @@ msgstr ""
 "\t\t\tJonathan A. Davis <davis at jdhouse.org>\n"
 "\t\t\tJeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Глобальные горячие клавиши"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Вывод JACK"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Подсоединиться к доступным портам"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Автоматически подключаться к портам вывода"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Подсоединиться только к портам вывода"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Обнаружены только выходные разъёмы %d JACK, но требуется %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Не подключаться ни к каким портам"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Ошибка подключения к разъёму JACK %s."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Режим соединения:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Выводить отладочную информацию"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Сбой подключения к серверу JACK; он работает?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Основан на xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Портирован в Audacious Giacomo Lozito"
+"Сервер JACK требует частоту семплов %d Гц, но Audacious воспроизводит на %d "
+"Гц. Пожалуйста, используйте эффект конвертера частоты семплов для устранения "
+"несовпадений."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "Вывод JACK"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Настройки"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Настройки хоста LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Путь к модулям:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2221,25 +2288,25 @@ msgstr ""
 "Поиск осуществляется по указанным путям и переменной LADSPA_PATH.\n"
 "Указав пути, нажмите Enter для поиска новых плагинов.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Доступные плагины:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Включить"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Включенные плагины"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Настройки"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2247,47 +2314,15 @@ msgstr ""
 "LADSPA Хост для Audacious\n"
 "Авторство 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "Сервер LADSPA"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: не могу инициализировать поддержу LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: не могу прочесть конфигурационный файл LIRC\n"
-"%s: пожалуйста прочтите документацию к LIRC\n"
-"%s: как создать правильный конфигурационный файл\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: пытаюсь переподключиться...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: неизвестная команда \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: отключен от LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: переподключаться каждые %d секунд...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Плагин LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2316,73 +2351,81 @@ msgstr ""
 "\n"
 "Больше инфромации про LIRC, смотрите http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Подключение</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Переподключиться к LIRC серверу"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Ждать перед переподключением:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Плагин LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Плагин LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Текст песни недоступен"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Ошибка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Не удалось получить %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Ошибка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Не удалось проанализировать %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Поиск текста песни ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Метаданные песни отсутствуют"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Устанавливаю соединение с lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Плагин LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Надстройка LyricWiki (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "Списки воспроизведения M3U"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Генератор тактов"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Тактовый генератор: %d тактов/с"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Тактовый генератор: %d уд/мин %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2396,11 +2439,11 @@ msgstr ""
 "например tact://77 to play 77 beats per minute\n"
 "или tact://60*3/4 to play 60 bpm in 3/4 tacts"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Генератор тактов"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Микшер каналов"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2408,152 +2451,184 @@ msgstr ""
 "Плагин смешивания каналов Audacious\n"
 "Авторство 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Микшер каналов</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Каналов на выходе:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Микшер каналов"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Плагин MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Ошибка подключения к серверу MMS"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (модульный плеер)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Разрешение</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-бит"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-бит"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Каналы</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Ближайший (самый быстрый)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Линейный (быстрый)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Сплайн (хороший)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Многофазный (лучший)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>Частота дискретизации</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 кГц:"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 кГц:"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 кГц:"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 кГц:"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Уровень:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Отключение:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Реверберация</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Усиление басов</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Окружение</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Предусилитель</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Перекрытие"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Шумоподавление"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Воспроизвести модификацию Amiga"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Повторить</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Счетчик повторений:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Повторять всегда, задать число повторов до -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (модульный плеер)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Объёмное звучание"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "Настройки вступят в силу после перезапуска Audacious."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Плагин MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Расширенные</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Использовать аккуратное вычисление длины (медленно)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Объёмное звучание"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Сервер MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Плагин Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Ошибка парсинга перенаправлений"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Неизвестная ошибка HTTP"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Ошибка парсинга URL"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Слишком много перенаправлений"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Остановлен"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious ничего не воспроизводит."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Всплывающие сообщения"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2584,55 +2659,64 @@ msgstr ""
 "Вы должны были получить копию стандартной Общественной Лицензии GNU вместе с "
 "этой программой. Если нет,смотрите <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Показать кнопки управления воспроизведением"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Всегда показывать уведомления"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Всплывающие сообщения"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Включить название альбома в уведомление"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Показать"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Пауза"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Следующая дорожка"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Устройство по умолчанию"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "Вывод OSS4"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "Выход OSS3"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Устройство по умолчанию"
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Звуковое устройство:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Использовать другое устройство:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Сохранять громкость между сессиями."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Разрешить преобразования формата с помощью OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Включить монопольный режим, чтобы избежать виртуального микширования."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2646,19 +2730,35 @@ msgstr ""
 "Я хочу поблагодарить тех людей  #audacious, особенно Тони Vroon и Джон "
 "Линдгрен и, конечно же авторов предыдущих OSS плагин."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "Вывод OSS4"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Списки воспроизведения"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Элементы"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Удалить"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "Пере_именовать"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "Списки воспроизведения PLS"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Декодер OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Вывод PulseAudio"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2696,11 +2796,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "США."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Вывод PulseAudio"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Выход QtMultimedia"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Плагин QtMultimedia Audio Output для Audacious\n"
+"Права защищены 2014 Уиллиам Питкок\n"
+"\n"
+"Основан на плагине SDL Output для Audacious\n"
+"Права защищены 2010 Джон Линдгрэн"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Работаю ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Поиск"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "_Oткрыть папку ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Добавить папку ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "_Инспектор журнала ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Открыть файлы"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Добавить файлы"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Предыдущая дорожка"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Повтор"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Случайно"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Интерфейс Qt"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Конвертер частоты"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2708,99 +2870,107 @@ msgstr ""
 "Конвертер частоты дискретизации Плагин для Audacious\n"
 "Авторство 2010-2012 Джон Линдгрен"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Пропустить/повторить сэмплы"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Линейная интерполяция"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Быстрая sinc интерполяция"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Средняя sinc интерполяция"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Лучшая sinc интерполяция"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Преобразование</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метод:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Частота:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Карта частот</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Использвать карту частот"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 кГц:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 кГц:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 кГц:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 кГц:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 кГц:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 кГц:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 кГц:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 кГц:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 кГц:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 кГц:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Конвертер частоты"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "OK. Прослушивание для пользователя: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Отказано в доступе"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Воспользуйтесь следующей ссылкой чтобы разрешить Audacious отправлять "
 "прослушанные композиции на Last.fm:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Оставте это окно открытым и нажмите кнопку \" Запросить разрешение' снова.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2809,34 +2979,38 @@ msgstr ""
 "Он будет доставлен на Last.fm, как только Audacious получит разрешение это "
 "сделать."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Проблемы с сетью"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Невозможно подключится к Last.fm. Попробуйте повторить позже"
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Проверка..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "З_апросить разрешение"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Отменить разрешение"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Вы должны разрешить Audacious отправлять прослушанные дорожки в ваш аккаунт "
 "Last.fm\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Скробблер 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2844,7 +3018,7 @@ msgstr ""
 "Плагин scrobbler не может быть запущен.\n"
 "Могут быть проблемы с установкой"
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2860,11 +3034,7 @@ msgstr ""
 "\n"
 "Спасибо Джону Линдгрен что подал мне руку в начале этого проекта.\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Скробблер 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2872,7 +3042,11 @@ msgstr ""
 "Audacious теперь использует усовершенствованную версию модуля Last.fm "
 "Scrobbler"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "Вывод SDL"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2881,88 +3055,59 @@ msgstr ""
 "SDL модуль Вывода для Audacious\n"
 "Авторство 2010 Джон Линдгрен"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "Вывод SDL"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Библиотека"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Неизвестный исполнитель"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Неизвестный альбом"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"от %s до %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d результат"
+msgstr[1] "%d результатов"
+msgstr[2] "%d результатов"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d альбом"
-msgstr[1] "%d альбомы"
-msgstr[2] "%d альбомы"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d скрыто)"
+msgstr[1] "(%d скрыто)"
+msgstr[2] "(%d скрыто)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d песня"
-msgstr[1] ""
-"%s\n"
-" %s, %d песни"
-msgstr[2] ""
-"%s\n"
-" %s, %d песни"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d песня до %s"
-msgstr[1] ""
-"%s\n"
-" %d песни до %s"
-msgstr[2] ""
-"%s\n"
-" %d песни до %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d песня"
+msgstr[1] "%d песен"
+msgstr[2] "%d песен"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "этого жанра"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "на"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "от"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Создать список воспроизведения"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Добавить в список воспроизведения"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Поиск в библиотеке"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2970,679 +3115,771 @@ msgstr ""
 "Для импорта музыки в библиотеку Audacious выберите каталог, затем нажмите "
 "иконку \"обновить\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Пожалуйста, подождите ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Выберите каталог"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Проигрыватель SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Вывод</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Каналы:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Эмуляция</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Не выбирать модель чипа автоматически"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Имитировать фильтр"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Время воспроизведения</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Назначить максимальное время воспроизведения:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Задействовать в случае, когда длина композиции неизвестна"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Назначить минимальное время воспроизведения:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Шумоподавление"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Плагин шумоподавления для Audacious\n"
+"Права защищены 2014 Джон Линдгрэн"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Шумоподавление</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Примесь:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "дБ"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Открыть файлы..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Открыть URL..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Поиск в библиотеке"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Воспроизведение"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
-msgstr "Список воспроизведения"
+msgstr "Плейлист"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Вид"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Службы"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "О..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "настройки ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Выход"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Информация о песне"
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Повтор"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Случайно"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Без движения по списку воспроизведения"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Остановить после этой песни"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Предыдущая дорожка"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Установить A-B повтор"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Удалить A-B повтор"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Перейти к песне ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Перейти ко времени ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Воспроизвести этот список"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Воспроизвести/продолжить"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Новый список воспроизведения"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr "Переименовать список воспроизведения"
+msgstr "Переименовать список"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Удалить плейлист"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Предыдущий список"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Следующий список"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Импортировать список воспроизведения"
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Экспортировать список воспроизведения"
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Управление списками..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Управление очередью ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Обновить список воспроизведения"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Отобразить редактор списка воспроизведения"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Отобразить эквалайзер"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Показать Оставшееся время"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Поверх всех окон"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "На всех рабочих столах"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Свернуть проигрыватель"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Свернуть редактор списка воспроизведения"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Свернуть эквалайзер"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Двойной размер"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Добавить URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Добавить файлы..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "По названию"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "По имени файла"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "По расположению _файла"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Удалить все"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Очистить очередь"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Удалить недоступные файлы"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Удалить дубликаты"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Удалить не отмеченные"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Удалить выбранные"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Найти и выбрать"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Инвертировать выбор"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Снять выделение"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Выбрать все"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "По номеру дорожки"
+
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
+msgid "By Artist"
+msgstr "По исполнителю"
+
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
 msgid "By Album"
 msgstr "По альбому"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
-msgid "By Artist"
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
 msgstr "По исполнителю"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "По _дате выпуска"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "По номеру дорожки"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "По жанру"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "По длительности"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "По _заданному названию файла"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Сортировать в случайном порядке"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "В обратном порядке"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Сортировать выбранные"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Сортировать список"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Вырезать"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Копировать"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Вставить"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "В очередь/Из очереди"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Загрузить Предустановку"
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Загрузить Авто Установку..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Загрузить по умолчанию"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Загрузить файл предустановки"
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Загрузить EQF файл ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Сохранить предустановки...."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Сохранить авто установки..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Сохранить  по умолчанию"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "сохранить файл предустановки"
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Сохранить EQF Файл"
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Удалить предустановку..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Удалить авто установки..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Импортировать предустановки WinAMP'a...."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Сброс на Ноль"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Интерфейс классического Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Сохранить"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Загрузить"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Загрузить файл предустановки"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Загрузить EQF файл"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Сохранить файл предустановки"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Сохранить EQF файл"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Импортировать предустановки WinAMP'a"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Предустановки"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Загрузить предустановку"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Загрузить авто-установки"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Сохранить предустановки"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Сохранить автоустановки"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Удалить предустановку"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Удалить автоустановки"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
 msgstr "Проигрыватель:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Выберите шрифт основного окна проигрывателя:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "Список воспроизведения:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Список:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
-msgstr "Выберите шрифт списка воспроизведения:"
+msgstr "Выберите шрифт плейлиста:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Скин</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>Шрифты</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Использовать растровые шрифты (поддерживает только ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Прокручивать название песни "
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Прокручивать название песни в обоих направлениях"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Анализатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Осциллограмма"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Отпечаток голоса / VU измеритель"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Выкл."
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Обычный"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Огонь"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "Вертикальные линии"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Линии"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Полоски"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Очень медленно"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Медленно"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Средне"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Быстро"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Очень быстро"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Точки"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Линия"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Сплошная"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лёд"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Сглаженный"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Тип</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Тип визуализации:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Анализатор</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Показывать пики"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Окраска:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Стиль:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Спад:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Спад пиков:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Стиль осциллограммы:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Окраска отпечатка голоса:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Стиль VU измерителя:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Основной"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Визуализация"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Предусиление"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 кГц"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Эквалайзер Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Переход к %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Громкость: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Баланс: %d%% влево"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Баланс: по центру"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Баланс: %d%% вправо"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Меню параметров"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Отключить \"Поверх всех окон\""
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Включить \"Поверх всех окон\""
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Информация о файле"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Зрительные образы"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Повторить установки A"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Повторить установки B"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Повторить очищенные пункты"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Одиночный режим"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Режим списка воспроизведения"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Остановить после дорожки"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Поиск записей в активном списке воспроизведения"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Поиск"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3654,57 +3891,61 @@ msgstr ""
 "регистру. Если вы не знаете, как работают регулярные выражения, просто "
 "вставьте часть букв из слова, которые хотите найти."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Название: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Заголовок:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Альбом: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Альбом:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Исполнитель: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Артист:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Имя файла: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Имя файла:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Очистить предыдущий выбор до начала поиска"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Автоматически переключать поочерёдно на соответствующим записям"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Создать новый список воспроизведения с соответствующими записями"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Редактор списков воспроизведения Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d из %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Архивированная тема Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Не архивированная тема Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Невозможно создать каталог (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Плагин Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3744,84 +3985,73 @@ msgstr ""
 "программой; если этого не произошло, напишите во Free Software Foundation, "
 "Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Плагин Sndfile"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Выход Sndio"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "О плагине вывода Sndio"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
-"Плагин вывода Sndio\n"
-"\n"
-"Автор — Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Формат не поддерживается"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Ошибка Sndio: Неподдерживаемый звуковой формат (%d)"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
-"Формат не поддерживается запрошенным звуковым устройством.\n"
-"\n"
-"Попробуйте ещё раз, запустив сервер sndiod(1)"
-
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "Устройство sndio"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(пусто означает «по умолчанию»)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "ОК"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Смена дорожки"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Команда, запускаемая Audacious в начале воспроизведения новой дорожки"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Параметры, передаваемые оболочке, должны быть заключены в "
+"кавычки. В противном случае возможны проблемы с безопасностью</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Команды</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Команда:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Команда для выполнения после начала воспроизведения новой композиции:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Команда, запускаемая после окончания дорожки"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Команда выполняемая после окончания композиции:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr ""
-"Команда, запускаемая Audacious при достижении конца списка воспроизведения"
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Команда выполняемая после окончания списка воспроизведения:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Команда, запускаемая при изменении названия дорожки (например, при "
-"воспроизведении из сети)"
+"Команда для выполнения при изменении названия композиции (для "
+"воспроизведения по сети):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3835,26 +4065,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Вы можете использовать следующие форматы строк, которые будут заменены перед "
-"вызовом команды (не все они полезны для команды окончания списка ). %F: "
-"Frequency (in hertz) %c: Number of channels %f: filename (full path) %l: "
-"length (in milliseconds) %n or %s: Song name %r: Rate (in bits per second) "
-"%t: Playlist position (%02d) %p: Currently playing (1 or 0) %a: Artist %b: "
-"Album %T: Track title"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Параметры, передаваемые оболочке, должны быть заключены в "
-"кавычки. В противном случае возможны проблемы с безопасностью</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Команды"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Сведения о композиции (Qt)"
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX Ресемплер"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3868,51 +4088,51 @@ msgstr ""
 "Основан на плагине конвертора частоты дискретизации:\n"
 "Авторство 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Быстро"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Низкое"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Высокое"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Очень высокое"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Качество:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX Ресемплер"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Скорость и высота"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Скорость и высота</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Скорость:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Высота:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Скорость и высота"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Иконка статуса"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "Настройки ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3930,39 +4150,39 @@ msgstr ""
 "Этот модуль отображает значок программы\n"
 "в системном лотке"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Действие прокрутки мыши</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Изменить громкость"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Сменить текущую дорожку"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Другие настройки</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Отключить всплывающее окно"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Закрыть в системный трей"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Продвигаться по списку воспроизведения при прокрутке колёсика"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Иконка статуса"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Расширенное стерео"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3972,24 +4192,24 @@ msgstr ""
 "\n"
 "Johan Levin 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Расширенное стерео</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Расширенное стерео"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Генератор тона"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Гц"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Генератор сигналов: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -4004,15 +4224,11 @@ msgstr ""
 "частота1;частота2;частота3;...\n"
 "Например, tone://2000;2005 для воспроизведения сигналов 2000 Гц и 2005 Гц"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Генератор тона"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Удаление вокала"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4048,11 +4264,35 @@ msgstr ""
 "\n"
 "Посетите сайт Xiph.org Foundation по адресу http://www.xiph.org/"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Декодер Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Сведения о %s"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Декодер VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4062,19 +4302,19 @@ msgstr ""
 "Основан на коде in_vtx.dll от Roman Sherbakov <v_soft at microfor.ru>\n"
 "Реализацию для Audacious выполнил Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Декодер VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Декодер WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "lossy (hybrid)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "lossy"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4084,14 +4324,18 @@ msgstr ""
 "\n"
 "Некоторый код плагина Miles Egan"
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Декодер WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Декодер 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>Настройки XSF</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Не придавать значение длительности из файла"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XSPF"
diff --git a/po/si.po b/po/si.po
index 00dbde9564e5..292486fee293 100644
--- a/po/si.po
+++ b/po/si.po
@@ -3,16 +3,19 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# ashintha89 <ashintha at gmail.com>, 2013
-# D.N.Perera <deen.niro at gmail.com>, 2013
+# Ashintha Rukmal Perera <ashintha at gmail.com>, 2013
+# Ashintha Rukmal Perera <ashintha at gmail.com>, 2013-2014
+# Deenuka Niroshini Perera <deen.niro at gmail.com>, 2013
+# Deenuka Niroshini Perera <deen.niro at gmail.com>, 2013
+# P.I.Balasinghe <pushpika.indrachapa at gmail.com>, 2013
 # P.I.Balasinghe <pushpika.indrachapa at gmail.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Sinhala (http://www.transifex.com/projects/p/audacious/"
 "language/si/)\n"
 "Language: si\n"
@@ -21,40 +24,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr " තනි "
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "ත්‍රිමාන "
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "සිසාළ "
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "Adකෙවෙනිය (AdLib ධාවකය)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "අනුපිළිවෙළ"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "Adකෙවෙනිය (AdLib ධාවකය)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "සිහි කැඳවීම​"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -64,11 +55,7 @@ msgstr ""
 "⏎\n"
 "මුලින් ලියන ලද්දේ ඇඩම් ෆීකින් සහ ඩැනියෙල් ස්ටොඩ්ඩන් විසිනි."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "සිහි කැඳවීම​"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -110,7 +97,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -147,7 +134,7 @@ msgstr ""
 "වැඩිපුර විධාන:\n"
 "මෙම විධාන සිහිගන්වීමේ වෙලාවේදී ධාවනය කරන්න.\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -171,382 +158,370 @@ msgstr ""
 "කොටුව තුල සිහි කැදවුම ටයිප් කරන්න සහ ඔබට එය පෙන්වීමට\n"
 "අවශ්‍ය නම් ටොගල බොත්තම සක්‍රිය කරන්න "
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "මේ ඔබගේ සිහි කැඳවීමේ ඇමතුමයි."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "ඔබගේ අද දවසේ මතක් කිරීම වන්නේ..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "මතක් කිරීම​"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "සඳුදා"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "අඟහරුවාදා"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "බදාදා"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "බ්‍රහස්පතින්දා"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "සිකුරාදා"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "සෙනසුරාදා"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "ඉරිදා"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "සිහි කැඳවීම් සකසනයන්"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "වෙලාව​"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "සිහිකැඳවීම​ (පෙරනිමිය​)"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "පැ"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "පසු නිහඬවන්න:​"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "පැය​"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "මිනිත්තු"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "සිහි කැඳවීම් ලැබිය යුතු දිනයන් තෝරන්න​"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "දවස​"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "පෙරනිමිය​"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "දවස්"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "හායනය"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "තප්පර​"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "ශබ්ද මට්ටම​"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "ආරම්භ කරන්න​"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "අවසානය​"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "දැන්"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "අමතර විධාන​"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "සක්‍රීය​"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "ධාවනය වන ගොනුව (අමතර​)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "ධාවන ලැයිස්තුවක්​ තෝරන්න"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "විකල්ප​"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "මොනවාද මේ විකල්පයන්ගෙන් අදහස් වන්නේ?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "උදව්"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "ඇල්බම් කලාව"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA ප්‍රතිදානය "
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ඔඩෙෂස් සඳහා ALSA ප්‍රතිදාන පේනු  මෘදුකාංගය\n"
+"ප්‍රකාශන හිමිකම ජෝන් ලින්ඩ්ග්රෙන් 2009-2012\n"
+"මගේ ස්තුතිය ALSA  ප්‍රතිදාන පේනු  මෘදුකාංගයේ කර්තෘ විලියම් පිට්කොක් වෙත පුදන අතර ඔහුගේ කේතය "
+"ALSA අත්පොත ප්‍රමාණවත් නොවන විට ආදේශකයක් ලෙස භාවිතා කරන ලදී."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "පෙරනිමි PCM ආම්පන්නය "
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "පෙරනිමි මිශ්‍ර කිරීමේ ආම්පන්නය "
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM ආම්පන්නය:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "මිශ්‍ර කිරීමේ ආම්පන්නය:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "මිශ්‍ර කිරීමේ මූලද්‍රව්‍ය:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "ක්‍රමයෙන් අඩු වී නැවතීමක් පිළිබඳ ක්‍රියා කිරීම​"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-කෙවෙනිය (MIDI ධාවකය)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ඔඩෙෂස් සඳහා ALSA ප්‍රතිදාන පේනු  මෘදුකාංගය\n"
-"ප්‍රකාශන හිමිකම ජෝන් ලින්ඩ්ග්රෙන් 2009-2012\n"
-"මගේ ස්තුතිය ALSA  ප්‍රතිදාන පේනු  මෘදුකාංගයේ කර්තෘ විලියම් පිට්කොක් වෙත පුදන අතර ඔහුගේ කේතය "
-"ALSA අත්පොත ප්‍රමාණවත් නොවන විට ආදේශකයක් ලෙස භාවිතා කරන ලදී."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA ප්‍රතිදානය "
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-කෙවෙනිය (MIDI ධාවකය)"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "හර්ට්ස්"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-පේනු - SoundFont ගොනුව තෝරන්න​"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_අවලංගු කරන්න​"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "ගොනු නම​"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "ප්‍රමාණය (බයිට්ස්)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "නම​:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI තොරතුරු </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "හැඩතලය​:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "දිග (මිලි තප්පර​):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "ඛණ්ඩ ගණන:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "විචල්‍යය"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "කාලය​ බෙදීම​:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI අදහස් දැක්වීම් සහ පද රචනයන් </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* මෙම MIDI ගොනුවෙහි අදහස් දැක්වීම් නොමැත​ *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* මෙම MIDI ගොනුවෙහි පද රචනා නොමැත​ *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_වසන්න​"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(අවලංගු UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI-කෙවෙනිය ගැන "
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-පේනුව "
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"මොඩියුල MIDI ගීත ධාවකය \n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"රචනා කරන ලද්දේ Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"විශේෂ ස්තුතිය...\n"
-"Clemens Ladisch සහ  Jaroslav Kysela\n"
-"ඔවුන්ගේ වැඩසටහන් වන aplaymidi සහ  amixer; ඒවා \n"
-"ඉතා ප්‍රයෝජනවත් විය. එමෙන්ම alsa-lib ලේඛන \n"
-"ALSA API වැඩිදුර ඉගෙන ගැනීමට \n"
-"\n"
-"Alfredo Spadafina\n"
-"හට අලංකාර midi යතුරු පුවරු ලාංඡනය සඳහා \n"
-"\n"
-"Tony Vroon\n"
-"හට ඇල්ෆා පරීක්ෂණ සඳහා සහය දැක්වීම වෙනුවෙන් "
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -557,151 +532,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (තිරය මත සංදර්ශනය)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "ඍජුකෝණාශ්‍රය"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "වටකුරු කොන් සහිත​ ඍජුකෝණාශ්‍රය"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "අවතල ඍජුකෝණාශ්‍රය"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "කිසිවක් නැත​"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "පිළිවැයීම ආරම්භ කිරීම​"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "ධාවන ලැයිස්තු අයිතමයක් ක්‍රියාත්මක වනවිට OSD කියාත්මක කිරීම​"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "මාතෘකාව වෙනස්කිරීම"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"ධාවනය අතරතුර​, ගීත මාතෘකාව වෙනස් වුවද ගොනු නම එයම නම් OSD ක්‍රියාත්මක කිරීම​. අන්තර්ජාල "
-"ගලනයන්හි දී මාතෘකාව වෙනස් වීම් පෙන්වීමට මෙය ඉතා ප්‍රයෝජනවත් වේ."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "විරාමය ක්‍රියාත්මකයි"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "පිළිවැයීම් විරාමයේදී OSD ක්‍රියාත්මක කිරීම​"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "විරාමය ක්‍රියාවිරහිතයි"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "පිළිවැයීම් විරාමය අවසානයේදී OSD ක්‍රියාත්මක කිරීම​"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "ස්ථාපනය"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "සාපේක්ෂ X අනුලම්බය:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "සාපේක්ෂ Y අනුලම්බය:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "උපරිම OSD පළල:​"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "බහු මොනිටර විකල්ප​"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD දර්ශනයට​ භාවිතා කරන්න​:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "සියලුම මොනිටර​"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "මොනිටර​ය​ %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "කාල නියමය (මිලි තප්පර​)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "දර්ශනය​:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "ක්‍රමෝද්දීපනය:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "ක්‍රමාවදීපනය:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "අකුරු වර්ගය​"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "අකුරු වර්ගය ​%i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "සෙවනැල්ල​"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "විදැහුම් අන්දම"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "පාට​"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "පාට​ %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "ක්‍රියාරම්භකය සක්‍රිය කිරිම"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "සිද්ධිය​"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "සංයුක්ත කළමනාකාරකය හඳුනා ගන්නා ලදී"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -711,112 +681,112 @@ msgstr ""
 "දැනටමත් එකක් ධාවනය වෙමින් නොපවතී නම් කරුණාකර සංයුක්ත කළමනාකාරකයක් සක්‍රීය කරන්න​. එසේ නැතිනම් "
 "OSD නිසි ලෙස ක්‍රියා නොකරයි"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "ව්‍යාජ විනිවිද පෙනීම සඳහා සංයුක්ත කළමනාකාරකය අවශ්‍ය නැත​"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "විනිවිද පෙනීම"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "ව්‍යාජ විනිවිද පෙනීම​"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "සත්‍ය විනිවිද පෙනීම​ (X සංයුක්ත Ext. අවශ්‍යයයි)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "සංයුක්ත දිගුව​ ප්‍රවේශනය වී නොමැත​"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "සංයුක්ත දිගුව​ නොමැත​"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - වින්‍යාසය​"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "පිහිටීම​"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "සජීවනය​"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "පෙළ​"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "අලංකරණය"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "ක්‍රියාරම්භකය"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "විවිධ"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 ධාවන ලැයිස්තුව "
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "ඔඩෙෂස් ධාවන ලැස්තු (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>වර්ණ</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "නොපැහැදිලි විෂය පථය"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "ත්‍රිමාන ධ්වානික සංචාලන වල සිට ද්විකර්ණික වෙත (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "පෙර සකසන ලද:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "සංග්‍රහ මට්ටම:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "සංඛ්‍යාතය කපන්න:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "පෙර සකසන ලද:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "ත්‍රිමාන ධ්වානික සංචාලන වල සිට ද්විකර්ණික වෙත (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "වර්ණාවලි විශ්ලේශකය"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "ශ්‍රව්‍ය CD පේනු මෘදුකාංගය "
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -833,171 +803,156 @@ msgstr ""
 "උපදෙස් දීම සහ මගපෙන්වීම වෙනුවෙන් මගේ ස්තුතිය Tony Vroon වෙත පුද කරමි.\n"
 "මෙය 2007 වසරේ  Google Summer of Code ව්‍යාපෘතියකි."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>ආම්පන්නය</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "වේගයෙන් කියවන්න:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "ප්‍රතික්ෂේපිත ආම්පන්නය:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>පාරදත්ත</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "භාවිතා කරන්න CD-පෙළ "
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "භාවිතා කරන්න CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP වෙනුවට HTTP භාවිතා කරන්න​"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "සේවාදායකය:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "පථය:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "තොට:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "ශ්‍රව්‍ය CD පේනු මෘදුකාංගය "
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "cdio උප පද්ධතිය ඇරඹීම අසාර්ථකය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "අවලංගු  URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "ඛණ්ඩය %d සොයාගත නොහැක."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "ඛණ්ඩ %d දත්ත ඛණ්ඩයකි."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "ශ්‍රව්‍ය ප්‍රතිදානය විවෘත කිරීම අසාර්ථක විය."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "ශ්‍රව්‍ය CD කියවීමේ දෝෂය"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "ශ්‍රව්‍ය CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "CD අම්පන්නය  %s විවෘත කිරීම අසාර්ථක විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "ශ්‍රව්‍ය ක්‍රියා කල හැකි CD අම්පන්නය සොයාගත නොහැක."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "විවෘත කරන ලද CD අම්පන්නය අවසානය තෙක් ක්‍රියාත්මක කිරීම අසාර්ථක විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "පළමු/අවසාන ඛණ්ඩ අංකය සොයාගැනීම අසාර්ථක විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "ඛණ්ඩ  %d හි පළමු/අවසාන LSN කියවීමට නොහැක."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "cddb සම්බන්ධතාව තැනීම අසාර්ථක විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "CDDB සේවාදායකය විමසුමට අපොහොසත් විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "CDDB සේවාදායකය : %s විමසුමට අපොහොසත් විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "cddb තොරතුරු:  %s කියවීමට අපොහොසත් විය."
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "ධාවකය හිස්."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "සහාය නොමැති තැටි වර්ගයකි."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "ශ්‍රව්‍ය CD මෙනු අයිතම "
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "සංයුක්ත තැටිය​ ධාවනය කරන්න "
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "සංයුක්ත තැටිය එකතු කරන්න​"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "ශ්‍රව්‍ය CD මෙනු අයිතම "
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>හැකිලීම</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "මධ්‍ය ශබ්ද මට්ටම​ :"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "ගතික පරාසය:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"ඔඩෙෂස් පේනු මෘදුකාංගය සඳහා ගතික පරාස සම්පීඩනය\n"
-"ප්‍රකාශන හිමිකම් 2010-2012 ජෝන් ලින්ඩ්ග්රෙන්"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "ගතික පරාස සම්පීඩකය"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1013,205 +968,224 @@ msgstr ""
 " William Pitcock<nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "මන්ද්‍රස්වර:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "උච්චස්වනය:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "පෙරනිමි ගීත දිග​:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr " <b>නැවත සාම්පල කිරීම</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "නැවත නියැදීම​ සක්‍රිය කරන්න​"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "නැවත නියැදීම් අනුපාතය​:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "හර්ට්ස්"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC \tසම්බන්ධකයෙන් දිග නොසලකා හරින්න​"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "ප්‍රතිරාවය වැඩි කරන්න​"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "ක්‍රීඩා පාලන පුවරු සංගීත විකේතකය​"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"ගීත වලට වෙනස් නාලිකා කිහිපයක් තිබීම නිසා එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීමට අසමත් වී ඇත.  "
-"නාලිකා මිශ්‍රකය භාවිතයෙන් ඔබට ගීත සමාන නාලිකා ගණනකට වෙනස් කල හැක."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"ගීත වලට වෙනස් නියැදි අනුපාත තිබීම නිසා එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීමට අසමත් වී ඇත.  "
-"නාලිකා මිශ්‍රකය භාවිතයෙන් ඔබට ගීත එක් නියැදි අනුපාතයකට වෙනස් කල හැක."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Audacious සඳහා වන හරහා පෑහීමේ පේනු මෘදුකාංගය⏎\n"
-"ප්‍රකාශන අයිතිය 2010-2012 ජෝන් ලින්ඩ්ග්‍රෙන්"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීම</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "අතිච්ඡාදන:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීම"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"ගීත වලට වෙනස් නාලිකා කිහිපයක් තිබීම නිසා එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීමට අසමත් වී ඇත.  "
+"නාලිකා මිශ්‍රකය භාවිතයෙන් ඔබට ගීත සමාන නාලිකා ගණනකට වෙනස් කල හැක."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"ගීත වලට වෙනස් නියැදි අනුපාත තිබීම නිසා එක් ශබ්දයකින් තවත් ශබ්දයකට මාරු වීමට අසමත් වී ඇත.  "
+"නාලිකා මිශ්‍රකය භාවිතයෙන් ඔබට ගීත එක් නියැදි අනුපාතයකට වෙනස් කල හැක."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>පළිඟුව</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "තීව්‍රතාව:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "පළිඟුව"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "සලකුණු පත් පේනු මෘදුකාංගය "
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "මකන්න "
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "අවලංගු කිරීම​"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>ප්‍රතිරාව</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "ප්‍රමාදය:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "මාත සංවේද්‍යතාව"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "ප්‍රතිපෝෂණය:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "ශබ්ද මට්ටම​ :"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"ප්‍රතිධ්වනි පේනු මෘදුකාංගය⏎\n"
-"ජොහාන් ලෙවින් විසින්, 1999⏎\n"
-"⏎\n"
-"සිසාළ ප්‍රතිධ්වනි කාර්ල් වෑන් ස්චේයික් විසින්, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "ප්‍රතිරාව"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg පේනු මෘදුකාංගය "
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1227,55 +1201,55 @@ msgstr ""
 "විලියම් පිට්කොක් <nenolod at nenolod.net>⏎\n"
 "මැටී හැමලේයිනෙන් <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg පේනු මෘදුකාංගය "
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "ගොනු රචක පේනු මෘදුකාංගය "
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "ප්‍රතිදාන ගොනු ආකෘතිය:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "වින්‍යාස කරන්න​"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "මූලික නාමාවලියට සුරකින්න​"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "අභිරුචි නාමාවලියටකට​ සුරකින්න​"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "ප්‍රතිදාන ගොනු ෆෝල්ඩරය​:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "ෆෝල්ඩරයක්​ තෝරන්න​"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "වෙතින් ගොනු නාමයක් ලබාගන්න​:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "මූලික ගොනු සම්බන්ධකය"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "මූලික ගොනු නම​"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "ගොනු නම් දිගුව ඉවත් නොකරන්න​"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "පථ අංකය ගොනු නමට එකතු කරන්න​"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1303,165 +1277,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "ගොනු රචක පේනු මෘදුකාංගය "
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "ස්වයංක්‍රීය​"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "එකතු වූ ත්‍රිමාණ​"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "ත‍්‍ර‍්‍රිමාණ "
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "තනි "
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 වින්‍යාසය"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "ඇල්ගොරිතම තත්ත්වය:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "ප්‍රතිදාන නියැදි අනුපාතය​:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(හර්ට්ස්)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "බිට් රේටය / සම්පීඩක අනුපාතය​:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "බිට් රේටය (තප්පරයට කි.බ​.)"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "සම්පීඩක අනුපාතය​:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "ශ්‍රව්‍ය​ ප්‍රකාරය​:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "ප්‍රකීර්ණ:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "විධිමත් ISO අනුකූලවීමකට බල කරන්න​"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "දෝෂ ආරක්‍ෂාව​"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "ප්‍රශස්තතාව"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR සක්‍රිය කරන්න​"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "වර්ගය​:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR විකල්ප​:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "අවම බිට් රේටය (තප්පරයට කි.බ​.)"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "උපරිම​ බිට් රේටය (තප්පරයට කි.බ​.)"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "අවම බිට් රේටය සඳහා තදින් බලකරන්න​"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR විකල්ප​:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "සාමාන්‍ය බිට් රේටය (තත්පරයට කි.බ​.)"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR ප්‍රශස්තතා මට්ටම​:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR ශීර්‍ෂකය​ නොලියන්න​"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "රාමු පරාමිතිය :"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "ප්‍රකාශන අයිතිය සහිත ලෙස සලකුණු කරන්න"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "මුල් පිටපතක් ලෙස සලකුණු කරන්න​"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "2 වන සංස්කරණයේ සම්බන්ධකයට​ බලෙන් ඇතුලත් කිරීම​"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "1 වන සංස්කරණයේ සම්බන්ධකය පමණක් එකතු කරන්න​"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "2 වන සංස්කරණයේ සම්බන්ධකය පමණක් එකතු කරන්න​"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "සම්බන්ධක"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis විකේතකයේ වින්‍යාසය"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "ප්‍රශස්ථතා මට්ටම​ (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC විකේතකය"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "හානි වී නොමැති "
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1473,11 +1451,7 @@ msgstr ""
 "⏎\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC විකේතකය"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1485,14 +1459,22 @@ msgstr ""
 "Audacious සඳහා වන​ GIO පේනු මෘදුකාංගය⏎\n"
 "ප්‍රකාශන අයිතිය 2009-2012 ජෝන් ලින්ඩ්ග්‍රෙන්"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO පේනු මෘදුකාංගය "
 
-#: src/gl-spectrum/gl-spectrum.c:400
-msgid ""
-"OpenGL Spectrum Analyzer for Audacious\n"
-"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
 "\n"
 "Based on the XMMS plugin:\n"
 "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
@@ -1501,534 +1483,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL වර්ණාවලි විශ්ලේශකය"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"ග්නෝම් කෙටි යෙදුම් පේනු මෘදුකාංගය⏎\n"
-"ග්නෝම් කෙටි යෙදුම් මගින් ඔබට ධාවකය පාලනයට ඉඩ සලසයි.⏎\n"
-"⏎\n"
-"ප්‍රකාශන අයිතිය​ (C) 2007-2008 සස්චා හ්ලුසියැක් <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome කෙටිමග "
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "ඇතුලත් කිරීමේ අංකය​"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "මාතෘකාව"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "ශිල්පියා "
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "වර්ෂය "
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "ඇල්බමය "
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "ඛණ්ඩය "
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "ප්‍රභේදය"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "පේලියෙහි පිහිටන ස්ථානය​"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "දිග"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "ගොනු පථය"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "ගොනු නම​"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "අභිරුචි මාතෘකාව​"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "බිට් රේටය​"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "සෙවීමේ මෙවලම "
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "වමට ඈඳන්න​"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "දකුණට ​ඈඳන්න​"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "ඉහළට​ ඈඳන්න​"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr " පහළට ඈඳන්න​"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "ඈඳීම​ අවලංගු කරන්න​"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "අක්‍රීය කරන්න​"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "සෙවීමේ මෙවලම "
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_ගොනු විවෘත කරන්න ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "_URL විවෘත කරන්න ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_ගොනු එකතු කරන්න ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL එකතු කරන්න ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "පි_ළිබඳ​ ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_පිටවෙන්න​"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_ධාවනය කරන්න​"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "විරාම_ය​"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_නවත්වන්න​"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "ක_ලින්"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_ඊළඟ​"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_නැවත​ ධාවනය​"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "ක_ළවම් කිරීම​"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "ධාවන ලැස්තු නැ_ත "
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "මෙම ගීතයෙන් පසු නවත්තන්න "
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "ගීත_තොරතුරු ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "මගහැර වේලාවට_පිවිසෙන්න ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "_මගහැර ගීතයට පිවිසෙන්න ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "නැවත සිදුවන ස්ථාන_A පිහිටුවන්න "
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "නැවත සිදුවන ස්ථාන_B පිහිටුවන්න "
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "නැවත සිදුවන ස්ථාන හිස්කරන්න "
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "මාතෘකා_වෙන්"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "ගොනු නාමයෙන් "
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "ගොනු පථයෙන් "
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "ඛණ්ඩ_අංකයෙන් "
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "ශිල්පියා_ගෙන්"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "ඇල්බමයෙන් "
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "පිට කල _දිනයෙන්"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "දුරෙන් "
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "ගොනු_පථයෙන්"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "අභිරුචි_මාතෘකාවෙන් "
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "අග_සිට මුලට​"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_සසම්භාවී පිළිවෙල​"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_ධාවන ලැයිස්තුව ධාවනය කරන්න​"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_නැවුම් කරන්න​"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_අනුපිළිවෙලට සකසන්න​"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "අනුපිටපත්_ඉවත් කිරීම "
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "අනුපයෝජ්‍ය_ගොනු ඉවත් කරන්න"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_නව​"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Ren_ame ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_ආයාත කරන්න​ ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_නිර්යාත කරන්න ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "ධාවන ලැයිස්තු_කළමනාකාරකය​ ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_පෙළගැස්ම කළමනාකරණය ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "ශබ්ද මට්ටම​ _වැඩි කරන්න"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "ශබ්ද මට්ටම​ _අඩු කරන්න"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_ඊක්‍යුවලයිසරය​"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_මෙනු තීරුව පෙන්වන්න​"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "තොරතුරු තී_රුව පෙන්වන්න​"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "තොරතුරු තීරුවේ දෘෂ්ටි කල්පනය පෙන්වන්න "
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "තත්ව _තීරුව පෙන්වන්න​"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "ඉතුරුවී ඇති කාලය පෙන්වන්න."
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_ගොනුව​"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_පිළිවැයුම​"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "ධා_වන ලැයිස්තුව​"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_සේවා"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_ප්‍රතිදාන​"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_දසුන​"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_පෙළගස්වන්න​/පෙළගැස්ම අවලංගු කරන්න​"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "කපන්_න​"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_පිටපත් කරන්න​"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_අලවන්න​"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "සියල්ල_තෝරන්න"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_නැවත නම් කිරීම​ ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>විවිධ</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK අතුරු මුහුණත"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "අන්තරාචයනය..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "ඔඩෙෂස් "
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr " තනි "
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "ත්‍රිමාන "
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d නාලිකාව "
 msgstr[1] "%d නාලිකා "
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d තත්පරයට කිලෝ බයිට් "
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "තනි ප්‍රකාරය."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "ධාවන ලැස්තු ප්‍රකාරය."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "ගීතයකින් පසු නැවතීම."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "පෙර ඛණ්ඩය"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "ධාවනය කරන්න "
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "නැවතීම/නැවත ඇරඹීම  "
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "නැවතීම "
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "පසු ඛණ්ඩය "
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "තත්.5 ධාවනය කරන්න"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "තත්.5 පසු ධාවනය කරන්න"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "නිහඬ කරන්න "
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "ශබ්ද මට්ටම​ වැඩි කරන්න"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "ශබ්ද මට්ටම​ අඩු කරන්න"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "මගහැර ගොනුවට පිවිසෙන්න "
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "ධාවක කවුළු(ව) පුරුක් කරන්න"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "තිරය මත සංදර්ශනය කර පෙන්වන්න "
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "නැවත කිරීම ටොගල් කරන්න"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "කළවම් කිරිම ටොගල් කරන්න"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "පවතින ගීතයෙන් පසු නැවතීම ටොගල් කරන්න "
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "ධාවක කවුළු(ව) පෙන්වන්න"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(කිසිවක් නැත)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2038,15 +2093,11 @@ msgstr ""
 "ප්‍රාථමික මූසික බොත්තම් නවීකරණයකින් තොරව බැඳීමට නිර්දේශ නොකෙරේ.\n"
 "ඔබට ඉදිරියටයාම‍ට අවශ්‍යද ?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "බැඳෙන මූසික බොත්තම් "
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "ගෝලීය  විශේෂ  බොත්තම්  පේනු මෘදුකංග වින්‍යාසය "
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2054,23 +2105,27 @@ msgstr ""
 "පෙළ ක්ෂේත්‍රය ඇතුලත යතුරු එකතුව ඔබන්න.\n"
 "ඔබට මූසික බොත්තමද බැඳීය හැක."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "විශේෂ බොත්තම්:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>ක්‍රියාව:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>යතුරු බැඳීම:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "ගෝලීය විශේෂ බොත්තම්:"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2096,60 +2151,51 @@ msgstr ""
 "ජොනතන් ඒ. ඩේවිස් <davis at jdhouse.org>,\n"
 "ජෙරමි ටෑන් <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "ගෝලීය විශේෂ බොත්තම්:"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK ප්‍රතිදානය"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"ක්‍රිස් මෝර්ගන් ගේ xmms-jack මත පදනම් වී ඇත​:⏎\n"
-"http://xmms-jack.sourceforge.net/⏎\n"
-"⏎\n"
-"Audacious වෙත ඇතුලත් කළේ ජියාකොමෝ ලොසීටෝ විසිනි"
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK ප්‍රතිදානය"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s සිටුවම "
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA  සත්කාරක සිටුවම "
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "මොඩියුල පථය:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2159,25 +2205,25 @@ msgstr ""
 "මෙම පථ සොයන්නේ LADSPA_PATH එකට අමතරවය.\n"
 "නව පථ ඇතුලත් කිරීමෙන් පසුව, නව පේනු මෘදුකාංග සදහා Enter යතුර ඔබන්න.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "උපයෝජ්‍ය පේනු මෘදුකාංග:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "සක්‍රිය "
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "සක්‍රිය පේනු මෘදුකාංග:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "සිටුවම් "
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2185,47 +2231,15 @@ msgstr ""
 "Audacious සඳහා වන LADSPA සත්කාරකය​⏎\n"
 "ප්‍රකාශන අයිතිය​ 2011 ජෝන් ලින්ඩ්ග්‍රෙන්"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA සත්කාරක "
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC සඳහා සහයවිය නොහැක\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC වින්‍යාස ගොනුව කියවිය නොහැක \n"
-"%s: කරුණාකර  LIRC වලට අදාල ලේඛන කියවන්න \n"
-"%s: ක්‍රමානුකූල වින්‍යාස ගොනුවක් සාදන්නේ කෙසේද \n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr " %s: ප්‍රතිසම්බන්ධ වීමට උත්සාහ කිරීම...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: නොදන්නා විධානයකි \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC වලින් ක්‍රියාවිරහිත කර ඇත \n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: සෑම තත්පර %d වරක් නැවත සම්බන්ධ වීමට  උත්සාහ කරයි...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC පේනු මෘදුකාංගය"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2253,73 +2267,81 @@ msgstr ""
 "⏎\n"
 "LIRC පිළිබඳ වැඩි විස්තර සඳහා,http://lirc.org බලන්න​."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>සබැඳුම</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "සේවාදායකයට ප්‍රතිසම්බන්ධ කරන්න "
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "ප්‍රතිසම්බන්ධ වීමට පෙර මදක් සිටින්න:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC පේනු මෘදුකාංගය"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "ලිරික් විකී  පේනු මෘදුකාංගය"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "පද රචනා නොමැත​"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "දෝෂය "
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "කැඳවාගෙන යා නොහැක​ %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "දෝෂය "
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "parse කළ නොහැක​ %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "පද රචනා සොයමින් පවතී ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "ගීතයේ metadata නොමැත​"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "lyrics.wikia.com වෙත​ සම්බන්ද වෙමින් පවතී ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "ලිරික් විකී  පේනු මෘදුකාංගය"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U ධාවන ලැයිස්තුව​"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "ටැක්ට් ජනකය"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "ටැක්ට් ජනකය: %d මිනිත්තුවට බයිට්ස් "
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "ටැක්ට් ජනකය: %d මිනිත්තුවට බයිට්ස්  %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2333,11 +2355,11 @@ msgstr ""
 "e.g. tact://77 to play 77 beats per minute⏎\n"
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "ටැක්ට් ජනකය"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "නාලිකා මිශ්‍රකය"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2345,152 +2367,184 @@ msgstr ""
 "Audacious සඳහා නාලිකා මිශ්‍රන​ පේනු මෘදුකාංගයක්\n"
 "ප්‍රකාශන අයිතිය​ 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>නාලිකා මිශ්‍රකය</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "ප්‍රතිදාන නාලිකා:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "නාලිකා මිශ්‍රකය"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS පේනු මෘදුකාංගය"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "මොඩ් කෙවෙනිය (මොඩියුල  ධාවකය)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>විභේදනය</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "බිටු-8"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "බිටු-16"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>නාලිකා </b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "කිට්ටුතම (වේගවත්ම)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "රේඛීය (වේගවත්)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "හිර ඇලිය (යහපත්)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "බහු අදියර (ප්‍රශස්ත)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>සාම්පල ශ්‍රීඝ‍්‍රතාව</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "මට්ටම:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "කපා හැරීම:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>ප්‍රතිනාදකය</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "\t<b>මන්ද්‍රස්වරය වැඩිවීම</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>වටපිටාව</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>ප්‍රාක්වර්ධකය</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "අධික සාම්පල"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "ශබ්දය අඩු කිරීම"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Amiga MODs ධාවනය කරන්න "
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>නැවත කිරීම</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "නැවත ගණන් කිරීම"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "සදහටම නැවත නැවත කිරීමට, නැවත වරක් ගණන් කිරීම -1 හි පිහිටුවන්න."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "මොඩ් කෙවෙනිය (මොඩියුල  ධාවකය)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "සිසාළ "
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123  පේනු මෘදුකාංගය"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "සිසාළ "
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 සේවාදායකය"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "නිඕන් HTTP/HTTPS පේනු මෘදුකාංගය"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "නැවතුන "
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "ඔඩෙෂස්  ක්‍රියාත්මක නොවේ."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "වැඩතලය දැනුම් දීම "
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2524,55 +2578,64 @@ msgstr ""
 "ඔබට මම මෘදුකාංගය සමග GNU පොදු  මහජන වරපතේ පිටපතක් ලැබී තිබිය යුතුය, එසේ නොමැති නම් "
 "<http://www.gnu.org/licenses/>. බලන්න."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "යළි ධාවන පාලන යතුරු පෙන්නන්න  "
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "නිතර නිවේදන පෙන්නන්න"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "වැඩතලය දැනුම් දීම "
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "පෙන්නන්න "
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "විරාමය "
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "ඊළඟ  "
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1.පෙරනිමි ආම්පන්නය "
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 ප්‍රතිදානය"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "ස්වයංක්‍රිය අම්පන්නය:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "විකල්ප අම්පන්නයක් භාවිතා කරන්න:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "සැසි අතර ශබ්දය සුරකින්න."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "OSS මෘදුකාංගයෙන් සාදන ලද ආකෘති අනුවර්තන සක්‍රීය කරන්න."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "අතාත්වික ඝටනාවෙන් මිදීමට කේවල ප්‍රකාරය සක්‍රිය කරන්න."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2586,19 +2649,35 @@ msgstr ""
 "#audacious හි මිනිසුන් වෙත ස්තූති කරමි, විශේෂයෙන් Tony Vroon සහ​ John Lindgren මෙන්ම පෙර "
 "OSS පේනු මෘදුකාංගයයෙහි කතෘන් හට ."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 ප්‍රතිදානය"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS ධාවන ලැයිස්තුව​"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "PSF PSF1/PSF2 විකේතකය විවෘත කරන්න "
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "ශ්‍රව්‍ය ස්පන්ද ප්‍රතිදානය "
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2632,11 +2711,68 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "ශ්‍රව්‍ය ස්පන්ද ප්‍රතිදානය "
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "පෙර "
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "නැවත  කරන්න "
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "කලවම් කරන්න "
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "නියැදි අනුපාත පරිවර්තකය "
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2644,96 +2780,104 @@ msgstr ""
 "ඔඩෙෂස් සඳහා නියැදි අනුපාත පරිවර්තකය \n"
 "ප්‍රකාශන හිමිකම 2010-2012 ජෝන් ලින්දඩ්ග්රෙන් "
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "නියැදි මගහැරීම/නැවත කිරීම "
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "රේඛිය අන්තර් නිවේෂණය"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "වේගවත් සින්ක්  අන්තර් නිවේෂණය"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "මධ්‍යම සින්ක්  අන්තර් නිවේෂණය"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "හොඳම සින්ක්  අන්තර් නිවේෂණය"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>පරිවර්තනය</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "ක්‍රමය "
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "අනුපාතය:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>අනුපාතය සිතියම්කරණය</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "අනුපාතය සිතියම්කරණය භාවිතා කරන්න​"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 කිලෝ හරට්ස්:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "නියැදි අනුපාත පරිවර්තකය "
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "ඔව්. \tපරිශ්‍රීලක: %s සදහා භාවිත දත්ත සුරකින්න"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "අනුමැතිය තහනම් කිරීම "
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "Audacious සදහා භාවිත දත්ත සුරකීමට මෙම අමුණට පිවිසෙන්න :"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "මම කවුළුව විවෘත​ව තබා 'අවසර පිරික්සන්න' නැවත ක්ලික් කරන්න\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2741,32 +2885,36 @@ msgstr ""
 "කණගාටු නොවන්න ඔබගේ භාවිත දත්ත ඔබගේ පරිගණකයේ ම සුරක්ෂිත කරයි.\n"
 "ඒවා Audacious සදහා අවසර ලැබුණු වහාම සුරක්ෂිත වේ"
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "ජාල ගැටළු."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "අවසානයට සම්බන්ධ වීමේ ගැටළුවක් විය.fm.කරුණාකර පසුව නැවත උත්සහ කරන්න "
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "පිරික්සන..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "C_heck අනුමැතිය "
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_අනුමැතිය අවලංගු කිරීම "
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "ඔබ ඔඩෙෂස් හට ඔබගේ අවසාන fm ගිණුමෙන් ගීත ලබා ගැනීමට අවසර දිය යුතුය.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "ස්ක්රෝබ්ලර් 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2774,7 +2922,7 @@ msgstr ""
 "Scrobbler පේනු මෘදුකාංගය ඇරභිය නොහැකිය.⏎\n"
 "සමහරවිට ඔබගේ පිහිටැවුමෙහි ගැටලුවක් ඇත."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2788,11 +2936,7 @@ msgstr ""
 "\n"
 "ප්‍රකාශන අයිතිය © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "ස්ක්රෝබ්ලර් 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2800,7 +2944,11 @@ msgstr ""
 "Audacious අවසානයට වැඩි දියුණුකළ අනුවාදය භාවිත කරයි.fm Scrobbler.⏎ \n"
 "කරුණාකර Scrobbler පේනු මෘදුකාංගයේ අභිරුචිය පරීක්ෂා කර බලන්න."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL ප්‍රතිදානය"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2808,760 +2956,825 @@ msgstr ""
 "Audacious සඳහා වන SDL ප්‍රතිදාන​ පේනු මෘදුකාංගය\n"
 "ප්‍රකාශන අයිතිය 2010 ජෝන් ලින්ඩ්ග්‍රෙන්"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL ප්‍රතිදානය"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "පුස්තකාලය "
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "නාඳුනන ශිල්පියා"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "නාඳුනන ඇල්බමය "
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"මතුපිට %s විසින්  %s"
-
-#: src/search-tool/search-tool.c:631
-#, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d ඇල්බමය "
-msgstr[1] "%d ඇල්බම"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s⏎\n"
-"%s, %d ගීතය "
 msgstr[1] ""
-"%s\n"
-"%s, %d ගීත "
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-"%d ගීතයෙන් %s"
 msgstr[1] ""
-"%s⏎\n"
-"%d ගීත වලින් %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_ධාවන ලැයිස්තුව​ තනන්න "
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_ධාවන ලැයිස්තුව​ට එකතු කරන්න "
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "පුස්තකාලය සොයන්න "
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 "ඔඩෙෂස් තුලට ඔබගේ ගීත පුස්තකාලය ආයාත කිරීමට, ෆෝල්ඩරයක් තෝරා \"නැවුම් කරන්න\" නිරූපකය ඔබන්න."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "කරුණාකර රැඳී සිටින්න ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "ෆෝල්ඩරය තෝරන්න "
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "පිළිවැයීම"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "ධාවන ලැයිස්තුව​"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "දක්වන්න "
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "නැවත  කරන්න "
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "කලවම් කරන්න "
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "ධාවන ලැස්තු නැත "
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "පෙර "
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "නව ධාවන ලැයිස්තුව​"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "ධාවන ලැස්තු සකසනය පෙන්වන්න "
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr " ඉකුවලිසරය  පෙන්වන්න "
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "සැමවිටම  ඉහළ"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "මාතෘකාවෙන් "
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "ගොනු නාමයෙන් "
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "සියල්ල ඉවත් කරන්න "
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "පෙළගැස්ම හිස් කරන්න"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "අනුපයෝජ්‍ය ගොනු ඉවත් කරන්න "
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "ද්විකරණ ඉවත් කරන්න "
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "තෝරානොගත් ඒවා ඉවත් කරන්න "
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "තෝරාගත් ඒවා ඉවත් කරන්න "
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "සොයන්න සහ තෝරන්න "
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "වරණය පෙරලන්න "
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "කිසිවක් තෝරානොගන්න "
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "සියල්ල තෝරන්න"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "ඇල්බමයෙන් "
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "ඛණ්ඩ අංකයෙන් "
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "ශිල්පියාගෙන් "
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "ඇල්බමයෙන් "
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "ඛණ්ඩ අංකයෙන් "
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "සසම්භාවී ධාවන ලැයිස්තුව "
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "ලැස්තුවේ  ආපස්සට යන්න "
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "තෝරාගත් අනුපිළිවලට "
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "ලැයිස්තුව අනුපිළිවලට සකසන්න "
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "කපන්න "
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "පිටපත් කරන්න "
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "අලවන්න "
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp සම්භාව්‍ය අතුරු මුහුණත"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "සුරකින්න "
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "ප්‍රවේශනය "
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "පෙර සකසන ලද "
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "පෙර සකසනය  ප්‍රවේශනය කරන්න "
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "පෙර සකසන-ස්වයංක්‍රිය ප්‍රවේශනය"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "පෙර සකසනය සුරකින්න "
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "පෙර සකසනය-ස්වයංක්‍රියව සුරකින්න"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "පෙර සකසනය මකන්න"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "පෙර සකසනය-ස්වයංක්‍රියව මකන්න"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_ධාවකය:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "කවුළු ෆොන්ටයේ ප්‍රධාන ධාවකය තෝරන්න:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_ධාවන ලැස්තුව:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "ධාවන ලැස්තු ෆොන්ටය තෝරන්න:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "බිට්මැප් ෆොන්ට භාවිතා කරන්න (ASCII පමණක් සහය වන )"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "ගීත තේමාව දෙපසට චලනය කරන්න "
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "විශ්ලේශකය "
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "විෂය පථය "
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "වහනවා "
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "සාමාන්‍ය "
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "දල්වනවා "
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr " රේඛා"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "තීරු "
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "මන්දගාමිම "
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "මන්දගාමි"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "මධ්‍යම "
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "වේගවත් "
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "වේගවත්ම "
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "හිම "
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "මෘදු "
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "සාමාන්‍ය"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "දෘෂ්ටි කල්පනය "
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "පූර්ව වර්ධකය"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 හරට්ස් "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16  හරට්ස් "
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "ඔඩෙෂස් ඉකුවලිසරය "
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "සොයනවා %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "ශබ්ද මට්ටම​ : %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "තුලනය : %d%% වමට "
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "තුලනය: මැදට "
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "තුලනය: %d%% දකුණට "
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "විකල්ප මෙනුව "
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "අක්‍රිය කරන්න 'සැමවිටම  ඉහළ '"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "සක්‍රිය කරන්න 'සැමවිටම  ඉහළ '"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "ගොනු තොරතුරු පෙට්ටිය "
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "පුනරාවර්ථන ස්ථානය A කුලකය."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "පුනරාවර්ථන ස්ථානය B කුලකය."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "පුනරාවර්ථන ස්ථාන හිස් කරන ලදී."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "තනි ප්‍රකාරය."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "ධාවන ලැස්තු ප්‍රකාරය."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "ගීතයකින් පසු නැවතීම."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "සක්‍රිය ධාවන ලැයිස්තුවේ  පිවිසුම් සොයන්න "
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3572,57 +3785,61 @@ msgstr ""
 "වාග් රීති, අකුරු තටු-සංවේදී නැති භාවිතා කරයි. ඔබට  විධිමත් ප්‍රකාශන වාග් රීති ක්‍රියාත්මක වන ආකාරය "
 "පිළිබඳ අවබෝධයක් නැති නම්, ඔබ සොයන වචන කොටස ඇතුල් කරන්න."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "මාතෘකාව:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "ඇල්බමය:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "ශිල්පියා:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "ගොනු නාමය:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "පෙර තේරීම සෙවීමට පෙර හිස් කරන්න "
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "ගැලපෙන පිවිසුම් සඳහා ස්වයංක්‍රියව පෙළගැස්ම ටෝගල කරන්න "
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "ගැලපෙන පිවිසුම් සමග නව ධාවන ලැයිස්තුව තනන්න "
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "ඔඩෙෂස් ධාවන ලැස්තු සකසනය "
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d ගෙන්  %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "සංරක්ෂිත Winamp 2.x මතුපිට "
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "සංරක්ෂණය නොකරන ලද Winamp 2.x මතුපිට"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "නාමාවලිය නිර්මාණය කීරීමට නොහැකිය (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Snd ගොනු පේනු මෘදුකාංගය"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3661,81 +3878,71 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Snd ගොනු පේනු මෘදුකාංගය"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio ප්‍රතිදාන පේනු මෘදුකාංගය පිළිබඳ​"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio ප්‍රතිදාන පේනු මෘදුකාංගය⏎\n"
-"⏎\n"
-"ලියනු ලැබුවේ තෝමස් ප්ෆැෆ් විසින් <tpfaff at tp76.info>⏎\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "සහාය නොමැති හැඩතලය​කි"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"ශ්‍රව්‍ය ආම්පන්නයට සහය නොදක්වන හැඩතලයක් අයැදුම් කරන ලදී.⏎\n"
-"⏎\n"
-"sndiod(1) සේවාදායකය​ ධාවනය වන අතරතුර නැවත උත්සාහ කරන්න​."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio ආම්පන්නය"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(හිස් ව තැබීම යනු පෙරනිමියයි )"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "එකඟයි"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "ගීත වෙනස්කිරීම "
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "ඔඩෙෂස් නව ගීතයක් ආරම්භ කළ විට ධාවනය සඳහා විධානය."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>කවචය වෙත හුවමාරු කරන ලද පරාමිතික කොටස් ලෙස ප්‍රාවරිකෘත කර ඇත. එය "
+"එසේ නොකරහොත් ආරක්ෂාව පිළිබඳ අවදානමක් පවතී.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "විධානය:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "ගීතයක අවසානය තෙක් ධාවනය සඳහා විධානය."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "ඔඩෙෂස් ධාවන ලැස්තුවේ අවසානයට පැමිණිවිට ධාවනය සඳහා විධානය."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "ගීතයක මාතෘකාව වෙනස් වූ විට ධාවනය සඳහා විධානය (ජාල ප්‍රවාහ මාතෘකා )."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3749,34 +3956,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"ඔබට පහත දැක්වෙන අනුලකුණු වැල්හි ආකෘති විධානය කිරීමට පෙර ආදේශ කළ හැක\n"
-"(ධාවන ලැයිස්තු විධාන අවසානයේදී ඇතැම්විට සියලුම විධාන ප්‍රයෝජනවත් නොවිය හැක):\n"
-"\n"
-"%F: සංඛ්‍යාතය  (හර්ට්ස් වලින්)\n"
-"%c: නාලිකා ගණන \n"
-"%f: ගොනු නාමය  (සම්පුර්ණ පථය)\n"
-"%l: ආයාමය (මිලි තත්පර වලින්)\n"
-"%n හෝ  %s: ගීතයේ නම \n"
-"%r: අනුපාතය  (තත්පරයට බිට්ස් වලින්)\n"
-"%t: ධාවන  ලැයිස්තුවේ ස්ථානය  (%02d)\n"
-"%p: දැන්  ධාවනය වන (1 or 0)\n"
-"%a: ශිල්පියා \n"
-"%b: ඇල්බමය \n"
-"%T: ඛණ්ඩයේ මතෘකාව "
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>කවචය වෙත හුවමාරු කරන ලද පරාමිතික කොටස් ලෙස ප්‍රාවරිකෘත කර ඇත. එය "
-"එසේ නොකරහොත් ආරක්ෂාව පිළිබඳ අවදානමක් පවතී.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "විධාන:"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Sox නැවත සාම්පල කිරීම "
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3790,51 +3979,51 @@ msgstr ""
 "නියැදි අනුපාත පරිවර්තන පේනු මෘදුකාංගය මත පදනම් වී ඇත​:\n"
 "ප්‍රකාශන අයිතිය 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "කඩිනම්"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "පහළ"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "ඉහළ"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "අති- උච්ච"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "ප්‍රශස්තතාව:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Sox නැවත සාම්පල කිරීම "
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "වේගය සහ ස්වරමානය"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>වේගය සහ ස්වරමානය</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "වේගය:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "ස්වරමානය:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "වේගය සහ ස්වරමානය"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "තත්ව නිරූපකය"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3852,39 +4041,39 @@ msgstr ""
 "මෙම පේනු මෘදුකාංගය තත්ත්ව සුරුවමක් සපයනු ලබයි,  කවුළු කළමනාකාරකයෙහි පද්ධති ට්‍රේ කොටසේ රඳවා "
 "තැබෙන ලෙස."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>මුසික අනුචලන ක්‍රියාව</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "ශබ්දය වෙනස්කිරීම "
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "වාදනය වන ගීතය වෙනස්කිරීම "
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>අනෙකුත් සැකසුම්</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "උත්පතන කවුළුව අක්‍රිය කරන්න "
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "පද්ධති තට්ටුවට ආසන්නව "
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "අනුචලනය ඉහළට සිදුකරන විට ධාවන ලැයිස්තු ප්‍රගමනය "
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "තත්ව නිරූපකය"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "අතිරේක ත‍්‍ර‍්‍රිමාණ"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3894,24 +4083,24 @@ msgstr ""
 "\n"
 "Johan Levin විසින්, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>අතිරේක ත්‍රිමාන</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "අතිරේක ත‍්‍ර‍්‍රිමාණ"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "ස්වර ජනකය"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f හර්ට්ස් "
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "ස්වර ජනකය:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3925,15 +4114,11 @@ msgstr ""
 "භාවිතා කිරීම සඳහා, add a URL: tone://frequency1;frequency2;frequency3;...\n"
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "ස්වර ජනකය"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "කටහඬ ඉවත් කිරීම​"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3971,11 +4156,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis විකේතකය"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX විකේතකය"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -3985,19 +4194,19 @@ msgstr ""
 "Based on in_vtx.dll Roman Sherbakov විසින් <v_soft at microfor.ru>\n"
 "Audacious පේනු මෘදුකාංගය Pavel Vymetalek විසින් <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX විකේතකය"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack විකේතකය"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "හානිමත් (දෙමුහුන්)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "හානිමත් "
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4006,14 +4215,18 @@ msgstr ""
 "ප්‍රකාශන හිමිකම 2006 William Pitcock <nenolod at nenolod.net>\n"
 "ඇතැම් පේනු  මෘදුකාංග කේත Miles Egan විසිනි."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack විකේතකය"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr " 2SF විකේතකය"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML හුවමාරු කළ හැකි ධාවන ලැයිස්තුව​ (XSPF)"
diff --git a/po/sk.po b/po/sk.po
index 7f8190638179..2ed74993a28f 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -4,17 +4,17 @@
 #
 # Translators:
 # Andrej Herceg <herceg.andrej at zoznam.sk>, 2007, 2008, 2010, 2011
-# citro <lukas.dobransky at gmail.com>, 2012
+# Lukáš Dobránsky <lukas.dobransky at gmail.com>, 2012
 # Tomáš Vadina <tomasvadina+transifex at cryptolab.net>, 2012
 # Corduroy <vdcorduroy at gmail.com>, 2013
 # Corduroy <vdcorduroy at gmail.com>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Slovak (http://www.transifex.com/projects/p/audacious/"
 "language/sk/)\n"
 "Language: sk\n"
@@ -23,40 +23,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "Priestorový zvuk"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib prehrávač)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "sekvenčný"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib prehrávač)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -66,11 +54,7 @@ msgstr ""
 "\n"
 "Napísali Adam Feakin a Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -93,7 +77,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -115,7 +99,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -129,384 +113,371 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Toto je budiaci signál."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Upozornenie"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Pondelok"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Utorok"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Streda"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Å tvrtok"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Piatok"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Sobota"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Nedeľa"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Nastavenie Alarmu"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "ÄŒas"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Budiť o (predvolené):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Ticho po:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "hodín"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "minút"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Vyberte dni, kedy má budík budiť"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Deň"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Štandardné"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Dni"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Zosilovanie"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "sekúnd"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Hlasitosť"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Začať na"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Skončiť na"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Aktuálna"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Dodatočný príkaz"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "povoliť"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Zoznam skladieb (voliteľné)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Vyber zoznam skladieb"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Možnosti"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Čo tieto možnosti znamenajú?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Pomocník"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Album"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA výstup"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA výstupný zásuvný modul pre Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"Moja vďaka patrí Williamovy Pitcockovy, autorovy ALSA výstupného zásuvného "
+"modulu NG, ktorého kód mi poslúžil ako predloha keď ALSA manual nestačil."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Predvolené PCM zariadenie"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Predvolené zariadenie mixéra"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM zariadenie:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Zariadenie mixéra:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Prvok mixéra:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Obísť problém so zasekávaním pri vyprázdňovaní"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI prehrávač)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"ALSA výstupný zásuvný modul pre Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Moja vďaka patrí Williamovy Pitcockovy, autorovy ALSA výstupného zásuvného "
-"modulu NG, ktorého kód mi poslúžil ako predloha keď ALSA manual nestačil."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA výstup"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI prehrávač)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - vyberte SoundFont súbor"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Názov súboru"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Veľkosť (v bajtoch)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Názov:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Podrobnosti o MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Formát:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Dĺžka (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Počet stôp:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "premenlivé"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (váž.):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "ÄŒas. pomer:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Komentáre a slová MIDI skladby </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* v MIDI súbore sa nenachádzajú žiadne komentáre *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* v MIDI súbore sa nenachádzajú žiadne texty skladby *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Zatvoriť"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (neplatné UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "O AMIDI zásuvnom module"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"modulárny prehrávač MIDI hudby\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"napísal Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"zvláštne poďakovanie...\n"
-"\n"
-"Clemens Ladisch a Jaroslav Kysela\n"
-"za ich úžasné programy aplaymidi a amixer; boli\n"
-"naozaj užitočné, spolu s alsa-lib dokumentáciou\n"
-"som sa naučil viac o ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"za pekné logo MIDI klávesnice\n"
-"\n"
-"Tony Vroon\n"
-"za pomoc pri testovaní"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -517,152 +488,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Obdĺžnik"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Zaoblený obdĺžnik"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Konkávny obdĺžnik"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Žiadne"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Začiatok prehrávania"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "OSD sa zobrazí pri zahájení prehrávania položky zo zoznamu skladieb."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Zmena názvu"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"OSD sa zobrazí počas prehrávania ak sa zmení názov, ale meno súboru ostane "
-"nezmenené. Je to hlavne vhodné na zobrazenie zmien názvov skladieb pri "
-"prehrávaní internetových prúdov."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Pozastavenie prehrávania"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "OSD sa zobrazí pri pozastavení prehrávania."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Obnovenie prehrávania"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "OSD sa zobrazí keď je prehrávanie obnovené."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Umiestnenie"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Relatívne odsadenie v smere osi X:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Relatívne odsadenie v smere osi Y:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maximálna šírka OSD:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Nastavenia pre viac monitorov"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Zobraziť OSD na:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "všetkých monitoroch"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "monitore %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "ÄŒasovanie (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Zobrazenie:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Rozsvietenie:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Zhasnutie:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Písma"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Písmo %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Tieň"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Štýl zobrazenia"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Farby"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Farba %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Povoliť spúšťač"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Udalosť"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Bol zistený kompozitný správca"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -672,112 +637,112 @@ msgstr ""
 "Ak viete, že žiadny nebeží, prosím, aktivujte kompozitného správcu, inak "
 "nebude OSD pracovať správne"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Pri falošnej priehľadnosti nie je potrebný kompozitný správca"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Priehľadnosť"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Falošná priehľadnosť"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Skutočná priehľadnosť (vyžaduje kompozitné rozšírenie X servera)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Kompozitné rozšírenie nie je načítané"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Kompozitné rozšírenie nie je dostupné"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>OSD Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "OSD pre Audacious - nastavenie"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Umiestnenie"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Animácia"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Text"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Výzdoba"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Spúšťač"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Rôzne"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 zoznamy skladieb"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious zoznamy skladieb (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Farba</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Rozsah rozostrenia"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Predvoľby:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Úroveň zdroja:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Frekvencia pre vystrihnutie:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Predvoľby:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Analyzér spektra"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Audio CD zásuvný modul"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -797,171 +762,156 @@ msgstr ""
 "\n"
 "Toto bol Google Summer of Code 2007 projekt."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "Zariadenia"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Rýchlosť disku:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Prepísať zariadenie:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadáta</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Použiť CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Použiť CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Namiesto CDDBP použiť HTTP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Server: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Cesta: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Port: "
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Audio CD zásuvný modul"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Zlyhala inicializácia cdio podsystému."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Neplatná URI %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Stopa %d sa nenašla."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Stopa %d je dátová stopa."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Zlyhalo otvorenie audio výstupu."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Chyba pri čítaní audio CD."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Zvukové CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Zlyhalo CD zariadenie %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Nebolo nájdené žiadne spôsobilé CD zariadenie."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Zlyhalo dokončenie inicializácie otvoreného CD zariadenia."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Zlyhalo načítanie prvého/posledného čísla skladby."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Nie je možné prečítať začiatok/koniec LSN pre stopu %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Zlyhalo vytvorenie cddb pripojenia."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Nepodaril sa dotaz na CDDB server"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Nepodaril sa dotaz na CDDB server: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Zlyhalo načítanie cddb info: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Mechanika je prázdna."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Nepodporovaný typ disku."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Položky Audio CD menu"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Prehrať CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Pridať CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Položky Audio CD menu"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Kompresia</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Stredná hlasitosť:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dynamický rozsah:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Dynamic Range Compression zásuvný modul pre Audacious\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Dynamický rozsah kompresora"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -977,207 +927,226 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Hĺbky:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Výšky:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Predvolená dĺžka skladby:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Povoliť prevzorkovanie zvuku"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Prevzorkovať na:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ignorovať dĺžku z SPC značiek"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Predĺžiť dozvuk"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Dekodér konzolovej hudby"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"Prelínanie sa nepodarilo, pretože skladby mali rôzny počet kanálov. Môžete\n"
-"použiť Zmiešavač kanálov a previesť piesne na rovnaký počet kanálov."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
-msgstr ""
-"Prelínanie zlyhalo, pretože skladby majú rozdielnu vzorkovaciu frekvenciu:\n"
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Na prevzorkovanie skladieb na rovnakú frekvenciu môžete použiť efektový "
-"modul „Konvertor vzorkovacej frekvencie“."
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Crossfade zásuvný modul pre Audacious\n"
-"Copyright 2010-2012 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Prelínanie</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Prekrývanie:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Prelínanie"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Prelínanie sa nepodarilo, pretože skladby mali rôzny počet kanálov. Môžete\n"
+"použiť Zmiešavač kanálov a previesť piesne na rovnaký počet kanálov."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Prelínanie zlyhalo, pretože skladby majú rozdielnu vzorkovaciu frekvenciu:\n"
+"\n"
+"Na prevzorkovanie skladieb na rovnakú frekvenciu môžete použiť efektový "
+"modul „Konvertor vzorkovacej frekvencie“."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Kryštalizér</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Intenzita:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet zásuvný modul"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Vymazať"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Zrušiť"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Ozvena</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Oneskorenie:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Spätná väzba:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Hlasitosť:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo zásuvný modul\n"
-"napísal Johan Levin, 1999\n"
-"\n"
-"Surround echo napísal Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Ozvena"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg zásuvný modul"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1194,55 +1163,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg zásuvný modul"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Zápis do súboru zásuvný modul"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Formát výstupného súboru:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Nastaviť"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Ukladať do pôvodného adresára"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Ukladať do vlastného adresára"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Priečinok s výstupnými súbormi:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Vybrať priečinok"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Získať názov súboru z:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "pôvodných značiek v súbore"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "názvu pôvodného súboru"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Neodstraňovať príponu názvu súboru"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Na začiatok názvu súboru pridať číslo stopy"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1274,165 +1243,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Zápis do súboru zásuvný modul"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Auto"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Joint Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Nastavenie MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Kvalita algoritmu:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Výstupná vzorkovacia frekvencia:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Dátový tok / kompresný pomer:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Dátový tok (kb/s):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Kompresný pomer:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Zvukový režim:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Rôzne:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Vynútiť prísnu zhodu s ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Ochrana pred chybami"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kvalita"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Povoliť VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Typ:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Nastavenia VBR:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Najmenší dátový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Najväčší dátový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Prísne vynucovať najmenší dátový tok"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Nastavenia ABR:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Priemerný dátový tok (kb/s):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Úroveň kvality VBR:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Nezapisovať hlavičku Xing VBR"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Parametre rámcov:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Pridať označenie autorských práv"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Pridať označenie originálu"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Parametre ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Vynútiť pridanie značiek verzie 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Pridávať iba značky verzie 1"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Pridávať iba značky verzie 2"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Značky"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Nastavenie kodéra Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Úroveň kvality (0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC dekodér"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "bezstratový"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1444,11 +1417,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC dekodér"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1456,11 +1425,19 @@ msgstr ""
 "GIO zásuvný modul pre Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO zásuvný modul"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1472,450 +1449,509 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
-"Zásuvný modul pre klávesové skratky Gnome\n"
-"Ovládajte prehrávač klávesovými skratkami Gnome.\n"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Klávesové skratky GNOME"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Číslo položky"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Názov"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Umelec"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Rok"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Album"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Stopa"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Žáner"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Poradie vo fronte"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Dĺžka"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Cesta k súboru"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Názov súboru"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Vlastný názov"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Dátový tok"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Vyhľadávací nástroj"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Ukotviť vľavo"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Ukotviť vpravo"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Ukotviť hore"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Ukotviť dole"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Uvolniť"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Zakázať"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Vyhľadávací nástroj"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Otvoriť súbory ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Otvoriť _URL ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Prid_ať súbory ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Pridať U_RL ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "_O programe ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Koniec"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Hrať"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "P_ozastaviť"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "Za_staviť"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "Pred_chádzajúca"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Nasledujúca"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "O_pakovať"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "Ná_hodné prehrávanie"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Nep_okračovať podľa zoznamu skladieb"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Zastaviť po tejto skladbe"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Informácie o skladbe ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "S_kočiť na čas ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Skočiť na sk_ladbu ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Podľa _názvu"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Podľa čí_sla stopy"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Podľa _umelca"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Podľa dátumu vy_dania"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Podľa _cesty k súboru"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Podľa vlastného ná_zvu"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Obrátené poradie"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "Náhodné po_radie"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Prehrať tento zoznam skladieb"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Obnoviť"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Zoradiť"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Odstrániť nedost_upné súbory"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Nový"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Pre_menovať ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Importovať ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Exportovať ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Správca_zoznamu skladieb ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Správca _fronty .."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Zo_silniť"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "S_tíšiť"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ekvalizér"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Zobraziť _panel s ponukou"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Zobraziť panel s i_nformáciami"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Zobraziť znázornenie oblasti informácií"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Zobraziť panel so _stavom"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Súbor"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Prehrávanie"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "Zoznam sk_ladieb"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Služby"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Výstup"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Zobrazenie"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "Pridať alebo odobrať z _fronty"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Vys_trihnúť"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopírovať"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "V_ložiť"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Ozn_ačiť všetko"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Premenovať ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Rozhranie GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Napĺňanie vyrovnávajúcej pamäte ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1923,84 +1959,98 @@ msgstr[0] "%d kanálov"
 msgstr[1] "%d kanál"
 msgstr[2] "%d kanály"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Režim jednej skladby."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Režim zoznamu skladieb."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Zastaviť po skončení skladby."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Predchádzajúca skladba"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Prehrať"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Pozastaviť/Pokračovať"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Zastaviť"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Nasledujúca skladba"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Vpred o 5 sekúnd"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Späť o 5 sekúnd"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Stlmiť"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Zvýšenie hlasitosti"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Zníženie hlasitosti"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Prejsť na súbor"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Zobraziť OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Opakovanie"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Náhodné prehrávanie"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Zastaviť po skončení aktuálnej skladby"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(žiadne)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2011,15 +2061,11 @@ msgstr ""
 "\n"
 "Chcete pokračovať?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Priradenie tlačidiel myši"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Nastavenie modulu Globálne klávesové skratky"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2027,23 +2073,27 @@ msgstr ""
 "V textovom poli stlačte kombináciu klávesov.\n"
 "Môžete priradiť aj tlačítka na myši."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Klávesové skratky:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Činnosť:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Priradenie klávesu:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Globálne klávesové skratky"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2069,60 +2119,51 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Globálne klávesové skratky"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK výstup"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Založené na xmms-jack, ktorý napísal Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Port pre Audacious napísal Giacomo Lozito"
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK výstup"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Nastavenia %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Nastavenia hostiteľa LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Cesty modulu:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2133,25 +2174,25 @@ msgstr ""
 "Po pridaní novej cesty, stlačte Enter pre vyhľadanie nových modulov. </ "
 "Small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Dostupné moduly:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Povoliť"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Povolené moduly:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Nastavenie"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2159,49 +2200,15 @@ msgstr ""
 "LADSPA Host pre Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA Host"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr ""
-"%s: nie je možné inicializovať podporu LIRC\n"
-"\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: nie je možné načítať konfiguračný súbor LIRC\n"
-"%s: prosím prečítajte si dokumentáciu k LIRC\n"
-"%s: ako správne vytvoriť konfiguračný súbor\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: pokúšam sa znova pripojiť...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: neznámy príkaz \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: odpojené od LIRC\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: skúsim sa znova napojiť každých %d sekúnd...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC zásuvný modul"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2228,73 +2235,81 @@ msgstr ""
 "\n"
 "Pre viac informácií o LIRC, navštívte http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Pripojenie</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Znovu sa pripojiť k serveru LIRC"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Počkajte pred opätovným pripojením:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC zásuvný modul"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki zásuvný modul"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Žiadne texty k dispozícii"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Chyba"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Nedá sa načítať %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Chyba"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Nedá sa analyzovať %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Vyhľadáva sa text skladby..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Chýba metadata skladby"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Pripájanie na lyrics.wikia.com..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki zásuvný modul"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U zoznam skladieb"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Generátor taktov"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Generátor taktu: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Generátor taktu: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2308,11 +2323,11 @@ msgstr ""
 "napr. tact://77 to play 77 beats per minute\n"
 "alebo tact://60*3/4 to play 60 bpm in 3/4 tacts"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Generátor taktov"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Zmiešavač kanálov"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2320,152 +2335,184 @@ msgstr ""
 "Channel Mixer zásuvný modul pre Audacious\n"
 "Copyright 2011-2012 John Lindgren a Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Zmiešavač kanálov</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Výstupné kanály:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Zmiešavač kanálov"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS zásuvný modul"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module Player) zásuvný modul"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module Player) zásuvný modul"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Priestorový zvuk"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 zásuvný modul"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Priestorový zvuk"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 Server"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS zásuvný modul"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Zastavené"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious teraz neprehráva."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Oznámenia na plochu"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2485,55 +2532,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Oznámenia na plochu"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Pozastaviť"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Nasledujúca"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Štandardné zariadenie"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 výstup"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Zvukové zariadenie:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Použiť iné zariadenie:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Ulož hlasitosť medzi reláciami"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Povoliť konverziu formátu prostredníctvom OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Povoliť exkluzívny režim pre predchádzanie virtuálnemu zmiešavaniu."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2547,19 +2603,35 @@ msgstr ""
 "Chcem poďakovať ľuďom z #audacious, najmä Tonymu Vroonovy a Johnovy "
 "Lindgrenovy a samozrejme autorom predošlého OSS zásuvného modulu."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 výstup"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS zoznamy skladieb"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 dekodér"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio výstup"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2595,11 +2667,68 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio výstup"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Predchádzajúca"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Opakovať"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Náhodné poradie"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Konvertor vzorkovacej frekvencie"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2607,133 +2736,145 @@ msgstr ""
 "Sample Rate Converter zásuvný modul pre Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Preskoč/opakuj vzorky"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineárna interpolácia"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Rýchla sinc interpolácia"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Priemerná sinc interpolácia"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Najlepšia sinc interpolácia"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Prevod</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metóda:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Hodnotenie:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Mapovanie hodnotenia</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Použiť mapovanie hodnotenia"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Konvertor vzorkovacej frekvencie"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "Vyskytol sa problém s pripojením k Last.fm. Prosím, skúste to neskôr."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2744,11 +2885,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2756,7 +2893,11 @@ msgstr ""
 "Audacious odteraz používa vylepšenú verziu doplnku Last.fm Scrobbler.\n"
 "Prosím, skontrolujte Predvoľby doplnku Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL výstup"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2764,88 +2905,59 @@ msgstr ""
 "SDL výstupný zásuvný modul pre Aduacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL výstup"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Knižnica"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Neznámy Umelec"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Neznámy Album"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" na %s od %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d album"
-msgstr[1] "%d álb"
-msgstr[2] "%d albumov"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d skladba"
 msgstr[1] ""
-"%s\n"
-" %s, %d skladby"
 msgstr[2] ""
-"%s\n"
-" %s, %d skladieb"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d skladba od %s"
 msgstr[1] ""
-"%s\n"
-" %d skladby od %s"
 msgstr[2] ""
-"%s\n"
-" %d skladieb od %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Vytvoriť zoznam skladieb"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Pridať do zoznamu skladieb"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Vyhľadať knižnicu"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2853,679 +2965,769 @@ msgstr ""
 "Pre import hudobnej knižnice do Audacious, vyberte priečinok a potom "
 "kliknite na ikonu \"obnoviť\"."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Čakajte prosím ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Vybrať priečinok"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Prehrávanie"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Zoznam skladieb"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Zobrazenie"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Opakovať"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Náhodné poradie"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Neprehrávať ďalšiu skladbu zo zoznamu"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Predchádzajúca"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Nový zoznam skladieb"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Zobraziť editor zoznamu skladieb"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Zobraziť ekvalizér"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Vždy navrchu"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Podľa názvu"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Podľa názvu súboru"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Odstrániť všetky"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Vyprázdniť front"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Odstrániť nedostupné súbory"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Odstrániť duplikáty"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Odstrániť neoznačené"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Odstrániť označené"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Hľadanie a výber"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Invertovať výber"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Zrušiť výber"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Označiť všetko"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Podľa albumu"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Podľa čísla stopy"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Podľa umelca"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Podľa albumu"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Podľa čísla stopy"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Premiešať poradie"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Obrátiť poradie"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Triediť výber"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Triediť zoznam"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Vystrihnúť"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopírovať"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Vložiť"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp Classic Interface"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Uložiť"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Načítať"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Predvoľby"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Načítať predvoľbu"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Načítať automatickú predvoľbu"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Uložiť predvoľbu"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Uložiť automatickú predvoľbu"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Vymazať predvoľbu"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Vymazať automatickú predvoľbu"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "V _okne prehrávača:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Vyberte písmo pre hlavné okno prehrávača:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "V zozname _skladieb:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Vyberte písmo pre zoznam skladieb:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Použiť bitmapové písma (podporuje iba ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Rolovať názov skladby obidvoma smermi"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analyzátor"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Osciloskop"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Žiadne"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normálny"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Oheň"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "ÄŒiary"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Obdĺžniky"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Najpomalšie"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Pomaly"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Stredne"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Rýchlo"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Najrýchlejšie"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Ľad"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Plynulý"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Všeobecné"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Vizualizácia"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Predzosilnenie"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz "
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Ekvalizér Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "prejsť na %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Hlasitosť: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Vyváženie: %d%% vľavo"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Vyváženie: stred"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Vyváženie: %d%% vpravo"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Ponuka s možnosťami"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Vypnúť „Vždy navrchu“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Zapnúť „Vždy navrchu“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Informácie o súbore"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Režim jednej skladby."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Režim zoznamu skladieb."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Zastaviť po skončení skladby."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Vyhľadať skladby v aktívnom zozname skladieb"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3537,57 +3739,61 @@ msgstr ""
 "regulárnym výrazom nerozumiete, jednoducho zadajte časť textu, ktorý chcete "
 "vyhľadať."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Názov: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Umelec: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Názov súboru: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Pred hľadaním vymazať predchádzajúci výber"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Zhodujúce sa položky pridať do (odstrániť z) frontu"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Zo zhodujúcich sa položiek vytvoriť nový zoznam skladieb"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Editor zoznamu skladieb"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d z %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Zabalený vzhľad pre WinAMP 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Nezabalený vzhľad pre WinAMP 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Nepodarilo sa vytvoriť adresár (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile zásuvný modul"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3627,84 +3833,72 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile zásuvný modul"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "O Sndio výstupnom zásuvnom module"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Sndio Output zásuvný modul\n"
-"\n"
-"napísal Thomas Pfaff <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Nepodporovaný formát"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Formát nie je podporovaný týmto zvukovým zariadením.\n"
-"\n"
-"Skúste to znova prosím s bežiacim sndiod(1) serverom."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio zariadenie"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(prázdne znamená predvolené)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "OK"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Zmena skladby"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Príkaz, ktorý sa vykoná keď Audacious začne prehrávať novú skladbu."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Parametre predávané shellu by mali byť uzatvorené do "
+"úvodzoviek. Nerešpektovanie tejto rady predstavuje bezpečnostné riziko.</"
+"span>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Príkaz:"
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Príkaz, ktorý sa vykoná na konci skladby."
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
 msgstr ""
-"Príkaz, ktorý sa vykoná, keď Audacious dosiahne koniec zoznamu skladieb."
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
 msgstr ""
-"Príkaz, ktorý sa vykoná pri zmene názvu skladby (t.j. pre názvy v sieťových "
-"prúdoch)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
+
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3718,36 +3912,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Môžete použiť nasledujúce formátovacie reťazce,\n"
-"ktoré budú pri spustení príkazu nahradené (nie všetky\n"
-"sú užitočné pre príkaz spúšťaný na konci zoznamu skladieb).\n"
-"\n"
-"%F: Frekvencia (v hertzoch)\n"
-"%c: Počet kanálov\n"
-"%f: Názov súboru (celá cesta)\n"
-"%l: Dĺžka (v milisekundách)\n"
-"%n alebo %s: Názov skladby\n"
-"%r: Dátový tok (v bitoch za sekundu)\n"
-"%t: Pozícia v zozname skladieb (%02d)\n"
-"%p: Práve sa hrá (1 alebo 0)\n"
-"%a: Umelec\n"
-"%b: Album\n"
-"%T: Názov stopy"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Parametre predávané shellu by mali byť uzatvorené do "
-"úvodzoviek. Nerešpektovanie tejto rady predstavuje bezpečnostné riziko.</"
-"span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Príkazy"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3756,51 +3930,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Rýchlosť a výška"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Rýchlosť a výška</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Rýchlosť"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Výška"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Rýchlosť a výška"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Stavová ikona"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3818,39 +3992,39 @@ msgstr ""
 "Tento zásuvný modul poskytuje stavovú ikonu, umiestnenú v\n"
 "stavovej oblasti správcu okien."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Rolovanie kolieskom myši</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Zmeniť hlasitosť"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Zmeniť prehrávanú skladbu"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Ostatné nastavenia</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Zakázať vyskakovacie okno"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Zatvor do systémového zásobníka"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Pokračovať v zozname skladieb ak sa posúva smerom hore"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Stavová ikona"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3860,24 +4034,24 @@ msgstr ""
 "\n"
 "Napísal Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Generátor tónov"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Generátor tónov: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3891,15 +4065,11 @@ msgstr ""
 "Pre použitie, pridajte URL: tone://frequency1;frequency2;frequency3;...\n"
 "napr.. tone://2000;2005 prehrá 2000 Hz tón a 2005 Hz tón"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Generátor tónov"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Odstránenie hlasu"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3937,11 +4107,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis dekodér"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX dekodér"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -3951,19 +4145,19 @@ msgstr ""
 "Založené na in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious zásuvný modul napísal Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX dekodér"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack dekodér"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "stratový (hybrid)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "stratový"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -3973,14 +4167,18 @@ msgstr ""
 "\n"
 "časť kódu zásuvného modulu napísal Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack dekodér"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF dekodér"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML Shareable Playlists (XSPF)"
diff --git a/po/sr.po b/po/sr.po
index 94934fc7125e..0b6951523e4f 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -3,13 +3,14 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# Мирослав Николић <miroslavnikolic at rocketmail.com>, 2014-2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 19:51+0000\n"
+"Last-Translator: Мирослав Николић <miroslavnikolic at rocketmail.com>\n"
 "Language-Team: Serbian (http://www.transifex.com/projects/p/audacious/"
 "language/sr/)\n"
 "Language: sr\n"
@@ -19,40 +20,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "моно"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стерео"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "окружење"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "ААЦ (МП4) декодер"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "ААЦ (Сирови) декодер"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "Ад прикључак (АдБибл програм)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "низовни"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "Ад прикључак (АдБибл програм)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Аларм"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "Подеси аларм ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -62,11 +51,7 @@ msgstr ""
 "\n"
 "Првобитни аутори су Адам Фикин и Данијел Стоден."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Аларм"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -107,7 +92,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -147,7 +132,7 @@ msgstr ""
 "    Покреће ову наредбу за време аларма.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -173,385 +158,390 @@ msgstr ""
 "    упишите подсетник у поље и штиклирајте\n"
 "    квадратић ако желите да буде приказиван."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Ово је ваш позив за буђење."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Ваш подсетник за данас је..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Подсетник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Понедељак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Уторак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Среда"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Четвртак"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Петак"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Субота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Недеља"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Подешавања аларма"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "У _реду"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "_Откажи"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Време"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Активирај аларм у (основно):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "часова"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Утишај након:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "сат(а)"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "минута"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Изаберите којим данима ће се активирати аларм"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Дан"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Основно"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дани"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Ишчезавање"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунде"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Јачина"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Започни при"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Заврши при"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Тренутно"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Додатна наредба"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "укључи"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Списак нумера (необавезно)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Изаберите списак нумера"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опције"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Шта значе ове опције?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Помоћ"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Омот албума"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Омот албума (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Излаз АЛСА-е"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Прикључак излаза АЛСА-е за Безочника\n"
+"Ауторска права 2009-2012 Џон Линдгрин\n"
+"\n"
+"Захваљујем се Вилијаму Питкоку, аутору НГ прикључка излаза АЛСА-е, чији је "
+"код служио као узор када упутство АЛСА-е није било довољно."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(без описа)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Основни ПЦМ уређај"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Основни уређај мешача"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "ПЦМ уређај:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Уређај миксера:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Елемент мешача:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Решите суви прекид"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "АМИДИ-Прикључак (МИДИ програм)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Прикључак излаза АЛСА-е за Безочника\n"
-"Ауторска права 2009-2012 Џон Линдгрин\n"
+"АМИДИ-Прикључак\n"
+"Модуларни МИДИ музички програм\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"Захваљујем се Вилијаму Питкоку, аутору НГ прикључка излаза АЛСА-е, чији је "
-"код служио као узор када упутство АЛСА-е није било довољно."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Излаз АЛСА-е"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "АМИДИ-Прикључак (МИДИ програм)"
+"Написао га је Ђакомо Лоцито\n"
+"< james at develia.org >\n"
+"\n"
+"Посебно су заслужни...\n"
+"\n"
+"Клеменс Ладиш и Јарослав Кисела\n"
+"због њихових програма „aplaymidi“ и „amixer“; који\n"
+"су врло корисни, уз „alsa-lib docs“, како бисмо\n"
+"сазнали више о АЛСА АПИју\n"
+"\n"
+"Алфредо Спадафина\n"
+"који је урадио леп логотип МИДИ тастатуре \n"
+"\n"
+"Тони Врун\n"
+"због одличне помоћи за алфа тестирање"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "Препиши основно појачање:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr "Препиши основну полифонију: "
+msgstr "Препиши основну полифонију:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "Препиши основни одјек:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "Укљ."
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "Препиши основни хор:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>Пуштање</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "Премештај:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "полутонови"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "Промена бубња:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>Напредно</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "бројеви ноте"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "Извуци напомене из МИДИ датотеке"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "Прескочи водећу тишину"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "Извуци текст песме из МИДИ датотеке"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "Прескочи пратећу тишину"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>СаундФонт</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>Синтисајзер</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "Проток узорка:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "АМИДИ прикључак — изаберите СаундФонт датотеку"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "От_кажи"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr "_Отвори"
+msgstr "От_вори"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Назив датотеке"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Величина (бајтова)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Назив:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
-msgstr "<span size=\"smaller\"> МИДИ Информације </span>"
+msgstr "<span size=\"smaller\"> МИДИ подаци </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Запис:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Трајање (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Број нумера:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "променљиво"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "БПМ:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "БПМ (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Див време:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> МИДИ коментари и текстови песама </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* нема доступних коментара у овој МИДИ датотеци *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* нема доступних текстова песама у овој МИДИ датотеци *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Затвори"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (неисправан УТФ-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "О АМИДИ прикључку"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "АМИДИ прикључак"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Модуларни МИДИ музички програм\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Написао га је Ђакомо Лоцито\n"
-"< james at develia.org >\n"
-"\n"
-"\n"
-"Посебно су заслужни...\n"
-"\n"
-"Клеменс Ладиш и Јарослав Кисела\n"
-"због њихових програма „aplaymidi“ и „amixer“; који\n"
-"су врло корисни, уз „alsa-lib docs“, како бисмо\n"
-"сазнали више о АЛСА АПИју\n"
-"\n"
-"Алфредо Спадафина\n"
-"који је урадио леп логотип МИДИ тастатуре \n"
-"\n"
-"Тони Врун\n"
-"због одличне помоћи за алфа тестирање"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -561,153 +551,154 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"НЕП Безочника\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Написао га је Ђакомо Лоцито < james at develia.org >\n"
+"\n"
+"Делом је заснован на библиотеци „Ghosd“ коју је написао Еван Мартин\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "БОСД (Приказ на екрану)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Правоугаоник"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Заобљени правоугаоник"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Удубљен правоугаоник"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ништа"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Почетак репродукције"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Приказује ОСД када почиње репродукција песме."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Промена наслова"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"Приказује ОСД када се, у току репродукције, измени наслов песме али назив "
-"датотеке остане исти. Ово је углавном корисно за приказивање измена у "
-"насловима у интернет токовима."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "Пребацује ОСД када се промени наслов песме (за интернет токове)."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Паузирање"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Приказује ОСД када је репродукција привремено заустављена."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Отпаузирање"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Приказује ОСД када је репродукција поново покренута."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Постављање"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Релативан хоризонтални померај:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Релативан вертикални померај:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Највећа ширина приказа:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Опција више монитора"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Прикажи ОСД на:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "свим мониторима"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "на монитору бр. %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Време трајања (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Приказ:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Појављивање:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Ишчезавање:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Словни ликови"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Писмо %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Сенка"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Стил исцртавања"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Боје"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Боја %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Омогући активирање"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Догађај"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Откривен је композитни управник"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -717,112 +708,112 @@ msgstr ""
 "осим ако знате да је један већ покренут, молим покрените композитног "
 "управника јер у супротном ОСД неће радити исправно"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Композитни управник није потребан за лажну провидност"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Провидност"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Лажна провидност"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Стварна провидност (захтева Х композитно проширење)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Композитно проширење није учитано"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Композитно проширење није доступно"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Безочник — ОСД</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Безочник ОСД — подешавања"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Испробај"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Подеси"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Положај"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анимација"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Декорација"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Укључивање"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Остало"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Испробај"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "АСИксв3 списак нумера"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "АСИксв1/АСИксв2 спискови нумера"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Безочникови спискови нумера (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Боје</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Обим замућења"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Бојер стереофонски-у-бинаурални (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Претподешавања:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Ниво довода:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Учестаност исецања:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Претподешавања:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Бојер стереофонски-у-бинаурални (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Анализатор спектра"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Прикључак звучног ЦД-а"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -842,171 +833,158 @@ msgstr ""
 "\n"
 "Беше то Гугл лето пројекта Кôд 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Уређај</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Брзина читања:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Препиши уређај:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метаподаци</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Користи ЦД-текст"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Користи ЦДБП"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Користи ХТТП уместо ЦДДБП-а"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Путања:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Прикључник:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Прикључак звучног ЦД-а"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Нисам успео да започнем цдуи подсистем."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Неисправна путања „%s“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Нисам пронашао нумеру „%d“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Нумера „%d“ је запис података."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Нисам успео да отворим излаз звука."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Грешка читања звучног диска."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Аудио ЦД"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Нумера %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Нисам успео да отворим ЦД уређај „%s“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Нисам пронашао уређај за читање ЦД-а."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Нисам успео да завршим покретање отвореног ЦД уређаја."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Нисам успео да пронађем број прве/последње нумере."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Не могу да прочитам почетак/крај ЛСН-а за нумеру „%d“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Нисам успео да направим везу са цд базом података."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Нисам успео да пропитам сервер базе података ЦД-а"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Нисам успео да пропитам сервер базе података ЦД-а: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Нисам успео да прочитам обавештење базе података цд-а: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Уређај је празан."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Неподржана врста диска."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Ставке изборника звучног ЦД-а"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Пусти ЦД"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Додај ЦД"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Ставке изборника звучног ЦД-а"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Сажимање</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Главна јачина:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамички опсег:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Прикључак сажимања динамичког опсега за Безочника\n"
-"Ауторска права 2010-2012 Џон Линдгрин"
+"Ауторска права 2010-2014 Џон Линдгрин"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Сажиматељ динамичког опсега"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1021,206 +999,238 @@ msgstr ""
 "Вилијам Питкок <nenolod at dereferenced.org>, \n"
 "Шај Грин <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Ниски тонови:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Високи тонови:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "Одјек:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Основно трајање песме:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Поновно узорковање</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Укључи поновно узорковање"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Проток поновног узорковања:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>СПЦ</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Занемари трајање из СПЦ ознака"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Повећај одјек"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Конзолни музички декодер игре"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"Постепени прелаз није успео јер је песма имала различит број канала. Можете "
-"да користите Мешача канала да претворите песме на исти број канала."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "Коре‑аудио излаз"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Постепени прелаз није успео јер је песма имала различит проток узорка.  "
-"Можете да користите Претварача протока узорка да претворите песме на исти "
-"проток узорка."
+"Прикључак Коре-аудио излаза за Безочника\n"
+"Ауторска права 2014 Вилијам Питкок\n"
+"\n"
+"Засновано на прикључку СДЛ излаза за Безочника:\n"
+"Ауторска права 2010 Џон Линдгрин"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "Користи искључиви режим"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Прикључак постепеног прелаза за Безочника\n"
-"Ауторска права 2010-2012 Џон Линдгрин"
+"Ауторска права 2010-2014 Џон Линдгрин"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Постепени прелаз</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "При самосталној промени песме"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Преклапање:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "При премотавању или ручној промени песме"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>Савет</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+"За бољи постепени прелаз, укључите\n"
+"дејство уклањања тишине."
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Постепени прелаз"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Постепени прелаз није успео јер је песма имала различит број канала. Можете "
+"да користите Мешача канала да претворите песме на исти број канала."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Постепени прелаз није успео јер је песма имала различит проток узорка.  "
+"Можете да користите Претварача протока узорка да претворите песме на исти "
+"проток узорка."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристализатор</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Јакост:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристализатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Прикључак „cue“ табеле"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Обриши датотеке"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "Грешка премештања „%s“ у смеће: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "Грешка брисања „%s“: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "Грешка брисања „%s“: није месна датотека."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "Да ли желите да преместите изабране датотеке у смеће?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Премести у смеће"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Да ли желите трајно да обришете изабране датотеке?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Обриши"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Откажи"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Обриши датотеке"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Обришите изабране датотеке"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>Начин брисања</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "Преместите у смеће уместо да одмах обришете"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Прикључак одјека\n"
+"Аутор Јохан Левин 1999\n"
+"Одјек окружења је написао Карл ван Шаик, 1999\n"
+"За Безочника су га освежили Вилијам Питкок и Џон Линдгрен, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Одјек</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Застој:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Одзив:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Јачина звука:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Прикључак одјека\n"
-"Аутор Јохан Левин 1999\n"
-"\n"
-"Окружење одјека је написао Карл ван Шаик, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Одјек"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Прикључак ФФмпег-а"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1236,55 +1246,55 @@ msgstr ""
 "Вилијам Питкок <nenolod at nenolod.net>\n"
 "Мати Хамалајнен <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Прикључак ФФмпег-а"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Прикључак записивања датотека"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Формат излазне датотеке:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Подеси"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Сачувај у оригиналном директоријуму"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Сачувај у произвољном директоријуму"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Фасцикла излазне датотеке:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Изаберите фасциклу"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Набави име датотеке из:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "Створи назив датотеке из:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "ознаке оригиналне датотеке"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "Изворне ознаке датотеке"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "назива оригиналне датотеке"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "Изворног назива датотеке"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Не одузимај проширење назива датотеке"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "Укључи проширење изворног назива датотеке"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Придодај број нумере називу датотеке"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "Стави број нумере назива датотеке"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1316,165 +1326,169 @@ msgstr ""
 "„Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA“."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Прикључак записивања датотека"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Самостално"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Удружени стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "МП3 подешавања"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "У _реду"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Квалитет алгоритма:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Проток узорка излаза:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr "Излазни проток узорка:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "Проток бита / Однос сажимања:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Проток бита (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Однос сажимања:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Режим звука:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
 msgstr "Разно:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Присили строго ИСО поштовање"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "Приморај изричиту ИСО сагласност"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Грешка заштите"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Квалитет"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
-msgstr "Укључи ВБР/АБР"
+msgstr "Укључи ППБ/СПБ"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Врста:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
-msgstr "ВБР опције:"
+msgstr "Опције ППБ-а:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Најмањи проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Највећи проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Строго спроведи најмањи проток бита"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
-msgstr "АБР опције:"
+msgstr "Опције СПБ-а:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
-msgstr "Просечни проток бита (kb/s):"
+msgstr "Средњи проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
-msgstr "Ниво ВБР квалитета:"
+msgstr "Ниво квалитета ППБ-а:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Не записуј Хинг ВБР заглавље"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "Изостави Иксинг заглавље ППБ-а"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
-msgstr "ВБР/АБР"
+msgstr "ППБ/СПБ"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "Параметри кадра:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Означи као ауторско право"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Означи као оригинал"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ИД3 параметри:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Присили додавање ознаке издања 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Додај само в1 ознаку"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Додај само в2 ознаку"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Ознаке"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Подешавање Ворбис шифрера"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Ниво квалитета (0 — 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "ФЛАЦ декодер"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "без губитака"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1486,11 +1500,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "ФЛАЦ декодер"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1498,11 +1508,19 @@ msgstr ""
 "ГУИ прикључак за Безочника\n"
 "Ауторска права 2009-2012 Џон Линдгрин"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "ГУИ прикључак"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "Режим читај-и-прикачи није подржан"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "Неисправан режим отварања"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1522,450 +1540,522 @@ msgstr ""
 "\n"
 "Дозвола: ОЈЛв2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "ОпенГЛ Анализатор спектра"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"Прикључак Гномове пречице\n"
-"Омогућава вам да управљате програмом користећи Гномове пречице.\n"
+"ОпенГЛ анализатор спектра за Безочника\n"
+"Ауторска права 2013 Кристоф Буде, Џон Линдгрин, и Карло Брамини\n"
+"Ауторска права 2014 Вилијам Питкок\n"
 "\n"
-"Ауторска права (C) 2007-2008 Саша Хласјак <contact at saschahlusiak.de>"
+"Засновано на ИКсММС прикључку:\n"
+"Ауторска права 1998-2000 Питер Алм, Мајкол Алм, Оле Халнас, Томас Нилсон, и "
+"4Фронт Технологије\n"
+"\n"
+"Дозвола: ОЈЛв2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "ОпенГЛ Анализатор спектра (Qt)"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr "Гномове пречице"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"Прикључак Гномових пречица\n"
+"Управљајте пуштачем музике Гномовим пречицама.\n"
+"\n"
+"Ауторска права (C) 2007-2008 Саша Хлусјак <contact at saschahlusiak.de>"
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Број ставке"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Наслов"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Извођач"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Година"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Албум"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Извођач албума"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Нумера"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Положај колоне"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Трајање"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Путања датотеке"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Назив датотеке"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Произвољан наслов"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Битски проток"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "Доступни ступци"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "Приказани ступци"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Алат за претрагу"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Усидри на лево"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Усидри на десно"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Усидри на врх"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Усидри на дно"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Откачи"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Искључи"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Алат за претрагу"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Отвори _датотеке ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Отвори _адресу ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Додај да_тотеке ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Додај ад_ресу ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "Претражи _библиотеку"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "О _програму ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "_Подешавања ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Изађи"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "Пу_сти"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Па_узирај"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Заустави"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Претходно"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "С_ледеће"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Понови"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Насумично"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Н_е напредуј у списку нумера"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Заустави _након ове песме"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Подаци о _песми ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Пређи на _време ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Пређи на _песму ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Постави _А тачку понављања"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Постави _Б тачку понављања"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Очисти тачке понављања"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Према _наслову"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "Према називу _датотеке"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "Према _путањи датотеке"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Према броју _нумере"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Према _извођачу"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "Према _албуму"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "Према извођачу албу_ма"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Према _датуму издавања"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "Према _жанру"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "Према _трајању"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Према _путањи датотеке"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
-msgstr "Према п_роизвољном наслову"
+msgstr "Према произвољном _наслову"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Преокрени п_оредак"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Случајан поредак"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Пусти овај списак нумера"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Пусти/Настави"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Освежи"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "Пор_еђај"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "Поређај _означене"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Уклони _двоструке"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Уклони _недоступне датотеке"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Ново"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Преименуј ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "_Уклони"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "Ув_ези ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "Из_вези ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Управник списка _нумера ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Управник _редоследа ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "По_јачај"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "У_тишај"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "Ује_дначавач"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "_Дејства ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Прикажи траку _изборника"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Прикажи траку _података"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Прикажи _визуелизацију траке обавештења"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Прикажи траку _стања"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Прикажи преостало _време"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "_Визуелизације ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Датотека"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Извођење"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Списак нумера"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Услуге"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Излаз"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Преглед"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Стави у ред/Избаци из реда"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "_Отвори садржавајућу фасциклу"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Исеци"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "У_множи"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "У_баци"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_Изабери све"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Преименуј ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>Језичци списка нумера</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "Увек прикажи језичке"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "Прикажи број уноса"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "Прикажи дугмад затварања"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>Ступци списка нумера</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "Прикажи заглавља колона"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Разно</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "Стралице померају за:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "Клизај при промени песме"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "ГТК сучеље"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s — Безочник"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Баферујем ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Безочник"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "моно"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стерео"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1973,84 +2063,98 @@ msgstr[0] "%d канал"
 msgstr[1] "%d канала"
 msgstr[2] "%d канала"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kb/s"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Једноставни режим."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Режим списка нумера."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Зауставља након песме."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Претходна нумера"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Пусти"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Паузирај/настави"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Заустави"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Следећа нумера"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "Унапред 5 секунде"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "Уназад 5 секунде"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Искључи звук"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Појачај"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Утишај"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Скочи до датотеке"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Укључи/искључи главни прозор"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Прикажи приказ на екрану"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Укључи/искључи понављање"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Укључи/искључи премештање"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Заустави после текуће песме"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Издигни главни прозор"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ништа)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2061,15 +2165,11 @@ msgstr ""
 "\n"
 "Да ли желите да наставите?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Повезујем дугмад миша"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Подешавања прикључка општих пречица"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2077,23 +2177,27 @@ msgstr ""
 "Притисните комбинацију тастера унутар поља за текст.\n"
 "Можете такође да повежете дугмад миша."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Пречице:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Радња:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Свезе тастера:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Додај"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Опште пречице"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2120,60 +2224,55 @@ msgstr ""
 " Џонатан А. Давис <davis at jdhouse.org>\n"
 " Џереми Тан <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Опште пречице"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "ЏЕК излаз"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "Повежи са свим расположивим портовима утичница"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "Самостално повезивање на прикључнике излаза"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "Повежи само излазне портове"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "Нашао сам само %d излазна прикључка ЏЕК-а али су потребна %d."
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "Не повезуј се на прикључнике"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Нисам успео да се повежем на прикључник ЏЕК-а „%s“."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "Режим повезивања:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"ЏЕК подржава само звук покретног зареза.  Морате изменити дубину излазног "
+"бита на покретни зарез у подешавањима Безочника."
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "Укључи штампање уклањања грешака"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "Нисам успео да се повежем на сервер ЏЕК-а; да ли је покренут?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Засновано на иксммс-џеку, који је приредио Крис Морган:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ђакомо Лоцито је припремио за Безочника"
+"ЏЕК сервер захтева проток узорка од %d Hz, али Безочник пушта при %d Hz.  "
+"Користите дејство претварача протока узорка да исправите несагласност."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "ЏЕК излаз"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Подешавања за %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Подешавања ЛАДСПА домаћину"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Путање модула:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2184,25 +2283,25 @@ msgstr ""
 "Након додавања нових путања, притисните Унеси да потражите нове прикључке.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Доступни прикључци:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Укључи"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Укључени прикључци:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Подешавања"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2210,47 +2309,15 @@ msgstr ""
 "ЛАДСПА домаћин за Безочника\n"
 "Ауторска права 2011 Џон Линдгрин"
 
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "ЛАДСПА домаћин"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: не могу да започнем ЛИРЦ подршку\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: не могу да прочитам датотеку ЛИРЦ подешавања\n"
-"%s: молим прочитајте ЛИРЦ документацију\n"
-"%s: како да направите личну датотеку подешавања\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: покушавам да се поново повежем...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: непозната наредба „%s“\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: прекинута је веза са ЛИРЦ-а\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "ЛАДСПА домаћин"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: покушаћу да се поново повежем сваке %d секунде...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "ЛИРЦ прикључак"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2279,73 +2346,81 @@ msgstr ""
 "\n"
 "Да сазнате више о ЛИРЦ-у, погледајте „http://lirc.org“."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Веза</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Поново се повежи са ЛИРЦ сервером"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Сачекај пре поновног повезивања:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "ЛИРЦ прикључак"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Прикључак за Лирик вики"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Нема доступних текстова"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Грешка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Не могу да довучем „%s“"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Грешка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Не могу да обрадим „%s“"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Тражим текст песме ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Недостају метаподаци песме"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Повезујем се на „lyrics.wikia.com“ ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Прикључак за Лирик вики"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "Прикључак за Лирик вики (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "М3У списак нумера"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Генератор такта"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Генератор такта: %d отк/мин"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Генератор такта: %d отк/мин %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2359,11 +2434,11 @@ msgstr ""
 "нпр.: „tact://77“ да добијете 77 откуцаја у минуту\n"
 "или: „tact://60*3/4“ да добијете 60 отк./мин у 3/4 такту"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Генератор такта"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Мешач канала"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2371,152 +2446,185 @@ msgstr ""
 "Прикључак мешача канала за Безочника\n"
 "Ауторска права 2011-2012 Џон Линдгрин и Михал Липски"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Мешач канала</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Излазни канали:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Мешач канала"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "ММС прикључак"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "Грешка повезивања на ММС сервер"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "Мод прикључак (Програм за модле)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Резолуција</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8 бита"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16 бита"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Бр. канала</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Најближе (најбрже)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Линеарно (брзо)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Сп-крива (добро)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Полифазни (најбоље)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Проток узорка</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr "<b>Проток узорка:</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Ниво:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Прекид:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Одјек</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Прираст баса</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Окружење</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Претпојачање</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Преклапање"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Смањење буке"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Пуштај Амига МОД-е"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Понови</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Број понављања:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "За непрекидно понављање, поставите број понављања на -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "Мод прикључак (Програм за модле)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Окружење"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
+"Ова подешавања ће ступити у дејство након поновног покретања Безочника."
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "МПГ123 прикључак"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Напредно</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "Користи тачан прорачун трајања (споро)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Окружење"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "МПРИС 2 сервер"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Неон ХТТП/ХХТПС прикључак"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "Грешка обраде преусмерења"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "Непозната ХТТП грешка"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "Грешка обраде адресе"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "Превише преусмерења"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Заустављено"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Безочник не пушта песме."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Обавештења радне површи"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2552,55 +2660,64 @@ msgstr ""
 "Требали сте да примите примерак Гнуове опште јавне лиценце уз овај\n"
 "програм. Ако нисте, погледајте <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Прикажи дугмад за пуштање"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Звек прикажи обавештења"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Обавештења радне површи"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "Укључи назив албума у обавештењу"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Прикажи"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Паузирај"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Следећа"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Основни уређај"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "ОСС4 излаз"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "ОСС3 излаз"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "Основни уређај"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Звучни уређај:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Користи алтернативни уређај:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Сачувајте јачину звука између сесија."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Укључује претварање формата направљено ОСС софтвером."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Укључује искључиви режим да спречи виртуално мешање."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2614,19 +2731,35 @@ msgstr ""
 "Желим да се захвалим људима на „#audacious“, нарочито Тони Вруну и Џону "
 "Линдгрину и наравно ауторима претходног ОСС прикључка."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "ОСС4 излаз"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Управник списка нумера"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Уноси"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Уклони"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "_Преименуј"
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "ПЛС спискови нумера"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "ОпенПСФ ПСФ1/ПСФ2 декодер"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Пулс‑аудио излаз"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2663,11 +2796,73 @@ msgstr ""
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Пулс‑аудио излаз"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "Излаз Кут мултимедија"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Прикључак аудио излаза Кут мултимедија за Безочника\n"
+"Ауторска права 2014 Вилијам Питкок\n"
+"\n"
+"Засновано на прикључку СДЛ излаза за Безочника\n"
+"Ауторска права 2010 Џон Линдгрин"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "Радим ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Потражи"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "Отвори _фасциклу ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "_Додај фасциклу ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "Надзорник _дневника ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "Отвори датотеке"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "Додај датотеке"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Претходна"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Понови"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Насумично"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Кут сучеље"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Претварач протока узорка"
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2675,98 +2870,106 @@ msgstr ""
 "Прикључак Претварача протока узорка за Безочника\n"
 "Ауторска права 2010-2012 Џон Линдгрин"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Прескочи/понови узорке"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Линијско уметање"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Брзо уметање усклађења"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Средње уметање усклађења"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Најбоље уметање усклађења"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Претварање</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метод:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Проток:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Мапирање протока</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Користи мапирање протока"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Претварач протока узорка"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "У реду. Скроблујем за корисника: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Овлашћења су одбијена"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Приступите следећој вези да омогућите Безочнику да скроблује ваша пуштања:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Задржите овај прозор отвореним и опет притисните „Провери овлашћења“.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2774,34 +2977,38 @@ msgstr ""
 "Не брините. Ваша скробловања су сачувана на вашем рачунару.\n"
 "Биће послата чим Безочнику то буде било омогућено."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Проблем са мрежом."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Дошло је до проблема ступања у везу са Ласт.фм-ом. Касније покушајте поново."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Проверавам..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "_Провери овлашћења"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Уклони овлашћења"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Требате да омогућите Безочнику да скроблује нумере до вашег Ласт.фм налога.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Скроблер 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2809,7 +3016,7 @@ msgstr ""
 "Прикључак Скроблера не може бити покренут.\n"
 "Можда је проблем са вашом инсталацијом."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2826,11 +3033,7 @@ msgstr ""
 "Захваљујем се Џону Линдгрину што ми је помогао на почетку овог пројекта.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Скроблер 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2838,7 +3041,11 @@ msgstr ""
 "Безочник сада користи побољшано издање Ласт.фм-овог Скроблера.\n"
 "Проверите у поставкама за прикључком Скроблера"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "СДЛ излаз"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2846,88 +3053,59 @@ msgstr ""
 "Прикључак СДЛ излаза за Безочника\n"
 "Ауторска права 2010 Џон Линдгрин"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "СДЛ излаз"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Библиотека"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Непознат извођач"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Непознат албум"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" „%s“ изводи %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d резултат"
+msgstr[1] "%d резултата"
+msgstr[2] "%d резултата"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d албум"
-msgstr[1] "%d албума"
-msgstr[2] "%d албума"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d скривена)"
+msgstr[1] "(%d скривене)"
+msgstr[2] "(%d скривених)"
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s, %d песма"
-msgstr[1] ""
-"%s\n"
-" %s, %d песме"
-msgstr[2] ""
-"%s\n"
-" %s, %d песама"
-
-#: src/search-tool/search-tool.c:639
-#, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d песма коју изводи %s"
-msgstr[1] ""
-"%s\n"
-" %d песме које изводи %s"
-msgstr[2] ""
-"%s\n"
-" %d песама које изводи %s"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d песма"
+msgstr[1] "%d песме"
+msgstr[2] "%d песама"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "овог жанра"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr " "
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "изводи"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Направи списак нумера"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Додај у списак нумера"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Претражите библиотеку"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2935,679 +3113,771 @@ msgstr ""
 "Да увезете вашу музичку библиотеку у Безочнику, изаберите фасциклу и затим "
 "кликните на иконицу „освежи“."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Молим сачекајте ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Изаберите фасциклу"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "СИД пуштач"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>Излаз</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "Бр. канала:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>Опонашање</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "Опонашај МОС 8580 (основно: МОС 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "Не бирај сам модел чипа"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "Опонашај пропусник"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "Брзина сата:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "Не бирај сам брзину сата"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>Време пуштања</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "Подеси највеће време пуштања:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "Користи само када је трајање песме непознато"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "Подеси најмање време пуштања:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Субтјунс</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "Укључите субтјунсе"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "Занемари субтјунсе краће од:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>Напомена</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "Уклањање тишине"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Прикључак уклањања тишине за Безочника\n"
+"Ауторска права 2014 Џон Линдгрин"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>Уклањање тишине</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "Осетљивост:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Отвори датотеке ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "Отвори адресу ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "Претражи библиотеку"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Пуштање"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Списак нумера"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
-msgstr "Преглед"
+msgstr "Поглед"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Услуге"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "О програму ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Подешавања ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Изађи"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Подаци о песми ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Понови"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Насумично"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Не напредуј у списку нумера"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Заустави након ове песме"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Претходна"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "Постави А—Б понављања"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "Очисти А—Б понављања"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "Пређи на песму ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "Пређи на време ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Пусти овај списак нумера"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Пусти/Настави"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Нови списак нумера"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Преименуј списак нумера ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Нови списак нумера"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Претходни списак нумера"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Следећи списак нумера"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Увези списак нумера ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Извези списак нумера ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Управник списка нумера ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Управник редоследа ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Освежи списак нумера"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Прикажи уређивач списка нумера"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Прикажи уједначавач"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "Прикажи преостало време"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Увек у првом плану"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "Све на радне просторе"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "Замотај плејер"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "Замотај уређивач списка нумера"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "Замотај уједначавач"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "Двострука величина"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "Додај адресу ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "Додај датотеке ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Према наслову"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "Према називу датотеке"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "Према путањи датотеке"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Уклони све"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Обриши заказано"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Уклони недоступне датотеке"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Уклони дупликате"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Уклони неозначене"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Уклони означене"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Претражи и означи"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Обрни избор"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Означи ништа"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Означи све"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Према албуму"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Према броју нумере"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Према извођачу"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Према албуму"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "Према извођачу албума"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "Према датуму издавања"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Према броју нумере"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "Према жанру"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "Према трајању"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "Према произвољном наслову"
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Насумице испремештај списак"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Преокрени списак"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Поређај означене"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Поређај списак"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Исеци"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Умножи"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Убаци"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "Стави у ред/Избаци из реда"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "Учитај претподешавање ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "Учитај самостално претподешавање ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "Учитај основно"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "Учитај датотеку претподешавања ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "Учитај ЕКуФ датотеку ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "Сачувај претподешавање ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "Сачувај самостално претподешавање ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "Сачувај основно"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "Сачувај датотеку претподешавања ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "Сачувај ЕКуФ датотеку ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "Обриши претподешавање ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "Обриши самостално претподешавање ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "Увези Винамп претподешавања ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "Врати на нулу"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Винампово уобичајено сучеље"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Сачувај"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Учитај"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "Учитај датотеку претподешавања"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "Учитај ЕКуФ датотеку"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "Сачувај датотеку претподешавања"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "Сачувај ЕКуФ датотеку"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "Увези Винамп претподешавања"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Претподешавања"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Учитава претподешавање"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Учитава самостално претподешавање"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Чува претподешавање"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Чува самостално претподешавање"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Избриши претподешавање"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Брише самостално претподешавање"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Плејер:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Пуштач:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
-msgstr "Изаберите словни лик главног прозора плејера:"
+msgstr "Изаберите словни лик главног прозора програма:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Списак нумера:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Списак нумера:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Изабери словни лик списка нумера:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>Маска</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr "<b>Словни ликови</b>"
+msgstr "<b>Слова</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Користи битмап словне ликове (подржава само АСКРИ)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "Померај наслов песме"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Померај наслов песме у оба смера"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Анализатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Досег"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "Режим отиска гласа / ВУ мерач"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Искључено"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Нормалан"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Ватра"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr "Вертикалне линије"
+msgstr "Усправне линије"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Линије"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Траке"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Најспорије"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Споро"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Средње"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Брзо"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Најбрже"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "Тачке"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "Линија"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "Испуњено"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лед"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Глатко"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>Врста</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "Врста приказивања:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>Анализатор</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "Прикажи врхунце"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "Боја:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "Изглед:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "Опадање:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "Опадање врхова:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "Режим досега:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "Обојавање отиска гласа:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "Стил ВУ мерача:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Опште"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Приказивање"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Претпојачање"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Уједначавач Безочника"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Тражи до: %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Јачина звука: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Уравнотеженост: %d%% леви"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Уравнотеженост: центрирано"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Уравнотеженост: %d%% десни"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Изборник опција"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Искључи „Увек у првом плану“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Укључи „Увек у првом плану“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
-msgstr "Поље информација о датотеци"
+msgstr "Поље података датотеке"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "Визуализације"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Понови скуп тачке А."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Понови скуп тачке Б."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Понови очишћене тачке."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Једноставни режим."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Режим списка нумера."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Зауставља након песме."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Претражи ставке у активном списку нумера"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "Потражи"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3619,57 +3889,61 @@ msgstr ""
 "како обични изрази функционишу, једноставно дословно унесите део онога што "
 "тражите."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Наслов: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr "Наслов:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Албум: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr "Албум:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Извођач: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr "Извођач:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Назив датотеке: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "Назив датотеке:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Обриши претходни избор пре претраге"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Подударајуће ставке самостално пребаци у ред"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Направи нови списак нумера са подударајућим ставкама"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Уређивач списка нумера"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d од %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Архивирана Винамп 2.x маска"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Неархивирана Винамп 2.x маска"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Не могу да направим фасциклу (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Прикључак звучне датотеке"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3696,7 +3970,7 @@ msgstr ""
 "За Безочника га је прилагодио Тони Врун <chainsaw at gentoo.org>\n"
 "\n"
 "Овај програм је слободан софтвер; можете га прослеђивати\n"
-"и/или мењати под условима ГНУ Опште јавне лиценце коју је\n"
+"и/или мењати под условима Гнуове Опште јавне лиценце коју је\n"
 "објавила Задужбина слободног софтвера; верзије 2 лиценце\n"
 "или (по вашем избору) било које новије верзије.\n"
 "\n"
@@ -3705,88 +3979,76 @@ msgstr ""
 "ТРЖИШНЕ ВРЕДНОСТИ или ПРИЛАГОЂЕНОСТИ ОДРЕЂЕНОЈ НАМЕНИ.\n"
 "Погледајте ГНУ Општу јавну лиценцу за више детаља.\n"
 "\n"
-"Требали сте да примите примерак ГНУ Опште јавне лиценце\n"
+"Требали сте да примите примерак Гнуове Опште јавне лиценце\n"
 "уз овај програм; ако нисте, пишите Задужбини слободног\n"
 "софтва на адресу: Free Software Foundation, Inc.,\n"
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Прикључак звучне датотеке"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Излаз звкуи"
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "О прикључку звучногуи излаза"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Прикључак звучногуи излаза\n"
-"\n"
-"Написао га је Томас Пфаф <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "Уређај (празно за основно):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Неподржани облик датотеке"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "Сачувај и врати јачину звка:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"Звучни уређај је затражио неподржани облик датотеке.\n"
-"\n"
-"Молим покушајте опет са покренутим „sndiod(1)“ сервером."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Звкуи грешка: Неподржан запис звука (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "звучниуи уређај"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Звкуи грешка: није успело „sio_open()“"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(празно значи задато)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Звкуи грешка: није успело „sio_setpar()“"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "У реду"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Звкуи грешка: није успело „sio_start()“"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Промена песме"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Наредба за покретање када Безочник започиње нову песму."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Параметри прослеђени љусци би требало да буду у "
+"наводницима. Све другачије је безбедносни ризик.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>Наредбе</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Наредба:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "Наредба за покретање приликом почетка нове песме:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Наредба за покретање при крају песме."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "Наредба за покретање при крају песме:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Наредба за покретање када Безочник стигне на крај списка нумера."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "Наредба за покретање при крају списка нумера:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr ""
-"Наредба за покретање када се промени наслов песме (тј. наслови мрежних "
-"токова)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "Наредба за покретање када се промени наслов песме (за мрежне токове):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3800,9 +4062,8 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Можете да користите следеће ниске формата које\n"
-"ће бити замењене пре позивања наредбе\n"
-"(нису све корисне за наредбу крај-списка-нумера):\n"
+"Можете да користите следеће ниске записа које ће бити замењене пре позивања "
+"наредбе (нису све корисне за наредбу краја-списка-нумера):\n"
 "\n"
 "%F:         Учесталост (у херцима)\n"
 "%c:         Број канала\n"
@@ -3810,25 +4071,21 @@ msgstr ""
 "%l:         Трајање (у милисекундама)\n"
 "%n или %s:  Назив песме\n"
 "%r:         Проток (у битима у секунди)\n"
-"%t:         Позиција списка нумера (%%02d)\n"
+"%t:         Позиција списка нумера (%02d)\n"
 "%p:         Тренутно пуштена (1 или 0)\n"
 "%a:         Уметник\n"
 "%b:         Албум\n"
 "%T:         Наслов нумере"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>Параметри прослеђени љусци би требало да буду у "
-"наводницима. Све другачије је безбедносни ризик.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "Подаци о песми (Кут)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Наредбе"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "СоКС поновни узорковач"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3842,51 +4099,51 @@ msgstr ""
 "Засновано на прикључку претварача протока узорка:\n"
 "Ауторска права 2010-2012 Џон Линдгрин"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Брзо"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Ниско"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Високо"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Врло високо"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Квалитет:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "СоКС поновни узорковач"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Брзина и врхунац"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Брзина и врхунац</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Брзина:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Врхунац:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Брзина и врхунац"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Иконица стања"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "_Подешавања ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3904,39 +4161,39 @@ msgstr ""
 "Овај додатак обезбеђује иконицу стања, смештену\n"
 "у области фиоке система управника прозора."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Радња клизања мишем</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Промени јачину звука"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Промени песму"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Остала подешавања</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Искључи прозор облачића"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Затвори у системску касету"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Напредује у списку нумера када клиза унапред"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Иконица стања"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Додатни стерео"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3946,24 +4203,24 @@ msgstr ""
 "\n"
 "Написао га је Џон Левин, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Додатни стерео</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Додатни стерео"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Тонски генератор"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Тонски генератор: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3978,15 +4235,11 @@ msgstr ""
 "учесталост3;...\n"
 "нпр.: tone://2000;2005 да пустите тонове 2000 Hz и 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Тонски генератор"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Уклањање гласа"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4024,11 +4277,46 @@ msgstr ""
 "Ђанкарло Паскуто <gcp at sjeng.org>\n"
 "Јуџон Загидулин <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Огг Ворбис декодер"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "Појединости о „%s“"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"Наслов: %t\n"
+"Извођач: %a\n"
+"Од: %f\n"
+"Пратилац: %T\n"
+"Напомена: %C\n"
+"Врста чипа: %c\n"
+"Стерео: %s\n"
+"Понављање: %l\n"
+"Учестаност чипа: %F\n"
+"Учестаност пуштача: %P\n"
+"Година: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "ВТКС декодер"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4040,19 +4328,19 @@ msgstr ""
 "ru>\n"
 "Прикључак за Безочника је написао Павел Виметалек <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "ВТКС декодер"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Вејвпак декодер"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "ослабљено (хибридно)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "ослабљено"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4062,14 +4350,18 @@ msgstr ""
 "\n"
 "Нешто кода прикључка је написао Мајлс Иган."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Вејвпак декодер"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2СФ декодер"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>ИксСФ подешавања</b>"
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "Занемари трајање из датотеке"
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "ИксМЛ дељиви спискови пуштања (XSPF)"
diff --git a/po/sr_RS.po b/po/sr_RS.po
index b57770a1f39a..a8006e117659 100644
--- a/po/sr_RS.po
+++ b/po/sr_RS.po
@@ -3,14 +3,14 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# MirosNik <miroslavnikolic at rocketmail.com>, 2011-2012
+# Мирослав Николић <miroslavnikolic at rocketmail.com>, 2011-2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Serbian (Serbia) (http://www.transifex.com/projects/p/"
 "audacious/language/sr_RS/)\n"
 "Language: sr_RS\n"
@@ -20,40 +20,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "моно"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стерео"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "окружење"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "Ад прикључак (АдБибл програм)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "низовни"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "Ад прикључак (АдБибл програм)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Аларм"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +51,7 @@ msgstr ""
 "\n"
 "Првобитни аутори су Адам Фикин и Данијел Стоден."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Аларм"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -90,7 +74,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -112,7 +96,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -126,365 +110,371 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Ово је ваш позив за буђење."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Подсетник"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Понедељак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Уторак"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Среда"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Четвртак"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Петак"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Субота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Недеља"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Подешавања аларма"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Време"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Активирај аларм у (основно):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "часова"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Утишај након:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "сат(а)"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "минута"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Изаберите којим данима ће се активирати аларм"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Дан"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Основно"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дани"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Ишчезавање"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "секунде"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Јачина"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Започни при"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Заврши при"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Тренутно"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Додатна наредба"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "укључи"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Списак нумера (необавезно)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Изаберите списак нумера"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опције"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Шта значе ове опције?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Помоћ"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Омот албума"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "Излаз АЛСА-е"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Прикључак излаза АЛСА-е за Безочника\n"
+"Ауторска права 2009-2012 Џон Линдгрин\n"
+"\n"
+"Захваљујем се Вилијаму Питкоку, аутору НГ прикључка излаза АЛСА-е, чији је "
+"код служио као узор када упутство АЛСА-е није било довољно."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Основни ПЦМ уређај"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Основни уређај мешача"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "ПЦМ уређај:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Уређај миксера:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Елемент мешача:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Решите суви прекид"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "АМИДИ-Прикључак (МИДИ програм)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"Прикључак излаза АЛСА-е за Безочника\n"
-"Ауторска права 2009-2012 Џон Линдгрин\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Захваљујем се Вилијаму Питкоку, аутору НГ прикључка излаза АЛСА-е, чији је "
-"код служио као узор када упутство АЛСА-е није било довољно."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "Излаз АЛСА-е"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "АМИДИ-Прикључак (МИДИ програм)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "АМИДИ прикључак — изаберите СаундФонт датотеку"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Назив датотеке"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Величина (бајтова)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Назив:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> МИДИ Информације </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Формат:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Трајање (msec):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Број нумера:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "променљиво"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "БПМ:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "БПМ (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Див време:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> МИДИ коментари и текстови песама </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* нема доступних коментара у овој МИДИ датотеци *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* нема доступних текстова песама у овој МИДИ датотеци *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Затвори"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (неисправан УТФ-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "О АМИДИ прикључку"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -495,152 +485,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "БОСД (Приказ на екрану)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Правоугаоник"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Заобљени правоугаоник"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Удубљен правоугаоник"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Ништа"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Почетак репродукције"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Приказује ОСД када почиње репродукција песме."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Промена наслова"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Приказује ОСД када се, у току репродукције, измени наслов песме али назив "
-"датотеке остане исти. Ово је углавном корисно за приказивање измена у "
-"насловима у интернет токовима."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Паузирање"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Приказује ОСД када је репродукција привремено заустављена."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Отпаузирање"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Приказује ОСД када је репродукција поново покренута."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Постављање"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Релативан хоризонтални померај:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Релативан вертикални померај:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Највећа ширина приказа:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Опција више монитора"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Прикажи ОСД на:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "свим мониторима"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "на монитору бр. %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Време трајања (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Приказ:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Појављивање:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Ишчезавање:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Словни ликови"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Писмо %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Сенка"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Стил исцртавања"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Боје"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Боја %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Омогући активирање"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Догађај"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Откривен је композитни управник"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -650,112 +634,112 @@ msgstr ""
 "осим ако знате да је један већ покренут, молим покрените композитног "
 "управника јер у супротном ОСД неће радити исправно"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Композитни управник није потребан за лажну провидност"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Провидност"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Лажна провидност"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Стварна провидност (захтева Х композитно проширење)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Композитно проширење није учитано"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Композитно проширење није доступно"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Безочник — ОСД</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Безочник ОСД — подешавања"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Положај"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анимација"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Декорација"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Укључивање"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Остало"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "АСИксв1/АСИксв2 спискови нумера"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Безочникови спискови нумера (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Боје</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Обим замућења"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Бојер стереофонски-у-бинаурални (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Претподешавања:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Ниво довода:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Учестаност исецања:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Претподешавања:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Бојер стереофонски-у-бинаурални (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Анализатор спектра"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Прикључак звучног ЦД-а"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -775,171 +759,156 @@ msgstr ""
 "\n"
 "Беше то Гугл лето пројекта Кôд 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Уређај</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Брзина читања:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Препиши уређај:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метаподаци</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Користи ЦД-текст"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Користи ЦДБП"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Користи ХТТП уместо ЦДДБП-а"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Путања:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Прикључник:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Прикључак звучног ЦД-а"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Нисам успео да започнем цдуи подсистем."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Неисправна путања „%s“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Нисам пронашао нумеру „%d“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Нисам успео да отворим излаз звука."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Аудио ЦД"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Нисам успео да отворим ЦД уређај „%s“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Нисам пронашао уређај за читање ЦД-а."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Нисам успео да завршим покретање отвореног ЦД уређаја."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Нисам успео да пронађем број прве/последње нумере."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Не могу да прочитам почетак/крај ЛСН-а за нумеру „%d“."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Нисам успео да направим везу са цд базом података."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Нисам успео да пропитам сервер базе података ЦД-а"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Нисам успео да пропитам сервер базе података ЦД-а: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Нисам успео да прочитам обавештење базе података цд-а: %s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Уређај је празан."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Неподржана врста диска."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Ставке изборника звучног ЦД-а"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Пусти ЦД"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Додај ЦД"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Ставке изборника звучног ЦД-а"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Сажимање</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Главна јачина:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамички опсег:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Прикључак сажимања динамичког опсега за Безочника\n"
-"Ауторска права 2010-2012 Џон Линдгрин"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Сажиматељ динамичког опсега"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -954,206 +923,225 @@ msgstr ""
 "Вилијам Питкок <nenolod at dereferenced.org>, \n"
 "Шај Грин <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Ниски тонови:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Високи тонови:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Основно трајање песме:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Укључи поновно узорковање"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Проток поновног узорковања:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Занемари трајање из СПЦ ознака"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Повећај одјек"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Конзолни музички декодер игре"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"Постепени прелаз није успео јер је песма имала различит број канала. Можете "
-"да користите Мешача канала да претворите песме на исти број канала."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"Постепени прелаз није успео јер је песма имала различит проток узорка.  "
-"Можете да користите Претварача протока узорка да претворите песме на исти "
-"проток узорка."
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Прикључак постепеног прелаза за Безочника\n"
-"Ауторска права 2010-2012 Џон Линдгрин"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Постепени прелаз</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Преклапање:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Постепени прелаз"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Постепени прелаз није успео јер је песма имала различит број канала. Можете "
+"да користите Мешача канала да претворите песме на исти број канала."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Постепени прелаз није успео јер је песма имала различит проток узорка.  "
+"Можете да користите Претварача протока узорка да претворите песме на исти "
+"проток узорка."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристализатор</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Јакост:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристализатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Прикључак „cue“ табеле"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Обриши"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Откажи"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Одјек</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Застој:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Одзив:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Јачина звука:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Прикључак одјека\n"
-"Аутор Јохан Левин 1999\n"
-"\n"
-"Окружење одјека је написао Карл ван Шаик, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Одјек"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Прикључак ФФмпег-а"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1169,55 +1157,55 @@ msgstr ""
 "Вилијам Питкок <nenolod at nenolod.net>\n"
 "Мати Хамалајнен <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Прикључак ФФмпег-а"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Прикључак записивања датотека"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Формат излазне датотеке:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Подеси"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Сачувај у оригиналном директоријуму"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Сачувај у произвољном директоријуму"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Фасцикла излазне датотеке:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Изаберите фасциклу"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Набави име датотеке из:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "ознаке оригиналне датотеке"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "назива оригиналне датотеке"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Не одузимај проширење назива датотеке"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Придодај број нумере називу датотеке"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1249,165 +1237,169 @@ msgstr ""
 "„Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA“."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Прикључак записивања датотека"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Самостално"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Удружени стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "МП3 подешавања"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Квалитет алгоритма:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Проток узорка излаза:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Проток бита / Однос сажимања:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Проток бита (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Однос сажимања:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Режим звука:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Разно:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "Присили строго ИСО поштовање"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Грешка заштите"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Квалитет"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Укључи ВБР/АБР"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Врста:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "ВБР опције:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Најмањи проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Највећи проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Строго спроведи најмањи проток бита"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "АБР опције:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Просечни проток бита (kb/s):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Ниво ВБР квалитета:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Не записуј Хинг ВБР заглавље"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "ВБР/АБР"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Параметри кадра:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Означи као ауторско право"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Означи као оригинал"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ИД3 параметри:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Присили додавање ознаке издања 2"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Додај само в1 ознаку"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Додај само в2 ознаку"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Ознаке"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Подешавање Ворбис шифрера"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Ниво квалитета (0 — 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "ФЛАЦ декодер"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "без губитака"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1419,11 +1411,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "ФЛАЦ декодер"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1431,11 +1419,19 @@ msgstr ""
 "ГУИ прикључак за Безочника\n"
 "Ауторска права 2009-2012 Џон Линдгрин"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "ГУИ прикључак"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1447,450 +1443,509 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
-msgstr ""
-"Прикључак Гномове пречице\n"
-"Омогућава вам да управљате програмом користећи Гномове пречице.\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
 "\n"
-"Ауторска права (C) 2007-2008 Саша Хласјак <contact at saschahlusiak.de>"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Гномове пречице"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Број ставке"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Наслов"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Извођач"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Година"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Албум"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Нумера"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Положај колоне"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Трајање"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Путања датотеке"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Назив датотеке"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Произвољан наслов"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Битски проток"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Алат за претрагу"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Усидри на лево"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Усидри на десно"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Усидри на врх"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Усидри на дно"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Откачи"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Искључи"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Алат за претрагу"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Отвори _датотеке ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Отвори _адресу ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "Додај да_тотеке ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Додај ад_ресу ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "О _програму ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Изађи"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "Пу_сти"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "Па_узирај"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Заустави"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Претходно"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "С_ледеће"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Понови"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Насумично"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Н_е напредуј у списку нумера"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "Подаци о _песми ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Пређи на _време ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Пређи на _песму ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "Према _наслову"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "Према броју _нумере"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "Према _извођачу"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "Према _датуму издавања"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "Према _путањи датотеке"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Према п_роизвољном наслову"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "Преокрени п_оредак"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Случајан поредак"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "_Пусти овај списак нумера"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Освежи"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "Пор_еђај"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Уклони _недоступне датотеке"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Ново"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "_Преименуј ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "Ув_ези ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "Из_вези ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Управник списка _нумера ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Управник _редоследа ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "По_јачај"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "У_тишај"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "Ује_дначавач"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Прикажи траку _изборника"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Прикажи траку _података"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "Прикажи _визуелизацију траке обавштења"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Прикажи траку _стања"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Датотека"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Извођење"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Списак нумера"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_Услуге"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_Излаз"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Преглед"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Стави у ред/Избаци из реда"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Исеци"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "У_множи"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "У_баци"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_Изабери све"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "_Преименуј ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "ГТК сучеље"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s — Безочник"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Баферујем ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Безочник"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "моно"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стерео"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1898,84 +1953,98 @@ msgstr[0] "%d канал"
 msgstr[1] "%d канала"
 msgstr[2] "%d један канал"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kb/s"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Једноставни режим."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Режим списка нумера."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Зауставља након песме."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Пусти"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Паузирај/настави"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Заустави"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr ""
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Искључи звук"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr ""
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr ""
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr ""
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Прикажи приказ на екрану"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ништа)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1986,15 +2055,11 @@ msgstr ""
 "\n"
 "Да ли желите да наставите?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Повезујем дугмад миша"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Подешавања прикључка општих пречица"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2002,23 +2067,27 @@ msgstr ""
 "Притисните комбинацију тастера унутар поља за текст.\n"
 "Можете такође да повежете дугмад миша."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Пречице:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Радња:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Свезе тастера:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Опште пречице"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2045,60 +2114,51 @@ msgstr ""
 " Џонатан А. Давис <davis at jdhouse.org>\n"
 " Џереми Тан <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Опште пречице"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "ЏЕК излаз"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Засновано на иксммс-џеку, који је приредио Крис Морган:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ђакомо Лоцито је припремио за Безочника"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "ЏЕК излаз"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Подешавања за %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Подешавања ЛАДСПА домаћину"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Путање модула:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2109,25 +2169,25 @@ msgstr ""
 "Након додавања нових путања, притисните Унеси да потражите нове прикључке.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Доступни прикључци:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Укључи"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Укључени прикључци:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Подешавања"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2135,47 +2195,15 @@ msgstr ""
 "ЛАДСПА домаћин за Безочника\n"
 "Ауторска права 2011 Џон Линдгрин"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "ЛАДСПА домаћин"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: не могу да започнем ЛИРЦ подршку\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: не могу да прочитам датотеку ЛИРЦ подешавања\n"
-"%s: молим прочитајте ЛИРЦ документацију\n"
-"%s: како да направите личну датотеку подешавања\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: покушавам да се поново повежем...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: непозната наредба „%s“\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: прекинута је веза са ЛИРЦ-а\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: покушаћу да се поново повежем сваке %d секунде...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "ЛИРЦ прикључак"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2204,73 +2232,81 @@ msgstr ""
 "\n"
 "Да сазнате више о ЛИРЦ-у, погледајте „http://lirc.org“."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>Веза</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Поново се повежи са ЛИРЦ сервером"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Сачекај пре поновног повезивања:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "ЛИРЦ прикључак"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Прикључак за Лирик вики"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Нема доступних текстова"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Грешка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Не могу да довучем „%s“"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Грешка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Не могу да обрадим „%s“"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Тражим текст песме ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Недостају метаподаци песме"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "Повезујем се на „lyrics.wikia.com“ ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Прикључак за Лирик вики"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "М3У списак нумера"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Генератор такта"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Генератор такта: %d отк/мин"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Генератор такта: %d отк/мин %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2284,11 +2320,11 @@ msgstr ""
 "нпр.: „tact://77“ да добијете 77 откуцаја у минуту\n"
 "или: „tact://60*3/4“ да добијете 60 отк./мин у 3/4 такту"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Генератор такта"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Мешач канала"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2296,152 +2332,184 @@ msgstr ""
 "Прикључак мешача канала за Безочника\n"
 "Ауторска права 2011-2012 Џон Линдгрин и Михал Липски"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Мешач канала</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Излазни канали:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Мешач канала"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "ММС прикључак"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "Мод прикључак (Програм за модле)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "Мод прикључак (Програм за модле)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Окружење"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "МПГ123 прикључак"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Окружење"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "МПРИС 2 сервер"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Неон ХТТП/ХХТПС прикључак"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Заустављено"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Безочник не пушта песме."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Обавештења радне површи"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2461,55 +2529,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Обавештења радне површи"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr ""
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Паузирај"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Следећа"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Основни уређај"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "ОСС4 излаз"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Звучни уређај:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Користи алтернативни уређај:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Сачувајте јачину звука између сесија."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Укључује претварање формата направљено ОСС софтвером."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Укључује искључиви режим да спречи виртуално мешање."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2523,19 +2600,35 @@ msgstr ""
 "Желим да се захвалим људима на „#audacious“, нарочито Тони Вруну и Џону "
 "Линдгрину и наравно ауторима претходног ОСС прикључка."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "ОСС4 излаз"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "ПЛС спискови нумера"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "ОпенПСФ ПСФ1/ПСФ2 декодер"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "Пулс‑аудио излаз"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2572,11 +2665,68 @@ msgstr ""
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "Пулс‑аудио излаз"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Претходна"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Понови"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Насумично"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Претварач протока узорка"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2584,133 +2734,145 @@ msgstr ""
 "Прикључак Претварача протока узорка за Безочника\n"
 "Ауторска права 2010-2012 Џон Линдгрин"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Прескочи/понови узорке"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Линијско уметање"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Брзо уметање усклађења"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Средње уметање усклађења"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Најбоље уметање усклађења"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Претварање</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метод:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Проток:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Мапирање протока</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Користи мапирање протока"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Претварач протока узорка"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2721,17 +2883,17 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "СДЛ излаз"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2739,76 +2901,59 @@ msgstr ""
 "Прикључак СДЛ излаза за Безочника\n"
 "Ауторска права 2010 Џон Линдгрин"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "СДЛ излаз"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Библиотека"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Непознат извођач"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Непознат албум"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" „%s“ изводи %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Направи списак нумера"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Додај у списак нумера"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Претражите библиотеку"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2816,679 +2961,769 @@ msgstr ""
 "Да увезете вашу музичку библиотеку у Безочнику, изаберите фасциклу и затим "
 "кликните на иконицу „освежи“."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Молим сачекајте ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Изаберите фасциклу"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Репродукција"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Списак нумера"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Поглед"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Понови"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Насумично"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Не напредуј у списку нумера"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Претходна"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Нови списак нумера"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Прикажи уређивач списка нумера"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Прикажи уједначавач"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Увек у првом плану"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "Према наслову"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "Према називу датотеке"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Уклони све"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Обриши заказано"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Уклони недоступне датотеке"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Уклони дупликате"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Уклони неозначене"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Уклони означене"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Претражи и означи"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Обрни избор"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Означи ништа"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Означи све"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "Према албуму"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "Према броју нумере"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "Према извођачу"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "Према албуму"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "Према броју нумере"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Насумице испремештај списак"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Преокрени списак"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Поређај означене"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Поређај списак"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Исеци"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Умножи"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Убаци"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Винампово уобичајено сучеље"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Сачувај"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Учитај"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Претподешавања"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Учитава претподешавање"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Учитава самостално претподешавање"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Чува претподешавање"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Чува самостално претподешавање"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Избриши претподешавање"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Брише самостално претподешавање"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Плејер:"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Изаберите словни лик главног прозора плејера:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Списак нумера:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Изабери словни лик списка нумера:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Користи битмап словне ликове (подржава само АСКРИ)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Померај наслов песме у оба смера"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Анализатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Досег"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Искључено"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Нормалан"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Ватра"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Линије"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Траке"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Најспорије"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Споро"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Средње"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Брзо"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Најбрже"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лед"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Глатко"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Опште"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Приказивање"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Претпојачање"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Уједначавач Безочника"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Тражи до: %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Јачина звука: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Уравнотеженост: %d%% леви"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Уравнотеженост: центрирано"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Уравнотеженост: %d%% десни"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Изборник опција"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Искључи „Увек у првом плану“"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Укључи „Увек у првом плану“"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Поље информација о датотеци"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Једноставни режим."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Режим списка нумера."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Зауставља након песме."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Претражи ставке у активном списку нумера"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3500,57 +3735,61 @@ msgstr ""
 "како обични изрази функционишу, једноставно дословно унесите део онога што "
 "тражите."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Наслов: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Албум: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Извођач: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Назив датотеке: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Обриши претходни избор пре претраге"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Подударајуће ставке самостално пребаци у ред"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Направи нови списак нумера са подударајућим ставкама"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Уређивач списка нумера"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d од %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Архивирана Винамп 2.x маска"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Неархивирана Винамп 2.x маска"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Не могу да направим фасциклу (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Прикључак звучне датотеке"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3591,83 +3830,71 @@ msgstr ""
 "софтва на адресу: Free Software Foundation, Inc.,\n"
 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Прикључак звучне датотеке"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "О прикључку звучногуи излаза"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
-"Прикључак звучногуи излаза\n"
-"\n"
-"Написао га је Томас Пфаф <tpfaff at tp76.info>\n"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Неподржани облик датотеке"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Звучни уређај је затражио неподржани облик датотеке.\n"
-"\n"
-"Молим покушајте опет са покренутим „sndiod(1)“ сервером."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "звучниуи уређај"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(празно значи задато)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "У реду"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Промена песме"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Наредба за покретање када Безочник започиње нову песму."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Параметри прослеђени љусци би требало да буду у "
+"наводницима. Све другачије је безбедносни ризик.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Наредба:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Наредба за покретање при крају песме."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Наредба за покретање када Безочник стигне на крај списка нумера."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Наредба за покретање када се промени наслов песме (тј. наслови мрежних "
-"токова)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3681,35 +3908,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Можете да користите следеће ниске формата које\n"
-"ће бити замењене пре позивања наредбе\n"
-"(нису све корисне за наредбу крај-списка-нумера):\n"
-"\n"
-"%F:         Учесталост (у херцима)\n"
-"%c:         Број канала\n"
-"%f:         Назив датотеке (пуна путања)\n"
-"%l:         Трајање (у милисекундама)\n"
-"%n или %s:  Назив песме\n"
-"%r:         Проток (у битима у секунди)\n"
-"%t:         Позиција списка нумера (%%02d)\n"
-"%p:         Тренутно пуштена (1 или 0)\n"
-"%a:         Уметник\n"
-"%b:         Албум\n"
-"%T:         Наслов нумере"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Параметри прослеђени љусци би требало да буду у "
-"наводницима. Све другачије је безбедносни ризик.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Наредбе"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3718,51 +3926,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr ""
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Брзина и врхунац"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Брзина и врхунац</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Брзина:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Врхунац:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Брзина и врхунац"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Иконица стања"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3780,39 +3988,39 @@ msgstr ""
 "Овај додатак обезбеђује иконицу стања, смештену\n"
 "у области фиоке система управника прозора."
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Радња клизања мишем</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Промени јачину звука"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Промени песму"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Остала подешавања</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Искључи прозор облачића"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Затвори у системску касету"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Напредује у списку нумера када клиза унапред"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Иконица стања"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Додатни стерео"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3822,24 +4030,24 @@ msgstr ""
 "\n"
 "Написао га је Џон Левин, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Додатни стерео</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Додатни стерео"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Тонски генератор"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Тонски генератор: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3854,15 +4062,11 @@ msgstr ""
 "учесталост3;...\n"
 "нпр.: tone://2000;2005 да пустите тонове 2000 Hz и 2005 Hz"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Тонски генератор"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Уклањање гласа"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3900,11 +4104,35 @@ msgstr ""
 "Ђанкарло Паскуто <gcp at sjeng.org>\n"
 "Јуџон Загидулин <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Огг Ворбис декодер"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "ВТКС декодер"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -3916,19 +4144,19 @@ msgstr ""
 "ru>\n"
 "Прикључак за Безочника је написао Павел Виметалек <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "ВТКС декодер"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Вејвпак декодер"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "ослабљено (хибридно)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "ослабљено"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -3938,14 +4166,18 @@ msgstr ""
 "\n"
 "Нешто кода прикључка је написао Мајлс Иган."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Вејвпак декодер"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2СФ декодер"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "ИксМЛ дељиви спискови пуштања (XSPF)"
diff --git a/po/sv.po b/po/sv.po
new file mode 100644
index 000000000000..24703d7ffb52
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,4012 @@
+# Swedish translation for Audacious Plugins
+# Copyright (C) Audacious translators
+# This file is distributed under the same license as the Audacious Plugins package.
+#
+# Translators:
+# Bo Serrander <bserrander at gmail.com>, 2013
+# Martin Jernberg <bittin at cafe8bitar.se>, 2014
+msgid ""
+msgstr ""
+"Project-Id-Version: Audacious Plugins\n"
+"Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
+"Language-Team: Swedish (http://www.transifex.com/projects/p/audacious/"
+"language/sv/)\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/aac-raw/aac.cc:18
+msgid "AAC (Raw) Decoder"
+msgstr "AAC (Raw) Dekoder"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Spelare)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
+msgid "sequenced"
+msgstr ""
+
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
+
+#: src/alarm/alarm.cc:782
+msgid "Set Alarm ..."
+msgstr "Ställ in Alarm ..."
+
+#: src/alarm/alarm.cc:810
+msgid ""
+"A plugin that can be used to start playing at a certain time.\n"
+"\n"
+"Originally written by Adam Feakin and Daniel Stodden."
+msgstr ""
+
+#: src/alarm/interface.cc:28
+msgid ""
+"Time\n"
+"  Alarm at:\n"
+"    The time for the alarm to come on.\n"
+"\n"
+"  Quiet after:\n"
+"    Stop alarm after this amount of time.\n"
+"       (if the wakeup dialog is not closed)\n"
+"\n"
+"\n"
+"Days\n"
+"  Day:\n"
+"    Select the days for the alarm to activate.\n"
+"\n"
+"  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"
+msgstr ""
+
+#: src/alarm/interface.cc:45
+msgid ""
+"Volume\n"
+"  Fading:\n"
+"    Fade the volume up to the chosen volume\n"
+"    for this amount of time.\n"
+"\n"
+"  Start at:\n"
+"    Start fading from this volume.\n"
+"\n"
+"  Final:\n"
+"    The volume to stop fading at.  If the fading\n"
+"    time is 0 then set volume to this and start\n"
+"    playing.\n"
+"\n"
+"\n"
+"Options:\n"
+"  Additional Command:\n"
+"    Run this command at the alarm time.\n"
+"\n"
+msgstr ""
+
+#: src/alarm/interface.cc:62
+msgid ""
+"  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"
+"    can also be entered here.\n"
+"\n"
+"  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."
+msgstr ""
+
+#: src/alarm/interface.cc:81
+msgid "This is your wakeup call."
+msgstr "Detta är din väckarklocka."
+
+#: src/alarm/interface.cc:99
+msgid "Your reminder for today is..."
+msgstr "Din påminelse idag är ..."
+
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
+msgid "Reminder"
+msgstr "PÃ¥minelse"
+
+#: src/alarm/interface.cc:132
+msgid "Monday"
+msgstr "MÃ¥ndag"
+
+#: src/alarm/interface.cc:132
+msgid "Tuesday"
+msgstr "Tisdag"
+
+#: src/alarm/interface.cc:132
+msgid "Wednesday"
+msgstr "Onsdag"
+
+#: src/alarm/interface.cc:133
+msgid "Thursday"
+msgstr "Torsdag"
+
+#: src/alarm/interface.cc:133
+msgid "Friday"
+msgstr "Fredag"
+
+#: src/alarm/interface.cc:133
+msgid "Saturday"
+msgstr "Lördag"
+
+#: src/alarm/interface.cc:133
+msgid "Sunday"
+msgstr "Söndag"
+
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
+msgid "Time"
+msgstr "Tid"
+
+#: src/alarm/interface.cc:178
+msgid "Alarm at (default):"
+msgstr "Larm på (standard):"
+
+#: src/alarm/interface.cc:200
+msgid "h"
+msgstr "h"
+
+#: src/alarm/interface.cc:203
+msgid "Quiet after:"
+msgstr "Tyst efter:"
+
+#: src/alarm/interface.cc:215
+msgid "hours"
+msgstr "timmar"
+
+#: src/alarm/interface.cc:226
+msgid "minutes"
+msgstr "minuter"
+
+#: src/alarm/interface.cc:235
+msgid "Choose the days for the alarm to come on"
+msgstr ""
+
+#: src/alarm/interface.cc:242
+msgid "Day"
+msgstr "Dag"
+
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
+msgid "Default"
+msgstr "Standard"
+
+#: src/alarm/interface.cc:288
+msgid "Days"
+msgstr "Dagar"
+
+#: src/alarm/interface.cc:297
+msgid "Fading"
+msgstr ""
+
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
+msgid "seconds"
+msgstr "sekunder"
+
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
+msgid "Volume"
+msgstr "Volym"
+
+#: src/alarm/interface.cc:317
+msgid "Start at"
+msgstr "Börja på"
+
+#: src/alarm/interface.cc:333
+msgid "Final"
+msgstr ""
+
+#: src/alarm/interface.cc:346
+msgid "Current"
+msgstr "Nuvarande"
+
+#: src/alarm/interface.cc:359
+msgid "Additional Command"
+msgstr "Ytterligare Kommando"
+
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
+msgid "enable"
+msgstr ""
+
+#: src/alarm/interface.cc:372
+msgid "Playlist (optional)"
+msgstr "Spellista (valfritt)"
+
+#: src/alarm/interface.cc:379
+msgid "Select a playlist"
+msgstr "Välj en spellista"
+
+#: src/alarm/interface.cc:399
+msgid "Options"
+msgstr "Inställningar"
+
+#: src/alarm/interface.cc:404
+msgid "What do these options mean?"
+msgstr "Vad betyder dessa inställningar?"
+
+#: src/alarm/interface.cc:420
+msgid "Help"
+msgstr "Hjälp"
+
+#: src/albumart/albumart.cc:31
+msgid "Album Art"
+msgstr "Skivomslag"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA Utgång"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
+msgid "Default PCM device"
+msgstr ""
+
+#: src/alsa/config.cc:188
+msgid "Default mixer device"
+msgstr ""
+
+#: src/alsa/config.cc:296
+msgid "PCM device:"
+msgstr ""
+
+#: src/alsa/config.cc:299
+msgid "Mixer device:"
+msgstr ""
+
+#: src/alsa/config.cc:302
+msgid "Mixer element:"
+msgstr ""
+
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI Spelare)"
+
+#: src/amidi-plug/amidi-plug.cc:437
+msgid ""
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
+"\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:94
+msgid "Override default gain:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:102
+msgid "Override default polyphony:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:110
+msgid "Override default reverb:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
+msgid "On"
+msgstr "PÃ¥"
+
+#: src/amidi-plug/i_configure.cc:118
+msgid "Override default chorus:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
+msgid "<b>Playback</b>"
+msgstr "<b> Uppspelning </ b>"
+
+#: src/amidi-plug/i_configure.cc:129
+msgid "Transpose:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
+msgid "Drum shift:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:141
+msgid "<b>SoundFont</b>"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:143
+msgid "<b>Synthesizer</b>"
+msgstr "<b>Synthesizer</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
+msgid "AMIDI-Plug - select SoundFont file"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Avbryt"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
+msgid "_Open"
+msgstr "_Öppna"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Filnamn"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
+msgid "Size (bytes)"
+msgstr "Storlek (bytes)"
+
+#: src/amidi-plug/i_fileinfo.cc:163
+msgid "Name:"
+msgstr "Namn:"
+
+#: src/amidi-plug/i_fileinfo.cc:181
+msgid "<span size=\"smaller\"> MIDI Info </span>"
+msgstr "<span size=\"smaller\"> MIDI Info </span>"
+
+#: src/amidi-plug/i_fileinfo.cc:195
+msgid "Format:"
+msgstr "Format:"
+
+#: src/amidi-plug/i_fileinfo.cc:198
+msgid "Length (msec):"
+msgstr "Längd (msec):"
+
+#: src/amidi-plug/i_fileinfo.cc:201
+msgid "No. of Tracks:"
+msgstr "Nummer av Spår:"
+
+#: src/amidi-plug/i_fileinfo.cc:207
+msgid "variable"
+msgstr "variabel"
+
+#: src/amidi-plug/i_fileinfo.cc:209
+msgid "BPM:"
+msgstr "BPM:"
+
+#: src/amidi-plug/i_fileinfo.cc:217
+msgid "BPM (wavg):"
+msgstr "BPM (wavg):"
+
+#: src/amidi-plug/i_fileinfo.cc:220
+msgid "Time Div:"
+msgstr ""
+
+#: src/amidi-plug/i_fileinfo.cc:231
+msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
+msgstr ""
+
+#: src/amidi-plug/i_fileinfo.cc:278
+msgid "* no comments available in this MIDI file *"
+msgstr "* Inga kommentarer finns i denna MIDI-fil *"
+
+#: src/amidi-plug/i_fileinfo.cc:290
+msgid "* no lyrics available in this MIDI file *"
+msgstr "* Inga texter finns i denna MIDI-fil *"
+
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
+msgid "_Close"
+msgstr "_Stäng"
+
+#: src/amidi-plug/i_fileinfo.cc:325
+msgid "  (invalid UTF-8)"
+msgstr "(ogiltig UTF-8)"
+
+#: src/aosd/aosd.cc:32
+msgid ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Written by Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Based in part on Evan Martin's Ghosd library:\n"
+"http://neugierig.org/software/ghosd/"
+msgstr ""
+
+#: src/aosd/aosd.h:37
+msgid "AOSD (On-Screen Display)"
+msgstr ""
+
+#: src/aosd/aosd_style.cc:54
+msgid "Rectangle"
+msgstr "Rektangel"
+
+#: src/aosd/aosd_style.cc:59
+msgid "Rounded Rectangle"
+msgstr "Rundad Rektangel"
+
+#: src/aosd/aosd_style.cc:64
+msgid "Concave Rectangle"
+msgstr "Konkav Rektangel"
+
+#: src/aosd/aosd_style.cc:69
+msgid "None"
+msgstr "Ingen"
+
+#: src/aosd/aosd_trigger.cc:50
+msgid "Playback Start"
+msgstr "Starta Uppspelning"
+
+#: src/aosd/aosd_trigger.cc:51
+msgid "Triggers OSD when a playlist entry is played."
+msgstr ""
+
+#: src/aosd/aosd_trigger.cc:56
+msgid "Title Change"
+msgstr ""
+
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr ""
+
+#: src/aosd/aosd_trigger.cc:62
+msgid "Pause On"
+msgstr "Pause på"
+
+#: src/aosd/aosd_trigger.cc:63
+msgid "Triggers OSD when playback is paused."
+msgstr ""
+
+#: src/aosd/aosd_trigger.cc:68
+msgid "Pause Off"
+msgstr "Pause Av"
+
+#: src/aosd/aosd_trigger.cc:69
+msgid "Triggers OSD when playback is unpaused."
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:163
+msgid "Placement"
+msgstr "Placering"
+
+#: src/aosd/aosd_ui.cc:196
+msgid "Relative X offset:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:203
+msgid "Relative Y offset:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:210
+msgid "Max OSD width:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:221
+msgid "Multi-Monitor options"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:225
+msgid "Display OSD using:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:227
+msgid "all monitors"
+msgstr "alla skärmar"
+
+#: src/aosd/aosd_ui.cc:230
+#, c-format
+msgid "monitor %i"
+msgstr "skärm %i"
+
+#: src/aosd/aosd_ui.cc:282
+msgid "Timing (ms)"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:287
+msgid "Display:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:292
+msgid "Fade in:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:297
+msgid "Fade out:"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:361
+msgid "Fonts"
+msgstr "Teckensnitt"
+
+#: src/aosd/aosd_ui.cc:368
+#, c-format
+msgid "Font %i:"
+msgstr "Teckensnitt %i:"
+
+#: src/aosd/aosd_ui.cc:382
+msgid "Shadow"
+msgstr "Skugga"
+
+#: src/aosd/aosd_ui.cc:486
+msgid "Render Style"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:502
+msgid "Colors"
+msgstr "Färger"
+
+#: src/aosd/aosd_ui.cc:513
+#, c-format
+msgid "Color %i:"
+msgstr "Färg %i:"
+
+#: src/aosd/aosd_ui.cc:600
+msgid "Enable trigger"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:627
+msgid "Event"
+msgstr "Event"
+
+#: src/aosd/aosd_ui.cc:655
+msgid "Composite manager detected"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:662
+msgid ""
+"Composite manager not detected;\n"
+"unless you know that you have one running, please activate a composite "
+"manager otherwise the OSD won't work properly"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:670
+msgid "Composite manager not required for fake transparency"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:706
+msgid "Transparency"
+msgstr "Genomskinlighet"
+
+#: src/aosd/aosd_ui.cc:712
+msgid "Fake transparency"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:714
+msgid "Real transparency (requires X Composite Ext.)"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:756
+msgid "Composite extension not loaded"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:764
+msgid "Composite extension not available"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:781
+#, c-format
+msgid "<span font_desc='%s'>Audacious OSD</span>"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:844
+msgid "Position"
+msgstr ""
+
+#: src/aosd/aosd_ui.cc:849
+msgid "Animation"
+msgstr "Animation"
+
+#: src/aosd/aosd_ui.cc:854
+msgid "Text"
+msgstr "Text"
+
+#: src/aosd/aosd_ui.cc:859
+msgid "Decoration"
+msgstr "Dekoration"
+
+#: src/aosd/aosd_ui.cc:864
+msgid "Trigger"
+msgstr "Trigger"
+
+#: src/aosd/aosd_ui.cc:869
+msgid "Misc"
+msgstr "Misc"
+
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
+msgid "ASXv3 Playlists"
+msgstr "ASXv3 Spellistor"
+
+#: src/asx/asx.cc:33
+msgid "ASXv1/ASXv2 Playlists"
+msgstr "ASXv1/ASXv2 Spellistor"
+
+#: src/audpl/audpl.cc:33
+msgid "Audacious Playlists (audpl)"
+msgstr "Audacious Spellistor (audpl)"
+
+#: src/blur_scope/blur_scope.cc:42
+msgid "<b>Color</b>"
+msgstr "<b>Färg</b>"
+
+#: src/blur_scope/blur_scope.cc:58
+msgid "Blur Scope"
+msgstr ""
+
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr ""
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr ""
+
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
+msgstr ""
+
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
+msgid "Spectrum Analyzer"
+msgstr "Spektrumanalysator"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Ljud CD Plugin"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
+msgid ""
+"Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
+"\n"
+"Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/>\n"
+"and to libcddb developers <http://libcddb.sourceforge.net/>.\n"
+"\n"
+"Also thank you to Tony Vroon for mentoring and guiding me.\n"
+"\n"
+"This was a Google Summer of Code 2007 project."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:137
+msgid "<b>Device</b>"
+msgstr "<b>Enhet</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:138
+msgid "Read speed:"
+msgstr "Läshastighet:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:141
+msgid "Override device:"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:143
+msgid "<b>Metadata</b>"
+msgstr "<b>Metadata</b>"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:144
+msgid "Use CD-Text"
+msgstr "Använd CD-Text"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:146
+msgid "Use CDDB"
+msgstr "Använd CDDB"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:148
+msgid "Use HTTP instead of CDDBP"
+msgstr "Använd HTTP istället för CDDBP"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:151
+msgid "Server:"
+msgstr "Server:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:155
+msgid "Path:"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:159
+msgid "Port:"
+msgstr "Port:"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:246
+msgid "Failed to initialize cdio subsystem."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:281
+#, c-format
+msgid "Invalid URI %s."
+msgstr "Ogiltig URI %s"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:283
+#, c-format
+msgid "Track %d not found."
+msgstr "Spår %d kunde inte hittas."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:285
+#, c-format
+msgid "Track %d is a data track."
+msgstr "Spår %d är ett dataspår."
+
+#: src/cdaudio-ng/cdaudio-ng.cc:360
+msgid "Error reading audio CD."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:429
+msgid "Audio CD"
+msgstr "Ljud CD"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
+#, c-format
+msgid "Failed to open CD device %s."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:472
+msgid "No audio capable CD drive found."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:497
+msgid "Failed to finish initializing opened CD drive."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:510
+msgid "Failed to retrieve first/last track number."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:531
+#, c-format
+msgid "Cannot read start/end LSN for track %d."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:613
+msgid "Failed to create the cddb connection."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:679
+msgid "Failed to query the CDDB server"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:681
+#, c-format
+msgid "Failed to query the CDDB server: %s"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:705
+#, c-format
+msgid "Failed to read the cddb info: %s"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:765
+msgid "Drive is empty."
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:767
+msgid "Unsupported disk type."
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Play CD"
+msgstr "Spela CD"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
+msgid "Add CD"
+msgstr ""
+
+#: src/compressor/compressor.cc:45
+msgid "<b>Compression</b>"
+msgstr ""
+
+#: src/compressor/compressor.cc:46
+msgid "Center volume:"
+msgstr ""
+
+#: src/compressor/compressor.cc:49
+msgid "Dynamic range:"
+msgstr ""
+
+#: src/compressor/compressor.cc:57
+msgid ""
+"Dynamic Range Compression Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+
+#: src/compressor/compressor.cc:64
+msgid "Dynamic Range Compressor"
+msgstr ""
+
+#: src/console/plugin.cc:15
+msgid ""
+"Console music decoder engine based on Game_Music_Emu 0.5.2\n"
+"Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at dereferenced.org>\n"
+"Shay Green <gblargg at gmail.com>"
+msgstr ""
+
+#: src/console/plugin.cc:30
+msgid "Bass:"
+msgstr "Bass:"
+
+#: src/console/plugin.cc:33
+msgid "Treble:"
+msgstr ""
+
+#: src/console/plugin.cc:36
+msgid "Echo:"
+msgstr "Eko:"
+
+#: src/console/plugin.cc:39
+msgid "Default song length:"
+msgstr "Standard sånglängd:"
+
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
+msgid "<b>Resampling</b>"
+msgstr "<b>Resampling</b>"
+
+#: src/console/plugin.cc:43
+msgid "Enable audio resampling"
+msgstr ""
+
+#: src/console/plugin.cc:49
+msgid "<b>SPC</b>"
+msgstr "<b>SPC</b>"
+
+#: src/console/plugin.cc:50
+msgid "Ignore length from SPC tags"
+msgstr ""
+
+#: src/console/plugin.cc:52
+msgid "Increase reverb"
+msgstr ""
+
+#: src/console/plugin.h:26
+msgid "Game Console Music Decoder"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:131
+msgid ""
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:44
+msgid ""
+"Crossfade Plugin for Audacious\n"
+"Copyright 2010-2014 John Lindgren"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:48
+msgid "<b>Crossfade</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
+msgid "Overlap:"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
+msgid "Crossfade"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
+msgid "<b>Crystalizer</b>"
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
+msgid "Intensity:"
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:43
+msgid "Crystalizer"
+msgstr ""
+
+#: src/cue/cue.cc:37
+msgid "Cue Sheet Plugin"
+msgstr "Cue Sheet Plugin"
+
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Ta bort Filer"
+
+#: src/delete-files/delete-files.cc:75
+#, c-format
+msgid "Error moving %s to trash: %s."
+msgstr ""
+
+#: src/delete-files/delete-files.cc:86
+#, c-format
+msgid "Error deleting %s: %s."
+msgstr ""
+
+#: src/delete-files/delete-files.cc:117
+#, c-format
+msgid "Error deleting %s: not a local file."
+msgstr ""
+
+#: src/delete-files/delete-files.cc:134
+msgid "Do you want to move the selected files to the trash?"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:135
+msgid "Move to Trash"
+msgstr "Flytta till Papperskorgen"
+
+#: src/delete-files/delete-files.cc:140
+msgid "Do you want to permanently delete the selected files?"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
+msgid "Delete"
+msgstr "Ta Bort"
+
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
+msgid "Cancel"
+msgstr "Avsluta"
+
+#: src/delete-files/delete-files.cc:166
+msgid "Delete Selected Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:181
+msgid "<b>Delete Method</b>"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:182
+msgid "Move to trash instead of deleting immediately"
+msgstr "Flytta till papperskorgen istället för att ta bort direkt"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
+msgid "<b>Echo</b>"
+msgstr "<b>Eko</b>"
+
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "Delay:"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
+msgid "ms"
+msgstr "ms"
+
+#: src/echo_plugin/echo.cc:25
+msgid "Feedback:"
+msgstr "Feedback:"
+
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
+msgid "Volume:"
+msgstr "Volym:"
+
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
+msgstr "Eko"
+
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg Plugin"
+
+#: src/ffaudio/ffaudio-core.cc:571
+msgid ""
+"Multi-format audio decoding plugin for Audacious using\n"
+"FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
+"\n"
+"Audacious plugin by:\n"
+"William Pitcock <nenolod at nenolod.net>\n"
+"Matti Hämäläinen <ccr at tnsp.org>"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:386
+msgid "Output file format:"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:403
+msgid "Configure"
+msgstr "Konfigurera"
+
+#: src/filewriter/filewriter.cc:413
+msgid "Save into original directory"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:417
+msgid "Save into custom directory"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:427
+msgid "Output file folder:"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:431
+msgid "Pick a folder"
+msgstr "Välj en mapp"
+
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
+
+#: src/filewriter/filewriter.cc:484
+msgid ""
+"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."
+msgstr ""
+
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
+msgid "Auto"
+msgstr "Auto"
+
+#: src/filewriter/mp3.cc:40
+msgid "Joint Stereo"
+msgstr "Joint Stereo"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
+msgid "Stereo"
+msgstr "Stereo"
+
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
+msgid "Mono"
+msgstr "Mono"
+
+#: src/filewriter/mp3.cc:657
+msgid "MP3 Configuration"
+msgstr "MP3 Konfiguration"
+
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_OK"
+
+#: src/filewriter/mp3.cc:681
+msgid "Algorithm Quality:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:733
+msgid "(Hz)"
+msgstr "(Hz)"
+
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:764
+msgid "Bitrate (kbps):"
+msgstr "Bitrate (kbps):"
+
+#: src/filewriter/mp3.cc:796
+msgid "Compression ratio:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:820
+msgid "Audio Mode:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
+
+#: src/filewriter/mp3.cc:867
+msgid "Error protection"
+msgstr ""
+
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
+msgid "Quality"
+msgstr "Kvalite"
+
+#: src/filewriter/mp3.cc:888
+msgid "Enable VBR/ABR"
+msgstr ""
+
+#: src/filewriter/mp3.cc:898
+msgid "Type:"
+msgstr "Typ:"
+
+#: src/filewriter/mp3.cc:931
+msgid "VBR Options:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:947
+msgid "Minimum bitrate (kbps):"
+msgstr ""
+
+#: src/filewriter/mp3.cc:973
+msgid "Maximum bitrate (kbps):"
+msgstr ""
+
+#: src/filewriter/mp3.cc:995
+msgid "Strictly enforce minimum bitrate"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1007
+msgid "ABR Options:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1017
+msgid "Average bitrate (kbps):"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1044
+msgid "VBR quality level:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1076
+msgid "VBR/ABR"
+msgstr "VBR/ABR"
+
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1097
+msgid "Mark as copyright"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1108
+msgid "Mark as original"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1131
+msgid "Force addition of version 2 tag"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1141
+msgid "Only add v1 tag"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1148
+msgid "Only add v2 tag"
+msgstr ""
+
+#: src/filewriter/mp3.cc:1169
+msgid "Tags"
+msgstr "Taggar"
+
+#: src/filewriter/vorbis.cc:196
+msgid "Vorbis Encoder Configuration"
+msgstr ""
+
+#: src/filewriter/vorbis.cc:219
+msgid "Quality level (0 - 10):"
+msgstr ""
+
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC Dekoder"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
+msgid "lossless"
+msgstr "lossless"
+
+#: src/flacng/plugin.cc:169
+msgid ""
+"Original code by\n"
+"Ralf Ertzinger <ralf at skytale.net>\n"
+"\n"
+"http://www.skytale.net/projects/bmp-flac2/"
+msgstr ""
+
+#: src/gio/gio.cc:34
+msgid ""
+"GIO Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren"
+msgstr ""
+
+#: src/gio/gio.cc:42
+msgid "GIO Plugin"
+msgstr "GIO Plugin"
+
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:62
+msgid "OpenGL Spectrum Analyzer"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
+msgid "Entry number"
+msgstr ""
+
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
+msgid "Title"
+msgstr "Titel"
+
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
+msgid "Artist"
+msgstr "Artist"
+
+#: src/gtkui/columns.cc:38
+msgid "Year"
+msgstr "Ã…r"
+
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
+msgid "Album"
+msgstr "Album"
+
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
+msgid "Track"
+msgstr "Spår"
+
+#: src/gtkui/columns.cc:42
+msgid "Genre"
+msgstr "Genre"
+
+#: src/gtkui/columns.cc:43
+msgid "Queue position"
+msgstr ""
+
+#: src/gtkui/columns.cc:44
+msgid "Length"
+msgstr "Längd"
+
+#: src/gtkui/columns.cc:45
+msgid "File path"
+msgstr ""
+
+#: src/gtkui/columns.cc:47
+msgid "Custom title"
+msgstr "Anpassad titel"
+
+#: src/gtkui/columns.cc:48
+msgid "Bitrate"
+msgstr "Bitrate"
+
+#: src/gtkui/columns.cc:308
+msgid "Available columns"
+msgstr ""
+
+#: src/gtkui/columns.cc:334
+msgid "Displayed columns"
+msgstr ""
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Left"
+msgstr ""
+
+#: src/gtkui/layout.cc:167
+msgid "Dock at Right"
+msgstr ""
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Top"
+msgstr ""
+
+#: src/gtkui/layout.cc:168
+msgid "Dock at Bottom"
+msgstr ""
+
+#: src/gtkui/layout.cc:168
+msgid "Undock"
+msgstr ""
+
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
+msgid "Disable"
+msgstr ""
+
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
+msgid "_Open Files ..."
+msgstr "_Öppna filer..."
+
+#: src/gtkui/menus.cc:127
+msgid "Open _URL ..."
+msgstr "Öppna _URL ..."
+
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
+msgid "_Add Files ..."
+msgstr "_Lägg till filer ..."
+
+#: src/gtkui/menus.cc:129
+msgid "Add U_RL ..."
+msgstr "Lägg till U_RL ..."
+
+#: src/gtkui/menus.cc:131
+msgid "Search _Library"
+msgstr ""
+
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
+msgid "A_bout ..."
+msgstr "O_m ..."
+
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
+msgid "_Settings ..."
+msgstr "_Inställningar ..."
+
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
+msgid "_Quit"
+msgstr "_Avsluta"
+
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
+msgid "_Play"
+msgstr "_Spela"
+
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
+msgid "Paus_e"
+msgstr "_Paus_a"
+
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
+msgid "_Stop"
+msgstr "_Stoppa"
+
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
+msgid "Pre_vious"
+msgstr "Förra"
+
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
+msgid "_Next"
+msgstr "_Nästa"
+
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
+msgid "_Repeat"
+msgstr ""
+
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
+msgid "S_huffle"
+msgstr ""
+
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
+msgid "N_o Playlist Advance"
+msgstr ""
+
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
+msgid "Stop A_fter This Song"
+msgstr ""
+
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
+msgid "Song _Info ..."
+msgstr "LÃ¥tinformation"
+
+#: src/gtkui/menus.cc:151
+msgid "Jump to _Time ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:152
+msgid "_Jump to Song ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:154
+msgid "Set Repeat Point _A"
+msgstr ""
+
+#: src/gtkui/menus.cc:155
+msgid "Set Repeat Point _B"
+msgstr ""
+
+#: src/gtkui/menus.cc:156
+msgid "_Clear Repeat Points"
+msgstr ""
+
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
+msgid "By _Title"
+msgstr ""
+
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
+
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
+msgid "By File _Path"
+msgstr ""
+
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
+msgid "By Track _Number"
+msgstr ""
+
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
+msgid "By _Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
+msgid "By Al_bum"
+msgstr ""
+
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
+msgid "By Release _Date"
+msgstr ""
+
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
+msgid "By _Length"
+msgstr ""
+
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
+msgid "By _File Path"
+msgstr ""
+
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
+msgid "By _Custom Title"
+msgstr ""
+
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
+msgid "R_everse Order"
+msgstr ""
+
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
+msgid "_Random Order"
+msgstr ""
+
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr ""
+
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
+msgid "_Refresh"
+msgstr ""
+
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
+msgid "_Sort"
+msgstr "_Sortera"
+
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
+msgid "Sort Se_lected"
+msgstr ""
+
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
+msgid "Remove _Duplicates"
+msgstr ""
+
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
+msgid "Remove _Unavailable Files"
+msgstr ""
+
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
+msgid "_New"
+msgstr "_Ny"
+
+#: src/gtkui/menus.cc:207
+msgid "Ren_ame ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
+msgid "Remo_ve"
+msgstr ""
+
+#: src/gtkui/menus.cc:210
+msgid "_Import ..."
+msgstr "_Importera"
+
+#: src/gtkui/menus.cc:211
+msgid "_Export ..."
+msgstr "_Exportera"
+
+#: src/gtkui/menus.cc:213
+msgid "Playlist _Manager ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
+msgid "_Queue Manager ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
+msgid "Volume _Up"
+msgstr "Volym _Upp"
+
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
+msgid "Volume _Down"
+msgstr "Volym _Ner"
+
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
+msgid "_Equalizer"
+msgstr "_Equalizer"
+
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
+msgid "E_ffects ..."
+msgstr "Effekter ..."
+
+#: src/gtkui/menus.cc:227
+msgid "Show _Menu Bar"
+msgstr ""
+
+#: src/gtkui/menus.cc:228
+msgid "Show I_nfo Bar"
+msgstr ""
+
+#: src/gtkui/menus.cc:229
+msgid "Show Info Bar Vis_ualization"
+msgstr ""
+
+#: src/gtkui/menus.cc:230
+msgid "Show _Status Bar"
+msgstr ""
+
+#: src/gtkui/menus.cc:232
+msgid "Show _Remaining Time"
+msgstr ""
+
+#: src/gtkui/menus.cc:234
+msgid "_Visualizations ..."
+msgstr ""
+
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
+msgid "_File"
+msgstr "_Fil"
+
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
+msgid "_Playback"
+msgstr ""
+
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
+msgid "P_laylist"
+msgstr "Spellista"
+
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
+msgid "_Services"
+msgstr "_Services"
+
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
+msgid "_Output"
+msgstr ""
+
+#: src/gtkui/menus.cc:243
+msgid "_View"
+msgstr "_Visa"
+
+#: src/gtkui/menus.cc:248
+msgid "_Queue/Unqueue"
+msgstr ""
+
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
+msgid "Cu_t"
+msgstr ""
+
+#: src/gtkui/menus.cc:254
+msgid "_Copy"
+msgstr "_Kopiera"
+
+#: src/gtkui/menus.cc:255
+msgid "_Paste"
+msgstr "_Klistra in"
+
+#: src/gtkui/menus.cc:256
+msgid "Select _All"
+msgstr "Välj _Alla"
+
+#: src/gtkui/menus.cc:263
+msgid "_Rename ..."
+msgstr "_Döp om ..."
+
+#: src/gtkui/settings.cc:35
+msgid "<b>Playlist Tabs</b>"
+msgstr ""
+
+#: src/gtkui/settings.cc:36
+msgid "Always show tabs"
+msgstr ""
+
+#: src/gtkui/settings.cc:38
+msgid "Show entry counts"
+msgstr ""
+
+#: src/gtkui/settings.cc:40
+msgid "Show close buttons"
+msgstr ""
+
+#: src/gtkui/settings.cc:42
+msgid "<b>Playlist Columns</b>"
+msgstr ""
+
+#: src/gtkui/settings.cc:44
+msgid "Show column headers"
+msgstr ""
+
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
+msgid "<b>Miscellaneous</b>"
+msgstr ""
+
+#: src/gtkui/settings.cc:47
+msgid "Arrow keys seek by:"
+msgstr ""
+
+#: src/gtkui/settings.cc:50
+msgid "Scroll on song change"
+msgstr ""
+
+#: src/gtkui/ui_gtk.cc:71
+msgid "GTK Interface"
+msgstr "GTK Interface"
+
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
+#, c-format
+msgid "%s - Audacious"
+msgstr "%s - Audacious"
+
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
+msgid "Buffering ..."
+msgstr "Buffrar ..."
+
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
+msgid "Audacious"
+msgstr "Audacious"
+
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "Stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
+#, c-format
+msgid "%d channel"
+msgid_plural "%d channels"
+msgstr[0] "%d kanal "
+msgstr[1] "%d kanaler"
+
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
+#, c-format
+msgid "%d kbps"
+msgstr "%d kbps"
+
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr ""
+
+#: src/hotkey/gui.cc:71
+msgid "Previous track"
+msgstr "Förra låten"
+
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
+msgid "Play"
+msgstr "Spela"
+
+#: src/hotkey/gui.cc:73
+msgid "Pause/Resume"
+msgstr "Pausa/Fortsätta"
+
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
+msgid "Stop"
+msgstr "Stoppa"
+
+#: src/hotkey/gui.cc:75
+msgid "Next track"
+msgstr "Nästa låt"
+
+#: src/hotkey/gui.cc:76
+msgid "Forward 5 seconds"
+msgstr "Spola fram 5 sekunder"
+
+#: src/hotkey/gui.cc:77
+msgid "Rewind 5 seconds"
+msgstr "Spola bakåt 5 sekunder"
+
+#: src/hotkey/gui.cc:78
+msgid "Mute"
+msgstr ""
+
+#: src/hotkey/gui.cc:79
+msgid "Volume up"
+msgstr "Volym Upp"
+
+#: src/hotkey/gui.cc:80
+msgid "Volume down"
+msgstr "Volym Ner"
+
+#: src/hotkey/gui.cc:81
+msgid "Jump to file"
+msgstr "Hoppa till fil"
+
+#: src/hotkey/gui.cc:82
+msgid "Toggle player window(s)"
+msgstr ""
+
+#: src/hotkey/gui.cc:83
+msgid "Show On-Screen-Display"
+msgstr ""
+
+#: src/hotkey/gui.cc:84
+msgid "Toggle repeat"
+msgstr ""
+
+#: src/hotkey/gui.cc:85
+msgid "Toggle shuffle"
+msgstr ""
+
+#: src/hotkey/gui.cc:86
+msgid "Toggle stop after current"
+msgstr ""
+
+#: src/hotkey/gui.cc:87
+msgid "Raise player window(s)"
+msgstr ""
+
+#: src/hotkey/gui.cc:97
+msgid "(none)"
+msgstr "(ingen)"
+
+#: src/hotkey/gui.cc:234
+msgid ""
+"It is not recommended to bind the primary mouse buttons without "
+"modificators.\n"
+"\n"
+"Do you want to continue?"
+msgstr ""
+
+#: src/hotkey/gui.cc:236
+msgid "Binding mouse buttons"
+msgstr ""
+
+#: src/hotkey/gui.cc:391
+msgid ""
+"Press a key combination inside a text field.\n"
+"You can also bind mouse buttons."
+msgstr ""
+
+#: src/hotkey/gui.cc:396
+msgid "Hotkeys:"
+msgstr ""
+
+#: src/hotkey/gui.cc:413
+msgid "<b>Action:</b>"
+msgstr ""
+
+#: src/hotkey/gui.cc:420
+msgid "<b>Key Binding:</b>"
+msgstr ""
+
+#: src/hotkey/gui.cc:468
+msgid "_Add"
+msgstr "_Lägg till"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
+msgid ""
+"Global Hotkey Plugin\n"
+"Control the player with global key combinations or multimedia keys.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n"
+"\n"
+"Contributers include:\n"
+"Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+"Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+" Bryn Davies <curious at ihug.com.au>,\n"
+" Jonathan A. Davis <davis at jdhouse.org>,\n"
+" Jeremy Tan <nsx at nsx.homeip.net>"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr ""
+
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
+msgid ""
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
+msgstr ""
+
+#: src/ladspa/plugin.cc:414
+#, c-format
+msgid "%s Settings"
+msgstr ""
+
+#: src/ladspa/plugin.cc:478
+msgid "Module paths:"
+msgstr ""
+
+#: src/ladspa/plugin.cc:483
+msgid ""
+"<small>Separate multiple paths with a colon.\n"
+"These paths are searched in addition to LADSPA_PATH.\n"
+"After adding new paths, press Enter to scan for new plugins.</small>"
+msgstr ""
+
+#: src/ladspa/plugin.cc:499
+msgid "Available plugins:"
+msgstr ""
+
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
+msgid "Enable"
+msgstr ""
+
+#: src/ladspa/plugin.cc:518
+msgid "Enabled plugins:"
+msgstr ""
+
+#: src/ladspa/plugin.cc:534
+msgid "Settings"
+msgstr "Inställningar"
+
+#: src/ladspa/plugin.cc:551
+msgid ""
+"LADSPA Host for Audacious\n"
+"Copyright 2011 John Lindgren"
+msgstr ""
+
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr ""
+
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr ""
+
+#: src/lirc/lirc.cc:381
+msgid ""
+"A simple plugin to control Audacious using the LIRC remote control daemon\n"
+"\n"
+"Adapted for Audacious by:\n"
+"Tony Vroon <chainsaw at gentoo.org>\n"
+"Joonas Harjumäki <jharjuma at gmail.com>\n"
+"\n"
+"Based on the XMMS LIRC plugin by:\n"
+"Carl van Schaik <carl at leg.uct.ac.za>\n"
+"Christoph Bartelmus <xmms at bartelmus.de>\n"
+"Andrew O. Shadoura <bugzilla at tut.by>\n"
+"\n"
+"For more information about LIRC, see http://lirc.org."
+msgstr ""
+
+#: src/lirc/lirc.cc:392
+msgid "<b>Connection</b>"
+msgstr ""
+
+#: src/lirc/lirc.cc:393
+msgid "Reconnect to LIRC server"
+msgstr ""
+
+#: src/lirc/lirc.cc:395
+msgid "Wait before reconnecting:"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
+msgid "No lyrics available"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Fel"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
+#, c-format
+msgid "Unable to fetch %s"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
+#, c-format
+msgid "Unable to parse %s"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
+msgid "Looking for lyrics ..."
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Missing song metadata"
+msgstr ""
+
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
+msgid "Connecting to lyrics.wikia.com ..."
+msgstr ""
+
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
+
+#: src/m3u/m3u.cc:32
+msgid "M3U Playlists"
+msgstr ""
+
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
+#, c-format
+msgid "Tact generator: %d bpm"
+msgstr ""
+
+#: src/metronom/metronom.cc:149
+#, c-format
+msgid "Tact generator: %d bpm %d/%d"
+msgstr ""
+
+#: src/metronom/metronom.cc:237
+msgid ""
+"A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
+"\n"
+"To use it, add a URL: tact://beats*num/den\n"
+"e.g. tact://77 to play 77 beats per minute\n"
+"or tact://60*3/4 to play 60 bpm in 3/4 tacts"
+msgstr ""
+
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr ""
+
+#: src/mixer/mixer.cc:202
+msgid ""
+"Channel Mixer Plugin for Audacious\n"
+"Copyright 2011-2012 John Lindgren and Michał Lipski"
+msgstr ""
+
+#: src/mixer/mixer.cc:206
+msgid "<b>Channel Mixer</b>"
+msgstr ""
+
+#: src/mixer/mixer.cc:207
+msgid "Output channels:"
+msgstr ""
+
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
+msgstr ""
+
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
+msgid "<b>Resolution</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:54
+msgid "8-bit"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:55
+msgid "16-bit"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:56
+msgid "<b>Channels</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:60
+msgid "Nearest (fastest)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:61
+msgid "Linear (fast)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:62
+msgid "Spline (good)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:63
+msgid "Polyphase (best)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:65
+msgid "22 kHz"
+msgstr "22 kHz"
+
+#: src/modplug/plugin_main.cc:66
+msgid "44 kHz"
+msgstr "44 kHz"
+
+#: src/modplug/plugin_main.cc:67
+msgid "48 kHz"
+msgstr "48 kHz"
+
+#: src/modplug/plugin_main.cc:68
+msgid "96 kHz"
+msgstr "96 kHz"
+
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
+msgid "Level:"
+msgstr "Nivå:"
+
+#: src/modplug/plugin_main.cc:78
+msgid "Cutoff:"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:91
+msgid "<b>Reverb</b>"
+msgstr "<b>Reverb</b>"
+
+#: src/modplug/plugin_main.cc:94
+msgid "<b>Bass Boost</b>"
+msgstr "<b>Bass Boost</b>"
+
+#: src/modplug/plugin_main.cc:97
+msgid "<b>Surround</b>"
+msgstr "<b>Surround</b>"
+
+#: src/modplug/plugin_main.cc:100
+msgid "<b>Preamp</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:107
+msgid "Oversample"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:108
+msgid "Noise reduction"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:109
+msgid "Play Amiga MODs"
+msgstr "Spela Amiga Moduler"
+
+#: src/modplug/plugin_main.cc:110
+msgid "<b>Repeat</b>"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:111
+msgid "Repeat count:"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:112
+msgid "To repeat forever, set the repeat count to -1."
+msgstr ""
+
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
+
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
+msgstr "MPG123 Plugin"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b> Avancerat </ b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
+msgid "MPRIS 2 Server"
+msgstr "MPRIS 2 Server"
+
+#: src/neon/neon.cc:97
+msgid "Neon HTTP/HTTPS Plugin"
+msgstr "Neon HTTP/HTTPS Plugin"
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
+msgid "Stopped"
+msgstr "Stoppad"
+
+#: src/notify/event.cc:64
+msgid "Audacious is not playing."
+msgstr ""
+
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
+msgid ""
+"Desktop Notifications Plugin for Audacious\n"
+"Copyright (C) 2010 Maximilian Bogner\n"
+"Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n"
+"\n"
+"This plugin is free software: you can redistribute it and/or modify it under "
+"the terms of the GNU General Public License as published by the Free "
+"Software Foundation, either version 3 of the License, or (at your option) "
+"any later version.\n"
+"\n"
+"This plugin is distributed in the hope that 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, see <http://www.gnu.org/licenses/>."
+msgstr ""
+
+#: src/notify/notify.cc:110
+msgid "Show playback controls"
+msgstr ""
+
+#: src/notify/notify.cc:112
+msgid "Always show notification"
+msgstr ""
+
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
+
+#: src/notify/osd.cc:58
+msgid "Show"
+msgstr "Visa"
+
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
+msgid "Pause"
+msgstr "Pause"
+
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
+msgid "Next"
+msgstr "Nästa"
+
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
+msgid "Audio device:"
+msgstr ""
+
+#: src/oss4/plugin.cc:80
+msgid "Use alternate device:"
+msgstr ""
+
+#: src/oss4/plugin.cc:84
+msgid "Save volume between sessions."
+msgstr ""
+
+#: src/oss4/plugin.cc:86
+msgid "Enable format conversions made by the OSS software."
+msgstr ""
+
+#: src/oss4/plugin.cc:88
+msgid "Enable exclusive mode to prevent virtual mixing."
+msgstr ""
+
+#: src/oss4/plugin.cc:100
+msgid ""
+"OSS4 Output Plugin for Audacious\n"
+"Copyright 2010-2012 Michał Lipski\n"
+"\n"
+"I would like to thank people on #audacious, especially Tony Vroon and John "
+"Lindgren and of course the authors of the previous OSS plugin."
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
+msgid "PLS Playlists"
+msgstr "PLS Spellistor"
+
+#: src/psf/plugin.cc:45
+msgid "OpenPSF PSF1/PSF2 Decoder"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
+msgid ""
+"Audacious PulseAudio Output Plugin\n"
+"\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."
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Sök"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Förra"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr ""
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr ""
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr ""
+
+#: src/resample/resample.cc:183
+msgid ""
+"Sample Rate Converter Plugin for Audacious\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+
+#: src/resample/resample.cc:187
+msgid "Skip/repeat samples"
+msgstr ""
+
+#: src/resample/resample.cc:188
+msgid "Linear interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:189
+msgid "Fast sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:190
+msgid "Medium sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:191
+msgid "Best sinc interpolation"
+msgstr ""
+
+#: src/resample/resample.cc:195
+msgid "<b>Conversion</b>"
+msgstr ""
+
+#: src/resample/resample.cc:196
+msgid "Method:"
+msgstr ""
+
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
+msgid "Rate:"
+msgstr ""
+
+#: src/resample/resample.cc:202
+msgid "<b>Rate Mappings</b>"
+msgstr ""
+
+#: src/resample/resample.cc:203
+msgid "Use rate mappings"
+msgstr ""
+
+#: src/resample/resample.cc:205
+msgid "8 kHz:"
+msgstr "8 kHz:"
+
+#: src/resample/resample.cc:209
+msgid "16 kHz:"
+msgstr "16 kHz:"
+
+#: src/resample/resample.cc:213
+msgid "22.05 kHz:"
+msgstr "22.05 kHz:"
+
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
+msgid "44.1 kHz:"
+msgstr "44.1 kHz:"
+
+#: src/resample/resample.cc:225
+msgid "48 kHz:"
+msgstr "48 kHz:"
+
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
+msgid "96 kHz:"
+msgstr "96 kHz:"
+
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
+msgstr "192 kHz:"
+
+#: src/scrobbler2/config_window.cc:41
+#, c-format
+msgid "OK. Scrobbling for user: %s"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:54
+msgid "Permission Denied"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:56
+msgid "Access the following link to allow Audacious to scrobble your plays:"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:66
+msgid "Keep this window open and click 'Check Permission' again.\n"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
+msgid ""
+"Don't worry. Your scrobbles are saved on your computer.\n"
+"They will be submitted as soon as Audacious is allowed to do so."
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:77
+msgid "Network Problem."
+msgstr "Nätverksproblem"
+
+#: src/scrobbler2/config_window.cc:78
+msgid "There was a problem contacting Last.fm. Please try again later."
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:110
+msgid "Checking..."
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:176
+msgid "C_heck Permission"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:177
+msgid "_Revoke Permission"
+msgstr ""
+
+#: src/scrobbler2/config_window.cc:220
+msgid ""
+"You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
+msgid ""
+"The Scrobbler plugin could not be started.\n"
+"There might be a problem with your installation."
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:289
+msgid ""
+"Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
+"\n"
+"Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n"
+"\n"
+"Thanks to John Lindgren for giving me a hand at the beginning of this "
+"project.\n"
+"\n"
+msgstr ""
+
+#: src/scrobbler2/scrobbler_communication.cc:642
+msgid ""
+"Audacious is now using an improved version of the Last.fm Scrobbler.\n"
+"Please check the Preferences for the Scrobbler plugin."
+msgstr ""
+
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
+msgid ""
+"SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
+msgid "Library"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:394
+#, c-format
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/search-tool/search-tool.cc:400
+#, c-format
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/search-tool/search-tool.cc:594
+#, c-format
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
+msgid "_Create Playlist"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:645
+msgid "_Add to Playlist"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:684
+msgid "Search library"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:688
+msgid ""
+"To import your music library into Audacious, choose a folder and then click "
+"the \"refresh\" icon."
+msgstr ""
+
+#: src/search-tool/search-tool.cc:696
+msgid "Please wait ..."
+msgstr ""
+
+#: src/search-tool/search-tool.cc:723
+msgid "Choose Folder"
+msgstr "Välj Mapp"
+
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Öppna filer..."
+
+#: src/skins/menus.cc:65
+msgid "Open URL ..."
+msgstr "Öppna URL ..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
+msgid "Playback"
+msgstr "Uppspelning"
+
+#: src/skins/menus.cc:69
+msgid "Playlist"
+msgstr "Spellista"
+
+#: src/skins/menus.cc:70
+msgid "View"
+msgstr "Visa"
+
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
+msgid "Services"
+msgstr ""
+
+#: src/skins/menus.cc:74
+msgid "About ..."
+msgstr "Om ..."
+
+#: src/skins/menus.cc:75
+msgid "Settings ..."
+msgstr "Inställningar..."
+
+#: src/skins/menus.cc:76
+msgid "Quit"
+msgstr "Avsluta"
+
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
+msgid "Song Info ..."
+msgstr "LÃ¥tinformation ..."
+
+#: src/skins/menus.cc:84
+msgid "No Playlist Advance"
+msgstr ""
+
+#: src/skins/menus.cc:85
+msgid "Stop After This Song"
+msgstr ""
+
+#: src/skins/menus.cc:93
+msgid "Set A-B Repeat"
+msgstr ""
+
+#: src/skins/menus.cc:94
+msgid "Clear A-B Repeat"
+msgstr ""
+
+#: src/skins/menus.cc:96
+msgid "Jump to Song ..."
+msgstr "Hoppa till låt ..."
+
+#: src/skins/menus.cc:97
+msgid "Jump to Time ..."
+msgstr "Hoppa till tid ..."
+
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr ""
+
+#: src/skins/menus.cc:103
+msgid "New Playlist"
+msgstr "Ny spellista"
+
+#: src/skins/menus.cc:104
+msgid "Rename Playlist ..."
+msgstr "Döp om spellista"
+
+#: src/skins/menus.cc:105
+msgid "Remove Playlist"
+msgstr "Ta Bort Spellista"
+
+#: src/skins/menus.cc:107
+msgid "Previous Playlist"
+msgstr "Förra Spellista"
+
+#: src/skins/menus.cc:108
+msgid "Next Playlist"
+msgstr "Nästa Spellista"
+
+#: src/skins/menus.cc:110
+msgid "Import Playlist ..."
+msgstr "Importera spellista"
+
+#: src/skins/menus.cc:111
+msgid "Export Playlist ..."
+msgstr "Exportera spellista"
+
+#: src/skins/menus.cc:113
+msgid "Playlist Manager ..."
+msgstr ""
+
+#: src/skins/menus.cc:114
+msgid "Queue Manager ..."
+msgstr ""
+
+#: src/skins/menus.cc:116
+msgid "Refresh Playlist"
+msgstr ""
+
+#: src/skins/menus.cc:120
+msgid "Show Playlist Editor"
+msgstr ""
+
+#: src/skins/menus.cc:121
+msgid "Show Equalizer"
+msgstr "Visa Equalizer"
+
+#: src/skins/menus.cc:123
+msgid "Show Remaining Time"
+msgstr ""
+
+#: src/skins/menus.cc:125
+msgid "Always on Top"
+msgstr ""
+
+#: src/skins/menus.cc:126
+msgid "On All Workspaces"
+msgstr ""
+
+#: src/skins/menus.cc:128
+msgid "Roll Up Player"
+msgstr ""
+
+#: src/skins/menus.cc:129
+msgid "Roll Up Playlist Editor"
+msgstr ""
+
+#: src/skins/menus.cc:130
+msgid "Roll Up Equalizer"
+msgstr ""
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
+msgid "Add URL ..."
+msgstr "Lägg till URL ..."
+
+#: src/skins/menus.cc:139
+msgid "Add Files ..."
+msgstr "Lägg till filer ..."
+
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
+msgid "By Title"
+msgstr ""
+
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
+
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
+msgid "By File Path"
+msgstr ""
+
+#: src/skins/menus.cc:151
+msgid "Remove All"
+msgstr "Ta Bort Alla"
+
+#: src/skins/menus.cc:152
+msgid "Clear Queue"
+msgstr ""
+
+#: src/skins/menus.cc:154
+msgid "Remove Unavailable Files"
+msgstr ""
+
+#: src/skins/menus.cc:155
+msgid "Remove Duplicates"
+msgstr ""
+
+#: src/skins/menus.cc:157
+msgid "Remove Unselected"
+msgstr ""
+
+#: src/skins/menus.cc:158
+msgid "Remove Selected"
+msgstr ""
+
+#: src/skins/menus.cc:162
+msgid "Search and Select"
+msgstr ""
+
+#: src/skins/menus.cc:164
+msgid "Invert Selection"
+msgstr ""
+
+#: src/skins/menus.cc:165
+msgid "Select None"
+msgstr ""
+
+#: src/skins/menus.cc:166
+msgid "Select All"
+msgstr ""
+
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr ""
+
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
+msgid "By Artist"
+msgstr ""
+
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr ""
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
+msgid "By Release Date"
+msgstr ""
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
+msgid "Randomize List"
+msgstr ""
+
+#: src/skins/menus.cc:199
+msgid "Reverse List"
+msgstr ""
+
+#: src/skins/menus.cc:201
+msgid "Sort Selected"
+msgstr "Sortera vald"
+
+#: src/skins/menus.cc:202
+msgid "Sort List"
+msgstr "Sortera Lista"
+
+#: src/skins/menus.cc:208
+msgid "Cut"
+msgstr "Klipp"
+
+#: src/skins/menus.cc:209
+msgid "Copy"
+msgstr "Kopiera"
+
+#: src/skins/menus.cc:210
+msgid "Paste"
+msgstr "Klistra in"
+
+#: src/skins/menus.cc:212
+msgid "Queue/Unqueue"
+msgstr ""
+
+#: src/skins/menus.cc:218
+msgid "Load Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:219
+msgid "Load Auto Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:220
+msgid "Load Default"
+msgstr ""
+
+#: src/skins/menus.cc:221
+msgid "Load Preset File ..."
+msgstr ""
+
+#: src/skins/menus.cc:222
+msgid "Load EQF File ..."
+msgstr ""
+
+#: src/skins/menus.cc:224
+msgid "Save Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:225
+msgid "Save Auto Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:226
+msgid "Save Default"
+msgstr ""
+
+#: src/skins/menus.cc:227
+msgid "Save Preset File ..."
+msgstr ""
+
+#: src/skins/menus.cc:228
+msgid "Save EQF File ..."
+msgstr ""
+
+#: src/skins/menus.cc:230
+msgid "Delete Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:231
+msgid "Delete Auto Preset ..."
+msgstr ""
+
+#: src/skins/menus.cc:233
+msgid "Import Winamp Presets ..."
+msgstr ""
+
+#: src/skins/menus.cc:235
+msgid "Reset to Zero"
+msgstr ""
+
+#: src/skins/plugin.cc:48
+msgid "Winamp Classic Interface"
+msgstr ""
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
+msgid "Save"
+msgstr ""
+
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
+msgid "Load"
+msgstr ""
+
+#: src/skins/preset-browser.cc:83
+msgid "Load Preset File"
+msgstr ""
+
+#: src/skins/preset-browser.cc:100
+msgid "Load EQF File"
+msgstr ""
+
+#: src/skins/preset-browser.cc:119
+msgid "Save Preset File"
+msgstr ""
+
+#: src/skins/preset-browser.cc:137
+msgid "Save EQF File"
+msgstr ""
+
+#: src/skins/preset-browser.cc:151
+msgid "Import Winamp Presets"
+msgstr ""
+
+#: src/skins/preset-list.cc:285
+msgid "Presets"
+msgstr ""
+
+#: src/skins/preset-list.cc:335
+msgid "Load preset"
+msgstr ""
+
+#: src/skins/preset-list.cc:351
+msgid "Load auto-preset"
+msgstr ""
+
+#: src/skins/preset-list.cc:367
+msgid "Save preset"
+msgstr ""
+
+#: src/skins/preset-list.cc:382
+msgid "Save auto-preset"
+msgstr ""
+
+#: src/skins/preset-list.cc:408
+msgid "Delete preset"
+msgstr ""
+
+#: src/skins/preset-list.cc:424
+msgid "Delete auto-preset"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:178
+msgid "Select main player window font:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:181
+msgid "Select playlist font:"
+msgstr "Välj spelliste teckensnitt:"
+
+#: src/skins/skins_cfg.cc:187
+msgid "<b>Skin</b>"
+msgstr "<b>Skin</b>"
+
+#: src/skins/skins_cfg.cc:189
+msgid "<b>Fonts</b>"
+msgstr "<b>Teckensnitt</b>"
+
+#: src/skins/skins_cfg.cc:192
+msgid "Use bitmap fonts (supports ASCII only)"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:194
+msgid "Scroll song title"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:196
+msgid "Scroll song title in both directions"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:201
+msgid "Analyzer"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:202
+msgid "Scope"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:203
+msgid "Voiceprint / VU meter"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:204
+msgid "Off"
+msgstr "Av"
+
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
+msgid "Normal"
+msgstr "Normal"
+
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
+msgid "Fire"
+msgstr "Eld"
+
+#: src/skins/skins_cfg.cc:210
+msgid "Vertical lines"
+msgstr "Vertikala linjer"
+
+#: src/skins/skins_cfg.cc:214
+msgid "Lines"
+msgstr "Linjer"
+
+#: src/skins/skins_cfg.cc:215
+msgid "Bars"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:219
+msgid "Slowest"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:220
+msgid "Slow"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
+msgid "Medium"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:222
+msgid "Fast"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:223
+msgid "Fastest"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:227
+msgid "Dots"
+msgstr "Punkter"
+
+#: src/skins/skins_cfg.cc:228
+msgid "Line"
+msgstr "Linje"
+
+#: src/skins/skins_cfg.cc:229
+msgid "Solid"
+msgstr "Solid"
+
+#: src/skins/skins_cfg.cc:235
+msgid "Ice"
+msgstr "Is"
+
+#: src/skins/skins_cfg.cc:240
+msgid "Smooth"
+msgstr "Smooth"
+
+#: src/skins/skins_cfg.cc:244
+msgid "<b>Type</b>"
+msgstr "<b> Typ</b>"
+
+#: src/skins/skins_cfg.cc:245
+msgid "Visualization type:"
+msgstr "Visualiserings typ:"
+
+#: src/skins/skins_cfg.cc:248
+msgid "<b>Analyzer</b>"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:249
+msgid "Show peaks"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:251
+msgid "Coloring:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:254
+msgid "Style:"
+msgstr "Stil:"
+
+#: src/skins/skins_cfg.cc:257
+msgid "Falloff:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:260
+msgid "Peak falloff:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:264
+msgid "Scope Style:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:267
+msgid "Voiceprint Coloring:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:270
+msgid "VU Meter Style:"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:276
+msgid "General"
+msgstr ""
+
+#: src/skins/skins_cfg.cc:277
+msgid "Visualization"
+msgstr "Visualisering"
+
+#: src/skins/ui_equalizer.cc:282
+msgid "Preamp"
+msgstr ""
+
+#: src/skins/ui_equalizer.cc:286
+msgid "31 Hz"
+msgstr "31 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "63 Hz"
+msgstr "63 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "125 Hz"
+msgstr "125 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "250 Hz"
+msgstr "250 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "500 Hz"
+msgstr "500 Hz"
+
+#: src/skins/ui_equalizer.cc:287
+msgid "1 kHz"
+msgstr "1 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "2 kHz"
+msgstr "2 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "4 kHz"
+msgstr "4 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "8 kHz"
+msgstr "8 kHz"
+
+#: src/skins/ui_equalizer.cc:288
+msgid "16 kHz"
+msgstr "16 kHz"
+
+#: src/skins/ui_equalizer.cc:330
+msgid "Audacious Equalizer"
+msgstr "Audacious Equalizer"
+
+#: src/skins/ui_main.cc:688
+#, c-format
+msgid "Seek to %d:%-2.2d / %d:%-2.2d"
+msgstr ""
+
+#: src/skins/ui_main.cc:709
+#, c-format
+msgid "Volume: %d%%"
+msgstr ""
+
+#: src/skins/ui_main.cc:732
+#, c-format
+msgid "Balance: %d%% left"
+msgstr ""
+
+#: src/skins/ui_main.cc:734
+msgid "Balance: center"
+msgstr ""
+
+#: src/skins/ui_main.cc:736
+#, c-format
+msgid "Balance: %d%% right"
+msgstr ""
+
+#: src/skins/ui_main.cc:842
+msgid "Options Menu"
+msgstr ""
+
+#: src/skins/ui_main.cc:846
+msgid "Disable 'Always On Top'"
+msgstr ""
+
+#: src/skins/ui_main.cc:848
+msgid "Enable 'Always On Top'"
+msgstr ""
+
+#: src/skins/ui_main.cc:851
+msgid "File Info Box"
+msgstr ""
+
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
+msgid "Repeat point A set."
+msgstr ""
+
+#: src/skins/ui_main.cc:1341
+msgid "Repeat point B set."
+msgstr ""
+
+#: src/skins/ui_main.cc:1350
+msgid "Repeat points cleared."
+msgstr ""
+
+#: src/skins/ui_playlist.cc:219
+msgid "Search entries in active playlist"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:226
+msgid ""
+"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."
+msgstr ""
+
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:263
+msgid "Clear previous selection before searching"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:266
+msgid "Automatically toggle queue for matching entries"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:269
+msgid "Create a new playlist with matching entries"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:717
+msgid "Audacious Playlist Editor"
+msgstr ""
+
+#: src/skins/ui_playlist.cc:752
+#, c-format
+msgid "%s (%d of %d)"
+msgstr ""
+
+#: src/skins/ui_skinselector.cc:167
+msgid "Archived Winamp 2.x skin"
+msgstr ""
+
+#: src/skins/ui_skinselector.cc:172
+msgid "Unarchived Winamp 2.x skin"
+msgstr ""
+
+#: src/skins/util.cc:430
+#, c-format
+msgid "Could not create directory (%s): %s\n"
+msgstr ""
+
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
+msgid ""
+"Based on the xmms_sndfile plugin:\n"
+"Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
+"\n"
+"Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\n"
+"\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."
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
+
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
+
+#: src/song_change/song_change.cc:33
+msgid "Song Change"
+msgstr ""
+
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
+
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
+
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
+
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
+
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
+
+#: src/song_change/song_change.cc:376
+msgid ""
+"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"
+"%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"
+"%p: Currently playing (1 or 0)\n"
+"%a: Artist\n"
+"%b: Album\n"
+"%T: Track title"
+msgstr ""
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:144
+msgid ""
+"SoX Resampler Plugin for Audacious\n"
+"Copyright 2013 Michał Lipski\n"
+"\n"
+"Based on Sample Rate Converter Plugin:\n"
+"Copyright 2010-2012 John Lindgren"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:150
+msgid "Quick"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:151
+msgid "Low"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:153
+msgid "High"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:154
+msgid "Very High"
+msgstr ""
+
+#: src/sox-resampler/sox-resampler.cc:158
+msgid "Quality:"
+msgstr ""
+
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr ""
+
+#: src/speed-pitch/speed-pitch.cc:210
+msgid "<b>Speed and Pitch</b>"
+msgstr ""
+
+#: src/speed-pitch/speed-pitch.cc:211
+msgid "Speed:"
+msgstr ""
+
+#: src/speed-pitch/speed-pitch.cc:214
+msgid "Pitch:"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Status ikon"
+
+#: src/statusicon/statusicon.cc:283
+msgid "Se_ttings ..."
+msgstr ""
+
+#: src/statusicon/statusicon.cc:372
+msgid ""
+"Status Icon Plugin\n"
+"\n"
+"Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
+"Copyright 2010 Michał Lipski <tallica at o2.pl>\n"
+"\n"
+"This plugin provides a status icon, placed in\n"
+"the system tray area of the window manager."
+msgstr ""
+
+#: src/statusicon/statusicon.cc:379
+msgid "<b>Mouse Scroll Action</b>"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:380
+msgid "Change volume"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:383
+msgid "Change playing song"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:386
+msgid "<b>Other Settings</b>"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:387
+msgid "Disable the popup window"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:389
+msgid "Close to the system tray"
+msgstr ""
+
+#: src/statusicon/statusicon.cc:391
+msgid "Advance in playlist when scrolling upward"
+msgstr ""
+
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
+
+#: src/stereo_plugin/stereo.cc:36
+msgid ""
+"Extra Stereo Plugin\n"
+"\n"
+"By Johan Levin, 1999"
+msgstr ""
+"Extra Stereo Plugin\n"
+"\n"
+"Av Johan Levin, 1999"
+
+#: src/stereo_plugin/stereo.cc:44
+msgid "<b>Extra Stereo</b>"
+msgstr "<b>Extra Stereo</b>"
+
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr ""
+
+#: src/tonegen/tonegen.cc:94
+#, c-format
+msgid "%s %.1f Hz"
+msgstr "%s %.1f Hz"
+
+#: src/tonegen/tonegen.cc:94
+msgid "Tone Generator: "
+msgstr ""
+
+#: src/tonegen/tonegen.cc:160
+msgid ""
+"Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
+"Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
+"\n"
+"To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
+"e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
+msgstr ""
+
+#: src/voice_removal/voice_removal.cc:28
+msgid "Voice Removal"
+msgstr ""
+
+#: src/vorbis/vorbis.cc:465
+msgid ""
+"Audacious Ogg Vorbis Decoder\n"
+"\n"
+"Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+"http://www.xiph.org/\n"
+"\n"
+"Original code by:\n"
+"Tony Arcieri <bascule at inferno.tusculum.edu>\n"
+"\n"
+"Contributions from:\n"
+"Chris Montgomery <monty at xiph.org>\n"
+"Peter Alm <peter at xmms.org>\n"
+"Michael Smith <msmith at labyrinth.edu.au>\n"
+"Jack Moffitt <jack at icecast.org>\n"
+"Jorn Baayen <jorn at nl.linux.org>\n"
+"Håvard Kvålen <havardk at xmms.org>\n"
+"Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
+msgstr ""
+"Audacious Ogg Vorbis Decoder\n"
+"\n"
+"Baserat på Xiph.org stiftelsens Ogg Vorbis Plugin: \n"
+"http://www.xiph.org/\n"
+"\n"
+"Original kod av: \n"
+"Tony Arcieri <bascule at inferno.tusculum.edu> \n"
+"\n"
+"Bidrag från: \n"
+"Chris Montgomery <monty at xiph.org> \n"
+"Peter Alm <peter at xmms.org> \n"
+"Michael Smith <msmith at labyrinth.edu.au> \n"
+"Jack Moffitt <jack at icecast.org> \n"
+"Jorn Baayen <jorn at nl.linux.org> \n"
+"Håvard Kvålen <havardk at xmms.org> \n"
+"Gian-Carlo Pascutto <gcp at sjeng.org> \n"
+"Eugene Zagidullin <e.asphyx at gmail.com>"
+
+#: src/vorbis/vorbis.h:18
+msgid "Ogg Vorbis Decoder"
+msgstr "Ogg Vorbis Dekoder"
+
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX Dekoder"
+
+#: src/vtx/vtx.cc:184
+msgid ""
+"Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
+"Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
+"Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
+msgstr ""
+"Vortex filformat spelaren genom Sashnov Alexander <sashnov at ngs.ru> \n"
+"Baserat på in_vtx.dll av Roman Sherbakov <v_soft at microfor.ru>  \n"
+"Audacious plugin av Pavel Vymetalek <pvymetalek at seznam.cz>"
+
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack Dekoder"
+
+#: src/wavpack/wavpack.cc:211
+msgid "lossy (hybrid)"
+msgstr "lossy (hybrid)"
+
+#: src/wavpack/wavpack.cc:213
+msgid "lossy"
+msgstr "lossy"
+
+#: src/wavpack/wavpack.cc:255
+msgid ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
+"\n"
+"Some of the plugin code was by Miles Egan."
+msgstr ""
+"Copyright 2006 William Pitcock <nenolod at nenolod.net> \n"
+"En del av plugin-koden var av Miles Egan."
+
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
+msgstr "2SF Dekoder"
+
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "XML Delbara Spellistor (XSPF)"
diff --git a/po/ta.po b/po/ta.po
index f12f846cc441..cb9a8a9555bc 100644
--- a/po/ta.po
+++ b/po/ta.po
@@ -3,15 +3,17 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# Gobi <gobikrishnant at gmail.com>, 2013
-# nar7esh <rajnareshwar at gmail.com>, 2013
+# Gobikrishnan <gobikrishnant at gmail.com>, 2013
+# Gobikrishnan <gobikrishnant at gmail.com>, 2013
+# Nareshwar Raju Vaneshwar <rajnareshwar at gmail.com>, 2013
+# Nareshwar Raju Vaneshwar <rajnareshwar at gmail.com>, 2013
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-04 21:21+0000\n"
+"Last-Translator: Thomas Lange <thomas-lange2 at gmx.de>\n"
 "Language-Team: Tamil (http://www.transifex.com/projects/p/audacious/language/"
 "ta/)\n"
 "Language: ta\n"
@@ -20,51 +22,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "தனித்த "
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "ஒலிப்பிரிப்பு"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "சூழ்ந்த"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr ""
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib Player)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib Player)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "அலாரம்"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr ""
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "அலாரம்"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -87,7 +73,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -109,7 +95,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -123,360 +109,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "இது உங்களை எழுப்புவதற்கான அழைப்பு"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr ""
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "நினைவூட்டி"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "திங்கட்கிழமை "
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "செவ்வாய்கிழமை "
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "புதன்கிழமை "
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "வியாழக்கிழமை "
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "வெள்ளிக்கிழமை "
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "சனிக்கிழமை "
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "ஞாயிற்றுகிழமை "
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "அலாரம் அமைப்புகள்"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "நேரம் "
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "அலாரம் அடிக்கும் நேரம் (இயல்புநிலை) :"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "பின் நிசப்தமாக்குக: "
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "மணித்தியாலங்கள் "
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "நிமிடங்கள் "
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "அலாரம் வேண்டிய நாட்களை தெரிவு செய்க "
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "நாள் "
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "இயல்புநிலை"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "நாட்கள் "
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "மங்குதல் "
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "வினாடிகள் "
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "ஒலி அளவு "
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "இங்கு ஆரம்பிக்குக "
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "இறுதி "
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "தற்போதைய "
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "மேலதிக பின்னூட்டு"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "செயல்படுத்துக "
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "பாடல் பட்டியல் (விரும்பினால் மட்டும்)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "பாடல் பட்டியலினை தெரிவு செய்க"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "விருப்பத்தேர்வுகள் "
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "இவ்விருப்ப தேர்வுகள் எதனை உணர்த்துகின்றன?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "உதவி "
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "குறுவட்டு வரைவு "
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA வெளியீடு"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "இயல்புநிலை துடிப்பு குறியீடு பண்பேற்ற சாதனம் "
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "இயல்புநிலை கலவை சாதனம்"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "துடிப்பு குறியீடு பண்பேற்ற சாதனம்:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "கலவை சாதனம்:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "கலவை உறுப்பு:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "தொங்கும் தன்மையை குறைக்குக "
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-சொருகி  (MIDI இயக்கி )"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA வெளியீடு"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-சொருகி  (MIDI இயக்கி )"
-
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-சொருகி - ஒலி எழுத்துரு கோப்பினை தெரிவு செய்க "
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr ""
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "கோப்பின் பெயர் "
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "அளவு (பயிட்ஸ்)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "பெயர்: "
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI தகவல் </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "வடிவமைப்பு: "
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "நீளம் (மில்லி வினாடிகள்): "
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "பாடல்களின் இலக்கங்கள்:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "மாறி "
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "துடிப்புகள் ஒரு நிமிடத்திற்கு: "
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "துடிப்புகள் ஒரு நிமிடத்திற்கு (wavg): "
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "நேரப் பிரிவு:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI பின்னூட்டுகள் மற்றும் பாடல் வரிகள் </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "*இந்த MIDI கோப்பிற்கான எந்தவொரு பின்னூட்டும் கிடைக்கப்படவில்லை * "
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "*இந்த MIDI கோப்பிற்கான எந்தவொரு பாடல்வரிகளும் கிடைக்கப்படவில்லை * "
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_மூடவும்"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "(செல்லுபடியற்ற UTF-8 )"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "AMIDI-சொருகி பற்றி "
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -487,152 +479,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr " AOSD ( திரையில் தோன்றும் காட்சி)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "செவ்வகம் "
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "வட்ட வடிவிலான செவ்வகம் "
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "குழிவான செவ்வகம் "
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "ஏதுமில்லை "
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "மீள் இயக்கினை ஆரம்பிக்குக "
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "பாடல் பட்டியல் இடுகை இயக்கப்படுகையில் திரையில் தோன்றும் காட்சி தூண்டப்படுகிறது. "
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "தலைப்பு மாற்றம் "
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"மீள் இயக்கத்தின் போது திரையில் தோன்றும் காட்சி தூண்டப்படுகிறது, பாடல் தலைப்பு "
-"மாற்றப்படுகிறது, ஆனால் கோப்பின் பெயர் மாற்றமடையாது. இணைய நீரோடைகளின் போது இம்முறை "
-"மிகவும் பிரயோசனமானது. "
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "இடைநிறுத்தத்தை ஆரம்பிக்க "
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "மீளியக்கம் இடைநிறுத்தப்படும் போது  திரையில் தோன்றும் காட்சி தூண்டப்படுகிறது."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "இடைநிறுத்தத்தை நிறுத்துக"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "மீளியக்கம் நிறுத்தப்படுகையில் திரையில் தோன்றும் காட்சி தூண்டப்படுகிறது. "
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "ஒன்றின் நிறுத்தப்பட்ட நிலை "
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "ஒப்பீட்டு X விலக்கம்:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "ஒப்பீட்டு Y விலக்கம்: "
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "அதிகூடிய  திரையில் தோன்றும் காட்சியின் அகலம்:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "பல்-கணினித்திரை தேர்வுகள் "
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "திரையில் தோன்றும் காட்சியினை காட்டுக இதனை பயன்படுத்தி: "
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "அனைத்து கணினித்திரைகள் "
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "கணினித்திரை %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "நேரம் (மில்லி வினாடிகளில்) "
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "காட்சிப்படுத்துக:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "உண்மங்கியடைதல்:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "வெளிமங்குதல்:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "எழுத்துருக்கள் "
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "எழுத்துரு %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "நிழல் "
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "வழங்கும் பாங்கு "
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "நிறங்கள் "
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "நிறம் %i "
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "தூண்டுதலினை செயல்படுத்துக "
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "நிகழ்வு "
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "தொகுப்பு நிர்வாகி கண்டறியப்பட்டது"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -643,112 +629,112 @@ msgstr ""
 "கட்டாயமாக தொகுப்பு நிர்வாகியொன்று செயற்படுத்தப்பட வேண்டும். இல்லையெனில் திரையில் "
 "தோன்றும் காட்சி ஒழுங்காக இயங்காது. "
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "போலி வெளிப்படைத்தன்மையிற்கு தொகுப்பு நிர்வாகியொன்று தேவையில்லை "
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "வெளிப்படைத்தன்மை "
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "போலி வெளிப்படைத்தன்மை "
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "உண்மையான வெளிப்படைத்தன்மை ( X தொகுப்பு நீடிப்பு தேவைப்படுகிறது.)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "தொகுப்பு நீட்டிப்பு ஏற்றப்படவில்லை "
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "தொகுப்பு நீட்டிப்பு காணப்படவில்லை "
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>ஔடகிவஸ் திரையில் தோன்றும் காட்சி </span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "ஔடகிவஸ் திரையில் தோன்றும் காட்சி - உள்ளமைவு"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "இடம் "
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "உயிரூட்டுதல் "
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "எழுத்து "
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "அலங்காரம் "
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "தூண்டுதல் "
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "மற்றவை"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr ""
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 பாடல் பட்டியல் "
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "ஔடகிவஸ் பாடல் பட்டியல்கள் "
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>நிறம்</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "மங்கலான குறியிலக்கம்"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "பார் இசைப்பிரிப்பு முதல் இருசெவிக்குரியது (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "முன்னமைப்புகள்:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "நிலை ஊட்டல்:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "குறை அதிர்வெண்:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "முன்னமைப்புகள்:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "பார் இசைப்பிரிப்பு முதல் இருசெவிக்குரியது (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "நிறமாலை பகுப்பாய்வி "
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "ஒலி இறுவட்டு சொருகி"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -760,169 +746,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>சாதனம்</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "வாசிக்கும் வேகம் :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "சாதனம் மேலெழுது:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>மீத்தரவு </b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "இறுவட்டு எழுத்துகளை உபயோகிக்க"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "CDDB இனை உபயோகிக்க"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP இற்கு பதிலாக HTTP இனை பயன்படுத்துக "
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "சேவையகம்:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "வழி :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "போர்ட் :"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "ஒலி இறுவட்டு சொருகி"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "ஒலி இறுவட்டு"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "வட்டு வெறுமையாக உள்ளது."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "ஆதரவற்ற வட்டு வகை."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "ஒலி இறுவட்டு பட்டியல் உருப்படிகள்"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "இறுவட்டினை இயக்குக "
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "இறுவட்டினை சேர்க்குக "
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "ஒலி இறுவட்டு பட்டியல் உருப்படிகள்"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>சுருக்கம்</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "மைய சத்தம்: "
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "நிலைமாறும் வரம்பாக: "
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "நிலைமாறும் வரம்பு சுருக்கி "
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -932,199 +905,224 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "அடித்தொனி:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "உயர் இறுதி அதிர்வெண்:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr ""
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "இயல்புநிலை பாடல் நீளம்:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "ஒலி புதுப்பித்தலை செயல்படுத்தக "
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "புதுப்பித்தல் வீதம்: "
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC குறிச்சொற்களின் நீளத்தை புறக்கணிக்ககுக "
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "எதிர்முழக்கத்தை அதிகரிக்குக "
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "விளையாட்டு பணியக இசை குறிவிலக்கி"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"பாடல்கள் வித்தியாசமான தல இலக்கங்களை கொண்டதால் குறுக்குமங்குதல் செயலிழந்தது. செயல்ப்படுத்த "
-"ஒரு தட கலவையினை உபயோகித்து  ஒre தட இலக்கங்களுக்கு மாற்றவும்."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"பாடல்கள் வித்தியாசமான மாதிரி வீதங்களை கொண்டதால் குறுக்குமங்குதல் செயலிழந்தது. "
-"செயல்ப்படுத்த ஒரு மாதிரி வீத கலவையினை உபயோகித்து  ஒரே மாதிரி வீதங்களுக்கு மாற்றவும்."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>குறுக்கு மங்கல்</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "மேற்பொருந்தல்:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "குறுக்கு மங்கல்"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"பாடல்கள் வித்தியாசமான தல இலக்கங்களை கொண்டதால் குறுக்குமங்குதல் செயலிழந்தது. செயல்ப்படுத்த "
+"ஒரு தட கலவையினை உபயோகித்து  ஒre தட இலக்கங்களுக்கு மாற்றவும்."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"பாடல்கள் வித்தியாசமான மாதிரி வீதங்களை கொண்டதால் குறுக்குமங்குதல் செயலிழந்தது. "
+"செயல்ப்படுத்த ஒரு மாதிரி வீத கலவையினை உபயோகித்து  ஒரே மாதிரி வீதங்களுக்கு மாற்றவும்."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>பளிங்குருவாக்கl</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "அடர்த்தி:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "palinguruvaathal"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "கோல் தாள் செருகுநிரல்"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr ""
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr ""
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "அழிக்குக "
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "ரத்து செய்க "
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr ""
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>ethiroli</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "தாமதம் :"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "ms"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "பின்னூட்டு :"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "ஒலி அளவு "
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "எதிரொலி "
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg நீட்சி"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1134,55 +1132,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg நீட்சி"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter நீட்சி "
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "வெளியீட்டு கோப்பு வடிவம்:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "கட்டமைக்குக "
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "அசல் கோப்பகத்தில் சேமிக்கவும்"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "விருப்ப கோப்பகத்தில் சேமிக்கவும்"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "வெளியீட்டு கோப்பு கோப்பகம்: "
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "ஒரு கோப்புறையை தேர்ந்தெடுக்கவும்"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "இருந்து கோப்பு கிடைக்கும்:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "அசல் கோப்பு குறிச்சொற்கl"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "அசல் கோப்புறை "
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "கோப்பு நீட்டிப்பினை அகற்ற வேண்டாம்"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "கோப்பு பெயரையும் பாடல் எண்ணையும் வரைக"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1200,165 +1198,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter நீட்சி "
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "தானியங்கு"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "கூட்டு பேரொலி"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "பேரொலி"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "ஒற்றை"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 கட்டமைப்பு  "
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "படிமுறை தரம்:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "வெளியீtடு மாதிரி வீதம்:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "பிட்வீதm / அழுத்த விகிதம்:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "பிட்வீதம் (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "அழுத்த விகிதம்:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "ஒலி முறைமை:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "மற்றவை"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "கடுமையான ISO இணக்கத்தை செயல்படுத்தக "
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "தவறு பாதுகாப்பு"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "தரம் "
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR இனை செயல்படுத்துக "
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "வகை:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR தேர்வுகள்:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "அதிகுறைந்த பிட்வீதம் (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "அதிகூடிய பிட்வீதம் (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "கண்டிப்பாக குறைந்த பிட்வீதத்தை செயல்படுத்துக "
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR தேர்வுகள்:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "சராசரி பிட்வீதம் (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR தர நிலை:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR தலைப்பை எழுத வேண்டாம் "
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "அளவுருக்களை சட்டப்படுத்துக :"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "பதிப்புரிமை என குறிக்குக "
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "அசலென குriக்குக"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 அளபுரு:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "பதிப்பு 2 குறியை பலமாக உள்ளடக்குக "
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "பதிப்பு 1 குறியை மாத்திரம் உள்ளடக்குக "
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "பதிப்பு 2 குறியை மாத்திரம் உள்ளடக்குக "
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "குறி "
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis குறிமுறையாக்கி கட்டமைப்பு"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "தரம் (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC குறிவிலக்கி "
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr ""
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1366,21 +1368,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC குறிவிலக்கி "
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO நீட்சி"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1392,530 +1398,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL நிறமாலை பகுப்பாய்வி"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome குறுக்குவழிகள் "
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "பதிவு எண்"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "தலைப்பு"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "பாடகர்"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "வருடம்"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "குறுவட்டு"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "பாடல் "
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "இலக்கியநடை"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "வரிசையில் இடம் "
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "நீளம்"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "கோப்பு vali"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "கோப்பின் பெயர் "
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "விருப்ப தலைப்பு "
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "பிட்வீதம்"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "தேடல் கருவி"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "இடது பக்கம் தரையிறக்குக "
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "வலது பக்கம் தரையிறக்குக"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "மேல் பக்கம் தரையிறக்குக"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "கீழ் பக்கம் தரையிறக்குக"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "தரையிறக்க வேண்டாம் "
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "முடக்குக "
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "தேடல் கருவி"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_கோப்புக்களைத் திற ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "முகவரியை_திற ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "கோப்புக்களை _சேர் ..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "முகவரியை சேர் ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "பற்றி ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_விலகு "
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_இயக்குக "
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_இடைநிறுத்து"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_நிறுத்துga"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_முந்தைய"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_அடுத்து "
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_மறுபடியும்"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "குலுக்குக "
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "முன்னோக்கிய பாடல் பட்டியல் alla"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "பாடல் தகவல் "
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "_நேரத்திற்கு தாவவும் "
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "பாடலுக்கு _தாவவும்"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr ""
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr ""
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr ""
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "_தலைப்பு  அடிப்படையில்"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr ""
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "பாடல் _இலக்க அடிப்படையில்  "
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "_பாடகர்  அடிப்படையில்"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "வெளியிட்ட திகதி அடிப்படையில்"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "_கோப்பு வழி அடிப்படையில்"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "_விருப்ப தலைப்பு அடிப்படையில்"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "தலைகீழ் ஒழுங்கு"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_தற்போக்கு ஒழுங்கு"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_புதுப்பிக்குக "
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_வரிசைப்படுத்துக "
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "_கிடைக்கப்பெறாத கோப்புகளை அகற்றுக"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_புதிய "
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_இறக்குமதி ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_ஏற்றுமதி ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "_வரிசை நிர்வாகி ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "ஒலிஉரப்பான் _அதிகரிக்குக "
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "ஒலிஉரப்பான் _குறைக்குக "
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_சமமாக்கி"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "_பட்டியல் பட்டியை காண்பிக்குக "
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "தகவல் பட்டியை காண்பிக்குக "
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "தகவல் பட்டி காட்சியாக்கத்தை காண்பிக்குக "
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "_நிலைமை பட்டியை காண்பிக்குக"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "கோப்பு "
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_மீள்இயக்குக "
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "பாடல் பட்டியல் "
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "_சேவைகள் "
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "_வெளியீடு"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_paarvayiduga"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_வரிசைப்படுத்துக/வரிசைப்படுத்தலை அகற்றுக "
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "வெட்டுக "
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "நகலெடுக்க "
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_ஒட்டவும்"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "_அனைத்தையும் தேர்ந்தெடுக்குக "
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "மறுபெயர்"
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr ""
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK இடைமுகம் "
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - ஔடகிவஸ்"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "இடைநிலைப்படுத்துகிறது ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "ஔடகிவஸ்"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "தனித்த "
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "ஒலிப்பிரிப்பு"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "ஒற்றை முறை."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "பாடல் பட்டியல் murai"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "பாடலின் பின்னர் நிறுத்துக."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr ""
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "இயக்குக "
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "இடைநிறுத்து / மீண்டும் இயக்கு "
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "நிறுத்துக "
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr ""
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 விநாடிகள் முன்னாள் செல்க "
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 விநாடிகள் பின்னால் செல்க "
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "ஒலியடக்கவும்"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "ஒலிஉரப்பான்  அதிகரிக்குக"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "ஒலிஉரப்பான்  குறைக்குக"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "கோப்பிற்கு தாவவும்."
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr " திரையில் தோன்றும் காட்சியினை kaattuga"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(எதுவுமல்ல)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1926,15 +2009,11 @@ msgstr ""
 "⏎\n"
 "நீங்கள் தொடர விரும்புகிறீர்களா?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "சுட்டி பொத்தான்களை பிணைத்தல்"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "உலகளாவிய முக்கியசாவி நீட்சி கட்டமைப்பு"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -1942,23 +2021,27 @@ msgstr ""
 "எழுத்து புலத்தில் ஒரு விசை சேர்க்கையை அழுத்தவும்.⏎\n"
 "உங்களுக்கு சுட்டி பொத்தான்களை பிணைக்கவும் முடியும்."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "குறுக்குவிசைகள்:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>நடவடிக்கை: </b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>சாவி பிணைத்தல்:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr ""
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "உலகளாவிய குறுக்குவிசைகள்:"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1973,56 +2056,51 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "உலகளாவிய குறுக்குவிசைகள்:"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK வெளியீடு "
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK வெளியீடு "
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s அமைப்புகள்"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA புரவலன் அமைப்புகள்"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "தொகுதிக்கூறு பாதைகள்:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2033,73 +2111,39 @@ msgstr ""
 "புதிய பாதைகள் சேர்த்ததன் பின்னர், புதிய செருகுநிரல்கள் வருட உள்ளிடுகவினை அழுத்தக.</"
 "small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "இருப்பிலுள்ள செருகுநிரல்கள்:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "செயல்படுத்துக "
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "செருகுநிரல்களினை செயல்ப்படுத்துக:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "அமைப்புக்கள்"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA "
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC உதவியை ஆரம்பிக்க mudiyavillai⏎\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC இன் கட்டமைப்பு கோப்பினை வாசிக்க முடியவில்லை⏎\n"
-"\n"
-"%s: LIRC இன் ஆவணங்களை படிக்கவும்⏎\n"
-"\n"
-"%s: எப்படி ஒரு சரியான கட்டமைப்பு கோப்பினை உருவாக்குவது⏎\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: மீள் இணைப்பிற்கு முனைகிறது ...⏎\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: அறியப்படாத கட்டளை \"%s\"⏎\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC இல் இருந்து துண்டிக்கப்பட்டு விட்டது ⏎\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: ஒவ்வொரு %d வினாடிக்கும் மீள் இணைப்பை பெற முயலும் ...⏎\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC "
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2115,73 +2159,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b> இணைப்பு </b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "LIRC சேவைகயத்துக்கு மீள் இணைக்குக "
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "மீள் இணைக்க முன் பொறுக்க :"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC "
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki நீட்சி "
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "எந்தவொரு பாடல்வரிகளும் கிடைக்கப்படவில்லை "
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "thavaruthal"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "thavaruthal"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki நீட்சி "
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U பாடல் பட்டியல்"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "திறமை பிறப்பாக்கி"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "திறமை பிறப்பாக்கி:% d நிமிடத்திற்கான துடிப்புகள் "
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "திறமை பிறப்பாக்கி:%d நிமிடத்திற்கான துடிப்புகள் %d %d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2190,162 +2242,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "திறமை பிறப்பாக்கி"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "தட கலவைப்பான் "
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>தட கலவை</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "வெளியீட்டு thadangal"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "தட கலவைப்பான் "
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS நீட்சி"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (தொகுதி இயக்கி )"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr ""
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (தொகுதி இயக்கி )"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
+
+#: src/mpg123/mpg123.cc:54
+msgid "MPG123 Plugin"
+msgstr "MPG123 நீட்சி"
+
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
 
-#: src/mpg123/mpg123.c:210
+#: src/mpg123/mpg123.cc:248
 msgid "Surround"
 msgstr "சூழ்ந்த"
 
-#: src/mpg123/mpg123.c:412
-msgid "MPG123 Plugin"
-msgstr "MPG123 நீட்சி"
+#: src/mpris2/plugin.cc:39
+msgid "MPRIS 2 Server"
+msgstr "MPRIS 2 சேவையகம் "
+
+#: src/neon/neon.cc:97
+msgid "Neon HTTP/HTTPS Plugin"
+msgstr "Neon HTTP/HTTPS நீட்சி "
+
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
 
-#: src/mpris2/plugin.c:403
-msgid "MPRIS 2 Server"
-msgstr "MPRIS 2 சேவையகம் "
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
 
-#: src/neon/neon.c:1056
-msgid "Neon HTTP/HTTPS Plugin"
-msgstr "Neon HTTP/HTTPS நீட்சி "
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "நிறுத்துப்பட்டது "
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "ஔடகிவஸ் இயங்கவில்லை "
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "பணிமேடை அறிவிப்புகள்"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2365,55 +2449,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr ""
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "பணிமேடை அறிவிப்புகள்"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "காண்பிக்குக "
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "இடைநிறுத்துக "
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "அடுத்தது "
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. இயல்புநிலை சாதனம்"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 வெளியீடு "
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "ஒலி சாதனம்:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "மாற்று சாதனம் பயன்படுத்துக:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "அமர்வுகள் இடையே ஒலி அளவை சேமிக்குக."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "OSS மென்பொருள் மூலம் வடிவமைப்பு மாற்றத்தை செயல்படுத்துக."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "மெய்நிகர் கலப்பினை தடுக்க பிரத்யேக முறையினை செயல்படுத்துக."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2422,19 +2515,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 வெளியீடு "
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS பாடல் பட்டியல்"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 குறிவிலக்கி "
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio வெளியீடு "
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2454,143 +2563,212 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio வெளியீடு "
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "முந்தைய"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "மறுமுறை"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "குலுக்குக "
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "மாதிரி விகிதம் பரிமாற்றி "
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "மாதிரிகளை தவிர்க்கவும் / மீlavum"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "நேர்கோட்டு இடைக்கணிப்பு"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "வேகமாக sinc இடைச்செருகல்"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "மத்திமமான sinc இடைச்செருகல்"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "சிறந்த sinc இடைச்செருகல்"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b> பரிமாற்றம் </b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "முறைமை "
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "வீதம்:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>வீத வரைபடங்கள் </b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "வீத வரைபடங்களினை உபயோகிக்குக "
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz: "
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz: "
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz: "
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz: "
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz: "
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz: "
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "மாதிரி விகிதம் பரிமாற்றி "
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "வலையமைப்பு சிக்கல் "
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "சரிபார்க்கப்படுகிறது "
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2601,86 +2779,72 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL வெளியீடு "
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL வெளியீடு "
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "நூலகம்"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "தெரியாத பாடகர்"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "தெரியாத குறுவட்டு"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
+msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "பாடல் பட்டியலொன்றை _உருவாக்குக "
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "பாடல் பட்டியலிற்கு _சேர்க்க "
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "நூலகத்தில் தேடுக "
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2688,679 +2852,769 @@ msgstr ""
 "ஔடகிவஸ் இல் இசை நூகலமொன்றை இறக்குமதி செய்ய கோப்பகமொன்றை தெரிவு செய்து புதுப்பிப்பு "
 "பொத்தானை அழுத்துக. "
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "தயவு செய்து பொருத்திருக்குக ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "கோப்பகமொன்றை தேர்க "
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "மீள் இயக்கு"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "பாடல் பட்டியல்"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "பார்வையிடுக "
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr ""
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr ""
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr ""
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr ""
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr ""
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "மறுமுறை"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "குலுக்குக "
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "முன்னோக்கிய பாடல் பட்டியலுக்கு செல்ல வேண்டாம்"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr ""
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "முந்தைய"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
 msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "புதிய பாடல் பட்டியல்"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr ""
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr ""
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr ""
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr ""
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr ""
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr ""
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "பாடல் பட்டியல் திருத்தியை காண்பிக்க "
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "சமமாக்கியை காண்பிக்க "
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "எப்பொழுதும் மேலே "
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "தலைப்பின் படி "
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "கோப்பு பெயரின் படி "
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "அனைத்தையும் அகற்றுக. "
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "வரிசையினை அழிக்குக. "
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "கிடைக்கப்பெறாத கோப்புகளை அகற்றுக. "
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "போலிகளை அகற்றுக "
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "தெரிவுசெய்யாதவற்றை அகற்றுக. "
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "தெரிவுசெய்தவற்றை அகற்றுக"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "தேடி தேர்ந்தெடுக்கவும்"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "தலைகீழ் தேர்ந்தெடுப்பு"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "எதனையும் தேர்ந்தெடுக்க வேண்டாம்."
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "அனைத்தையும் தேர்ந்தெடுக்குக "
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "குறுவட்டின் படி "
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "பாடல் இலக்க அடிப்படையில்  "
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "பாடகர்களின் படி "
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "குறுவட்டின் படி "
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "பாடல் இலக்க அடிப்படையில்  "
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
+
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "பட்டியலினை தற்போக்காக தோன்றச்செய்க "
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "பட்டியலினை தலைகீழாக்குக"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "வரிசையானவற்றை தெரிக."
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "பட்டியலை வரிசையாக்குக "
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "வெட்டுக "
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "நகleடுக்குக"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "ஒட்டுக "
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp பாரம்பரிய இடைமுகம்"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "சேமிக்குக "
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "ஏற்றுக "
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "முன்னமைப்புகள்"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "முன்னமைப்புகளினை ஏற்றுக "
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "தானியங்கு முன்னமைப்புகளை ஏற்றுக  "
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "முன்னமைப்புகளை சேமிக்க"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "தானியங்கு முன்னமைப்புகளை சேமிக்குக"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "முன்னமைப்பினை அழிக்குக "
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "தானியங்கு முன்னமைப்புகளை அழிக்குக"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_iyakkai"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "பிரதான இயக்கி சாளரத்தின் எழுத்துருவை தெரிவு செய்க :"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_பாடல் பட்டியல்:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "பாடல் பட்டியலின் எழுத்துருவை தெரிவு செய்க :"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "பிட்மாப் பட எழுத்துருக்களை உபயோகிக்க (ASCII இணை மட்டும் ஆதரிக்கிறது)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "இரு திசைகளிலும் பாடல் தலைப்பை ururavaikkuga "
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "பகுப்பாய்வி "
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "குறியிலக்கம்"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "அணைக்குக "
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "இயல்பான"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "நெருப்பு "
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "கோடுகள் "
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "பட்டைகள்"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "மெதுவான "
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "மெதுவாய் "
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "நடுத்தரம் "
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "விரைவு "
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "மிக விரைவாக "
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "பனி "
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "மிருதுவான "
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "பொதுவான"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "உருவக காட்சிப்படுத்தல் "
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "முன் விரிவாக்கி "
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "ஔடகிவஸ் சமமாக்கி "
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "%d:%-2.2d / %d:%-2.2d இனை நாடுக"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "ஒலி அளவு: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "சமநிலை:% d%% இடது"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "சமநிலை:மத்தி "
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "சமநிலை:% d%% வலது "
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "தேர்வு பட்டியல்"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "'எப்போதும் மேலே' என்பதை முடக்குக "
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "'எப்போதும் மேலே' என்பதை செயற்படுத்துக "
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "கோப்பு தகவல் பெட்டி"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "ஒற்றை முறை."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "பாடல் பட்டியல் murai"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "பாடலின் பின்னர் நிறுத்துக."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "செய்வினை பாடல் பட்டியலிலுள்ள பதிவுகளை தேடுக "
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3371,57 +3625,61 @@ msgstr ""
 "வழக்கமான வெளிப்பாடுகள் தொடரியலை கொண்டவை. வழக்கமான வெளிப்பாடுகள் எவ்வாறு இயங்கும் என "
 "தெரியாவிடின் நீங்கள் தேடுவதின் துல்லியமான பகுதியினை உள்ளிடுக. "
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "தலைப்பு:"
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "குறுவட்டு:"
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "பாடகர்:"
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "கோப்பின் பெயர்:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "தேட முன் முன்னைய தெரிவுகளை துடைத்தழிக்குக "
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "தேர்வடையும் பதிவுகளை தானாக நிலைமாற்று வரிசையாக்குக"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "தேர்வடையும் பதிவுகளுக்கு புதிய பாடல் பட்டியலொன்றை உருவாக்குக."
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "ஔடகிவஸ் பாடல் பட்டியல் திருத்தி"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d இன் %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "ஆவணப்படுத்தப்பட்ட Winamp 2.x தோல் "
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "ஆவணப்படுத்தப்படாத Winamp 2.x தோல் "
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "கோப்பகமொன்றை உருவாக்க முடியவில்லை (%s): %s⏎\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3443,76 +3701,71 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Sndio வெளியீட்டு நீட்சிகள் பற்றி"
-
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "ஆதரிக்கப்படாத வடிவமைப்பு "
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "சரி "
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "பாடல் மாற்றம் "
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "ஔடகிவஸ் புதிய பாடலொன்றை இயக்க கட்டளையிடுக. "
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>அளவுருக்கள் ஓட்டுக்குள் மேற்கோள் குறிகளால் உட்பொதிந்திருக்க வேண்டும்."
+"இல்லையெனில் பாதுகாப்பு ஆபத்து இருக்கிறது</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "கட்டளை:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "ஔடகிவஸ் பாடலொன்றை நிறுத்த கட்டளையிடுக. "
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "ஔடகிவஸ் பாடல் பட்டியலொன்று முடிவடையும் போது  இயக்க கட்டளையிடுக. "
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"பாடலொன்றின் தலைப்பு மாறும் போது இயக்க கட்டளையிடுக. (அதாவது பிணைய நீரோடைகளின் போது )"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3527,19 +3780,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>அளவுருக்கள் ஓட்டுக்குள் மேற்கோள் குறிகளால் உட்பொதிந்திருக்க வேண்டும்."
-"இல்லையெனில் பாதுகாப்பு ஆபத்து இருக்கிறது</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "கட்டளைகள் "
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3548,51 +3797,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "விரைவு "
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "குறைவு "
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "உயர்"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "மிக உயர் "
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "தரம்:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "வேகம்:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "சுருதி:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
 msgstr ""
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3603,63 +3852,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "சப்த அளவை மாற்றுக "
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "இயங்கும் பாடலை மாற்றுக "
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr ""
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "திடீர் சாளரத்தை செயலிழக்க செய்க."
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr ""
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "பாடல் பட்டியலினை உருட்டும் போது முன்னோக்கி செல்லவும் "
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>கூடுதல் பேரொலி </b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr ""
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "ஒலி  உருவாக்கி "
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "தொனி பிறப்பாக்கி:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3668,15 +3917,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "ஒலி  உருவாக்கி "
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "குரல் நீக்கம்"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3697,44 +3942,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr ""
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr ""
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
 msgstr ""
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
+#: src/xsf/plugin.cc:50
+msgid "2SF Decoder"
 msgstr ""
 
-#: src/xsf/plugin.c:217
-msgid "2SF Decoder"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
 msgstr ""
 
-#: src/xspf/xspf.c:438
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr ""
diff --git a/po/tr.po b/po/tr.po
index 47c1885e8b2f..5311488d4834 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -5,28 +5,29 @@
 # Translators:
 # aamet <aaydin159 at gmail.com>, 2012
 # aamet <aaydin159 at gmail.com>, 2012
-# elma sevmem <drmxmyt at gmail.com>, 2013
-# elma sevmem <drmxmyt at gmail.com>, 2013
-# emfi <emrefirat93 at gmail.com>, 2013
-# etc <etcetin at gmail.com>, 2014
-# emfi <emrefirat93 at gmail.com>, 2013
-# ferhatelmas <elmas.ferhat at gmail.com>, 2013
-# ferhatelmas <elmas.ferhat at gmail.com>, 2013
+# elmasevmem <drmxmyt at gmail.com>, 2013
+# elmasevmem <drmxmyt at gmail.com>, 2013
+# Emre FIRAT <emrefirat93 at gmail.com>, 2013
+# Emin Tufan <etcetin at gmail.com>, 2014
+# Emre FIRAT <emrefirat93 at gmail.com>, 2013
+# ferhat elmas <elmas.ferhat at gmail.com>, 2013
+# ferhat elmas <elmas.ferhat at gmail.com>, 2013
 # Murat Senel <muratasenel at gmail.com>, 2007
 # Murat Åženel <muratasenel at gmail.com>, 2007
 # Onur Küçük <onur at pardus.org.tr>, 2007
-# seckyn <seckyn at windowslive.com>, 2013
-# seckyn <seckyn at windowslive.com>, 2013
+# seckin Yılmaz <seckyn at windowslive.com>, 2013
+# seckin Yılmaz <seckyn at windowslive.com>, 2013
 # tarkan255 <t.oguzman at hotmail.com>, 2012
 # tarkan255 <t.oguzman at hotmail.com>, 2012
-# volkangezer <volkangezer at gmail.com>, 2013
+# Tolga <tolsen92 at outlook.com>, 2014
+# Volkan Gezer <volkangezer at gmail.com>, 2013,2015
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-13 00:59+0000\n"
+"Last-Translator: Volkan Gezer <volkangezer at gmail.com>\n"
 "Language-Team: Turkish (http://www.transifex.com/projects/p/audacious/"
 "language/tr/)\n"
 "Language: tr\n"
@@ -35,51 +36,35 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "mono"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "stereo"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr ""
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "AAC(Raw) Çözücü"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug(AdLib Oynatıcı)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr ""
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr ""
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Alarm"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Alarm ayarla..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 msgstr ""
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Alarm"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -102,7 +87,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -124,7 +109,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -138,360 +123,366 @@ msgid ""
 "    toggle button if you want it to be shown."
 msgstr ""
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Bu uyandırma çağrısıdır."
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
-msgstr ""
+msgstr "Bugünkü hatırlatıcınız..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Hatırlatıcı"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Pazartesi"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Salı"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Çarşamba"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "PerÅŸembe"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "Cuma"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Cumartesi"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Pazar"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Alarm Ayarları"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Zaman"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Alarm (Varsayılan)"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Sonra sessiz:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "saat"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "dakika"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Sonraki alarm için günleri seçiniz"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "Gün"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Öntanımlı"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Günler"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Bozulma"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "saniye"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Ses"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "Ä°le baÅŸla"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "Son"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Åžu anda"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Ek Komut"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "izin ver"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Çalma Listesi(isteğe bağlı)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
-msgstr ""
+msgstr "Çalma listesi Seç"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Seçenekler"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Bu ayarlar ne anlama geliyor?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Yardım"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
+msgstr "Albüm kapağı"
+
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "Albüm Kapağı (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA Çıktısı"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
 msgstr ""
 
-#: src/alsa/config.c:210
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(açıklama yok)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Varsayılan PCM aygıtı"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Varsayılan karıştırma aygıtı"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM aygıtı:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Karıştırıcı aygıt:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Karıştırıcı öğesi:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
 msgstr ""
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr ""
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>GeliÅŸmiÅŸ</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr ""
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - SoundFont dosyası seç"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Ä°ptal"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "_Aç"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "Dosya adı"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Boyut (bayt)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Ä°sim:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI Bilgisi </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Biçim:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Uzunluk (ms):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr ""
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "deÄŸiÅŸken"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Zamanı Böl:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI Yorumları ve Sözleri </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* bu midi dosyasında yorum bulunamadı *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* bu midi dosyasında şarkı sözü bulunamadı *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Kapat"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (geçersiz UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr ""
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -502,152 +493,146 @@ msgid ""
 "http://neugierig.org/software/ghosd/"
 msgstr ""
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr ""
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Dikdörtgen"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Dairesel Dikdörtgen"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "İçbükey Dikdörtgen"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Hiçbiri"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Çalmayı Başlat"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Parça listesindeki girdi oynatıldığında OSD'yi başlatır."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Başlık Değiştirme"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Şarkı başladığında görünen şarkı başlığı değişir, fakat dosya adı aynı kalır "
-"ise OSD'yi tetikler. Bu yetenek özellikle İnternet üzerinden dinlenen "
-"yayınlarda başlık değişikliği olduğunda bu ayar faydalı oluyor."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Bekletme Açık"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Çalma bekletildiğinde OSD'yi başlatır."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Bekletme Kapalı"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Çalmaya yeniden başladığında OSD'yi başlatır."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "YerleÅŸtirme"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "DeÄŸiÅŸken X deÄŸeri:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "DeÄŸiÅŸken Y deÄŸeri:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Maksimum OSD geniÅŸliÄŸi:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Çoklu Ekran seçenekleri"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD kullanımını göster:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "tüm ekranlar"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "ekran %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Zamanlama (ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Görüntü:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Gecikme:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Kaybolma:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Yazı Tipleri"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Yazı tipi %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Gölge"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Tarama Biçemi"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Renkler"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Renkler %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Tetikleyiciyi etkinleÅŸtir"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Olay"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Composite yöneticisi tespit edildi"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -657,112 +642,112 @@ msgstr ""
 "Çalışan bir Composite yöneticisinin olduğundan emin değilseniz lütfen "
 "OSD'nin düzgün çalışması için bir Composite yöneticisi çalıştırınız"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Sahte şeffaflık için composite yöneticisi gerekli değil"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Şeffaflık"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Sahte şeffaflık"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Gerçek Şeffaflık (X Composite Eklentisi gerekli)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite eklentisi yüklü değil"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite eklentisi eriÅŸilebilir deÄŸil"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - yapılandırması"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "_Sına"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "_Ayarla"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Konum"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Canlandırma"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Metin"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Dekorasyon"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "BaÅŸlat"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Çeşitli"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr ""
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 Parça listesi"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr ""
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr ""
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
-msgstr ""
+msgstr "<b>Renk</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr ""
 
-#: src/bs2b/plugin.c:142
-msgid "Feed level:"
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
 msgstr ""
 
-#: src/bs2b/plugin.c:154
-msgid "Cut frequency:"
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
 msgstr ""
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
+#: src/bs2b/plugin.cc:136
+msgid "Feed level:"
 msgstr ""
 
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
 msgstr ""
 
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/bs2b/plugin.cc:139
+msgid "Cut frequency:"
+msgstr ""
+
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr ""
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -774,169 +759,156 @@ msgid ""
 "This was a Google Summer of Code 2007 project."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "CDDBP yerine HTTP kullan"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Bağlantı Noktası:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Ses CD'si"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "Parça %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr ""
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Sürücü boş."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Desteklenmeyen disk türü."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr ""
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "CD çal"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "CD Ekle"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr ""
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr ""
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr ""
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Dinamik alan:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr ""
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -946,195 +918,220 @@ msgid ""
 "Shay Green <gblargg at gmail.com>"
 msgstr ""
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "Bas:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "Tiz:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Yankı:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Varsayılan şarkı uzunluğu:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr ""
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Ses örneklemesini etkinleştir"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Örnekleme oranı:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr ""
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "SPC etiketlerindeki uzunluğu gözardı et"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Derinliği artır"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Oyun Konsolu Müzik Çözümleyicisi"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr ""
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr ""
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr ""
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr ""
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr ""
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Dosyaları Sil"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr ""
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr ""
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr ""
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "Çöp kutusuna taşı"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "Seçilen dosyaları kalıcı olarak silmek istiyor musunuz?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Sil"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Ä°ptal"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "Dosyaları Sil"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "Seçilen Dosyaları Sil"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr ""
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr ""
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr ""
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr ""
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
+#: src/echo_plugin/echo.cc:39
+msgid "Echo"
 msgstr ""
 
-#: src/echo_plugin/echo.c:122
-msgid "Echo"
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1144,55 +1141,55 @@ msgid ""
 "Matti Hämäläinen <ccr at tnsp.org>"
 msgstr ""
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
 msgstr ""
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Çıktı dosya biçimi:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Yapılandır"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Orjinal dizine kaydet"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Özel dizine kaydet"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Çıktı dosya klasörü:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Dizin seçimi"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Dosya adı kaynağı:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "orijinal dosya iÅŸaretleri"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "özgün dosya adı"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Dosya ismi uzantılarını daraltma"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Parça numarısını dosya adına ekle"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1210,165 +1207,169 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr ""
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Otomatik"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "BirleÅŸik Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Stereo"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Mono"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 Yapılandırması"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr ""
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Algoritma Kalitesi:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Çıktı Örnekleme Oranı:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Bit oranı / Sıkıştırma oranı:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Bit oranı (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Sıkıştırma oranı:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Ses Kipi:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Çeşitli"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "ISO standartlarına mutlak uyum gözetmeye zorla"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr ""
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "Hata koruması"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Kalite"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "VBR/ABR etkinleÅŸtir"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Tür:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR Seçenekleri:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "En düşük bit oranı (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "En yüksek bit oranı (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "En düşük bit oranını tam olarak zorla"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR Seçenekleri:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Ortalama bit oranı (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR kalite seviyesi:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Xing VBR başlığını yazma"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "Telif hakkı olarak işaretle"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "Orijinal olarak iÅŸaretle"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "ID3 parametreleri:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "sürüm 2 etkiketin eklenmesini zorla"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Sadece v1 etiketini ekle"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Sadece v2 etiketini ekle"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Etiketler:"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis Kodlayıcı Ayarları"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Kalite seviyesi (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr ""
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "kayıpsız"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1376,21 +1377,25 @@ msgid ""
 "http://www.skytale.net/projects/bmp-flac2/"
 msgstr ""
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr ""
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 msgstr ""
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1402,530 +1407,607 @@ msgid ""
 "License: GPLv2+"
 msgstr ""
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
 msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Sayı girin"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Başlık"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Sanatçı"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Yıl"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Albüm"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr ""
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Parça"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr ""
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Liste sırası"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Uzunluk"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Dosya yolu"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Dosya adı"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Özel başlık"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Bit oranı"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr ""
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr ""
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Arama Aracı"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Sola kenetle"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "SaÄŸa kenetle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Ãœste kenetle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Aşağıya kenetle"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Çıkar"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Devre Dışı"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Arama Aracı"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "_Dosya Aç ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "URL _Aç ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr ""
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "U_RL Ekle ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr ""
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "H_akkında"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr ""
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Çık"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Oynat"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Duraklat"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "D_urdur"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "_Önceki"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Sonraki"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "_Tekrarla"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "_Karıştır"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr ""
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr ""
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Şarkı Bilgisi ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Süre Atla"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Şarkı Atla"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
-msgstr ""
+msgstr "Tekrarlama Başlancığı _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
-msgstr ""
+msgstr "Tekrarlama Sonu _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
-msgstr ""
+msgstr "_Tekrarlama Noktalarını Sil"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "_Başlığa Göre"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
-msgstr ""
+msgstr "_Dosya Yoluna Göre"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
-msgstr "Parça Numarası"
+msgstr "Parça_Numarasına Göre"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
-msgstr "Sanatçı"
+msgstr "_Sanatçıya Göre"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr ""
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
-msgid "By Release _Date"
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
+msgid "By Release _Date"
 msgstr "Yayın Tarihi"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr ""
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr ""
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "Özel Başlık"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr ""
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "_Rastgele SipariÅŸ"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
 msgstr ""
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Yenile"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Tür"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr ""
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr ""
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr ""
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Yeni"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr ""
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr ""
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Yükle ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Çıkart ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr ""
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Sıra Yöneticisi ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "Sesi_Arttır"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "Sesi_Azalt"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Ekolayzır"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr ""
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Menü_Çubuğunu Göster"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Bilgi Çubuğunu Göster"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr ""
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Durum Çubuğunu Göster"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr ""
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr ""
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Dosya"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Oynatma"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "Çalma Listesi"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "Servisler"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "Çıktı"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "_Görünüm"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr ""
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "Ke_s"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Kopyala"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "_Yapıştır"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Tümünü_Seç"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr ""
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr ""
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr ""
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Kapatma Butonu Göster"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr ""
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr ""
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr ""
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK Arayüzü"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr ""
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "mono"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "stereo"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr ""
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Çalma Listesi modu"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Şarkıdan sonra duruyor."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Önceki parça"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Çal"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Ara ver/Devam et"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Dur"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Sonraki parça"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "5 saniye sonrası"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "5 saniye öncesi"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Sessiz"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Sesi aç"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Sesi kıs"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Dosyaya Atla"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr ""
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr ""
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr ""
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr ""
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr ""
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(hiçbiri)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -1933,37 +2015,37 @@ msgid ""
 "Do you want to continue?"
 msgstr ""
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr ""
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Genel Kısayol Eklentisi Ayarları"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr ""
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Kısayollar:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr ""
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "_Ekle"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr ""
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -1978,127 +2060,90 @@ msgid ""
 " Jeremy Tan <nsx at nsx.homeip.net>"
 msgstr ""
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "Jack Çıkış baglantısı"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr ""
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "Jack girişine baglantı saglanamadı %s.."
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
-msgstr ""
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s Ayarlar"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA Makine Ayarlari"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
-msgstr ""
+msgstr "Modül Yolu:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
 "After adding new paths, press Enter to scan for new plugins.</small>"
 msgstr ""
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Kullanılabilir Eklentiler:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Ä°zin ver"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Eklentilere Ä°zin ver:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Ayarlar"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 msgstr ""
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr ""
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: LIRC desteği başlatılamıyor\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: LIRC config dosyası okunamıyor\n"
-"%s: Lütfen LIRC dökümanlarını okuyunuz\n"
-"%s: uygun bir config dosyası nasıl yaratılır\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr ""
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: bilinmeyen komut  \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: LIRC bağlantısını kes\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
 msgstr ""
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2114,73 +2159,81 @@ msgid ""
 "For more information about LIRC, see http://lirc.org."
 msgstr ""
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr ""
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr ""
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr ""
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Hata"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Hata"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr ""
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
 msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr ""
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr ""
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Takt oluÅŸturucu: %d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Takt oluÅŸturucu: %d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2189,162 +2242,194 @@ msgid ""
 "or tact://60*3/4 to play 60 bpm in 3/4 tacts"
 msgstr ""
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
 msgstr ""
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 msgstr ""
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr ""
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Çıkış kanalları:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
+#: src/mms/mms.cc:35
+msgid "MMS Plugin"
 msgstr ""
 
-#: src/mms/mms.c:195
-msgid "MMS Plugin"
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
 msgstr ""
 
-#: src/modplug/plugin_main.c:55
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr ""
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "En Yakın (en hızlı)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Lineer (hızlı)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr ""
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr ""
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Seviye:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr ""
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr ""
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr ""
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr ""
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr ""
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr ""
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
 msgstr ""
 
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Surround"
-
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr ""
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>GeliÅŸmiÅŸ</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Surround"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr ""
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr ""
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Durdu"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious oynatmıyor."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr ""
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2364,55 +2449,64 @@ msgid ""
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 msgstr ""
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr ""
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Her zaman bildirim göster"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
 msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Göster"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Duraklat"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Sonraki Parça"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Varsayılan cihaz"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr ""
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Ses aygıtı:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Farklı aygıt kullan:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr ""
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr ""
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr ""
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2421,19 +2515,35 @@ msgid ""
 "Lindgren and of course the authors of the previous OSS plugin."
 msgstr ""
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "Çalma Listesi Düzenleyici"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "Girdiler"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "_Sil"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
 msgstr ""
 
-#: src/pls/pls.c:102
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr ""
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr ""
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2453,144 +2563,213 @@ msgid ""
 "USA."
 msgstr ""
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Önceki Parça"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Tekrar et"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Karıştır"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
 msgstr ""
 
-#: src/resample/resample.c:165
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr ""
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Lineer interpolasyon"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr ""
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Çeviri</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Metot:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Derece:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr ""
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr ""
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr ""
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:204
-msgid "192 kHz:"
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
 msgstr ""
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
+#: src/resample/resample.cc:241
+msgid "192 kHz:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "AÄŸ Sorunu."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Last.fm ile iletişimde bir sorun var. Lütfen daha sonra tekrar deneyin."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr ""
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr ""
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr ""
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2601,765 +2780,840 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr ""
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
 msgstr ""
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr ""
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 msgstr ""
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr ""
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr ""
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr ""
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
+msgid "%d result"
+msgid_plural "%d results"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr ""
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr ""
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr ""
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr ""
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr ""
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr ""
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "Dosya Aç ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "URL Aç ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr ""
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Çal"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Parça Listesi"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Görünüm"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "Hizmetler"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "Hakkında ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "Ayarlar ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "Çıkış"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "Şarkı Bilgisi ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Tekrar et"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Karıştır"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr ""
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "Şarkıdan Sonra Durdur"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Önceki Parça"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr ""
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr ""
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr ""
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "Çalma Listesini Oynat"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr ""
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Yeni Çalma Listesi"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "Çalma Listesini Yeniden Adlandır"
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "Çalma Listesini Kaldır"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "Önceki Çalma Listesi"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "Sonraki Çalma Listesi"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "Çalma Listesi İçe Aktar"
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "Çalma Listesi Dışa Aktar"
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "Çalma Listesi Yöneticisi"
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "Kuyruk Yöneticisi"
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "Çalma Listesini Yenile"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr ""
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Her Zaman Ãœstte"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr ""
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr ""
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr ""
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr ""
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr ""
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr ""
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr ""
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr ""
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Tümünü Sil"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr ""
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Bulunamayan Dosyaları Sil"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Birden Fazla Olanı Sil"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr ""
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Seçilenleri Kaldır"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Ara ve Seç"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr ""
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Hiçbiri Seçilmedi"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Tümünü_Seç"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
 msgstr ""
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr ""
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr ""
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr ""
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr ""
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
 msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Rastgele Listele"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr ""
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr ""
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Kısa Liste"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Kes"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Kopyala"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Yapıştır"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr ""
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr ""
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr ""
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr ""
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr ""
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr ""
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr ""
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr ""
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr ""
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Kaydet"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Yükle"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr ""
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr ""
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr ""
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr ""
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr ""
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr ""
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr ""
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr ""
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Oynatıcı"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr ""
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Arayüz yazı tipini seçiniz:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr ""
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr ""
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr ""
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Analiz Et"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr ""
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr ""
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Kapalı"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Normal"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "AteÅŸ"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr ""
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Çizgiler"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Çubuk"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "YavaÅŸ"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Orta"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Hızlı"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr ""
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr ""
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr ""
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr ""
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr ""
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr ""
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr ""
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr ""
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr ""
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Genel"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Görselleştirme"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Preamp"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr ""
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious Ekolayzır"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Zıpla %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Ses: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr ""
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr ""
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr ""
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Seçenekler Menüsü"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Devre dışı bırak 'Her Zaman Görünür' "
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Etkinleştir 'Her Zaman Görünür' "
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr ""
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr ""
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr ""
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr ""
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr ""
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Çalma Listesi modu"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Şarkıdan sonra duruyor."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr ""
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3367,57 +3621,61 @@ msgid ""
 "for."
 msgstr ""
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Başlık: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Albüm: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "DosyaAdı:"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Önceki aramaları temizle"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr ""
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr ""
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr ""
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr ""
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr ""
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3439,77 +3697,71 @@ msgid ""
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 msgstr ""
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
 msgstr ""
 
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
 msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
 msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
 msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Tamam"
-
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Şarkıyı değiştir"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Audacious yeni bir şarkı başlattığında çalışacak komut."
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Kabuğa yollanan parametreler tırnak içinde belirtilmeli. "
+"Aksi takdirde güvenlik sorunu yaratır. </span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "Komut:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Bir şarkının sonuna doğru çalışacak komut."
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Audacious parça listesinin sonuna ulaştığında çalıştırılacak komut."
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
 msgstr ""
-"Bir şarkı için başlık değiştiğinde çalıştırılacak komut (örneğin ağ yayını "
-"başlıkları)."
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3524,19 +3776,15 @@ msgid ""
 "%T: Track title"
 msgstr ""
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Kabuğa yollanan parametreler tırnak içinde belirtilmeli. "
-"Aksi takdirde güvenlik sorunu yaratır. </span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Komutlar"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3545,51 +3793,51 @@ msgid ""
 "Copyright 2010-2012 John Lindgren"
 msgstr ""
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Hızlı"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Düşük"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Yüksek"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Daha Yüksek"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Kalite:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Hız:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr ""
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr ""
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Durum iconu"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr ""
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3600,63 +3848,63 @@ msgid ""
 "the system tray area of the window manager."
 msgstr ""
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Mouse kaydırma hareketi</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Ses seviyesini deÄŸiÅŸtir"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Çalan şarkıyı değiştir"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>DiÄŸer Ayarlar</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Açılır pencereleri engelle"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Sistem tepsisinden çıkar"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr ""
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Durum iconu"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
 "By Johan Levin, 1999"
 msgstr ""
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr ""
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Ton OluÅŸturucu: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3665,15 +3913,11 @@ msgid ""
 "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone"
 msgstr ""
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr ""
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Ses yok etme"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3694,44 +3938,72 @@ msgid ""
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 msgstr ""
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis Çözücü"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTC Çözücü"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 msgstr ""
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTC Çözücü"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Wav Çözücü"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr ""
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr ""
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
 "Some of the plugin code was by Miles Egan."
 msgstr ""
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Wav Çözücü"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF Çözücü"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML Paylaşılabilir müzik listesi (XSPF)"
diff --git a/po/uk.po b/po/uk.po
index c9ce8cadf790..14fe61ad5a73 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -3,26 +3,27 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# Dennis <tymbood at gmail.com>, 2014-2015
 # Kostyantyn Fedenko <fedenko at ukr.net>, 2011
 # Kostyantyn Fedenko <fedenko at ukr.net>, 2011
-# StreamThreaedr <kvantarium at gmail.com>, 2012
+# Oleg <kvantarium at gmail.com>, 2012
 # NaiLi (aka jamesjames) Rootaerc <theism at mail.ru>, 2012
 # NaiLi (aka jamesjames) Rootaerc <theism at mail.ru>, 2012
 # Rax Garfield <admin at dvizho.ks.ua>, 2012
 # Rax Garfield (http://biokillaz.com/), 2012
 # Rax Garfield (http://biokillaz.com)/, 2012
 # Rax Garfield <admin at dvizho.ks.ua>, 2012
-# rustam <rustam.tsurik at gmail.com>, 2013
-# rustam <rustam.tsurik at gmail.com>, 2013
-# StreamThreaedr <kvantarium at gmail.com>, 2012
+# Rustam Tsurik <rustam.tsurik at gmail.com>, 2013
+# Rustam Tsurik <rustam.tsurik at gmail.com>, 2013
+# Oleg <kvantarium at gmail.com>, 2012
 # Yuri Chornoivan <yurchor at ukr.net>, 2012
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-11 16:24+0000\n"
-"Last-Translator: Radioactiveman <thomas-lange2 at gmx.de>\n"
+"POT-Creation-Date: 2015-04-03 11:52+0200\n"
+"PO-Revision-Date: 2015-03-07 09:36+0000\n"
+"Last-Translator: Dennis <tymbood at gmail.com>\n"
 "Language-Team: Ukrainian (http://www.transifex.com/projects/p/audacious/"
 "language/uk/)\n"
 "Language: uk\n"
@@ -32,40 +33,28 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "моно"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "стерео"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "об'ємний"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr ""
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
-msgstr ""
+msgstr "Декодер AAC (Raw)"
+
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (програвач AdLib)"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "послідовний"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (програвач AdLib)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "Будильник"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
-msgstr ""
+msgstr "Встановити Будильник..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -75,11 +64,7 @@ msgstr ""
 "\n"
 "Автори плаґіну-оригіналу: Adam Feakin, Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "Будильник"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -121,7 +106,7 @@ msgstr ""
 "⏎\n"
 "⏎\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -161,7 +146,7 @@ msgstr ""
 "Запускати цю команду при старті будильника.\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -185,383 +170,371 @@ msgstr ""
 "Введіть нагадування у полі та увімкніть⏎\n"
 "кнопку-прапорець, якщо ви хочете, щоб його було показано."
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "Вставай, Україно! Вставай, рідна ненько! Москаль вже годину не спить!"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "Нагадування на сьогодні..."
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "Повідомлення"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "Понеділок"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "Вівторок"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "Середа"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "Четвер"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "П’ятниця"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "Субота"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "Неділя"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "Налаштування будильника"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr ""
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr ""
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "Час"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "Починати о (типово):"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
-msgstr " "
+msgstr " г"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "Закінчити через:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "год"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "хв"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "Налаштуйте дні тижня, в які працюватиме будильник."
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "День"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "Як типово"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "Дні"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "Наростання"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "сек"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "Гучність"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "На початку:"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "По закінченню:"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "Як зараз"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "Виконувати команду"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "увімкнути"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "Список відтворення (необов’язково)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "Обрати список відтворення"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "Опції"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "Як це все налаштувати?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "Як налаштувати?"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "Обкладинка альбому"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr ""
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA-вивід"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Плаґін виводу ALSA,\n"
+"написаний Джоном Ліндґреном у 2010–2012 роках.\n"
+"\n"
+"Дякую авторові ALSA Output Plugin NG (William Pitcock), чий код допомагав, "
+"коли документації до ALSA було недостатньо."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr ""
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "Типовий PCM-прилад"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "Типовий мікшер"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM-пристрій:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "Мікшер:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "Елемент мікшера:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "Не зависати через «drain»-ваду ALSA"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI-програвач)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-msgstr ""
-"Плаґін виводу ALSA,\n"
-"написаний Джоном Ліндґреном у 2010–2012 роках.\n"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
 "\n"
-"Дякую авторові ALSA Output Plugin NG (William Pitcock), чий код допомагав, "
-"коли документації до ALSA було недостатньо."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA-вивід"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI-програвач)"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
+msgstr ""
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
-msgstr ""
+msgstr "Змінити типовий підсилювач на:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
-msgstr ""
+msgstr "Змінити типову поліфонію на:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
-msgstr ""
+msgstr "Змінити типову реверберацію:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
-msgstr ""
+msgstr "Увімк."
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
-msgstr ""
+msgstr "Змінити типовий хор:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
-msgstr ""
+msgstr "<b>Відтворення</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
+msgstr "Транспозиція: "
+
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
-msgstr ""
+msgstr "Зсув ударних: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
 msgstr ""
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
-msgstr ""
+msgstr "<b>Шрифт</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
-msgstr ""
-
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr ""
+msgstr "<b>Синтезатор</b>"
+
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr ""
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Гц"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - вибір файлу SoundFont"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "_Скасувати"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr ""
+msgstr "_Відкрити"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
-msgstr "Ім’я файлу"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
+msgstr "Назва файлу"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "Розмір (у байтах)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "Назва:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> Інформація MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "Назва:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "Тривалість (мс):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "Кількість доріжок:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "змінна"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "Темп (BMP):"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "Часовий код MIDI:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> Коментарі й слова пісні в MIDI </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* у цьому MIDI-файлі немає коментарів *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* у цьому MIDI-файлі немає слів пісні *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "_Закрити"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (недійсний UTF-8)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "Про плаґін AMIDI"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "Плагін AMIDI"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"Програвач музики в форматі MIDI\n"
-"написаний Джакомо Лоціто.\n"
-"\n"
-"<james at develia.org>\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"Клеменс Ладіш та Ярослав Кисела\n"
-"написали класні програми «aplaymidi» та «amixer»,\n"
-"що виявилися надзвичайно корисними\n"
-"при вивченні ALSA API,\n"
-"як і документація до alsa-lib.\n"
-"\n"
-"Альфредо Спадафіна\n"
-"створив гарненький логотип MIDI-клавіатури.\n"
-"\n"
-"Тоні Врун\n"
-"надав вагому допомогу з альфа-тестуванням."
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -571,152 +544,154 @@ msgid ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 msgstr ""
+"Audacious OSD\n"
+"http://www.develia.org/projects.php?p=audacious#aosd\n"
+"\n"
+"Автор Giacomo Lozito <james at develia.org>\n"
+"\n"
+"Частково заснована на бібліотеці Ghosd від Evan Martin:\n"
+"http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD-сповіщення"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "Прямокутник"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "Заокруглений прямокутник"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "Увігнутий прямокутник"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "Тільки текст"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "Відтворення"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "Показує повідомлення на початку відтворення."
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "Зміна назви"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
 msgstr ""
-"Показує повідомлення, коли під час відтворення змінюється назва доріжки, а "
-"ім’я файлу залишається старим. Це корисно при відтворенні потоків."
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "Пауза"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "Показує повідомлення при призупиненні відтворення."
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "Продовження"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "Показує повідомлення при продовженні відтворення."
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "Розташування"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "Відносний горизонтальний зсув:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Відносний вертикальний зсув:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "Максимальна ширина повідомлення:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "Опції для кількох моніторів"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "Показувати на:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "всіх моніторах"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "моніторі %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "Часова витримка (мс)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "Показ:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "Поява:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "Зникнення:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "Шрифти"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "Шрифт %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "Тінь"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "Показати стиль"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "Кольори"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "Колір %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "Задіяти спусковий гачок"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "Подія"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "Композитний "
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -726,112 +701,112 @@ msgstr ""
 "Якщо він не запущений, увімкніть його, інакше екранне меню працюватиме "
 "неправильно."
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "Композитний менеджер не потрібен для фальшивої прозорості"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "Прозорість"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "Фальшива прозорість"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "Справжня прозорість (потребує композитні розширення X)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Композитне розширення вимкнене"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Композитне розширення недоступне"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>OSD-повідомлення Audacious</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Налаштування повідомлень на екрані"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr ""
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "Розташування"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "Анімація"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "Текст"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "Оздоблення"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "Спусковий гачок"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "Різне"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "Тест"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
-msgstr ""
+msgstr "ASXv3 Плейлісти"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2-списки відтворення"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Списки відтворення Audacious (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>Колір</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "Осцилоскоп"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Перетворення стереозвуку в бінауральний за Бауером (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "Пресети:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "Рівень змішування каналів:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr ""
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "Частота зрізу:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "Пресети:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Перетворення стереозвуку в бінауральний за Бауером (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "Стовпці (аналізатор спектру)"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "Плаґін аудіодисків"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -851,171 +826,156 @@ msgstr ""
 "\n"
 "Цей проект брав участь у Google Summer of Code 2007."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>Пристрій</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "Швидкість читання:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "Перевизначення пристроїв:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Метадані</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "Використовувати CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "Використовувати CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "Використовувати HTTP замість CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "Сервер:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "Шлях:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "Порт:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "Плаґін аудіодисків"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "Не вдалося задіяти підсистему cdio."
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "Хибне посилання: %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "Доріжки %d не знайдено."
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "Доріжка %d — не музичні дані."
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "Не вдалося відкрити аудіовивід."
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "Стався збій при читанні аудіодиску."
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "Аудіодиск"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr ""
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "Не вдалося відкрити CD-пристрій %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "Не знайдено CD-пристрою з підтримкою аудіо."
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "Не вдалося задіяти відкритий CD-привід."
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "Не вдалося отримати номер першої/останньої доріжки."
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "Не вдалося прочитати LSN початку/кінця доріжки %d."
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "Не вдалося з’єднатися з cddb."
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "Не вдалося запитати сервер CDDB."
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "Не вдалося запитати сервер CDDB: %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "Не вдалося прочитати інформацію CDDB: %s."
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "Привід порожній."
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "Непідтримуваний тип диску."
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "Пункти меню для аудіодисків"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "Відтворити диск"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "Додати диск"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "Пункти меню для аудіодисків"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>Стиснення</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "Гучність центру:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "Динамічний діапазон:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Компресор звукового діапазону,\n"
-"написаний Джоном Ліндґреном у 2010–2012 роках."
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "Компресор звукового діапазону"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1031,204 +991,225 @@ msgstr ""
 "Автори — William Pitcock <nenolod at dereferenced.org>,\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "НЧ:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "ВЧ:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
-msgstr ""
+msgstr "Ехо:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "Типова тривалість пісні:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>Ресемплінг</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "Примусова передискретизація"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "Частота дискретизації:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Гц"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
-msgstr ""
+msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "Ігнорувати тривалість із теґів SPC"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "Посилити реверберацію"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "Декодер ігроконсольної музики"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
 msgstr ""
-"Збій при перехресному затиханні: композиції мають різну кількість каналів.\n"
-"Виправте це плаґіном-мікшером каналів."
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
 msgstr ""
-"Збій при перехресному затиханні: композиції мають різну частоту "
-"дискретизації.\n"
-"Виправте це плаґіном-конвертором частоти дискретизації."
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Перехресне затихання,\n"
-"написаний Джоном Ліндґреном у 2010–2012 роках."
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>Перехресне затихання</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "Перекриття:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr ""
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr ""
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "Перехресне затихання"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"Збій при перехресному затиханні: композиції мають різну кількість каналів.\n"
+"Виправте це плаґіном-мікшером каналів."
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"Збій при перехресному затиханні: композиції мають різну частоту "
+"дискретизації.\n"
+"Виправте це плаґіном-конвертором частоти дискретизації."
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Кристалізатор</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "Інтенсивність:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Кристалізатор"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Плаґін cue-листів"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "Видалення файлів"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
-msgstr ""
+msgstr "Помилка при переміщенні %s в смітник: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
-msgstr ""
+msgstr "Помилка при видаленні %s: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
-msgstr ""
+msgstr "Помилка при видаленні %s: це не локальний файл."
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
-msgstr ""
+msgstr "Ви хочете перемістити вибрані файли до смітника?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
-msgstr ""
+msgstr "Перемістити до смітника"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
-msgstr ""
+msgstr "Ви хочете безповоротно видалити вибрані файли?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "Вилучити"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "Скасувати"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr ""
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
-msgstr ""
+msgstr "Видалити вибрані файли"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
-msgstr ""
+msgstr "<b>Метод Видалення</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
+msgstr "Перемістити до смітника замість видалення відразу"
+
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
 msgstr ""
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>Відлуння</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "Затримка:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "мс"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "Сила:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "Гучність:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Луна,\n"
-"плаґін написаний у 1999 році (автор — Johan Levin)."
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "Відлуння"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "Плаґін FFmpeg"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1246,55 +1227,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "Плаґін FFmpeg"
-
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "Плаґін запису у файл"
+
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "Тип файлу виводу:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "Налаштування..."
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "Зберігати в теку оригіналу"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "Обрати теку самостійно"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "Зберігати вивід до:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "Вибір теки виводу"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "Назва файла:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr ""
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "за тегами доріжки"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr ""
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "за назвою файлу оригіналу"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "Не вирізати розширення оригіналу"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr ""
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "Номер доріжки на початку назви файлу"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr ""
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1328,166 +1309,169 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA"
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "Плаґін запису у файл"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "Авто"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "Об’єднане стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "Стерео"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "Моно"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "Налаштування MP3"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "_Гаразд"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "Швидкість стиснення:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
-msgstr "Частота дискретизації виводу:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
+msgstr ""
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
-msgstr "Гц"
+msgstr "(Гц)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "Сила стискання"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr ""
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "Бітрейт (Кбіт/с)"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "Коефіцієнт стиснення:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "Тип звуку:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "Різне:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr ""
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr ""
-"Примусова відповідність до ISO (для апаратних програвачів, більший розмір)"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "CRC-захист від збоїв (дещо менша якість)"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "Якість"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "Увімкнути змінний чи усереднений бітрейт"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "Тип бітрейту:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "Опції VBR (змінний бітрейт):"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "Мінімальний бітрейт (Кбіт/c):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "Максимальний бітрейт (Кбіт/c):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "Примусово встановити мінімальний бітрейт"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "Опції ABR (усереднений бітрейт):"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "Середній бітрейт (Кбіт/с):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "Рівень якості VBR (менше - краще):"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "Не писати VBR-заголовок («Xing»)"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr ""
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
-msgstr "Копірастія:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "«Під авторськими правами»"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "«Є оригіналом»"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
-msgstr "Параметри ID3:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
+msgstr ""
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "Примусово додавати теґ другої версії"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "Додавати лише v1-теґ"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "Додавати лише v2-теґ"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "Теґи"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Налаштування кодувальника Vorbis"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "Рівень якості (0-10, менше - краще):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "Декодер FLAC"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "без втрат"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1499,11 +1483,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "Декодер FLAC"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1511,11 +1491,19 @@ msgstr ""
 "Плаґін GIO,\n"
 "написаний Джоном Ліндґреном у 2010–2012 роках."
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "Плаґін GIO"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr ""
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr ""
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1526,450 +1514,518 @@ msgid ""
 "\n"
 "License: GPLv2+"
 msgstr ""
+"OpenGL Аналізатор Спектру для Audacious\n"
+"Авторське право 2013 Christophe Budé, John Lindgren, та Carlo Bramini\n"
+"\n"
+"На основі плаґіну для XMMS:\n"
+"Авторське право 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas "
+"Nilsson, та 4Front Technologies\n"
+"\n"
+"Ліцензія: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL аналізатор спектру"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr ""
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr ""
-"Плаґін надає можливість керувати відтворенням\n"
-"за допомогою клавіатурних скорочень GNOME.\n"
-"Автор у 2007–2008 роках — Sascha Hlusiak <contact at saschahlusiak.de>."
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Ярлики Gnome"
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "Номер у списку"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "Назва"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "Виконавець"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "Рік"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "Альбом"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "Виконавець альбому"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "Доріжка"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "Жанр"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "Позиція у черзі"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "Тривалість"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "Шлях до файлу"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "Назва файлу"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "Назва файлу"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "Бітова швидкість"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
-msgstr ""
+msgstr "Доступні колонки"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
-msgstr ""
+msgstr "Відображені колонки"
+
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "Пошуковий інструмент"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "Прикріпити зліва"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "Прикріпити справа"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "Прикріпити вгорі"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "Прикріпити внизу"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "Відкріпити"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "Вимкнути"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "Пошуковий інструмент"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "Відтворити _файли..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "Відтворити файли за _посиланням..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "_Додати файли..."
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "Додати файли _за посиланням..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr ""
+msgstr "Шукати в _бібліотеці"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "П_ро Audacious..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr ""
+msgstr "_Налаштування ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "_Вихід"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "_Відтворити"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "_Призупинити"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "_Зупинити"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "П_опередня"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "_Наступна"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "Повто_рювати"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "В_ипадково"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "Н_е просуватися списком"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "Зупинити після _цієї пісні"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "_Інформація про доріжку..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "Перейти до _часу..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "Перейти до _доріжки..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "Встановити точку повтору _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "Встановити точку повтору _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "_Скинути точки повтору"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "За _назвою"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "За _назвою файлу"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr ""
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "За _шляхом до файлу"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "_За номером доріжки"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "За _виконавцем"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "За а_льбомом"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr ""
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "За _датою видання"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr ""
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "За _тривалістю"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "За _шляхом до файлу"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "За назвою _файлу"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "_У зворотньому порядку"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "У випадковому по_рядку"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "Відтворити _цей список"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "_Відтворити/продовжити"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "_Оновити"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "_Сортувати"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr ""
+msgstr "Сортувати ви_бране"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "Видалити _дублікати"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "Прибрати _недоступні файли"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "_Новий"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "Пере_йменувати..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr ""
+msgstr "Видали_ти"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "_Імпортувати..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "_Експортувати..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "Керування списками _відтворення..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "Керування _чергою..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "З_більшити гучність"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "З_меншити гучність"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "_Еквалайзер"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr ""
+msgstr "Е_фекти..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "Показувати панель _меню"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "Показувати панель і_нформації"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "П_оказувати візуалізацію"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "Показувати рядок _стану"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "Показати час до _завершення"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr ""
+msgstr "_Візуалізації ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "_Файл"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "_Відтворення"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "_Список відтворення"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "С_лужби"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "В_ивід"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "Ви_гляд"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "_Елемент черги"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr ""
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "_Вирізати"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "_Копіювати"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "Вст_авити"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "Виді_лити все"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "Пере_йменувати..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
-msgstr ""
+msgstr "<b>Вкладки плейлисту</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
-msgstr ""
+msgstr "Завжди показувати вкладки"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
-msgstr ""
+msgstr "Показувати лічильник файлів"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
-msgstr ""
+msgstr "Показувати кнопку закриття"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
-msgstr ""
+msgstr "<b>Колонки плейлисту</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
-msgstr ""
+msgstr "Показувати заголовки колонок"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>Різне</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
-msgstr ""
+msgstr "Крок перемотування стрілками:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
-msgstr ""
+msgstr "Прокручувати плейлист при зміні доріжки"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "Інтерфейс GTK"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "Буферую..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "моно"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "стерео"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
@@ -1977,84 +2033,98 @@ msgstr[0] "%d канал"
 msgstr[1] "%d канали"
 msgstr[2] "%d каналів"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d кб/с"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "Однодоріжковий режим."
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "Режим списка відтворення."
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "Зупинити після цієї доріжки."
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "Попередня доріжка"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "Відтворити"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "Призупинити/продовжити"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "Зупинити"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "Наступна доріжка"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "На 5 секунд вперед"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "На 5 секунд назад"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "Вимкнути звук"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "Збільшити гучність"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "Зменшити гучність"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "Перейти до файлу"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "Перемкнути стан вікон програвача"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "Показати OSD-повідомлення"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "Перемкнути повтор"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "Перемкнути тасування"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "Перемкнути зупинку після поточної"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "Підняти вікна програвача"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(немає)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2065,15 +2135,11 @@ msgstr ""
 "\n"
 "Продовжувати попри це?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "Пов’язування кнопок миші"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "Налаштування гарячих клавіш"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2082,23 +2148,27 @@ msgstr ""
 "поля.\n"
 "Можна також прив’язувати кнопки миші."
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "Гарячі клавіші:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>Дія:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>Прив’язка до клавіш:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr ""
+msgstr "_Додати"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "Гарячі клавіші"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2125,60 +2195,51 @@ msgstr ""
 "Jeremy Tan <nsx at nsx.homeip.net>\n"
 "також брали участь у розробці."
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "Гарячі клавіші"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK-вивід"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
 msgstr ""
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
 msgstr ""
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
 msgstr ""
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
 msgstr ""
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
 msgstr ""
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"На основі xmms-jack від Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Автор портування до Audacious — Giacomo Lozito."
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK-вивід"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "Налаштування %s"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "Налаштування хосту LADSPA"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "Шляхи до модулів:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2188,25 +2249,25 @@ msgstr ""
 "Пошук відбувається за вказаними шляхами та змінною LADSPA_PATH.\n"
 "Вказавши шляхи, натисніть Enter для пошуку плаґінів.</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "Наявні плаґіни:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "Увімкнути"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "Увімкнені плаґіни:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "Налаштування"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2214,47 +2275,15 @@ msgstr ""
 "Хост LADSPA,\n"
 "написаний Джоном Ліндґреном у 2011 році."
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "Хост LADSPA"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: не можу ініціалізувати підтримку LIRC\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: не можу прочитати конфігураційний файл LIRC\n"
-"%s: прочитайте документацію до LIRC\n"
-"%s: як створити правильний конфигураційний файл\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: намагаюсь перез’єднатися...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: невідома команда «%s»\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: з’єднання з LIRC розірвано\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: намагаюся перез’єднатися кожні %d секунд...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Плаґін LIRC"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2283,73 +2312,81 @@ msgstr ""
 "\n"
 "http://lirc.org/"
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>З’еднання</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "Переприєднатись до LIRC серверу"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "Чекати перед перез’єднанням:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Плаґін LIRC"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "Плаґін LyricWiki"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "Тексту пісні не знайдено"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "Помилка"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "Не вдалося отримати %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "Помилка"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "Не вдалося проаналізувати %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "Шукаю текст пісні..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "Відсутні метадані пісні"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "З’єднуюся з lyrics.wikia.com..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "Плаґін LyricWiki"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr ""
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U-списки відтворення"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Генератор такту"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "Генератор такту: %d BPM"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "Генератор такту: %d BPM, %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2366,11 +2403,11 @@ msgstr ""
 "Наприклад, tact://77 — 77 ударів за хвилину,\n"
 "tact://60*3/4 — 60 ударів за хвилину з тактом 3/4."
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Генератор такту"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "Мікшер каналів"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2378,152 +2415,184 @@ msgstr ""
 "Мікшер каналів,\n"
 "написаний у 2011–2012 роках Джоном Ліндґреном та Michał Lipski."
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>Мікшер каналів</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "Каналів на виході:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "Мікшер каналів"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "Плаґін MMS"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr ""
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (програвач модулів)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>Роздільна здатність</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-біт"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-біт"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>Канали</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "Найближчий (найшвидший)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "Лінійний (швидкий)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "Сплайн (якісний)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "Поліфазний (найкращий)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
-msgstr "<b>Частота дискретизації</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
+msgstr ""
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 кГц"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 кГц"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 кГц"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 кГц"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "Рівень:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "Границя:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>Реверберація</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>Додатковий бас</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>Об’ємне звучання</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>Попереднє підсилення</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "Передискретизація"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "Зменшення шуму"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "Грати Amiga MOD-файли"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>Повторення</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "Кількість повторень:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "Для безкінечного повторення, встановіть кількість повторень в -1."
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (програвач модулів)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "Об’ємний звук"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr ""
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "Плаґін MPG123"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>Додаткові</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr ""
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "Об’ємний звук"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "Сервер MPRIS 2"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Плаґін Neon HTTP/HTTPS"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr ""
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr ""
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr ""
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr ""
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "Зупинено"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious нічого не відтворює."
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "Сповіщення"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2560,55 +2629,64 @@ msgstr ""
 "Ви мали отримати копію Загальної публічної ліцензії GNU разом із цією "
 "програмою. В іншому випадку, дивіться <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "Показати елементи керування відтворенням"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "Завжди показувати повідомлення"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "Сповіщення"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr ""
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "Показати"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "Призупинити відтворення"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "Наступна доріжка"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. Типовий прилад"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4-вивід"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr ""
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr ""
+
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "Аудіоприлад:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "Використати інший прилад:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "Зберігати гучність між сеансами."
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "Задіяти зміни формату, здійснені програмами OSS."
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "Діяти в ексклюзивному режимі, уникаючи віртуального мікшування."
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2623,19 +2701,35 @@ msgstr ""
 "Дякуємо #audacious, особливо Тоні Врунові, Джонові Ліндґрену й, звісно, "
 "авторам попереднього плаґіну OSS."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4-вивід"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr ""
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr ""
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr ""
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS-списки відтворення"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "Декодер OpenPSF PSF1/PSF2"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio-вивід"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2673,11 +2767,68 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA"
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio-вивід"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr ""
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr ""
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "Пошук"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr ""
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr ""
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr ""
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "Попередня доріжка"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "Повторювати"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "Випадково"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr ""
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "Конвертор частоти дискретизації"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2685,99 +2836,107 @@ msgstr ""
 "Конвертор частоти дискретизації,\n"
 "написаний Джоном Ліндґреном у 2010–2012 роках."
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "Пропуск/повтор фрагментів"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "Лінійна інтерполяція"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "Швидка sinc-інтерполяція"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "Звичайна sinc-інтерполяція"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "Найкраща sinc-інтерполяція"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>Конвертування</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "Метод:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "Частота:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>Схема конвертування</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "Конвертувати за схемою:"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 кГц:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 кГц:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 кГц:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 кГц:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 кГц:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 кГц:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 кГц:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 кГц:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 кГц:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 кГц:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "Конвертор частоти дискретизації"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "Ок. Скроблінг для користувача: %s"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "Відмовлено у доступі"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr ""
 "Відвідайте наступне посилання щоб дозволити Audacious скроблінг ваших "
 "доріжок:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr ""
 "Лишіть це вікно відкритим та ще раз натисніть 'Перевірити права доступу'.\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2785,34 +2944,38 @@ msgstr ""
 "Не хвилюйтесь. Дані для скроблінгу збережені на комп’ютері.\n"
 "Вони будуть відправлені, як тільки Audacious'у буде дозволено це зробити."
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "Проблема мережі."
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr ""
 "Виникла проблема зі з’єднанням до Last.fm. Будь ласка спробуйте пізніше."
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "Перевірка..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "П_еревірити права доступу"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "_Видалити права доступу"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr ""
 "Вам потрібно дозволити Audacious скроблити доріжки у ваш акаунт на Last.fm.\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Скроблер 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2820,7 +2983,7 @@ msgstr ""
 "Модуль скроблера не може бути запущений.\n"
 "Можливо це проблема з встановленою програмою."
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2838,11 +3001,7 @@ msgstr ""
 "цього проекту.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Скроблер 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2850,7 +3009,11 @@ msgstr ""
 "На даний час Audacious використовує покращену версію скробблера Last.fm.⏎\n"
 "Будь-ласка перевірте Налаштування для плаґіна Scrobbler."
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL-вивід"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2858,88 +3021,59 @@ msgstr ""
 "Плаґін виводу в SDL,\n"
 "написаний Джоном Ліндґреном у 2010 році."
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL-вивід"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "Бібліотека"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "Невідомий виконавець"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "Невідомий альбом"
-
-#: src/search-tool/search-tool.c:625
-#, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"від %s по %s"
-
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d альбом"
-msgstr[1] "%d альбоми"
-msgstr[2] "%d альбомів"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
 
-#: src/search-tool/search-tool.c:633
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
 msgstr[0] ""
-"%s\n"
-" %s, %d пісня"
 msgstr[1] ""
-"%s\n"
-" %s, %d пісні"
 msgstr[2] ""
-"%s\n"
-" %s, %d пісень"
 
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
+msgid "%d song"
+msgid_plural "%d songs"
 msgstr[0] ""
-"%s\n"
-" %d пісня по %s"
 msgstr[1] ""
-"%s\n"
-" %d пісні по %s"
 msgstr[2] ""
-"%s\n"
-" %d пісень по %s"
 
-#: src/search-tool/search-tool.c:675
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr ""
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "_Створити список відтворення"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "_Додати до списку відтворення"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "Шукати в бібліотеці"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
@@ -2947,679 +3081,769 @@ msgstr ""
 "Щоб імпортувати свою музичну бібліотеку до Audacious, виберіть теку й "
 "натисніть на значок оновлення."
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "Зачекайте..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "Вибрати теку"
 
-#: src/skins/menus.c:56
-msgid "Open Files ..."
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "Програвач SID"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr ""
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr ""
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr ""
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr ""
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr ""
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr ""
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr ""
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr ""
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr ""
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr ""
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr ""
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr ""
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
 msgstr ""
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:64
+msgid "Open Files ..."
+msgstr "Відкрити файли..."
+
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
+msgstr "Відкрити адресу..."
+
+#: src/skins/menus.cc:66
+msgid "Search Library"
 msgstr ""
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "Відтворення"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "Список відтворення"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "Перегляд"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
-msgstr ""
+msgstr "Служби"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
-msgstr ""
+msgstr "Про ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
-msgstr ""
+msgstr "Налаштування ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
-msgstr ""
+msgstr "Вихід"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
-msgstr ""
+msgstr "Інформація про доріжку..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "Повторювати"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "Випадково"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "Не просуватися у списку відтворення"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
-msgstr ""
-
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "Попередня доріжка"
+msgstr "Зупинити після цієї доріжки"
 
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
-msgstr ""
+msgstr "Встановити A-B повтор"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
-msgstr ""
+msgstr "Скинути A-B повтор"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
-msgstr ""
+msgstr "Перейти до доріжки..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
-msgstr ""
+msgstr "Перейти до часу..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr ""
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "Відтворити/продовжити"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "Новий список відтворення"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
-msgstr ""
+msgstr "Перейменувати список..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
-msgstr ""
+msgstr "Видалити список"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
-msgstr ""
+msgstr "Попередній список"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
-msgstr ""
+msgstr "Наступний список"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
-msgstr ""
+msgstr "Імпортувати список відтворення..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
-msgstr ""
+msgstr "Експортувати список відтворення..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
-msgstr ""
+msgstr "Керування списками відтворення..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
-msgstr ""
+msgstr "Керування чергою..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
-msgstr ""
+msgstr "Оновити список відтворення"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "Показати редактор списків відтворення"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "Показати еквалайзер"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
-msgstr ""
+msgstr "Показати час до завершення"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "Завжди згори"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
-msgstr ""
+msgstr "На всіх робочих столах"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
-msgstr ""
+msgstr "Згорнути плеєр"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
-msgstr ""
+msgstr "Згорнути редактор списку відтворення"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
+msgstr "Згорнути еквалайзер"
+
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
 msgstr ""
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
-msgstr ""
+msgstr "Додати адресу..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
-msgstr ""
+msgstr "Додати файли..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "За назвою"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "За ім’ям файлу"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr ""
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
-msgstr ""
+msgstr "За шляхом до файлу"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "Вилучити всі"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "Очистити чергу"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "Прибрати недоступні файли."
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "Видалити дублікати"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "Вилучити невідмічені "
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "Вилучити виділені"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "Пошук і виділення"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "Інвертувати виділення"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "Зняти виділення"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "Виділити все"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "За альбомом"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "За номером доріжки"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "За виконавцем"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "За альбомом"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "За виконавцем альбому"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
+msgstr "За датою видання"
+
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
 msgstr ""
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "За номером доріжки"
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr ""
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr ""
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "Порушити порядок"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "Обернути список"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "Сортувати виділене"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "Сортувати список..."
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "Вирізати"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "Копіювати"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "Вставити"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
-msgstr ""
+msgstr "В чергу/З черги"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
-msgstr ""
+msgstr "Завантажити пресет..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
-msgstr ""
+msgstr "Завантажити авто-пресет..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
-msgstr ""
+msgstr "Завантажити за замовчуванням"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
-msgstr ""
+msgstr "Завантажити пресет із файлу..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
-msgstr ""
+msgstr "Завантажити EQF файл.."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
-msgstr ""
+msgstr "Зберегти пресет..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
-msgstr ""
+msgstr "Зберегти авто-пресет..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
-msgstr ""
+msgstr "Зберегти за замовчуванням"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
-msgstr ""
+msgstr "Зберегти пресет до файлу..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
-msgstr ""
+msgstr "Зберегти EQF файл..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
-msgstr ""
+msgstr "Видалити пресет..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
-msgstr ""
+msgstr "Видалити авто-пресет..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
-msgstr ""
+msgstr "Імпортувати пресети WinAMP..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
-msgstr ""
+msgstr "Скинути на нуль"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Класичний інтерфейс Winamp"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "Зберегти"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "Завантажити"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
-msgstr ""
+msgstr "Завантажити пресет із файлу"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
-msgstr ""
+msgstr "Завантажити EQF файл"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
-msgstr ""
+msgstr "Зберегти пресет до файлу"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
-msgstr ""
+msgstr "Зберегти EQF файл"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
-msgstr ""
+msgstr "Імпортувати пресети WinAMP"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "Типові налаштування"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "Вибір пресету"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "Завантажити відповідний доріжці пресет"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "Збереження пресету"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "Зберегти пресет як відповідний доріжці"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "Видалення пресету"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "Видалити відповідний доріжці пресет"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "_Програвач"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "Програвач:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "Шрифт основного вікна програвача"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "_Список відтворення"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "Плейлист:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "Шрифт списку відтворення:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
-msgstr ""
+msgstr "<b>Оболонка</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
-msgstr ""
+msgstr "<b>Шрифти</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "Використовувати растрові шрифти (підтримується тільки ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
-msgstr ""
+msgstr "Прокручувати назву пісні"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "Прокручувати назву пісні в обох напрямках"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "Аналізатор"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "Осцилограф"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
-msgstr ""
+msgstr "Спектрограма / VU-вимірювач"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "Вимкнено"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "Звичайний"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "Вогонь"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
-msgstr ""
+msgstr "Вертикальні лінії"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "Лінії"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "Стовпчики"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "Дуже повільне"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "Повільне"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "Помірне"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "Швидке"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "Дуже швидке"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
-msgstr ""
+msgstr "Точки"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
-msgstr ""
+msgstr "Лінія"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
-msgstr ""
+msgstr "Суцільна"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "Лід"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "Плавний"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
-msgstr ""
+msgstr "<b>Тип</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
-msgstr ""
+msgstr "Тип візуалізації:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
-msgstr ""
+msgstr "<b>Аналізатор</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
-msgstr ""
+msgstr "Показувати піки"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
-msgstr ""
+msgstr "Забарвлення:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
-msgstr ""
+msgstr "Стиль:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
-msgstr ""
+msgstr "Спад"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
-msgstr ""
+msgstr "Спад піку:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
-msgstr ""
+msgstr "Стиль осцилограми:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
-msgstr ""
+msgstr "Забарвлення спектрограми:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
-msgstr ""
+msgstr "Стиль VU-вимірювача:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "Загальне"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "Візуалізація"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "Попередній підсилювач"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Гц"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 кГц"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 кГц"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Еквалайзер Audacious"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "Перехід до %d:%-2.2d / %d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "Гучність: %d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "Баланс: %d%% вліво"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "Баланс: центр"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "Баланс: %d%% вправо"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "Меню опцій"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "Вимкнути відображення над іншими вікнами"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "Відображати над іншими вікнами"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "Редактор інформації про доріжку"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr ""
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "Точку повтору A встановлено."
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "Точку повтору B встановлено."
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "Точки повтору скинуті."
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "Однодоріжковий режим."
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "Режим списка відтворення."
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "Зупинити після цієї доріжки."
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "Пошук в активному списку відтворення"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr ""
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3630,57 +3854,61 @@ msgstr ""
 "Можна використовувати літери, цифри, інші знаки, регулярні вирази. Поля "
 "нечутливі до регістру."
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
-msgstr "Назва: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
-msgstr "Альбом: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
-msgstr "Виконавець: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "Ім’я файлу: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr ""
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "Зняти попереднє виділення перед пошуком"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "Автоматично перемикати стан черги знайдених елементів"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "Виділити знайдене в новий список відтворення"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Редактор списків відтворення Audacious"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d із %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "Заархівований жупан Winamp 2.x"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "Неархівований жупан Winamp 2.x"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "Неможливо створити теку (%s): %s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Плаґін Sndfile"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3723,78 +3951,71 @@ msgstr ""
 "Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA "
 "02110-1301, USA"
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Плаґін Sndfile"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "Про плаґін виводу Sndio"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr ""
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr "Плаґін виводу Sndio, за авторством Thomas Pfaff <tpfaff at tp76.info>.\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr ""
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "Непідтримуваний формат"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr ""
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
 msgstr ""
-"Формат не підтримується аудіопристроєм.\n"
-"\n"
-"Спробуйте ще раз, запустивши сервер sndiod(1)."
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "Пристрій Sndio"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(порожнє — типове)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr ""
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "Гаразд"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr ""
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "Зміна доріжки"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "Виконувати на початку відтворення доріжки:"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>Параметри подавати слід у лапках. Робити інакше "
+"небезпечно для системи.</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr ""
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr " "
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr ""
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "Виконувати наприкінці відтворення доріжки:"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr ""
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "Виконувати при досягненні кінця списка відтворення:"
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr ""
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "Виконувати при зміні назви доріжки (онлайн-потоки тощо):"
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr ""
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3808,34 +4029,16 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"Ви можете використовувати наступні шаблони\n"
-"(для команди на кінець списку підходять не всі)\n"
-"\n"
-"%F: Частота (Гц)\n"
-"%c: Кількість каналів\n"
-"%f: Ім’я файла (повний шлях)\n"
-"%l: Довжина (мс)\n"
-"%n чи %s: Назва композиції\n"
-"%r: Швидкість (біт/с)\n"
-"%t: Позиція в списку відтворення (%02d)\n"
-"%p: Зараз грає (1 or 0)\n"
-"%a: Виконавець\n"
-"%b: Альбом\n"
-"%T: Назва доріжки"
-
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
+
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
 msgstr ""
-"<span size='small'>Параметри подавати слід у лапках. Робити інакше "
-"небезпечно для системи.</span>"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "Команди"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "Ресемплер SoX"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3849,51 +4052,51 @@ msgstr ""
 "Базується на коді модуля Sample Rate Converter:\n"
 "Авторське право 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "Швидка"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "Низька"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "Висока"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "Дуже висока"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "Якість:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "Ресемплер SoX"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "Швидкість та висота"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>Швидкість та висота</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "Швидкість:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "Висота:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "Швидкість та висота"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "Значок у лотку"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr ""
+msgstr "Н_алаштування ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3908,39 +4111,39 @@ msgstr ""
 "2005–2007 — Джакомо Лоціто <james at develia.org>\n"
 "2010 — Michał Lipski <tallica at o2.pl>"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>Дія коліщатка миші</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "Зміна гучності"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "Зміна поточної доріжки"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>Інші налаштування</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "Вимкнути спливне вікно"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "Замість закриття згортати до лотка"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "Просуватися списком відтворення при прокручуванні догори"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "Значок у лотку"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Розширене стерео"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3949,24 +4152,24 @@ msgstr ""
 "Розширене стерео,\n"
 "плаґін написаний у 1999 році (автор — Johan Levin)."
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Розширене стерео</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Розширене стерео"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Генератор тону"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Гц"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "Генератор тону: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3984,15 +4187,11 @@ msgstr ""
 "Наприклад, tone://2000;2005 — послідовне відтворення тонів з частотою 2000 "
 "Гц і 2005 Гц."
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Генератор тону"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "Видалення голосу"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -4030,11 +4229,35 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Декодер Ogg Vorbis"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr ""
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "Декодер VTX"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4045,19 +4268,19 @@ msgstr ""
 "\n"
 "Плаґін для Audacious створив Павел Виметалек <pvymetalek at seznam.cz>."
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "Декодер VTX"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "Декодер WavPack"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "зі втратами (гібрид)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "зі втратами"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4067,14 +4290,18 @@ msgstr ""
 "\n"
 "Деякий код написав Майлс Еґан."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "Декодер WavPack"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "Декодер 2SF"
 
-#: src/xspf/xspf.c:438
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr ""
+
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr ""
+
+#: src/xspf/xspf.cc:89
 msgid "XML Shareable Playlists (XSPF)"
 msgstr "XML-списки відтворення (XSPF)"
diff --git a/po/update-potfiles.sh b/po/update-potfiles.sh
index ace2d5c30339..437cd13e8f9b 100755
--- a/po/update-potfiles.sh
+++ b/po/update-potfiles.sh
@@ -2,4 +2,5 @@
 rm POTFILES*
 echo "# Please don't update this file manually - use ./update-potfiles.sh instead!" > POTFILES.in
 cd ..
-find src/ \( -name "*.c" -o -name "*.cxx" -o -name "*.cc" -o -name "*.glade" \) -exec grep -lE "translatable|_\(" \{\} \; | sort | uniq >> po/POTFILES.in
+find src/ \( -name "*.c" -o -name "*.h" -o -name "*.cxx" -o -name "*.cc" -o -name "*.glade" \) \
+  -exec grep -lE "translatable|_\(" \{\} \; | sort | uniq >> po/POTFILES.in
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 0979900f8b93..2a76fefcb142 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -3,22 +3,30 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
+# 周嘉韡 <btchina at live.com>, 2013
 # Chasye <chasye at gmail.com>, 2010
 # yinsigan <ganweiliang886 at gmail.com>, 2012
-# JeffBai <jeffbaichina at members.fsf.org>, 2014
-# michaeljayt <michaeljayt at gmail.com>, 2013
+# 白铭骢 <jeffbaichina at members.fsf.org>, 2014
+# 白铭骢 <jeffbaichina at members.fsf.org>, 2014
 # Luke <runningwaterpro at gmail.com>, 2012
-# sd542927172 <sd542927172 at live.cn>, 2013
-# min zhang <zm1990s at gmail.com>, 2014
-# min zhang <zm1990s at gmail.com>, 2013
-# 4679kun <btchina at live.com>, 2013
+# Michael Jay Tong <michaeljayt at gmail.com>, 2013
+# Michael Jay Tong <michaeljayt at gmail.com>, 2013-2014
+# zhangmin <zm1990s at gmail.com>, 2013-2014
+# Luke <runningwaterpro at gmail.com>, 2012
+# shan dong <sd542927172 at live.cn>, 2013
+# shan dong <sd542927172 at live.cn>, 2013
+# yinsigan <ganweiliang886 at gmail.com>, 2012
+# zhangmin <zm1990s at gmail.com>, 2013-2015
+# zhangmin <zm1990s at gmail.com>, 2013
+# 周嘉韡 <btchina at live.com>, 2013
+# 蒋浩海 <jhaohai at foxmail.com>, 2014
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-12 08:18+0000\n"
-"Last-Translator: min zhang <zm1990s at gmail.com>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-05 10:15+0000\n"
+"Last-Translator: zhangmin <zm1990s at gmail.com>\n"
 "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/"
 "audacious/language/zh_CN/)\n"
 "Language: zh_CN\n"
@@ -27,40 +35,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "单声道"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "立体声"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "环绕声"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) 解码器"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) 解码器"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib 播放器)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "è¿žç»­çš„"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib 播放器)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "闹钟"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "设置闹钟"
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -70,11 +66,7 @@ msgstr ""
 "\n"
 "最初由 Adam Feakin 和 Daniel Stodden 编写。"
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "闹钟"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -112,7 +104,7 @@ msgstr ""
 "选择闹铃时间,或者点按开关按钮以使用默认时间。\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -149,7 +141,7 @@ msgstr ""
 "在设定的时间运行命令。\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -170,383 +162,390 @@ msgstr ""
 "在闹铃响后显示一个备忘录。\n"
 "在此输入框输入备忘录并打开开关按钮。"
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "此为起床闹钟"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "你今日的备忘录是……"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "提醒器"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "星期一"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "星期二"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "星期三"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "星期四"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "星期五"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "星期六"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "星期日"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "闹钟设置"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "好的 (&O)"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "取消 (&C)"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "时间"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "响闹钟 (默认) : "
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "点"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "静音时间:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "小时"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "分"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "选择响闹钟的日期"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "日期"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "默认"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "日期"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "渐隐"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "秒"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "音量"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "开始于"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "完成于"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "当前"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "附加命令"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "启用"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "播放列表(可选)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "选择一个播放列表"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "选项"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "这些选项代表什么?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "帮助"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "专辑封面"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "专辑封面(Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA 输出"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"Audacious 的 ALSA Output 插件\n"
+"版权所有 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(无描述)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "默认 PCM 设备"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "默认混音设备"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM 设备:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "混音设备"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "混音单元:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "尝试解决音频输出不畅"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI 播放器)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"Audacious 的 ALSA Output 插件\n"
-"版权所有 2009-2012 John Lindgren\n"
+"AMIDI-插件\n"
+"模块化 MIDI 音乐播放器\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA 输出"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI 播放器)"
+"作者: Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"特别感谢...\n"
+"\n"
+"Clemens Ladisch , Jaroslav Kysela\n"
+"编写的超帅的 aplaymidi 和 amixer;这两个\n"
+"以及 alsa-lib docs 对我们学习 ALSA API 有很大帮助\n"
+"\n"
+"\n"
+"Alfredo Spadafina\n"
+"贡献了很漂亮的 midi 键盘标志\n"
+"\n"
+"Tony Vroon\n"
+"帮助我们进行测试"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "覆盖默认增益: "
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "覆盖默认复调: "
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "覆盖默认回响: "
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "开启"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "覆盖默认和声: "
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>回放</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "转置: "
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "半音"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "鼓移: "
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>高级设置</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "音符数字"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "从 MIDI 文件释放备注"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "跳过开头的静音"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "从 MIDI 文件释放歌词"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "跳过尾部静音"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>合成器</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
-msgstr "取样率:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
+msgstr "采样率:"
+
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "赫兹"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - 选择SoundFont文件"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "取消 (_C)"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
-msgstr "打开 (&O)"
+msgstr "打开 (_O)"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "文件名"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "大小(bytes)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "名称:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI 信息 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "格式:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "长度(毫秒):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "音轨数:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "变体"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "每分钟节拍: "
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "每分钟节拍 (wavg): "
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "时间格: "
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI备注与歌词</span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* MIDI文件不包含备注 *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* MIDI文件不包含歌词 *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "关闭(_C)"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (非法的UTF-8编码)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "关于AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"模块化的 MIDI 音乐播放器\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"由 Giacomo Lozito 编写\n"
-"<james at develia.org>\n"
-"\n"
-"特别鸣谢……\n"
-"\n"
-"Clemens Ladisch 及 Jaroslav Kysela\n"
-"为他们炫酷的程序如 aplaymidi 以及 amixerl; 这些软件相当有用,与 alsa-lib 的文"
-"档配合以便深入学习 ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"为 Ta 漂亮的 MIDI 键盘图标\n"
-"\n"
-"Tony Vroon\n"
-"为他在 Alpha 测试阶段提供的帮助"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -564,151 +563,146 @@ msgstr ""
 "部分基于 Evan Martin 的 Ghosd 库:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (On-Screen Display)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "方角矩形"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "圆角矩形"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "凹角矩形"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "æ— "
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "播放开始"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "开始播放时触发OSD"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "标题改变"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"播放同一文件时,标题发生改变时触发OSD。\n"
-"播放网络媒体时会经常碰到。"
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "在曲目标题改变时触发 OSD(用于互联网流媒体)。"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "暂停播放"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "暂停播放时触发OSD"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "恢复播放"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "恢复播放时触发OSD"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X相对位移:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y相对位移:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "最大OSD宽度:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "多屏选项"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "OSD显示于:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "所有显示器"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "显示器%i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "延时(ms)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "显示:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "淡入:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "淡出:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "字体"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "字体 %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "阴影"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "渲染风格"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "颜色"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "颜色  %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "启用触发器"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "事件"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "检测到混合管理器"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -717,112 +711,112 @@ msgstr ""
 "未检测到混合管理器;\n"
 "OSD无法正常工作,除非你激活混合管理器。"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "假透明无需混合管理支持"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "透明"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "假透明"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "真透明(需要X Composite扩展)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "X Composite扩展未加载"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "X Composite扩展不可用"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - 设置"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "测试 (&T)"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "设置 (&S)"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "动画"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "字体"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "装饰器"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "触发器"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "其它"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "测试"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 播放列表"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 播放列表"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious 播放列表 (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>颜色</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "模糊范围"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer 立体双声(BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "预置:"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "评级: "
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "截止频率: "
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "预置:"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer 立体双声(BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "频谱分析器"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "音频 CD 插件"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -842,171 +836,158 @@ msgstr ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>设备</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "读取速度:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "覆盖设备:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>Metadata</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "使用 CD 文本"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "使用 CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "使用HTTP代替CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "服务器:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "路径:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "端口:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "音频 CD 插件"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "初始化 cdio 子系统失败。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "无效的 URI %s。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "未找到音轨 %d。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "磁道 %d 是一个数据磁道"
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "打开音频输出失败。"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "读取音频 CD 时出错。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "音频CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "音轨 %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "打开 CD 设备 %s 失败。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "没有找到合适的 CD 音频驱动器。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "完成打开的 CD 驱动器初始化失败。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "取得第一首/最后一首音频音轨号失败。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "不能读取音频 %d 开始/结束的 LSN 信息。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "创建 CDDB 连接失败。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "查询 CDDB 服务器失败"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "查询 CDDB 服务器失败:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "读取 CDDB 信息失败:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "设备为空"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "未支持光盘类型"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "音频 CD 目录项"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "播放CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "添加CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "音频 CD 目录项"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>压缩</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "中间音量:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "动态范围:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Audacious 的 Dynamic Range Compression 插件\n"
-"版权所有 2010-2012 John Lindgren"
+"Audacious 动态范围压缩插件\n"
+"John Lindgren 2010-2014 版权所有"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "动态范围压缩"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1023,207 +1004,237 @@ msgstr ""
 "Shay Green <gblargg at gmail.com>\n"
 "编写"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "低音:"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "高音:"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "回响: "
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "默认歌曲长度:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>重取样</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "启用音频重采样"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "采样率:"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "赫兹"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "忽略SPC标签显示的长度"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "延长余响"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "游戏机音乐解码器"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"淡出失败, 原因:歌曲的通道数不一致。\n"
-"\n"
-"你可以尝试使用”声道混音器“使歌曲的通道数保持一致。"
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio 输出"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"淡出失败, 原因:歌曲的采样率不一致。\n"
+"Audacious CoreAudio 输出插件\n"
+"William Pitcock 2014 版权所有\n"
 "\n"
-"你可以尝试使用”采样率转换器“使歌曲的采样保持一致。"
+"基于 Audacious SDL 输出插件\n"
+"John Lindgren 2010 版权所有"
 
-#: src/crossfade/crossfade.c:256
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "使用排除模式"
+
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
-"Audacious 的淡出插件\n"
-"版权所有 2010-2012 John Lindgren"
+"Audacious Crossfade 插件\n"
+"John Lindgren 2010-2014 版权所有"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>淡出</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "在自动切换歌曲时"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "重叠:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "在定位或者手动改变歌曲时"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>提示</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr "为了让淡出更好地工作,启用静音移除特效"
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "淡出"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"淡出失败, 原因:歌曲的通道数不一致。\n"
+"\n"
+"你可以尝试使用”声道混音器“使歌曲的通道数保持一致。"
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"淡出失败, 原因:歌曲的采样率不一致。\n"
+"\n"
+"你可以尝试使用”采样率转换器“使歌曲的采样保持一致。"
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>保真音效</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "强度:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue 表插件"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "删除文件"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "将 %s 移动至垃圾箱时出错: %s."
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "删除 %s 时出错: %s."
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "删除 %s 时出错: 不是一个本地文件。"
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "你希望将选中的文件移至垃圾箱吗?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "移至垃圾箱"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "你希望永久删除选中的文件吗?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "删除"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "取消"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "删除文件"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "删除选中的文件"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>删除方式</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "移动到垃圾箱而不是直接删除"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"回音插件\n"
+"作者: Johan Levin, 1999\n"
+"环绕回声,作者: Carl van Schaik, 1999\n"
+"由 William Pitcock 和 John Lindgren 修改后用于 Audacious, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>回响</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "延迟:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "毫秒"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "反馈:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "音量:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"回响插件\n"
-"作者 Johan Levin 1999.\n"
-"\n"
-"回音环绕 作者 Carl van Schaik 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "回响"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg 插件"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1240,55 +1251,55 @@ msgstr ""
 "Matti Hämäläinen <ccr at tnsp.org>\n"
 "编写"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg 插件"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "FileWriter 插件"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "输出文件格式:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "设置"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "保存到原来的目录"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "保存到自定义目录"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "输出文件目录:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "选择目录"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "文件名来自:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "文件名生成来源:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
 msgstr "原始文件标签"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
 msgstr "原始文件名"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "保留文件后缀"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "包含原始文件的扩展名"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
 msgstr "文件名前加上音轨号"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1320,165 +1331,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "FileWriter 插件"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "自动"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "联合立体声"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "立体声"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "单声道"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3设置"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "好的 (_O)"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "音质"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "输出取样:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(赫兹)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
 msgstr "码率/压缩率:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "码率(kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "压缩率:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "音频模式:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "其它:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "杂项:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
 msgstr "强制严格遵从ISO"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "错误保护"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "质量"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "启用VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "类型:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR选项:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "最小码率(kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "最大码率(kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "严格执行最小码率"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR选项:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "平均码率(kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR质量等级:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "不要写入Xing VBR头"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "忽略Xing VBR头"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "帧参数:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "标记为版权"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "标记为原始文件"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3参数:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "强制添加V2标签"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "仅添加v1标签"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "仅添加v2标签"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "标签"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis编码器设置"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "质量等级(0-10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC 解码器"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "无损的"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1490,11 +1505,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC 解码器"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1502,11 +1513,19 @@ msgstr ""
 "Audacious 的 GIO 插件\n"
 "版权所有 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO 插件"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "读取-追加模式不受支持"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "打开模式不可用"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1526,533 +1545,619 @@ msgstr ""
 "\n"
 "许可: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL 频谱分析器"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
+msgid ""
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
+msgstr ""
+"Audacious OpenGL 频谱图分析器\n"
+"Christophe Budé, John Lindgren, Carlo Bramini. 2013 版权所有\n"
+"William Pitcock. 2014 版权所有\n"
+"\n"
+"基于 XMMS 插件:\n"
+"Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson,4Front Technologies. "
+"1998-2000 版权所有\n"
+"\n"
+"许可: GPLv2+"
+
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL 频谱分析器(Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
+msgstr "GNOME 快捷键"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 msgstr ""
-"GNOME 快捷方式插件\n"
+"GNOME 快捷键插件\n"
 "让你使用 GNOME 快捷键来控制播放器。\n"
 "\n"
 "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
-msgstr "Gnome 快捷键"
-
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "序号"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "标题"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "艺术家"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "年份"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "专辑"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "专辑艺术家"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "音轨"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "流派"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "队列位置"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "长度"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "文件路径"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "文件名"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "自定标题"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "比率"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "可用列"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "显示列"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "搜索工具"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "面板在左"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "面板在右"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "面板在上"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "面板在下"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "无面板"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "禁用"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "搜索工具"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
-msgstr "打开文件(_O) ..."
+msgstr "打开文件...(_O)"
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
-msgstr "打开URL(_U)..."
+msgstr "打开URL...(_U)"
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
-msgstr "添加文件"
+msgstr "添加文件(_A)"
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
-msgstr "添加URL(_R)..."
+msgstr "添加URL...(_R)"
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
-msgstr "搜索库 (&L)"
+msgstr "搜索库 (_L)"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "关于(_b)"
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
-msgstr "设置 ... (&S)"
+msgstr "设置 ... (_S)"
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "退出(_Q)"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "播放(_P)"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "暂停(_e)"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "停止(_S)"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "上一首(_v)"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "下一首(_N)"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "重复(_R)"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "随机(_h)"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "禁止自动播放下一首(_o)"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "在这首歌后停止"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
-msgstr "歌曲信息(_I)..."
+msgstr "歌曲信息...(_I)"
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
-msgstr "跳到时间(_T)..."
+msgstr "跳到时间...(_T)"
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
-msgstr "跳到歌曲(_J)..."
+msgstr "跳到歌曲...(_J)"
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "设置重复点 _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "设置重复点 _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
-msgstr "清除重复点"
+msgstr "清除重复点(_C)"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "按标题(_T)"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
-msgstr "使用文件名排序"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
+msgstr "按文件名(_F)"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
-msgstr "使用文件路径排序"
+msgstr "按文件路径(_P)"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "按音轨序号(_N)"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "按艺术家(_A)"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
-msgstr "使用专辑排序"
+msgstr "按专辑(_b)"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "按专辑艺术家(_m)"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "按发表日期(_D)"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "按照类型 (_G)"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
-msgstr "使用长度排序"
+msgstr "按长度(_L)"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "按文件路径(_F)"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "按自定义标题(_C)"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
-msgstr "反转(_e)"
+msgstr "逆序(_e)"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "随机(_R)"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "播放此列表(_P)"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "播放/继续 (_P)"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "刷新(_R)"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "排序(_S)"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
-msgstr "排序选中项"
+msgstr "排序选中项(_l)"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
-msgstr "删除重复"
+msgstr "删除重复(_D)"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
-msgstr "移除无效文件"
+msgstr "移除无效文件(_U)"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "新建(_N)"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
-msgstr "重命名(_A) ..."
+msgstr "重命名(_a) ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
-msgstr "移除 (&V)"
+msgstr "移除 (_v)"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
-msgstr "导入(_I)..."
+msgstr "导入...(_I)"
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
-msgstr "导出(_E)..."
+msgstr "导出...(_E)"
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "播放列表管理器(_M)..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "队列管理器(_Q)..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "调高音量(_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "调低音量(_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "均衡器(_E)"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
-msgstr "音效 ... (&E)"
+msgstr "音效 ... (_E)"
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "显示菜单(_M)"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "显示信息区域(_n)"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "显示可视化信息栏(_U)"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "显示状态栏(_S)"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
-msgstr "显示剩余时间"
+msgstr "显示剩余时间(_R)"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
-msgstr "可视化 ... (&V)"
+msgstr "可视化 ... (_V)"
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "文件(_F)"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "回放(_P)"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "播放列表(_l)"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "服务(_S)"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "输出(_O)"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "外观(_V)"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "入队/出列(_Q)"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "打开所属文件夹 (_O)"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "剪切(_t)"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "复制(_C)"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "粘贴(_P)"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "选中全部(_A)"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
-msgstr "重命名(_R) ..."
+msgstr "重命名...(_R)"
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>播放列表标签页</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "总是显示标签页"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "显示条目数量"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "显示关闭按钮"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>播放列表列</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "显示列头"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>杂项</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "箭头键排序:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "歌曲改变时滚动"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK界面"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "缓冲中..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "单声道"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "立体声"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d声道"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "单一窗口模式"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "播放列表模式"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "完成后停止"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "上一首"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "播放"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "暂停/继续"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "停止"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "下一首"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "快进 5 秒"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "快退 5 秒"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "静音"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "提高音量"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "降低音量"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "跳到文件"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "播放窗口切换"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "显示On-Screen-Display"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "打开重复"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "打开随机播放"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "打开当前曲目后停止"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "提出播放器窗口"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(æ— )"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2060,37 +2165,37 @@ msgid ""
 "Do you want to continue?"
 msgstr "并不建议绑定鼠标主键。要继续吗?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "绑定鼠标按键"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "全局热键插件设置"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
 msgstr "请在文本区按下要绑定的组合键,你亦可以绑定鼠标键"
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "热键:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>动作:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>键位绑定:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
-msgstr "添加 (&A)"
+msgstr "添加 (_A)"
+
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "全局热键"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2116,60 +2221,53 @@ msgstr ""
 "Jonathan A. Davis <davis at jdhouse.org>,\n"
 "Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "全局热键"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK 输出"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "连接到所有可用的 Jack 接口"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "自动连接到输出端口"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "仅连接到输出端口"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "仅发现 %d 个 JACK 端口,但是需要 %d 个。"
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "不连接到任何端口"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "连接到 JACK 端口 %s 失败。"
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "连接模式: "
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr "JACK 仅支持浮点音频。你必须在 Audacious 设置中将输出位深改为浮点。"
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "启用调试输出"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "连接到 JACK 服务器失败,服务是否在运行?"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"基于 xmms-jack, 由 Chris Morgan 制作: \n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"由 Giacomo Lozito 移植到 Audacious"
-
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK 输出"
+"JACK 服务要求采样率为 %d Hz,但是 Audacious 以 %d Hz 播放。请使用采样率转换特"
+"效插件纠正此错误"
 
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s 设置"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA主机设置"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "模块路径:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2179,25 +2277,25 @@ msgstr ""
 "这些路径将附加于 LADSPA_PATH 进行搜索。\n"
 "在添加这些新的路径后,按下 Enter 以扫描新插件。</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "可用插件:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "启用"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "已启用插件:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "设置"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2205,47 +2303,15 @@ msgstr ""
 "Audacious çš„ LADSPA Host\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
-msgid "LADSPA Host"
-msgstr "LADSPA 主机"
-
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s: 无法初始化 LIRC 支持\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s: 无法读取 LIRC 配置文件\n"
-"%s: 请阅读 LIRC 文档\n"
-"%s: 如何建立合适的配置文件\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s: 尝试重新连接中...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s: 未知命令 \"%s\"\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s: 从 LIRC 断开\n"
+#: src/ladspa/plugin.h:78
+msgid "LADSPA Host"
+msgstr "LADSPA 主机"
 
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s: 将会在 %d 秒后重试连接...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "LIRC 插件"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2273,73 +2339,81 @@ msgstr ""
 "\n"
 "欲获知更多关于 LIRC 的信息,请访问 http://lirc.org ."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>连接</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "重新连接 LIRC 服务器"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "重连前等待:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "LIRC 插件"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki 插件"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "没有相符歌词"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "错误"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "无法取回 %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "错误"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "无法解析 %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "正在搜索歌词..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "缺少歌曲元信息"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "正在连接到 lyrics.wikia.com ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki 插件"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki 插件(Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U 播放列表"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "Tact 生成器"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "节拍生成器: 每分钟节拍为 %d"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "节拍生成器: 每分钟节拍为 %d %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2353,11 +2427,11 @@ msgstr ""
 "例如 tact://77 则每分钟播放 77 个节拍\n"
 "或 tact://60*3/4 每分钟播放 60 个节拍于 3/4 拍"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "Tact 生成器"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "通道混合器"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2365,152 +2439,184 @@ msgstr ""
 "Audacious 的声道混合器插件\n"
 "Copyright 2011-2012 John Lindgren 及 Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>通道混音器</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "输出通道:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "通道混合器"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS 插件"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "连接到 MMS 服务错误"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (Module 播放器)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>分辨率</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8 位"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16 位"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>声道</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "最近的 (最快的)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "线性 (快速)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "仿样 (较好)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "多相 (最好的)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>采样率</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "层级: "
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "截断: "
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>回音</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>重低音增强</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>环绕</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>前置放大器</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "过度采样"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "减少噪声"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "播放 Amiga MOD 文件"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>重复</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "重复计数: "
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "要永远重复,将重复计数调整为 -1"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (Module 播放器)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "环绕音"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "这些设置会在重启 Audacious 后生效。"
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 插件"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>高级设置</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "使用精确长度计算(慢)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "环绕音"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 服务器"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS 插件"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "重定向解析错误"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "未知 HTTP 错误"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "解析网址错误"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "太多重定向"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "已停止"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious未开始播放"
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "桌面提醒"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2546,55 +2652,64 @@ msgstr ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "显示回放控制"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "总是显示消息提醒"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "桌面提醒"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "在通知中显示专辑名"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "显示"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "暂停"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "下一首"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. 默认设备"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 输出"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 输出"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "默认设备"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "音频设备:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "使用其它设备"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "会话中保存音量"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "使用OSS的格式转换。"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "开启独占模式以避免虚拟混合。"
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2608,19 +2723,35 @@ msgstr ""
 "我希望感谢 #audacious 上的人们,尤其 Tony Vroon 及 John Lindgren,当然,还有"
 "之前 OSS 插件的作者们。"
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 输出"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "播放列表管理器"
+
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "条目"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "移除(_R)"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "重命名(_a)"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS 播放列表"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 解码器"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio 输出"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2656,11 +2787,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio 输出"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia 输出"
+
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"Audacious QtMultimedia 音频输出插件\n"
+"William Pitcock 2014 版权所有\n"
+"\n"
+"基于Audacious SDL 输出插件\n"
+"John Lindgren 2010 版权所有"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "工作中 ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "搜索"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "打开文件夹 ... (&O)"
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "添加文件夹 ... (Add)"
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "日志监视(_L) ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "打开文件"
 
-#: src/resample/resample.c:165
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "添加文件"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "上一首"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "重复"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "随机"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt 界面"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "采样率转换器"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2668,96 +2861,104 @@ msgstr ""
 "Audacious 的抽样率转换器插件\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "跳过/重复样本"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "线性插值"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "快速 sinc 插值"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "中等 sinc 插值"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "最佳 sinc 插值"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>转换</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "方法:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "比率:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>比率映射</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "比率映射:"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "采样率转换器"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "搞定。正在为用户 %s Scrobble"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "权限阻止"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "请访问如下链接以允许 Audacious Scrobble 你的播放列表: "
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "保持此窗口并再次点击 '检查权限'。\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2765,32 +2966,36 @@ msgstr ""
 "不要担心。你的 Scrobble 已保存到了计算机上。\n"
 "他们将在 Audacious 被允许时提交。"
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "网络问题。"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "在访问 Last.fm 时遇到问题。请稍候重试。"
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "正在检索……"
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
-msgstr "检查权限"
+msgstr "检查权限(_C)"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
-msgstr "吊销权限"
+msgstr "吊销权限(_R)"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "你需要允许 Audacious 以 Scrobble 你 Last.fm 帐户上的音乐。\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2798,7 +3003,7 @@ msgstr ""
 "Scrobbler 插件无法启动。\n"
 "你的安装可能存在问题。"
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2815,11 +3020,7 @@ msgstr ""
 "感谢 John Lindgren 在项目初始阶段提供的帮助\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2827,7 +3028,11 @@ msgstr ""
 "Audacious 目前正在使用一个增强版的 Last.fm Scrobbler.\n"
 "请检查 Scrobbler 插件的首选项。"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL 输出"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2835,750 +3040,823 @@ msgstr ""
 "Audacious 的 SDL 输出插件\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL 输出"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "库"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "未知艺术家"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "未知专辑"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-"位于 %s 中的 %s"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d 个结果"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d 张专辑"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d 个隐藏的)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-"%s, %d 首歌曲"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d 首歌"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "属于此风格"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "在"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "-"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
-msgstr "创建播放列表"
+msgstr "创建播放列表(_C)"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
-msgstr "添加到播放列表"
+msgstr "添加到播放列表(_A)"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "搜索库"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr "要将您的音乐库导入Audacious,选择一个文件夹,然后点击“刷新”图标。"
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "请稍等...."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "选择文件夹"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID 播放器"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>输出</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "声道数:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>仿真</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "仿真 MOS 8580 (默认为:MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "不要自动选择芯片模板"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "仿真过滤器"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "时钟速率:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "不要自动选择时钟速率"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>播放时间</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "使用最大播放时间:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "仅当歌曲长度未知时使用"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "设置最大播放时间:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtunes</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "启用subtunes"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "忽略的subtunes短于:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>音符</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "静音移除"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Audacious 静音移除插件\n"
+"John Lindgren 2014 版权所有"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>静音移除</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "阈值:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "打开文件 ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "打开 URL ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "搜索库"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "回放"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "播放列表"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "外观"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "服务"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "关于 ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "设置 ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "退出"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "歌曲信息 ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "重复"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "随机"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "禁止自动播放下一首"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "在这首歌后停止"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "上一首"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "设置 A-B 点重复"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "清除 A-B 点重复"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "跳至曲目 ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "跳至时间 ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "播放此播放列表"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "播放/继续"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "新建播放列表"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "重命名播放列表 ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "移除播放列表"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "上一个播放列表"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "下一个播放列表"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "导入播放列表"
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "导出播放列表 ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "播放列表管理器 ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "队列管理器 ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "刷新播放列表"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "显示播放列表编辑器"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "显示均衡器"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "显示重命名时间"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "顶置窗口"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "所有工作区可见"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "收起播放器"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "收起播放列表编辑器"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "收起均衡器"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "双倍大小"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "添加 URL ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "添加文件 ..."
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "按标题"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
-msgstr "根据文件名"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
+msgstr "按文件名"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "按文件路径"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "清空"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "清空队列"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "删除不可用文件"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "删除重复的条目"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "删除未被选中的"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "删除已选中的"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "搜索/选择"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "反选"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "取消选中"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "选中全部"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "按专辑"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "按音轨号码"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "按艺术家"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "按专辑"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "按专辑艺术家"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "按发表日期"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "按音轨号码"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "按照类型"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "按照长度"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "按照自定义标题"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "打乱列表"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "反转列表"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "排序已选中的"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "排序列表"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "剪切"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "复制"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "粘贴"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "加入/移出列表"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "载入预设 ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "载入自动载入预设 ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "载入预设值"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "载入预设文件 ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "载入 EQF 文件 ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "保存预设 ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "保存自动加载预设 ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "保存为默认值"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "保存预设文件 ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "保存 EQF 文件 ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "删除预设 ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "删除自动预设 ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "导入 WinAMP 预设 ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "归零"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp 经典界面"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "保存"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "载入"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "载入预设文件"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "载入 EQF 文件"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "保存预设文件"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "保存 EQF 文件"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "导入 WinAMP 预设"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "预设"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "载入预设"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "载入自动载入预设"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "保存预设"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "保存自动加载预设"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "删除预设"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "删除自动加载预设"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "播放器(_P):"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "播放器:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "选择主界面字体"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "播放列表(_P):"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "播放列表:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "选择播放列表字体:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>皮肤</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>字体</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "使用点阵字体(仅支持ASCII字符)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "滚动曲目标题"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "来回滚动歌曲标题"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "分析器"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "示波器"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "声纹 / VU 表"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "关闭"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "一般"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "火炎"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "竖线"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "细线"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "柱状"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "最慢"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "æ…¢"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "中速"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "å¿«"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "最快"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "点"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "线"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "色块"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "冷蓝"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "平滑"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>类型</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "可视化类型: "
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>分析器</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "显示峰值"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "上色: "
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "风格: "
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "减退: "
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "峰值减退速度: "
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "示波器风格: "
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "声纹上色: "
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU 表风格: "
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "常规"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "可视化效果"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "前置放大"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 赫兹"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 赫兹"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 赫兹"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 赫兹"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "200 赫兹"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1000 赫兹"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2000 赫兹"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4000 赫兹"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8000 赫兹"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16000 赫兹"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious均衡器"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "查找: %d:%-2.2d/%d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "音量:%d%%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "平衡:%d%% 左"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "平衡:中间"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "平衡:%d%% 右"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "选项菜单"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "禁用“顶置窗口”"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "启用“顶置窗口”"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "文件信息"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "可视化效果"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "重复点 A 已设置。"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "重复点 B 已设置。"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "重复点已清除。"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "单一窗口模式"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "播放列表模式"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "完成后停止"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "从当前播放列表中搜索条目"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "搜索"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3588,57 +3866,61 @@ msgstr ""
 "按部分字段搜索播放列表中的条目。各个字段都可以使用正则表达式,而且是不分大小"
 "字的。如果你不知道何为正则表达式,简单的输入部分你想搜索的文字亦可。"
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "标题:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "专辑:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "艺术家:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
-msgstr "文件名"
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
+msgstr "文件名:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "搜索前清空之前的结果"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "自动为区配条目切换队列"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "用匹配的条目创建新的播放列表"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious播放列表编辑器"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d of %d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "已打包的Winamp 2.x主题"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "未打包的Winamp 2.x主题"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "无法创建目录(%s):%s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile 插件"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3678,81 +3960,71 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile 插件"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "关于 Sndio 输出插件"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio 输出"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio Output 插件\n"
-"\n"
-"作者 Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "设备(默认为空):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "不支持的格式"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "保存并恢复音量:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"所请求的声音设备不支持这种格式。\n"
-"\n"
-"请重试,并且保持 sndiod(1) 服务器的运行。"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio 错误:不支持音频格式(%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio 设备:"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio 错误: sio_open() failed"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(空代表默认)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio 错误: sio_setpar() failed"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "确定"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio 错误: sio_start() failed"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "歌曲改变"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "歌曲开始播放时执行指令。"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>传递到Shell的参数一定要用引号包围,否则会是一件相当危险的"
+"事。</span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>命令</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "指令:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "开始播放新歌曲时运行命令:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "歌曲即将完成时执行指令。"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "歌曲结束播放时运行命令:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "当Audacious播放到列表结尾时执行指令。"
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "播放列表结束时运行命令:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "歌曲的标题改变时执行指令(如:网络媒体的标题)。"
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "歌曲标题改变时运行命令(用于网络流媒体):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3766,35 +4038,29 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"你可以使用以下的格式化字符串,命令调用前,\n"
-"它们会被转换为相应的值。\n"
-"(部分字符串在end-of-playlist命令中无效)\n"
+"你可以使用下列格式的替代符 (并非所有都适用于“播放列表结束后执行命令”):\n"
 "\n"
-"%F: 频率 (单位:Hz)\n"
+"%F: 频率 (Hz)\n"
 "%c: 声道数\n"
 "%f: 文件名 (完整路径)\n"
-"%l: 长度 (单位:毫秒)\n"
+"%l: 长度 (毫秒)\n"
 "%n 或 %s: 歌曲名\n"
-"%r: 比率 (单位: bit/秒)\n"
+"%r: 比特率 (每秒比特数)\n"
 "%t: 播放列表位置 (%02d)\n"
-"%p: 当前播放曲目 (1 or 0)\n"
+"%p: 当前正在播放(1 或 0)\n"
 "%a: 艺术家\n"
 "%b: 专辑\n"
-"%T: 音轨标题"
+"%T: 曲目标题"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>传递到Shell的参数一定要用引号包围,否则会是一件相当危险的"
-"事。</span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "歌曲信息 (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "指令"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX 重采样器"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3808,51 +4074,51 @@ msgstr ""
 "基于取样率转换器插件:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "快速"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "低"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "高"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "非常高"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "音质: "
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX 重采样器"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "速度和音调"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>速度和音调</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "速度:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "音调:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "速度和音调"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "状态图标"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
-msgstr "设置 (&T)"
+msgstr "设置... (_t)"
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3869,39 +4135,39 @@ msgstr ""
 "\n"
 "此插件提供一个状态图标,放置于系统托盘位置。"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>鼠标滚轮动作</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "调整音量"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "改变歌曲"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>其他设置</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "禁用弹出窗口"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "关闭系统托盘"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "向上卷动时显示在播放列表顶部"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "状态图标"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "Extra Stereo"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3911,24 +4177,24 @@ msgstr ""
 "\n"
 "作者: Johan Levin 1999."
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>Extra Stereo</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "Extra Stereo"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "Tone Generator"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "音调生成器: "
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3942,15 +4208,11 @@ msgstr ""
 "要使用这个生成器,添加一个 URL:tone://frequency1;frequency2;frequency3;...\n"
 "实例 tone://2000;2005 以播放一个 2000 Hz 以及 2005 Hz 的音调"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "Tone Generator"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "人声消除"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3988,11 +4250,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis 解码器"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "%s 的细节"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"标题: %t\n"
+"作者: %a\n"
+"来自: %f\n"
+"tracker: %T\n"
+"注释: %C\n"
+"芯片类型: %c\n"
+"立体声: %s\n"
+"循环: %l\n"
+"芯片频率: %F\n"
+"播放器频率: %P\n"
+"年代: %y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX 解码器"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4002,19 +4299,19 @@ msgstr ""
 "基于 Roman Sherbakov <v_soft at microfor.ru> 制作的 in_vtx.dll\n"
 "Audacious 插件作者为 Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX 解码器"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack 解码器"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "有损的 (混合)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "有损的"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4024,23 +4321,18 @@ msgstr ""
 "\n"
 "一部分插件代码由 Miles Egan 编写。"
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack 解码器"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF 解码器"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "可分享的 XML 播放列表 (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF 设置</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "忽略文件长度"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "可分享的 XML 播放列表 (XSPF)"
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 402941083caf..3c3ec134f8fb 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -3,15 +3,15 @@
 # This file is distributed under the same license as the Audacious Plugins package.
 #
 # Translators:
-# 瑞元 盧 <rueiyuan.lu at gmail.com>, 2014
+# Ruei-Yuan Lu <rueiyuan.lu at gmail.com>, 2014
 # Ruei-Yuan Lu <RueiYuan.Lu at gmail.com>, 2011
 msgid ""
 msgstr ""
-"Project-Id-Version: Audacious Plugins Plugins\n"
+"Project-Id-Version: Audacious Plugins\n"
 "Report-Msgid-Bugs-To: http://redmine.audacious-media-player.org/\n"
-"POT-Creation-Date: 2014-04-21 23:02+0200\n"
-"PO-Revision-Date: 2014-04-17 08:21+0000\n"
-"Last-Translator: 瑞元 盧 <rueiyuan.lu at gmail.com>\n"
+"POT-Creation-Date: 2015-02-28 19:18+0100\n"
+"PO-Revision-Date: 2015-02-25 03:48+0000\n"
+"Last-Translator: Ruei-Yuan Lu <rueiyuan.lu at gmail.com>\n"
 "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/"
 "audacious/language/zh_TW/)\n"
 "Language: zh_TW\n"
@@ -20,40 +20,28 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:82
-msgid "mono"
-msgstr "單聲道"
-
-#: src/aac/libmp4.c:98 src/gtkui/ui_statusbar.c:84
-msgid "stereo"
-msgstr "立體聲"
-
-#: src/aac/libmp4.c:98
-msgid "surround"
-msgstr "環繞"
-
-#: src/aac/libmp4.c:313
-msgid "AAC (MP4) Decoder"
-msgstr "AAC (MP4) 解碼器"
-
-#: src/aac-raw/aac.c:476
+#: src/aac-raw/aac.cc:18
 msgid "AAC (Raw) Decoder"
 msgstr "AAC (Raw) 解碼器"
 
-#: src/adplug/adplug-xmms.cc:137 src/modplug/modplugbmp.cxx:348
-#: src/psf/plugin.c:122 src/vtx/vtx.c:62 src/xsf/plugin.c:80
+#: src/adplug/adplug-xmms.cc:42
+msgid "AdPlug (AdLib Player)"
+msgstr "AdPlug (AdLib 播放器)"
+
+#: src/adplug/adplug-xmms.cc:156 src/modplug/modplugbmp.cc:335
+#: src/psf/plugin.cc:138 src/vtx/vtx.cc:87 src/xsf/plugin.cc:113
 msgid "sequenced"
 msgstr "編曲機"
 
-#: src/adplug/plugin.c:14
-msgid "AdPlug (AdLib Player)"
-msgstr "AdPlug (AdLib 播放器)"
+#: src/alarm/alarm.cc:55 src/alarm/interface.cc:82
+msgid "Alarm"
+msgstr "鬧鐘"
 
-#: src/alarm/alarm.c:778
+#: src/alarm/alarm.cc:782
 msgid "Set Alarm ..."
 msgstr "設定鬧鐘 ..."
 
-#: src/alarm/alarm.c:806
+#: src/alarm/alarm.cc:810
 msgid ""
 "A plugin that can be used to start playing at a certain time.\n"
 "\n"
@@ -63,11 +51,7 @@ msgstr ""
 "\n"
 "Originally written by Adam Feakin and Daniel Stodden."
 
-#: src/alarm/alarm.c:811 src/alarm/interface.c:86
-msgid "Alarm"
-msgstr "鬧鐘"
-
-#: src/alarm/interface.c:32
+#: src/alarm/interface.cc:28
 msgid ""
 "Time\n"
 "  Alarm at:\n"
@@ -108,7 +92,7 @@ msgstr ""
 "\n"
 "\n"
 
-#: src/alarm/interface.c:49
+#: src/alarm/interface.cc:45
 msgid ""
 "Volume\n"
 "  Fading:\n"
@@ -148,7 +132,7 @@ msgstr ""
 "    鬧鐘觸發時執行這個指令。\n"
 "\n"
 
-#: src/alarm/interface.c:66
+#: src/alarm/interface.cc:62
 msgid ""
 "  Playlist:\n"
 "    Load this playlist. If no playlist\n"
@@ -172,384 +156,390 @@ msgstr ""
 "    若您希望它被顯示,請勾選並在欄\n"
 "    位中輸入訊息。"
 
-#: src/alarm/interface.c:85
+#: src/alarm/interface.cc:81
 msgid "This is your wakeup call."
 msgstr "這是您的喚醒。"
 
-#: src/alarm/interface.c:103
+#: src/alarm/interface.cc:99
 msgid "Your reminder for today is..."
 msgstr "您今天的提醒"
 
-#: src/alarm/interface.c:105 src/alarm/interface.c:417
+#: src/alarm/interface.cc:101 src/alarm/interface.cc:386
 msgid "Reminder"
 msgstr "提醒"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Monday"
 msgstr "星期一"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Tuesday"
 msgstr "星期二"
 
-#: src/alarm/interface.c:144
+#: src/alarm/interface.cc:132
 msgid "Wednesday"
 msgstr "星期三"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Thursday"
 msgstr "星期四"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Friday"
 msgstr "星期五"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Saturday"
 msgstr "星期六"
 
-#: src/alarm/interface.c:145
+#: src/alarm/interface.cc:133
 msgid "Sunday"
 msgstr "星期日"
 
-#: src/alarm/interface.c:179
-msgid "Alarm Settings"
-msgstr "鬧鐘設定"
-
-#: src/alarm/interface.c:180 src/filewriter/mp3.c:690
-msgid "_OK"
-msgstr "確認(_O)"
-
-#: src/alarm/interface.c:180 src/amidi-plug/i_configure-fluidsynth.c:55
-#: src/aosd/aosd_ui.c:930 src/filewriter/mp3.c:690 src/hotkey/gui.c:486
-msgid "_Cancel"
-msgstr "取消(_C)"
-
-#: src/alarm/interface.c:188 src/alarm/interface.c:252
-#: src/alarm/interface.c:267
+#: src/alarm/interface.cc:171 src/alarm/interface.cc:230
+#: src/alarm/interface.cc:245
 msgid "Time"
 msgstr "時間"
 
-#: src/alarm/interface.c:195
+#: src/alarm/interface.cc:178
 msgid "Alarm at (default):"
 msgstr "鈴響於 (預設)"
 
-#: src/alarm/interface.c:218
+#: src/alarm/interface.cc:200
 msgid "h"
 msgstr "h"
 
-#: src/alarm/interface.c:222
+#: src/alarm/interface.cc:203
 msgid "Quiet after:"
 msgstr "多久後靜音:"
 
-#: src/alarm/interface.c:236
+#: src/alarm/interface.cc:215
 msgid "hours"
 msgstr "小時"
 
-#: src/alarm/interface.c:248
+#: src/alarm/interface.cc:226
 msgid "minutes"
 msgstr "分鐘"
 
-#: src/alarm/interface.c:257
+#: src/alarm/interface.cc:235
 msgid "Choose the days for the alarm to come on"
 msgstr "選擇想要在哪幾天啟用鬧鐘"
 
-#: src/alarm/interface.c:264
+#: src/alarm/interface.cc:242
 msgid "Day"
 msgstr "哪幾天"
 
-#: src/alarm/interface.c:282 src/bs2b/plugin.c:168 src/skins/preset-list.c:439
-#: src/skins/preset-list.c:445
+#: src/alarm/interface.cc:259 src/bs2b/plugin.cc:130
+#: src/skins/preset-list.cc:434 src/skins/preset-list.cc:440
 msgid "Default"
 msgstr "預設"
 
-#: src/alarm/interface.c:312
+#: src/alarm/interface.cc:288
 msgid "Days"
 msgstr "週排程"
 
-#: src/alarm/interface.c:321
+#: src/alarm/interface.cc:297
 msgid "Fading"
 msgstr "淡出"
 
-#: src/alarm/interface.c:329 src/console/plugin.c:41
-#: src/crossfade/crossfade.c:263 src/gtkui/settings.c:53 src/lirc/lirc.c:395
+#: src/alarm/interface.cc:305 src/console/plugin.cc:41
+#: src/crossfade/crossfade.cc:53 src/crossfade/crossfade.cc:59
+#: src/gtkui/settings.cc:49 src/lirc/lirc.cc:397 src/sid/xs_config.cc:85
+#: src/sid/xs_config.cc:94 src/sid/xs_config.cc:103
 msgid "seconds"
 msgstr "秒"
 
-#: src/alarm/interface.c:336 src/alarm/interface.c:383
+#: src/alarm/interface.cc:312 src/alarm/interface.cc:353
 msgid "Volume"
 msgstr "音量"
 
-#: src/alarm/interface.c:341
+#: src/alarm/interface.cc:317
 msgid "Start at"
 msgstr "初始音量"
 
-#: src/alarm/interface.c:359
+#: src/alarm/interface.cc:333
 msgid "Final"
 msgstr "最終音量"
 
-#: src/alarm/interface.c:374
+#: src/alarm/interface.cc:346
 msgid "Current"
 msgstr "目前音量"
 
-#: src/alarm/interface.c:389
+#: src/alarm/interface.cc:359
 msgid "Additional Command"
 msgstr "額外命令"
 
-#: src/alarm/interface.c:395 src/alarm/interface.c:422
+#: src/alarm/interface.cc:365 src/alarm/interface.cc:391
 msgid "enable"
 msgstr "啟用"
 
-#: src/alarm/interface.c:402
+#: src/alarm/interface.cc:372
 msgid "Playlist (optional)"
 msgstr "播放清單 (選用)"
 
-#: src/alarm/interface.c:409
+#: src/alarm/interface.cc:379
 msgid "Select a playlist"
 msgstr "請選擇播放清單"
 
-#: src/alarm/interface.c:430
+#: src/alarm/interface.cc:399
 msgid "Options"
 msgstr "選項"
 
-#: src/alarm/interface.c:435
+#: src/alarm/interface.cc:404
 msgid "What do these options mean?"
 msgstr "這些選項代表什麼意思?"
 
-#: src/alarm/interface.c:449
+#: src/alarm/interface.cc:420
 msgid "Help"
 msgstr "說明"
 
-#: src/albumart/albumart.c:72
+#: src/albumart/albumart.cc:31
 msgid "Album Art"
 msgstr "專輯封面"
 
-#: src/alsa/config.c:210
+#: src/albumart-qt/albumart.cc:33
+msgid "Album Art (Qt)"
+msgstr "專輯封面 (Qt)"
+
+#: src/alsa/alsa.h:70
+msgid "ALSA Output"
+msgstr "ALSA 輸出"
+
+#: src/alsa/config.cc:28
+msgid ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+msgstr ""
+"ALSA Output Plugin for Audacious\n"
+"Copyright 2009-2012 John Lindgren\n"
+"\n"
+"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+"code served as a reference when the ALSA manual was not enough."
+
+#: src/alsa/config.cc:61
+msgid "(no description)"
+msgstr "(無描述訊息)"
+
+#: src/alsa/config.cc:166
 msgid "Default PCM device"
 msgstr "預設 PCM 裝置"
 
-#: src/alsa/config.c:239
+#: src/alsa/config.cc:188
 msgid "Default mixer device"
 msgstr "預設混音器裝置"
 
-#: src/alsa/config.c:428
+#: src/alsa/config.cc:296
 msgid "PCM device:"
 msgstr "PCM 裝置:"
 
-#: src/alsa/config.c:430
+#: src/alsa/config.cc:299
 msgid "Mixer device:"
 msgstr "混音器裝置:"
 
-#: src/alsa/config.c:432
+#: src/alsa/config.cc:302
 msgid "Mixer element:"
 msgstr "混音器元件:"
 
-#: src/alsa/config.c:435
-msgid "Work around drain hangup"
-msgstr "處理欠載鎖死"
+#: src/amidi-plug/amidi-plug.cc:41
+msgid "AMIDI-Plug (MIDI Player)"
+msgstr "AMIDI-Plug (MIDI 播放器)"
 
-#: src/alsa/plugin.c:27
+#: src/amidi-plug/amidi-plug.cc:437
 msgid ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 msgstr ""
-"ALSA Output Plugin for Audacious\n"
-"Copyright 2009-2012 John Lindgren\n"
+"AMIDI-Plug\n"
+"modular MIDI music player\n"
+"http://www.develia.org/projects.php?p=amidiplug\n"
 "\n"
-"My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-"code served as a reference when the ALSA manual was not enough."
-
-#: src/alsa/plugin.c:41
-msgid "ALSA Output"
-msgstr "ALSA 輸出"
-
-#: src/amidi-plug/amidi-plug.c:466
-msgid "AMIDI-Plug (MIDI Player)"
-msgstr "AMIDI-Plug (MIDI 播放器)"
+"written by Giacomo Lozito\n"
+"<james at develia.org>\n"
+"\n"
+"special thanks to...\n"
+"\n"
+"Clemens Ladisch and Jaroslav Kysela\n"
+"for their cool programs aplaymidi and amixer; those\n"
+"were really useful, along with alsa-lib docs, in order\n"
+"to learn more about the ALSA API\n"
+"\n"
+"Alfredo Spadafina\n"
+"for the nice midi keyboard logo\n"
+"\n"
+"Tony Vroon\n"
+"for the good help with alpha testing"
 
-#: src/amidi-plug/i_configure.c:96
+#: src/amidi-plug/i_configure.cc:94
 msgid "Override default gain:"
 msgstr "覆載預設的增益值:"
 
-#: src/amidi-plug/i_configure.c:102
+#: src/amidi-plug/i_configure.cc:102
 msgid "Override default polyphony:"
 msgstr "覆載預設的同時發音數:"
 
-#: src/amidi-plug/i_configure.c:108
+#: src/amidi-plug/i_configure.cc:110
 msgid "Override default reverb:"
 msgstr "覆載預設的殘響強度:"
 
-#: src/amidi-plug/i_configure.c:110 src/amidi-plug/i_configure.c:116
+#: src/amidi-plug/i_configure.cc:112 src/amidi-plug/i_configure.cc:120
 msgid "On"
 msgstr "啟用"
 
-#: src/amidi-plug/i_configure.c:114
+#: src/amidi-plug/i_configure.cc:118
 msgid "Override default chorus:"
 msgstr "覆載預設和聲強度:"
 
-#: src/amidi-plug/i_configure.c:122 src/console/plugin.c:33
+#: src/amidi-plug/i_configure.cc:128 src/console/plugin.cc:29
 msgid "<b>Playback</b>"
 msgstr "<b>播放</b>"
 
-#: src/amidi-plug/i_configure.c:123
+#: src/amidi-plug/i_configure.cc:129
 msgid "Transpose:"
 msgstr "移調:"
 
-#: src/amidi-plug/i_configure.c:125
+#: src/amidi-plug/i_configure.cc:131
+msgid "semitones"
+msgstr "半音"
+
+#: src/amidi-plug/i_configure.cc:132
 msgid "Drum shift:"
 msgstr "鼓移:"
 
-#: src/amidi-plug/i_configure.c:127
-msgid "<b>Advanced</b>"
-msgstr "<b>進階</b>"
+#: src/amidi-plug/i_configure.cc:134
+msgid "note numbers"
+msgstr "音符數量"
 
-#: src/amidi-plug/i_configure.c:128
-msgid "Extract comments from MIDI file"
-msgstr "抽取 MIDI 檔的備註資料"
+#: src/amidi-plug/i_configure.cc:135
+msgid "Skip leading silence"
+msgstr "跳過開頭的靜音"
 
-#: src/amidi-plug/i_configure.c:130
-msgid "Extract lyrics from MIDI file"
-msgstr "抽取 MIDI 檔的歌詞資料"
+#: src/amidi-plug/i_configure.cc:137
+msgid "Skip trailing silence"
+msgstr "跳過結尾的靜音"
 
-#: src/amidi-plug/i_configure.c:134
+#: src/amidi-plug/i_configure.cc:141
 msgid "<b>SoundFont</b>"
 msgstr "<b>SoundFont</b>"
 
-#: src/amidi-plug/i_configure.c:136
+#: src/amidi-plug/i_configure.cc:143
 msgid "<b>Synthesizer</b>"
 msgstr "<b>合成器</b>"
 
-#: src/amidi-plug/i_configure.c:141
-msgid "Sampling rate:"
+#: src/amidi-plug/i_configure.cc:148 src/console/plugin.cc:45
+#: src/sid/xs_config.cc:65
+msgid "Sample rate:"
 msgstr "取樣率:"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:52
+#: src/amidi-plug/i_configure.cc:150 src/bs2b/plugin.cc:141
+#: src/console/plugin.cc:47 src/modplug/plugin_main.cc:78
+#: src/resample/resample.cc:201 src/resample/resample.cc:207
+#: src/resample/resample.cc:211 src/resample/resample.cc:215
+#: src/resample/resample.cc:219 src/resample/resample.cc:223
+#: src/resample/resample.cc:227 src/resample/resample.cc:231
+#: src/resample/resample.cc:235 src/resample/resample.cc:239
+#: src/resample/resample.cc:243 src/sid/xs_config.cc:67
+#: src/sox-resampler/sox-resampler.cc:163
+msgid "Hz"
+msgstr "Hz"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:52
 msgid "AMIDI-Plug - select SoundFont file"
 msgstr "AMIDI-Plug - 選擇 SoundFont 檔案"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:56
+#: src/amidi-plug/i_configure-fluidsynth.cc:55 src/filewriter/mp3.cc:658
+msgid "_Cancel"
+msgstr "取消(_C)"
+
+#: src/amidi-plug/i_configure-fluidsynth.cc:56
 msgid "_Open"
 msgstr "é–‹å•Ÿ(_O)"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:227
-msgid "Filename"
+#: src/amidi-plug/i_configure-fluidsynth.cc:225 src/gtkui/columns.cc:46
+msgid "File name"
 msgstr "檔案名稱"
 
-#: src/amidi-plug/i_configure-fluidsynth.c:231
+#: src/amidi-plug/i_configure-fluidsynth.cc:229
 msgid "Size (bytes)"
 msgstr "大小 (位元組)"
 
-#: src/amidi-plug/i_fileinfo.c:176
+#: src/amidi-plug/i_fileinfo.cc:163
 msgid "Name:"
 msgstr "名稱:"
 
-#: src/amidi-plug/i_fileinfo.c:203
+#: src/amidi-plug/i_fileinfo.cc:181
 msgid "<span size=\"smaller\"> MIDI Info </span>"
 msgstr "<span size=\"smaller\"> MIDI 資訊 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:217
+#: src/amidi-plug/i_fileinfo.cc:195
 msgid "Format:"
 msgstr "格式:"
 
-#: src/amidi-plug/i_fileinfo.c:220
+#: src/amidi-plug/i_fileinfo.cc:198
 msgid "Length (msec):"
 msgstr "長度 (毫秒):"
 
-#: src/amidi-plug/i_fileinfo.c:223
+#: src/amidi-plug/i_fileinfo.cc:201
 msgid "No. of Tracks:"
 msgstr "音軌編號:"
 
-#: src/amidi-plug/i_fileinfo.c:229
+#: src/amidi-plug/i_fileinfo.cc:207
 msgid "variable"
 msgstr "變動的"
 
-#: src/amidi-plug/i_fileinfo.c:231
+#: src/amidi-plug/i_fileinfo.cc:209
 msgid "BPM:"
 msgstr "BPM:"
 
-#: src/amidi-plug/i_fileinfo.c:239
+#: src/amidi-plug/i_fileinfo.cc:217
 msgid "BPM (wavg):"
 msgstr "BPM (wavg):"
 
-#: src/amidi-plug/i_fileinfo.c:242
+#: src/amidi-plug/i_fileinfo.cc:220
 msgid "Time Div:"
 msgstr "時間分割:"
 
-#: src/amidi-plug/i_fileinfo.c:253
+#: src/amidi-plug/i_fileinfo.cc:231
 msgid "<span size=\"smaller\"> MIDI Comments and Lyrics </span>"
 msgstr "<span size=\"smaller\"> MIDI 備註與歌詞 </span>"
 
-#: src/amidi-plug/i_fileinfo.c:302
+#: src/amidi-plug/i_fileinfo.cc:278
 msgid "* no comments available in this MIDI file *"
 msgstr "* 這個 MIDI 檔不包含備註資料 *"
 
-#: src/amidi-plug/i_fileinfo.c:314
+#: src/amidi-plug/i_fileinfo.cc:290
 msgid "* no lyrics available in this MIDI file *"
 msgstr "* 這個 MIDI 檔不包含歌詞資料 *"
 
-#: src/amidi-plug/i_fileinfo.c:341 src/amidi-plug/i_utils.c:40
-#: src/filewriter/vorbis.c:210 src/ladspa/plugin.c:521 src/ladspa/plugin.c:588
+#: src/amidi-plug/i_fileinfo.cc:300 src/filewriter/vorbis.cc:197
+#: src/ladspa/plugin.cc:416
 msgid "_Close"
 msgstr "關閉(_C)"
 
-#: src/amidi-plug/i_fileinfo.c:366
+#: src/amidi-plug/i_fileinfo.cc:325
 msgid "  (invalid UTF-8)"
 msgstr "  (無效的 UTF-8 字串)"
 
-#: src/amidi-plug/i_utils.c:39
-msgid "About AMIDI-Plug"
-msgstr "關於 AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:53
-msgid "AMIDI-Plug"
-msgstr "AMIDI-Plug"
-
-#: src/amidi-plug/i_utils.c:54
-msgid ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-msgstr ""
-"\n"
-"modular MIDI music player\n"
-"http://www.develia.org/projects.php?p=amidiplug\n"
-"\n"
-"written by Giacomo Lozito\n"
-"<james at develia.org>\n"
-"\n"
-"special thanks to...\n"
-"\n"
-"Clemens Ladisch and Jaroslav Kysela\n"
-"for their cool programs aplaymidi and amixer; those\n"
-"were really useful, along with alsa-lib docs, in order\n"
-"to learn more about the ALSA API\n"
-"\n"
-"Alfredo Spadafina\n"
-"for the nice midi keyboard logo\n"
-"\n"
-"Tony Vroon\n"
-"for the good help with alpha testing"
-
-#: src/aosd/aosd.c:30
+#: src/aosd/aosd.cc:32
 msgid ""
 "Audacious OSD\n"
 "http://www.develia.org/projects.php?p=audacious#aosd\n"
@@ -567,150 +557,146 @@ msgstr ""
 "Based in part on Evan Martin's Ghosd library:\n"
 "http://neugierig.org/software/ghosd/"
 
-#: src/aosd/aosd.c:38
+#: src/aosd/aosd.h:37
 msgid "AOSD (On-Screen Display)"
 msgstr "AOSD (Audacious OSD)"
 
-#: src/aosd/aosd_style.c:75
+#: src/aosd/aosd_style.cc:54
 msgid "Rectangle"
 msgstr "矩形"
 
-#: src/aosd/aosd_style.c:79
+#: src/aosd/aosd_style.cc:59
 msgid "Rounded Rectangle"
 msgstr "圓角矩形"
 
-#: src/aosd/aosd_style.c:83
+#: src/aosd/aosd_style.cc:64
 msgid "Concave Rectangle"
 msgstr "角落凹陷的矩形"
 
-#: src/aosd/aosd_style.c:87
+#: src/aosd/aosd_style.cc:69
 msgid "None"
 msgstr "ç„¡"
 
-#: src/aosd/aosd_trigger.c:74
+#: src/aosd/aosd_trigger.cc:50
 msgid "Playback Start"
 msgstr "開始播放"
 
-#: src/aosd/aosd_trigger.c:75
+#: src/aosd/aosd_trigger.cc:51
 msgid "Triggers OSD when a playlist entry is played."
 msgstr "當播放清單中的項目被播放時觸發 OSD"
 
-#: src/aosd/aosd_trigger.c:79
+#: src/aosd/aosd_trigger.cc:56
 msgid "Title Change"
 msgstr "標題變更"
 
-#: src/aosd/aosd_trigger.c:80
-msgid ""
-"Triggers OSD when, during playback, the song title changes but the filename "
-"is the same. This is mostly useful to display title changes in internet "
-"streams."
-msgstr ""
-"當播放中歌曲標題改變但檔名不變時觸發 OSD。這對顯示網路串流的標題很有用。"
+#: src/aosd/aosd_trigger.cc:57
+msgid "Triggers OSD when the song title changes (for internet streams)."
+msgstr "歌曲標題改變時顯示 OSD (網路串流用)。"
 
-#: src/aosd/aosd_trigger.c:86
+#: src/aosd/aosd_trigger.cc:62
 msgid "Pause On"
 msgstr "暫停播放"
 
-#: src/aosd/aosd_trigger.c:87
+#: src/aosd/aosd_trigger.cc:63
 msgid "Triggers OSD when playback is paused."
 msgstr "當播放暫停時觸發 OSD"
 
-#: src/aosd/aosd_trigger.c:91
+#: src/aosd/aosd_trigger.cc:68
 msgid "Pause Off"
 msgstr "解除暫停"
 
-#: src/aosd/aosd_trigger.c:92
+#: src/aosd/aosd_trigger.cc:69
 msgid "Triggers OSD when playback is unpaused."
 msgstr "當解除暫停時觸發 OSD"
 
-#: src/aosd/aosd_ui.c:192
+#: src/aosd/aosd_ui.cc:163
 msgid "Placement"
 msgstr "放置位置"
 
-#: src/aosd/aosd_ui.c:224
+#: src/aosd/aosd_ui.cc:196
 msgid "Relative X offset:"
 msgstr "X 軸相對位移:"
 
-#: src/aosd/aosd_ui.c:231
+#: src/aosd/aosd_ui.cc:203
 msgid "Relative Y offset:"
 msgstr "Y 軸相對位移:"
 
-#: src/aosd/aosd_ui.c:238
+#: src/aosd/aosd_ui.cc:210
 msgid "Max OSD width:"
 msgstr "最大 OSD 寬度:"
 
-#: src/aosd/aosd_ui.c:249
+#: src/aosd/aosd_ui.cc:221
 msgid "Multi-Monitor options"
 msgstr "多螢幕選項"
 
-#: src/aosd/aosd_ui.c:253
+#: src/aosd/aosd_ui.cc:225
 msgid "Display OSD using:"
 msgstr "顯示 OSD:"
 
-#: src/aosd/aosd_ui.c:255
+#: src/aosd/aosd_ui.cc:227
 msgid "all monitors"
 msgstr "所有螢幕"
 
-#: src/aosd/aosd_ui.c:258
+#: src/aosd/aosd_ui.cc:230
 #, c-format
 msgid "monitor %i"
 msgstr "螢幕 %i"
 
-#: src/aosd/aosd_ui.c:310
+#: src/aosd/aosd_ui.cc:282
 msgid "Timing (ms)"
 msgstr "計時 (毫秒)"
 
-#: src/aosd/aosd_ui.c:315
+#: src/aosd/aosd_ui.cc:287
 msgid "Display:"
 msgstr "顯示:"
 
-#: src/aosd/aosd_ui.c:320
+#: src/aosd/aosd_ui.cc:292
 msgid "Fade in:"
 msgstr "淡入:"
 
-#: src/aosd/aosd_ui.c:325
+#: src/aosd/aosd_ui.cc:297
 msgid "Fade out:"
 msgstr "淡出:"
 
-#: src/aosd/aosd_ui.c:390
+#: src/aosd/aosd_ui.cc:361
 msgid "Fonts"
 msgstr "å­—åž‹"
 
-#: src/aosd/aosd_ui.c:397
+#: src/aosd/aosd_ui.cc:368
 #, c-format
 msgid "Font %i:"
 msgstr "字型 %i:"
 
-#: src/aosd/aosd_ui.c:412
+#: src/aosd/aosd_ui.cc:382
 msgid "Shadow"
 msgstr "é™°å½±"
 
-#: src/aosd/aosd_ui.c:518
+#: src/aosd/aosd_ui.cc:486
 msgid "Render Style"
 msgstr "呈現樣式"
 
-#: src/aosd/aosd_ui.c:534
+#: src/aosd/aosd_ui.cc:502
 msgid "Colors"
 msgstr "顏色"
 
-#: src/aosd/aosd_ui.c:545
+#: src/aosd/aosd_ui.cc:513
 #, c-format
 msgid "Color %i:"
 msgstr "顏色 %i:"
 
-#: src/aosd/aosd_ui.c:648
+#: src/aosd/aosd_ui.cc:600
 msgid "Enable trigger"
 msgstr "啟用觸發器"
 
-#: src/aosd/aosd_ui.c:675
+#: src/aosd/aosd_ui.cc:627
 msgid "Event"
 msgstr "事件"
 
-#: src/aosd/aosd_ui.c:703
+#: src/aosd/aosd_ui.cc:655
 msgid "Composite manager detected"
 msgstr "已偵測到合成特效管理程式"
 
-#: src/aosd/aosd_ui.c:710
+#: src/aosd/aosd_ui.cc:662
 msgid ""
 "Composite manager not detected;\n"
 "unless you know that you have one running, please activate a composite "
@@ -719,112 +705,112 @@ msgstr ""
 "未偵測到合成特效管理程式;\n"
 "除非您確定已經執行,否則 OSD 將無法正確啟用。"
 
-#: src/aosd/aosd_ui.c:718
+#: src/aosd/aosd_ui.cc:670
 msgid "Composite manager not required for fake transparency"
 msgstr "假的透明特效不需要 Composite manager"
 
-#: src/aosd/aosd_ui.c:754
+#: src/aosd/aosd_ui.cc:706
 msgid "Transparency"
 msgstr "透明"
 
-#: src/aosd/aosd_ui.c:760
+#: src/aosd/aosd_ui.cc:712
 msgid "Fake transparency"
 msgstr "假的透明特效"
 
-#: src/aosd/aosd_ui.c:762
+#: src/aosd/aosd_ui.cc:714
 msgid "Real transparency (requires X Composite Ext.)"
 msgstr "真的透明特效 (需要 X Composite 延伸功能)"
 
-#: src/aosd/aosd_ui.c:804
+#: src/aosd/aosd_ui.cc:756
 msgid "Composite extension not loaded"
 msgstr "Composite 延伸功能未載入"
 
-#: src/aosd/aosd_ui.c:812
+#: src/aosd/aosd_ui.cc:764
 msgid "Composite extension not available"
 msgstr "Composite 延伸功能不存在"
 
-#: src/aosd/aosd_ui.c:831
+#: src/aosd/aosd_ui.cc:781
 #, c-format
 msgid "<span font_desc='%s'>Audacious OSD</span>"
 msgstr "<span font_desc='%s'>Audacious OSD</span>"
 
-#: src/aosd/aosd_ui.c:906
-msgid "Audacious OSD - configuration"
-msgstr "Audacious OSD - 設定"
-
-#: src/aosd/aosd_ui.c:927
-msgid "_Test"
-msgstr "測試(_T)"
-
-#: src/aosd/aosd_ui.c:933 src/hotkey/gui.c:491
-msgid "_Set"
-msgstr "套用(_S)"
-
-#: src/aosd/aosd_ui.c:940
+#: src/aosd/aosd_ui.cc:844
 msgid "Position"
 msgstr "位置"
 
-#: src/aosd/aosd_ui.c:945
+#: src/aosd/aosd_ui.cc:849
 msgid "Animation"
 msgstr "å‹•ç•«"
 
-#: src/aosd/aosd_ui.c:950
+#: src/aosd/aosd_ui.cc:854
 msgid "Text"
 msgstr "文字"
 
-#: src/aosd/aosd_ui.c:955
+#: src/aosd/aosd_ui.cc:859
 msgid "Decoration"
 msgstr "裝飾"
 
-#: src/aosd/aosd_ui.c:960
+#: src/aosd/aosd_ui.cc:864
 msgid "Trigger"
 msgstr "觸發"
 
-#: src/aosd/aosd_ui.c:965
+#: src/aosd/aosd_ui.cc:869
 msgid "Misc"
 msgstr "雜項"
 
-#: src/asx3/asx3.c:179
+#: src/aosd/aosd_ui.cc:878
+msgid "Test"
+msgstr "測試"
+
+#: src/asx3/asx3.cc:35
 msgid "ASXv3 Playlists"
 msgstr "ASXv3 播放清單"
 
-#: src/asx/asx.c:83
+#: src/asx/asx.cc:33
 msgid "ASXv1/ASXv2 Playlists"
 msgstr "ASXv1/ASXv2 播放清單"
 
-#: src/audpl/audpl.c:186
+#: src/audpl/audpl.cc:33
 msgid "Audacious Playlists (audpl)"
 msgstr "Audacious 播放清單 (audpl)"
 
-#: src/blur_scope/blur_scope.c:47
+#: src/blur_scope/blur_scope.cc:42
 msgid "<b>Color</b>"
 msgstr "<b>色彩</b>"
 
-#: src/blur_scope/blur_scope.c:56
+#: src/blur_scope/blur_scope.cc:58
 msgid "Blur Scope"
 msgstr "模糊波形"
 
-#: src/bs2b/plugin.c:142
+#: src/bs2b/plugin.cc:38
+msgid "Bauer Stereophonic-to-Binaural (BS2B)"
+msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
+
+#: src/bs2b/plugin.cc:129
+msgid "Presets:"
+msgstr "樣式"
+
+#: src/bs2b/plugin.cc:136
 msgid "Feed level:"
 msgstr "饋送等級:"
 
-#: src/bs2b/plugin.c:154
+#: src/bs2b/plugin.cc:138
+msgid "x1/10 dB"
+msgstr "x1/10 dB"
+
+#: src/bs2b/plugin.cc:139
 msgid "Cut frequency:"
 msgstr "截斷頻率:"
 
-#: src/bs2b/plugin.c:166
-msgid "Presets:"
-msgstr "樣式"
-
-#: src/bs2b/plugin.c:189
-msgid "Bauer Stereophonic-to-Binaural (BS2B)"
-msgstr "Bauer Stereophonic-to-Binaural (BS2B)"
-
-#: src/cairo-spectrum/cairo-spectrum.c:297
+#: src/cairo-spectrum/cairo-spectrum.cc:41
 msgid "Spectrum Analyzer"
 msgstr "頻譜分析儀"
 
-#: src/cdaudio-ng/cdaudio-ng.c:101
+#: src/cdaudio-ng/cdaudio-ng.cc:72
+msgid "Audio CD Plugin"
+msgstr "音樂 CD 外掛"
+
+#: src/cdaudio-ng/cdaudio-ng.cc:121
 msgid ""
 "Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n"
 "\n"
@@ -844,171 +830,158 @@ msgstr ""
 "\n"
 "This was a Google Summer of Code 2007 project."
 
-#: src/cdaudio-ng/cdaudio-ng.c:119
+#: src/cdaudio-ng/cdaudio-ng.cc:137
 msgid "<b>Device</b>"
 msgstr "<b>裝置</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:120
+#: src/cdaudio-ng/cdaudio-ng.cc:138
 msgid "Read speed:"
 msgstr "讀取速度:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:123
+#: src/cdaudio-ng/cdaudio-ng.cc:141
 msgid "Override device:"
 msgstr "覆載裝置:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:125
+#: src/cdaudio-ng/cdaudio-ng.cc:143
 msgid "<b>Metadata</b>"
 msgstr "<b>詮釋資料</b>"
 
-#: src/cdaudio-ng/cdaudio-ng.c:126
+#: src/cdaudio-ng/cdaudio-ng.cc:144
 msgid "Use CD-Text"
 msgstr "使用 CD-Text"
 
-#: src/cdaudio-ng/cdaudio-ng.c:128
+#: src/cdaudio-ng/cdaudio-ng.cc:146
 msgid "Use CDDB"
 msgstr "使用 CDDB"
 
-#: src/cdaudio-ng/cdaudio-ng.c:130
+#: src/cdaudio-ng/cdaudio-ng.cc:148
 msgid "Use HTTP instead of CDDBP"
 msgstr "使用 HTTP 而非 CDDBP"
 
-#: src/cdaudio-ng/cdaudio-ng.c:132
+#: src/cdaudio-ng/cdaudio-ng.cc:151
 msgid "Server:"
 msgstr "伺服器:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:134
+#: src/cdaudio-ng/cdaudio-ng.cc:155
 msgid "Path:"
 msgstr "路徑:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:136
+#: src/cdaudio-ng/cdaudio-ng.cc:159
 msgid "Port:"
 msgstr "連接埠:"
 
-#: src/cdaudio-ng/cdaudio-ng.c:146
-msgid "Audio CD Plugin"
-msgstr "音樂 CD 外掛"
-
-#: src/cdaudio-ng/cdaudio-ng.c:244
+#: src/cdaudio-ng/cdaudio-ng.cc:246
 msgid "Failed to initialize cdio subsystem."
 msgstr "無法初始化 cdio 子系統。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:300
+#: src/cdaudio-ng/cdaudio-ng.cc:281
 #, c-format
 msgid "Invalid URI %s."
 msgstr "無效的 URI %s。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:302
+#: src/cdaudio-ng/cdaudio-ng.cc:283
 #, c-format
 msgid "Track %d not found."
 msgstr "找不到音軌 %d。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:304
+#: src/cdaudio-ng/cdaudio-ng.cc:285
 #, c-format
 msgid "Track %d is a data track."
 msgstr "軌道 %d 是資料軌。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:306
-msgid "Failed to open audio output."
-msgstr "無法開啟音訊輸出。"
-
-#: src/cdaudio-ng/cdaudio-ng.c:378
+#: src/cdaudio-ng/cdaudio-ng.cc:360
 msgid "Error reading audio CD."
 msgstr "讀取音樂 CD 時發生錯誤。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:449
+#: src/cdaudio-ng/cdaudio-ng.cc:429
 msgid "Audio CD"
 msgstr "音樂 CD"
 
-#: src/cdaudio-ng/cdaudio-ng.c:458
-#, c-format
-msgid "Track %d"
-msgstr "音軌 %d"
-
-#: src/cdaudio-ng/cdaudio-ng.c:485 src/cdaudio-ng/cdaudio-ng.c:494
+#: src/cdaudio-ng/cdaudio-ng.cc:460 src/cdaudio-ng/cdaudio-ng.cc:469
 #, c-format
 msgid "Failed to open CD device %s."
 msgstr "無法開啟 CD 裝置 %s。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:497
+#: src/cdaudio-ng/cdaudio-ng.cc:472
 msgid "No audio capable CD drive found."
 msgstr "找不到可以播放音訊的光碟機。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:524
+#: src/cdaudio-ng/cdaudio-ng.cc:497
 msgid "Failed to finish initializing opened CD drive."
 msgstr "開啟的光碟機無法完成初始化。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:537
+#: src/cdaudio-ng/cdaudio-ng.cc:510
 msgid "Failed to retrieve first/last track number."
 msgstr "無法取得第一個或最後的音軌編號。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:562
+#: src/cdaudio-ng/cdaudio-ng.cc:531
 #, c-format
 msgid "Cannot read start/end LSN for track %d."
 msgstr "無法讀取音軌 %d 的起始/結束邏輯磁區編號。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:646
+#: src/cdaudio-ng/cdaudio-ng.cc:613
 msgid "Failed to create the cddb connection."
 msgstr "無法建立 cddb 的連線。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:721
+#: src/cdaudio-ng/cdaudio-ng.cc:679
 msgid "Failed to query the CDDB server"
 msgstr "無法查詢 CDDB 伺服器"
 
-#: src/cdaudio-ng/cdaudio-ng.c:723
+#: src/cdaudio-ng/cdaudio-ng.cc:681
 #, c-format
 msgid "Failed to query the CDDB server: %s"
 msgstr "無法查詢 CDDB 伺服器:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:747
+#: src/cdaudio-ng/cdaudio-ng.cc:705
 #, c-format
 msgid "Failed to read the cddb info: %s"
 msgstr "無法讀取 cddb 資訊:%s"
 
-#: src/cdaudio-ng/cdaudio-ng.c:818
+#: src/cdaudio-ng/cdaudio-ng.cc:765
 msgid "Drive is empty."
 msgstr "光碟機是空的。"
 
-#: src/cdaudio-ng/cdaudio-ng.c:820
+#: src/cdaudio-ng/cdaudio-ng.cc:767
 msgid "Unsupported disk type."
 msgstr "未支援的光碟類型"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:35
+msgid "Audio CD Menu Items"
+msgstr "音樂 CD 選單項目"
+
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Play CD"
 msgstr "播放 CD"
 
-#: src/cd-menu-items/cd-menu-items.c:31
+#: src/cd-menu-items/cd-menu-items.cc:47
 msgid "Add CD"
 msgstr "加入 CD"
 
-#: src/cd-menu-items/cd-menu-items.c:56
-msgid "Audio CD Menu Items"
-msgstr "音樂 CD 選單項目"
-
-#: src/compressor/plugin.c:35
+#: src/compressor/compressor.cc:45
 msgid "<b>Compression</b>"
 msgstr "<b>壓縮</b>"
 
-#: src/compressor/plugin.c:36
+#: src/compressor/compressor.cc:46
 msgid "Center volume:"
 msgstr "中央音量:"
 
-#: src/compressor/plugin.c:39
+#: src/compressor/compressor.cc:49
 msgid "Dynamic range:"
 msgstr "動態範圍:"
 
-#: src/compressor/plugin.c:53
+#: src/compressor/compressor.cc:57
 msgid ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Dynamic Range Compression Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/compressor/plugin.c:58
+#: src/compressor/compressor.cc:64
 msgid "Dynamic Range Compressor"
 msgstr "動態範圍壓縮"
 
-#: src/console/plugin.c:19
+#: src/console/plugin.cc:15
 msgid ""
 "Console music decoder engine based on Game_Music_Emu 0.5.2\n"
 "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n"
@@ -1024,205 +997,235 @@ msgstr ""
 "William Pitcock <nenolod at dereferenced.org>\n"
 "Shay Green <gblargg at gmail.com>"
 
-#: src/console/plugin.c:34
+#: src/console/plugin.cc:30
 msgid "Bass:"
 msgstr "低音"
 
-#: src/console/plugin.c:36
+#: src/console/plugin.cc:33
 msgid "Treble:"
 msgstr "高音"
 
-#: src/console/plugin.c:38
+#: src/console/plugin.cc:36
 msgid "Echo:"
 msgstr "回音:"
 
-#: src/console/plugin.c:40
+#: src/console/plugin.cc:39
 msgid "Default song length:"
 msgstr "預設歌曲長度:"
 
-#: src/console/plugin.c:43 src/modplug/plugin_main.c:65
+#: src/console/plugin.cc:42 src/modplug/plugin_main.cc:59
 msgid "<b>Resampling</b>"
 msgstr "<b>重取樣</b>"
 
-#: src/console/plugin.c:44
+#: src/console/plugin.cc:43
 msgid "Enable audio resampling"
 msgstr "啟用聲音重取樣"
 
-#: src/console/plugin.c:46
-msgid "Resampling rate:"
-msgstr "重取樣率"
-
-#: src/console/plugin.c:47 src/modplug/plugin_main.c:96
-#: src/resample/resample.c:182 src/resample/resample.c:188
-#: src/resample/resample.c:191 src/resample/resample.c:194
-#: src/resample/resample.c:197 src/resample/resample.c:200
-#: src/resample/resample.c:203 src/resample/resample.c:206
-#: src/sox-resampler/sox-resampler.c:155
-msgid "Hz"
-msgstr "Hz"
-
-#: src/console/plugin.c:49
+#: src/console/plugin.cc:49
 msgid "<b>SPC</b>"
 msgstr "<b>SPC</b>"
 
-#: src/console/plugin.c:50
+#: src/console/plugin.cc:50
 msgid "Ignore length from SPC tags"
 msgstr "忽略 SPC 標籤裡記錄的長度"
 
-#: src/console/plugin.c:52
+#: src/console/plugin.cc:52
 msgid "Increase reverb"
 msgstr "增加殘響強度"
 
-#: src/console/plugin.c:61
+#: src/console/plugin.h:26
 msgid "Game Console Music Decoder"
 msgstr "遊戲主機音樂解碼器"
 
-#: src/crossfade/crossfade.c:83
-msgid ""
-"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."
-msgstr ""
-"因為歌曲間的聲道數不同,無法使用 Crossfade。您可以使用聲道混合將歌曲轉換成相"
-"同的聲道數量。"
+#: src/coreaudio/coreaudio.cc:50
+msgid "CoreAudio output"
+msgstr "CoreAudio 輸出"
 
-#: src/crossfade/crossfade.c:90
+#: src/coreaudio/coreaudio.cc:131
 msgid ""
-"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."
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
 msgstr ""
-"淡入淡出失敗,因為歌曲間的取樣率不同。您可以使用取樣率轉換功能來取得相同的取"
-"樣率。"
+"CoreAudio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/coreaudio/coreaudio.cc:143
+msgid "Use exclusive mode"
+msgstr "使用獨占模式"
 
-#: src/crossfade/crossfade.c:256
+#: src/crossfade/crossfade.cc:44
 msgid ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 msgstr ""
 "Crossfade Plugin for Audacious\n"
-"Copyright 2010-2012 John Lindgren"
+"Copyright 2010-2014 John Lindgren"
 
-#: src/crossfade/crossfade.c:260
+#: src/crossfade/crossfade.cc:48
 msgid "<b>Crossfade</b>"
 msgstr "<b>淡入淡出</b>"
 
-#: src/crossfade/crossfade.c:261
+#: src/crossfade/crossfade.cc:49
+msgid "On automatic song change"
+msgstr "自動切換歌曲時"
+
+#: src/crossfade/crossfade.cc:51 src/crossfade/crossfade.cc:57
 msgid "Overlap:"
 msgstr "重疊:"
 
-#: src/crossfade/crossfade.c:271
+#: src/crossfade/crossfade.cc:55
+msgid "On seek or manual song change"
+msgstr "跳轉或手動切換歌曲時"
+
+#: src/crossfade/crossfade.cc:61
+msgid "<b>Tip</b>"
+msgstr "<b>提示</b>"
+
+#: src/crossfade/crossfade.cc:62
+msgid ""
+"For better crossfading, enable\n"
+"the Silence Removal effect."
+msgstr "為了有較佳的效果,請一併啟用移除靜音。"
+
+#: src/crossfade/crossfade.cc:72
 msgid "Crossfade"
 msgstr "淡入淡出"
 
-#: src/crystalizer/crystalizer.c:40
+#: src/crossfade/crossfade.cc:161
+msgid ""
+"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."
+msgstr ""
+"因為歌曲間的聲道數不同,無法使用 Crossfade。您可以使用聲道混合將歌曲轉換成相"
+"同的聲道數量。"
+
+#: src/crossfade/crossfade.cc:168
+msgid ""
+"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."
+msgstr ""
+"淡入淡出失敗,因為歌曲間的取樣率不同。您可以使用取樣率轉換功能來取得相同的取"
+"樣率。"
+
+#: src/crystalizer/crystalizer.cc:31
 msgid "<b>Crystalizer</b>"
 msgstr "<b>Crystalizer</b>"
 
-#: src/crystalizer/crystalizer.c:41 src/stereo_plugin/stereo.c:26
+#: src/crystalizer/crystalizer.cc:32 src/stereo_plugin/stereo.cc:45
 msgid "Intensity:"
 msgstr "效果強度:"
 
-#: src/crystalizer/crystalizer.c:51
+#: src/crystalizer/crystalizer.cc:43
 msgid "Crystalizer"
 msgstr "Crystalizer"
 
-#: src/cue/cue.c:155
+#: src/cue/cue.cc:37
 msgid "Cue Sheet Plugin"
 msgstr "Cue Sheet 外掛"
 
-#: src/delete-files/delete-files.c:48
+#: src/delete-files/delete-files.cc:46 src/delete-files/delete-files.cc:146
+msgid "Delete Files"
+msgstr "刪除檔案"
+
+#: src/delete-files/delete-files.cc:75
 #, c-format
 msgid "Error moving %s to trash: %s."
 msgstr "移動「%s」到垃圾桶時發生錯誤:%s。"
 
-#: src/delete-files/delete-files.c:60
+#: src/delete-files/delete-files.cc:86
 #, c-format
 msgid "Error deleting %s: %s."
 msgstr "刪除「%s」時發生錯誤:%s。"
 
-#: src/delete-files/delete-files.c:98
+#: src/delete-files/delete-files.cc:117
 #, c-format
 msgid "Error deleting %s: not a local file."
 msgstr "刪除「%s」時發生錯誤:這不是本機檔案。"
 
-#: src/delete-files/delete-files.c:119
+#: src/delete-files/delete-files.cc:134
 msgid "Do you want to move the selected files to the trash?"
 msgstr "您確定要將選擇的檔案移動到垃圾桶嗎?"
 
-#: src/delete-files/delete-files.c:120
+#: src/delete-files/delete-files.cc:135
 msgid "Move to Trash"
 msgstr "移動到垃圾桶"
 
-#: src/delete-files/delete-files.c:125
+#: src/delete-files/delete-files.cc:140
 msgid "Do you want to permanently delete the selected files?"
 msgstr "您確定要永久地刪除選擇的檔案嗎?"
 
-#: src/delete-files/delete-files.c:126 src/skins/preset-list.c:416
-#: src/skins/preset-list.c:432
+#: src/delete-files/delete-files.cc:141 src/skins/preset-list.cc:411
+#: src/skins/preset-list.cc:427
 msgid "Delete"
 msgstr "刪除"
 
-#: src/delete-files/delete-files.c:130 src/skins/preset-browser.c:56
-#: src/skins/preset-list.c:311 src/skins/ui_playlist.c:224
-#: src/sndio/sndio.c:424
+#: src/delete-files/delete-files.cc:145 src/skins/preset-browser.cc:56
+#: src/skins/preset-list.cc:307 src/skins/ui_playlist.cc:221
 msgid "Cancel"
 msgstr "取消"
 
-#: src/delete-files/delete-files.c:131 src/delete-files/delete-files.c:172
-msgid "Delete Files"
-msgstr "刪除檔案"
-
-#: src/delete-files/delete-files.c:147
+#: src/delete-files/delete-files.cc:166
 msgid "Delete Selected Files"
 msgstr "刪除選擇的檔案"
 
-#: src/delete-files/delete-files.c:162
+#: src/delete-files/delete-files.cc:181
 msgid "<b>Delete Method</b>"
 msgstr "<b>刪除方式</b>"
 
-#: src/delete-files/delete-files.c:163
+#: src/delete-files/delete-files.cc:182
 msgid "Move to trash instead of deleting immediately"
 msgstr "移動到垃圾桶而不是直接刪除"
 
-#: src/echo_plugin/echo.c:26
+#: src/echo_plugin/echo.cc:9
+msgid ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+msgstr ""
+"Echo Plugin\n"
+"By Johan Levin, 1999\n"
+"Surround echo by Carl van Schaik, 1999\n"
+"Updated for Audacious by William Pitcock and John Lindgren, 2010-2014"
+
+#: src/echo_plugin/echo.cc:21
 msgid "<b>Echo</b>"
 msgstr "<b>回音</b>"
 
-#: src/echo_plugin/echo.c:27 src/modplug/plugin_main.c:88
-#: src/modplug/plugin_main.c:102
+#: src/echo_plugin/echo.cc:22 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "Delay:"
 msgstr "延遲:"
 
-#: src/echo_plugin/echo.c:29 src/modplug/plugin_main.c:89
-#: src/modplug/plugin_main.c:103
+#: src/echo_plugin/echo.cc:24 src/modplug/plugin_main.cc:73
+#: src/modplug/plugin_main.cc:83
 msgid "ms"
 msgstr "毫秒"
 
-#: src/echo_plugin/echo.c:30
+#: src/echo_plugin/echo.cc:25
 msgid "Feedback:"
 msgstr "反饋:"
 
-#: src/echo_plugin/echo.c:33 src/modplug/plugin_main.c:107
+#: src/echo_plugin/echo.cc:28 src/modplug/plugin_main.cc:87
 msgid "Volume:"
 msgstr "音量:"
 
-#: src/echo_plugin/echo.c:116
-msgid ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-msgstr ""
-"Echo Plugin\n"
-"By Johan Levin, 1999\n"
-"\n"
-"Surround echo by Carl van Schaik, 1999"
-
-#: src/echo_plugin/echo.c:122
+#: src/echo_plugin/echo.cc:39
 msgid "Echo"
 msgstr "回音"
 
-#: src/ffaudio/ffaudio-core.c:589
+#: src/ffaudio/ffaudio-core.cc:41
+msgid "FFmpeg Plugin"
+msgstr "FFmpeg 外掛"
+
+#: src/ffaudio/ffaudio-core.cc:571
 msgid ""
 "Multi-format audio decoding plugin for Audacious using\n"
 "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
@@ -1238,55 +1241,55 @@ msgstr ""
 "William Pitcock <nenolod at nenolod.net>\n"
 "Matti Hämäläinen <ccr at tnsp.org>"
 
-#: src/ffaudio/ffaudio-core.c:641
-msgid "FFmpeg Plugin"
-msgstr "FFmpeg 外掛"
+#: src/filewriter/filewriter.cc:45
+msgid "FileWriter Plugin"
+msgstr "檔案輸出外掛"
 
-#: src/filewriter/filewriter.c:404
+#: src/filewriter/filewriter.cc:386
 msgid "Output file format:"
 msgstr "輸出檔案格式:"
 
-#: src/filewriter/filewriter.c:421
+#: src/filewriter/filewriter.cc:403
 msgid "Configure"
 msgstr "設定"
 
-#: src/filewriter/filewriter.c:431
+#: src/filewriter/filewriter.cc:413
 msgid "Save into original directory"
 msgstr "儲存到原始資料夾"
 
-#: src/filewriter/filewriter.c:435
+#: src/filewriter/filewriter.cc:417
 msgid "Save into custom directory"
 msgstr "儲存到自訂資料夾"
 
-#: src/filewriter/filewriter.c:445
+#: src/filewriter/filewriter.cc:427
 msgid "Output file folder:"
 msgstr "輸出檔案資料夾:"
 
-#: src/filewriter/filewriter.c:449
+#: src/filewriter/filewriter.cc:431
 msgid "Pick a folder"
 msgstr "選擇一個資料夾"
 
-#: src/filewriter/filewriter.c:462
-msgid "Get filename from:"
-msgstr "檔名來源:"
+#: src/filewriter/filewriter.cc:444
+msgid "Generate file name from:"
+msgstr "產生檔名自:"
 
-#: src/filewriter/filewriter.c:466
-msgid "original file tags"
-msgstr "原始檔案標籤"
+#: src/filewriter/filewriter.cc:448
+msgid "Original file tag"
+msgstr "原始檔案的標籤"
 
-#: src/filewriter/filewriter.c:471
-msgid "original filename"
-msgstr "原始檔名"
+#: src/filewriter/filewriter.cc:453
+msgid "Original file name"
+msgstr "原始檔案的檔名"
 
-#: src/filewriter/filewriter.c:477
-msgid "Don't strip file name extension"
-msgstr "不要去掉副檔名"
+#: src/filewriter/filewriter.cc:459
+msgid "Include original file name extension"
+msgstr "包含原始檔案的副檔名"
 
-#: src/filewriter/filewriter.c:486
-msgid "Prepend track number to filename"
-msgstr "在檔名前面加上音軌號碼"
+#: src/filewriter/filewriter.cc:468
+msgid "Prepend track number to file name"
+msgstr "在檔案名稱前加入音軌編號"
 
-#: src/filewriter/filewriter.c:502
+#: src/filewriter/filewriter.cc:484
 msgid ""
 "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"
@@ -1318,165 +1321,169 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/filewriter/filewriter.c:527
-msgid "FileWriter Plugin"
-msgstr "檔案輸出外掛"
-
-#: src/filewriter/mp3.c:38 src/filewriter/mp3.c:749
+#: src/filewriter/mp3.cc:40 src/filewriter/mp3.cc:717
 msgid "Auto"
 msgstr "自動"
 
-#: src/filewriter/mp3.c:38
+#: src/filewriter/mp3.cc:40
 msgid "Joint Stereo"
 msgstr "聯合立體聲"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:63
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:58
+#: src/mpg123/mpg123.cc:248
 msgid "Stereo"
 msgstr "立體聲"
 
-#: src/filewriter/mp3.c:39 src/modplug/plugin_main.c:61
-#: src/mpg123/mpg123.c:210
+#: src/filewriter/mp3.cc:41 src/modplug/plugin_main.cc:57
+#: src/mpg123/mpg123.cc:248
 msgid "Mono"
 msgstr "單聲道"
 
-#: src/filewriter/mp3.c:689
+#: src/filewriter/mp3.cc:657
 msgid "MP3 Configuration"
 msgstr "MP3 設定"
 
-#: src/filewriter/mp3.c:713
+#: src/filewriter/mp3.cc:658
+msgid "_OK"
+msgstr "確認(_O)"
+
+#: src/filewriter/mp3.cc:681
 msgid "Algorithm Quality:"
 msgstr "演算法品質:"
 
-#: src/filewriter/mp3.c:738
-msgid "Output Samplerate:"
+#: src/filewriter/mp3.cc:706
+msgid "Output Sample Rate:"
 msgstr "輸出取樣率:"
 
-#: src/filewriter/mp3.c:766
+#: src/filewriter/mp3.cc:733
 msgid "(Hz)"
 msgstr "(Hz)"
 
-#: src/filewriter/mp3.c:773
-msgid "Bitrate / Compression ratio:"
-msgstr "位元率/壓縮比率:"
+#: src/filewriter/mp3.cc:740
+msgid "Bitrate / Compression Ratio:"
+msgstr "位元率/壓縮比:"
 
-#: src/filewriter/mp3.c:797
+#: src/filewriter/mp3.cc:764
 msgid "Bitrate (kbps):"
 msgstr "位元率 (kbps):"
 
-#: src/filewriter/mp3.c:830
+#: src/filewriter/mp3.cc:796
 msgid "Compression ratio:"
 msgstr "壓縮比率:"
 
-#: src/filewriter/mp3.c:854
+#: src/filewriter/mp3.cc:820
 msgid "Audio Mode:"
 msgstr "音訊模式:"
 
-#: src/filewriter/mp3.c:879
-msgid "Misc:"
-msgstr "雜項:"
+#: src/filewriter/mp3.cc:845
+msgid "Miscellaneous:"
+msgstr "其他選項:"
 
-#: src/filewriter/mp3.c:890
-msgid "Enforce strict ISO complience"
-msgstr "強制嚴格相容於 ISO"
+#: src/filewriter/mp3.cc:856
+msgid "Enforce strict ISO compliance"
+msgstr "強制要求 ISO 相容"
 
-#: src/filewriter/mp3.c:901
+#: src/filewriter/mp3.cc:867
 msgid "Error protection"
 msgstr "錯誤保護"
 
-#: src/filewriter/mp3.c:913 src/filewriter/vorbis.c:220
+#: src/filewriter/mp3.cc:879 src/filewriter/vorbis.cc:206
 msgid "Quality"
 msgstr "品質"
 
-#: src/filewriter/mp3.c:922
+#: src/filewriter/mp3.cc:888
 msgid "Enable VBR/ABR"
 msgstr "啟用 VBR/ABR"
 
-#: src/filewriter/mp3.c:932
+#: src/filewriter/mp3.cc:898
 msgid "Type:"
 msgstr "類型:"
 
-#: src/filewriter/mp3.c:965
+#: src/filewriter/mp3.cc:931
 msgid "VBR Options:"
 msgstr "VBR 選項:"
 
-#: src/filewriter/mp3.c:981
+#: src/filewriter/mp3.cc:947
 msgid "Minimum bitrate (kbps):"
 msgstr "最小位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1008
+#: src/filewriter/mp3.cc:973
 msgid "Maximum bitrate (kbps):"
 msgstr "最大位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1031
+#: src/filewriter/mp3.cc:995
 msgid "Strictly enforce minimum bitrate"
 msgstr "強制使用最小位元率"
 
-#: src/filewriter/mp3.c:1043
+#: src/filewriter/mp3.cc:1007
 msgid "ABR Options:"
 msgstr "ABR 選項:"
 
-#: src/filewriter/mp3.c:1053
+#: src/filewriter/mp3.cc:1017
 msgid "Average bitrate (kbps):"
 msgstr "平均位元率 (kbps):"
 
-#: src/filewriter/mp3.c:1081
+#: src/filewriter/mp3.cc:1044
 msgid "VBR quality level:"
 msgstr "VBR 品質等級:"
 
-#: src/filewriter/mp3.c:1100
-msgid "Don't write Xing VBR header"
-msgstr "不要寫入 Xing VBR 檔頭"
+#: src/filewriter/mp3.cc:1063
+msgid "Omit Xing VBR header"
+msgstr "省略 Xing VBR 檔頭"
 
-#: src/filewriter/mp3.c:1113
+#: src/filewriter/mp3.cc:1076
 msgid "VBR/ABR"
 msgstr "VBR/ABR"
 
-#: src/filewriter/mp3.c:1122
-msgid "Frame parameters:"
+#: src/filewriter/mp3.cc:1085
+msgid "Frame Parameters:"
 msgstr "音框參數:"
 
-#: src/filewriter/mp3.c:1134
+#: src/filewriter/mp3.cc:1097
 msgid "Mark as copyright"
 msgstr "標示為版權"
 
-#: src/filewriter/mp3.c:1145
+#: src/filewriter/mp3.cc:1108
 msgid "Mark as original"
 msgstr "標示為原創"
 
-#: src/filewriter/mp3.c:1157
-msgid "ID3 params:"
+#: src/filewriter/mp3.cc:1120
+msgid "ID3 Parameters:"
 msgstr "ID3 參數:"
 
-#: src/filewriter/mp3.c:1168
+#: src/filewriter/mp3.cc:1131
 msgid "Force addition of version 2 tag"
 msgstr "強制加入第二版標籤"
 
-#: src/filewriter/mp3.c:1178
+#: src/filewriter/mp3.cc:1141
 msgid "Only add v1 tag"
 msgstr "只加入第一版標籤"
 
-#: src/filewriter/mp3.c:1185
+#: src/filewriter/mp3.cc:1148
 msgid "Only add v2 tag"
 msgstr "只加入第二版標籤"
 
-#: src/filewriter/mp3.c:1206
+#: src/filewriter/mp3.cc:1169
 msgid "Tags"
 msgstr "標籤"
 
-#: src/filewriter/vorbis.c:210
+#: src/filewriter/vorbis.cc:196
 msgid "Vorbis Encoder Configuration"
 msgstr "Vorbis 編碼器設定"
 
-#: src/filewriter/vorbis.c:233
+#: src/filewriter/vorbis.cc:219
 msgid "Quality level (0 - 10):"
 msgstr "品質等級 (0 - 10):"
 
-#: src/flacng/metadata.c:359 src/wavpack/wavpack.c:212
+#: src/flacng/flacng.h:35
+msgid "FLAC Decoder"
+msgstr "FLAC 解碼器"
+
+#: src/flacng/metadata.cc:351 src/wavpack/wavpack.cc:209
 msgid "lossless"
 msgstr "無損"
 
-#: src/flacng/plugin.c:187
+#: src/flacng/plugin.cc:169
 msgid ""
 "Original code by\n"
 "Ralf Ertzinger <ralf at skytale.net>\n"
@@ -1488,11 +1495,7 @@ msgstr ""
 "\n"
 "http://www.skytale.net/projects/bmp-flac2/"
 
-#: src/flacng/plugin.c:195
-msgid "FLAC Decoder"
-msgstr "FLAC 解碼器"
-
-#: src/gio/gio.c:295
+#: src/gio/gio.cc:34
 msgid ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
@@ -1500,11 +1503,19 @@ msgstr ""
 "GIO Plugin for Audacious\n"
 "Copyright 2009-2012 John Lindgren"
 
-#: src/gio/gio.c:314
+#: src/gio/gio.cc:42
 msgid "GIO Plugin"
 msgstr "GIO 外掛"
 
-#: src/gl-spectrum/gl-spectrum.c:400
+#: src/gio/gio.cc:153
+msgid "Read-and-append mode not supported"
+msgstr "不支援讀取並附加的存取模式"
+
+#: src/gio/gio.cc:166
+msgid "Invalid open mode"
+msgstr "無效的開啟模式"
+
+#: src/gl-spectrum/gl-spectrum.cc:51
 msgid ""
 "OpenGL Spectrum Analyzer for Audacious\n"
 "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
@@ -1524,533 +1535,619 @@ msgstr ""
 "\n"
 "License: GPLv2+"
 
-#: src/gl-spectrum/gl-spectrum.c:409
+#: src/gl-spectrum/gl-spectrum.cc:62
 msgid "OpenGL Spectrum Analyzer"
 msgstr "OpenGL 頻譜分析儀"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:41
+#: src/gl-spectrum-qt/gl-spectrum.cc:41
 msgid ""
-"Gnome Shortcut Plugin\n"
-"Lets you control the player with Gnome's shortcuts.\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 msgstr ""
-"Gnome Shortcut Plugin\n"
-"讓您使用 Gnome 的快速鍵控制播放器。\n"
+"OpenGL Spectrum Analyzer for Audacious\n"
+"Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+"Copyright 2014 William Pitcock\n"
 "\n"
-"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+"Based on the XMMS plugin:\n"
+"Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and "
+"4Front Technologies\n"
+"\n"
+"License: GPLv2+"
 
-#: src/gnomeshortcuts/gnomeshortcuts.c:47
-msgid "Gnome Shortcuts"
+#: src/gl-spectrum-qt/gl-spectrum.cc:53
+msgid "OpenGL Spectrum Analyzer (Qt)"
+msgstr "OpenGL 頻譜分析儀 (Qt)"
+
+#: src/gnomeshortcuts/gnomeshortcuts.cc:38
+msgid "GNOME Shortcuts"
 msgstr "Gnome 快速鍵"
 
-#: src/gtkui/columns.c:34
+#: src/gnomeshortcuts/gnomeshortcuts.cc:54
+msgid ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+msgstr ""
+"GNOME Shortcut Plugin\n"
+"Lets you control the player with GNOME's shortcuts.\n"
+"\n"
+"Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>"
+
+#: src/gtkui/columns.cc:35
 msgid "Entry number"
 msgstr "項目編號"
 
-#: src/gtkui/columns.c:34
+#: src/gtkui/columns.cc:36 src/playlist-manager/playlist-manager.cc:225
+#: src/qtui/playlist_model.cc:123
 msgid "Title"
 msgstr "標題"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:37 src/qtui/playlist_model.cc:125
 msgid "Artist"
 msgstr "藝人"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:38
 msgid "Year"
 msgstr "年份"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:39 src/qtui/playlist_model.cc:127
 msgid "Album"
 msgstr "專輯"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:40
+msgid "Album artist"
+msgstr "專輯藝人"
+
+#: src/gtkui/columns.cc:41
 msgid "Track"
 msgstr "音軌"
 
-#: src/gtkui/columns.c:35
+#: src/gtkui/columns.cc:42
 msgid "Genre"
 msgstr "é¡žåž‹"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:43
 msgid "Queue position"
 msgstr "佇列位置"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:44
 msgid "Length"
 msgstr "長度"
 
-#: src/gtkui/columns.c:36
+#: src/gtkui/columns.cc:45
 msgid "File path"
 msgstr "檔案路徑"
 
-#: src/gtkui/columns.c:36
-msgid "File name"
-msgstr "檔案名稱"
-
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:47
 msgid "Custom title"
 msgstr "自訂標題"
 
-#: src/gtkui/columns.c:37
+#: src/gtkui/columns.cc:48
 msgid "Bitrate"
 msgstr "位元率"
 
-#: src/gtkui/columns.c:286
+#: src/gtkui/columns.cc:308
 msgid "Available columns"
 msgstr "可用的欄位"
 
-#: src/gtkui/columns.c:312
+#: src/gtkui/columns.cc:334
 msgid "Displayed columns"
 msgstr "顯示的欄位"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:72 src/search-tool/search-tool.cc:40
+msgid "Search Tool"
+msgstr "搜尋工具"
+
+#: src/gtkui/layout.cc:167
 msgid "Dock at Left"
 msgstr "嵌入左方"
 
-#: src/gtkui/layout.c:119
+#: src/gtkui/layout.cc:167
 msgid "Dock at Right"
 msgstr "嵌入右方"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Top"
 msgstr "嵌入頂端"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Dock at Bottom"
 msgstr "嵌入底端"
 
-#: src/gtkui/layout.c:120
+#: src/gtkui/layout.cc:168
 msgid "Undock"
 msgstr "解除嵌入"
 
-#: src/gtkui/layout.c:120 src/ladspa/plugin.c:649
+#: src/gtkui/layout.cc:168 src/ladspa/plugin.cc:531
 msgid "Disable"
 msgstr "關閉"
 
-#: src/gtkui/layout.c:226 src/search-tool/search-tool.c:786
-msgid "Search Tool"
-msgstr "搜尋工具"
-
-#: src/gtkui/menus.c:127 src/statusicon/statusicon.c:262
+#: src/gtkui/menus.cc:126 src/qtui/main_window_actions.cc:93
+#: src/statusicon/statusicon.cc:276
 msgid "_Open Files ..."
 msgstr "開啟檔案(_O) ..."
 
-#: src/gtkui/menus.c:128
+#: src/gtkui/menus.cc:127
 msgid "Open _URL ..."
 msgstr "開啟網址(_U) ..."
 
-#: src/gtkui/menus.c:129
+#: src/gtkui/menus.cc:128 src/qtui/main_window_actions.cc:95
 msgid "_Add Files ..."
 msgstr "加入檔案(_A) ... "
 
-#: src/gtkui/menus.c:130
+#: src/gtkui/menus.cc:129
 msgid "Add U_RL ..."
 msgstr "加入網址(_R) ..."
 
-#: src/gtkui/menus.c:132
+#: src/gtkui/menus.cc:131
 msgid "Search _Library"
 msgstr "搜尋媒體櫃(_L)"
 
-#: src/gtkui/menus.c:134
+#: src/gtkui/menus.cc:133 src/qtui/main_window_actions.cc:98
 msgid "A_bout ..."
 msgstr "關於(_B) ..."
 
-#: src/gtkui/menus.c:135
+#: src/gtkui/menus.cc:134 src/qtui/main_window_actions.cc:99
 msgid "_Settings ..."
 msgstr "設定(_S) ..."
 
-#: src/gtkui/menus.c:136 src/statusicon/statusicon.c:270
+#: src/gtkui/menus.cc:135 src/qtui/main_window_actions.cc:103
+#: src/statusicon/statusicon.cc:284
 msgid "_Quit"
 msgstr "離開(_Q)"
 
-#: src/gtkui/menus.c:139 src/gtkui/menus.c:254
-#: src/search-tool/search-tool.c:674 src/statusicon/statusicon.c:264
+#: src/gtkui/menus.cc:139 src/gtkui/menus.cc:262
+#: src/qtui/main_window_actions.cc:107 src/search-tool/search-tool.cc:641
+#: src/statusicon/statusicon.cc:278
 msgid "_Play"
 msgstr "播放(_P)"
 
-#: src/gtkui/menus.c:140 src/statusicon/statusicon.c:265
+#: src/gtkui/menus.cc:140 src/qtui/main_window_actions.cc:108
+#: src/statusicon/statusicon.cc:279
 msgid "Paus_e"
 msgstr "暫停(_E)"
 
-#: src/gtkui/menus.c:141 src/statusicon/statusicon.c:266
+#: src/gtkui/menus.cc:141 src/qtui/main_window_actions.cc:109
+#: src/statusicon/statusicon.cc:280
 msgid "_Stop"
 msgstr "停止(_S)"
 
-#: src/gtkui/menus.c:142 src/statusicon/statusicon.c:263
+#: src/gtkui/menus.cc:142 src/qtui/main_window_actions.cc:110
+#: src/statusicon/statusicon.cc:277
 msgid "Pre_vious"
 msgstr "上一個(_V)"
 
-#: src/gtkui/menus.c:143 src/statusicon/statusicon.c:267
+#: src/gtkui/menus.cc:143 src/qtui/main_window_actions.cc:111
+#: src/statusicon/statusicon.cc:281
 msgid "_Next"
 msgstr "下一個(_N)"
 
-#: src/gtkui/menus.c:145
+#: src/gtkui/menus.cc:145 src/qtui/main_window_actions.cc:113
 msgid "_Repeat"
 msgstr "重複"
 
-#: src/gtkui/menus.c:146
+#: src/gtkui/menus.cc:146 src/qtui/main_window_actions.cc:114
 msgid "S_huffle"
 msgstr "隨機"
 
-#: src/gtkui/menus.c:147
+#: src/gtkui/menus.cc:147 src/qtui/main_window_actions.cc:115
 msgid "N_o Playlist Advance"
 msgstr "不要切換播放清單"
 
-#: src/gtkui/menus.c:149
+#: src/gtkui/menus.cc:148 src/qtui/main_window_actions.cc:116
 msgid "Stop A_fter This Song"
 msgstr "播放完目前歌曲後停止(_F)"
 
-#: src/gtkui/menus.c:152 src/gtkui/menus.c:242
+#: src/gtkui/menus.cc:150 src/gtkui/menus.cc:247
+#: src/qtui/main_window_actions.cc:118
 msgid "Song _Info ..."
 msgstr "歌曲資訊(_I) ..."
 
-#: src/gtkui/menus.c:153
+#: src/gtkui/menus.cc:151
 msgid "Jump to _Time ..."
 msgstr "跳轉到指定時間(_T) ..."
 
-#: src/gtkui/menus.c:154
+#: src/gtkui/menus.cc:152
 msgid "_Jump to Song ..."
 msgstr "跳轉到指定歌曲(_J) ..."
 
-#: src/gtkui/menus.c:156
+#: src/gtkui/menus.cc:154
 msgid "Set Repeat Point _A"
 msgstr "設定重複點 _A"
 
-#: src/gtkui/menus.c:157
+#: src/gtkui/menus.cc:155
 msgid "Set Repeat Point _B"
 msgstr "設定重複點 _B"
 
-#: src/gtkui/menus.c:158
+#: src/gtkui/menus.cc:156
 msgid "_Clear Repeat Points"
 msgstr "清除重複點(_C)"
 
-#: src/gtkui/menus.c:161 src/gtkui/menus.c:167 src/gtkui/menus.c:180
+#: src/gtkui/menus.cc:160 src/gtkui/menus.cc:167 src/gtkui/menus.cc:183
+#: src/qtui/main_window_actions.cc:122 src/qtui/main_window_actions.cc:129
+#: src/qtui/main_window_actions.cc:145
 msgid "By _Title"
 msgstr "標題(_T)"
 
-#: src/gtkui/menus.c:162
-msgid "By _Filename"
+#: src/gtkui/menus.cc:161 src/qtui/main_window_actions.cc:123
+msgid "By _File Name"
 msgstr "檔案名稱(_F)"
 
-#: src/gtkui/menus.c:163
+#: src/gtkui/menus.cc:162 src/qtui/main_window_actions.cc:124
 msgid "By File _Path"
 msgstr "檔案路徑(_P)"
 
-#: src/gtkui/menus.c:166 src/gtkui/menus.c:179
+#: src/gtkui/menus.cc:166 src/gtkui/menus.cc:182
+#: src/qtui/main_window_actions.cc:128 src/qtui/main_window_actions.cc:144
 msgid "By Track _Number"
 msgstr "音軌編號(_N)"
 
-#: src/gtkui/menus.c:168 src/gtkui/menus.c:181
+#: src/gtkui/menus.cc:168 src/gtkui/menus.cc:184
+#: src/qtui/main_window_actions.cc:130 src/qtui/main_window_actions.cc:146
 msgid "By _Artist"
 msgstr "藝人(_A)"
 
-#: src/gtkui/menus.c:169 src/gtkui/menus.c:182
+#: src/gtkui/menus.cc:169 src/gtkui/menus.cc:185
+#: src/qtui/main_window_actions.cc:131 src/qtui/main_window_actions.cc:147
 msgid "By Al_bum"
 msgstr "專輯(_B)"
 
-#: src/gtkui/menus.c:170 src/gtkui/menus.c:183
+#: src/gtkui/menus.cc:170 src/gtkui/menus.cc:186
+#: src/qtui/main_window_actions.cc:132 src/qtui/main_window_actions.cc:148
+msgid "By Albu_m Artist"
+msgstr "專輯藝人(_M)"
+
+#: src/gtkui/menus.cc:171 src/gtkui/menus.cc:187
+#: src/qtui/main_window_actions.cc:133 src/qtui/main_window_actions.cc:149
 msgid "By Release _Date"
 msgstr "發行日期(_D)"
 
-#: src/gtkui/menus.c:171 src/gtkui/menus.c:184
+#: src/gtkui/menus.cc:172 src/gtkui/menus.cc:188
+#: src/qtui/main_window_actions.cc:134 src/qtui/main_window_actions.cc:150
+msgid "By _Genre"
+msgstr "é¡žåž‹(_G)"
+
+#: src/gtkui/menus.cc:173 src/gtkui/menus.cc:189
+#: src/qtui/main_window_actions.cc:135 src/qtui/main_window_actions.cc:151
 msgid "By _Length"
 msgstr "長度(_L)"
 
-#: src/gtkui/menus.c:172 src/gtkui/menus.c:185
+#: src/gtkui/menus.cc:174 src/gtkui/menus.cc:190
+#: src/qtui/main_window_actions.cc:136 src/qtui/main_window_actions.cc:152
 msgid "By _File Path"
 msgstr "檔案路徑(_F)"
 
-#: src/gtkui/menus.c:173 src/gtkui/menus.c:186
+#: src/gtkui/menus.cc:175 src/gtkui/menus.cc:191
+#: src/qtui/main_window_actions.cc:137 src/qtui/main_window_actions.cc:153
 msgid "By _Custom Title"
 msgstr "自訂標題(_C)"
 
-#: src/gtkui/menus.c:175 src/gtkui/menus.c:188
+#: src/gtkui/menus.cc:177 src/gtkui/menus.cc:193
+#: src/qtui/main_window_actions.cc:139 src/qtui/main_window_actions.cc:155
 msgid "R_everse Order"
 msgstr "反向順序(_E)"
 
-#: src/gtkui/menus.c:176 src/gtkui/menus.c:189
+#: src/gtkui/menus.cc:178 src/gtkui/menus.cc:194
+#: src/qtui/main_window_actions.cc:140 src/qtui/main_window_actions.cc:156
 msgid "_Random Order"
 msgstr "隨機順序(_R)"
 
-#: src/gtkui/menus.c:192
-msgid "_Play This Playlist"
-msgstr "播放此清單(_P)"
+#: src/gtkui/menus.cc:198 src/qtui/main_window_actions.cc:160
+msgid "_Play/Resume"
+msgstr "播放/回復(_P)"
 
-#: src/gtkui/menus.c:193 src/gtkui/menus.c:244
+#: src/gtkui/menus.cc:199 src/gtkui/menus.cc:251
+#: src/qtui/main_window_actions.cc:161
 msgid "_Refresh"
 msgstr "重新整理(_R)"
 
-#: src/gtkui/menus.c:195
+#: src/gtkui/menus.cc:201 src/qtui/main_window_actions.cc:163
 msgid "_Sort"
 msgstr "排序(_S)"
 
-#: src/gtkui/menus.c:196
+#: src/gtkui/menus.cc:202 src/qtui/main_window_actions.cc:164
 msgid "Sort Se_lected"
 msgstr "排序選擇的項目(_L)"
 
-#: src/gtkui/menus.c:197
+#: src/gtkui/menus.cc:203 src/qtui/main_window_actions.cc:165
 msgid "Remove _Duplicates"
 msgstr "移除重複的項目(_D)"
 
-#: src/gtkui/menus.c:198
+#: src/gtkui/menus.cc:204 src/qtui/main_window_actions.cc:166
 msgid "Remove _Unavailable Files"
 msgstr "移除不存在的檔案(_U)"
 
-#: src/gtkui/menus.c:200
+#: src/gtkui/menus.cc:206 src/playlist-manager/playlist-manager.cc:244
+#: src/qtui/main_window_actions.cc:168
 msgid "_New"
 msgstr "新增(_N)"
 
-#: src/gtkui/menus.c:201
+#: src/gtkui/menus.cc:207
 msgid "Ren_ame ..."
 msgstr "重新命名(_A) ..."
 
-#: src/gtkui/menus.c:202 src/gtkui/menus.c:256
+#: src/gtkui/menus.cc:208 src/gtkui/menus.cc:264
+#: src/qtui/main_window_actions.cc:170
 msgid "Remo_ve"
 msgstr "移除(_V)"
 
-#: src/gtkui/menus.c:204
+#: src/gtkui/menus.cc:210
 msgid "_Import ..."
 msgstr "匯入(_I) ..."
 
-#: src/gtkui/menus.c:205
+#: src/gtkui/menus.cc:211
 msgid "_Export ..."
 msgstr "匯出(_E) ..."
 
-#: src/gtkui/menus.c:207
+#: src/gtkui/menus.cc:213
 msgid "Playlist _Manager ..."
 msgstr "播放清單管理(_M) ..."
 
-#: src/gtkui/menus.c:208
+#: src/gtkui/menus.cc:214 src/qtui/main_window_actions.cc:176
 msgid "_Queue Manager ..."
 msgstr "佇列管理(_Q) ..."
 
-#: src/gtkui/menus.c:211
+#: src/gtkui/menus.cc:218 src/qtui/main_window_actions.cc:180
 msgid "Volume _Up"
 msgstr "提高音量(_U)"
 
-#: src/gtkui/menus.c:212
+#: src/gtkui/menus.cc:219 src/qtui/main_window_actions.cc:181
 msgid "Volume _Down"
 msgstr "降低音量(_D)"
 
-#: src/gtkui/menus.c:214
+#: src/gtkui/menus.cc:221 src/qtui/main_window_actions.cc:183
 msgid "_Equalizer"
 msgstr "等化器(_E)"
 
-#: src/gtkui/menus.c:216
+#: src/gtkui/menus.cc:223 src/qtui/main_window_actions.cc:185
 msgid "E_ffects ..."
 msgstr "特效(_F) ..."
 
-#: src/gtkui/menus.c:219
+#: src/gtkui/menus.cc:227
 msgid "Show _Menu Bar"
 msgstr "顯示選單列(_M)"
 
-#: src/gtkui/menus.c:221
+#: src/gtkui/menus.cc:228
 msgid "Show I_nfo Bar"
 msgstr "顯示資訊列(_N)"
 
-#: src/gtkui/menus.c:223
+#: src/gtkui/menus.cc:229
 msgid "Show Info Bar Vis_ualization"
 msgstr "顯示資訊列的視覺特效(_U)"
 
-#: src/gtkui/menus.c:225
+#: src/gtkui/menus.cc:230
 msgid "Show _Status Bar"
 msgstr "顯示狀態列(_S)"
 
-#: src/gtkui/menus.c:228
+#: src/gtkui/menus.cc:232
 msgid "Show _Remaining Time"
 msgstr "顯示剩餘時間(_R)"
 
-#: src/gtkui/menus.c:231
+#: src/gtkui/menus.cc:234
 msgid "_Visualizations ..."
 msgstr "視覺特效(_V) ..."
 
-#: src/gtkui/menus.c:234
+#: src/gtkui/menus.cc:238 src/qtui/main_window_actions.cc:189
 msgid "_File"
 msgstr "檔案(_F)"
 
-#: src/gtkui/menus.c:235
+#: src/gtkui/menus.cc:239 src/qtui/main_window_actions.cc:190
 msgid "_Playback"
 msgstr "播放(_P)"
 
-#: src/gtkui/menus.c:236
+#: src/gtkui/menus.cc:240 src/qtui/main_window_actions.cc:191
 msgid "P_laylist"
 msgstr "播放清單(_L)"
 
-#: src/gtkui/menus.c:237 src/gtkui/menus.c:251
+#: src/gtkui/menus.cc:241 src/gtkui/menus.cc:258
+#: src/qtui/main_window_actions.cc:192
 msgid "_Services"
 msgstr "服務(_S)"
 
-#: src/gtkui/menus.c:238
+#: src/gtkui/menus.cc:242 src/qtui/main_window_actions.cc:193
 msgid "_Output"
 msgstr "輸出(_O)"
 
-#: src/gtkui/menus.c:239
+#: src/gtkui/menus.cc:243
 msgid "_View"
 msgstr "檢視(_V)"
 
-#: src/gtkui/menus.c:243
+#: src/gtkui/menus.cc:248
 msgid "_Queue/Unqueue"
 msgstr "排入/移出佇列(_Q)"
 
-#: src/gtkui/menus.c:246
+#: src/gtkui/menus.cc:250
+msgid "_Open Containing Folder"
+msgstr "開啟該資料夾(_O)"
+
+#: src/gtkui/menus.cc:253
 msgid "Cu_t"
 msgstr "剪下(_T)"
 
-#: src/gtkui/menus.c:247
+#: src/gtkui/menus.cc:254
 msgid "_Copy"
 msgstr "複製(_C)"
 
-#: src/gtkui/menus.c:248
+#: src/gtkui/menus.cc:255
 msgid "_Paste"
 msgstr "貼上(_P)"
 
-#: src/gtkui/menus.c:249
+#: src/gtkui/menus.cc:256
 msgid "Select _All"
 msgstr "選擇全部(_A)"
 
-#: src/gtkui/menus.c:255
+#: src/gtkui/menus.cc:263
 msgid "_Rename ..."
 msgstr "重新命名(_R) ..."
 
-#: src/gtkui/settings.c:35
+#: src/gtkui/settings.cc:35
 msgid "<b>Playlist Tabs</b>"
 msgstr "<b>播放清單分頁</b>"
 
-#: src/gtkui/settings.c:36
+#: src/gtkui/settings.cc:36
 msgid "Always show tabs"
 msgstr "永遠顯示分頁"
 
-#: src/gtkui/settings.c:39
+#: src/gtkui/settings.cc:38
 msgid "Show entry counts"
 msgstr "顯示項目數量"
 
-#: src/gtkui/settings.c:42
+#: src/gtkui/settings.cc:40
 msgid "Show close buttons"
 msgstr "顯示關閉按鈕"
 
-#: src/gtkui/settings.c:45
+#: src/gtkui/settings.cc:42
 msgid "<b>Playlist Columns</b>"
 msgstr "<b>播放清單欄位</b>"
 
-#: src/gtkui/settings.c:47
+#: src/gtkui/settings.cc:44
 msgid "Show column headers"
 msgstr "顯示欄位標頭"
 
-#: src/gtkui/settings.c:50 src/modplug/plugin_main.c:131
-#: src/skins/skins_cfg.c:267
+#: src/gtkui/settings.cc:46 src/modplug/plugin_main.cc:106
+#: src/skins/skins_cfg.cc:263
 msgid "<b>Miscellaneous</b>"
 msgstr "<b>其他選項</b>"
 
-#: src/gtkui/settings.c:51
+#: src/gtkui/settings.cc:47
 msgid "Arrow keys seek by:"
 msgstr "按下方向鍵時跳轉的時間長度:"
 
-#: src/gtkui/settings.c:54
+#: src/gtkui/settings.cc:50
 msgid "Scroll on song change"
 msgstr "切換歌曲時捲動清單"
 
-#: src/gtkui/ui_gtk.c:94
+#: src/gtkui/ui_gtk.cc:71
 msgid "GTK Interface"
 msgstr "GTK 介面"
 
-#: src/gtkui/ui_gtk.c:192 src/skins/ui_main.c:233
+#: src/gtkui/ui_gtk.cc:222 src/skins/ui_main.cc:232
 #, c-format
 msgid "%s - Audacious"
 msgstr "%s - Audacious"
 
-#: src/gtkui/ui_gtk.c:197
+#: src/gtkui/ui_gtk.cc:225 src/qtui/main_window.cc:186
 msgid "Buffering ..."
 msgstr "緩衝中 ..."
 
-#: src/gtkui/ui_gtk.c:200 src/skins/ui_main.c:235 src/skins/ui_main.c:1143
+#: src/gtkui/ui_gtk.cc:228 src/skins/ui_main.cc:234 src/skins/ui_main.cc:1164
 msgid "Audacious"
 msgstr "Audacious"
 
-#: src/gtkui/ui_statusbar.c:86
+#: src/gtkui/ui_statusbar.cc:63 src/qtui/status_bar.cc:67
+msgid "mono"
+msgstr "單聲道"
+
+#: src/gtkui/ui_statusbar.cc:65 src/qtui/status_bar.cc:69
+msgid "stereo"
+msgstr "立體聲"
+
+#: src/gtkui/ui_statusbar.cc:67 src/qtui/status_bar.cc:71
 #, c-format
 msgid "%d channel"
 msgid_plural "%d channels"
 msgstr[0] "%d 聲道"
 
-#: src/gtkui/ui_statusbar.c:101
+#: src/gtkui/ui_statusbar.cc:81 src/qtui/status_bar.cc:85
 #, c-format
 msgid "%d kbps"
 msgstr "%d kbps"
 
-#: src/hotkey/gui.c:70
+#: src/gtkui/ui_statusbar.cc:107 src/skins/ui_main_evlisteners.cc:103
+msgid "Single mode."
+msgstr "單一模式。"
+
+#: src/gtkui/ui_statusbar.cc:109 src/skins/ui_main_evlisteners.cc:105
+msgid "Playlist mode."
+msgstr "播放清單模式。"
+
+#: src/gtkui/ui_statusbar.cc:117 src/skins/ui_main_evlisteners.cc:111
+msgid "Stopping after song."
+msgstr "播放完成後停止。"
+
+#: src/hotkey/gui.cc:71
 msgid "Previous track"
 msgstr "上一個音軌"
 
-#: src/hotkey/gui.c:71 src/notify/osd.c:68 src/skins/menus.c:78
+#: src/hotkey/gui.cc:72 src/notify/osd.cc:69 src/qtui/main_window.cc:69
+#: src/qtui/main_window.cc:172 src/qtui/main_window.cc:173
+#: src/skins/menus.cc:87
 msgid "Play"
 msgstr "播放"
 
-#: src/hotkey/gui.c:72
+#: src/hotkey/gui.cc:73
 msgid "Pause/Resume"
 msgstr "暫停/回復"
 
-#: src/hotkey/gui.c:73 src/skins/menus.c:80
+#: src/hotkey/gui.cc:74 src/qtui/main_window.cc:70 src/skins/menus.cc:89
 msgid "Stop"
 msgstr "停止"
 
-#: src/hotkey/gui.c:74
+#: src/hotkey/gui.cc:75
 msgid "Next track"
 msgstr "下一個音軌"
 
-#: src/hotkey/gui.c:75
+#: src/hotkey/gui.cc:76
 msgid "Forward 5 seconds"
 msgstr "快轉五秒"
 
-#: src/hotkey/gui.c:76
+#: src/hotkey/gui.cc:77
 msgid "Rewind 5 seconds"
 msgstr "倒轉五秒"
 
-#: src/hotkey/gui.c:77
+#: src/hotkey/gui.cc:78
 msgid "Mute"
 msgstr "靜音"
 
-#: src/hotkey/gui.c:78
+#: src/hotkey/gui.cc:79
 msgid "Volume up"
 msgstr "提高音量"
 
-#: src/hotkey/gui.c:79
+#: src/hotkey/gui.cc:80
 msgid "Volume down"
 msgstr "降低音量"
 
-#: src/hotkey/gui.c:80
+#: src/hotkey/gui.cc:81
 msgid "Jump to file"
 msgstr "跳轉到指定檔案"
 
-#: src/hotkey/gui.c:81
+#: src/hotkey/gui.cc:82
 msgid "Toggle player window(s)"
 msgstr "切換顯示播放器視窗"
 
-#: src/hotkey/gui.c:82
+#: src/hotkey/gui.cc:83
 msgid "Show On-Screen-Display"
 msgstr "顯示 OSD"
 
-#: src/hotkey/gui.c:83
+#: src/hotkey/gui.cc:84
 msgid "Toggle repeat"
 msgstr "切換重複播放"
 
-#: src/hotkey/gui.c:84
+#: src/hotkey/gui.cc:85
 msgid "Toggle shuffle"
 msgstr "切換隨機播放"
 
-#: src/hotkey/gui.c:85
+#: src/hotkey/gui.cc:86
 msgid "Toggle stop after current"
 msgstr "播放完目前歌曲後停止"
 
-#: src/hotkey/gui.c:86
+#: src/hotkey/gui.cc:87
 msgid "Raise player window(s)"
 msgstr "將播放器視窗放到最上層"
 
-#: src/hotkey/gui.c:96
+#: src/hotkey/gui.cc:97
 msgid "(none)"
 msgstr "(ç„¡)"
 
-#: src/hotkey/gui.c:233
+#: src/hotkey/gui.cc:234
 msgid ""
 "It is not recommended to bind the primary mouse buttons without "
 "modificators.\n"
@@ -2061,15 +2158,11 @@ msgstr ""
 "\n"
 "您想要繼續嗎?"
 
-#: src/hotkey/gui.c:235
+#: src/hotkey/gui.cc:236
 msgid "Binding mouse buttons"
 msgstr "綁定滑鼠按鈕"
 
-#: src/hotkey/gui.c:385
-msgid "Global Hotkey Plugin Configuration"
-msgstr "全域熱鍵外掛設定"
-
-#: src/hotkey/gui.c:400
+#: src/hotkey/gui.cc:391
 msgid ""
 "Press a key combination inside a text field.\n"
 "You can also bind mouse buttons."
@@ -2077,23 +2170,27 @@ msgstr ""
 "請在輸入欄位中按下想要的按鍵組合。\n"
 "您也可以綁定滑鼠按鈕。"
 
-#: src/hotkey/gui.c:405
+#: src/hotkey/gui.cc:396
 msgid "Hotkeys:"
 msgstr "熱鍵:"
 
-#: src/hotkey/gui.c:422
+#: src/hotkey/gui.cc:413
 msgid "<b>Action:</b>"
 msgstr "<b>動作:</b>"
 
-#: src/hotkey/gui.c:429
+#: src/hotkey/gui.cc:420
 msgid "<b>Key Binding:</b>"
 msgstr "<b>按鍵綁定:</b>"
 
-#: src/hotkey/gui.c:476
+#: src/hotkey/gui.cc:468
 msgid "_Add"
 msgstr "加入(_A)"
 
-#: src/hotkey/plugin.c:67
+#: src/hotkey/plugin.cc:61
+msgid "Global Hotkeys"
+msgstr "全域熱鍵"
+
+#: src/hotkey/plugin.cc:79
 msgid ""
 "Global Hotkey Plugin\n"
 "Control the player with global key combinations or multimedia keys.\n"
@@ -2119,60 +2216,54 @@ msgstr ""
 " Jonathan A. Davis <davis at jdhouse.org>,\n"
 " Jeremy Tan <nsx at nsx.homeip.net>"
 
-#: src/hotkey/plugin.c:79
-msgid "Global Hotkeys"
-msgstr "全域熱鍵"
+#: src/jack-ng/jack-ng.cc:49
+msgid "JACK Output"
+msgstr "JACK 輸出"
 
-#: src/jack/jack.c:196
-msgid "Connect to all available jack ports"
-msgstr "連接到所有可用的 jack 連接埠"
+#: src/jack-ng/jack-ng.cc:114
+msgid "Automatically connect to output ports"
+msgstr "自動連接到輸出埠"
 
-#: src/jack/jack.c:197
-msgid "Connect only the output ports"
-msgstr "僅連接到輸出埠"
+#: src/jack-ng/jack-ng.cc:155
+#, c-format
+msgid "Only %d JACK output ports were found but %d are required."
+msgstr "只找到 %d 個 JACK 輸出埠,但系統需要 %d 個。"
 
-#: src/jack/jack.c:198
-msgid "Don't connect to any port"
-msgstr "不要連接到任何連接埠"
+#: src/jack-ng/jack-ng.cc:164
+#, c-format
+msgid "Failed to connect to JACK port %s."
+msgstr "無法連接到 JACK 埠 %s 。"
 
-#: src/jack/jack.c:202
-msgid "Connection mode:"
-msgstr "連線模式:"
+#: src/jack-ng/jack-ng.cc:184
+msgid ""
+"JACK supports only floating-point audio.  You must change the output bit "
+"depth to floating-point in Audacious settings."
+msgstr ""
+"JACK 只支援浮點數音訊。您必須在 Audacious 設定中將輸出的取樣格式改為浮點數。"
 
-#: src/jack/jack.c:205
-msgid "Enable debug printing"
-msgstr "啟用除錯輸出"
+#: src/jack-ng/jack-ng.cc:197
+msgid "Failed to connect to the JACK server; is it running?"
+msgstr "無法連接到 JACK 伺服器。請確認它是否正常運作。"
 
-#: src/jack/jack.c:432
+#: src/jack-ng/jack-ng.cc:273
+#, c-format
 msgid ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"The JACK server requires a sample rate of %d Hz, but Audacious is playing at "
+"%d Hz.  Please use the Sample Rate Converter effect to correct the mismatch."
 msgstr ""
-"Based on xmms-jack, by Chris Morgan:\n"
-"http://xmms-jack.sourceforge.net/\n"
-"\n"
-"Ported to Audacious by Giacomo Lozito"
+"JACK 伺服器需要使用 %d Hz 的取樣率,但 Audacious 目前正以 %d Hz 播放中。請使"
+"用「取樣率轉換」特效修正這個問題。"
 
-#: src/jack/jack.c:438
-msgid "JACK Output"
-msgstr "JACK 輸出"
-
-#: src/ladspa/plugin.c:519
+#: src/ladspa/plugin.cc:414
 #, c-format
 msgid "%s Settings"
 msgstr "%s 設定"
 
-#: src/ladspa/plugin.c:587
-msgid "LADSPA Host Settings"
-msgstr "LADSPA 主控端設定"
-
-#: src/ladspa/plugin.c:596
+#: src/ladspa/plugin.cc:478
 msgid "Module paths:"
 msgstr "模組路徑:"
 
-#: src/ladspa/plugin.c:601
+#: src/ladspa/plugin.cc:483
 msgid ""
 "<small>Separate multiple paths with a colon.\n"
 "These paths are searched in addition to LADSPA_PATH.\n"
@@ -2182,25 +2273,25 @@ msgstr ""
 "系統除了 LADSPA_PATH 之外也會搜尋這些路徑。\n"
 "加入新路徑之後請按 Enter 掃描新的外掛。</small>"
 
-#: src/ladspa/plugin.c:617
+#: src/ladspa/plugin.cc:499
 msgid "Available plugins:"
 msgstr "可用的外掛:"
 
-#: src/ladspa/plugin.c:630 src/modplug/plugin_main.c:113
-#: src/modplug/plugin_main.c:117 src/modplug/plugin_main.c:121
-#: src/modplug/plugin_main.c:125
+#: src/ladspa/plugin.cc:512 src/modplug/plugin_main.cc:92
+#: src/modplug/plugin_main.cc:95 src/modplug/plugin_main.cc:98
+#: src/modplug/plugin_main.cc:101
 msgid "Enable"
 msgstr "啟用"
 
-#: src/ladspa/plugin.c:636
+#: src/ladspa/plugin.cc:518
 msgid "Enabled plugins:"
 msgstr "啟用外掛:"
 
-#: src/ladspa/plugin.c:652
+#: src/ladspa/plugin.cc:534
 msgid "Settings"
 msgstr "設定"
 
-#: src/ladspa/plugin.c:671
+#: src/ladspa/plugin.cc:551
 msgid ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
@@ -2208,47 +2299,15 @@ msgstr ""
 "LADSPA Host for Audacious\n"
 "Copyright 2011 John Lindgren"
 
-#: src/ladspa/plugin.c:676
+#: src/ladspa/plugin.h:78
 msgid "LADSPA Host"
 msgstr "LADSPA 主控端"
 
-#: src/lirc/lirc.c:74
-#, c-format
-msgid "%s: could not init LIRC support\n"
-msgstr "%s:無法初始化 LIRC 支援\n"
-
-#: src/lirc/lirc.c:81
-#, c-format
-msgid ""
-"%s: could not read LIRC config file\n"
-"%s: please read the documentation of LIRC\n"
-"%s: how to create a proper config file\n"
-msgstr ""
-"%s:無法讀取 LIRC 組態檔\n"
-"%s:請閱讀 LIRC 的相關文件\n"
-"%s:如何建立一個適合的組態檔\n"
-
-#: src/lirc/lirc.c:112
-#, c-format
-msgid "%s: trying to reconnect...\n"
-msgstr "%s:嘗試重新連線中...\n"
-
-#: src/lirc/lirc.c:352
-#, c-format
-msgid "%s: unknown command \"%s\"\n"
-msgstr "%s:未知的命令「%s」\n"
-
-#: src/lirc/lirc.c:363
-#, c-format
-msgid "%s: disconnected from LIRC\n"
-msgstr "%s:已從 LIRC 離線\n"
-
-#: src/lirc/lirc.c:369
-#, c-format
-msgid "%s: will try reconnect every %d seconds...\n"
-msgstr "%s:將每 %d 秒嘗試重新連線一次...\n"
+#: src/lirc/lirc.cc:55
+msgid "LIRC Plugin"
+msgstr "Linux 紅外線遙控器外掛"
 
-#: src/lirc/lirc.c:379
+#: src/lirc/lirc.cc:381
 msgid ""
 "A simple plugin to control Audacious using the LIRC remote control daemon\n"
 "\n"
@@ -2276,73 +2335,81 @@ msgstr ""
 "\n"
 "For more information about LIRC, see http://lirc.org."
 
-#: src/lirc/lirc.c:390
+#: src/lirc/lirc.cc:392
 msgid "<b>Connection</b>"
 msgstr "<b>連線</b>"
 
-#: src/lirc/lirc.c:391
+#: src/lirc/lirc.cc:393
 msgid "Reconnect to LIRC server"
 msgstr "重新連線到 LIRC 伺服器"
 
-#: src/lirc/lirc.c:393
+#: src/lirc/lirc.cc:395
 msgid "Wait before reconnecting:"
 msgstr "重新連線前的等待時間:"
 
-#: src/lirc/lirc.c:403
-msgid "LIRC Plugin"
-msgstr "Linux 紅外線遙控器外掛"
+#: src/lyricwiki/lyricwiki.cc:41
+msgid "LyricWiki Plugin"
+msgstr "LyricWiki 歌詞外掛"
 
-#: src/lyricwiki/lyricwiki.c:117
+#: src/lyricwiki/lyricwiki.cc:131 src/lyricwiki-qt/lyricwiki.cc:136
 msgid "No lyrics available"
 msgstr "無可用的歌詞"
 
-#: src/lyricwiki/lyricwiki.c:207 src/lyricwiki/lyricwiki.c:241
+#: src/lyricwiki/lyricwiki.cc:217 src/lyricwiki/lyricwiki.cc:226
+#: src/lyricwiki/lyricwiki.cc:243 src/lyricwiki/lyricwiki.cc:252
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:222
+#: src/lyricwiki-qt/lyricwiki.cc:231 src/lyricwiki-qt/lyricwiki.cc:248
+#: src/lyricwiki-qt/lyricwiki.cc:257 src/lyricwiki-qt/lyricwiki.cc:272
+msgid "Error"
+msgstr "錯誤"
+
+#: src/lyricwiki/lyricwiki.cc:218 src/lyricwiki/lyricwiki.cc:244
+#: src/lyricwiki-qt/lyricwiki.cc:223 src/lyricwiki-qt/lyricwiki.cc:249
 #, c-format
 msgid "Unable to fetch %s"
 msgstr "無法取得 %s"
 
-#: src/lyricwiki/lyricwiki.c:208 src/lyricwiki/lyricwiki.c:218
-#: src/lyricwiki/lyricwiki.c:242 src/lyricwiki/lyricwiki.c:252
-#: src/lyricwiki/lyricwiki.c:271
-msgid "Error"
-msgstr "錯誤"
-
-#: src/lyricwiki/lyricwiki.c:217 src/lyricwiki/lyricwiki.c:251
+#: src/lyricwiki/lyricwiki.cc:227 src/lyricwiki/lyricwiki.cc:253
+#: src/lyricwiki-qt/lyricwiki.cc:232 src/lyricwiki-qt/lyricwiki.cc:258
 #, c-format
 msgid "Unable to parse %s"
 msgstr "無法分析 %s"
 
-#: src/lyricwiki/lyricwiki.c:260
+#: src/lyricwiki/lyricwiki.cc:259 src/lyricwiki-qt/lyricwiki.cc:264
 msgid "Looking for lyrics ..."
 msgstr "尋找歌詞中 ..."
 
-#: src/lyricwiki/lyricwiki.c:271
+#: src/lyricwiki/lyricwiki.cc:267 src/lyricwiki-qt/lyricwiki.cc:272
 msgid "Missing song metadata"
 msgstr "找不到歌曲詮釋資料"
 
-#: src/lyricwiki/lyricwiki.c:284
+#: src/lyricwiki/lyricwiki.cc:278 src/lyricwiki-qt/lyricwiki.cc:283
 msgid "Connecting to lyrics.wikia.com ..."
 msgstr "連線到 lyrics.wikia.com 中 ..."
 
-#: src/lyricwiki/lyricwiki.c:411
-msgid "LyricWiki Plugin"
-msgstr "LyricWiki 歌詞外掛"
+#: src/lyricwiki-qt/lyricwiki.cc:55
+msgid "LyricWiki Plugin (Qt)"
+msgstr "LyricWiki 歌詞外掛 (Qt)"
 
-#: src/m3u/m3u.c:116
+#: src/m3u/m3u.cc:32
 msgid "M3U Playlists"
 msgstr "M3U 播放清單"
 
-#: src/metronom/metronom.c:127
+#: src/metronom/metronom.cc:44
+msgid "Tact Generator"
+msgstr "節拍產生器"
+
+#: src/metronom/metronom.cc:147
 #, c-format
 msgid "Tact generator: %d bpm"
 msgstr "節拍產生器:%d bpm"
 
-#: src/metronom/metronom.c:129
+#: src/metronom/metronom.cc:149
 #, c-format
 msgid "Tact generator: %d bpm %d/%d"
 msgstr "節拍產生器:%d bpm %d/%d"
 
-#: src/metronom/metronom.c:218
+#: src/metronom/metronom.cc:237
 msgid ""
 "A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n"
 "\n"
@@ -2356,11 +2423,11 @@ msgstr ""
 "範例:tact://77 播放 77 BPM\n"
 "或 tact://60*3/4 以 3/4 拍播放 60 BPM"
 
-#: src/metronom/metronom.c:227
-msgid "Tact Generator"
-msgstr "節拍產生器"
+#: src/mixer/mixer.cc:38
+msgid "Channel Mixer"
+msgstr "聲道混合"
 
-#: src/mixer/mixer.c:171
+#: src/mixer/mixer.cc:202
 msgid ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
@@ -2368,152 +2435,184 @@ msgstr ""
 "Channel Mixer Plugin for Audacious\n"
 "Copyright 2011-2012 John Lindgren and Michał Lipski"
 
-#: src/mixer/mixer.c:175
+#: src/mixer/mixer.cc:206
 msgid "<b>Channel Mixer</b>"
 msgstr "<b>聲道混合</b>"
 
-#: src/mixer/mixer.c:176
+#: src/mixer/mixer.cc:207
 msgid "Output channels:"
 msgstr "輸出聲道數目:"
 
-#: src/mixer/mixer.c:186
-msgid "Channel Mixer"
-msgstr "聲道混合"
-
-#: src/mms/mms.c:195
+#: src/mms/mms.cc:35
 msgid "MMS Plugin"
 msgstr "MMS 外掛"
 
-#: src/modplug/plugin_main.c:55
+#: src/mms/mms.cc:82
+msgid "Error connecting to MMS server"
+msgstr "連線到 MMS 伺服器時發生錯誤"
+
+#: src/modplug/modplugbmp.h:53
+msgid "ModPlug (Module Player)"
+msgstr "ModPlug (MOD 播放器)"
+
+#: src/modplug/plugin_main.cc:53
 msgid "<b>Resolution</b>"
 msgstr "<b>解析度</b>"
 
-#: src/modplug/plugin_main.c:56
+#: src/modplug/plugin_main.cc:54
 msgid "8-bit"
 msgstr "8-bit"
 
-#: src/modplug/plugin_main.c:58
+#: src/modplug/plugin_main.cc:55
 msgid "16-bit"
 msgstr "16-bit"
 
-#: src/modplug/plugin_main.c:60
+#: src/modplug/plugin_main.cc:56
 msgid "<b>Channels</b>"
 msgstr "<b>聲道</b>"
 
-#: src/modplug/plugin_main.c:66
+#: src/modplug/plugin_main.cc:60
 msgid "Nearest (fastest)"
 msgstr "最近點取樣(最快)"
 
-#: src/modplug/plugin_main.c:68
+#: src/modplug/plugin_main.cc:61
 msgid "Linear (fast)"
 msgstr "線性取樣(快)"
 
-#: src/modplug/plugin_main.c:70
+#: src/modplug/plugin_main.cc:62
 msgid "Spline (good)"
 msgstr "曲線函數(佳)"
 
-#: src/modplug/plugin_main.c:72
+#: src/modplug/plugin_main.cc:63
 msgid "Polyphase (best)"
 msgstr "多相位取樣(最佳)"
 
-#: src/modplug/plugin_main.c:74
-msgid "<b>Sampling rate</b>"
+#: src/modplug/plugin_main.cc:64
+msgid "<b>Sample rate</b>"
 msgstr "<b>取樣率</b>"
 
-#: src/modplug/plugin_main.c:75
+#: src/modplug/plugin_main.cc:65
 msgid "22 kHz"
 msgstr "22 kHz"
 
-#: src/modplug/plugin_main.c:77
+#: src/modplug/plugin_main.cc:66
 msgid "44 kHz"
 msgstr "44 kHz"
 
-#: src/modplug/plugin_main.c:79
+#: src/modplug/plugin_main.cc:67
 msgid "48 kHz"
 msgstr "48 kHz"
 
-#: src/modplug/plugin_main.c:81
+#: src/modplug/plugin_main.cc:68
 msgid "96 kHz"
 msgstr "96 kHz"
 
-#: src/modplug/plugin_main.c:86 src/modplug/plugin_main.c:93
-#: src/modplug/plugin_main.c:100
+#: src/modplug/plugin_main.cc:72 src/modplug/plugin_main.cc:77
+#: src/modplug/plugin_main.cc:82
 msgid "Level:"
 msgstr "強度:"
 
-#: src/modplug/plugin_main.c:95
+#: src/modplug/plugin_main.cc:78
 msgid "Cutoff:"
 msgstr "裁切:"
 
-#: src/modplug/plugin_main.c:112
+#: src/modplug/plugin_main.cc:91
 msgid "<b>Reverb</b>"
 msgstr "<b>殘響</b>"
 
-#: src/modplug/plugin_main.c:116
+#: src/modplug/plugin_main.cc:94
 msgid "<b>Bass Boost</b>"
 msgstr "<b>重低音強化</b>"
 
-#: src/modplug/plugin_main.c:120
+#: src/modplug/plugin_main.cc:97
 msgid "<b>Surround</b>"
 msgstr "<b>環繞音效</b>"
 
-#: src/modplug/plugin_main.c:124
+#: src/modplug/plugin_main.cc:100
 msgid "<b>Preamp</b>"
 msgstr "<b>前置放大</b>"
 
-#: src/modplug/plugin_main.c:132
+#: src/modplug/plugin_main.cc:107
 msgid "Oversample"
 msgstr "超取樣"
 
-#: src/modplug/plugin_main.c:134
+#: src/modplug/plugin_main.cc:108
 msgid "Noise reduction"
 msgstr "降噪"
 
-#: src/modplug/plugin_main.c:136
+#: src/modplug/plugin_main.cc:109
 msgid "Play Amiga MODs"
 msgstr "播放 Amiga MOD 檔案"
 
-#: src/modplug/plugin_main.c:138
+#: src/modplug/plugin_main.cc:110
 msgid "<b>Repeat</b>"
 msgstr "<b>重複</b>"
 
-#: src/modplug/plugin_main.c:139
+#: src/modplug/plugin_main.cc:111
 msgid "Repeat count:"
 msgstr "重複次數:"
 
-#: src/modplug/plugin_main.c:141
+#: src/modplug/plugin_main.cc:112
 msgid "To repeat forever, set the repeat count to -1."
 msgstr "將重複次數設定為 -1 表示永遠重複播放。"
 
-#: src/modplug/plugin_main.c:236
-msgid "ModPlug (Module Player)"
-msgstr "ModPlug (MOD 播放器)"
-
-#: src/mpg123/mpg123.c:210
-msgid "Surround"
-msgstr "環繞"
+#: src/modplug/plugin_main.cc:125 src/sid/xs_config.cc:106
+msgid "These settings will take effect when Audacious is restarted."
+msgstr "這些設定值將在 Audacious 重新啟動後生效。"
 
-#: src/mpg123/mpg123.c:412
+#: src/mpg123/mpg123.cc:54
 msgid "MPG123 Plugin"
 msgstr "MPG123 外掛"
 
-#: src/mpris2/plugin.c:403
+#: src/mpg123/mpg123.cc:83
+msgid "<b>Advanced</b>"
+msgstr "<b>進階</b>"
+
+#: src/mpg123/mpg123.cc:84
+msgid "Use accurate length calculation (slow)"
+msgstr "啟用精確長度計算(慢)"
+
+#: src/mpg123/mpg123.cc:248
+msgid "Surround"
+msgstr "環繞"
+
+#: src/mpris2/plugin.cc:39
 msgid "MPRIS 2 Server"
 msgstr "MPRIS 2 伺服器"
 
-#: src/neon/neon.c:1056
+#: src/neon/neon.cc:97
 msgid "Neon HTTP/HTTPS Plugin"
 msgstr "Neon HTTP/HTTPS 外掛"
 
-#: src/notify/event.c:65
+#: src/neon/neon.cc:521
+msgid "Error parsing redirect"
+msgstr "解析重新導向時發生錯誤"
+
+#: src/neon/neon.cc:535
+msgid "Unknown HTTP error"
+msgstr "發生未知的 HTTP 錯誤"
+
+#: src/neon/neon.cc:569
+msgid "Error parsing URL"
+msgstr "解析網址時發生錯誤"
+
+#: src/neon/neon.cc:632
+msgid "Too many redirects"
+msgstr "過多的重新導向"
+
+#: src/notify/event.cc:64
 msgid "Stopped"
 msgstr "已停止"
 
-#: src/notify/event.c:65
+#: src/notify/event.cc:64
 msgid "Audacious is not playing."
 msgstr "Audacious 非播放中。"
 
-#: src/notify/notify.c:33
+#: src/notify/notify.cc:42
+msgid "Desktop Notifications"
+msgstr "桌面通知"
+
+#: src/notify/notify.cc:60
 msgid ""
 "Desktop Notifications Plugin for Audacious\n"
 "Copyright (C) 2010 Maximilian Bogner\n"
@@ -2549,55 +2648,64 @@ msgstr ""
 "You should have received a copy of the GNU General Public License along with "
 "this program.  If not, see <http://www.gnu.org/licenses/>."
 
-#: src/notify/notify.c:77
+#: src/notify/notify.cc:110
 msgid "Show playback controls"
 msgstr "顯示播放控制元件"
 
-#: src/notify/notify.c:80
+#: src/notify/notify.cc:112
 msgid "Always show notification"
 msgstr "永遠顯示通知"
 
-#: src/notify/notify.c:92
-msgid "Desktop Notifications"
-msgstr "桌面通知"
+#: src/notify/notify.cc:114
+msgid "Include album name in notification"
+msgstr "在通知訊息中顯示專輯名稱"
 
-#: src/notify/osd.c:57
+#: src/notify/osd.cc:58
 msgid "Show"
 msgstr "顯示"
 
-#: src/notify/osd.c:65 src/skins/menus.c:79
+#: src/notify/osd.cc:66 src/qtui/main_window.cc:178
+#: src/qtui/main_window.cc:179 src/skins/menus.cc:88
 msgid "Pause"
 msgstr "暫停"
 
-#: src/notify/osd.c:72 src/skins/menus.c:82
+#: src/notify/osd.cc:73 src/qtui/main_window.cc:72 src/skins/menus.cc:91
 msgid "Next"
 msgstr "下一個"
 
-#: src/oss4/plugin.c:38
-msgid "1. Default device"
-msgstr "1. 預設裝置"
+#: src/oss4/oss.h:93
+msgid "OSS4 Output"
+msgstr "OSS4 輸出"
+
+#: src/oss4/oss.h:95
+msgid "OSS3 Output"
+msgstr "OSS3 輸出"
+
+#: src/oss4/plugin.cc:35
+msgid "Default device"
+msgstr "預設裝置"
 
-#: src/oss4/plugin.c:77 src/sndio/sndio.c:393
+#: src/oss4/plugin.cc:77
 msgid "Audio device:"
 msgstr "音訊裝置:"
 
-#: src/oss4/plugin.c:79
+#: src/oss4/plugin.cc:80
 msgid "Use alternate device:"
 msgstr "使用替代裝置:"
 
-#: src/oss4/plugin.c:83
+#: src/oss4/plugin.cc:84
 msgid "Save volume between sessions."
 msgstr "儲存不同工作階段的音量。"
 
-#: src/oss4/plugin.c:85
+#: src/oss4/plugin.cc:86
 msgid "Enable format conversions made by the OSS software."
 msgstr "啟用格式轉換 (使用 OSS 軟體)。"
 
-#: src/oss4/plugin.c:87
+#: src/oss4/plugin.cc:88
 msgid "Enable exclusive mode to prevent virtual mixing."
 msgstr "啟用獨占模式以防止虛擬混音。"
 
-#: src/oss4/plugin.c:110
+#: src/oss4/plugin.cc:100
 msgid ""
 "OSS4 Output Plugin for Audacious\n"
 "Copyright 2010-2012 Michał Lipski\n"
@@ -2611,19 +2719,35 @@ msgstr ""
 "I would like to thank people on #audacious, especially Tony Vroon and John "
 "Lindgren and of course the authors of the previous OSS plugin."
 
-#: src/oss4/plugin.c:117
-msgid "OSS4 Output"
-msgstr "OSS4 輸出"
+#: src/playlist-manager/playlist-manager.cc:37
+msgid "Playlist Manager"
+msgstr "播放清單管理"
 
-#: src/pls/pls.c:102
+#: src/playlist-manager/playlist-manager.cc:226
+msgid "Entries"
+msgstr "項目數"
+
+#: src/playlist-manager/playlist-manager.cc:245
+msgid "_Remove"
+msgstr "移除(_R)"
+
+#: src/playlist-manager/playlist-manager.cc:246
+msgid "Ren_ame"
+msgstr "重新命名(_A)"
+
+#: src/pls/pls.cc:35
 msgid "PLS Playlists"
 msgstr "PLS 播放清單"
 
-#: src/psf/plugin.c:209
+#: src/psf/plugin.cc:45
 msgid "OpenPSF PSF1/PSF2 Decoder"
 msgstr "OpenPSF PSF1/PSF2 解碼器"
 
-#: src/pulse_audio/pulse_audio.c:644
+#: src/pulse_audio/pulse_audio.cc:38
+msgid "PulseAudio Output"
+msgstr "PulseAudio 輸出"
+
+#: src/pulse_audio/pulse_audio.cc:611
 msgid ""
 "Audacious PulseAudio Output Plugin\n"
 "\n"
@@ -2659,11 +2783,73 @@ msgstr ""
 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n"
 "USA."
 
-#: src/pulse_audio/pulse_audio.c:662
-msgid "PulseAudio Output"
-msgstr "PulseAudio 輸出"
+#: src/qtaudio/qtaudio.cc:49
+msgid "QtMultimedia Output"
+msgstr "QtMultimedia 輸出"
 
-#: src/resample/resample.c:165
+#: src/qtaudio/qtaudio.cc:77
+msgid ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+msgstr ""
+"QtMultimedia Audio Output Plugin for Audacious\n"
+"Copyright 2014 William Pitcock\n"
+"\n"
+"Based on SDL Output Plugin for Audacious\n"
+"Copyright 2010 John Lindgren"
+
+#: src/qtui/dialog_windows.cc:31
+msgid "Working ..."
+msgstr "處理中 ..."
+
+#: src/qtui/filter_input.cc:44 src/skins/ui_playlist.cc:221
+msgid "Search"
+msgstr "搜尋"
+
+#: src/qtui/main_window_actions.cc:94
+msgid "_Open Folder ..."
+msgstr "開啟資料夾(_O) ..."
+
+#: src/qtui/main_window_actions.cc:96
+msgid "_Add Folder ..."
+msgstr "加入資料夾(_A) ..."
+
+#: src/qtui/main_window_actions.cc:101
+msgid "_Log Inspector ..."
+msgstr "監控記錄(_L) ..."
+
+#: src/qtui/main_window.cc:64
+msgid "Open Files"
+msgstr "開啟檔案"
+
+#: src/qtui/main_window.cc:66
+msgid "Add Files"
+msgstr "加入檔案"
+
+#: src/qtui/main_window.cc:71 src/skins/menus.cc:90
+msgid "Previous"
+msgstr "上一個"
+
+#: src/qtui/main_window.cc:77 src/skins/menus.cc:82
+msgid "Repeat"
+msgstr "重複"
+
+#: src/qtui/main_window.cc:79 src/skins/menus.cc:83
+msgid "Shuffle"
+msgstr "隨機"
+
+#: src/qtui/qtui.cc:42
+msgid "Qt Interface"
+msgstr "Qt 介面"
+
+#: src/resample/resample.cc:43
+msgid "Sample Rate Converter"
+msgstr "取樣率轉換"
+
+#: src/resample/resample.cc:183
 msgid ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
@@ -2671,96 +2857,104 @@ msgstr ""
 "Sample Rate Converter Plugin for Audacious\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/resample/resample.c:169
+#: src/resample/resample.cc:187
 msgid "Skip/repeat samples"
 msgstr "跳過/重複取樣"
 
-#: src/resample/resample.c:170
+#: src/resample/resample.cc:188
 msgid "Linear interpolation"
 msgstr "線性內插"
 
-#: src/resample/resample.c:171
+#: src/resample/resample.cc:189
 msgid "Fast sinc interpolation"
 msgstr "快速 sinc 內插"
 
-#: src/resample/resample.c:172
+#: src/resample/resample.cc:190
 msgid "Medium sinc interpolation"
 msgstr "中等 sinc 內插"
 
-#: src/resample/resample.c:173
+#: src/resample/resample.cc:191
 msgid "Best sinc interpolation"
 msgstr "最佳 sinc 內插"
 
-#: src/resample/resample.c:176
+#: src/resample/resample.cc:195
 msgid "<b>Conversion</b>"
 msgstr "<b>轉換</b>"
 
-#: src/resample/resample.c:177
+#: src/resample/resample.cc:196
 msgid "Method:"
 msgstr "演算法:"
 
-#: src/resample/resample.c:180 src/sox-resampler/sox-resampler.c:153
+#: src/resample/resample.cc:199 src/sox-resampler/sox-resampler.cc:161
 msgid "Rate:"
 msgstr "取樣率:"
 
-#: src/resample/resample.c:183
+#: src/resample/resample.cc:202
 msgid "<b>Rate Mappings</b>"
 msgstr "<b>取樣率映射</b>"
 
-#: src/resample/resample.c:184
+#: src/resample/resample.cc:203
 msgid "Use rate mappings"
 msgstr "使用取樣率映射"
 
-#: src/resample/resample.c:186
+#: src/resample/resample.cc:205
 msgid "8 kHz:"
 msgstr "8 kHz:"
 
-#: src/resample/resample.c:189
+#: src/resample/resample.cc:209
 msgid "16 kHz:"
 msgstr "16 kHz:"
 
-#: src/resample/resample.c:192
+#: src/resample/resample.cc:213
 msgid "22.05 kHz:"
 msgstr "22.05 kHz:"
 
-#: src/resample/resample.c:195
+#: src/resample/resample.cc:217
+msgid "32.0 kHz:"
+msgstr "32.0 kHz:"
+
+#: src/resample/resample.cc:221
 msgid "44.1 kHz:"
 msgstr "44.1 kHz:"
 
-#: src/resample/resample.c:198
+#: src/resample/resample.cc:225
 msgid "48 kHz:"
 msgstr "48 kHz:"
 
-#: src/resample/resample.c:201
+#: src/resample/resample.cc:229
+msgid "88.2 kHz:"
+msgstr "88.2 kHz:"
+
+#: src/resample/resample.cc:233
 msgid "96 kHz:"
 msgstr "96 kHz:"
 
-#: src/resample/resample.c:204
+#: src/resample/resample.cc:237
+msgid "176.4 kHz:"
+msgstr "176.4 kHz:"
+
+#: src/resample/resample.cc:241
 msgid "192 kHz:"
 msgstr "192 kHz:"
 
-#: src/resample/resample.c:214
-msgid "Sample Rate Converter"
-msgstr "取樣率轉換"
-
-#: src/scrobbler2/config_window.c:41
+#: src/scrobbler2/config_window.cc:41
 #, c-format
 msgid "OK. Scrobbling for user: %s"
 msgstr "確認。上傳使用者 %s 的播放資訊"
 
-#: src/scrobbler2/config_window.c:53
+#: src/scrobbler2/config_window.cc:54
 msgid "Permission Denied"
 msgstr "存取被拒"
 
-#: src/scrobbler2/config_window.c:55
+#: src/scrobbler2/config_window.cc:56
 msgid "Access the following link to allow Audacious to scrobble your plays:"
 msgstr "點選下列連結允許 Audacious 上傳您的播放資訊:"
 
-#: src/scrobbler2/config_window.c:64
+#: src/scrobbler2/config_window.cc:66
 msgid "Keep this window open and click 'Check Permission' again.\n"
 msgstr "請保持這個視窗的開啟並再次點選「檢查權限」。\n"
 
-#: src/scrobbler2/config_window.c:67 src/scrobbler2/config_window.c:78
+#: src/scrobbler2/config_window.cc:69 src/scrobbler2/config_window.cc:80
 msgid ""
 "Don't worry. Your scrobbles are saved on your computer.\n"
 "They will be submitted as soon as Audacious is allowed to do so."
@@ -2768,32 +2962,36 @@ msgstr ""
 "別擔心。您的資訊已經儲存在電腦上。\n"
 "Audacious 會在狀況允許下盡快地將它們上傳。"
 
-#: src/scrobbler2/config_window.c:75
+#: src/scrobbler2/config_window.cc:77
 msgid "Network Problem."
 msgstr "網路發生問題。"
 
-#: src/scrobbler2/config_window.c:76
+#: src/scrobbler2/config_window.cc:78
 msgid "There was a problem contacting Last.fm. Please try again later."
 msgstr "存取 Last.fm 時發生問題。請稍候再試。"
 
-#: src/scrobbler2/config_window.c:108
+#: src/scrobbler2/config_window.cc:110
 msgid "Checking..."
 msgstr "檢查中..."
 
-#: src/scrobbler2/config_window.c:174
+#: src/scrobbler2/config_window.cc:176
 msgid "C_heck Permission"
 msgstr "檢查權限(_H)"
 
-#: src/scrobbler2/config_window.c:175
+#: src/scrobbler2/config_window.cc:177
 msgid "_Revoke Permission"
 msgstr "撤銷授權(_R)"
 
-#: src/scrobbler2/config_window.c:222
+#: src/scrobbler2/config_window.cc:220
 msgid ""
 "You need to allow Audacious to scrobble tracks to your Last.fm account.\n"
 msgstr "您需要允許 Audacious 上傳音軌的播放資訊到您的 Last.fm 帳號。\n"
 
-#: src/scrobbler2/scrobbler.c:220
+#: src/scrobbler2/scrobbler.cc:29
+msgid "Scrobbler 2.0"
+msgstr "Scrobbler 2.0"
+
+#: src/scrobbler2/scrobbler.cc:224
 msgid ""
 "The Scrobbler plugin could not be started.\n"
 "There might be a problem with your installation."
@@ -2801,7 +2999,7 @@ msgstr ""
 "無法啟動 Scrobbler 外掛。\n"
 "您的安裝可能有些問題。"
 
-#: src/scrobbler2/scrobbler.c:296
+#: src/scrobbler2/scrobbler.cc:289
 msgid ""
 "Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n"
 "\n"
@@ -2819,11 +3017,7 @@ msgstr ""
 "project.\n"
 "\n"
 
-#: src/scrobbler2/scrobbler.c:302
-msgid "Scrobbler 2.0"
-msgstr "Scrobbler 2.0"
-
-#: src/scrobbler2/scrobbler_communication.c:727
+#: src/scrobbler2/scrobbler_communication.cc:642
 msgid ""
 "Audacious is now using an improved version of the Last.fm Scrobbler.\n"
 "Please check the Preferences for the Scrobbler plugin."
@@ -2831,7 +3025,11 @@ msgstr ""
 "Audacious 現在使用改良版的 Last.fm 播放資訊上傳功能。\n"
 "請參閱偏好設定中的播放資訊外掛。"
 
-#: src/sdlout/plugin.c:26
+#: src/sdlout/sdlout.cc:48
+msgid "SDL Output"
+msgstr "SDL 輸出"
+
+#: src/sdlout/sdlout.cc:77
 msgid ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
@@ -2839,753 +3037,824 @@ msgstr ""
 "SDL Output Plugin for Audacious\n"
 "Copyright 2010 John Lindgren"
 
-#: src/sdlout/plugin.c:31
-msgid "SDL Output"
-msgstr "SDL 輸出"
-
-#: src/search-tool/search-tool.c:104 src/search-tool/search-tool.c:114
+#: src/search-tool/search-tool.cc:116 src/search-tool/search-tool.cc:124
 msgid "Library"
 msgstr "媒體櫃"
 
-#: src/search-tool/search-tool.c:211
-msgid "Unknown Artist"
-msgstr "未知的藝人"
-
-#: src/search-tool/search-tool.c:213
-msgid "Unknown Album"
-msgstr "未知的專輯"
-
-#: src/search-tool/search-tool.c:625
+#: src/search-tool/search-tool.cc:394
 #, c-format
-msgid ""
-"%s\n"
-" on %s by %s"
-msgstr ""
-"%s\n"
-" 於「%s」由「%s」演唱"
+msgid "%d result"
+msgid_plural "%d results"
+msgstr[0] "%d 項結果"
 
-#: src/search-tool/search-tool.c:631
+#: src/search-tool/search-tool.cc:400
 #, c-format
-msgid "%d album"
-msgid_plural "%d albums"
-msgstr[0] "%d 張專輯"
+msgid "(%d hidden)"
+msgid_plural "(%d hidden)"
+msgstr[0] "(%d 項隱藏)"
 
-#: src/search-tool/search-tool.c:633
-#, c-format
-msgid ""
-"%s\n"
-" %s, %d song"
-msgid_plural ""
-"%s\n"
-" %s, %d songs"
-msgstr[0] ""
-"%s\n"
-" %s,%d 首歌曲"
-
-#: src/search-tool/search-tool.c:639
+#: src/search-tool/search-tool.cc:594
 #, c-format
-msgid ""
-"%s\n"
-" %d song by %s"
-msgid_plural ""
-"%s\n"
-" %d songs by %s"
-msgstr[0] ""
-"%s\n"
-" %d 首歌曲由「%s」演唱"
-
-#: src/search-tool/search-tool.c:675
+msgid "%d song"
+msgid_plural "%d songs"
+msgstr[0] "%d 首歌曲"
+
+#: src/search-tool/search-tool.cc:601
+msgid "of this genre"
+msgstr "符合此分類"
+
+#: src/search-tool/search-tool.cc:607
+msgid "on"
+msgstr "收錄於"
+
+#: src/search-tool/search-tool.cc:607
+msgid "by"
+msgstr "-"
+
+#: src/search-tool/search-tool.cc:643
 msgid "_Create Playlist"
 msgstr "建立播放清單(_C)"
 
-#: src/search-tool/search-tool.c:676
+#: src/search-tool/search-tool.cc:645
 msgid "_Add to Playlist"
 msgstr "加到播放清單(_A)"
 
-#: src/search-tool/search-tool.c:713
+#: src/search-tool/search-tool.cc:684
 msgid "Search library"
 msgstr "搜尋媒體櫃"
 
-#: src/search-tool/search-tool.c:717
+#: src/search-tool/search-tool.cc:688
 msgid ""
 "To import your music library into Audacious, choose a folder and then click "
 "the \"refresh\" icon."
 msgstr ""
 "要將您的媒體櫃匯入 Audacious,請選擇目標資料夾並且按下 \"重新整理\" 圖示。"
 
-#: src/search-tool/search-tool.c:725
+#: src/search-tool/search-tool.cc:696
 msgid "Please wait ..."
 msgstr "請稍候 ..."
 
-#: src/search-tool/search-tool.c:747
+#: src/search-tool/search-tool.cc:723
 msgid "Choose Folder"
 msgstr "選擇資料夾"
 
-#: src/skins/menus.c:56
+#: src/sid/xmms-sid.cc:43
+msgid "SID Player"
+msgstr "SID 播放器"
+
+#: src/sid/xs_config.cc:61
+msgid "<b>Output</b>"
+msgstr "<b>輸出</b>"
+
+#: src/sid/xs_config.cc:62
+msgid "Channels:"
+msgstr "聲道數:"
+
+#: src/sid/xs_config.cc:68
+msgid "<b>Emulation</b>"
+msgstr "<b>模擬</b>"
+
+#: src/sid/xs_config.cc:69
+msgid "Emulate MOS 8580 (default: MOS 6581)"
+msgstr "模擬 MOS 8580 (預設值:MOS 6581)"
+
+#: src/sid/xs_config.cc:71
+msgid "Do not automatically select chip model"
+msgstr "不要自動選擇晶片型號"
+
+#: src/sid/xs_config.cc:73
+msgid "Emulate filter"
+msgstr "模擬濾波器"
+
+#: src/sid/xs_config.cc:75
+msgid "Clock speed:"
+msgstr "時脈:"
+
+#: src/sid/xs_config.cc:78
+msgid "Do not automatically select clock speed"
+msgstr "不要自動選擇時脈"
+
+#: src/sid/xs_config.cc:80
+msgid "<b>Playback time</b>"
+msgstr "<b>播放時間</b>"
+
+#: src/sid/xs_config.cc:81
+msgid "Set maximum playback time:"
+msgstr "設定最大的播放時間:"
+
+#: src/sid/xs_config.cc:87
+msgid "Use only when song length is unknown"
+msgstr "僅在歌曲長度未知時使用"
+
+#: src/sid/xs_config.cc:90
+msgid "Set minimum playback time:"
+msgstr "設定最小的播放時間:"
+
+#: src/sid/xs_config.cc:96
+msgid "<b>Subtunes</b>"
+msgstr "<b>Subtunes</b>"
+
+#: src/sid/xs_config.cc:97
+msgid "Enable subtunes"
+msgstr "啟用 Subtunes"
+
+#: src/sid/xs_config.cc:99
+msgid "Ignore subtunes shorter than:"
+msgstr "忽略過短的 Subtunes:"
+
+#: src/sid/xs_config.cc:105
+msgid "<b>Note</b>"
+msgstr "<b>注意</b>"
+
+#: src/silence-removal/silence-removal.cc:39
+msgid "Silence Removal"
+msgstr "移除靜音"
+
+#: src/silence-removal/silence-removal.cc:58
+msgid ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+msgstr ""
+"Silence Removal Plugin for Audacious\n"
+"Copyright 2014 John Lindgren"
+
+#: src/silence-removal/silence-removal.cc:67
+msgid "<b>Silence Removal</b>"
+msgstr "<b>移除靜音</b>"
+
+#: src/silence-removal/silence-removal.cc:68
+msgid "Threshold:"
+msgstr "閥值:"
+
+#: src/silence-removal/silence-removal.cc:70
+msgid "dB"
+msgstr "dB"
+
+#: src/skins/menus.cc:64
 msgid "Open Files ..."
 msgstr "開啟檔案 ..."
 
-#: src/skins/menus.c:57
+#: src/skins/menus.cc:65
 msgid "Open URL ..."
 msgstr "開啟網址 ..."
 
-#: src/skins/menus.c:59
+#: src/skins/menus.cc:66
+msgid "Search Library"
+msgstr "搜尋媒體櫃"
+
+#: src/skins/menus.cc:68
 msgid "Playback"
 msgstr "播放"
 
-#: src/skins/menus.c:60
+#: src/skins/menus.cc:69
 msgid "Playlist"
 msgstr "播放清單"
 
-#: src/skins/menus.c:61
+#: src/skins/menus.cc:70
 msgid "View"
 msgstr "檢視"
 
-#: src/skins/menus.c:63 src/skins/menus.c:133 src/skins/menus.c:146
-#: src/skins/menus.c:203
+#: src/skins/menus.cc:72 src/skins/menus.cc:136 src/skins/menus.cc:149
+#: src/skins/menus.cc:214
 msgid "Services"
 msgstr "服務"
 
-#: src/skins/menus.c:65
+#: src/skins/menus.cc:74
 msgid "About ..."
 msgstr "關於 ..."
 
-#: src/skins/menus.c:66
+#: src/skins/menus.cc:75
 msgid "Settings ..."
 msgstr "設定 ..."
 
-#: src/skins/menus.c:67
+#: src/skins/menus.cc:76
 msgid "Quit"
 msgstr "離開"
 
-#: src/skins/menus.c:71 src/skins/menus.c:195
+#: src/skins/menus.cc:80 src/skins/menus.cc:206
 msgid "Song Info ..."
 msgstr "歌曲資訊 ..."
 
-#: src/skins/menus.c:73
-msgid "Repeat"
-msgstr "重複"
-
-#: src/skins/menus.c:74
-msgid "Shuffle"
-msgstr "隨機"
-
-#: src/skins/menus.c:75
+#: src/skins/menus.cc:84
 msgid "No Playlist Advance"
 msgstr "不要切換播放清單"
 
-#: src/skins/menus.c:76
+#: src/skins/menus.cc:85
 msgid "Stop After This Song"
 msgstr "播放完目前歌曲後停止"
 
-#: src/skins/menus.c:81
-msgid "Previous"
-msgstr "上一個"
-
-#: src/skins/menus.c:84
+#: src/skins/menus.cc:93
 msgid "Set A-B Repeat"
 msgstr "設定 A-B 循環"
 
-#: src/skins/menus.c:85
+#: src/skins/menus.cc:94
 msgid "Clear A-B Repeat"
 msgstr "清除 A-B 循環"
 
-#: src/skins/menus.c:87
+#: src/skins/menus.cc:96
 msgid "Jump to Song ..."
 msgstr "跳轉到指定歌曲 ..."
 
-#: src/skins/menus.c:88
+#: src/skins/menus.cc:97
 msgid "Jump to Time ..."
 msgstr "跳轉到指定時間 ..."
 
-#: src/skins/menus.c:92
-msgid "Play This Playlist"
-msgstr "播放此清單"
+#: src/skins/menus.cc:101
+msgid "Play/Resume"
+msgstr "播放/回復"
 
-#: src/skins/menus.c:94
+#: src/skins/menus.cc:103
 msgid "New Playlist"
 msgstr "新增播放清單"
 
-#: src/skins/menus.c:95
+#: src/skins/menus.cc:104
 msgid "Rename Playlist ..."
 msgstr "重新命名播放清單 ..."
 
-#: src/skins/menus.c:96
+#: src/skins/menus.cc:105
 msgid "Remove Playlist"
 msgstr "移除播放清單"
 
-#: src/skins/menus.c:98
+#: src/skins/menus.cc:107
 msgid "Previous Playlist"
 msgstr "上一個播放清單"
 
-#: src/skins/menus.c:99
+#: src/skins/menus.cc:108
 msgid "Next Playlist"
 msgstr "下一個播放清單"
 
-#: src/skins/menus.c:101
+#: src/skins/menus.cc:110
 msgid "Import Playlist ..."
 msgstr "匯入播放清單 ..."
 
-#: src/skins/menus.c:102
+#: src/skins/menus.cc:111
 msgid "Export Playlist ..."
 msgstr "匯出播放清單 ..."
 
-#: src/skins/menus.c:104
+#: src/skins/menus.cc:113
 msgid "Playlist Manager ..."
 msgstr "播放清單管理 ..."
 
-#: src/skins/menus.c:105
+#: src/skins/menus.cc:114
 msgid "Queue Manager ..."
 msgstr "佇列管理 ..."
 
-#: src/skins/menus.c:107
+#: src/skins/menus.cc:116
 msgid "Refresh Playlist"
 msgstr "重整播放清單"
 
-#: src/skins/menus.c:111
+#: src/skins/menus.cc:120
 msgid "Show Playlist Editor"
 msgstr "顯示播放清單編輯器"
 
-#: src/skins/menus.c:113
+#: src/skins/menus.cc:121
 msgid "Show Equalizer"
 msgstr "顯示等化器"
 
-#: src/skins/menus.c:116
+#: src/skins/menus.cc:123
 msgid "Show Remaining Time"
 msgstr "顯示剩餘時間"
 
-#: src/skins/menus.c:119
+#: src/skins/menus.cc:125
 msgid "Always on Top"
 msgstr "永遠在最上層"
 
-#: src/skins/menus.c:121
+#: src/skins/menus.cc:126
 msgid "On All Workspaces"
 msgstr "在所有工作區顯示"
 
-#: src/skins/menus.c:124
+#: src/skins/menus.cc:128
 msgid "Roll Up Player"
 msgstr "捲起播放器"
 
-#: src/skins/menus.c:126
+#: src/skins/menus.cc:129
 msgid "Roll Up Playlist Editor"
 msgstr "捲起播放清單編輯器"
 
-#: src/skins/menus.c:128
+#: src/skins/menus.cc:130
 msgid "Roll Up Equalizer"
 msgstr "捲起等化器"
 
-#: src/skins/menus.c:135
+#: src/skins/menus.cc:132 src/skins/ui_main.cc:854
+msgid "Double Size"
+msgstr "兩倍大小"
+
+#: src/skins/menus.cc:138
 msgid "Add URL ..."
 msgstr "加入網址 ..."
 
-#: src/skins/menus.c:136
+#: src/skins/menus.cc:139
 msgid "Add Files ..."
 msgstr "加入檔案 ... "
 
-#: src/skins/menus.c:140 src/skins/menus.c:167 src/skins/menus.c:177
+#: src/skins/menus.cc:143 src/skins/menus.cc:171 src/skins/menus.cc:185
 msgid "By Title"
 msgstr "標題"
 
-#: src/skins/menus.c:141 src/skins/menus.c:170 src/skins/menus.c:180
-msgid "By Filename"
+#: src/skins/menus.cc:144 src/skins/menus.cc:178 src/skins/menus.cc:192
+msgid "By File Name"
 msgstr "檔案名稱"
 
-#: src/skins/menus.c:142 src/skins/menus.c:171 src/skins/menus.c:181
+#: src/skins/menus.cc:145 src/skins/menus.cc:179 src/skins/menus.cc:193
 msgid "By File Path"
 msgstr "檔案路徑"
 
-#: src/skins/menus.c:148
+#: src/skins/menus.cc:151
 msgid "Remove All"
 msgstr "全部移除"
 
-#: src/skins/menus.c:149
+#: src/skins/menus.cc:152
 msgid "Clear Queue"
 msgstr "清除佇列"
 
-#: src/skins/menus.c:151
+#: src/skins/menus.cc:154
 msgid "Remove Unavailable Files"
 msgstr "移除無法使用的檔案"
 
-#: src/skins/menus.c:152
+#: src/skins/menus.cc:155
 msgid "Remove Duplicates"
 msgstr "移除重複的項目"
 
-#: src/skins/menus.c:154
+#: src/skins/menus.cc:157
 msgid "Remove Unselected"
 msgstr "移除未選擇的項目"
 
-#: src/skins/menus.c:155
+#: src/skins/menus.cc:158
 msgid "Remove Selected"
 msgstr "移除選擇的項目"
 
-#: src/skins/menus.c:159
+#: src/skins/menus.cc:162
 msgid "Search and Select"
 msgstr "搜尋並選擇"
 
-#: src/skins/menus.c:161
+#: src/skins/menus.cc:164
 msgid "Invert Selection"
 msgstr "反向選擇"
 
-#: src/skins/menus.c:162
+#: src/skins/menus.cc:165
 msgid "Select None"
 msgstr "取消選擇"
 
-#: src/skins/menus.c:163
+#: src/skins/menus.cc:166
 msgid "Select All"
 msgstr "選擇全部"
 
-#: src/skins/menus.c:168 src/skins/menus.c:178
-msgid "By Album"
-msgstr "專輯"
+#: src/skins/menus.cc:170 src/skins/menus.cc:184
+msgid "By Track Number"
+msgstr "音軌編號"
 
-#: src/skins/menus.c:169 src/skins/menus.c:179
+#: src/skins/menus.cc:172 src/skins/menus.cc:186
 msgid "By Artist"
 msgstr "藝人"
 
-#: src/skins/menus.c:172 src/skins/menus.c:182
+#: src/skins/menus.cc:173 src/skins/menus.cc:187
+msgid "By Album"
+msgstr "專輯"
+
+#: src/skins/menus.cc:174 src/skins/menus.cc:188
+msgid "By Album Artist"
+msgstr "專輯藝人"
+
+#: src/skins/menus.cc:175 src/skins/menus.cc:190
 msgid "By Release Date"
 msgstr "發行日期"
 
-#: src/skins/menus.c:173 src/skins/menus.c:183
-msgid "By Track Number"
-msgstr "音軌編號"
+#: src/skins/menus.cc:176 src/skins/menus.cc:189
+msgid "By Genre"
+msgstr "é¡žåž‹"
+
+#: src/skins/menus.cc:177 src/skins/menus.cc:191
+msgid "By Length"
+msgstr "長度"
+
+#: src/skins/menus.cc:180 src/skins/menus.cc:194
+msgid "By Custom Title"
+msgstr "自訂標題"
 
-#: src/skins/menus.c:187
+#: src/skins/menus.cc:198
 msgid "Randomize List"
 msgstr "清單隨機排序"
 
-#: src/skins/menus.c:188
+#: src/skins/menus.cc:199
 msgid "Reverse List"
 msgstr "清單反向排序"
 
-#: src/skins/menus.c:190
+#: src/skins/menus.cc:201
 msgid "Sort Selected"
 msgstr "排序選擇的項目"
 
-#: src/skins/menus.c:191
+#: src/skins/menus.cc:202
 msgid "Sort List"
 msgstr "排序清單"
 
-#: src/skins/menus.c:197
+#: src/skins/menus.cc:208
 msgid "Cut"
 msgstr "剪下"
 
-#: src/skins/menus.c:198
+#: src/skins/menus.cc:209
 msgid "Copy"
 msgstr "複製"
 
-#: src/skins/menus.c:199
+#: src/skins/menus.cc:210
 msgid "Paste"
 msgstr "貼上"
 
-#: src/skins/menus.c:201
+#: src/skins/menus.cc:212
 msgid "Queue/Unqueue"
 msgstr "排入/移出佇列"
 
-#: src/skins/menus.c:207
+#: src/skins/menus.cc:218
 msgid "Load Preset ..."
 msgstr "載入樣式 ..."
 
-#: src/skins/menus.c:208
+#: src/skins/menus.cc:219
 msgid "Load Auto Preset ..."
 msgstr "讀取自動載入樣式 ..."
 
-#: src/skins/menus.c:209
+#: src/skins/menus.cc:220
 msgid "Load Default"
 msgstr "載入預設值"
 
-#: src/skins/menus.c:210
+#: src/skins/menus.cc:221
 msgid "Load Preset File ..."
 msgstr "從檔案載入樣式 ..."
 
-#: src/skins/menus.c:211
+#: src/skins/menus.cc:222
 msgid "Load EQF File ..."
 msgstr "載入 EQF 檔 ..."
 
-#: src/skins/menus.c:213
+#: src/skins/menus.cc:224
 msgid "Save Preset ..."
 msgstr "儲存樣式 ..."
 
-#: src/skins/menus.c:214
+#: src/skins/menus.cc:225
 msgid "Save Auto Preset ..."
 msgstr "儲存自動載入樣式 ..."
 
-#: src/skins/menus.c:215
+#: src/skins/menus.cc:226
 msgid "Save Default"
 msgstr "儲存預設值"
 
-#: src/skins/menus.c:216
+#: src/skins/menus.cc:227
 msgid "Save Preset File ..."
 msgstr "儲存樣式到檔案 ..."
 
-#: src/skins/menus.c:217
+#: src/skins/menus.cc:228
 msgid "Save EQF File ..."
 msgstr "儲存 EQF 檔 ..."
 
-#: src/skins/menus.c:219
+#: src/skins/menus.cc:230
 msgid "Delete Preset ..."
 msgstr "刪除樣式 ..."
 
-#: src/skins/menus.c:220
+#: src/skins/menus.cc:231
 msgid "Delete Auto Preset ..."
 msgstr "刪除自動載入樣式 ..."
 
-#: src/skins/menus.c:222
+#: src/skins/menus.cc:233
 msgid "Import Winamp Presets ..."
 msgstr "匯入 Winamp 樣式 ..."
 
-#: src/skins/menus.c:224
+#: src/skins/menus.cc:235
 msgid "Reset to Zero"
 msgstr "重置為零"
 
-#: src/skins/plugin.c:49
+#: src/skins/plugin.cc:48
 msgid "Winamp Classic Interface"
 msgstr "Winamp 傳統介面"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:375
-#: src/skins/preset-list.c:390
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:371
+#: src/skins/preset-list.cc:386
 msgid "Save"
 msgstr "儲存"
 
-#: src/skins/preset-browser.c:57 src/skins/preset-list.c:342
-#: src/skins/preset-list.c:358
+#: src/skins/preset-browser.cc:57 src/skins/preset-list.cc:338
+#: src/skins/preset-list.cc:354
 msgid "Load"
 msgstr "載入"
 
-#: src/skins/preset-browser.c:82
+#: src/skins/preset-browser.cc:83
 msgid "Load Preset File"
 msgstr "從檔案載入樣式"
 
-#: src/skins/preset-browser.c:106
+#: src/skins/preset-browser.cc:100
 msgid "Load EQF File"
 msgstr "載入 EQF 檔"
 
-#: src/skins/preset-browser.c:122
+#: src/skins/preset-browser.cc:119
 msgid "Save Preset File"
 msgstr "儲存樣式到檔案"
 
-#: src/skins/preset-browser.c:144
+#: src/skins/preset-browser.cc:137
 msgid "Save EQF File"
 msgstr "儲存 EQF 檔"
 
-#: src/skins/preset-browser.c:162
+#: src/skins/preset-browser.cc:151
 msgid "Import Winamp Presets"
 msgstr "匯入 Winamp 樣式"
 
-#: src/skins/preset-list.c:289
+#: src/skins/preset-list.cc:285
 msgid "Presets"
 msgstr "樣式"
 
-#: src/skins/preset-list.c:339
+#: src/skins/preset-list.cc:335
 msgid "Load preset"
 msgstr "載入樣式"
 
-#: src/skins/preset-list.c:355
+#: src/skins/preset-list.cc:351
 msgid "Load auto-preset"
 msgstr "讀取自動載入樣式"
 
-#: src/skins/preset-list.c:371
+#: src/skins/preset-list.cc:367
 msgid "Save preset"
 msgstr "儲存樣式"
 
-#: src/skins/preset-list.c:386
+#: src/skins/preset-list.cc:382
 msgid "Save auto-preset"
 msgstr "儲存自動載入樣式"
 
-#: src/skins/preset-list.c:413
+#: src/skins/preset-list.cc:408
 msgid "Delete preset"
 msgstr "刪除樣式"
 
-#: src/skins/preset-list.c:429
+#: src/skins/preset-list.cc:424
 msgid "Delete auto-preset"
 msgstr "刪除自動載入樣式"
 
-#: src/skins/skins_cfg.c:181
-msgid "_Player:"
-msgstr "播放器(_P):"
+#: src/skins/skins_cfg.cc:176
+msgid "Player:"
+msgstr "播放器:"
 
-#: src/skins/skins_cfg.c:183
+#: src/skins/skins_cfg.cc:178
 msgid "Select main player window font:"
 msgstr "選擇播放器主視窗字型:"
 
-#: src/skins/skins_cfg.c:184
-msgid "_Playlist:"
-msgstr "播放清單(_P):"
+#: src/skins/skins_cfg.cc:179
+msgid "Playlist:"
+msgstr "播放清單:"
 
-#: src/skins/skins_cfg.c:186
+#: src/skins/skins_cfg.cc:181
 msgid "Select playlist font:"
 msgstr "選擇播放清單字型:"
 
-#: src/skins/skins_cfg.c:191
+#: src/skins/skins_cfg.cc:187
 msgid "<b>Skin</b>"
 msgstr "<b>面板</b>"
 
-#: src/skins/skins_cfg.c:193
+#: src/skins/skins_cfg.cc:189
 msgid "<b>Fonts</b>"
 msgstr "<b>å­—åž‹</b>"
 
-#: src/skins/skins_cfg.c:196
+#: src/skins/skins_cfg.cc:192
 msgid "Use bitmap fonts (supports ASCII only)"
 msgstr "使用點陣字型 (只支援 ASCII)"
 
-#: src/skins/skins_cfg.c:198
+#: src/skins/skins_cfg.cc:194
 msgid "Scroll song title"
 msgstr "捲動歌曲標題"
 
-#: src/skins/skins_cfg.c:200
+#: src/skins/skins_cfg.cc:196
 msgid "Scroll song title in both directions"
 msgstr "雙向捲動歌曲標題"
 
-#: src/skins/skins_cfg.c:205
+#: src/skins/skins_cfg.cc:201
 msgid "Analyzer"
 msgstr "分析儀"
 
-#: src/skins/skins_cfg.c:206
+#: src/skins/skins_cfg.cc:202
 msgid "Scope"
 msgstr "示波器"
 
-#: src/skins/skins_cfg.c:207
+#: src/skins/skins_cfg.cc:203
 msgid "Voiceprint / VU meter"
 msgstr "聲紋/VU 計"
 
-#: src/skins/skins_cfg.c:208
+#: src/skins/skins_cfg.cc:204
 msgid "Off"
 msgstr "關閉"
 
-#: src/skins/skins_cfg.c:212 src/skins/skins_cfg.c:237
-#: src/skins/skins_cfg.c:243
+#: src/skins/skins_cfg.cc:208 src/skins/skins_cfg.cc:233
+#: src/skins/skins_cfg.cc:239
 msgid "Normal"
 msgstr "標準"
 
-#: src/skins/skins_cfg.c:213 src/skins/skins_cfg.c:238
+#: src/skins/skins_cfg.cc:209 src/skins/skins_cfg.cc:234
 msgid "Fire"
 msgstr "火焰"
 
-#: src/skins/skins_cfg.c:214
+#: src/skins/skins_cfg.cc:210
 msgid "Vertical lines"
 msgstr "垂直線條"
 
-#: src/skins/skins_cfg.c:218
+#: src/skins/skins_cfg.cc:214
 msgid "Lines"
 msgstr "線條"
 
-#: src/skins/skins_cfg.c:219
+#: src/skins/skins_cfg.cc:215
 msgid "Bars"
 msgstr "棒狀"
 
-#: src/skins/skins_cfg.c:223
+#: src/skins/skins_cfg.cc:219
 msgid "Slowest"
 msgstr "最慢"
 
-#: src/skins/skins_cfg.c:224
+#: src/skins/skins_cfg.cc:220
 msgid "Slow"
 msgstr "æ…¢"
 
-#: src/skins/skins_cfg.c:225 src/sox-resampler/sox-resampler.c:145
+#: src/skins/skins_cfg.cc:221 src/sox-resampler/sox-resampler.cc:152
 msgid "Medium"
 msgstr "中等"
 
-#: src/skins/skins_cfg.c:226
+#: src/skins/skins_cfg.cc:222
 msgid "Fast"
 msgstr "å¿«"
 
-#: src/skins/skins_cfg.c:227
+#: src/skins/skins_cfg.cc:223
 msgid "Fastest"
 msgstr "最快"
 
-#: src/skins/skins_cfg.c:231
+#: src/skins/skins_cfg.cc:227
 msgid "Dots"
 msgstr "點狀"
 
-#: src/skins/skins_cfg.c:232
+#: src/skins/skins_cfg.cc:228
 msgid "Line"
 msgstr "線條"
 
-#: src/skins/skins_cfg.c:233
+#: src/skins/skins_cfg.cc:229
 msgid "Solid"
 msgstr "實心"
 
-#: src/skins/skins_cfg.c:239
+#: src/skins/skins_cfg.cc:235
 msgid "Ice"
 msgstr "冰霜"
 
-#: src/skins/skins_cfg.c:244
+#: src/skins/skins_cfg.cc:240
 msgid "Smooth"
 msgstr "平滑"
 
-#: src/skins/skins_cfg.c:248
+#: src/skins/skins_cfg.cc:244
 msgid "<b>Type</b>"
 msgstr "<b>é¡žåž‹</b>"
 
-#: src/skins/skins_cfg.c:249
+#: src/skins/skins_cfg.cc:245
 msgid "Visualization type:"
 msgstr "視覺特效類型:"
 
-#: src/skins/skins_cfg.c:252
+#: src/skins/skins_cfg.cc:248
 msgid "<b>Analyzer</b>"
 msgstr "<b>分析儀</b>"
 
-#: src/skins/skins_cfg.c:253
+#: src/skins/skins_cfg.cc:249
 msgid "Show peaks"
 msgstr "顯示峰值標記"
 
-#: src/skins/skins_cfg.c:255
+#: src/skins/skins_cfg.cc:251
 msgid "Coloring:"
 msgstr "顏色:"
 
-#: src/skins/skins_cfg.c:258
+#: src/skins/skins_cfg.cc:254
 msgid "Style:"
 msgstr "樣式:"
 
-#: src/skins/skins_cfg.c:261
+#: src/skins/skins_cfg.cc:257
 msgid "Falloff:"
 msgstr "陷落:"
 
-#: src/skins/skins_cfg.c:264
+#: src/skins/skins_cfg.cc:260
 msgid "Peak falloff:"
 msgstr "峰值陷落:"
 
-#: src/skins/skins_cfg.c:268
+#: src/skins/skins_cfg.cc:264
 msgid "Scope Style:"
 msgstr "示波器樣式:"
 
-#: src/skins/skins_cfg.c:271
+#: src/skins/skins_cfg.cc:267
 msgid "Voiceprint Coloring:"
 msgstr "聲紋顏色:"
 
-#: src/skins/skins_cfg.c:274
+#: src/skins/skins_cfg.cc:270
 msgid "VU Meter Style:"
 msgstr "VU 計樣式:"
 
-#: src/skins/skins_cfg.c:280
+#: src/skins/skins_cfg.cc:276
 msgid "General"
 msgstr "一般"
 
-#: src/skins/skins_cfg.c:281
+#: src/skins/skins_cfg.cc:277
 msgid "Visualization"
 msgstr "視覺特效"
 
-#: src/skins/ui_equalizer.c:289
+#: src/skins/ui_equalizer.cc:282
 msgid "Preamp"
 msgstr "前置放大"
 
-#: src/skins/ui_equalizer.c:293
+#: src/skins/ui_equalizer.cc:286
 msgid "31 Hz"
 msgstr "31 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "63 Hz"
 msgstr "63 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "125 Hz"
 msgstr "125 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "250 Hz"
 msgstr "250 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "500 Hz"
 msgstr "500 Hz"
 
-#: src/skins/ui_equalizer.c:294
+#: src/skins/ui_equalizer.cc:287
 msgid "1 kHz"
 msgstr "1 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "2 kHz"
 msgstr "2 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "4 kHz"
 msgstr "4 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "8 kHz"
 msgstr "8 kHz"
 
-#: src/skins/ui_equalizer.c:295
+#: src/skins/ui_equalizer.cc:288
 msgid "16 kHz"
 msgstr "16 kHz"
 
-#: src/skins/ui_equalizer.c:337
+#: src/skins/ui_equalizer.cc:330
 msgid "Audacious Equalizer"
 msgstr "Audacious 等化器"
 
-#: src/skins/ui_main.c:686
+#: src/skins/ui_main.cc:688
 #, c-format
 msgid "Seek to %d:%-2.2d / %d:%-2.2d"
 msgstr "移動到 %d:%-2.2d/%d:%-2.2d"
 
-#: src/skins/ui_main.c:707
+#: src/skins/ui_main.cc:709
 #, c-format
 msgid "Volume: %d%%"
 msgstr "音量:%d%"
 
-#: src/skins/ui_main.c:730
+#: src/skins/ui_main.cc:732
 #, c-format
 msgid "Balance: %d%% left"
 msgstr "平衡:%d% 偏左"
 
-#: src/skins/ui_main.c:732
+#: src/skins/ui_main.cc:734
 msgid "Balance: center"
 msgstr "平衡:中間"
 
-#: src/skins/ui_main.c:734
+#: src/skins/ui_main.cc:736
 #, c-format
 msgid "Balance: %d%% right"
 msgstr "平衡:%d% 偏右"
 
-#: src/skins/ui_main.c:833
+#: src/skins/ui_main.cc:842
 msgid "Options Menu"
 msgstr "選單選項"
 
-#: src/skins/ui_main.c:837
+#: src/skins/ui_main.cc:846
 msgid "Disable 'Always On Top'"
 msgstr "關閉置頂"
 
-#: src/skins/ui_main.c:839
+#: src/skins/ui_main.cc:848
 msgid "Enable 'Always On Top'"
 msgstr "啟用置頂"
 
-#: src/skins/ui_main.c:842
+#: src/skins/ui_main.cc:851
 msgid "File Info Box"
 msgstr "檔案資訊視窗"
 
-#: src/skins/ui_main.c:1281
+#: src/skins/ui_main.cc:857
+msgid "Visualizations"
+msgstr "視覺特效"
+
+#: src/skins/ui_main.cc:1336
 msgid "Repeat point A set."
 msgstr "已設定重複點 A。"
 
-#: src/skins/ui_main.c:1286
+#: src/skins/ui_main.cc:1341
 msgid "Repeat point B set."
 msgstr "已設定重複點 B。"
 
-#: src/skins/ui_main.c:1295
+#: src/skins/ui_main.cc:1350
 msgid "Repeat points cleared."
 msgstr "已清除重複點。"
 
-#: src/skins/ui_main_evlisteners.c:109
-msgid "Single mode."
-msgstr "單一模式。"
-
-#: src/skins/ui_main_evlisteners.c:111
-msgid "Playlist mode."
-msgstr "播放清單模式。"
-
-#: src/skins/ui_main_evlisteners.c:117
-msgid "Stopping after song."
-msgstr "播放完成後停止。"
-
-#: src/skins/ui_playlist.c:222
+#: src/skins/ui_playlist.cc:219
 msgid "Search entries in active playlist"
 msgstr "在使用中的播放清單裡搜尋播放項目"
 
-#: src/skins/ui_playlist.c:224
-msgid "Search"
-msgstr "搜尋"
-
-#: src/skins/ui_playlist.c:229
+#: src/skins/ui_playlist.cc:226
 msgid ""
 "Select entries in playlist by filling one or more fields. Fields use regular "
 "expressions syntax, case-insensitive. If you don't know how regular "
@@ -3595,57 +3864,61 @@ msgstr ""
 "填入一個或多個欄位以選擇播放清單中的項目。欄位使用正規表示法,大小寫視為不同"
 "字元。若您不知道如何使用正規表示法,請輸入您想搜尋的部分文字。"
 
-#: src/skins/ui_playlist.c:237
-msgid "Title: "
+#: src/skins/ui_playlist.cc:234
+msgid "Title:"
 msgstr "標題:"
 
-#: src/skins/ui_playlist.c:245
-msgid "Album: "
+#: src/skins/ui_playlist.cc:241
+msgid "Album:"
 msgstr "專輯:"
 
-#: src/skins/ui_playlist.c:253
-msgid "Artist: "
+#: src/skins/ui_playlist.cc:248
+msgid "Artist:"
 msgstr "藝人:"
 
-#: src/skins/ui_playlist.c:261
-msgid "Filename: "
+#: src/skins/ui_playlist.cc:255
+msgid "File Name:"
 msgstr "檔名:"
 
-#: src/skins/ui_playlist.c:270
+#: src/skins/ui_playlist.cc:263
 msgid "Clear previous selection before searching"
 msgstr "進行搜尋前清空上次的選擇項目"
 
-#: src/skins/ui_playlist.c:273
+#: src/skins/ui_playlist.cc:266
 msgid "Automatically toggle queue for matching entries"
 msgstr "自動切換到符合項目的佇列"
 
-#: src/skins/ui_playlist.c:276
+#: src/skins/ui_playlist.cc:269
 msgid "Create a new playlist with matching entries"
 msgstr "以符合的項目建立新的播放清單"
 
-#: src/skins/ui_playlist.c:721
+#: src/skins/ui_playlist.cc:717
 msgid "Audacious Playlist Editor"
 msgstr "Audacious 播放清單編輯器"
 
-#: src/skins/ui_playlist.c:755
+#: src/skins/ui_playlist.cc:752
 #, c-format
 msgid "%s (%d of %d)"
 msgstr "%s (%d/%d)"
 
-#: src/skins/ui_skinselector.c:163
+#: src/skins/ui_skinselector.cc:167
 msgid "Archived Winamp 2.x skin"
 msgstr "壓縮的 Winamp 2.x 面板"
 
-#: src/skins/ui_skinselector.c:168
+#: src/skins/ui_skinselector.cc:172
 msgid "Unarchived Winamp 2.x skin"
 msgstr "未壓縮的 Winamp 2.x skin"
 
-#: src/skins/util.c:450
+#: src/skins/util.cc:430
 #, c-format
 msgid "Could not create directory (%s): %s\n"
 msgstr "無法建立資料夾 (%s):%s\n"
 
-#: src/sndfile/plugin.c:350
+#: src/sndfile/plugin.cc:39
+msgid "Sndfile Plugin"
+msgstr "Sndfile 外掛"
+
+#: src/sndfile/plugin.cc:336
 msgid ""
 "Based on the xmms_sndfile plugin:\n"
 "Copyright (C) 2000, 2002 Erik de Castro Lopo\n"
@@ -3685,81 +3958,71 @@ msgstr ""
 "this program; if not, write to the Free Software Foundation, Inc., 51 "
 "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
 
-#: src/sndfile/plugin.c:369
-msgid "Sndfile Plugin"
-msgstr "Sndfile 外掛"
-
-#: src/sndio/sndio.c:172
-msgid "About Sndio Output Plugin"
-msgstr "關於 Sndio 輸出外掛"
+#: src/sndio-ng/sndio.cc:44
+msgid "Sndio Output"
+msgstr "Sndio 輸出"
 
-#: src/sndio/sndio.c:173
-msgid ""
-"Sndio Output Plugin\n"
-"\n"
-"Written by Thomas Pfaff <tpfaff at tp76.info>\n"
-msgstr ""
-"Sndio 輸出外掛\n"
-"\n"
-"作者:Thomas Pfaff <tpfaff at tp76.info>\n"
+#: src/sndio-ng/sndio.cc:98
+msgid "Device (blank for default):"
+msgstr "裝置 (空白表示預設):"
 
-#: src/sndio/sndio.c:248
-msgid "Unsupported format"
-msgstr "未支援的格式"
+#: src/sndio-ng/sndio.cc:100
+msgid "Save and restore volume:"
+msgstr "儲存與還原音量:"
 
-#: src/sndio/sndio.c:249
-msgid ""
-"A format not supported by the audio device was requested.\n"
-"\n"
-"Please try again with the sndiod(1) server running."
-msgstr ""
-"要求了未被音訊裝置支援的格式。\n"
-"\n"
-"請確認 sndiod(1) 伺服器已執行後重試。"
+#: src/sndio-ng/sndio.cc:181
+#, c-format
+msgid "Sndio error: Unsupported audio format (%d)"
+msgstr "Sndio 錯誤:未支援的音訊格式 (%d)"
 
-#: src/sndio/sndio.c:384
-msgid "sndio device"
-msgstr "sndio 裝置"
+#: src/sndio-ng/sndio.cc:192
+msgid "Sndio error: sio_open() failed"
+msgstr "Sndio 錯誤:sio_open() 失敗"
 
-#: src/sndio/sndio.c:400
-msgid "(empty means default)"
-msgstr "(空白表示使用預設值)"
+#: src/sndio-ng/sndio.cc:222
+msgid "Sndio error: sio_setpar() failed"
+msgstr "Sndio 錯誤:sio_setpar() 失敗"
 
-#: src/sndio/sndio.c:416
-msgid "OK"
-msgstr "確認"
+#: src/sndio-ng/sndio.cc:234
+msgid "Sndio error: sio_start() failed"
+msgstr "Sndio 錯誤:sio_start() 失敗"
 
-#: src/song_change/song_change.c:54
+#: src/song_change/song_change.cc:33
 msgid "Song Change"
 msgstr "歌曲切換"
 
-#: src/song_change/song_change.c:428
-msgid "Command to run when Audacious starts a new song."
-msgstr "當 Audacious 開始播放新的歌曲時執行的指令。"
+#: src/song_change/song_change.cc:342
+msgid ""
+"<span size='small'>Parameters passed to the shell should be encapsulated in "
+"quotes. Doing otherwise is a security risk.</span>"
+msgstr ""
+"<span size='small'>傳給 shell 的參數應該用雙引號包起來,否則會有安全風險。</"
+"span>"
+
+#: src/song_change/song_change.cc:358
+msgid "<b>Commands</b>"
+msgstr "<b>命令</b>"
 
-#: src/song_change/song_change.c:430 src/song_change/song_change.c:436
-#: src/song_change/song_change.c:442 src/song_change/song_change.c:448
-msgid "Command:"
-msgstr "命令:"
+#: src/song_change/song_change.cc:360
+msgid "Command to run when starting a new song:"
+msgstr "開始播放新歌曲時執行此命令:"
 
-#: src/song_change/song_change.c:434
-msgid "Command to run toward the end of a song."
-msgstr "每當一首歌曲播放完時執行命令"
+#: src/song_change/song_change.cc:364
+msgid "Command to run at the end of a song:"
+msgstr "當某首個播放完時執行此命令:"
 
-#: src/song_change/song_change.c:440
-msgid "Command to run when Audacious reaches the end of the playlist."
-msgstr "每當 Audacious 播放達到清單尾端時執行命令"
+#: src/song_change/song_change.cc:368
+msgid "Command to run at the end of the playlist:"
+msgstr "播放至播放清單的結尾時執行此命令:"
 
-#: src/song_change/song_change.c:446
-msgid ""
-"Command to run when title changes for a song (i.e. network streams titles)."
-msgstr "當一首歌的標題改變時執行命令。(網路串流的標題)"
+#: src/song_change/song_change.cc:372
+msgid "Command to run when song title changes (for network streams):"
+msgstr "當歌曲標題改變時執行此命令 (網路串流用):"
 
-#: src/song_change/song_change.c:452
+#: src/song_change/song_change.cc:376
 msgid ""
-"You can use the following format strings which\n"
-"will be substituted before calling the command\n"
-"(not all are useful for the end-of-playlist command):\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"
 "%c: Number of channels\n"
@@ -3773,35 +4036,30 @@ msgid ""
 "%b: Album\n"
 "%T: Track title"
 msgstr ""
-"您可以在命令中使用下列的格式字串。\n"
-"它們會在執行命令前被實際值取代。\n"
-"(不是全部都能在播放清單結束命令中使用)\n"
+"您可以使用以下的格式字串來表示特殊欄位(不是全部都能在播放清單結束命令中使"
+"用):\n"
 "\n"
-"%F:頻率 (赫茲)\n"
-"%c:聲道數目\n"
-"%f:檔名 (完整路徑)\n"
+"%F:頻率 (HZ)\n"
+"%c:聲道數\n"
+"%f:檔案名稱 (完整路徑)\n"
 "%l:長度 (毫秒)\n"
 "%n 或 %s:歌曲名稱\n"
 "%r:位元率 (bps)\n"
-"%t:播放清單位置 (%02d)\n"
+"%t:播放清單的位置 (%02d)\n"
 "%p:播放中 (1 或 0)\n"
 "%a:藝人\n"
 "%b:專輯\n"
 "%T:音軌標題"
 
-#: src/song_change/song_change.c:479
-msgid ""
-"<span size='small'>Parameters passed to the shell should be encapsulated in "
-"quotes. Doing otherwise is a security risk.</span>"
-msgstr ""
-"<span size='small'>傳給 shell 的參數應該用雙引號包起來,否則會有安全風險。</"
-"span>"
+#: src/song-info-qt/song-info.cc:32
+msgid "Song Info (Qt)"
+msgstr "歌曲資訊 (Qt)"
 
-#: src/song_change/song_change.c:490
-msgid "Commands"
-msgstr "命令"
+#: src/sox-resampler/sox-resampler.cc:44
+msgid "SoX Resampler"
+msgstr "SoX 重取樣"
 
-#: src/sox-resampler/sox-resampler.c:137
+#: src/sox-resampler/sox-resampler.cc:144
 msgid ""
 "SoX Resampler Plugin for Audacious\n"
 "Copyright 2013 Michał Lipski\n"
@@ -3815,51 +4073,51 @@ msgstr ""
 "Based on Sample Rate Converter Plugin:\n"
 "Copyright 2010-2012 John Lindgren"
 
-#: src/sox-resampler/sox-resampler.c:143
+#: src/sox-resampler/sox-resampler.cc:150
 msgid "Quick"
 msgstr "快速"
 
-#: src/sox-resampler/sox-resampler.c:144
+#: src/sox-resampler/sox-resampler.cc:151
 msgid "Low"
 msgstr "低"
 
-#: src/sox-resampler/sox-resampler.c:146
+#: src/sox-resampler/sox-resampler.cc:153
 msgid "High"
 msgstr "高"
 
-#: src/sox-resampler/sox-resampler.c:147
+#: src/sox-resampler/sox-resampler.cc:154
 msgid "Very High"
 msgstr "非常高"
 
-#: src/sox-resampler/sox-resampler.c:150
+#: src/sox-resampler/sox-resampler.cc:158
 msgid "Quality:"
 msgstr "品質:"
 
-#: src/sox-resampler/sox-resampler.c:164
-msgid "SoX Resampler"
-msgstr "SoX 重取樣"
+#: src/speed-pitch/speed-pitch.cc:51
+msgid "Speed and Pitch"
+msgstr "速度與音高"
 
-#: src/speed-pitch/speed-pitch.c:227
+#: src/speed-pitch/speed-pitch.cc:210
 msgid "<b>Speed and Pitch</b>"
 msgstr "<b>速度與音高</b>"
 
-#: src/speed-pitch/speed-pitch.c:228
+#: src/speed-pitch/speed-pitch.cc:211
 msgid "Speed:"
 msgstr "速度:"
 
-#: src/speed-pitch/speed-pitch.c:231
+#: src/speed-pitch/speed-pitch.cc:214
 msgid "Pitch:"
 msgstr "音高:"
 
-#: src/speed-pitch/speed-pitch.c:266
-msgid "Speed and Pitch"
-msgstr "速度與音高"
+#: src/statusicon/statusicon.cc:47
+msgid "Status Icon"
+msgstr "狀態圖示"
 
-#: src/statusicon/statusicon.c:269
+#: src/statusicon/statusicon.cc:283
 msgid "Se_ttings ..."
 msgstr "設定(_T) ..."
 
-#: src/statusicon/statusicon.c:371
+#: src/statusicon/statusicon.cc:372
 msgid ""
 "Status Icon Plugin\n"
 "\n"
@@ -3876,39 +4134,39 @@ msgstr ""
 "\n"
 "這個外掛提供一個狀態圖示並放在系統通知區。"
 
-#: src/statusicon/statusicon.c:378
+#: src/statusicon/statusicon.cc:379
 msgid "<b>Mouse Scroll Action</b>"
 msgstr "<b>滑鼠滾輪動作</b>"
 
-#: src/statusicon/statusicon.c:379
+#: src/statusicon/statusicon.cc:380
 msgid "Change volume"
 msgstr "調整音量"
 
-#: src/statusicon/statusicon.c:382
+#: src/statusicon/statusicon.cc:383
 msgid "Change playing song"
 msgstr "切換播放歌曲"
 
-#: src/statusicon/statusicon.c:385
+#: src/statusicon/statusicon.cc:386
 msgid "<b>Other Settings</b>"
 msgstr "<b>其他設定</b>"
 
-#: src/statusicon/statusicon.c:386
+#: src/statusicon/statusicon.cc:387
 msgid "Disable the popup window"
 msgstr "關閉彈出式視窗"
 
-#: src/statusicon/statusicon.c:388
+#: src/statusicon/statusicon.cc:389
 msgid "Close to the system tray"
 msgstr "縮到系統列"
 
-#: src/statusicon/statusicon.c:390
+#: src/statusicon/statusicon.cc:391
 msgid "Advance in playlist when scrolling upward"
 msgstr "以與滑鼠滾輪的反方向切換歌曲"
 
-#: src/statusicon/statusicon.c:399
-msgid "Status Icon"
-msgstr "狀態圖示"
+#: src/stereo_plugin/stereo.cc:19
+msgid "Extra Stereo"
+msgstr "額外立體聲效果"
 
-#: src/stereo_plugin/stereo.c:17
+#: src/stereo_plugin/stereo.cc:36
 msgid ""
 "Extra Stereo Plugin\n"
 "\n"
@@ -3918,24 +4176,24 @@ msgstr ""
 "\n"
 "By Johan Levin, 1999"
 
-#: src/stereo_plugin/stereo.c:25
+#: src/stereo_plugin/stereo.cc:44
 msgid "<b>Extra Stereo</b>"
 msgstr "<b>額外立體聲效果</b>"
 
-#: src/stereo_plugin/stereo.c:36
-msgid "Extra Stereo"
-msgstr "額外立體聲效果"
+#: src/tonegen/tonegen.cc:45
+msgid "Tone Generator"
+msgstr "音調產生器"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 #, c-format
 msgid "%s %.1f Hz"
 msgstr "%s %.1f Hz"
 
-#: src/tonegen/tonegen.c:83
+#: src/tonegen/tonegen.cc:94
 msgid "Tone Generator: "
 msgstr "音調產生器:"
 
-#: src/tonegen/tonegen.c:174
+#: src/tonegen/tonegen.cc:160
 msgid ""
 "Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
 "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n"
@@ -3949,15 +4207,11 @@ msgstr ""
 "用法:加入網址:tone://frequency1;frequency2;frequency3;...\n"
 "範例:tone://2000;2005 會播放 2000 HZ 和 2005HZ 的正弦波"
 
-#: src/tonegen/tonegen.c:183
-msgid "Tone Generator"
-msgstr "音調產生器"
-
-#: src/voice_removal/voice_removal.c:53
+#: src/voice_removal/voice_removal.cc:28
 msgid "Voice Removal"
 msgstr "人聲移除"
 
-#: src/vorbis/vorbis.c:484
+#: src/vorbis/vorbis.cc:465
 msgid ""
 "Audacious Ogg Vorbis Decoder\n"
 "\n"
@@ -3995,11 +4249,46 @@ msgstr ""
 "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
 "Eugene Zagidullin <e.asphyx at gmail.com>"
 
-#: src/vorbis/vorbis.c:504
+#: src/vorbis/vorbis.h:18
 msgid "Ogg Vorbis Decoder"
 msgstr "Ogg Vorbis 解碼器"
 
-#: src/vtx/vtx.c:167
+#: src/vtx/info.cc:22
+#, c-format
+msgid "Details about %s"
+msgstr "關於 %s 的詳細資訊"
+
+#: src/vtx/info.cc:24
+msgid ""
+"Title: %t\n"
+"Author: %a\n"
+"From: %f\n"
+"Tracker: %T\n"
+"Comment: %C\n"
+"Chip type: %c\n"
+"Stereo: %s\n"
+"Loop: %l\n"
+"Chip freq: %F\n"
+"Player Freq: %P\n"
+"Year: %y"
+msgstr ""
+"標題:%t\n"
+"作者:%a\n"
+"來自:%f\n"
+"Tracker: %T\n"
+"備註:%C\n"
+"晶片類型:%c\n"
+"立體聲:%s\n"
+"循環:%l\n"
+"晶片頻率:%F\n"
+"播放器頻率:%P\n"
+"年份:%y"
+
+#: src/vtx/vtx.cc:38
+msgid "VTX Decoder"
+msgstr "VTX 解碼器"
+
+#: src/vtx/vtx.cc:184
 msgid ""
 "Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
@@ -4009,19 +4298,19 @@ msgstr ""
 "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
 "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>"
 
-#: src/vtx/vtx.c:173
-msgid "VTX Decoder"
-msgstr "VTX 解碼器"
+#: src/wavpack/wavpack.cc:24
+msgid "WavPack Decoder"
+msgstr "WavPack 解碼器"
 
-#: src/wavpack/wavpack.c:214
+#: src/wavpack/wavpack.cc:211
 msgid "lossy (hybrid)"
 msgstr "失真 (混合)"
 
-#: src/wavpack/wavpack.c:216
+#: src/wavpack/wavpack.cc:213
 msgid "lossy"
 msgstr "失真"
 
-#: src/wavpack/wavpack.c:265
+#: src/wavpack/wavpack.cc:255
 msgid ""
 "Copyright 2006 William Pitcock <nenolod at nenolod.net>\n"
 "\n"
@@ -4031,23 +4320,18 @@ msgstr ""
 "\n"
 "Some of the plugin code was by Miles Egan."
 
-#: src/wavpack/wavpack.c:272
-msgid "WavPack Decoder"
-msgstr "WavPack 解碼器"
-
-#: src/xsf/plugin.c:217
+#: src/xsf/plugin.cc:50
 msgid "2SF Decoder"
 msgstr "2SF 解碼器"
 
-#: src/xspf/xspf.c:438
-msgid "XML Shareable Playlists (XSPF)"
-msgstr "XML 可分享式播放清單 (XSPF)"
-
-#~ msgid "32.0 kHz:"
-#~ msgstr "32.0 kHz:"
+#: src/xsf/plugin.cc:238
+msgid "<b>XSF Configuration</b>"
+msgstr "<b>XSF 組態</b>"
 
-#~ msgid "88.2 kHz:"
-#~ msgstr "88.2 kHz:"
+#: src/xsf/plugin.cc:239
+msgid "Ignore length from file"
+msgstr "忽略來自檔案的長度資訊"
 
-#~ msgid "176.4 kHz:"
-#~ msgstr "176.4 kHz:"
+#: src/xspf/xspf.cc:89
+msgid "XML Shareable Playlists (XSPF)"
+msgstr "XML 可分享式播放清單 (XSPF)"
diff --git a/src/aac-raw/Makefile b/src/aac-raw/Makefile
index f44471f3d6e9..c3c9ee2bf06c 100644
--- a/src/aac-raw/Makefile
+++ b/src/aac-raw/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = aac-raw${PLUGIN_SUFFIX}
 
-SRCS = aac.c
+SRCS = aac.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${FAAD_CFLAGS} -I../..
 LIBS += ${FAAD_LIBS} -lm -laudtag
diff --git a/src/aac-raw/aac.c b/src/aac-raw/aac.c
deleted file mode 100644
index f5dd85a4c8c5..000000000000
--- a/src/aac-raw/aac.c
+++ /dev/null
@@ -1,482 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <neaacdec.h>
-
-#include <audacious/audtag.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-
-/*
- * BUFFER_SIZE is the highest amount of memory that can be pulled.
- * We use this for sanity checks, among other things, as mp4ff needs
- * a labotomy sometimes.
- */
-#define BUFFER_SIZE (FAAD_MIN_STREAMSIZE * 16)
-
-static const char *fmts[] = { "aac", NULL };
-
-/*
- * These routines are derived from MPlayer.
- */
-
-/// \param srate (out) sample rate
-/// \param num (out) number of audio frames in this ADTS frame
-/// \return size of the ADTS frame in bytes
-/// aac_parse_frames needs a buffer at least 8 bytes long
-int aac_parse_frame (unsigned char * buf, int *srate, int *num)
-{
-    int i = 0, sr, fl = 0;
-    static int srates[] =
-     { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000,
-         11025, 8000, 0, 0, 0 };
-
-    if ((buf[i] != 0xFF) || ((buf[i + 1] & 0xF6) != 0xF0))
-        return 0;
-
-/* We currently have no use for the id below.
-        id = (buf[i+1] >> 3) & 0x01;    //id=1 mpeg2, 0: mpeg4
-*/
-    sr = (buf[i + 2] >> 2) & 0x0F;
-    if (sr > 11)
-        return 0;
-    *srate = srates[sr];
-
-    fl =
-     ((buf[i + 3] & 0x03) << 11) | (buf[i + 4] << 3) | ((buf[i +
-     5] >> 5) & 0x07);
-    *num = (buf[i + 6] & 0x02) + 1;
-
-    return fl;
-}
-
-#define PROBE_DEBUG(...)
-
-/* Searches <length> bytes of data for an ADTS header.  Returns the offset of
- * the first header or -1 if none is found.  Sets <size> to the length of the
- * frame. */
-static int find_aac_header (unsigned char * data, int length, int * size)
-{
-    int offset, a, b;
-
-    for (offset = 0; offset <= length - 8; offset++)
-    {
-        if (data[offset] != 255)
-            continue;
-
-        *size = aac_parse_frame (data + offset, &a, &b);
-
-        if (*size < 8)
-            continue;
-
-        return offset;
-    }
-
-    return -1;
-}
-
-static bool_t parse_aac_stream (const char * filename, VFSFile * stream)
-{
-    unsigned char data[8192];
-    int offset, found, inner, size;
-
-    size = 0;                   /* avoid bogus uninitialized variable warning */
-
-    if (vfs_fread (data, 1, sizeof data, stream) != sizeof data)
-    {
-        PROBE_DEBUG ("Read failed.\n");
-        return FALSE;
-    }
-
-    offset = 0;
-
-    for (found = 0; found < 3; found++)
-    {
-        inner = find_aac_header (data + offset, sizeof data - offset, &size);
-
-        if (!(inner == 0 || (found == 0 && inner > 0)))
-        {
-            PROBE_DEBUG ("Only %d ADTS headers.\n", found);
-            return FALSE;
-        }
-
-        offset += inner + size;
-    }
-
-    PROBE_DEBUG ("Accepted.\n");
-    return TRUE;
-}
-
-/* Quick search for an ADTS or ADIF header in the first <len> bytes of <buf>.
- * Returns the byte offset of the header or <len> if none is found. */
-
-static int aac_probe (unsigned char * buf, int len)
-{
-    for (int i = 0; i <= len - 4; i ++)
-    {
-        if ((buf[i] == 0xff && (buf[i + 1] & 0xf6) == 0xf0) || ! strncmp
-         ((char *) buf + i, "ADIF", 4))
-            return i;
-    }
-
-    return len;
-}
-
-/* Gets info (some approximated) from an AAC/ADTS file.  <length> is
- * milliseconds, <bitrate> is kilobits per second.  Any parameters that cannot
- * be read are set to -1. */
-static void calc_aac_info (VFSFile * handle, int * length, int * bitrate,
- int * samplerate, int * channels)
-{
-    NeAACDecHandle decoder;
-    NeAACDecFrameInfo frame;
-    bool_t initted = FALSE;
-    int size = vfs_fsize (handle);
-    unsigned char buffer[BUFFER_SIZE];
-    int offset = 0, filled = 0;
-    int found, bytes_used = 0, time_used = 0;
-
-    decoder = NULL;             /* avoid bogus uninitialized variable warning */
-
-    *length = -1;
-    *bitrate = -1;
-    *samplerate = -1;
-    *channels = -1;
-
-    /* look for a representative bitrate in the middle of the file */
-    if (size > 0 && vfs_fseek (handle, size / 2, SEEK_SET))
-        goto DONE;
-
-    for (found = 0; found < 32; found++)
-    {
-        if (filled < BUFFER_SIZE / 2)
-        {
-            memmove (buffer, buffer + offset, filled);
-            offset = 0;
-
-            if (vfs_fread (buffer + filled, 1, BUFFER_SIZE - filled, handle)
-             != BUFFER_SIZE - filled)
-            {
-                PROBE_DEBUG ("Read failed.\n");
-                goto DONE;
-            }
-
-            filled = BUFFER_SIZE;
-        }
-
-        if (!initted)
-        {
-            int inner, a;
-            unsigned long r;
-            unsigned char ch;
-
-            inner = find_aac_header (buffer + offset, filled, &a);
-
-            if (inner < 0)
-            {
-                PROBE_DEBUG ("No ADTS header.\n");
-                goto DONE;
-            }
-
-            offset += inner;
-            filled -= inner;
-
-            decoder = NeAACDecOpen ();
-            inner = NeAACDecInit (decoder, buffer + offset, filled, &r, &ch);
-
-            if (inner < 0)
-            {
-                PROBE_DEBUG ("Decoder init failed.\n");
-                NeAACDecClose (decoder);
-                goto DONE;
-            }
-
-            offset += inner;
-            filled -= inner;
-            bytes_used += inner;
-
-            *samplerate = r;
-            *channels = ch;
-            initted = TRUE;
-        }
-
-        if (NeAACDecDecode (decoder, &frame, buffer + offset, filled) == NULL)
-        {
-            PROBE_DEBUG ("Decode failed.\n");
-            goto DONE;
-        }
-
-        if (frame.samplerate != *samplerate || frame.channels != *channels)
-        {
-            PROBE_DEBUG ("Parameter mismatch.\n");
-            goto DONE;
-        }
-
-        offset += frame.bytesconsumed;
-        filled -= frame.bytesconsumed;
-        bytes_used += frame.bytesconsumed;
-        time_used += frame.samples / frame.channels * (int64_t) 1000 /
-         frame.samplerate;
-    }
-
-    /* bits per millisecond = kilobits per second */
-    *bitrate = bytes_used * 8 / time_used;
-
-    if (size > 0)
-        *length = size * (int64_t) time_used / bytes_used;
-
-  DONE:
-    if (initted)
-        NeAACDecClose (decoder);
-}
-
-static Tuple *aac_get_tuple (const char * filename, VFSFile * handle)
-{
-    Tuple *tuple = tuple_new_from_filename (filename);
-    int length, bitrate, samplerate, channels;
-
-    tuple_set_str (tuple, FIELD_CODEC, "MPEG-2/4 AAC");
-
-    if (!vfs_is_remote (filename))
-    {
-        calc_aac_info (handle, &length, &bitrate, &samplerate, &channels);
-
-        if (length > 0)
-            tuple_set_int (tuple, FIELD_LENGTH, length);
-
-        if (bitrate > 0)
-            tuple_set_int (tuple, FIELD_BITRATE, bitrate);
-    }
-
-    tag_update_stream_metadata (tuple, handle);
-
-    return tuple;
-}
-
-static void aac_seek (VFSFile * file, NeAACDecHandle dec, int time, int len,
- void * buf, int size, int * buflen)
-{
-    /* == ESTIMATE BYTE OFFSET == */
-
-    int64_t total = vfs_fsize (file);
-    if (total < 0)
-    {
-        fprintf (stderr, "aac: File is not seekable.\n");
-        return;
-    }
-
-    /* == SEEK == */
-
-    if (vfs_fseek (file, total * time / len, SEEK_SET))
-        return;
-
-    * buflen = vfs_fread (buf, 1, size, file);
-
-    /* == FIND FRAME HEADER == */
-
-    int used = aac_probe (buf, * buflen);
-
-    if (used == * buflen)
-    {
-        fprintf (stderr, "aac: No valid frame header found.\n");
-        * buflen = 0;
-        return;
-    }
-
-    if (used)
-    {
-        * buflen -= used;
-        memmove (buf, (char *) buf + used, * buflen);
-        * buflen += vfs_fread ((char *) buf + * buflen, 1, size - * buflen, file);
-    }
-
-    /* == START DECODING == */
-
-    unsigned char chan;
-    unsigned long rate;
-
-    if ((used = NeAACDecInit (dec, buf, * buflen, & rate, & chan)))
-    {
-        * buflen -= used;
-        memmove (buf, (char *) buf + used, * buflen);
-        * buflen += vfs_fread ((char *) buf + * buflen, 1, size - * buflen, file);
-    }
-}
-
-static bool_t my_decode_aac (const char * filename, VFSFile * file)
-{
-    NeAACDecHandle decoder = 0;
-    NeAACDecConfigurationPtr decoder_config;
-    unsigned long samplerate = 0;
-    unsigned char channels = 0;
-    int bitrate = 0;
-
-    Tuple * tuple = aud_input_get_tuple ();
-
-    if (tuple != NULL)
-    {
-        bitrate = tuple_get_int (tuple, FIELD_BITRATE);
-        bitrate = 1000 * MAX (0, bitrate);
-    }
-
-    if ((decoder = NeAACDecOpen ()) == NULL)
-    {
-        fprintf (stderr, "AAC: Open Decoder Error\n");
-        goto ERR;
-    }
-
-    decoder_config = NeAACDecGetCurrentConfiguration (decoder);
-    decoder_config->outputFormat = FAAD_FMT_FLOAT;
-    NeAACDecSetConfiguration (decoder, decoder_config);
-
-    /* == FILL BUFFER == */
-
-    unsigned char buf[BUFFER_SIZE];
-    int buflen = vfs_fread (buf, 1, sizeof buf, file);
-
-    /* == SKIP ID3 TAG == */
-
-    if (buflen >= 10 && ! strncmp ((char *) buf, "ID3", 3))
-    {
-        if (vfs_fseek (file, 10 + (buf[6] << 21) + (buf[7] << 14) + (buf[8] <<
-         7) + buf[9], SEEK_SET))
-        {
-            fprintf (stderr, "aac: Failed to seek past ID3v2 tag.\n");
-            goto ERR_CLOSE_DECODER;
-        }
-
-        buflen = vfs_fread (buf, 1, sizeof buf, file);
-    }
-
-    /* == FIND FRAME HEADER == */
-
-    int used = aac_probe (buf, buflen);
-
-    if (used == buflen)
-    {
-        fprintf (stderr, "aac: No valid frame header found.\n");
-        goto ERR_CLOSE_DECODER;
-    }
-
-    if (used)
-    {
-        buflen -= used;
-        memmove (buf, buf + used, buflen);
-        buflen += vfs_fread (buf + buflen, 1, sizeof buf - buflen, file);
-    }
-
-    /* == START DECODING == */
-
-    if ((used = NeAACDecInit (decoder, buf, buflen, & samplerate, & channels)))
-    {
-        buflen -= used;
-        memmove (buf, buf + used, buflen);
-        buflen += vfs_fread (buf + buflen, 1, sizeof buf - buflen, file);
-    }
-
-    /* == CHECK FOR METADATA == */
-
-    if (tuple && tag_update_stream_metadata (tuple, file))
-    {
-        tuple_ref (tuple);
-        aud_input_set_tuple (tuple);
-    }
-
-    /* == START PLAYBACK == */
-
-    if (! aud_input_open_audio (FMT_FLOAT, samplerate, channels))
-        goto ERR_CLOSE_DECODER;
-
-    aud_input_set_bitrate (bitrate);
-
-    /* == MAIN LOOP == */
-
-    while (! aud_input_check_stop ())
-    {
-        /* == HANDLE SEEK REQUESTS == */
-
-        int seek_value = aud_input_check_seek ();
-
-        if (seek_value >= 0)
-        {
-            int length = tuple ? tuple_get_int (tuple, FIELD_LENGTH) : 0;
-
-            if (length > 0)
-                aac_seek (file, decoder, seek_value, length, buf, sizeof buf, & buflen);
-        }
-
-        /* == CHECK FOR END OF FILE == */
-
-        if (! buflen)
-            break;
-
-        /* == CHECK FOR METADATA == */
-
-        if (tuple && tag_update_stream_metadata (tuple, file))
-        {
-            tuple_ref (tuple);
-            aud_input_set_tuple (tuple);
-        }
-
-        /* == DECODE A FRAME == */
-
-        NeAACDecFrameInfo info;
-        void * audio = NeAACDecDecode (decoder, & info, buf, buflen);
-
-        if (info.error)
-        {
-            fprintf (stderr, "aac: %s.\n", NeAACDecGetErrorMessage (info.error));
-
-            if (buflen)
-            {
-                used = 1 + aac_probe (buf + 1, buflen - 1);
-                buflen -= used;
-                memmove (buf, buf + used, buflen);
-                buflen += vfs_fread (buf + buflen, 1, sizeof buf - buflen, file);
-            }
-
-            continue;
-        }
-
-        if ((used = info.bytesconsumed))
-        {
-            buflen -= used;
-            memmove (buf, buf + used, buflen);
-            buflen += vfs_fread (buf + buflen, 1, sizeof buf - buflen, file);
-        }
-
-        /* == PLAY THE SOUND == */
-
-        if (audio && info.samples)
-            aud_input_write_audio (audio, sizeof (float) * info.samples);
-    }
-
-    NeAACDecClose (decoder);
-
-    if (tuple)
-        tuple_unref (tuple);
-
-    return TRUE;
-
-ERR_CLOSE_DECODER:
-    NeAACDecClose (decoder);
-
-ERR:
-    if (tuple)
-        tuple_unref (tuple);
-
-    return FALSE;
-}
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("AAC (Raw) Decoder"),
-    .domain = PACKAGE,
-    .play = my_decode_aac,
-    .is_our_file_from_vfs = parse_aac_stream,
-    .probe_for_tuple = aac_get_tuple,
-    .extensions = fmts,
-)
diff --git a/src/aac-raw/aac.cc b/src/aac-raw/aac.cc
new file mode 100644
index 000000000000..1a6d2515cf11
--- /dev/null
+++ b/src/aac-raw/aac.cc
@@ -0,0 +1,477 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <neaacdec.h>
+
+#include <audacious/audtag.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+class AACDecoder : public InputPlugin
+{
+public:
+    static const char * const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("AAC (Raw) Decoder"),
+        PACKAGE
+    };
+
+    static constexpr auto iinfo = InputInfo ()
+        .with_exts (exts);
+
+    constexpr AACDecoder () : InputPlugin (info, iinfo) {}
+
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT AACDecoder aud_plugin_instance;
+
+const char * const AACDecoder::exts[] = {"aac", nullptr};
+
+/*
+ * BUFFER_SIZE is the highest amount of memory that can be pulled.
+ * We use this for sanity checks, among other things, as mp4ff needs
+ * a labotomy sometimes.
+ */
+#define BUFFER_SIZE (FAAD_MIN_STREAMSIZE * 16)
+
+/*
+ * These routines are derived from MPlayer.
+ */
+
+/// \param srate (out) sample rate
+/// \param num (out) number of audio frames in this ADTS frame
+/// \return size of the ADTS frame in bytes
+/// aac_parse_frames needs a buffer at least 8 bytes long
+int aac_parse_frame (unsigned char * buf, int *srate, int *num)
+{
+    int i = 0, sr, fl = 0;
+    static int srates[] =
+     { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000,
+         11025, 8000, 0, 0, 0 };
+
+    if ((buf[i] != 0xFF) || ((buf[i + 1] & 0xF6) != 0xF0))
+        return 0;
+
+/* We currently have no use for the id below.
+        id = (buf[i+1] >> 3) & 0x01;    //id=1 mpeg2, 0: mpeg4
+*/
+    sr = (buf[i + 2] >> 2) & 0x0F;
+    if (sr > 11)
+        return 0;
+    *srate = srates[sr];
+
+    fl =
+     ((buf[i + 3] & 0x03) << 11) | (buf[i + 4] << 3) | ((buf[i +
+     5] >> 5) & 0x07);
+    *num = (buf[i + 6] & 0x02) + 1;
+
+    return fl;
+}
+
+#define PROBE_DEBUG(...)
+
+/* Searches <length> bytes of data for an ADTS header.  Returns the offset of
+ * the first header or -1 if none is found.  Sets <size> to the length of the
+ * frame. */
+static int find_aac_header (unsigned char * data, int length, int * size)
+{
+    int offset, a, b;
+
+    for (offset = 0; offset <= length - 8; offset++)
+    {
+        if (data[offset] != 255)
+            continue;
+
+        *size = aac_parse_frame (data + offset, &a, &b);
+
+        if (*size < 8)
+            continue;
+
+        return offset;
+    }
+
+    return -1;
+}
+
+bool AACDecoder::is_our_file (const char * filename, VFSFile & stream)
+{
+    unsigned char data[8192];
+    int offset, found, inner, size;
+
+    size = 0;                   /* avoid bogus uninitialized variable warning */
+
+    if (stream.fread (data, 1, sizeof data) != sizeof data)
+    {
+        PROBE_DEBUG ("Read failed.\n");
+        return false;
+    }
+
+    offset = 0;
+
+    for (found = 0; found < 3; found++)
+    {
+        inner = find_aac_header (data + offset, sizeof data - offset, &size);
+
+        if (!(inner == 0 || (found == 0 && inner > 0)))
+        {
+            PROBE_DEBUG ("Only %d ADTS headers.\n", found);
+            return false;
+        }
+
+        offset += inner + size;
+    }
+
+    PROBE_DEBUG ("Accepted.\n");
+    return true;
+}
+
+/* Quick search for an ADTS or ADIF header in the first <len> bytes of <buf>.
+ * Returns the byte offset of the header or <len> if none is found. */
+
+static int aac_probe (unsigned char * buf, int len)
+{
+    for (int i = 0; i <= len - 4; i ++)
+    {
+        if ((buf[i] == 0xff && (buf[i + 1] & 0xf6) == 0xf0) || ! strncmp
+         ((char *) buf + i, "ADIF", 4))
+            return i;
+    }
+
+    return len;
+}
+
+/* Gets info (some approximated) from an AAC/ADTS file.  <length> is
+ * milliseconds, <bitrate> is kilobits per second.  Any parameters that cannot
+ * be read are set to -1. */
+static void calc_aac_info (VFSFile & handle, int * length, int * bitrate,
+ int * samplerate, int * channels)
+{
+    NeAACDecHandle decoder;
+    NeAACDecFrameInfo frame;
+    bool initted = false;
+    int size = handle.fsize ();
+    unsigned char buffer[BUFFER_SIZE];
+    int offset = 0, filled = 0;
+    int found, bytes_used = 0, time_used = 0;
+
+    decoder = nullptr;             /* avoid bogus uninitialized variable warning */
+
+    *length = -1;
+    *bitrate = -1;
+    *samplerate = -1;
+    *channels = -1;
+
+    /* look for a representative bitrate in the middle of the file */
+    if (size < 0 || handle.fseek (size / 2, VFS_SEEK_SET) < 0)
+        goto DONE;
+
+    for (found = 0; found < 32; found++)
+    {
+        if (filled < BUFFER_SIZE / 2)
+        {
+            memmove (buffer, buffer + offset, filled);
+            offset = 0;
+
+            if (handle.fread (buffer + filled, 1, BUFFER_SIZE - filled)
+             != BUFFER_SIZE - filled)
+            {
+                PROBE_DEBUG ("Read failed.\n");
+                goto DONE;
+            }
+
+            filled = BUFFER_SIZE;
+        }
+
+        if (!initted)
+        {
+            int inner, a;
+            unsigned long r;
+            unsigned char ch;
+
+            inner = find_aac_header (buffer + offset, filled, &a);
+
+            if (inner < 0)
+            {
+                PROBE_DEBUG ("No ADTS header.\n");
+                goto DONE;
+            }
+
+            offset += inner;
+            filled -= inner;
+
+            decoder = NeAACDecOpen ();
+            inner = NeAACDecInit (decoder, buffer + offset, filled, &r, &ch);
+
+            if (inner < 0)
+            {
+                PROBE_DEBUG ("Decoder init failed.\n");
+                NeAACDecClose (decoder);
+                goto DONE;
+            }
+
+            offset += inner;
+            filled -= inner;
+            bytes_used += inner;
+
+            *samplerate = r;
+            *channels = ch;
+            initted = true;
+        }
+
+        if (NeAACDecDecode (decoder, &frame, buffer + offset, filled) == nullptr)
+        {
+            PROBE_DEBUG ("Decode failed.\n");
+            goto DONE;
+        }
+
+        if ((int)frame.samplerate != *samplerate || (int)frame.channels != *channels)
+        {
+            PROBE_DEBUG ("Parameter mismatch.\n");
+            goto DONE;
+        }
+
+        offset += frame.bytesconsumed;
+        filled -= frame.bytesconsumed;
+        bytes_used += frame.bytesconsumed;
+        time_used += frame.samples / frame.channels * (int64_t) 1000 /
+         frame.samplerate;
+    }
+
+    /* bits per millisecond = kilobits per second */
+    *bitrate = bytes_used * 8 / time_used;
+
+    if (size > 0)
+        *length = size * (int64_t) time_used / bytes_used;
+
+  DONE:
+    if (initted)
+        NeAACDecClose (decoder);
+}
+
+Tuple AACDecoder::read_tuple (const char * filename, VFSFile & handle)
+{
+    Tuple tuple;
+    int length, bitrate, samplerate, channels;
+
+    tuple.set_filename (filename);
+    tuple.set_str (Tuple::Codec, "MPEG-2/4 AAC");
+
+    calc_aac_info (handle, &length, &bitrate, &samplerate, &channels);
+
+    if (length > 0)
+        tuple.set_int (Tuple::Length, length);
+    if (bitrate > 0)
+        tuple.set_int (Tuple::Bitrate, bitrate);
+
+    tuple.fetch_stream_info (handle);
+
+    return tuple;
+}
+
+static void aac_seek (VFSFile & file, NeAACDecHandle dec, int time, int len,
+ void * buf, int size, int * buflen)
+{
+    /* == ESTIMATE BYTE OFFSET == */
+
+    int64_t total = file.fsize ();
+    if (total < 0)
+    {
+        AUDERR ("File is not seekable.\n");
+        return;
+    }
+
+    /* == SEEK == */
+
+    if (file.fseek (total * time / len, VFS_SEEK_SET))
+        return;
+
+    * buflen = file.fread (buf, 1, size);
+
+    /* == FIND FRAME HEADER == */
+
+    int used = aac_probe ((unsigned char *) buf, * buflen);
+
+    if (used == * buflen)
+    {
+        AUDERR ("No valid frame header found.\n");
+        * buflen = 0;
+        return;
+    }
+
+    if (used)
+    {
+        * buflen -= used;
+        memmove (buf, (char *) buf + used, * buflen);
+        * buflen += file.fread ((char *) buf + * buflen, 1, size - * buflen);
+    }
+
+    /* == START DECODING == */
+
+    unsigned char chan;
+    unsigned long rate;
+
+    if ((used = NeAACDecInit (dec, (unsigned char *) buf, * buflen, & rate, & chan)))
+    {
+        * buflen -= used;
+        memmove (buf, (char *) buf + used, * buflen);
+        * buflen += file.fread ((char *) buf + * buflen, 1, size - * buflen);
+    }
+}
+
+bool AACDecoder::play (const char * filename, VFSFile & file)
+{
+    NeAACDecHandle decoder = 0;
+    NeAACDecConfigurationPtr decoder_config;
+    unsigned long samplerate = 0;
+    unsigned char channels = 0;
+    int bitrate = 0;
+
+    Tuple tuple = get_playback_tuple ();
+
+    if (tuple)
+    {
+        bitrate = tuple.get_int (Tuple::Bitrate);
+        bitrate = 1000 * aud::max (0, bitrate);
+    }
+
+    if ((decoder = NeAACDecOpen ()) == nullptr)
+    {
+        AUDERR ("Open Decoder Error\n");
+        return false;
+    }
+
+    decoder_config = NeAACDecGetCurrentConfiguration (decoder);
+    decoder_config->outputFormat = FAAD_FMT_FLOAT;
+    NeAACDecSetConfiguration (decoder, decoder_config);
+
+    /* == FILL BUFFER == */
+
+    unsigned char buf[BUFFER_SIZE];
+    int buflen;
+    buflen = file.fread (buf, 1, sizeof buf);
+
+    /* == SKIP ID3 TAG == */
+
+    if (buflen >= 10 && ! strncmp ((char *) buf, "ID3", 3))
+    {
+        int tagsize = 10 + (buf[6] << 21) + (buf[7] << 14) + (buf[8] << 7) + buf[9];
+
+        if (file.fseek (tagsize, VFS_SEEK_SET))
+        {
+            AUDERR ("Failed to seek past ID3v2 tag.\n");
+            goto ERR_CLOSE_DECODER;
+        }
+
+        buflen = file.fread (buf, 1, sizeof buf);
+    }
+
+    /* == FIND FRAME HEADER == */
+
+    int used;
+    used = aac_probe (buf, buflen);
+
+    if (used == buflen)
+    {
+        AUDERR ("No valid frame header found.\n");
+        goto ERR_CLOSE_DECODER;
+    }
+
+    if (used)
+    {
+        buflen -= used;
+        memmove (buf, buf + used, buflen);
+        buflen += file.fread (buf + buflen, 1, sizeof buf - buflen);
+    }
+
+    /* == START DECODING == */
+
+    if ((used = NeAACDecInit (decoder, buf, buflen, & samplerate, & channels)))
+    {
+        buflen -= used;
+        memmove (buf, buf + used, buflen);
+        buflen += file.fread (buf + buflen, 1, sizeof buf - buflen);
+    }
+
+    /* == CHECK FOR METADATA == */
+
+    if (tuple && tuple.fetch_stream_info (file))
+        set_playback_tuple (tuple.ref ());
+
+    set_stream_bitrate (bitrate);
+
+    /* == START PLAYBACK == */
+
+    open_audio (FMT_FLOAT, samplerate, channels);
+
+    /* == MAIN LOOP == */
+
+    while (! check_stop ())
+    {
+        /* == HANDLE SEEK REQUESTS == */
+
+        int seek_value = check_seek ();
+
+        if (seek_value >= 0)
+        {
+            int length = tuple ? tuple.get_int (Tuple::Length) : 0;
+
+            if (length > 0)
+                aac_seek (file, decoder, seek_value, length, buf, sizeof buf, & buflen);
+        }
+
+        /* == CHECK FOR END OF FILE == */
+
+        if (! buflen)
+            break;
+
+        /* == CHECK FOR METADATA == */
+
+        if (tuple && tuple.fetch_stream_info (file))
+            set_playback_tuple (tuple.ref ());
+
+        /* == DECODE A FRAME == */
+
+        NeAACDecFrameInfo info;
+        void * audio = NeAACDecDecode (decoder, & info, buf, buflen);
+
+        if (info.error)
+        {
+            AUDERR ("%s.\n", NeAACDecGetErrorMessage (info.error));
+
+            if (buflen)
+            {
+                used = 1 + aac_probe (buf + 1, buflen - 1);
+                buflen -= used;
+                memmove (buf, buf + used, buflen);
+                buflen += file.fread (buf + buflen, 1, sizeof buf - buflen);
+            }
+
+            continue;
+        }
+
+        if ((used = info.bytesconsumed))
+        {
+            buflen -= used;
+            memmove (buf, buf + used, buflen);
+            buflen += file.fread (buf + buflen, 1, sizeof buf - buflen);
+        }
+
+        /* == PLAY THE SOUND == */
+
+        if (audio && info.samples)
+            write_audio (audio, sizeof (float) * info.samples);
+    }
+
+    NeAACDecClose (decoder);
+    return true;
+
+ERR_CLOSE_DECODER:
+    NeAACDecClose (decoder);
+    return false;
+}
diff --git a/src/aac/Makefile b/src/aac/Makefile
deleted file mode 100644
index 48e09e0716ed..000000000000
--- a/src/aac/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-PLUGIN = aac${PLUGIN_SUFFIX}
-
-SRCS = itunes-cover.c \
-       libmp4.c \
-       mp4_utils.c		\
-       mp4ff/mp4ff.c		\
-       mp4ff/mp4atom.c		\
-       mp4ff/mp4meta.c		\
-       mp4ff/mp4sample.c	\
-       mp4ff/mp4util.c		\
-       mp4ff/mp4tagupdate.c
-
-include ../../buildsys.mk
-include ../../extra.mk
-
-plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
-
-CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${FAAD_CFLAGS} -I../.. -I. -Imp4ff -DUSE_TAGGING=1
-LIBS += ${GLIB_LIBS} ${FAAD_LIBS} -lm
diff --git a/src/aac/itunes-cover.c b/src/aac/itunes-cover.c
deleted file mode 100644
index ac8ad962e5c3..000000000000
--- a/src/aac/itunes-cover.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * itunes-cover.c
- * John Lindgren, 2010
- *
- * The author hereby releases this code into the public domain.
- *
- * Reference:
- * http://atomicparsley.sourceforge.net/mpeg-4files.html
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include <libaudcore/vfs.h>
-
-static const char * const hier[] = {"moov", "udta", "meta", "ilst", "covr", "data"};
-static const int skip[] = {0, 0, 4, 0, 0, 8};
-
-bool_t read_itunes_cover (const char * filename, VFSFile * file, void * *
- data, int64_t * size)
-{
-    unsigned char b[8];
-    int bsize;
-
-    * data = NULL;
-    * size = 0;
-
-    /* Check for ftyp frame. */
-
-    if (vfs_fread (b, 1, 8, file) != 8)
-        return FALSE;
-    if ((bsize = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) < 8)
-        return FALSE;
-    if (strncmp ((char *) b + 4, "ftyp", 4))
-        return FALSE;
-    if (vfs_fseek (file, bsize - 8, SEEK_CUR))
-        return FALSE;
-
-    int64_t stop = INT64_MAX;
-    int64_t at = bsize;
-
-    /* Descend into frame hierarchy. */
-
-    for (int h = 0; h < ARRAY_LEN (hier); h ++)
-    {
-        while (1)
-        {
-            if (vfs_fread (b, 1, 8, file) != 8)
-                return FALSE;
-            if ((bsize = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) < 8
-             || at + bsize > stop)
-                return FALSE;
-            if (! strncmp ((char *) b + 4, hier[h], 4))
-                break;
-            if (vfs_fseek (file, bsize - 8, SEEK_CUR))
-                return FALSE;
-
-            at += bsize;
-        }
-
-        stop = at + bsize;
-        at += 8;
-
-        /* Skip leading bytes in some frames. */
-
-        if (skip[h])
-        {
-            if (vfs_fseek (file, skip[h], SEEK_CUR))
-                return FALSE;
-            at += skip[h];
-        }
-    }
-
-    /* We're there. */
-
-    * data = g_malloc (stop - at);
-    * size = stop - at;
-
-    if (vfs_fread (* data, 1, stop - at, file) != stop - at)
-    {
-        g_free (* data);
-        * data = NULL;
-        * size = 0;
-        return FALSE;
-    }
-
-    return TRUE;
-}
diff --git a/src/aac/libmp4.c b/src/aac/libmp4.c
deleted file mode 100644
index 5ad655cc09a7..000000000000
--- a/src/aac/libmp4.c
+++ /dev/null
@@ -1,320 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <neaacdec.h>
-
-#include "mp4ff.h"
-
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-
-/*
- * BUFFER_SIZE is the highest amount of memory that can be pulled.
- * We use this for sanity checks, among other things, as mp4ff needs
- * a labotomy sometimes.
- */
-#define BUFFER_SIZE (FAAD_MIN_STREAMSIZE * 16)
-
-static const char *fmts[] = { "m4a", "mp4", NULL };
-
-int getAACTrack (mp4ff_t *);
-
-static uint32_t mp4_read_callback (void *data, void *buffer, uint32_t len)
-{
-    if (data == NULL || buffer == NULL)
-        return -1;
-
-    return vfs_fread (buffer, 1, len, (VFSFile *) data);
-}
-
-static uint32_t mp4_seek_callback (void *data, uint64_t pos)
-{
-    if (! data || pos > INT64_MAX)
-        return -1;
-
-    return vfs_fseek ((VFSFile *) data, pos, SEEK_SET);
-}
-
-static bool_t is_mp4_aac_file (const char * filename, VFSFile * handle)
-{
-    mp4ff_callback_t mp4_data = {
-        .read = mp4_read_callback,
-        .seek = mp4_seek_callback,
-        .user_data = handle
-    };
-
-    mp4ff_t *mp4_handle = mp4ff_open_read (&mp4_data);
-    bool_t success;
-
-    if (mp4_handle == NULL)
-        return FALSE;
-
-    success = (getAACTrack (mp4_handle) != -1);
-
-    mp4ff_close (mp4_handle);
-    return success;
-}
-
-static void read_and_set_string (mp4ff_t * mp4, int (*func) (const mp4ff_t *
- mp4, char * *string), Tuple * tuple, int field)
-{
-    char *string = NULL;
-
-    func (mp4, &string);
-
-    if (string != NULL)
-        tuple_set_str (tuple, field, string);
-
-    g_free (string);
-}
-
-static Tuple *generate_tuple (const char * filename, mp4ff_t * mp4, int track)
-{
-    Tuple *tuple = tuple_new_from_filename (filename);
-    int64_t length;
-    int scale, rate, channels, bitrate;
-    char *year = NULL, *cd_track = NULL;
-    char scratch[32];
-
-    tuple_set_str (tuple, FIELD_CODEC, "MPEG-2/4 AAC");
-
-    length = mp4ff_get_track_duration (mp4, track);
-    scale = mp4ff_time_scale (mp4, track);
-
-    if (length > 0 && scale > 0)
-        tuple_set_int (tuple, FIELD_LENGTH, length * 1000 / scale);
-
-    rate = mp4ff_get_sample_rate (mp4, track);
-    channels = mp4ff_get_channel_count (mp4, track);
-
-    if (rate > 0 && channels > 0)
-    {
-        snprintf (scratch, sizeof scratch, "%d kHz, %s", rate / 1000, channels
-         == 1 ? _("mono") : channels == 2 ? _("stereo") : _("surround"));
-        tuple_set_str (tuple, FIELD_QUALITY, scratch);
-    }
-
-    bitrate = mp4ff_get_avg_bitrate (mp4, track);
-
-    if (bitrate > 0)
-        tuple_set_int (tuple, FIELD_BITRATE, bitrate / 1000);
-
-    read_and_set_string (mp4, mp4ff_meta_get_title, tuple, FIELD_TITLE);
-    read_and_set_string (mp4, mp4ff_meta_get_album, tuple, FIELD_ALBUM);
-    read_and_set_string (mp4, mp4ff_meta_get_artist, tuple, FIELD_ARTIST);
-    read_and_set_string (mp4, mp4ff_meta_get_comment, tuple, FIELD_COMMENT);
-    read_and_set_string (mp4, mp4ff_meta_get_genre, tuple, FIELD_GENRE);
-
-    mp4ff_meta_get_date (mp4, &year);
-
-    if (year != NULL)
-        tuple_set_int (tuple, FIELD_YEAR, atoi (year));
-
-    g_free (year);
-
-    mp4ff_meta_get_track (mp4, &cd_track);
-
-    if (cd_track != NULL)
-        tuple_set_int (tuple, FIELD_TRACK_NUMBER, atoi (cd_track));
-
-    g_free (cd_track);
-
-    return tuple;
-}
-
-static Tuple *mp4_get_tuple (const char * filename, VFSFile * handle)
-{
-    mp4ff_callback_t mp4cb;
-    mp4ff_t *mp4;
-    int track;
-    Tuple *tuple;
-
-    mp4cb.read = mp4_read_callback;
-    mp4cb.seek = mp4_seek_callback;
-    mp4cb.user_data = handle;
-
-    mp4 = mp4ff_open_read (&mp4cb);
-
-    if (mp4 == NULL)
-        return NULL;
-
-    track = getAACTrack (mp4);
-
-    if (track < 0)
-    {
-        mp4ff_close (mp4);
-        return NULL;
-    }
-
-    tuple = generate_tuple (filename, mp4, track);
-    mp4ff_close (mp4);
-    return tuple;
-}
-
-static bool_t my_decode_mp4 (const char * filename, mp4ff_t * mp4file)
-{
-    // We are reading an MP4 file
-    int mp4track = getAACTrack (mp4file);
-    NeAACDecHandle decoder;
-    NeAACDecConfigurationPtr decoder_config;
-    unsigned char *buffer = NULL;
-    unsigned bufferSize = 0;
-    unsigned long samplerate = 0;
-    unsigned char channels = 0;
-    unsigned numSamples;
-    unsigned long sampleID = 1;
-    unsigned framesize = 0;
-
-    if (mp4track < 0)
-    {
-        fprintf (stderr, "Unsupported Audio track type\n");
-        return TRUE;
-    }
-
-    // Open decoder
-    decoder = NeAACDecOpen ();
-
-    // Configure for floating point output
-    decoder_config = NeAACDecGetCurrentConfiguration (decoder);
-    decoder_config->outputFormat = FAAD_FMT_FLOAT;
-    NeAACDecSetConfiguration (decoder, decoder_config);
-
-    mp4ff_get_decoder_config (mp4file, mp4track, &buffer, &bufferSize);
-    if (!buffer)
-    {
-        NeAACDecClose (decoder);
-        return FALSE;
-    }
-    if (NeAACDecInit2 (decoder, buffer, bufferSize, &samplerate, &channels) < 0)
-    {
-        NeAACDecClose (decoder);
-
-        return FALSE;
-    }
-
-    g_free (buffer);
-    if (!channels)
-    {
-        NeAACDecClose (decoder);
-
-        return FALSE;
-    }
-    numSamples = mp4ff_num_samples (mp4file, mp4track);
-
-    if (!aud_input_open_audio (FMT_FLOAT, samplerate, channels))
-    {
-        NeAACDecClose (decoder);
-        return FALSE;
-    }
-
-    aud_input_set_tuple (generate_tuple (filename, mp4file, mp4track));
-    aud_input_set_bitrate (mp4ff_get_avg_bitrate (mp4file, mp4track));
-
-    while (! aud_input_check_stop ())
-    {
-        void *sampleBuffer;
-        NeAACDecFrameInfo frameInfo;
-        int rc;
-
-        buffer = NULL;
-        bufferSize = 0;
-
-        /* If we've run to the end of the file, we're done. */
-        if (sampleID >= numSamples)
-            break;
-
-        rc = mp4ff_read_sample (mp4file, mp4track,
-         sampleID++, &buffer, &bufferSize);
-
-        /* If we can't read the file, we're done. */
-        if ((rc == 0) || (buffer == NULL) || (bufferSize == 0)
-         || (bufferSize > BUFFER_SIZE))
-        {
-            fprintf (stderr, "MP4: read error\n");
-            sampleBuffer = NULL;
-
-            NeAACDecClose (decoder);
-
-            return FALSE;
-        }
-
-        sampleBuffer = NeAACDecDecode (decoder, &frameInfo, buffer, bufferSize);
-
-        /* If there was an error decoding, we're done. */
-        if (frameInfo.error > 0)
-        {
-            fprintf (stderr, "MP4: %s\n", NeAACDecGetErrorMessage (frameInfo.error));
-            NeAACDecClose (decoder);
-
-            return FALSE;
-        }
-        if (buffer)
-        {
-            g_free (buffer);
-            buffer = NULL;
-            bufferSize = 0;
-        }
-
-        /* Calculate frame size from the first (non-blank) frame.  This needs to
-         * be done before we try to seek. */
-        if (!framesize)
-        {
-            framesize = frameInfo.samples / frameInfo.channels;
-
-            if (!framesize)
-                continue;
-        }
-
-        /* Respond to seek/stop requests.  This needs to be done after we
-         * calculate frame size but of course before we write any audio. */
-        int seek_value = aud_input_check_seek ();
-
-        if (seek_value >= 0)
-        {
-            sampleID = (int64_t) seek_value * samplerate / 1000 / framesize;
-            continue;
-        }
-
-        aud_input_write_audio (sampleBuffer, sizeof (float) * frameInfo.samples);
-    }
-
-    NeAACDecClose (decoder);
-
-    return TRUE;
-}
-
-static bool_t mp4_play (const char * filename, VFSFile * file)
-{
-    bool_t result;
-
-    mp4ff_callback_t mp4cb = {
-        .read = mp4_read_callback,
-        .seek = mp4_seek_callback,
-        .user_data = file
-    };
-
-    mp4ff_t * mp4file = mp4ff_open_read (& mp4cb);
-    result = my_decode_mp4 (filename, mp4file);
-    mp4ff_close (mp4file);
-
-    return result;
-}
-
-bool_t read_itunes_cover (const char * filename, VFSFile * file, void * *
- data, int64_t * size);
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("AAC (MP4) Decoder"),
-    .domain = PACKAGE,
-    .play = mp4_play,
-    .is_our_file_from_vfs = is_mp4_aac_file,
-    .probe_for_tuple = mp4_get_tuple,
-    .get_song_image = read_itunes_cover,
-    .extensions = fmts,
-)
diff --git a/src/aac/mp4_utils.c b/src/aac/mp4_utils.c
deleted file mode 100644
index 7f83cf6d9f6f..000000000000
--- a/src/aac/mp4_utils.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * some functions for MP4 files
-*/
-
-#include <stdlib.h>
-#include <glib.h>
-
-#include "mp4ff.h"
-#include "neaacdec.h"
-
-int getAACTrack (mp4ff_t * infile)
-{
-    int i, rc, numTracks = mp4ff_total_tracks (infile);
-    for (i = 0; i < numTracks; i++)
-    {
-        unsigned char *buff = NULL;
-        unsigned buff_size = 0;
-        mp4AudioSpecificConfig mp4ASC;
-
-        mp4ff_get_decoder_config (infile, i, &buff, &buff_size);
-        if (buff != NULL)
-        {
-            rc = AudioSpecificConfig (buff, buff_size, &mp4ASC);
-            g_free (buff);
-            if (rc < 0)
-                continue;
-            return i;
-        }
-    }
-    return -1;
-}
diff --git a/src/aac/mp4ff/mp4atom.c b/src/aac/mp4ff/mp4atom.c
deleted file mode 100644
index 23712dd1b06d..000000000000
--- a/src/aac/mp4ff/mp4atom.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4atom.c,v 1.29 2009/01/19 23:56:30 menno Exp $
-**/
-
-#include <stdlib.h>
-#include "mp4ffint.h"
-
-#define       COPYRIGHT_SYMBOL        ((int8_t)0xA9)
-
-/* parse atom header size */
-static uint32_t mp4ff_atom_get_size(const uint8_t *data)
-{
-    uint32_t result;
-    uint32_t a, b, c, d;
-
-    a = data[0];
-    b = data[1];
-    c = data[2];
-    d = data[3];
-
-    result = (a<<24) | (b<<16) | (c<<8) | d;
-    //if (result > 0 && result < 8) result = 8;
-
-    return result;
-}
-
-/* comnapre 2 atom names, returns 1 for equal, 0 for unequal */
-static int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1,
-                                  const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2)
-{
-    if (a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2)
-        return 1;
-    else
-        return 0;
-}
-
-static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b,
-                                       const int8_t c, const int8_t d)
-{
-    if (a == 'm')
-    {
-        if (mp4ff_atom_compare(a,b,c,d, 'm','o','o','v'))
-            return ATOM_MOOV;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','i','n','f'))
-            return ATOM_MINF;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','d','i','a'))
-            return ATOM_MDIA;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','d','a','t'))
-            return ATOM_MDAT;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','d','h','d'))
-            return ATOM_MDHD;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','v','h','d'))
-            return ATOM_MVHD;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','a'))
-            return ATOM_MP4A;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','v'))
-            return ATOM_MP4V;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','s'))
-            return ATOM_MP4S;
-        else if (mp4ff_atom_compare(a,b,c,d, 'm','e','t','a'))
-            return ATOM_META;
-    } else if (a == 't') {
-        if (mp4ff_atom_compare(a,b,c,d, 't','r','a','k'))
-            return ATOM_TRAK;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','k','h','d'))
-            return ATOM_TKHD;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','r','e','f'))
-            return ATOM_TREF;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','r','k','n'))
-            return ATOM_TRACK;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','m','p','o'))
-            return ATOM_TEMPO;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','v','n','n'))
-            return ATOM_NETWORK;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','v','s','h'))
-            return ATOM_SHOW;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','v','e','n'))
-            return ATOM_EPISODENAME;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','v','s','n'))
-            return ATOM_SEASON;
-        else if (mp4ff_atom_compare(a,b,c,d, 't','v','e','s'))
-            return ATOM_EPISODE;
-    } else if (a == 's') {
-        if (mp4ff_atom_compare(a,b,c,d, 's','t','b','l'))
-            return ATOM_STBL;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','m','h','d'))
-            return ATOM_SMHD;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','d'))
-            return ATOM_STSD;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','t','s'))
-            return ATOM_STTS;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','c','o'))
-            return ATOM_STCO;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','c'))
-            return ATOM_STSC;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','z'))
-            return ATOM_STSZ;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','t','z','2'))
-            return ATOM_STZ2;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','k','i','p'))
-            return ATOM_SKIP;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','i','n','f'))
-            return ATOM_SINF;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','c','h','i'))
-            return ATOM_SCHI;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','n','m'))
-            return ATOM_SORTTITLE;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','a','l'))
-            return ATOM_SORTALBUM;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','a','r'))
-            return ATOM_SORTARTIST;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','a','a'))
-            return ATOM_SORTALBUMARTIST;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','c','o'))
-            return ATOM_SORTWRITER;
-        else if (mp4ff_atom_compare(a,b,c,d, 's','o','s','n'))
-            return ATOM_SORTSHOW;
-    } else if (a == COPYRIGHT_SYMBOL) {
-        if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'n','a','m'))
-            return ATOM_TITLE;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'A','R','T'))
-            return ATOM_ARTIST;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'w','r','t'))
-            return ATOM_WRITER;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'a','l','b'))
-            return ATOM_ALBUM;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'d','a','y'))
-            return ATOM_DATE;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'t','o','o'))
-            return ATOM_TOOL;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'c','m','t'))
-            return ATOM_COMMENT;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'g','e','n'))
-            return ATOM_GENRE1;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'g','r','p'))
-            return ATOM_CONTENTGROUP;
-        else if (mp4ff_atom_compare(a,b,c,d, COPYRIGHT_SYMBOL,'l','y','r'))
-            return ATOM_LYRICS;
-    }
-
-    if (mp4ff_atom_compare(a,b,c,d, 'e','d','t','s'))
-        return ATOM_EDTS;
-    else if (mp4ff_atom_compare(a,b,c,d, 'e','s','d','s'))
-        return ATOM_ESDS;
-    else if (mp4ff_atom_compare(a,b,c,d, 'f','t','y','p'))
-        return ATOM_FTYP;
-    else if (mp4ff_atom_compare(a,b,c,d, 'f','r','e','e'))
-        return ATOM_FREE;
-    else if (mp4ff_atom_compare(a,b,c,d, 'h','m','h','d'))
-        return ATOM_HMHD;
-    else if (mp4ff_atom_compare(a,b,c,d, 'v','m','h','d'))
-        return ATOM_VMHD;
-    else if (mp4ff_atom_compare(a,b,c,d, 'u','d','t','a'))
-        return ATOM_UDTA;
-    else if (mp4ff_atom_compare(a,b,c,d, 'i','l','s','t'))
-        return ATOM_ILST;
-    else if (mp4ff_atom_compare(a,b,c,d, 'n','a','m','e'))
-        return ATOM_NAME;
-    else if (mp4ff_atom_compare(a,b,c,d, 'd','a','t','a'))
-        return ATOM_DATA;
-    else if (mp4ff_atom_compare(a,b,c,d, 'd','i','s','k'))
-        return ATOM_DISC;
-    else if (mp4ff_atom_compare(a,b,c,d, 'g','n','r','e'))
-        return ATOM_GENRE2;
-    else if (mp4ff_atom_compare(a,b,c,d, 'c','o','v','r'))
-        return ATOM_COVER;
-    else if (mp4ff_atom_compare(a,b,c,d, 'c','p','i','l'))
-        return ATOM_COMPILATION;
-    else if (mp4ff_atom_compare(a,b,c,d, 'c','t','t','s'))
-        return ATOM_CTTS;
-    else if (mp4ff_atom_compare(a,b,c,d, 'd','r','m','s'))
-        return ATOM_DRMS;
-    else if (mp4ff_atom_compare(a,b,c,d, 'f','r','m','a'))
-        return ATOM_FRMA;
-    else if (mp4ff_atom_compare(a,b,c,d, 'p','r','i','v'))
-        return ATOM_PRIV;
-    else if (mp4ff_atom_compare(a,b,c,d, 'i','v','i','v'))
-        return ATOM_IVIV;
-    else if (mp4ff_atom_compare(a,b,c,d, 'u','s','e','r'))
-        return ATOM_USER;
-    else if (mp4ff_atom_compare(a,b,c,d, 'k','e','y',' '))
-        return ATOM_KEY;
-    else if (mp4ff_atom_compare(a,b,c,d, 'a','A','R','T'))
-        return ATOM_ALBUM_ARTIST;
-    else if (mp4ff_atom_compare(a,b,c,d, 'd','e','s','c'))
-        return ATOM_DESCRIPTION;
-    else if (mp4ff_atom_compare(a,b,c,d, 'p','c','s','t'))
-        return ATOM_PODCAST;
-    else
-        return ATOM_UNKNOWN;
-}
-
-/* read atom header, return atom size, atom size is with header included */
-uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size)
-{
-    uint64_t size;
-    int32_t ret;
-    uint8_t atom_header[8];
-
-    ret = mp4ff_read_data(f, atom_header, 8);
-    if (ret != 8)
-        return 0;
-
-    size = mp4ff_atom_get_size(atom_header);
-    *header_size = 8;
-
-    /* check for 64 bit atom size */
-    if (size == 1)
-    {
-        *header_size = 16;
-        size = mp4ff_read_int64(f);
-    }
-
-    //printf("%c%c%c%c\n", atom_header[4], atom_header[5], atom_header[6], atom_header[7]);
-
-    *atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5], atom_header[6], atom_header[7]);
-
-    return size;
-}
-
-static int32_t mp4ff_read_stsz(mp4ff_t *f)
-{
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f);
-    f->track[f->total_tracks - 1]->stsz_sample_count = mp4ff_read_int32(f);
-
-    if (f->track[f->total_tracks - 1]->stsz_sample_size == 0)
-    {
-        int32_t i;
-        f->track[f->total_tracks - 1]->stsz_table =
-            (int32_t*)malloc(f->track[f->total_tracks - 1]->stsz_sample_count*sizeof(int32_t));
-
-        for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count; i++)
-        {
-            f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f);
-        }
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_read_esds(mp4ff_t *f)
-{
-    uint8_t tag;
-    uint32_t temp;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-
-    /* get and verify ES_DescrTag */
-    tag = mp4ff_read_char(f);
-    if (tag == 0x03)
-    {
-        /* read length */
-        if (mp4ff_read_mp4_descr_length(f) < 5 + 15)
-        {
-            return 1;
-        }
-        /* skip 3 bytes */
-        mp4ff_read_int24(f);
-    } else {
-        /* skip 2 bytes */
-        mp4ff_read_int16(f);
-    }
-
-    /* get and verify DecoderConfigDescrTab */
-    if (mp4ff_read_char(f) != 0x04)
-    {
-        return 1;
-    }
-
-    /* read length */
-    temp = mp4ff_read_mp4_descr_length(f);
-    if (temp < 13) return 1;
-
-    f->track[f->total_tracks - 1]->audioType = mp4ff_read_char(f);
-    mp4ff_read_int32(f);//0x15000414 ????
-    f->track[f->total_tracks - 1]->maxBitrate = mp4ff_read_int32(f);
-    f->track[f->total_tracks - 1]->avgBitrate = mp4ff_read_int32(f);
-
-    /* get and verify DecSpecificInfoTag */
-    if (mp4ff_read_char(f) != 0x05)
-    {
-        return 1;
-    }
-
-    /* read length */
-    f->track[f->total_tracks - 1]->decoderConfigLen = mp4ff_read_mp4_descr_length(f);
-
-    if (f->track[f->total_tracks - 1]->decoderConfig)
-        free(f->track[f->total_tracks - 1]->decoderConfig);
-    f->track[f->total_tracks - 1]->decoderConfig = malloc(f->track[f->total_tracks - 1]->decoderConfigLen);
-    if (f->track[f->total_tracks - 1]->decoderConfig)
-    {
-        mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig, f->track[f->total_tracks - 1]->decoderConfigLen);
-    } else {
-        f->track[f->total_tracks - 1]->decoderConfigLen = 0;
-    }
-
-    /* will skip the remainder of the atom */
-    return 0;
-}
-
-static int32_t mp4ff_read_mp4a(mp4ff_t *f)
-{
-    int32_t i;
-    uint8_t atom_type = 0;
-    uint8_t header_size = 0;
-
-    for (i = 0; i < 6; i++)
-    {
-        mp4ff_read_char(f); /* reserved */
-    }
-    /* data_reference_index */ mp4ff_read_int16(f);
-
-    mp4ff_read_int32(f); /* reserved */
-    mp4ff_read_int32(f); /* reserved */
-
-    f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f);
-    f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f);
-
-    mp4ff_read_int16(f);
-    mp4ff_read_int16(f);
-
-    f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f);
-
-    mp4ff_read_int16(f);
-
-    mp4ff_atom_read_header(f, &atom_type, &header_size);
-    if (atom_type == ATOM_ESDS)
-    {
-        mp4ff_read_esds(f);
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_read_stsd(mp4ff_t *f)
-{
-    int32_t i;
-    uint8_t header_size = 0;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-
-    f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f);
-
-    for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++)
-    {
-        uint64_t skip = mp4ff_position(f);
-        uint64_t size;
-        uint8_t atom_type = 0;
-        size = mp4ff_atom_read_header(f, &atom_type, &header_size);
-        skip += size;
-
-        if (atom_type == ATOM_MP4A)
-        {
-            f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
-            mp4ff_read_mp4a(f);
-        } else if (atom_type == ATOM_MP4V) {
-            f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
-        } else if (atom_type == ATOM_MP4S) {
-            f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
-        } else {
-            f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
-        }
-
-        mp4ff_set_position(f, skip);
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_read_stsc(mp4ff_t *f)
-{
-    int32_t i;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f);
-
-    f->track[f->total_tracks - 1]->stsc_first_chunk =
-        (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
-    f->track[f->total_tracks - 1]->stsc_samples_per_chunk =
-        (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
-    f->track[f->total_tracks - 1]->stsc_sample_desc_index =
-        (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t));
-
-    for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count; i++)
-    {
-        f->track[f->total_tracks - 1]->stsc_first_chunk[i] = mp4ff_read_int32(f);
-        f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] = mp4ff_read_int32(f);
-        f->track[f->total_tracks - 1]->stsc_sample_desc_index[i] = mp4ff_read_int32(f);
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_read_stco(mp4ff_t *f)
-{
-    int32_t i;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f);
-
-    f->track[f->total_tracks - 1]->stco_chunk_offset =
-        (int32_t*)malloc(f->track[f->total_tracks - 1]->stco_entry_count*sizeof(int32_t));
-
-    for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count; i++)
-    {
-        f->track[f->total_tracks - 1]->stco_chunk_offset[i] = mp4ff_read_int32(f);
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_read_ctts(mp4ff_t *f)
-{
-    int32_t i;
-    mp4ff_track_t * p_track = f->track[f->total_tracks - 1];
-
-    if (p_track->ctts_entry_count) return 0;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    p_track->ctts_entry_count = mp4ff_read_int32(f);
-
-    p_track->ctts_sample_count = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t));
-    p_track->ctts_sample_offset = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t));
-
-    if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0)
-    {
-        if (p_track->ctts_sample_count) {free(p_track->ctts_sample_count);p_track->ctts_sample_count=0;}
-        if (p_track->ctts_sample_offset) {free(p_track->ctts_sample_offset);p_track->ctts_sample_offset=0;}
-        p_track->ctts_entry_count = 0;
-        return 0;
-    }
-    else
-    {
-        for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count; i++)
-        {
-            p_track->ctts_sample_count[i] = mp4ff_read_int32(f);
-            p_track->ctts_sample_offset[i] = mp4ff_read_int32(f);
-        }
-        return 1;
-    }
-}
-
-static int32_t mp4ff_read_stts(mp4ff_t *f)
-{
-    int32_t i;
-    mp4ff_track_t * p_track = f->track[f->total_tracks - 1];
-
-    if (p_track->stts_entry_count) return 0;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    p_track->stts_entry_count = mp4ff_read_int32(f);
-
-    p_track->stts_sample_count = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t));
-    p_track->stts_sample_delta = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t));
-
-    if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0)
-    {
-        if (p_track->stts_sample_count) {free(p_track->stts_sample_count);p_track->stts_sample_count=0;}
-        if (p_track->stts_sample_delta) {free(p_track->stts_sample_delta);p_track->stts_sample_delta=0;}
-        p_track->stts_entry_count = 0;
-        return 0;
-    }
-    else
-    {
-        for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count; i++)
-        {
-            p_track->stts_sample_count[i] = mp4ff_read_int32(f);
-            p_track->stts_sample_delta[i] = mp4ff_read_int32(f);
-        }
-        return 1;
-    }
-}
-
-static int32_t mp4ff_read_mvhd(mp4ff_t *f)
-{
-    int32_t i;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-    /* creation_time */ mp4ff_read_int32(f);
-    /* modification_time */ mp4ff_read_int32(f);
-    f->time_scale = mp4ff_read_int32(f);
-    f->duration = mp4ff_read_int32(f);
-    /* preferred_rate */ mp4ff_read_int32(f); /*mp4ff_read_fixed32(f);*/
-    /* preferred_volume */ mp4ff_read_int16(f); /*mp4ff_read_fixed16(f);*/
-    for (i = 0; i < 10; i++)
-    {
-        /* reserved */ mp4ff_read_char(f);
-    }
-    for (i = 0; i < 9; i++)
-    {
-        mp4ff_read_int32(f); /* matrix */
-    }
-    /* preview_time */ mp4ff_read_int32(f);
-    /* preview_duration */ mp4ff_read_int32(f);
-    /* poster_time */ mp4ff_read_int32(f);
-    /* selection_time */ mp4ff_read_int32(f);
-    /* selection_duration */ mp4ff_read_int32(f);
-    /* current_time */ mp4ff_read_int32(f);
-    /* next_track_id */ mp4ff_read_int32(f);
-
-    return 0;
-}
-
-#if 0
-static int32_t mp4ff_read_tkhd(mp4ff_t *f)
-{
-    uint8_t version;
-    uint32_t flags;
-    version = mp4ff_read_char(f); /* version */
-    flags = mp4ff_read_int24(f); /* flags */
-    if (version==1)
-    {
-        mp4ff_read_int64(f);//creation-time
-        mp4ff_read_int64(f);//modification-time
-        mp4ff_read_int32(f);//track-id
-        mp4ff_read_int32(f);//reserved
-        f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration
-    }
-    else //version == 0
-    {
-        mp4ff_read_int32(f);//creation-time
-        mp4ff_read_int32(f);//modification-time
-        mp4ff_read_int32(f);//track-id
-        mp4ff_read_int32(f);//reserved
-        f->track[f->total_tracks - 1]->duration = mp4ff_read_int32(f);//duration
-        if (f->track[f->total_tracks - 1]->duration == 0xFFFFFFFF)
-            f->track[f->total_tracks - 1]->duration = 0xFFFFFFFFFFFFFFFF;
-
-    }
-    mp4ff_read_int32(f);//reserved
-    mp4ff_read_int32(f);//reserved
-    mp4ff_read_int16(f);//layer
-    mp4ff_read_int16(f);//pre-defined
-    mp4ff_read_int16(f);//volume
-    mp4ff_read_int16(f);//reserved
-
-    //matrix
-    mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
-    mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
-    mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f);
-    mp4ff_read_int32(f);//width
-    mp4ff_read_int32(f);//height
-    return 1;
-}
-#endif
-
-static int32_t mp4ff_read_mdhd(mp4ff_t *f)
-{
-    uint32_t version;
-
-    version = mp4ff_read_int32(f);
-    if (version==1)
-    {
-        mp4ff_read_int64(f);//creation-time
-        mp4ff_read_int64(f);//modification-time
-        f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale
-        f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration
-    }
-    else //version == 0
-    {
-        uint32_t temp;
-
-        mp4ff_read_int32(f);//creation-time
-        mp4ff_read_int32(f);//modification-time
-        f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale
-        temp = mp4ff_read_int32(f);
-        f->track[f->total_tracks - 1]->duration = (temp == (uint32_t)(-1)) ? (uint64_t)(-1) : (uint64_t)(temp);
-    }
-    mp4ff_read_int16(f);
-    mp4ff_read_int16(f);
-    return 1;
-}
-#ifdef USE_TAGGING
-static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size)
-{
-    uint64_t subsize, sumsize = 0;
-    uint8_t atom_type;
-    uint8_t header_size = 0;
-
-    mp4ff_read_char(f); /* version */
-    mp4ff_read_int24(f); /* flags */
-
-    while (sumsize < (size-(header_size+4)))
-    {
-        subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
-        if (subsize <= header_size+4)
-            return 1;
-        if (atom_type == ATOM_ILST)
-        {
-            mp4ff_parse_metadata(f, (uint32_t)(subsize-(header_size+4)));
-        } else {
-            mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size);
-        }
-        sumsize += subsize;
-    }
-
-    return 0;
-}
-#endif
-
-int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type)
-{
-    uint64_t dest_position = mp4ff_position(f)+size-8;
-    if (atom_type == ATOM_STSZ)
-    {
-        /* sample size box */
-        mp4ff_read_stsz(f);
-    } else if (atom_type == ATOM_STTS) {
-        /* time to sample box */
-        mp4ff_read_stts(f);
-    } else if (atom_type == ATOM_CTTS) {
-        /* composition offset box */
-        mp4ff_read_ctts(f);
-    } else if (atom_type == ATOM_STSC) {
-        /* sample to chunk box */
-        mp4ff_read_stsc(f);
-    } else if (atom_type == ATOM_STCO) {
-        /* chunk offset box */
-        mp4ff_read_stco(f);
-    } else if (atom_type == ATOM_STSD) {
-        /* sample description box */
-        mp4ff_read_stsd(f);
-    } else if (atom_type == ATOM_MVHD) {
-        /* movie header box */
-        mp4ff_read_mvhd(f);
-    } else if (atom_type == ATOM_MDHD) {
-        /* track header */
-        mp4ff_read_mdhd(f);
-#ifdef USE_TAGGING
-    } else if (atom_type == ATOM_META) {
-        /* iTunes Metadata box */
-        mp4ff_read_meta(f, size);
-#endif
-    }
-
-    mp4ff_set_position(f, dest_position);
-
-
-    return 0;
-}
diff --git a/src/aac/mp4ff/mp4ff.c b/src/aac/mp4ff/mp4ff.c
deleted file mode 100644
index d8458faa0ffd..000000000000
--- a/src/aac/mp4ff/mp4ff.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4ff.c,v 1.22 2009/01/26 23:01:40 menno Exp $
-**/
-
-#include <stdlib.h>
-#include <string.h>
-#include "mp4ffint.h"
-
-mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f)
-{
-    mp4ff_t *ff = malloc(sizeof(mp4ff_t));
-
-    memset(ff, 0, sizeof(mp4ff_t));
-
-    ff->stream = f;
-
-    parse_atoms(ff,0);
-
-    return ff;
-}
-
-mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t *f)
-{
-    mp4ff_t *ff = malloc(sizeof(mp4ff_t));
-
-    memset(ff, 0, sizeof(mp4ff_t));
-
-    ff->stream = f;
-
-    parse_atoms(ff,1);
-
-    return ff;
-}
-
-void mp4ff_close(mp4ff_t *ff)
-{
-    int32_t i;
-
-    for (i = 0; i < ff->total_tracks; i++)
-    {
-        if (ff->track[i])
-        {
-            if (ff->track[i]->stsz_table)
-                free(ff->track[i]->stsz_table);
-            if (ff->track[i]->stts_sample_count)
-                free(ff->track[i]->stts_sample_count);
-            if (ff->track[i]->stts_sample_delta)
-                free(ff->track[i]->stts_sample_delta);
-            if (ff->track[i]->stsc_first_chunk)
-                free(ff->track[i]->stsc_first_chunk);
-            if (ff->track[i]->stsc_samples_per_chunk)
-                free(ff->track[i]->stsc_samples_per_chunk);
-            if (ff->track[i]->stsc_sample_desc_index)
-                free(ff->track[i]->stsc_sample_desc_index);
-            if (ff->track[i]->stco_chunk_offset)
-                free(ff->track[i]->stco_chunk_offset);
-            if (ff->track[i]->decoderConfig)
-                free(ff->track[i]->decoderConfig);
-            if (ff->track[i]->ctts_sample_count)
-                free(ff->track[i]->ctts_sample_count);
-            if (ff->track[i]->ctts_sample_offset)
-                free(ff->track[i]->ctts_sample_offset);
-#ifdef ITUNES_DRM
-            if (ff->track[i]->p_drms)
-                drms_free(ff->track[i]->p_drms);
-#endif
-            free(ff->track[i]);
-        }
-    }
-
-#ifdef USE_TAGGING
-    mp4ff_tag_delete(&(ff->tags));
-#endif
-
-    free(ff);
-}
-
-void mp4ff_track_add(mp4ff_t *f)
-{
-    f->total_tracks++;
-
-    f->track[f->total_tracks - 1] = malloc(sizeof(mp4ff_track_t));
-
-    memset(f->track[f->total_tracks - 1], 0, sizeof(mp4ff_track_t));
-}
-
-static int need_parse_when_meta_only(uint8_t atom_type)
-{
-    switch(atom_type)
-    {
-    case ATOM_EDTS:
-//  case ATOM_MDIA:
-//  case ATOM_MINF:
-    case ATOM_DRMS:
-    case ATOM_SINF:
-    case ATOM_SCHI:
-//  case ATOM_STBL:
-//  case ATOM_STSD:
-    case ATOM_STTS:
-    case ATOM_STSZ:
-    case ATOM_STZ2:
-    case ATOM_STCO:
-    case ATOM_STSC:
-//  case ATOM_CTTS:
-    case ATOM_FRMA:
-    case ATOM_IVIV:
-    case ATOM_PRIV:
-        return 0;
-    default:
-        return 1;
-    }
-}
-
-/* parse atoms that are sub atoms of other atoms */
-int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size,int meta_only)
-{
-    uint64_t size;
-    uint8_t atom_type = 0;
-    uint64_t counted_size = 0;
-    uint8_t header_size = 0;
-
-    while (counted_size < total_size)
-    {
-        size = mp4ff_atom_read_header(f, &atom_type, &header_size);
-        counted_size += size;
-
-        /* check for end of file */
-        if (size == 0)
-            break;
-
-        /* we're starting to read a new track, update index,
-         * so that all data and tables get written in the right place
-         */
-        if (atom_type == ATOM_TRAK)
-        {
-            mp4ff_track_add(f);
-        }
-
-        /* parse subatoms */
-        if (meta_only && !need_parse_when_meta_only(atom_type))
-        {
-            mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
-        } else if (atom_type < SUBATOMIC)
-        {
-            parse_sub_atoms(f, size-header_size,meta_only);
-        } else {
-            mp4ff_atom_read(f, (uint32_t)size, atom_type);
-        }
-    }
-
-    return 0;
-}
-
-/* parse root atoms */
-int32_t parse_atoms(mp4ff_t *f,int meta_only)
-{
-    uint64_t size;
-    uint8_t atom_type = 0;
-    uint8_t header_size = 0;
-
-    f->file_size = 0;
-
-    while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0)
-    {
-        f->file_size += size;
-        f->last_atom = atom_type;
-
-        if (atom_type == ATOM_MDAT && f->moov_read)
-        {
-            /* moov atom is before mdat, we can stop reading when mdat is encountered */
-            /* file position will stay at beginning of mdat data */
-//            break;
-        }
-
-        if (atom_type == ATOM_MOOV && size > header_size)
-        {
-            f->moov_read = 1;
-            f->moov_offset = mp4ff_position(f)-header_size;
-            f->moov_size = size;
-        }
-
-        /* parse subatoms */
-        if (meta_only && !need_parse_when_meta_only(atom_type))
-        {
-            if(mp4ff_set_position(f, mp4ff_position(f) + size - header_size) != 0)
-                break;
-        }
-        else if (atom_type < SUBATOMIC)
-        {
-            parse_sub_atoms(f, size-header_size,meta_only);
-        }
-        else
-        {
-            /* skip this atom */
-            if(mp4ff_set_position(f, mp4ff_position(f) + size - header_size) != 0)
-                break;
-        }
-    }
-
-    return 0;
-}
-
-int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track,
-                                 uint8_t** ppBuf, uint32_t* pBufSize)
-{
-    if (track >= f->total_tracks)
-    {
-        *ppBuf = NULL;
-        *pBufSize = 0;
-        return 1;
-    }
-
-    if (f->track[track]->decoderConfig == NULL || f->track[track]->decoderConfigLen == 0)
-    {
-        *ppBuf = NULL;
-        *pBufSize = 0;
-    } else {
-        *ppBuf = malloc(f->track[track]->decoderConfigLen);
-        if (*ppBuf == NULL)
-        {
-            *pBufSize = 0;
-            return 1;
-        }
-        memcpy(*ppBuf, f->track[track]->decoderConfig, f->track[track]->decoderConfigLen);
-        *pBufSize = f->track[track]->decoderConfigLen;
-    }
-
-    return 0;
-}
-
-int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track)
-{
-    return f->track[track]->type;
-}
-
-int32_t mp4ff_total_tracks(const mp4ff_t *f)
-{
-    return f->total_tracks;
-}
-
-int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track)
-{
-    return f->track[track]->timeScale;
-}
-
-uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track)
-{
-    return f->track[track]->avgBitrate;
-}
-
-uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track)
-{
-    return f->track[track]->maxBitrate;
-}
-
-int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track)
-{
-    return f->track[track]->duration;
-}
-
-int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track)
-{
-    int64_t duration = mp4ff_get_track_duration(f,track);
-    if (duration!=-1)
-    {
-        int64_t offset = mp4ff_get_sample_offset(f,track,0);
-        if (offset > duration) duration = 0;
-        else duration -= offset;
-    }
-    return duration;
-}
-
-int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track)
-{
-    int32_t i;
-    int32_t total = 0;
-
-    if (track < 0)
-        return -1;
-
-    for (i = 0; i < f->track[track]->stts_entry_count; i++)
-    {
-        total += f->track[track]->stts_sample_count[i];
-    }
-
-    return total;
-}
-
-uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track)
-{
-    return f->track[track]->sampleRate;
-}
-
-uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track)
-{
-    return f->track[track]->channelCount;
-}
-
-uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track)
-{
-    return f->track[track]->audioType;
-}
-
-int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t d,o;
-    d = mp4ff_get_sample_duration(f,track,sample);
-    if (d!=-1)
-    {
-        o = mp4ff_get_sample_offset(f,track,sample);
-        if (o>d) d = 0;
-        else d -= o;
-    }
-    return d;
-}
-
-int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t i, co = 0;
-
-    for (i = 0; i < f->track[track]->stts_entry_count; i++)
-    {
-        int32_t delta = f->track[track]->stts_sample_count[i];
-        if (sample < co + delta)
-            return f->track[track]->stts_sample_delta[i];
-        co += delta;
-    }
-    return (int32_t)(-1);
-}
-
-int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t i, co = 0;
-    int64_t acc = 0;
-
-    for (i = 0; i < f->track[track]->stts_entry_count; i++)
-    {
-        int32_t delta = f->track[track]->stts_sample_count[i];
-        if (sample < co + delta)
-        {
-            acc += f->track[track]->stts_sample_delta[i] * (sample - co);
-            return acc;
-        }
-        else
-        {
-            acc += f->track[track]->stts_sample_delta[i] * delta;
-        }
-        co += delta;
-    }
-    return (int64_t)(-1);
-}
-
-int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t i, co = 0;
-
-    for (i = 0; i < f->track[track]->ctts_entry_count; i++)
-    {
-        int32_t delta = f->track[track]->ctts_sample_count[i];
-        if (sample < co + delta)
-            return f->track[track]->ctts_sample_offset[i];
-        co += delta;
-    }
-    return 0;
-}
-
-int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip)
-{
-    int32_t i, co = 0;
-    int64_t offset_total = 0;
-    mp4ff_track_t * p_track = f->track[track];
-
-    for (i = 0; i < p_track->stts_entry_count; i++)
-    {
-        int32_t sample_count = p_track->stts_sample_count[i];
-        int32_t sample_delta = p_track->stts_sample_delta[i];
-        int64_t offset_delta = (int64_t)sample_delta * (int64_t)sample_count;
-        if (offset < offset_total + offset_delta)
-        {
-            int64_t offset_fromstts = offset - offset_total;
-            if (toskip) *toskip = (int32_t)(offset_fromstts % sample_delta);
-            return co + (int32_t)(offset_fromstts / sample_delta);
-        }
-        else
-        {
-            offset_total += offset_delta;
-        }
-        co += sample_count;
-    }
-    return (int32_t)(-1);
-}
-
-int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip)
-{
-    return mp4ff_find_sample(f,track,offset + mp4ff_get_sample_offset(f,track,0),toskip);
-}
-
-int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample,
-                          uint8_t **audio_buffer,  uint32_t *bytes)
-{
-    int32_t result = 0;
-
-    *bytes = mp4ff_audio_frame_size(f, track, sample);
-
-    if (*bytes==0) return 0;
-
-    *audio_buffer = (uint8_t*)malloc(*bytes);
-
-    mp4ff_set_sample_position(f, track, sample);
-
-    result = mp4ff_read_data(f, *audio_buffer, *bytes);
-
-    if (!result)
-    {
-        free(*audio_buffer);
-        *audio_buffer = 0;
-        return 0;
-    }
-
-#ifdef ITUNES_DRM
-    if (f->track[track]->p_drms != NULL)
-    {
-        drms_decrypt(f->track[track]->p_drms, (uint32_t*)*audio_buffer, *bytes);
-    }
-#endif
-
-    return *bytes;
-}
-
-
-int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer)
-{
-    int32_t result = 0;
-    int32_t size = mp4ff_audio_frame_size(f,track,sample);
-    if (size<=0) return 0;
-    mp4ff_set_sample_position(f, track, sample);
-    result = mp4ff_read_data(f,buffer,size);
-
-#ifdef ITUNES_DRM
-    if (f->track[track]->p_drms != NULL)
-    {
-        drms_decrypt(f->track[track]->p_drms, (uint32_t*)buffer, size);
-    }
-#endif
-
-    return result;
-}
-
-int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample)
-{
-    int32_t temp = mp4ff_audio_frame_size(f, track, sample);
-    if (temp<0) temp = 0;
-    return temp;
-}
diff --git a/src/aac/mp4ff/mp4ff.h b/src/aac/mp4ff/mp4ff.h
deleted file mode 100644
index 5851b0c7b257..000000000000
--- a/src/aac/mp4ff/mp4ff.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4ff.h,v 1.27 2009/01/29 00:41:08 menno Exp $
-**/
-
-#ifndef MP4FF_H
-#define MP4FF_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#else
-#include "mp4ff_int_types.h"
-#endif
-
-/* file callback structure */
-typedef struct
-{
-    uint32_t (*read)(void *user_data, void *buffer, uint32_t length);
-    uint32_t (*write)(void *udata, void *buffer, uint32_t length);
-    uint32_t (*seek)(void *user_data, uint64_t position);
-    uint32_t (*truncate)(void *user_data);
-    void *user_data;
-} mp4ff_callback_t;
-
-/* mp4 main file structure */
-typedef void* mp4ff_t;
-
-
-/* API */
-
-mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f);
-mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t *f);
-void mp4ff_close(mp4ff_t *f);
-int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_get_sample_duration_use_offsets(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
-int32_t mp4ff_find_sample_use_offsets(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
-
-int32_t mp4ff_read_sample(mp4ff_t *f, const int track, const int sample,
-                          unsigned char **audio_buffer,  unsigned int *bytes);
-
-int32_t mp4ff_read_sample_v2(mp4ff_t *f, const int track, const int sample,unsigned char *buffer);//returns 0 on error, number of bytes read on success, use mp4ff_read_sample_getsize() to check buffer size needed
-int32_t mp4ff_read_sample_getsize(mp4ff_t *f, const int track, const int sample);//returns 0 on error, buffer size needed for mp4ff_read_sample_v2() on success
-
-
-
-int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int track,
-                             unsigned char** ppBuf, unsigned int* pBufSize);
-int32_t mp4ff_get_track_type(const mp4ff_t *f, const int track);
-int32_t mp4ff_total_tracks(const mp4ff_t *f);
-int32_t mp4ff_num_samples(const mp4ff_t *f, const int track);
-int32_t mp4ff_time_scale(const mp4ff_t *f, const int track);
-
-uint32_t mp4ff_get_avg_bitrate(const mp4ff_t *f, const int32_t track);
-uint32_t mp4ff_get_max_bitrate(const mp4ff_t *f, const int32_t track);
-int64_t mp4ff_get_track_duration(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown
-int64_t mp4ff_get_track_duration_use_offsets(const mp4ff_t *f, const int32_t track); //returns (-1) if unknown
-uint32_t mp4ff_get_sample_rate(const mp4ff_t *f, const int32_t track);
-uint32_t mp4ff_get_channel_count(const mp4ff_t * f,const int32_t track);
-uint32_t mp4ff_get_audio_type(const mp4ff_t * f,const int32_t track);
-
-
-/* metadata */
-int mp4ff_meta_get_num_items(const mp4ff_t *f);
-int mp4ff_meta_get_by_index(const mp4ff_t *f, unsigned int index,
-                            char **item, char **value);
-int mp4ff_meta_get_title(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_artist(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_writer(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_album(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_date(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_tool(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_comment(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_track(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
-int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);
-#ifdef USE_TAGGING
-
-/* metadata tag structure */
-typedef struct
-{
-    char *item;
-    char *value;
-} mp4ff_tag_t;
-
-/* metadata list structure */
-typedef struct
-{
-    mp4ff_tag_t *tags;
-    uint32_t count;
-} mp4ff_metadata_t;
-
-int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data);
-
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
diff --git a/src/aac/mp4ff/mp4ff_int_types.h b/src/aac/mp4ff/mp4ff_int_types.h
deleted file mode 100644
index 7c5d27b697c2..000000000000
--- a/src/aac/mp4ff/mp4ff_int_types.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _MP4FF_INT_TYPES_H_
-#define _MP4FF_INT_TYPES_H_
-
-#if defined _WIN32 && ! defined __MINGW32__
-
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef signed short int16_t;
-typedef unsigned short uint16_t;
-typedef signed long int32_t;
-typedef unsigned long uint32_t;
-
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-#else
-
-#include <stdint.h>
-
-#endif
-
-
-#endif
diff --git a/src/aac/mp4ff/mp4ffint.h b/src/aac/mp4ff/mp4ffint.h
deleted file mode 100644
index 83bd0c1ace41..000000000000
--- a/src/aac/mp4ff/mp4ffint.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4ffint.h,v 1.26 2009/01/25 20:14:34 menno Exp $
-**/
-
-#ifndef MP4FF_INTERNAL_H
-#define MP4FF_INTERNAL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include "mp4ff_int_types.h"
-#include <stdlib.h>
-
-#define MAX_TRACKS 1024
-#define TRACK_UNKNOWN 0
-#define TRACK_AUDIO   1
-#define TRACK_VIDEO   2
-#define TRACK_SYSTEM  3
-
-
-#define SUBATOMIC 128
-
-/* atoms without subatoms */
-#define ATOM_FTYP 129
-#define ATOM_MDAT 130
-#define ATOM_MVHD 131
-#define ATOM_TKHD 132
-#define ATOM_TREF 133
-#define ATOM_MDHD 134
-#define ATOM_VMHD 135
-#define ATOM_SMHD 136
-#define ATOM_HMHD 137
-#define ATOM_STSD 138
-#define ATOM_STTS 139
-#define ATOM_STSZ 140
-#define ATOM_STZ2 141
-#define ATOM_STCO 142
-#define ATOM_STSC 143
-#define ATOM_MP4A 144
-#define ATOM_MP4V 145
-#define ATOM_MP4S 146
-#define ATOM_ESDS 147
-#define ATOM_META 148 /* iTunes Metadata box */
-#define ATOM_NAME 149 /* iTunes Metadata name box */
-#define ATOM_DATA 150 /* iTunes Metadata data box */
-#define ATOM_CTTS 151
-#define ATOM_FRMA 152
-#define ATOM_IVIV 153
-#define ATOM_PRIV 154
-#define ATOM_USER 155
-#define ATOM_KEY  156
-
-#define ATOM_ALBUM_ARTIST   157
-#define ATOM_CONTENTGROUP   158
-#define ATOM_LYRICS         159
-#define ATOM_DESCRIPTION    160
-#define ATOM_NETWORK        161
-#define ATOM_SHOW           162
-#define ATOM_EPISODENAME    163
-#define ATOM_SORTTITLE      164
-#define ATOM_SORTALBUM      165
-#define ATOM_SORTARTIST     166
-#define ATOM_SORTALBUMARTIST    167
-#define ATOM_SORTWRITER     168
-#define ATOM_SORTSHOW       169
-#define ATOM_SEASON         170
-#define ATOM_EPISODE        171
-#define ATOM_PODCAST        172
-
-#define ATOM_UNKNOWN 255
-#define ATOM_FREE ATOM_UNKNOWN
-#define ATOM_SKIP ATOM_UNKNOWN
-
-/* atoms with subatoms */
-#define ATOM_MOOV 1
-#define ATOM_TRAK 2
-#define ATOM_EDTS 3
-#define ATOM_MDIA 4
-#define ATOM_MINF 5
-#define ATOM_STBL 6
-#define ATOM_UDTA 7
-#define ATOM_ILST 8 /* iTunes Metadata list */
-#define ATOM_TITLE 9
-#define ATOM_ARTIST 10
-#define ATOM_WRITER 11
-#define ATOM_ALBUM 12
-#define ATOM_DATE 13
-#define ATOM_TOOL 14
-#define ATOM_COMMENT 15
-#define ATOM_GENRE1 16
-#define ATOM_TRACK 17
-#define ATOM_DISC 18
-#define ATOM_COMPILATION 19
-#define ATOM_GENRE2 20
-#define ATOM_TEMPO 21
-#define ATOM_COVER 22
-#define ATOM_DRMS 23
-#define ATOM_SINF 24
-#define ATOM_SCHI 25
-
-/* file callback structure */
-typedef struct
-{
-    uint32_t (*read)(void *user_data, void *buffer, uint32_t length);
-    uint32_t (*write)(void *udata, void *buffer, uint32_t length);
-    uint32_t (*seek)(void *user_data, uint64_t position);
-    uint32_t (*truncate)(void *user_data);
-    void *user_data;
-} mp4ff_callback_t;
-
-
-/* metadata tag structure */
-typedef struct
-{
-    char *item;
-    char *value;
-} mp4ff_tag_t;
-
-/* metadata list structure */
-typedef struct
-{
-    mp4ff_tag_t *tags;
-    uint32_t count;
-} mp4ff_metadata_t;
-
-
-typedef struct
-{
-    int32_t type;
-    int32_t channelCount;
-    int32_t sampleSize;
-    uint16_t sampleRate;
-    int32_t audioType;
-
-    /* stsd */
-    int32_t stsd_entry_count;
-
-    /* stsz */
-    int32_t stsz_sample_size;
-    int32_t stsz_sample_count;
-    int32_t *stsz_table;
-
-    /* stts */
-    int32_t stts_entry_count;
-    int32_t *stts_sample_count;
-    int32_t *stts_sample_delta;
-
-    /* stsc */
-    int32_t stsc_entry_count;
-    int32_t *stsc_first_chunk;
-    int32_t *stsc_samples_per_chunk;
-    int32_t *stsc_sample_desc_index;
-
-    /* stsc */
-    int32_t stco_entry_count;
-    int32_t *stco_chunk_offset;
-
-    /* ctts */
-    int32_t ctts_entry_count;
-    int32_t *ctts_sample_count;
-    int32_t *ctts_sample_offset;
-
-    /* esde */
-    uint8_t *decoderConfig;
-    int32_t decoderConfigLen;
-
-    uint32_t maxBitrate;
-    uint32_t avgBitrate;
-
-    uint32_t timeScale;
-    uint64_t duration;
-
-} mp4ff_track_t;
-
-/* mp4 main file structure */
-typedef struct
-{
-    /* stream to read from */
-    mp4ff_callback_t *stream;
-    int64_t current_position;
-
-    int32_t moov_read;
-    uint64_t moov_offset;
-    uint64_t moov_size;
-    uint8_t last_atom;
-    uint64_t file_size;
-
-    /* mvhd */
-    int32_t time_scale;
-    int32_t duration;
-
-    /* incremental track index while reading the file */
-    int32_t total_tracks;
-
-    /* track data */
-    mp4ff_track_t *track[MAX_TRACKS];
-
-    /* metadata */
-    mp4ff_metadata_t tags;
-} mp4ff_t;
-
-
-
-
-/* mp4util.c */
-int32_t mp4ff_read_data(mp4ff_t *f, void *data, uint32_t size);
-int32_t mp4ff_write_data(mp4ff_t *f, void *data, uint32_t size);
-uint64_t mp4ff_read_int64(mp4ff_t *f);
-uint32_t mp4ff_read_int32(mp4ff_t *f);
-uint32_t mp4ff_read_int24(mp4ff_t *f);
-uint16_t mp4ff_read_int16(mp4ff_t *f);
-uint8_t mp4ff_read_char(mp4ff_t *f);
-int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data);
-uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f);
-int64_t mp4ff_position(const mp4ff_t *f);
-int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position);
-int32_t mp4ff_truncate(mp4ff_t * f);
-char * mp4ff_read_string(mp4ff_t * f,uint32_t length);
-
-/* mp4atom.c */
-uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size);
-int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type);
-
-/* mp4sample.c */
-int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample);
-
-#ifdef USE_TAGGING
-/* mp4meta.c */
-int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size);
-int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags);
-int32_t mp4ff_meta_get_num_items(const mp4ff_t *f);
-int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index,
-                            char **item, char **value);
-int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
-int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);
-#endif
-
-/* mp4ff.c */
-mp4ff_t *mp4ff_open_read(mp4ff_callback_t *f);
-#ifdef USE_TAGGING
-mp4ff_t *mp4ff_open_edit(mp4ff_callback_t *f);
-#endif
-void mp4ff_close(mp4ff_t *ff);
-//void mp4ff_track_add(mp4ff_t *f);
-int32_t parse_sub_atoms(mp4ff_t *f, const uint64_t total_size,int meta_only);
-int32_t parse_atoms(mp4ff_t *f,int meta_only);
-
-int32_t mp4ff_get_sample_duration(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int64_t mp4ff_get_sample_position(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_get_sample_offset(const mp4ff_t *f, const int32_t track, const int32_t sample);
-int32_t mp4ff_find_sample(const mp4ff_t *f, const int32_t track, const int64_t offset,int32_t * toskip);
-
-int32_t mp4ff_read_sample(mp4ff_t *f, const int32_t track, const int32_t sample,
-                          uint8_t **audio_buffer,  uint32_t *bytes);
-int32_t mp4ff_get_decoder_config(const mp4ff_t *f, const int32_t track,
-                                 uint8_t** ppBuf, uint32_t* pBufSize);
-int32_t mp4ff_total_tracks(const mp4ff_t *f);
-int32_t mp4ff_time_scale(const mp4ff_t *f, const int32_t track);
-int32_t mp4ff_num_samples(const mp4ff_t *f, const int32_t track);
-
-uint32_t mp4ff_meta_genre_to_index(const char * genrestr);//returns 1-based index, 0 if not found
-const char * mp4ff_meta_index_to_genre(uint32_t idx);//returns pointer to static string
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
diff --git a/src/aac/mp4ff/mp4meta.c b/src/aac/mp4ff/mp4meta.c
deleted file mode 100644
index f1d8270e8dce..000000000000
--- a/src/aac/mp4ff/mp4meta.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4meta.c,v 1.21 2009/01/19 23:56:30 menno Exp $
-**/
-
-#ifdef USE_TAGGING
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-#include "mp4ffint.h"
-
-
-
-static int32_t mp4ff_tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value)
-{
-    void *backup = (void *)tags->tags;
-
-    if (!item || (item && !*item) || !value) return 0;
-
-    tags->tags = (mp4ff_tag_t*)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
-    if (!tags->tags)
-    {
-        if (backup) free(backup);
-        return 0;
-    } else {
-        tags->tags[tags->count].item = strdup(item);
-        tags->tags[tags->count].value = strdup(value);
-
-        if (!tags->tags[tags->count].item || !tags->tags[tags->count].value)
-        {
-            if (!tags->tags[tags->count].item) free (tags->tags[tags->count].item);
-            if (!tags->tags[tags->count].value) free (tags->tags[tags->count].value);
-            tags->tags[tags->count].item = NULL;
-            tags->tags[tags->count].value = NULL;
-            return 0;
-        }
-
-        tags->count++;
-        return 1;
-    }
-}
-
-/* GCC 4 says: unused!
-static int32_t mp4ff_tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value)
-{
-    unsigned int i;
-
-    if (!item || (item && !*item) || !value) return 0;
-
-    for (i = 0; i < tags->count; i++)
-    {
-        if (!g_ascii_strcasecmp(tags->tags[i].item, item))
-        {
-            free(tags->tags[i].value);
-            tags->tags[i].value = strdup(value);
-            return 1;
-        }
-    }
-
-    return mp4ff_tag_add_field(tags, item, value);
-}
-*/
-
-int32_t mp4ff_tag_delete(mp4ff_metadata_t *tags)
-{
-    uint32_t i;
-
-    for (i = 0; i < tags->count; i++)
-    {
-        if (tags->tags[i].item) free(tags->tags[i].item);
-        if (tags->tags[i].value) free(tags->tags[i].value);
-    }
-
-    if (tags->tags) free(tags->tags);
-
-    tags->tags = NULL;
-    tags->count = 0;
-
-    return 0;
-}
-
-static const char* ID3v1GenreList[] = {
-    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
-    "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
-    "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
-    "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
-    "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
-    "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
-    "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
-    "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
-    "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
-    "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
-    "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
-    "New Wave", "Psychedelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
-    "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
-    "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
-    "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
-    "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
-    "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
-    "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
-    "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
-    "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
-    "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
-    "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
-    "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
-    "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
-    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
-    "SynthPop",
-};
-
-uint32_t mp4ff_meta_genre_to_index(const char * genrestr)
-{
-    unsigned n;
-    for(n=0;n<sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0]);n++)
-    {
-        if (!g_ascii_strcasecmp(genrestr,ID3v1GenreList[n])) return n+1;
-    }
-    return 0;
-}
-
-const char * mp4ff_meta_index_to_genre(uint32_t idx)
-{
-    if (idx>0 && idx<=sizeof(ID3v1GenreList)/sizeof(ID3v1GenreList[0]))
-    {
-        return ID3v1GenreList[idx-1];
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-/* GCC4 says: unused!
-static int32_t TrackToString(char** str, const uint16_t track, const uint16_t totalTracks)
-{
-    char temp[32];
-    sprintf(temp, "%.5u of %.5u", track, totalTracks);
-    *str = strdup(temp);
-    return 0;
-}
-*/
-
-static int32_t mp4ff_set_metadata_name(mp4ff_t *f, const uint8_t atom_type, char **name)
-{
-    static char *tag_names[] = {
-        "unknown", "title", "artist", "writer", "album",
-        "date", "tool", "comment", "genre", "track",
-        "disc", "compilation", "genre", "tempo", "cover",
-        "album_artist", "contentgroup", "lyrics", "description",
-        "network", "show", "episodename",
-        "sorttitle", "sortalbum", "sortartist", "sortalbumartist",
-        "sortwriter", "sortshow",
-        "season", "episode", "podcast"
-
-    };
-    uint8_t tag_idx = 0;
-
-    switch (atom_type)
-    {
-    case ATOM_TITLE: tag_idx = 1; break;
-    case ATOM_ARTIST: tag_idx = 2; break;
-    case ATOM_WRITER: tag_idx = 3; break;
-    case ATOM_ALBUM: tag_idx = 4; break;
-    case ATOM_DATE: tag_idx = 5; break;
-    case ATOM_TOOL: tag_idx = 6; break;
-    case ATOM_COMMENT: tag_idx = 7; break;
-    case ATOM_GENRE1: tag_idx = 8; break;
-    case ATOM_TRACK: tag_idx = 9; break;
-    case ATOM_DISC: tag_idx = 10; break;
-    case ATOM_COMPILATION: tag_idx = 11; break;
-    case ATOM_GENRE2: tag_idx = 12; break;
-    case ATOM_TEMPO: tag_idx = 13; break;
-    case ATOM_COVER: tag_idx = 14; break;
-    case ATOM_ALBUM_ARTIST: tag_idx = 15; break;
-    case ATOM_CONTENTGROUP: tag_idx = 16; break;
-    case ATOM_LYRICS: tag_idx = 17; break;
-    case ATOM_DESCRIPTION: tag_idx = 18; break;
-    case ATOM_NETWORK: tag_idx = 19; break;
-    case ATOM_SHOW: tag_idx = 20; break;
-    case ATOM_EPISODENAME: tag_idx = 21; break;
-    case ATOM_SORTTITLE: tag_idx = 22; break;
-    case ATOM_SORTALBUM: tag_idx = 23; break;
-    case ATOM_SORTARTIST: tag_idx = 24; break;
-    case ATOM_SORTALBUMARTIST: tag_idx = 25; break;
-    case ATOM_SORTWRITER: tag_idx = 26; break;
-    case ATOM_SORTSHOW: tag_idx = 27; break;
-    case ATOM_SEASON: tag_idx = 28; break;
-    case ATOM_EPISODE: tag_idx = 29; break;
-    case ATOM_PODCAST: tag_idx = 30; break;
-    default: tag_idx = 0; break;
-    }
-
-    *name = strdup(tag_names[tag_idx]);
-
-    return 0;
-}
-
-static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size)
-{
-    uint8_t atom_type;
-    uint8_t header_size = 0;
-    uint64_t subsize, sumsize = 0;
-    char * name = NULL;
-    char * data = NULL;
-    uint32_t done = 0;
-
-
-    while (sumsize < size)
-    {
-        uint64_t destpos;
-        subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
-        if (!subsize)
-            break;
-
-        destpos = mp4ff_position(f)+subsize-header_size;
-        if (!done)
-        {
-            if (atom_type == ATOM_DATA)
-            {
-                mp4ff_read_char(f); /* version */
-                mp4ff_read_int24(f); /* flags */
-                mp4ff_read_int32(f); /* reserved */
-
-                /* some need special attention */
-                if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO)
-                {
-                    if (subsize - header_size >= 8 + 2)
-                    {
-                        uint16_t val = mp4ff_read_int16(f);
-
-                        if (parent_atom_type == ATOM_TEMPO)
-                        {
-                            char temp[16];
-                            sprintf(temp, "%.5u BPM", val);
-                            mp4ff_tag_add_field(&(f->tags), "tempo", temp);
-                        }
-                        else
-                        {
-                            const char * temp = mp4ff_meta_index_to_genre(val);
-                            if (temp)
-                            {
-                                mp4ff_tag_add_field(&(f->tags), "genre", temp);
-                            }
-                        }
-                        done = 1;
-                    }
-                } else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
-                    /* if (!done && subsize - header_size >= 8 + 8) */
-                    /* modified by AJS */
-                    if ( !done && (subsize - header_size) >=
-                        (sizeof(char) + sizeof(uint8_t)*3 + sizeof(uint32_t) + /* version + flags + reserved */
-                        + sizeof(uint16_t) /* leading uint16_t */
-                        + sizeof(uint16_t) /* track / disc */
-                        + sizeof(uint16_t)) /* totaltracks / totaldiscs */
-                        )
-                    {
-                        uint16_t index,total;
-                        char temp[32];
-                        mp4ff_read_int16(f);
-                        index = mp4ff_read_int16(f);
-                        total = mp4ff_read_int16(f);
-                        /* modified by AJS */
-                        /* mp4ff_read_int16(f); */
-
-                        sprintf(temp,"%d",index);
-                        mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "track" : "disc", temp);
-                        if (total>0)
-                        {
-                            sprintf(temp,"%d",total);
-                            mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "totaltracks" : "totaldiscs", temp);
-                        }
-                        done = 1;
-                    }
-                } else
-                {
-                    if (data) {free(data);data = NULL;}
-                    data = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+8)));
-                }
-            } else if (atom_type == ATOM_NAME) {
-                if (!done)
-                {
-                    mp4ff_read_char(f); /* version */
-                    mp4ff_read_int24(f); /* flags */
-                    if (name) free(name);
-                    name = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+4)));
-                }
-            }
-            mp4ff_set_position(f, destpos);
-            sumsize += subsize;
-        }
-    }
-
-    if (data)
-    {
-        if (!done)
-        {
-            if (name == NULL) mp4ff_set_metadata_name(f, parent_atom_type, &name);
-            if (name) mp4ff_tag_add_field(&(f->tags), name, data);
-        }
-
-        free(data);
-    }
-    if (name) free(name);
-    return 1;
-}
-
-int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size)
-{
-    uint64_t subsize, sumsize = 0;
-    uint8_t atom_type;
-    uint8_t header_size = 0;
-
-    while (sumsize < size)
-    {
-        subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
-        if (subsize == 0)
-            break;
-        mp4ff_parse_tag(f, atom_type, (uint32_t)(subsize-header_size));
-        sumsize += subsize;
-    }
-
-    return 0;
-}
-
-/* find a metadata item by name */
-/* returns 0 if item found, 1 if no such item */
-static int32_t mp4ff_meta_find_by_name(const mp4ff_t *f, const char *item, char **value)
-{
-    uint32_t i;
-
-    for (i = 0; i < f->tags.count; i++)
-    {
-        if (!g_ascii_strcasecmp(f->tags.tags[i].item, item))
-        {
-            *value = strdup(f->tags.tags[i].value);
-            return 1;
-        }
-    }
-
-    *value = NULL;
-
-    /* not found */
-    return 0;
-}
-
-int32_t mp4ff_meta_get_num_items(const mp4ff_t *f)
-{
-    return f->tags.count;
-}
-
-int32_t mp4ff_meta_get_by_index(const mp4ff_t *f, uint32_t index,
-                                char **item, char **value)
-{
-    if (index >= f->tags.count)
-    {
-        *item = NULL;
-        *value = NULL;
-        return 0;
-    } else {
-        *item = strdup(f->tags.tags[index].item);
-        *value = strdup(f->tags.tags[index].value);
-        return 1;
-    }
-}
-
-int32_t mp4ff_meta_get_title(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "title", value);
-}
-
-int32_t mp4ff_meta_get_artist(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "artist", value);
-}
-
-int32_t mp4ff_meta_get_writer(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "writer", value);
-}
-
-int32_t mp4ff_meta_get_album(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "album", value);
-}
-
-int32_t mp4ff_meta_get_date(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "date", value);
-}
-
-int32_t mp4ff_meta_get_tool(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "tool", value);
-}
-
-int32_t mp4ff_meta_get_comment(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "comment", value);
-}
-
-int32_t mp4ff_meta_get_genre(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "genre", value);
-}
-
-int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "track", value);
-}
-
-int32_t mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "totaltracks", value);
-}
-
-int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "disc", value);
-}
-
-int32_t mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "totaldiscs", value);
-}
-
-int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "compilation", value);
-}
-
-int32_t mp4ff_meta_get_tempo(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "tempo", value);
-}
-
-int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value)
-{
-    return mp4ff_meta_find_by_name(f, "cover", value);
-}
-
-#endif
diff --git a/src/aac/mp4ff/mp4sample.c b/src/aac/mp4ff/mp4sample.c
deleted file mode 100644
index cb22264f7782..000000000000
--- a/src/aac/mp4ff/mp4sample.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4sample.c,v 1.20 2007/11/01 12:33:29 menno Exp $
-**/
-
-#include <stdlib.h>
-#include "mp4ffint.h"
-
-
-static int32_t mp4ff_chunk_of_sample(const mp4ff_t *f, const int32_t track, const int32_t sample,
-                                     int32_t *chunk_sample, int32_t *chunk)
-{
-    int32_t total_entries = 0;
-    int32_t chunk2entry;
-    int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
-
-    if (f->track[track] == NULL)
-    {
-        return -1;
-    }
-
-    total_entries = f->track[track]->stsc_entry_count;
-
-    chunk1 = 1;
-    chunk1samples = 0;
-    chunk2entry = 0;
-
-    do
-    {
-        chunk2 = f->track[track]->stsc_first_chunk[chunk2entry];
-        *chunk = chunk2 - chunk1;
-        range_samples = *chunk * chunk1samples;
-
-        if (sample < total + range_samples) break;
-
-        chunk1samples = f->track[track]->stsc_samples_per_chunk[chunk2entry];
-        chunk1 = chunk2;
-
-        if(chunk2entry < total_entries)
-        {
-            chunk2entry++;
-            total += range_samples;
-        }
-    } while (chunk2entry < total_entries);
-
-    if (chunk1samples)
-        *chunk = (sample - total) / chunk1samples + chunk1;
-    else
-        *chunk = 1;
-
-    *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
-
-    return 0;
-}
-
-static int32_t mp4ff_chunk_to_offset(const mp4ff_t *f, const int32_t track, const int32_t chunk)
-{
-    const mp4ff_track_t * p_track = f->track[track];
-
-    if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count))
-    {
-        return p_track->stco_chunk_offset[p_track->stco_entry_count - 1];
-    } else if (p_track->stco_entry_count) {
-        return p_track->stco_chunk_offset[chunk - 1];
-    } else {
-        return 8;
-    }
-
-    return 0;
-}
-
-static int32_t mp4ff_sample_range_size(const mp4ff_t *f, const int32_t track,
-                                       const int32_t chunk_sample, const int32_t sample)
-{
-    int32_t i, total;
-    const mp4ff_track_t * p_track = f->track[track];
-
-    if (p_track->stsz_sample_size)
-    {
-        return (sample - chunk_sample) * p_track->stsz_sample_size;
-    }
-    else
-    {
-        if (sample>=p_track->stsz_sample_count) return 0;//error
-
-        for(i = chunk_sample, total = 0; i < sample; i++)
-        {
-            total += p_track->stsz_table[i];
-        }
-    }
-
-    return total;
-}
-
-static int32_t mp4ff_sample_to_offset(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t chunk=0, chunk_sample=0, chunk_offset1, chunk_offset2;
-
-    mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
-
-    chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
-    chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f, track, chunk_sample, sample);
-
-    return chunk_offset2;
-}
-
-int32_t mp4ff_audio_frame_size(const mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t bytes;
-    const mp4ff_track_t * p_track = f->track[track];
-
-    if (p_track->stsz_sample_size)
-    {
-        bytes = p_track->stsz_sample_size;
-    } else {
-        bytes = p_track->stsz_table[sample];
-    }
-
-    return bytes;
-}
-
-int32_t mp4ff_set_sample_position(mp4ff_t *f, const int32_t track, const int32_t sample)
-{
-    int32_t offset;
-
-    offset = mp4ff_sample_to_offset(f, track, sample);
-    mp4ff_set_position(f, offset);
-
-    return 0;
-}
diff --git a/src/aac/mp4ff/mp4tagupdate.c b/src/aac/mp4ff/mp4tagupdate.c
deleted file mode 100644
index 4b6d79fbffc8..000000000000
--- a/src/aac/mp4ff/mp4tagupdate.c
+++ /dev/null
@@ -1,658 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include "mp4ffint.h"
-
-#ifdef USE_TAGGING
-
-static uint32_t fix_byte_order_32(uint32_t src)
-{
-    uint32_t result;
-    uint32_t a, b, c, d;
-    int8_t data[4];
-
-    memcpy(data,&src,sizeof(src));
-    a = (uint8_t)data[0];
-    b = (uint8_t)data[1];
-    c = (uint8_t)data[2];
-    d = (uint8_t)data[3];
-
-    result = (a<<24) | (b<<16) | (c<<8) | d;
-    return (uint32_t)result;
-}
-
-/* GCC4 says: unused!
-static uint16_t fix_byte_order_16(uint16_t src)
-{
-    uint16_t result;
-    uint16_t a, b;
-    int8_t data[2];
-
-    memcpy(data,&src,sizeof(src));
-    a = (uint8_t)data[0];
-    b = (uint8_t)data[1];
-
-    result = (a<<8) | b;
-    return (uint16_t)result;
-}
-*/
-
-typedef struct
-{
-    void * data;
-    unsigned written;
-    unsigned allocated;
-    unsigned error;
-} membuffer;
-
-unsigned membuffer_write(membuffer * buf,const void * ptr,unsigned bytes)
-{
-    unsigned dest_size = buf->written + bytes;
-
-    if (buf->error) return 0;
-    if (dest_size > buf->allocated)
-    {
-        do
-        {
-            buf->allocated <<= 1;
-        } while(dest_size > buf->allocated);
-
-        {
-            void * newptr = realloc(buf->data,buf->allocated);
-            if (newptr==0)
-            {
-                free(buf->data);
-                buf->data = 0;
-                buf->error = 1;
-                return 0;
-            }
-            buf->data = newptr;
-        }
-    }
-
-    if (ptr) memcpy((char*)buf->data + buf->written,ptr,bytes);
-    buf->written += bytes;
-    return bytes;
-}
-
-#define membuffer_write_data membuffer_write
-
-unsigned membuffer_write_int32(membuffer * buf,uint32_t data)
-{
-    uint8_t temp[4] = {(uint8_t)(data>>24),(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data};
-    return membuffer_write_data(buf,temp,4);
-}
-
-unsigned membuffer_write_int24(membuffer * buf,uint32_t data)
-{
-    uint8_t temp[3] = {(uint8_t)(data>>16),(uint8_t)(data>>8),(uint8_t)data};
-    return membuffer_write_data(buf,temp,3);
-}
-
-unsigned membuffer_write_int16(membuffer * buf,uint16_t data)
-{
-    uint8_t temp[2] = {(uint8_t)(data>>8),(uint8_t)data};
-    return membuffer_write_data(buf,temp,2);
-}
-
-unsigned membuffer_write_atom_name(membuffer * buf,const char * data)
-{
-    return membuffer_write_data(buf,data,4)==4 ? 1 : 0;
-}
-
-void membuffer_write_atom(membuffer * buf,const char * name,unsigned size,const void * data)
-{
-    membuffer_write_int32(buf,size + 8);
-    membuffer_write_atom_name(buf,name);
-    membuffer_write_data(buf,data,size);
-}
-
-unsigned membuffer_write_string(membuffer * buf,const char * data)
-{
-    return membuffer_write_data(buf,data,strlen(data));
-}
-
-unsigned membuffer_write_int8(membuffer * buf,uint8_t data)
-{
-    return membuffer_write_data(buf,&data,1);
-}
-
-void * membuffer_get_ptr(const membuffer * buf)
-{
-    return buf->data;
-}
-
-unsigned membuffer_get_size(const membuffer * buf)
-{
-    return buf->written;
-}
-
-unsigned membuffer_error(const membuffer * buf)
-{
-    return buf->error;
-}
-
-void membuffer_set_error(membuffer * buf) {buf->error = 1;}
-
-unsigned membuffer_transfer_from_file(membuffer * buf,mp4ff_t * src,unsigned bytes)
-{
-    unsigned oldsize;
-    void * bufptr;
-
-    oldsize = membuffer_get_size(buf);
-    if (membuffer_write_data(buf,0,bytes) != bytes) return 0;
-
-    bufptr = membuffer_get_ptr(buf);
-    if (bufptr==0) return 0;
-
-    if ((unsigned)mp4ff_read_data(src,(unsigned char*)bufptr + oldsize,bytes)!=bytes)
-    {
-        membuffer_set_error(buf);
-        return 0;
-    }
-
-    return bytes;
-}
-
-
-membuffer * membuffer_create()
-{
-    const unsigned initial_size = 256;
-
-    membuffer * buf = (membuffer *) malloc(sizeof(membuffer));
-    buf->data = malloc(initial_size);
-    buf->written = 0;
-    buf->allocated = initial_size;
-    buf->error = buf->data == 0 ? 1 : 0;
-
-    return buf;
-}
-
-void membuffer_free(membuffer * buf)
-{
-    if (buf->data) free(buf->data);
-    free(buf);
-}
-
-void * membuffer_detach(membuffer * buf)
-{
-    void * ret;
-
-    if (buf->error) return 0;
-
-    ret = realloc(buf->data,buf->written);
-
-    if (ret == 0) free(buf->data);
-
-    buf->data = 0;
-    buf->error = 1;
-
-    return ret;
-}
-
-#if 0
-/* metadata tag structure */
-typedef struct
-{
-    char *item;
-    char *value;
-} mp4ff_tag_t;
-
-/* metadata list structure */
-typedef struct
-{
-    mp4ff_tag_t *tags;
-    uint32_t count;
-} mp4ff_metadata_t;
-#endif
-
-typedef struct
-{
-    const char * atom;
-    const char * name;
-} stdmeta_entry;
-
-static stdmeta_entry stdmetas[] =
-{
-    {"\xA9" "nam","title"},
-    {"\xA9" "ART","artist"},
-    {"\xA9" "wrt","writer"},
-    {"\xA9" "alb","album"},
-    {"\xA9" "day","date"},
-    {"\xA9" "too","tool"},
-    {"\xA9" "cmt","comment"},
-//  {"\xA9" "gen","genre"},
-    {"cpil","compilation"},
-//  {"trkn","track"},
-//  {"disk","disc"},
-//  {"gnre","genre"},
-    {"covr","cover"},
-    /* added by AJS */
-    {"aART","album_artist"},
-};
-
-
-static const char* find_standard_meta(const char * name) //returns atom name if found, 0 if not
-{
-    unsigned n;
-    for(n=0;n<sizeof(stdmetas)/sizeof(stdmetas[0]);n++)
-    {
-        if (!g_ascii_strcasecmp(name,stdmetas[n].name)) return stdmetas[n].atom;
-    }
-    return 0;
-}
-
-static void membuffer_write_track_tag(membuffer * buf,const char * name,uint32_t index,uint32_t total)
-{
-    membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ );
-    membuffer_write_atom_name(buf,name);
-    membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 8 /*actual data*/ );
-    membuffer_write_atom_name(buf,"data");
-    membuffer_write_int32(buf,0);//flags
-    membuffer_write_int32(buf,0);//reserved
-    membuffer_write_int16(buf,0);
-    membuffer_write_int16(buf,(uint16_t)index);//track number
-    membuffer_write_int16(buf,(uint16_t)total);//total tracks
-    membuffer_write_int16(buf,0);
-}
-
-static void membuffer_write_int16_tag(membuffer * buf,const char * name,uint16_t value)
-{
-    membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ );
-    membuffer_write_atom_name(buf,name);
-    membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + 2 /*actual data*/ );
-    membuffer_write_atom_name(buf,"data");
-    membuffer_write_int32(buf,0);//flags
-    membuffer_write_int32(buf,0);//reserved
-    membuffer_write_int16(buf,value);//value
-}
-
-static void membuffer_write_std_tag(membuffer * buf,const char * name,const char * value)
-{
-    /* added by AJS */
-    uint32_t flags = 1;
-
-    /* special check for compilation flag */
-    if ( strcmp(name, "cpil") == 0)
-    {
-        flags = 21;
-    }
-
-    membuffer_write_int32(buf,8 /*atom header*/ + 8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value) );
-    membuffer_write_atom_name(buf,name);
-    membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value));
-    membuffer_write_atom_name(buf,"data");
-    membuffer_write_int32(buf,flags);//flags
-    membuffer_write_int32(buf,0);//reserved
-    membuffer_write_data(buf,value,strlen(value));
-}
-
-static void membuffer_write_custom_tag(membuffer * buf,const char * name,const char * value)
-{
-    membuffer_write_int32(buf,8 /*atom header*/ + 0x1C /*weirdo itunes atom*/ + 12 /*name atom header*/ + strlen(name) + 16 /*data atom header + flags*/ + strlen(value) );
-    membuffer_write_atom_name(buf,"----");
-    membuffer_write_int32(buf,0x1C);//weirdo itunes atom
-    membuffer_write_atom_name(buf,"mean");
-    membuffer_write_int32(buf,0);
-    membuffer_write_data(buf,"com.apple.iTunes",16);
-    membuffer_write_int32(buf,12 + strlen(name));
-    membuffer_write_atom_name(buf,"name");
-    membuffer_write_int32(buf,0);
-    membuffer_write_data(buf,name,strlen(name));
-    membuffer_write_int32(buf,8 /*data atom header*/ + 8 /*flags + reserved*/ + strlen(value));
-    membuffer_write_atom_name(buf,"data");
-    membuffer_write_int32(buf,1);//flags
-    membuffer_write_int32(buf,0);//reserved
-    membuffer_write_data(buf,value,strlen(value));
-
-}
-
-static uint32_t myatoi(const char * param)
-{
-    return param ? atoi(param) : 0;
-}
-
-static uint32_t create_ilst(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
-{
-    membuffer * buf = membuffer_create();
-    unsigned metaptr;
-    char * mask = (char*)malloc(data->count);
-    memset(mask,0,data->count);
-
-    {
-        const char * tracknumber_ptr = 0, * totaltracks_ptr = 0;
-        const char * discnumber_ptr = 0, * totaldiscs_ptr = 0;
-        const char * genre_ptr = 0, * tempo_ptr = 0;
-        for(metaptr = 0; metaptr < data->count; metaptr++)
-        {
-            mp4ff_tag_t * tag = &data->tags[metaptr];
-            if (!g_ascii_strcasecmp(tag->item,"tracknumber") || !g_ascii_strcasecmp(tag->item,"track"))
-            {
-                if (tracknumber_ptr==0) tracknumber_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-            else if (!g_ascii_strcasecmp(tag->item,"totaltracks"))
-            {
-                if (totaltracks_ptr==0) totaltracks_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-            else if (!g_ascii_strcasecmp(tag->item,"discnumber") || !g_ascii_strcasecmp(tag->item,"disc"))
-            {
-                if (discnumber_ptr==0) discnumber_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-            else if (!g_ascii_strcasecmp(tag->item,"totaldiscs"))
-            {
-                if (totaldiscs_ptr==0) totaldiscs_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-            else if (!g_ascii_strcasecmp(tag->item,"genre"))
-            {
-                if (genre_ptr==0) genre_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-            else if (!g_ascii_strcasecmp(tag->item,"tempo"))
-            {
-                if (tempo_ptr==0) tempo_ptr = tag->value;
-                mask[metaptr] = 1;
-            }
-
-        }
-
-        if (tracknumber_ptr) membuffer_write_track_tag(buf,"trkn",myatoi(tracknumber_ptr),myatoi(totaltracks_ptr));
-        if (discnumber_ptr) membuffer_write_track_tag(buf,"disk",myatoi(discnumber_ptr),myatoi(totaldiscs_ptr));
-        if (tempo_ptr) membuffer_write_int16_tag(buf,"tmpo",(uint16_t)myatoi(tempo_ptr));
-
-        if (genre_ptr)
-        {
-            uint32_t index = mp4ff_meta_genre_to_index(genre_ptr);
-            if (index==0)
-                membuffer_write_std_tag(buf,"\xa9""gen",genre_ptr);
-            else
-                membuffer_write_int16_tag(buf,"gnre",(uint16_t)index);
-        }
-    }
-
-    for(metaptr = 0; metaptr < data->count; metaptr++)
-    {
-        if (!mask[metaptr])
-        {
-            mp4ff_tag_t * tag = &data->tags[metaptr];
-            const char * std_meta_atom = find_standard_meta(tag->item);
-            if (std_meta_atom)
-            {
-                membuffer_write_std_tag(buf,std_meta_atom,tag->value);
-            }
-            else
-            {
-                membuffer_write_custom_tag(buf,tag->item,tag->value);
-            }
-        }
-    }
-
-    free(mask);
-
-    if (membuffer_error(buf))
-    {
-        membuffer_free(buf);
-        return 0;
-    }
-
-    *out_size = membuffer_get_size(buf);
-    *out_buffer = membuffer_detach(buf);
-    membuffer_free(buf);
-
-    return 1;
-}
-
-static uint32_t find_atom(mp4ff_t * f,uint64_t base,uint32_t size,const char * name)
-{
-    uint32_t remaining = size;
-    uint64_t atom_offset = base;
-    for(;;)
-    {
-        unsigned char atom_name[4];
-        uint32_t atom_size;
-
-        mp4ff_set_position(f,atom_offset);
-
-        if (remaining < 8) break;
-        atom_size = mp4ff_read_int32(f);
-        if (atom_size > remaining || atom_size < 8) break;
-        mp4ff_read_data(f,atom_name,4);
-
-        if (!memcmp(atom_name,name,4))
-        {
-            mp4ff_set_position(f,atom_offset);
-            return 1;
-        }
-
-        remaining -= atom_size;
-        atom_offset += atom_size;
-    }
-    return 0;
-}
-
-static uint32_t find_atom_v2(mp4ff_t * f,uint64_t base,uint32_t size,const char * name,uint32_t extraheaders,const char * name_inside)
-{
-    uint64_t first_base = (uint64_t)(-1);
-    while(find_atom(f,base,size,name))//try to find atom <name> with atom <name_inside> in it
-    {
-        uint64_t mybase = mp4ff_position(f);
-        uint32_t mysize = mp4ff_read_int32(f);
-
-        if (first_base == (uint64_t)(-1)) first_base = mybase;
-
-        if (mysize < 8 + extraheaders) break;
-
-        if (find_atom(f,mybase+(8+extraheaders),mysize-(8+extraheaders),name_inside))
-        {
-            mp4ff_set_position(f,mybase);
-            return 2;
-        }
-        base += mysize;
-        if (size<=mysize) {size=0;break;}
-        size -= mysize;
-    }
-
-    if (first_base != (uint64_t)(-1))//wanted atom inside not found
-    {
-        mp4ff_set_position(f,first_base);
-        return 1;
-    }
-    else return 0;
-}
-
-static uint32_t create_meta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
-{
-    membuffer * buf;
-    uint32_t ilst_size;
-    void * ilst_buffer;
-
-    if (!create_ilst(data,&ilst_buffer,&ilst_size)) return 0;
-
-    buf = membuffer_create();
-
-    membuffer_write_int32(buf,0);
-    membuffer_write_atom(buf,"ilst",ilst_size,ilst_buffer);
-    free(ilst_buffer);
-
-    *out_size = membuffer_get_size(buf);
-    *out_buffer = membuffer_detach(buf);
-    membuffer_free(buf);
-    return 1;
-}
-
-static uint32_t create_udta(const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
-{
-    membuffer * buf;
-    uint32_t meta_size;
-    void * meta_buffer;
-
-    if (!create_meta(data,&meta_buffer,&meta_size)) return 0;
-
-    buf = membuffer_create();
-
-    membuffer_write_atom(buf,"meta",meta_size,meta_buffer);
-
-    free(meta_buffer);
-
-    *out_size = membuffer_get_size(buf);
-    *out_buffer = membuffer_detach(buf);
-    membuffer_free(buf);
-    return 1;
-}
-
-static uint32_t modify_moov(mp4ff_t * f,const mp4ff_metadata_t * data,void ** out_buffer,uint32_t * out_size)
-{
-    uint64_t total_base = f->moov_offset + 8;
-    uint32_t total_size = (uint32_t)(f->moov_size - 8);
-
-    uint64_t udta_offset,meta_offset,ilst_offset;
-    uint32_t udta_size,  meta_size,  ilst_size;
-
-    uint32_t new_ilst_size;
-    void * new_ilst_buffer;
-
-    uint8_t * p_out;
-    int32_t size_delta;
-
-
-    if (!find_atom_v2(f,total_base,total_size,"udta",0,"meta"))
-    {
-        membuffer * buf;
-        void * new_udta_buffer;
-        uint32_t new_udta_size;
-        if (!create_udta(data,&new_udta_buffer,&new_udta_size)) return 0;
-
-        buf = membuffer_create();
-        mp4ff_set_position(f,total_base);
-        membuffer_transfer_from_file(buf,f,total_size);
-
-        membuffer_write_atom(buf,"udta",new_udta_size,new_udta_buffer);
-
-        free(new_udta_buffer);
-
-        *out_size = membuffer_get_size(buf);
-        *out_buffer = membuffer_detach(buf);
-        membuffer_free(buf);
-        return 1;
-    }
-    else
-    {
-        udta_offset = mp4ff_position(f);
-        udta_size = mp4ff_read_int32(f);
-        if (!find_atom_v2(f,udta_offset+8,udta_size-8,"meta",4,"ilst"))
-        {
-            membuffer * buf;
-            void * new_meta_buffer;
-            uint32_t new_meta_size;
-            if (!create_meta(data,&new_meta_buffer,&new_meta_size)) return 0;
-
-            buf = membuffer_create();
-            mp4ff_set_position(f,total_base);
-            membuffer_transfer_from_file(buf,f,(uint32_t)(udta_offset - total_base));
-
-            membuffer_write_int32(buf,udta_size + 8 + new_meta_size);
-            membuffer_write_atom_name(buf,"udta");
-            membuffer_transfer_from_file(buf,f,udta_size);
-
-            membuffer_write_atom(buf,"meta",new_meta_size,new_meta_buffer);
-            free(new_meta_buffer);
-
-            *out_size = membuffer_get_size(buf);
-            *out_buffer = membuffer_detach(buf);
-            membuffer_free(buf);
-            return 1;
-        }
-        meta_offset = mp4ff_position(f);
-        meta_size = mp4ff_read_int32(f);
-        if (!find_atom(f,meta_offset+12,meta_size-12,"ilst")) return 0;//shouldn't happen, find_atom_v2 above takes care of it
-        ilst_offset = mp4ff_position(f);
-        ilst_size = mp4ff_read_int32(f);
-
-        if (!create_ilst(data,&new_ilst_buffer,&new_ilst_size)) return 0;
-
-        size_delta = new_ilst_size - (ilst_size - 8);
-
-        *out_size = total_size + size_delta;
-        *out_buffer = malloc(*out_size);
-        if (*out_buffer == 0)
-        {
-            free(new_ilst_buffer);
-            return 0;
-        }
-
-        p_out = (uint8_t*)*out_buffer;
-
-        mp4ff_set_position(f,total_base);
-        mp4ff_read_data(f,p_out,(uint32_t)(udta_offset - total_base )); p_out += (uint32_t)(udta_offset - total_base );
-        *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
-        mp4ff_read_data(f,p_out,4); p_out += 4;
-        mp4ff_read_data(f,p_out,(uint32_t)(meta_offset - udta_offset - 8)); p_out += (uint32_t)(meta_offset - udta_offset - 8);
-        *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
-        mp4ff_read_data(f,p_out,4); p_out += 4;
-        mp4ff_read_data(f,p_out,(uint32_t)(ilst_offset - meta_offset - 8)); p_out += (uint32_t)(ilst_offset - meta_offset - 8);
-        *(uint32_t*)p_out = fix_byte_order_32(mp4ff_read_int32(f) + size_delta); p_out += 4;
-        mp4ff_read_data(f,p_out,4); p_out += 4;
-
-        memcpy(p_out,new_ilst_buffer,new_ilst_size);
-        p_out += new_ilst_size;
-
-        mp4ff_set_position(f,ilst_offset + ilst_size);
-        mp4ff_read_data(f,p_out,(uint32_t)(total_size - (ilst_offset - total_base) - ilst_size));
-
-        free(new_ilst_buffer);
-    }
-    return 1;
-
-}
-
-int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data)
-{
-    void * new_moov_data;
-    uint32_t new_moov_size;
-
-    mp4ff_t *ff = malloc(sizeof(mp4ff_t));
-
-    memset(ff, 0, sizeof(mp4ff_t));
-    ff->stream = f;
-    mp4ff_set_position(ff,0);
-
-    parse_atoms(ff,1);
-
-
-    if (!modify_moov(ff,data,&new_moov_data,&new_moov_size))
-    {
-        mp4ff_close(ff);
-        return 0;
-    }
-
-    /* copy moov atom to end of the file */
-    if (ff->last_atom != ATOM_MOOV)
-    {
-        char *free_data = "free";
-
-        /* rename old moov to free */
-        mp4ff_set_position(ff, ff->moov_offset + 4);
-        mp4ff_write_data(ff, free_data, 4);
-
-        mp4ff_set_position(ff, ff->file_size);
-        mp4ff_write_int32(ff,new_moov_size + 8);
-        mp4ff_write_data(ff,"moov",4);
-        mp4ff_write_data(ff, new_moov_data, new_moov_size);
-    }
-    else
-    {
-        mp4ff_set_position(ff, ff->moov_offset);
-        mp4ff_write_int32(ff,new_moov_size + 8);
-        mp4ff_write_data(ff,"moov",4);
-        mp4ff_write_data(ff, new_moov_data, new_moov_size);
-    }
-
-    mp4ff_truncate(ff);
-
-    mp4ff_close(ff);
-    return 1;
-}
-#endif
diff --git a/src/aac/mp4ff/mp4util.c b/src/aac/mp4ff/mp4util.c
deleted file mode 100644
index 6e784ad2cc57..000000000000
--- a/src/aac/mp4ff/mp4util.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation; either version 2 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
-** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-**
-** Any non-GPL usage of this software or parts of this software is strictly
-** forbidden.
-**
-** The "appropriate copyright message" mentioned in section 2c of the GPLv2
-** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
-**
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Nero AG through Mpeg4AAClicense at nero.com.
-**
-** $Id: mp4util.c,v 1.20 2007/11/01 12:33:29 menno Exp $
-**/
-
-#include "mp4ffint.h"
-#include <stdlib.h>
-
-int32_t mp4ff_read_data(mp4ff_t *f, void *data, uint32_t size)
-{
-    int32_t result = 1;
-
-    result = f->stream->read(f->stream->user_data, data, size);
-
-    f->current_position += size;
-
-    return result;
-}
-
-int32_t mp4ff_truncate(mp4ff_t * f)
-{
-    return f->stream->truncate(f->stream->user_data);
-}
-
-int32_t mp4ff_write_data(mp4ff_t *f, void *data, uint32_t size)
-{
-    int32_t result = 1;
-
-    result = f->stream->write(f->stream->user_data, data, size);
-
-    f->current_position += size;
-
-    return result;
-}
-
-int32_t mp4ff_write_int32(mp4ff_t *f,const uint32_t data)
-{
-    union {uint32_t dword; uint8_t bytes[4];} temp;
-    uint32_t a, b, c, d, result;
-
-    temp.dword = data;
-    a = temp.bytes[0];
-    b = temp.bytes[1];
-    c = temp.bytes[2];
-    d = temp.bytes[3];
-
-    result = (a<<24) | (b<<16) | (c<<8) | d;
-
-    return mp4ff_write_data(f,(uint8_t*)&result,sizeof(result));
-}
-
-int32_t mp4ff_set_position(mp4ff_t *f, const int64_t position)
-{
-    if (f->stream->seek(f->stream->user_data, position) != 0)
-        return -1;
-
-    f->current_position = position;
-    return 0;
-}
-
-int64_t mp4ff_position(const mp4ff_t *f)
-{
-    return f->current_position;
-}
-
-uint64_t mp4ff_read_int64(mp4ff_t *f)
-{
-    uint8_t data[8];
-    uint64_t result = 0;
-    int8_t i;
-
-    mp4ff_read_data(f, data, 8);
-
-    for (i = 0; i < 8; i++)
-    {
-        result |= ((uint64_t)data[i]) << ((7 - i) * 8);
-    }
-
-    return result;
-}
-
-uint32_t mp4ff_read_int32(mp4ff_t *f)
-{
-    uint32_t result;
-    uint32_t a, b, c, d;
-    uint8_t data[4];
-
-    mp4ff_read_data(f, data, 4);
-    a = data[0];
-    b = data[1];
-    c = data[2];
-    d = data[3];
-
-    result = (a<<24) | (b<<16) | (c<<8) | d;
-    return (uint32_t)result;
-}
-
-uint32_t mp4ff_read_int24(mp4ff_t *f)
-{
-    uint32_t result;
-    uint32_t a, b, c;
-    uint8_t data[4];
-
-    mp4ff_read_data(f, data, 3);
-    a = data[0];
-    b = data[1];
-    c = data[2];
-
-    result = (a<<16) | (b<<8) | c;
-    return (uint32_t)result;
-}
-
-uint16_t mp4ff_read_int16(mp4ff_t *f)
-{
-    uint32_t result;
-    uint32_t a, b;
-    uint8_t data[2];
-
-    mp4ff_read_data(f, data, 2);
-    a = data[0];
-    b = data[1];
-
-    result = (a<<8) | b;
-    return (uint16_t)result;
-}
-
-char * mp4ff_read_string(mp4ff_t * f,uint32_t length)
-{
-    char * str = (char*)malloc(length + 1);
-    if (str!=0)
-    {
-        if ((uint32_t)mp4ff_read_data(f,str,length)!=length)
-        {
-            free(str);
-            str = 0;
-        }
-        else
-        {
-            str[length] = 0;
-        }
-    }
-    return str;
-}
-
-uint8_t mp4ff_read_char(mp4ff_t *f)
-{
-    uint8_t output;
-    mp4ff_read_data(f, &output, 1);
-    return output;
-}
-
-uint32_t mp4ff_read_mp4_descr_length(mp4ff_t *f)
-{
-    uint8_t b;
-    uint8_t numBytes = 0;
-    uint32_t length = 0;
-
-    do
-    {
-        b = mp4ff_read_char(f);
-        numBytes++;
-        length = (length << 7) | (b & 0x7F);
-    } while ((b & 0x80) && numBytes < 4);
-
-    return length;
-}
diff --git a/src/adplug/Makefile b/src/adplug/Makefile
index 5c66ae0f1138..7ee162d39297 100644
--- a/src/adplug/Makefile
+++ b/src/adplug/Makefile
@@ -1,59 +1,58 @@
 PLUGIN = adplug${PLUGIN_SUFFIX}
 
 SRCS = adplug-xmms.cc		\
-       core/fmopl.c		\
-       core/debug.c		\
-       core/adlibemu.c		\
-       core/adplug.cxx		\
-       core/emuopl.cxx		\
-       core/fprovide.cxx	\
-       core/player.cxx		\
-       core/database.cxx	\
-       core/hsc.cxx		\
-       core/sng.cxx		\
-       core/imf.cxx		\
-       core/players.cxx		\
-       core/protrack.cxx	\
-       core/a2m.cxx		\
-       core/adtrack.cxx		\
-       core/amd.cxx		\
-       core/bam.cxx		\
-       core/cmf.cxx		\
-       core/d00.cxx		\
-       core/dfm.cxx		\
-       core/dmo.cxx		\
-       core/hsp.cxx		\
-       core/ksm.cxx		\
-       core/mad.cxx		\
-       core/mid.cxx		\
-       core/mkj.cxx		\
-       core/cff.cxx		\
-       core/dtm.cxx		\
-       core/fmc.cxx		\
-       core/mtk.cxx		\
-       core/rad.cxx		\
-       core/raw.cxx		\
-       core/sa2.cxx		\
-       core/s3m.cxx		\
-       core/xad.cxx		\
-       core/flash.cxx		\
-       core/bmf.cxx		\
-       core/hybrid.cxx		\
-       core/hyp.cxx		\
-       core/psi.cxx		\
-       core/rat.cxx		\
-       core/u6m.cxx		\
-       core/rol.cxx		\
-       core/xsm.cxx		\
-       core/dro.cxx		\
-       core/dro2.cxx		\
-       core/lds.cxx		\
-       core/temuopl.cxx		\
-       core/msc.cxx		\
-       core/rix.cxx		\
-       core/adl.cxx		\
-       core/jbm.cxx		\
-       plugin.c
+       core/fmopl.cc		\
+       core/debug.cc		\
+       core/adlibemu.cc		\
+       core/adplug.cc		\
+       core/emuopl.cc		\
+       core/fprovide.cc	\
+       core/player.cc		\
+       core/database.cc	\
+       core/hsc.cc		\
+       core/sng.cc		\
+       core/imf.cc		\
+       core/players.cc		\
+       core/protrack.cc	\
+       core/a2m.cc		\
+       core/adtrack.cc		\
+       core/amd.cc		\
+       core/bam.cc		\
+       core/cmf.cc		\
+       core/d00.cc		\
+       core/dfm.cc		\
+       core/dmo.cc		\
+       core/hsp.cc		\
+       core/ksm.cc		\
+       core/mad.cc		\
+       core/mid.cc		\
+       core/mkj.cc		\
+       core/cff.cc		\
+       core/dtm.cc		\
+       core/fmc.cc		\
+       core/mtk.cc		\
+       core/rad.cc		\
+       core/raw.cc		\
+       core/sa2.cc		\
+       core/s3m.cc		\
+       core/xad.cc		\
+       core/flash.cc		\
+       core/bmf.cc		\
+       core/hybrid.cc		\
+       core/hyp.cc		\
+       core/psi.cc		\
+       core/rat.cc		\
+       core/u6m.cc		\
+       core/rol.cc		\
+       core/xsm.cc		\
+       core/dro.cc		\
+       core/dro2.cc		\
+       core/lds.cc		\
+       core/temuopl.cc		\
+       core/msc.cc		\
+       core/rix.cc		\
+       core/adl.cc		\
+       core/jbm.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -62,6 +61,6 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
 LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CXXFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${BINIO_CFLAGS} -I../.. -I./core
-LIBS += ${GLIB_LIBS} ${BINIO_LIBS}
+CXXFLAGS += ${PLUGIN_CFLAGS} -Wno-sign-compare
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BINIO_CFLAGS} -I../.. -I./core
+LIBS += ${BINIO_LIBS}
diff --git a/src/adplug/adplug-xmms.cc b/src/adplug/adplug-xmms.cc
index b65bad034da5..89696cd11873 100644
--- a/src/adplug/adplug-xmms.cc
+++ b/src/adplug/adplug-xmms.cc
@@ -28,19 +28,44 @@
 #include "silentopl.h"
 #include "players.h"
 
-extern "C" {
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/i18n.h>
 #include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
 
-#include "adplug-xmms.h"
-}
+class AdPlugXMMS : public InputPlugin
+{
+public:
+    static const char * const exts[];
 
-/***** Defines *****/
+    static constexpr PluginInfo info = {
+        N_("AdPlug (AdLib Player)"),
+        PACKAGE
+    };
+
+    static constexpr auto iinfo = InputInfo ()
+        .with_exts (exts);
+
+    constexpr AdPlugXMMS () : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    void cleanup ();
 
-// Version string
-#define ADPLUG_NAME	"AdPlug (AdLib Sound Player)"
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT AdPlugXMMS aud_plugin_instance;
+
+const char * const AdPlugXMMS::exts[] = {
+    "a2m", "adl", "amd", "bam", "cff", "cmf", "d00", "dfm", "dmo", "dro",
+    "dtm", "hsc", "hsp", "ins", "jbm", "ksm", "laa", "lds", "m", "mad",
+    "mkj", "msc", "rad", "raw", "rix", "rol", "s3m", "sa2", "sat", "sci",
+    "sng", "wlf", "xad", "xsm", nullptr
+};
+
+/***** Defines *****/
 
 // Sound buffer size in samples
 #define SNDBUFSIZE	512
@@ -57,26 +82,20 @@ extern "C" {
 
 /***** Global variables *****/
 
-static bool_t audio_error = FALSE;
-
 // Configuration (and defaults)
-static struct
-{
-  int freq;
-  bool_t bit16, stereo, endless;
-  CPlayers players;
-} conf =
-{
-44100l, true, false, false, CAdPlug::getPlayers()};
+static struct {
+  int freq = 44100l;
+  bool bit16 = true, stereo = false, endless = false;
+  CPlayers players = CAdPlug::getPlayers();
+} conf;
 
 // Player variables
-static struct
-{
-  CPlayer *p;
-  CAdPlugDatabase *db;
-  unsigned int subsong, songlength;
-  char * filename;
-} plr = {0, 0, 0, 0, NULL};
+static struct {
+  CPlayer *p = nullptr;
+  CAdPlugDatabase *db = nullptr;
+  unsigned int subsong = 0, songlength = 0;
+  String filename;
+} plr;
 
 /***** Debugging *****/
 
@@ -104,61 +123,62 @@ dbg_printf (const char *fmt, ...)
 #endif
 
 static CPlayer *
-factory (VFSFile * fd, Copl * newopl)
+factory (VFSFile & fd, Copl * newopl)
 {
   return CAdPlug::factory (fd, newopl, conf.players);
 }
 
 /***** Main player (!! threaded !!) *****/
 
-extern "C" Tuple * adplug_get_tuple (const char * filename, VFSFile * fd)
+Tuple AdPlugXMMS::read_tuple (const char * filename, VFSFile & fd)
 {
-  Tuple * ti = NULL;
+  Tuple tuple;
   CSilentopl tmpopl;
 
   if (!fd)
-    return NULL;
+    return tuple;
 
   CPlayer *p = factory (fd, &tmpopl);
 
   if (p)
   {
-    ti = tuple_new_from_filename (filename);
+    tuple.set_filename (filename);
 
     if (! p->getauthor().empty())
-      tuple_set_str(ti, FIELD_ARTIST, p->getauthor().c_str());
+      tuple.set_str (Tuple::Artist, p->getauthor().c_str());
 
     if (! p->gettitle().empty())
-      tuple_set_str(ti, FIELD_TITLE, p->gettitle().c_str());
+      tuple.set_str (Tuple::Title, p->gettitle().c_str());
     else if (! p->getdesc().empty())
-      tuple_set_str(ti, FIELD_TITLE, p->getdesc().c_str());
+      tuple.set_str (Tuple::Title, p->getdesc().c_str());
 
-    tuple_set_str(ti, FIELD_CODEC, p->gettype().c_str());
-    tuple_set_str(ti, FIELD_QUALITY, _("sequenced"));
-    tuple_set_int(ti, FIELD_LENGTH, p->songlength (plr.subsong));
+    tuple.set_str (Tuple::Codec, p->gettype().c_str());
+    tuple.set_str (Tuple::Quality, _("sequenced"));
+    tuple.set_int (Tuple::Length, p->songlength (plr.subsong));
     delete p;
   }
 
-  return ti;
+  return tuple;
 }
 
-// Define sampsize macro (only usable inside play_loop()!)
-#define sampsize ((bit16 ? 2 : 1) * (stereo ? 2 : 1))
-
-static bool_t play_loop (const char * filename, VFSFile * fd)
 /* Main playback thread. Takes the filename to play as argument. */
+bool AdPlugXMMS::play (const char * filename, VFSFile & fd)
 {
-  dbg_printf ("play_loop(\"%s\"): ", filename);
+  dbg_printf ("adplug_play(\"%s\"): ", filename);
+
+  // Set XMMS main window information
+  dbg_printf ("xmms, ");
+  int sampsize = (conf.bit16 ? 2 : 1) * (conf.stereo ? 2 : 1);
+  set_stream_bitrate (conf.freq * sampsize * 8);
+
+  // open output plugin
+  dbg_printf ("open, ");
+  open_audio (conf.bit16 ? FORMAT_16 : FORMAT_8, conf.freq, conf.stereo ? 2 : 1);
+
   CEmuopl opl (conf.freq, conf.bit16, conf.stereo);
   long toadd = 0, i, towrite;
   char *sndbuf, *sndbufpos;
-  bool playing = true,          // Song self-end indicator.
-    bit16 = conf.bit16,          // Duplicate config, so it doesn't affect us if
-    stereo = conf.stereo;        // the user changes it while we're playing.
-  unsigned long freq = conf.freq;
-
-  if (!fd)
-    return FALSE;
+  bool playing = true;  // Song self-end indicator.
 
   // Try to load module
   dbg_printf ("factory, ");
@@ -166,15 +186,14 @@ static bool_t play_loop (const char * filename, VFSFile * fd)
   {
     dbg_printf ("error!\n");
     // MessageBox("AdPlug :: Error", "File could not be opened!", "Ok");
-    return FALSE;
+    return false;
   }
 
   // reset to first subsong on new file
   dbg_printf ("subsong, ");
   if (! plr.filename || strcmp (filename, plr.filename))
   {
-    free (plr.filename);
-    plr.filename = strdup (filename);
+    plr.filename = String (filename);
     plr.subsong = 0;
   }
 
@@ -182,28 +201,24 @@ static bool_t play_loop (const char * filename, VFSFile * fd)
   dbg_printf ("buffer, ");
   sndbuf = (char *) malloc (SNDBUFSIZE * sampsize);
 
-  // Set XMMS main window information
-  dbg_printf ("xmms, ");
-  aud_input_set_bitrate (freq * sampsize * 8);
-
   // Rewind player to right subsong
   dbg_printf ("rewind, ");
   plr.p->rewind (plr.subsong);
 
+  int time = 0;
+
   // main playback loop
   dbg_printf ("loop.\n");
   while ((playing || conf.endless))
   {
-    if (aud_input_check_stop ())
+    if (check_stop ())
       break;
 
-    int seek = aud_input_check_seek ();
+    int seek = check_seek ();
 
     // seek requested ?
     if (seek != -1)
     {
-      int time = aud_input_written_time ();
-
       // backward seek ?
       if (seek < time)
       {
@@ -223,17 +238,19 @@ static bool_t play_loop (const char * filename, VFSFile * fd)
     {
       while (toadd < 0)
       {
-        toadd += freq;
+        toadd += conf.freq;
         playing = plr.p->update ();
+        if (playing)
+          time += (int) (1000 / plr.p->getrefresh ());
       }
-      i = MIN (towrite, (long) (toadd / plr.p->getrefresh () + 4) & ~3);
+      i = std::min (towrite, (long) (toadd / plr.p->getrefresh () + 4) & ~3);
       opl.update ((short *) sndbufpos, i);
       sndbufpos += i * sampsize;
       towrite -= i;
       toadd -= (long) (plr.p->getrefresh () * i);
     }
 
-    aud_input_write_audio (sndbuf, SNDBUFSIZE * sampsize);
+    write_audio (sndbuf, SNDBUFSIZE * sampsize);
   }
 
   // free everything and exit
@@ -242,7 +259,7 @@ static bool_t play_loop (const char * filename, VFSFile * fd)
   plr.p = 0;
   free (sndbuf);
   dbg_printf (".\n");
-  return TRUE;
+  return true;
 }
 
 // sampsize macro not useful anymore.
@@ -250,8 +267,7 @@ static bool_t play_loop (const char * filename, VFSFile * fd)
 
 /***** Informational *****/
 
-extern "C" int
-adplug_is_our_fd (const char * filename, VFSFile * fd)
+bool AdPlugXMMS::is_our_file (const char * filename, VFSFile & fd)
 {
   CSilentopl tmpopl;
 
@@ -262,32 +278,12 @@ adplug_is_our_fd (const char * filename, VFSFile * fd)
   if (p)
   {
     delete p;
-    dbg_printf ("TRUE\n");
-    return TRUE;
+    dbg_printf ("true\n");
+    return true;
   }
 
-  dbg_printf ("FALSE\n");
-  return FALSE;
-}
-
-/***** Player control *****/
-
-extern "C" bool_t
-adplug_play (const char * filename, VFSFile * file)
-{
-  dbg_printf ("adplug_play(\"%s\"): ", filename);
-  audio_error = FALSE;
-
-  // open output plugin
-  dbg_printf ("open, ");
-  if (!aud_input_open_audio (conf.bit16 ? FORMAT_16 : FORMAT_8, conf.freq, conf.stereo ? 2 : 1))
-  {
-    audio_error = TRUE;
-    return TRUE;
-  }
-
-  play_loop (filename, file);
-  return FALSE;
+  dbg_printf ("false\n");
+  return false;
 }
 
 /***** Configuration file handling *****/
@@ -299,9 +295,9 @@ static const char * const adplug_defaults[] = {
  "Stereo", "FALSE",
  "Frequency", "44100",
  "Endless", "FALSE",
- NULL};
+ nullptr};
 
-extern "C" bool_t adplug_init (void)
+bool AdPlugXMMS::init ()
 {
   aud_config_set_defaults (CFG_VERSION, adplug_defaults);
 
@@ -313,26 +309,20 @@ extern "C" bool_t adplug_init (void)
   // Read file type exclusion list
   dbg_printf ("exclusion, ");
   {
-    char * cfgstr = aud_get_str (CFG_VERSION, "Exclude");
+    String cfgstr = aud_get_str (CFG_VERSION, "Exclude");
 
     if (cfgstr[0])
     {
-        char exclude[strlen (cfgstr) + 2];
-        memcpy (exclude, cfgstr, sizeof exclude - 1);
-        exclude[sizeof exclude - 1] = 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));
     }
-
-    str_unref (cfgstr);
   }
 
   // Load database from disk and hand it to AdPlug
   dbg_printf ("database");
-  plr.db = new CAdPlugDatabase;
-
   {
     const char *homedir = getenv ("HOME");
 
@@ -341,29 +331,28 @@ extern "C" bool_t adplug_init (void)
       std::string userdb;
       userdb = std::string ("file://") + homedir + "/" ADPLUG_CONFDIR "/" + ADPLUGDB_FILE;
 
-      if (vfs_file_test (userdb.c_str (), VFS_EXISTS))
+      if (VFSFile::test_file (userdb.c_str (), VFS_EXISTS))
       {
+        plr.db = new CAdPlugDatabase;
         plr.db->load (userdb);    // load user's database
         dbg_printf (" (userdb=\"%s\")", userdb.c_str());
+        CAdPlug::set_database (plr.db);
       }
     }
   }
-  CAdPlug::set_database (plr.db);
   dbg_printf (".\n");
 
-  return TRUE;
+  return true;
 }
 
-extern "C" void
-adplug_quit (void)
+void AdPlugXMMS::cleanup ()
 {
   // Close database
   dbg_printf ("db, ");
   if (plr.db)
     delete plr.db;
 
-  free (plr.filename);
-  plr.filename = NULL;
+  plr.filename = String ();
 
   aud_set_bool (CFG_VERSION, "16bit", conf.bit16);
   aud_set_bool (CFG_VERSION, "Stereo", conf.stereo);
diff --git a/src/adplug/adplug-xmms.h b/src/adplug/adplug-xmms.h
deleted file mode 100644
index 7941d7ccb53a..000000000000
--- a/src/adplug/adplug-xmms.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * AdPlug/XMMS - AdPlug XMMS Plugin
- * Copyright (C) 2002, 2003 Simon Peter <dn.tlp at gmx.net>
- *
- * AdPlug/XMMS 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 plugin is distributed in the hope that 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 plugin; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef ADPLUG_XMMS_H
-#define ADPLUG_XMMS_H
-
-#include <audacious/plugin.h>
-
-bool_t adplug_init (void);
-void adplug_quit (void);
-void adplug_about (void);
-void adplug_config (void);
-bool_t adplug_play (const char * filename, VFSFile * file);
-void adplug_info_box (const char * filename);
-Tuple * adplug_get_tuple (const char * filename, VFSFile * file);
-bool_t adplug_is_our_fd (const char * filename, VFSFile * file);
-
-#endif
diff --git a/src/adplug/core/a2m.cc b/src/adplug/core/a2m.cc
new file mode 100644
index 000000000000..4c446c257c20
--- /dev/null
+++ b/src/adplug/core/a2m.cc
@@ -0,0 +1,597 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * a2m.cpp - A2M Loader by Simon Peter <dn.tlp at gmx.net>
+ *
+ * NOTES:
+ * This loader detects and loads version 1, 4, 5 & 8 files.
+ *
+ * version 1-4 files:
+ * Following commands are ignored: FF1 - FF9, FAx - FEx
+ *
+ * version 5-8 files:
+ * Instrument panning is ignored. Flags byte is ignored.
+ * Following commands are ignored: Gxy, Hxy, Kxy - &xy
+ */
+
+#include <string.h>
+
+#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)
+{
+  return new Ca2mLoader (newopl);
+}
+
+bool
+Ca2mLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  char id[10];
+  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
+  };
+
+  // read header
+  f->readString (id, 10);
+  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);
+    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);
+    t = 9;
+  }
+  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);
+  }
+  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].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;
+
+  // 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]);
+    }
+    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);
+  }
+
+  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];
+
+          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)
+            track->param1 = o[3] >> 4;
+          else
+          {
+            track->param1 = convinf1[o[3] >> 4];
+            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
+              track->command = 25;
+              track->param1 = track->param2;
+              track->param2 = 0xf;
+              break;
+            case 8:            // convert volume slide up
+              track->command = 26;
+              track->param1 = track->param2;
+              track->param2 = 0;
+              break;
+            case 9:            // convert volume slide down
+              track->command = 26;
+              track->param1 = 0;
+              break;
+            }
+          }
+        }
+  }
+  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++)
+        {
+          struct Tracks *track = &tracks[i * 18 + j][k];
+          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];
+          track->command = newconvfx[o[2]];
+          track->param1 = o[3] >> 4;
+          track->param2 = o[3] & 0x0f;
+
+          // Convert '&' command
+          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)
+              track->command = 14;
+              track->param1 = 8;
+              // param2 already set correctly
+              break;
+            }
+        }
+  }
+
+  init_trackord ();
+
+  if (version == 1 || version == 5)
+  {
+    delete[]org;
+  }
+  else
+  {
+    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
+  }
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+float
+Ca2mLoader::getrefresh ()
+{
+  if (tempo != 18)
+    return (float) (tempo);
+  else
+    return 18.2f;
+}
+
+/*** private methods *************************************/
+
+void
+Ca2mLoader::inittree ()
+{
+  unsigned short i;
+
+  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;
+  }
+}
+
+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;
+}
+
+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];
+        }
+        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 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;
+}
+
+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;
+}
+
+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;
+        }
+
+        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;
+}
+
+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;
+}
diff --git a/src/adplug/core/a2m.cxx b/src/adplug/core/a2m.cxx
deleted file mode 100644
index b1ce8cb3657b..000000000000
--- a/src/adplug/core/a2m.cxx
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * a2m.cpp - A2M Loader by Simon Peter <dn.tlp at gmx.net>
- *
- * NOTES:
- * This loader detects and loads version 1, 4, 5 & 8 files.
- *
- * version 1-4 files:
- * Following commands are ignored: FF1 - FF9, FAx - FEx
- *
- * version 5-8 files:
- * Instrument panning is ignored. Flags byte is ignored.
- * Following commands are ignored: Gxy, Hxy, Kxy - &xy
- */
-
-#include <string.h>
-
-#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)
-{
-  return new Ca2mLoader (newopl);
-}
-
-bool
-Ca2mLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  char id[10];
-  int i, j, k, t;
-  unsigned int l;
-  unsigned char *org = NULL, *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
-  };
-
-  // read header
-  f->readString (id, 10);
-  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);
-    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);
-    t = 9;
-  }
-  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);
-  }
-  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].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;
-
-  // 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]);
-    }
-    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);
-  }
-
-  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];
-
-          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)
-            track->param1 = o[3] >> 4;
-          else
-          {
-            track->param1 = convinf1[o[3] >> 4];
-            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
-              track->command = 25;
-              track->param1 = track->param2;
-              track->param2 = 0xf;
-              break;
-            case 8:            // convert volume slide up
-              track->command = 26;
-              track->param1 = track->param2;
-              track->param2 = 0;
-              break;
-            case 9:            // convert volume slide down
-              track->command = 26;
-              track->param1 = 0;
-              break;
-            }
-          }
-        }
-  }
-  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++)
-        {
-          struct Tracks *track = &tracks[i * 18 + j][k];
-          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];
-          track->command = newconvfx[o[2]];
-          track->param1 = o[3] >> 4;
-          track->param2 = o[3] & 0x0f;
-
-          // Convert '&' command
-          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)
-              track->command = 14;
-              track->param1 = 8;
-              // param2 already set correctly
-              break;
-            }
-        }
-  }
-
-  init_trackord ();
-
-  if (version == 1 || version == 5)
-  {
-    delete[]org;
-  }
-  else
-  {
-    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
-  }
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-float
-Ca2mLoader::getrefresh ()
-{
-  if (tempo != 18)
-    return (float) (tempo);
-  else
-    return 18.2f;
-}
-
-/*** private methods *************************************/
-
-void
-Ca2mLoader::inittree ()
-{
-  unsigned short i;
-
-  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;
-  }
-}
-
-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;
-}
-
-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];
-        }
-        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 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;
-}
-
-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;
-}
-
-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;
-        }
-
-        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;
-}
-
-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;
-}
diff --git a/src/adplug/core/a2m.h b/src/adplug/core/a2m.h
index f1a20c736c3f..d55ae13074dc 100644
--- a/src/adplug/core/a2m.h
+++ b/src/adplug/core/a2m.h
@@ -33,7 +33,7 @@ public:
 		: CmodPlayer(newopl)
 	{ };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	float getrefresh();
 
 	std::string gettype()
@@ -82,4 +82,3 @@ private:
 	unsigned char *obuf, *buf;
 };
 #endif
-
diff --git a/src/adplug/core/adl.cc b/src/adplug/core/adl.cc
new file mode 100644
index 000000000000..281c3b18e0b6
--- /dev/null
+++ b/src/adplug/core/adl.cc
@@ -0,0 +1,2874 @@
+/*
+ * adl.cpp - ADL player adaption by Simon Peter <dn.tlp at gmx.net>
+ *
+ * Original ADL player by Torbjorn Andersson and Johannes Schickel
+ * 'lordhoto' <lordhoto at scummvm dot org> of the ScummVM project.
+ */
+
+/* ScummVM - Scumm Interpreter
+ *
+ * This file is licensed under both GPL and LGPL
+ * Copyright (C) 2006 The ScummVM project
+ * Copyright (C) 2006 Torbjorn Andersson and Johannes Schickel
+ *
+ * GPL License
+ *
+ * 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.
+ *
+ * LPGL License
+ *
+ * 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
+ *
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "adl.h"
+#include "debug.h"
+
+#ifdef ADL_DEBUG
+#	define warning(...)		AdPlug_LogWrite(__VA_ARGS__); \
+AdPlug_LogWrite("\n")
+
+#	define debugC(i1, i2, ...)	AdPlug_LogWrite(__VA_ARGS__); \
+AdPlug_LogWrite("\n")
+#else
+#	define kDebugLevelSound	1
+
+static inline void
+warning (const char *str, ...)
+{
+}
+
+static inline void
+debugC (int i1, int i2, const char *str, ...)
+{
+}
+#endif
+
+// #define warning(...)
+// #define debugC(i1, i2, ...)
+
+#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
+
+// Basic Adlib Programming:
+// http://www.gamedev.net/reference/articles/article446.asp
+
+#define CALLBACKS_PER_SECOND 72
+
+typedef uint8_t uint8;
+typedef int8_t int8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+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;
+  return (b[1] << 8) + b[0];
+}
+
+static inline uint16
+READ_BE_UINT16 (const void *ptr)
+{
+  const byte *b = (const byte *) ptr;
+  return (b[0] << 8) + b[1];
+}
+
+class AdlibDriver
+{
+public:
+  AdlibDriver (Copl * opl);
+  ~AdlibDriver ();
+
+  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 render = MIN(samplesLeft, _samplesTillCallback);
+  //            samplesLeft -= render;
+  //            _samplesTillCallback -= render;
+  //            YM3812UpdateOne(_adlib, buffer, render);
+  //            buffer += render;
+  //        }
+  //        return numSamples;
+  //    }
+
+  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);
+    DriverOpcode function;
+    const char *name;
+  };
+
+  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);
+
+  // These variables have not yet been named, but some of them are partly
+  // known nevertheless:
+  //
+  // unk16 - Sound-related. Possibly some sort of pitch bend.
+  // unk18 - Sound-effect. Used for secondaryEffect1()
+  // unk19 - Sound-effect. Used for secondaryEffect1()
+  // unk20 - Sound-effect. Used for secondaryEffect1()
+  // unk21 - Sound-effect. Used for secondaryEffect1()
+  // unk22 - Sound-effect. Used for secondaryEffect1()
+  // unk29 - Sound-effect. Used for primaryEffect1()
+  // unk30 - Sound-effect. Used for primaryEffect1()
+  // unk31 - Sound-effect. Used for primaryEffect1()
+  // unk32 - Sound-effect. Used for primaryEffect2()
+  // unk33 - Sound-effect. Used for primaryEffect2()
+  // unk34 - Sound-effect. Used for primaryEffect2()
+  // unk35 - Sound-effect. Used for primaryEffect2()
+  // unk36 - Sound-effect. Used for primaryEffect2()
+  // unk37 - Sound-effect. Used for primaryEffect2()
+  // unk38 - Sound-effect. Used for primaryEffect2()
+  // unk39 - Currently unused, except for updateCallback56()
+  // unk40 - Currently unused, except for updateCallback56()
+  // unk41 - Sound-effect. Used for primaryEffect2()
+
+  struct Channel
+  {
+    uint8 opExtraLevel2;
+    uint8 *dataptr;
+    uint8 duration;
+    uint8 repeatCounter;
+    int8 baseOctave;
+    uint8 priority;
+    uint8 dataptrStackPos;
+    uint8 *dataptrStack[4];
+    int8 baseNote;
+    uint8 unk29;
+    uint8 unk31;
+    uint16 unk30;
+    uint16 unk37;
+    uint8 unk33;
+    uint8 unk34;
+    uint8 unk35;
+    uint8 unk36;
+    uint8 unk32;
+    uint8 unk41;
+    uint8 unk38;
+    uint8 opExtraLevel1;
+    uint8 spacing2;
+    uint8 baseFreq;
+    uint8 tempo;
+    uint8 position;
+    uint8 regAx;
+    uint8 regBx;
+    typedef void (AdlibDriver::*Callback) (Channel &);
+    Callback primaryEffect;
+    Callback secondaryEffect;
+    uint8 fractionalSpacing;
+    uint8 opLevel1;
+    uint8 opLevel2;
+    uint8 opExtraLevel3;
+    uint8 twoChan;
+    uint8 unk39;
+    uint8 unk40;
+    uint8 spacing1;
+    uint8 durationRandomness;
+    uint8 unk19;
+    uint8 unk18;
+    int8 unk20;
+    int8 unk21;
+    uint8 unk22;
+    uint16 offset;
+    uint8 tempoReset;
+    uint8 rawNote;
+    int8 unk16;
+  };
+
+  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);
+
+  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 adjustVolume (Channel & channel);
+
+  uint8 calculateOpLevel1 (Channel & channel);
+  uint8 calculateOpLevel2 (Channel & channel);
+
+  uint16 checkValue (int16 val)
+  {
+    if (val < 0)
+      val = 0;
+    else if (val > 0x3F)
+      val = 0x3F;
+    return val;
+  }
+
+  // The sound data has at least two lookup tables:
+  //
+  // * 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 *getInstrument (int instrumentId)
+  {
+    return _soundData + READ_LE_UINT16 (_soundData + 500 + 2 * instrumentId);
+  }
+
+  void setupPrograms ();
+  void executePrograms ();
+
+  struct ParserOpcode
+  {
+    typedef int (AdlibDriver::*POpcode) (uint8 * &dataptr, Channel & channel,
+                                         uint8 value);
+    POpcode function;
+    const char *name;
+  };
+
+  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);
+
+  // These variables have not yet been named, but some of them are partly
+  // known nevertheless:
+  //
+  // _unkValue1      - Unknown. Used for updating _unkValue2
+  // _unkValue2      - Unknown. Used for updating _unkValue4
+  // _unkValue3      - Unknown. Used for updating _unkValue2
+  // _unkValue4      - Unknown. Used for updating _unkValue5
+  // _unkValue5      - Unknown. Used for controlling updateCallback24().
+  // _unkValue6      - Unknown. Rhythm section volume?
+  // _unkValue7      - Unknown. Rhythm section volume?
+  // _unkValue8      - Unknown. Rhythm section volume?
+  // _unkValue9      - Unknown. Rhythm section volume?
+  // _unkValue10     - Unknown. Rhythm section volume?
+  // _unkValue11     - Unknown. Rhythm section volume?
+  // _unkValue12     - Unknown. Rhythm section volume?
+  // _unkValue13     - Unknown. Rhythm section volume?
+  // _unkValue14     - Unknown. Rhythm section volume?
+  // _unkValue15     - Unknown. Rhythm section volume?
+  // _unkValue16     - Unknown. Rhythm section volume?
+  // _unkValue17     - Unknown. Rhythm section volume?
+  // _unkValue18     - Unknown. Rhythm section volume?
+  // _unkValue19     - Unknown. Rhythm section volume?
+  // _unkValue20     - Unknown. Rhythm section volume?
+  // _unkTable[]     - Probably frequences for the 12-tone scale.
+  // _unkTable2[]    - Unknown. Currently only used by updateCallback46()
+  // _unkTable2_1[]  - One of the tables in _unkTable2[]
+  // _unkTable2_2[]  - One of the tables in _unkTable2[]
+  // _unkTable2_3[]  - One of the tables in _unkTable2[]
+
+  int32 _samplesPerCallback;
+  int32 _samplesPerCallbackRemainder;
+  int32 _samplesTillCallback;
+  int32 _samplesTillCallbackRemainder;
+
+  int _lastProcessed;
+  int8 _flagTrigger;
+  int _curChannel;
+  uint8 _soundTrigger;
+  int _soundsPlaying;
+
+  uint16 _rnd;
+
+  uint8 _unkValue1;
+  uint8 _unkValue2;
+  uint8 _unkValue3;
+  uint8 _unkValue4;
+  uint8 _unkValue5;
+  uint8 _unkValue6;
+  uint8 _unkValue7;
+  uint8 _unkValue8;
+  uint8 _unkValue9;
+  uint8 _unkValue10;
+  uint8 _unkValue11;
+  uint8 _unkValue12;
+  uint8 _unkValue13;
+  uint8 _unkValue14;
+  uint8 _unkValue15;
+  uint8 _unkValue16;
+  uint8 _unkValue17;
+  uint8 _unkValue18;
+  uint8 _unkValue19;
+  uint8 _unkValue20;
+
+  int _flags;
+
+  uint8 *_soundData;
+
+  uint8 _soundIdTable[0x10];
+  Channel _channels[10];
+
+  uint8 _vibratoAndAMDepthBits;
+  uint8 _rhythmSectionBits;
+
+  uint8 _curRegOffset;
+  uint8 _tempo;
+
+  const uint8 *_tablePtr1;
+  const uint8 *_tablePtr2;
+
+  static const uint8 _regOffset[];
+  static const uint16 _unkTable[];
+  static const uint8 *_unkTable2[];
+  static const uint8 _unkTable2_1[];
+  static const uint8 _unkTable2_2[];
+  static const uint8 _unkTable2_3[];
+  static const uint8 _unkTables[][32];
+
+  Copl *opl;
+};
+
+AdlibDriver::AdlibDriver (Copl * newopl):opl (newopl)
+{
+  setupOpcodeList ();
+  setupParserOpcodeTable ();
+
+  //    _mixer = mixer;
+
+  _flags = 0;
+  //    _adlib = makeAdlibOPL(getRate());
+  //    assert(_adlib);
+
+  memset (_channels, 0, sizeof (_channels));
+  _soundData = 0;
+
+  _vibratoAndAMDepthBits = _curRegOffset = 0;
+
+  _lastProcessed = _flagTrigger = _curChannel = _rhythmSectionBits = 0;
+  _soundsPlaying = 0;
+  _rnd = 0x1234;
+
+  _tempo = 0;
+  _soundTrigger = 0;
+
+  _unkValue3 = 0xFF;
+  _unkValue1 = _unkValue2 = _unkValue4 = _unkValue5 = 0;
+  _unkValue6 = _unkValue7 = _unkValue8 = _unkValue9 = _unkValue10 = 0;
+  _unkValue11 = _unkValue12 = _unkValue13 = _unkValue14 = _unkValue15 =
+    _unkValue16 = _unkValue17 = _unkValue18 = _unkValue19 = _unkValue20 = 0;
+
+  _tablePtr1 = _tablePtr2 = 0;
+
+  //    _mixer->setupPremix(this);
+
+  //    _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
+  //    _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
+  _samplesTillCallback = 0;
+  _samplesTillCallbackRemainder = 0;
+}
+
+AdlibDriver::~AdlibDriver ()
+{
+  //    _mixer->setupPremix(0);
+  //    OPLDestroy(_adlib);
+  //    _adlib = 0;
+}
+
+int
+AdlibDriver::callback (int opcode, ...)
+{
+  //    lock();
+  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);
+
+  va_list 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)
+{
+  return 0x100;
+}
+
+int
+AdlibDriver::snd_ret0x1983 (va_list & list)
+{
+  return 0x1983;
+}
+
+int
+AdlibDriver::snd_initDriver (va_list & list)
+{
+  _lastProcessed = _soundsPlaying = 0;
+  resetAdlibState ();
+  return 0;
+}
+
+int
+AdlibDriver::snd_deinitDriver (va_list & list)
+{
+  resetAdlibState ();
+  return 0;
+}
+
+int
+AdlibDriver::snd_setSoundData (va_list & list)
+{
+  if (_soundData)
+  {
+    delete[]_soundData;
+    _soundData = 0;
+  }
+  _soundData = va_arg (list, uint8 *);
+  return 0;
+}
+
+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);
+  _flags |= 8;
+  _flagTrigger = 1;
+
+  uint8 *ptr = getProgram (songId);
+  uint8 chan = *ptr;
+
+  if ((songId << 1) != 0)
+  {
+    if (chan == 9)
+    {
+      if (_flags & 2)
+        return 0;
+    }
+    else
+    {
+      if (_flags & 1)
+        return 0;
+    }
+  }
+
+  _soundIdTable[_soundsPlaying++] = songId;
+  _soundsPlaying &= 0x0F;
+
+  return 0;
+}
+
+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 loop = value;
+  if (value < 0)
+  {
+    value = 0;
+    loop = 9;
+  }
+  loop -= value;
+  ++loop;
+
+  while (loop--)
+  {
+    _curChannel = value;
+    Channel & channel = _channels[_curChannel];
+    channel.priority = 0;
+    channel.dataptr = 0;
+    if (value != 9)
+    {
+      noteOff (channel);
+    }
+    ++value;
+  }
+
+  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;
+  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;
+  uint8 oldValue = *ptr;
+  *ptr = (uint8) c;
+  return oldValue;
+}
+
+int
+AdlibDriver::snd_getSoundTrigger (va_list & list)
+{
+  return _soundTrigger;
+}
+
+int
+AdlibDriver::snd_unkOpcode4 (va_list & list)
+{
+  warning ("unimplemented snd_unkOpcode4");
+  return 0;
+}
+
+int
+AdlibDriver::snd_dummy (va_list & list)
+{
+  return 0;
+}
+
+int
+AdlibDriver::snd_getNullvar4 (va_list & list)
+{
+  warning ("unimplemented snd_getNullvar4");
+  return 0;
+}
+
+int
+AdlibDriver::snd_setNullvar3 (va_list & list)
+{
+  warning ("unimplemented snd_setNullvar3");
+  return 0;
+}
+
+int
+AdlibDriver::snd_setFlag (va_list & list)
+{
+  int oldFlags = _flags;
+  _flags |= va_arg (list, int);
+  return oldFlags;
+}
+
+int
+AdlibDriver::snd_clearFlag (va_list & list)
+{
+  int oldFlags = _flags;
+  _flags &= ~(va_arg (list, int));
+  return oldFlags;
+}
+
+// timer callback
+
+void
+AdlibDriver::callback ()
+{
+  //    lock();
+  --_flagTrigger;
+  if (_flagTrigger < 0)
+    _flags &= ~8;
+  setupPrograms ();
+  executePrograms ();
+
+  uint8 temp = _unkValue3;
+  _unkValue3 += _tempo;
+  if (_unkValue3 < temp)
+  {
+    if (!(--_unkValue2))
+    {
+      _unkValue2 = _unkValue1;
+      ++_unkValue4;
+    }
+  }
+  //    unlock();
+}
+
+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];
+
+    if (priority >= channel.priority)
+    {
+      initChannel (channel);
+      channel.priority = priority;
+      channel.dataptr = ptr;
+      channel.tempo = 0xFF;
+      channel.position = 0xFF;
+      channel.duration = 1;
+      unkOutput2 (chan);
+    }
+
+    ++_lastProcessed;
+    _lastProcessed &= 0x0F;
+  }
+}
+
+// A few words on opcode parsing and timing:
+//
+// First of all, We simulate a timer callback 72 times per second. Each timeout
+// we update each channel that has something to play.
+//
+// Each channel has its own individual tempo, which is added to its position.
+// This will frequently cause the position to "wrap around" but that is
+// intentional. In fact, it's the signal to go ahead and do more stuff with
+// that channel.
+//
+// Each channel also has a duration, indicating how much time is left on the
+// its current task. This duration is decreased by one. As long as it still has
+// not reached zero, the only thing that can happen is that the note is turned
+// off depending on manual or automatic note spacing. Once the duration reaches
+// zero, a new set of musical opcodes are executed.
+//
+// An opcode is one byte, followed by a variable number of parameters. Since
+// most opcodes have at least one one-byte parameter, we read that as well. Any
+// opcode that doesn't have that one parameter is responsible for moving the
+// data pointer back again.
+//
+// If the most significant bit of the opcode is 1, it's a function; call it.
+// The opcode functions return either 0 (continue), 1 (stop) or 2 (stop, and do
+// not run the effects callbacks).
+//
+// If the most significant bit of the opcode is 0, it's a note, and the first
+// parameter is its duration. (There are cases where the duration is modified
+// but that's an exception.) The note opcode is assumed to return 1, and is the
+// last opcode unless its duration is zero.
+//
+// Finally, most of the times that the callback is called, it will invoke the
+// 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 ()
+{
+  // 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)
+  {
+    int result = 1;
+
+    if (!_channels[_curChannel].dataptr)
+    {
+      continue;
+    }
+
+    Channel & channel = _channels[_curChannel];
+    _curRegOffset = _regOffset[_curChannel];
+
+    if (channel.tempoReset)
+    {
+      channel.tempo = _tempo;
+    }
+
+    uint8 backup = channel.position;
+    channel.position += channel.tempo;
+    if (channel.position < backup)
+    {
+      if (--channel.duration)
+      {
+        if (channel.duration == channel.spacing2)
+          noteOff (channel);
+        if (channel.duration == channel.spacing1 && _curChannel != 9)
+          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
+        // on a copy of the data pointer.
+        //
+        // This fixes a subtle music bug where the
+        // wrong music would play when getting the
+        // quill in Kyra 1.
+        uint8 *dataptr = channel.dataptr;
+        while (dataptr)
+        {
+          uint8 opcode = *dataptr++;
+          uint8 param = *dataptr++;
+
+          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);
+            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)
+            {
+              channel.dataptr = dataptr;
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    if (result == 1)
+    {
+      if (channel.primaryEffect)
+        (this->*(channel.primaryEffect)) (channel);
+      if (channel.secondaryEffect)
+        (this->*(channel.secondaryEffect)) (channel);
+    }
+  }
+}
+
+//
+
+void
+AdlibDriver::resetAdlibState ()
+{
+  debugC (9, kDebugLevelSound, "resetAdlibState()");
+  _rnd = 0x1234;
+
+  // Authorize the control of the waveforms
+  writeOPL (0x01, 0x20);
+
+  // Select FM music mode
+  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);
+
+  int loop = 10;
+  while (loop--)
+  {
+    if (loop != 9)
+    {
+      // Silence the channel
+      writeOPL (0x40 + _regOffset[loop], 0x3F);
+      writeOPL (0x43 + _regOffset[loop], 0x3F);
+    }
+    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::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;
+  // normally here are nullfuncs but we set 0 for now
+  channel.primaryEffect = 0;
+  channel.secondaryEffect = 0;
+  channel.spacing1 = 1;
+}
+
+void
+AdlibDriver::noteOff (Channel & channel)
+{
+  debugC (9, kDebugLevelSound, "noteOff(%lu)", (long) (&channel - _channels));
+
+  // The control channel has no corresponding Adlib channel
+
+  if (_curChannel >= 9)
+    return;
+
+  // When the rhythm section is enabled, channels 6, 7 and 8 are special.
+
+  if (_rhythmSectionBits && _curChannel >= 6)
+    return;
+
+  // This means the "Key On" bit will always be 0
+  channel.regBx &= 0xDF;
+
+  // Octave / F-Number / Key-On
+  writeOPL (0xB0 + _curChannel, channel.regBx);
+}
+
+void
+AdlibDriver::unkOutput2 (uint8 chan)
+{
+  debugC (9, kDebugLevelSound, "unkOutput2(%d)", chan);
+
+  // The control channel has no corresponding Adlib channel
+
+  if (chan >= 9)
+    return;
+
+  // I believe this has to do with channels 6, 7, and 8 being special
+  // when Adlib's rhythm section is enabled.
+
+  if (_rhythmSectionBits && chan >= 6)
+    return;
+
+  uint8 offset = _regOffset[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 (0x80 + offset, 0xFF);
+  writeOPL (0x83 + offset, 0xFF);
+
+  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 -
+  // including the two most significant frequency bit, and the octave -
+  // set to zero.
+  //
+  // This is very strange behaviour, and causes problems with the ancient
+  // FMOPL code we borrowed from AdPlug. I've added a workaround. See
+  // fmopl.cpp for more details.
+  //
+  // More recent versions of the MAME FMOPL don't seem to have this
+  // problem, but cannot currently be used because of licensing and
+  // performance issues.
+  //
+  // Ken Silverman's Adlib emulator (which can be found on his Web page -
+  // 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);
+}
+
+// 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 ()
+{
+  _rnd += 0x9248;
+  uint16 lowBits = _rnd & 7;
+  _rnd >>= 3;
+  _rnd |= (lowBits << 13);
+  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);
+    return;
+  }
+  if (channel.fractionalSpacing)
+  {
+    channel.spacing2 = (duration >> 3) * channel.fractionalSpacing;
+  }
+  channel.duration = duration;
+}
+
+// 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));
+
+  channel.rawNote = rawNote;
+
+  int8 note = (rawNote & 0x0F) + channel.baseNote;
+  int8 octave = ((rawNote + channel.baseOctave) >> 4) & 0x0F;
+
+  // There are only twelve notes. If we go outside that, we have to
+  // adjust the note and octave.
+
+  if (note >= 12)
+  {
+    note -= 12;
+    octave++;
+  }
+  else if (note < 0)
+  {
+    note += 12;
+    octave--;
+  }
+
+  // The calculation of frequency looks quite different from the original
+  // disassembly at a first glance, but when you consider that the
+  // largest possible value would be 0x0246 + 0xFF + 0x47 (and that's if
+  // baseFreq is unsigned), freq is still a 10-bit value, just as it
+  // should be to fit in the Ax and Bx registers.
+  //
+  // If it were larger than that, it could have overflowed into the
+  // octave bits, and that could possibly have been used in some sound.
+  // But as it is now, I can't see any way it would happen.
+
+  uint16 freq = _unkTable[note] + channel.baseFreq;
+
+  // When called from callback 41, the behaviour is slightly different:
+  // We adjust the frequency, even when channel.unk16 is 0.
+
+  if (channel.unk16 || flag)
+  {
+    const uint8 *table;
+
+    if (channel.unk16 >= 0)
+    {
+      table = _unkTables[(channel.rawNote & 0x0F) + 2];
+      freq += table[channel.unk16];
+    }
+    else
+    {
+      table = _unkTables[channel.rawNote & 0x0F];
+      freq -= table[-channel.unk16];
+    }
+  }
+
+  channel.regAx = freq & 0xFF;
+  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);
+}
+
+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++);
+
+  uint8 temp = *dataptr++;
+
+  // Feedback / Algorithm
+
+  // 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);
+
+  // The algorithm bit. I don't pretend to understand this fully, but
+  // "If set to 0, operator 1 modulates operator 2. In this case,
+  // operator 2 is the only one producing sound. If set to 1, both
+  // operators produce sound directly. Complex sounds are more easily
+  // created if the algorithm is set to 0."
+
+  channel.twoChan = temp & 1;
+
+  // Waveform Select
+  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));
+
+  // Attack Rate / Decay Rate
+  writeOPL (0x60 + regOffset, *dataptr++);
+  writeOPL (0x63 + regOffset, *dataptr++);
+
+  // Sustain Level / Release Rate
+  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));
+
+  // The "note on" bit is set, and the current note is played.
+
+  channel.regBx |= 0x20;
+  writeOPL (0xB0 + _curChannel, channel.regBx);
+
+  int8 shift = 9 - channel.unk33;
+  uint16 temp = channel.regAx | (channel.regBx << 8);
+  channel.unk37 = ((temp & 0x3FF) >> shift) & 0xFF;
+  channel.unk38 = channel.unk36;
+}
+
+void
+AdlibDriver::adjustVolume (Channel & channel)
+{
+  debugC (9, kDebugLevelSound, "adjustVolume(%lu)",
+          (long) (&channel - _channels));
+  // Level Key Scaling / Total Level
+
+  writeOPL (0x43 + _regOffset[_curChannel], calculateOpLevel2 (channel));
+  if (channel.twoChan)
+    writeOPL (0x40 + _regOffset[_curChannel], calculateOpLevel1 (channel));
+}
+
+// This is presumably only used for some sound effects, e.g. Malcolm blowing up
+// the trees in the intro (but not the effect where he "booby-traps" the big
+// tree) and turning Kallak to stone. Related functions and variables:
+//
+// update_setupPrimaryEffect1()
+//    - Initialises unk29, unk30 and unk31
+//    - unk29 is not further modified
+//    - unk30 is not further modified, except by update_removePrimaryEffect1()
+//
+// update_removePrimaryEffect1()
+//    - Deinitialises unk30
+//
+// unk29 - determines how often the notes are played
+// 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);
+  uint8 temp = channel.unk31;
+  channel.unk31 += channel.unk29;
+  if (channel.unk31 >= temp)
+    return;
+
+  // Initialise unk1 to the current frequency
+  uint16 unk1 = ((channel.regBx & 3) << 8) | channel.regAx;
+
+  // This is presumably to shift the "note on" bit so far to the left
+  // 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;
+
+  if (unk3 >= 0)
+  {
+    unk1 += unk3;
+    if (unk1 >= 734)
+    {
+      // The new frequency is too high. Shift it down and go
+      // up one octave.
+      unk1 >>= 1;
+      if (!(unk1 & 0x3FF))
+        ++unk1;
+      unk2 = (unk2 & 0xFF00) | ((unk2 + 4) & 0xFF);
+      unk2 &= 0xFF1C;
+    }
+  }
+  else
+  {
+    unk1 += unk3;
+    if (unk1 < 388)
+    {
+      // The new frequency is too low. Shift it up and go
+      // down one octave.
+      unk1 <<= 1;
+      if (!(unk1 & 0x3FF))
+        --unk1;
+      unk2 = (unk2 & 0xFF00) | ((unk2 - 4) & 0xFF);
+      unk2 &= 0xFF1C;
+    }
+  }
+
+  // Make sure that the new frequency is still a 10-bit value.
+  unk1 &= 0x3FF;
+
+  writeOPL (0xA0 + _curChannel, unk1 & 0xFF);
+  channel.regAx = unk1 & 0xFF;
+
+  // Shift down the "note on" bit again.
+  uint8 value = unk1 >> 8;
+  value |= (unk2 >> 8) & 0xFF;
+  value |= unk2 & 0xFF;
+
+  writeOPL (0xB0 + _curChannel, value);
+  channel.regBx = value;
+}
+
+// This is presumably only used for some sound effects, e.g. Malcolm entering
+// and leaving Kallak's hut. Related functions and variables:
+//
+// update_setupPrimaryEffect2()
+//    - Initialises unk32, unk33, unk34, unk35 and unk36
+//    - unk32 is not further modified
+//    - unk33 is not further modified
+//    - unk34 is a countdown that gets reinitialised to unk35 on zero
+//    - unk35 is based on unk34 and not further modified
+//    - unk36 is not further modified
+//
+// noteOn()
+//    - Plays the current note
+//    - Updates unk37 with a new (lower?) frequency
+//    - Copies unk36 to unk38. The unk38 variable is a countdown.
+//
+// unk32 - determines how often the notes are played
+// unk33 - modifies the frequency
+// unk34 - countdown, updates frequency on zero
+// unk35 - initialiser for unk34 countdown
+// unk36 - initialiser for unk38 countdown
+// unk37 - frequency
+// unk38 - countdown, begins playing on zero
+// unk41 - determines how often the notes are played
+//
+// 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)
+  {
+    --channel.unk38;
+    return;
+  }
+
+  uint8 temp = channel.unk41;
+  channel.unk41 += channel.unk32;
+  if (channel.unk41 < temp)
+  {
+    uint16 unk1 = channel.unk37;
+    if (!(--channel.unk34))
+    {
+      unk1 ^= 0xFFFF;
+      ++unk1;
+      channel.unk37 = unk1;
+      channel.unk34 = channel.unk35;
+    }
+
+    uint16 unk2 = (channel.regAx | (channel.regBx << 8)) & 0x3FF;
+    unk2 += unk1;
+
+    channel.regAx = unk2 & 0xFF;
+    channel.regBx = (channel.regBx & 0xFC) | (unk2 >> 8);
+
+    // Octave / F-Number / Key-On
+    writeOPL (0xA0 + _curChannel, channel.regAx);
+    writeOPL (0xB0 + _curChannel, channel.regBx);
+  }
+}
+
+// I don't know where this is used. The same operation is performed several
+// times on the current channel, using a chunk of the _soundData[] buffer for
+// parameters. The parameters are used starting at the end of the chunk.
+//
+// Since we use _curRegOffset to specify the final register, it's quite
+// unlikely that this function is ever used to play notes. It's probably only
+// used to modify the sound. Another thing that supports this idea is that it
+// can be combined with any of the effects callbacks above.
+//
+// Related functions and variables:
+//
+// update_setupSecondaryEffect1()
+//    - Initialies unk18, unk19, unk20, unk21, unk22 and offset
+//    - unk19 is not further modified
+//    - unk20 is not further modified
+//    - unk22 is not further modified
+//    - offset is not further modified
+//
+// unk18 -  determines how often the operation is performed
+// unk19 -  determines how often the operation is performed
+// unk20 -  the start index into the data chunk
+// unk21 -  the current index into the data chunk
+// 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);
+  uint8 temp = channel.unk18;
+  channel.unk18 += channel.unk19;
+  if (channel.unk18 < temp)
+  {
+    if (--channel.unk21 < 0)
+    {
+      channel.unk21 = channel.unk20;
+    }
+    writeOPL (channel.unk22 + _curRegOffset,
+              _soundData[channel.offset + channel.unk21]);
+  }
+}
+
+uint8
+AdlibDriver::calculateOpLevel1 (Channel & channel)
+{
+  int8 value = channel.opLevel1 & 0x3F;
+
+  if (channel.twoChan)
+  {
+    value += channel.opExtraLevel1;
+    value += channel.opExtraLevel2;
+    value += channel.opExtraLevel3;
+  }
+
+  // Preserve the scaling level bits from opLevel1
+
+  return checkValue (value) | (channel.opLevel1 & 0xC0);
+}
+
+uint8
+AdlibDriver::calculateOpLevel2 (Channel & channel)
+{
+  int8 value = channel.opLevel2 & 0x3F;
+
+  value += channel.opExtraLevel1;
+  value += channel.opExtraLevel2;
+  value += channel.opExtraLevel3;
+
+  // Preserve the scaling level bits from opLevel2
+
+  return checkValue (value) | (channel.opLevel2 & 0xC0);
+}
+
+// parser opcodes
+
+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)
+{
+  ++dataptr;
+  if (--channel.repeatCounter)
+  {
+    int16 add = READ_LE_UINT16 (dataptr - 2);
+    dataptr += add;
+  }
+  return 0;
+}
+
+int
+AdlibDriver::update_setupProgram (uint8 * &dataptr, Channel & channel,
+                                  uint8 value)
+{
+  if (value == 0xFF)
+    return 0;
+
+  uint8 *ptr = getProgram (value);
+  uint8 chan = *ptr++;
+  uint8 priority = *ptr++;
+
+  Channel & channel2 = _channels[chan];
+
+  if (priority >= channel2.priority)
+  {
+    _flagTrigger = 1;
+    _flags |= 8;
+    initChannel (channel2);
+    channel2.priority = priority;
+    channel2.dataptr = ptr;
+    channel2.tempo = 0xFF;
+    channel2.position = 0xFF;
+    channel2.duration = 1;
+    unkOutput2 (chan);
+  }
+
+  return 0;
+}
+
+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)
+{
+  --dataptr;
+  int16 add = READ_LE_UINT16 (dataptr);
+  dataptr += 2;
+  dataptr += add;
+  return 0;
+}
+
+int
+AdlibDriver::update_jumpToSubroutine (uint8 * &dataptr, Channel & channel,
+                                      uint8 value)
+{
+  --dataptr;
+  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)
+{
+  dataptr = channel.dataptrStack[--channel.dataptrStackPos];
+  return 0;
+}
+
+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)
+{
+  channel.priority = 0;
+  if (_curChannel != 9)
+  {
+    noteOff (channel);
+  }
+  dataptr = 0;
+  return 2;
+}
+
+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++);
+  return 0;
+}
+
+int
+AdlibDriver::update_setupNoteAndDuration (uint8 * &dataptr, Channel & channel,
+                                          uint8 value)
+{
+  setupNote (value, channel);
+  value = *dataptr++;
+  setupDuration (value, channel);
+  return (value != 0);
+}
+
+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)
+{
+  channel.unk18 = value;
+  channel.unk19 = value;
+  channel.unk20 = channel.unk21 = *dataptr++;
+  channel.unk22 = *dataptr++;
+  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];
+  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);
+  uint8 chan = *ptr;
+
+  if (!_channels[chan].dataptr)
+  {
+    return 0;
+  }
+
+  dataptr -= 2;
+  return 2;
+}
+
+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)
+{
+  channel.unk29 = value;
+  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)
+{
+  --dataptr;
+  channel.primaryEffect = 0;
+  channel.unk30 = 0;
+  return 0;
+}
+
+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)
+{
+  channel.unk32 = value;
+  channel.unk33 = *dataptr++;
+  uint8 temp = *dataptr++;
+  channel.unk34 = temp + 1;
+  channel.unk35 = temp << 1;
+  channel.unk36 = *dataptr++;
+  channel.primaryEffect = &AdlibDriver::primaryEffect2;
+  return 0;
+}
+
+int
+AdlibDriver::update_setPriority (uint8 * &dataptr, Channel & channel,
+                                 uint8 value)
+{
+  channel.priority = value;
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback23 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  value >>= 1;
+  _unkValue1 = _unkValue2 = value;
+  _unkValue3 = 0xFF;
+  _unkValue4 = _unkValue5 = 0;
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback24 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  if (_unkValue5)
+  {
+    if (_unkValue4 & value)
+    {
+      _unkValue5 = 0;
+      return 0;
+    }
+  }
+
+  if (!(value & _unkValue4))
+  {
+    ++_unkValue5;
+  }
+
+  dataptr -= 2;
+  channel.duration = 1;
+  return 2;
+}
+
+int
+AdlibDriver::update_setExtraLevel1 (uint8 * &dataptr, Channel & channel,
+                                    uint8 value)
+{
+  channel.opExtraLevel1 = value;
+  adjustVolume (channel);
+  return 0;
+}
+
+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);
+  return (value != 0);
+}
+
+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)
+{
+  _tempo = value;
+  return 0;
+}
+
+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)
+{
+  channel.tempo = value;
+  return 0;
+}
+
+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 channelBackUp = _curChannel;
+
+  _curChannel = value;
+  Channel & channel2 = _channels[value];
+  channel2.opExtraLevel2 = *dataptr++;
+  adjustVolume (channel2);
+
+  _curChannel = channelBackUp;
+  return 0;
+}
+
+int
+AdlibDriver::update_changeExtraLevel2 (uint8 * &dataptr, Channel & channel,
+                                       uint8 value)
+{
+  int channelBackUp = _curChannel;
+
+  _curChannel = value;
+  Channel & channel2 = _channels[value];
+  channel2.opExtraLevel2 += *dataptr++;
+  adjustVolume (channel2);
+
+  _curChannel = channelBackUp;
+  return 0;
+}
+
+// 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)
+{
+  if (value & 1)
+    _vibratoAndAMDepthBits |= 0x80;
+  else
+    _vibratoAndAMDepthBits &= 0x7F;
+
+  writeOPL (0xBD, _vibratoAndAMDepthBits);
+  return 0;
+}
+
+int
+AdlibDriver::update_setVibratoDepth (uint8 * &dataptr, Channel & channel,
+                                     uint8 value)
+{
+  if (value & 1)
+    _vibratoAndAMDepthBits |= 0x40;
+  else
+    _vibratoAndAMDepthBits &= 0xBF;
+
+  writeOPL (0xBD, _vibratoAndAMDepthBits);
+  return 0;
+}
+
+int
+AdlibDriver::update_changeExtraLevel1 (uint8 * &dataptr, Channel & channel,
+                                       uint8 value)
+{
+  channel.opExtraLevel1 += value;
+  adjustVolume (channel);
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback38 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  int channelBackUp = _curChannel;
+
+  _curChannel = value;
+  Channel & channel2 = _channels[value];
+  channel2.duration = channel2.priority = 0;
+  channel2.dataptr = 0;
+  channel2.opExtraLevel2 = 0;
+
+  if (value != 9)
+  {
+    uint8 outValue = _regOffset[value];
+
+    // Feedback strength / Connection type
+    writeOPL (0xC0 + _curChannel, 0x00);
+
+    // Key scaling level / Operator output level
+    writeOPL (0x43 + outValue, 0x3F);
+
+    // Sustain Level / Release Rate
+    writeOPL (0x83 + outValue, 0xFF);
+
+    // Key On / Octave / Frequency
+    writeOPL (0xB0 + _curChannel, 0x00);
+  }
+
+  _curChannel = channelBackUp;
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback39 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  uint16 unk = *dataptr++;
+  unk |= value << 8;
+  unk &= getRandomNr ();
+
+  uint16 unk2 = ((channel.regBx & 0x1F) << 8) | channel.regAx;
+  unk2 += unk;
+  unk2 |= ((channel.regBx & 0x20) << 8);
+
+  // Frequency
+  writeOPL (0xA0 + _curChannel, unk2 & 0xFF);
+
+  // Key On / Octave / Frequency
+  writeOPL (0xB0 + _curChannel, (unk2 & 0xFF00) >> 8);
+
+  return 0;
+}
+
+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)
+{
+  channel.unk16 = value;
+  setupNote (channel.rawNote, channel, true);
+  return 0;
+}
+
+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)
+{
+  --dataptr;
+  return 0;
+}
+
+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;
+
+  if (tempo <= 0)
+    tempo = 1;
+  else if (tempo > 255)
+    tempo = 255;
+
+  channel.tempo = tempo;
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback46 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  uint8 entry = *dataptr++;
+  _tablePtr1 = _unkTable2[entry++];
+  _tablePtr2 = _unkTable2[entry];
+  if (value == 2)
+  {
+    // Frequency
+    writeOPL (0xA0, _tablePtr2[0]);
+  }
+  return 0;
+}
+
+// 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)
+{
+  --dataptr;
+  return 0;
+}
+
+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);
+  _unkValue6 = channel.opLevel2;
+
+  _curChannel = 7;
+  _curRegOffset = _regOffset[7];
+
+  setupInstrument (_curRegOffset, getInstrument (*dataptr++), channel);
+  _unkValue7 = channel.opLevel1;
+  _unkValue8 = channel.opLevel2;
+
+  _curChannel = 8;
+  _curRegOffset = _regOffset[8];
+
+  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++);
+
+  _channels[7].regBx = *dataptr++ & 0x2F;
+  writeOPL (0xB7, _channels[7].regBx);
+  writeOPL (0xA7, *dataptr++);
+
+  _channels[8].regBx = *dataptr++ & 0x2F;
+  writeOPL (0xB8, _channels[8].regBx);
+  writeOPL (0xA8, *dataptr++);
+
+  _rhythmSectionBits = 0x20;
+
+  _curRegOffset = regOffsetBackUp;
+  _curChannel = channelBackUp;
+  return 0;
+}
+
+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);
+
+  // ...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
+  // useful the cleverness above is. We could perhaps simply turn off all
+  // the rhythm instruments instead.
+
+  _rhythmSectionBits |= value;
+
+  writeOPL (0xBD, _vibratoAndAMDepthBits | 0x20 | _rhythmSectionBits);
+  return 0;
+}
+
+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);
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback51 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  uint8 value2 = *dataptr++;
+
+  if (value & 1)
+  {
+    _unkValue12 = value2;
+
+    // Channel 7, op1: Level Key Scaling / Total Level
+    writeOPL (0x51,
+              checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12));
+  }
+
+  if (value & 2)
+  {
+    _unkValue14 = value2;
+
+    // Channel 8, op2: Level Key Scaling / Total Level
+    writeOPL (0x55,
+              checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14));
+  }
+
+  if (value & 4)
+  {
+    _unkValue15 = value2;
+
+    // Channel 8, op1: Level Key Scaling / Total Level
+    writeOPL (0x52,
+              checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15));
+  }
+
+  if (value & 8)
+  {
+    _unkValue18 = value2;
+
+    // Channel 7, op2: Level Key Scaling / Total Level
+    writeOPL (0x54,
+              checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18));
+  }
+
+  if (value & 16)
+  {
+    _unkValue20 = value2;
+
+    // Channel 6, op2: Level Key Scaling / Total Level
+    writeOPL (0x53,
+              checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20));
+  }
+
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback52 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  uint8 value2 = *dataptr++;
+
+  if (value & 1)
+  {
+    _unkValue11 =
+      checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12);
+
+    // Channel 7, op1: Level Key Scaling / Total Level
+    writeOPL (0x51, _unkValue11);
+  }
+
+  if (value & 2)
+  {
+    _unkValue13 =
+      checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14);
+
+    // Channel 8, op2: Level Key Scaling / Total Level
+    writeOPL (0x55, _unkValue13);
+  }
+
+  if (value & 4)
+  {
+    _unkValue16 =
+      checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15);
+
+    // Channel 8, op1: Level Key Scaling / Total Level
+    writeOPL (0x52, _unkValue16);
+  }
+
+  if (value & 8)
+  {
+    _unkValue17 =
+      checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18);
+
+    // Channel 7, op2: Level Key Scaling / Total Level
+    writeOPL (0x54, _unkValue17);
+  }
+
+  if (value & 16)
+  {
+    _unkValue19 =
+      checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20);
+
+    // Channel 6, op2: Level Key Scaling / Total Level
+    writeOPL (0x53, _unkValue19);
+  }
+
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback53 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  uint8 value2 = *dataptr++;
+
+  if (value & 1)
+  {
+    _unkValue11 = value2;
+
+    // Channel 7, op1: Level Key Scaling / Total Level
+    writeOPL (0x51, checkValue (value2 + _unkValue7 + _unkValue12));
+  }
+
+  if (value & 2)
+  {
+    _unkValue13 = value2;
+
+    // Channel 8, op2: Level Key Scaling / Total Level
+    writeOPL (0x55, checkValue (value2 + _unkValue10 + _unkValue14));
+  }
+
+  if (value & 4)
+  {
+    _unkValue16 = value2;
+
+    // Channel 8, op1: Level Key Scaling / Total Level
+    writeOPL (0x52, checkValue (value2 + _unkValue9 + _unkValue15));
+  }
+
+  if (value & 8)
+  {
+    _unkValue17 = value2;
+
+    // Channel 7, op2: Level Key Scaling / Total Level
+    writeOPL (0x54, checkValue (value2 + _unkValue8 + _unkValue18));
+  }
+
+  if (value & 16)
+  {
+    _unkValue19 = value2;
+
+    // Channel 6, op2: Level Key Scaling / Total Level
+    writeOPL (0x53, checkValue (value2 + _unkValue6 + _unkValue20));
+  }
+
+  return 0;
+}
+
+int
+AdlibDriver::update_setSoundTrigger (uint8 * &dataptr, Channel & channel,
+                                     uint8 value)
+{
+  _soundTrigger = value;
+  return 0;
+}
+
+int
+AdlibDriver::update_setTempoReset (uint8 * &dataptr, Channel & channel,
+                                   uint8 value)
+{
+  channel.tempoReset = value;
+  return 0;
+}
+
+int
+AdlibDriver::updateCallback56 (uint8 * &dataptr, Channel & channel,
+                               uint8 value)
+{
+  channel.unk39 = value;
+  channel.unk40 = *dataptr++;
+  return 0;
+}
+
+// static res
+
+#define COMMAND(x) { &AdlibDriver::x, #x }
+
+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)
+  };
+
+  _opcodeList = opcodeList;
+  _opcodesEntries = ARRAYSIZE (opcodeList);
+}
+
+void
+AdlibDriver::setupParserOpcodeTable ()
+{
+  static const ParserOpcode parserOpcodeTable[] = {
+    // 0
+    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),
+
+    // 8
+    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),
+
+    // 16
+    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),
+
+    // 24
+    COMMAND (update_stopChannel),
+    COMMAND (update_stopChannel),
+    COMMAND (update_setPriority),
+    COMMAND (update_stopChannel),
+
+    // 28
+    COMMAND (updateCallback23),
+    COMMAND (updateCallback24),
+    COMMAND (update_setExtraLevel1),
+    COMMAND (update_stopChannel),
+
+    // 32
+    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),
+
+    // 40
+    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),
+
+    // 48
+    COMMAND (update_changeExtraLevel1),
+    COMMAND (update_stopChannel),
+    COMMAND (update_stopChannel),
+    COMMAND (updateCallback38),
+
+    // 52
+    COMMAND (update_stopChannel),
+    COMMAND (updateCallback39),
+    COMMAND (update_removePrimaryEffect2),
+    COMMAND (update_stopChannel),
+
+    // 56
+    COMMAND (update_stopChannel),
+    COMMAND (updateCallback41),
+    COMMAND (update_resetToGlobalTempo),
+    COMMAND (update_nop1),
+
+    // 60
+    COMMAND (update_setDurationRandomness),
+    COMMAND (update_changeChannelTempo),
+    COMMAND (update_stopChannel),
+    COMMAND (updateCallback46),
+
+    // 64
+    COMMAND (update_nop2),
+    COMMAND (update_setupRhythmSection),
+    COMMAND (update_playRhythmSection),
+    COMMAND (update_removeRhythmSection),
+
+    // 68
+    COMMAND (updateCallback51),
+    COMMAND (updateCallback52),
+    COMMAND (updateCallback53),
+    COMMAND (update_setSoundTrigger),
+
+    // 72
+    COMMAND (update_setTempoReset),
+    COMMAND (updateCallback56),
+    COMMAND (update_stopChannel)
+  };
+
+  _parserOpcodeTable = 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[] = {
+  0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11,
+  0x12
+};
+
+// Given the size of this table, and the range of its values, it's probably the
+// 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[] = {
+  0x0134, 0x0147, 0x015A, 0x016F, 0x0184, 0x019C, 0x01B4, 0x01CE, 0x01E9,
+  0x0207, 0x0225, 0x0246
+};
+
+// 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[] = {
+  AdlibDriver::_unkTable2_1,
+  AdlibDriver::_unkTable2_2,
+  AdlibDriver::_unkTable2_1,
+  AdlibDriver::_unkTable2_2,
+  AdlibDriver::_unkTable2_3,
+  AdlibDriver::_unkTable2_2
+};
+
+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,
+  0x44, 0x44, 0x43, 0x43, 0x42, 0x42, 0x41, 0x41,
+  0x40, 0x40, 0x3F, 0x3F, 0x3E, 0x3E, 0x3D, 0x3D,
+  0x3C, 0x3C, 0x3B, 0x3B, 0x3A, 0x3A, 0x39, 0x39,
+  0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35,
+  0x34, 0x34, 0x33, 0x33, 0x32, 0x32, 0x31, 0x31,
+  0x30, 0x30, 0x2F, 0x2F, 0x2E, 0x2E, 0x2D, 0x2D,
+  0x2C, 0x2C, 0x2B, 0x2B, 0x2A, 0x2A, 0x29, 0x29,
+  0x28, 0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25,
+  0x24, 0x24, 0x23, 0x23, 0x22, 0x22, 0x21, 0x21,
+  0x20, 0x20, 0x1F, 0x1F, 0x1E, 0x1E, 0x1D, 0x1D,
+  0x1C, 0x1C, 0x1B, 0x1B, 0x1A, 0x1A, 0x19, 0x19,
+  0x18, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15,
+  0x14, 0x14, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11,
+  0x10, 0x10
+};
+
+// no don't ask me WHY this table exsits!
+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,
+  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+  0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+  0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x6F,
+  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+  0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
+};
+
+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,
+  0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36,
+  0x36, 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x33,
+  0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31, 0x31,
+  0x30, 0x30, 0x30, 0x2F, 0x2F, 0x2F, 0x2E, 0x2E,
+  0x2E, 0x2D, 0x2D, 0x2D, 0x2C, 0x2C, 0x2C, 0x2B,
+  0x2B, 0x2B, 0x2A, 0x2A, 0x2A, 0x29, 0x29, 0x29,
+  0x28, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26,
+  0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23,
+  0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21,
+  0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E,
+  0x1E, 0x1D, 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1B,
+  0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19,
+  0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16, 0x16,
+  0x16, 0x15
+};
+
+// This table is used to modify the frequency of the notes, depending on the
+// note value and unk16. In theory, we could very well try to access memory
+// outside this table, but in reality that probably won't happen.
+//
+// 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] = {
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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},
+  // 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}
+};
+
+// #pragma mark -
+
+// 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[] = {
+  0, 4, 5, 3
+};
+
+const int
+  CadlPlayer::_kyra1NumSoundTriggers =
+ARRAYSIZE (CadlPlayer::_kyra1SoundTriggers);
+
+CadlPlayer::CadlPlayer (Copl * newopl):CPlayer (newopl), numsubsongs (0), _trackEntries (),
+_soundDataPtr (0)
+{
+  memset (_trackEntries, 0, sizeof (_trackEntries));
+  _driver = new AdlibDriver (newopl);
+  assert (_driver);
+
+  _sfxPlayingSound = -1;
+  //    _soundFileLoaded = "";
+
+  _soundTriggers = _kyra1SoundTriggers;
+  _numSoundTriggers = _kyra1NumSoundTriggers;
+
+  init ();
+}
+
+CadlPlayer::~CadlPlayer ()
+{
+  delete[]_soundDataPtr;
+  _soundDataPtr = 0;
+  delete _driver;
+  _driver = 0;
+}
+
+bool
+CadlPlayer::init ()
+{
+  _driver->callback (2);
+  _driver->callback (16, int (4));
+  return true;
+}
+
+void
+CadlPlayer::process ()
+{
+  uint8 trigger = _driver->callback (11);
+
+  if (trigger < _numSoundTriggers)
+  {
+    int soundId = _soundTriggers[trigger];
+
+    if (soundId)
+    {
+      playTrack (soundId);
+    }
+  }
+  else
+  {
+    warning ("Unknown sound trigger %d", trigger);
+    // TODO: At this point, we really want to clear the trigger...
+  }
+}
+
+// void CadlPlayer::setVolume(int volume) {
+// }
+
+// int CadlPlayer::getVolume() {
+//  return 0;
+// }
+
+// void CadlPlayer::loadMusicFile(const char *file) {
+//  loadSoundFile(file);
+// }
+
+void
+CadlPlayer::playTrack (uint8 track)
+{
+  play (track);
+}
+
+// void CadlPlayer::haltTrack() {
+//  unk1();
+//  unk2();
+//  //_engine->_system->delayMillis(3 * 60);
+// }
+
+void
+CadlPlayer::playSoundEffect (uint8_t track)
+{
+  play (track);
+}
+
+void
+CadlPlayer::play (uint8_t track)
+{
+  uint8 soundId = _trackEntries[track];
+  if ((int8) soundId == -1 || !_soundDataPtr)
+    return;
+  soundId &= 0xFF;
+  _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);
+  //    }
+  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));
+    _sfxPlayingSound = -1;
+  }
+
+  int chan = _driver->callback (9, soundId, int (0));
+
+  if (chan != 9)
+  {
+    _sfxPlayingSound = soundId;
+    _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.
+    //
+    // The extra level is part of the channels "total level", which
+    // is a six-bit value where larger values means softer volume.
+    //
+    // So what seems to be happening here is that sounds which are
+    // started by this function are given a slightly lower priority
+    // and a slightly higher (i.e. softer) extra level 3 than they
+    // would have if they were started from anywhere else. Strange.
+
+    int newVal = ((((-_sfxFourthByteOfSong) + 63) * 0xFF) >> 8) & 0xFF;
+    newVal = -newVal + 63;
+    _driver->callback (10, soundId, int (3), newVal);
+    newVal = ((_sfxPriority * 0xFF) >> 8) & 0xFF;
+    _driver->callback (10, soundId, int (1), newVal);
+  }
+
+  _driver->callback (6, soundId);
+}
+
+// void CadlPlayer::beginFadeOut() {
+//  playSoundEffect(1);
+// }
+
+bool
+CadlPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  std::string filename (fd.filename ());
+
+  // file validation section
+  if (!f || !fp.extension (filename, ".adl"))
+  {
+    fp.close (f);
+    return false;
+  }
+
+  //    if (_soundFileLoaded == file)
+  //        return;
+
+  //    if (_soundDataPtr) {
+  //        haltTrack();
+  //    }
+
+  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;
+  //    }
+
+  unk2 ();
+  unk1 ();
+
+  file_size = fp.filesize (f);
+  file_data = new uint8[file_size];
+  f->readString ((char *) file_data, file_size);
+
+  _driver->callback (8, int (-1));
+  _soundDataPtr = 0;
+
+  uint8 *p = file_data;
+  memcpy (_trackEntries, p, 120 * sizeof (uint8));
+  p += 120;
+
+  int soundDataSize = file_size - 120;
+
+  _soundDataPtr = new uint8[soundDataSize];
+  assert (_soundDataPtr);
+
+  memcpy (_soundDataPtr, p, soundDataSize * sizeof (uint8));
+
+  delete[]file_data;
+  file_data = p = 0;
+  file_size = 0;
+
+  _driver->callback (4, _soundDataPtr);
+
+  //    _soundFileLoaded = file;
+
+  // find last subsong
+  for(int i = 119; i >= 0; i--)
+    if(_trackEntries[i] != 0xff) {
+      numsubsongs = i + 1;
+      break;
+    }
+  fp.close (f);
+  cursubsong = 2;
+  rewind();
+  return true;
+}
+
+void
+CadlPlayer::rewind (int subsong)
+{
+  if(subsong == -1) subsong = cursubsong;
+  opl->init ();
+  opl->write (1, 32);
+  playSoundEffect (subsong);
+  cursubsong = subsong;
+  update ();
+}
+
+unsigned int
+CadlPlayer::getsubsongs ()
+{
+  return numsubsongs;
+}
+
+bool
+CadlPlayer::update ()
+{
+  bool songend = true;
+
+//   if(_trackEntries[cursubsong] == 0xff)
+//     return false;
+
+  _driver->callback ();
+
+  for (int i = 0; i < 10; i++)
+    if (_driver->_channels[i].dataptr != nullptr)
+      songend = false;
+
+  return !songend;
+}
+
+void
+CadlPlayer::unk1 ()
+{
+  playSoundEffect (0);
+  //_engine->_system->delayMillis(5 * 60);
+}
+
+void
+CadlPlayer::unk2 ()
+{
+  playSoundEffect (0);
+}
+
+CPlayer *
+CadlPlayer::factory (Copl * newopl)
+{
+  return new CadlPlayer (newopl);
+}
diff --git a/src/adplug/core/adl.cxx b/src/adplug/core/adl.cxx
deleted file mode 100644
index e3506b595b21..000000000000
--- a/src/adplug/core/adl.cxx
+++ /dev/null
@@ -1,2874 +0,0 @@
-/*
- * adl.cpp - ADL player adaption by Simon Peter <dn.tlp at gmx.net>
- *
- * Original ADL player by Torbjorn Andersson and Johannes Schickel
- * 'lordhoto' <lordhoto at scummvm dot org> of the ScummVM project.
- */
-
-/* ScummVM - Scumm Interpreter
- *
- * This file is licensed under both GPL and LGPL
- * Copyright (C) 2006 The ScummVM project
- * Copyright (C) 2006 Torbjorn Andersson and Johannes Schickel
- *
- * GPL License
- *
- * 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.
- *
- * LPGL License
- *
- * 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
- *
- */
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "adl.h"
-#include "debug.h"
-
-#ifdef ADL_DEBUG
-#	define warning(...)		AdPlug_LogWrite(__VA_ARGS__); \
-AdPlug_LogWrite("\n")
-
-#	define debugC(i1, i2, ...)	AdPlug_LogWrite(__VA_ARGS__); \
-AdPlug_LogWrite("\n")
-#else
-#	define kDebugLevelSound	1
-
-static inline void
-warning (const char *str, ...)
-{
-}
-
-static inline void
-debugC (int i1, int i2, const char *str, ...)
-{
-}
-#endif
-
-// #define warning(...)
-// #define debugC(i1, i2, ...)
-
-#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
-
-// Basic Adlib Programming:
-// http://www.gamedev.net/reference/articles/article446.asp
-
-#define CALLBACKS_PER_SECOND 72
-
-typedef uint8_t uint8;
-typedef int8_t int8;
-typedef uint16_t uint16;
-typedef int16_t int16;
-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;
-  return (b[1] << 8) + b[0];
-}
-
-static inline uint16
-READ_BE_UINT16 (const void *ptr)
-{
-  const byte *b = (const byte *) ptr;
-  return (b[0] << 8) + b[1];
-}
-
-class AdlibDriver
-{
-public:
-  AdlibDriver (Copl * opl);
-  ~AdlibDriver ();
-
-  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 render = MIN(samplesLeft, _samplesTillCallback);
-  //            samplesLeft -= render;
-  //            _samplesTillCallback -= render;
-  //            YM3812UpdateOne(_adlib, buffer, render);
-  //            buffer += render;
-  //        }
-  //        return numSamples;
-  //    }
-
-  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);
-    DriverOpcode function;
-    const char *name;
-  };
-
-  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);
-
-  // These variables have not yet been named, but some of them are partly
-  // known nevertheless:
-  //
-  // unk16 - Sound-related. Possibly some sort of pitch bend.
-  // unk18 - Sound-effect. Used for secondaryEffect1()
-  // unk19 - Sound-effect. Used for secondaryEffect1()
-  // unk20 - Sound-effect. Used for secondaryEffect1()
-  // unk21 - Sound-effect. Used for secondaryEffect1()
-  // unk22 - Sound-effect. Used for secondaryEffect1()
-  // unk29 - Sound-effect. Used for primaryEffect1()
-  // unk30 - Sound-effect. Used for primaryEffect1()
-  // unk31 - Sound-effect. Used for primaryEffect1()
-  // unk32 - Sound-effect. Used for primaryEffect2()
-  // unk33 - Sound-effect. Used for primaryEffect2()
-  // unk34 - Sound-effect. Used for primaryEffect2()
-  // unk35 - Sound-effect. Used for primaryEffect2()
-  // unk36 - Sound-effect. Used for primaryEffect2()
-  // unk37 - Sound-effect. Used for primaryEffect2()
-  // unk38 - Sound-effect. Used for primaryEffect2()
-  // unk39 - Currently unused, except for updateCallback56()
-  // unk40 - Currently unused, except for updateCallback56()
-  // unk41 - Sound-effect. Used for primaryEffect2()
-
-  struct Channel
-  {
-    uint8 opExtraLevel2;
-    uint8 *dataptr;
-    uint8 duration;
-    uint8 repeatCounter;
-    int8 baseOctave;
-    uint8 priority;
-    uint8 dataptrStackPos;
-    uint8 *dataptrStack[4];
-    int8 baseNote;
-    uint8 unk29;
-    uint8 unk31;
-    uint16 unk30;
-    uint16 unk37;
-    uint8 unk33;
-    uint8 unk34;
-    uint8 unk35;
-    uint8 unk36;
-    uint8 unk32;
-    uint8 unk41;
-    uint8 unk38;
-    uint8 opExtraLevel1;
-    uint8 spacing2;
-    uint8 baseFreq;
-    uint8 tempo;
-    uint8 position;
-    uint8 regAx;
-    uint8 regBx;
-    typedef void (AdlibDriver::*Callback) (Channel &);
-    Callback primaryEffect;
-    Callback secondaryEffect;
-    uint8 fractionalSpacing;
-    uint8 opLevel1;
-    uint8 opLevel2;
-    uint8 opExtraLevel3;
-    uint8 twoChan;
-    uint8 unk39;
-    uint8 unk40;
-    uint8 spacing1;
-    uint8 durationRandomness;
-    uint8 unk19;
-    uint8 unk18;
-    int8 unk20;
-    int8 unk21;
-    uint8 unk22;
-    uint16 offset;
-    uint8 tempoReset;
-    uint8 rawNote;
-    int8 unk16;
-  };
-
-  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);
-
-  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 adjustVolume (Channel & channel);
-
-  uint8 calculateOpLevel1 (Channel & channel);
-  uint8 calculateOpLevel2 (Channel & channel);
-
-  uint16 checkValue (int16 val)
-  {
-    if (val < 0)
-      val = 0;
-    else if (val > 0x3F)
-      val = 0x3F;
-    return val;
-  }
-
-  // The sound data has at least two lookup tables:
-  //
-  // * 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 *getInstrument (int instrumentId)
-  {
-    return _soundData + READ_LE_UINT16 (_soundData + 500 + 2 * instrumentId);
-  }
-
-  void setupPrograms ();
-  void executePrograms ();
-
-  struct ParserOpcode
-  {
-    typedef int (AdlibDriver::*POpcode) (uint8 * &dataptr, Channel & channel,
-                                         uint8 value);
-    POpcode function;
-    const char *name;
-  };
-
-  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);
-
-  // These variables have not yet been named, but some of them are partly
-  // known nevertheless:
-  //
-  // _unkValue1      - Unknown. Used for updating _unkValue2
-  // _unkValue2      - Unknown. Used for updating _unkValue4
-  // _unkValue3      - Unknown. Used for updating _unkValue2
-  // _unkValue4      - Unknown. Used for updating _unkValue5
-  // _unkValue5      - Unknown. Used for controlling updateCallback24().
-  // _unkValue6      - Unknown. Rhythm section volume?
-  // _unkValue7      - Unknown. Rhythm section volume?
-  // _unkValue8      - Unknown. Rhythm section volume?
-  // _unkValue9      - Unknown. Rhythm section volume?
-  // _unkValue10     - Unknown. Rhythm section volume?
-  // _unkValue11     - Unknown. Rhythm section volume?
-  // _unkValue12     - Unknown. Rhythm section volume?
-  // _unkValue13     - Unknown. Rhythm section volume?
-  // _unkValue14     - Unknown. Rhythm section volume?
-  // _unkValue15     - Unknown. Rhythm section volume?
-  // _unkValue16     - Unknown. Rhythm section volume?
-  // _unkValue17     - Unknown. Rhythm section volume?
-  // _unkValue18     - Unknown. Rhythm section volume?
-  // _unkValue19     - Unknown. Rhythm section volume?
-  // _unkValue20     - Unknown. Rhythm section volume?
-  // _unkTable[]     - Probably frequences for the 12-tone scale.
-  // _unkTable2[]    - Unknown. Currently only used by updateCallback46()
-  // _unkTable2_1[]  - One of the tables in _unkTable2[]
-  // _unkTable2_2[]  - One of the tables in _unkTable2[]
-  // _unkTable2_3[]  - One of the tables in _unkTable2[]
-
-  int32 _samplesPerCallback;
-  int32 _samplesPerCallbackRemainder;
-  int32 _samplesTillCallback;
-  int32 _samplesTillCallbackRemainder;
-
-  int _lastProcessed;
-  int8 _flagTrigger;
-  int _curChannel;
-  uint8 _soundTrigger;
-  int _soundsPlaying;
-
-  uint16 _rnd;
-
-  uint8 _unkValue1;
-  uint8 _unkValue2;
-  uint8 _unkValue3;
-  uint8 _unkValue4;
-  uint8 _unkValue5;
-  uint8 _unkValue6;
-  uint8 _unkValue7;
-  uint8 _unkValue8;
-  uint8 _unkValue9;
-  uint8 _unkValue10;
-  uint8 _unkValue11;
-  uint8 _unkValue12;
-  uint8 _unkValue13;
-  uint8 _unkValue14;
-  uint8 _unkValue15;
-  uint8 _unkValue16;
-  uint8 _unkValue17;
-  uint8 _unkValue18;
-  uint8 _unkValue19;
-  uint8 _unkValue20;
-
-  int _flags;
-
-  uint8 *_soundData;
-
-  uint8 _soundIdTable[0x10];
-  Channel _channels[10];
-
-  uint8 _vibratoAndAMDepthBits;
-  uint8 _rhythmSectionBits;
-
-  uint8 _curRegOffset;
-  uint8 _tempo;
-
-  const uint8 *_tablePtr1;
-  const uint8 *_tablePtr2;
-
-  static const uint8 _regOffset[];
-  static const uint16 _unkTable[];
-  static const uint8 *_unkTable2[];
-  static const uint8 _unkTable2_1[];
-  static const uint8 _unkTable2_2[];
-  static const uint8 _unkTable2_3[];
-  static const uint8 _unkTables[][32];
-
-  Copl *opl;
-};
-
-AdlibDriver::AdlibDriver (Copl * newopl):opl (newopl)
-{
-  setupOpcodeList ();
-  setupParserOpcodeTable ();
-
-  //    _mixer = mixer;
-
-  _flags = 0;
-  //    _adlib = makeAdlibOPL(getRate());
-  //    assert(_adlib);
-
-  memset (_channels, 0, sizeof (_channels));
-  _soundData = 0;
-
-  _vibratoAndAMDepthBits = _curRegOffset = 0;
-
-  _lastProcessed = _flagTrigger = _curChannel = _rhythmSectionBits = 0;
-  _soundsPlaying = 0;
-  _rnd = 0x1234;
-
-  _tempo = 0;
-  _soundTrigger = 0;
-
-  _unkValue3 = 0xFF;
-  _unkValue1 = _unkValue2 = _unkValue4 = _unkValue5 = 0;
-  _unkValue6 = _unkValue7 = _unkValue8 = _unkValue9 = _unkValue10 = 0;
-  _unkValue11 = _unkValue12 = _unkValue13 = _unkValue14 = _unkValue15 =
-    _unkValue16 = _unkValue17 = _unkValue18 = _unkValue19 = _unkValue20 = 0;
-
-  _tablePtr1 = _tablePtr2 = 0;
-
-  //    _mixer->setupPremix(this);
-
-  //    _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
-  //    _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
-  _samplesTillCallback = 0;
-  _samplesTillCallbackRemainder = 0;
-}
-
-AdlibDriver::~AdlibDriver ()
-{
-  //    _mixer->setupPremix(0);
-  //    OPLDestroy(_adlib);
-  //    _adlib = 0;
-}
-
-int
-AdlibDriver::callback (int opcode, ...)
-{
-  //    lock();
-  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);
-
-  va_list 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)
-{
-  return 0x100;
-}
-
-int
-AdlibDriver::snd_ret0x1983 (va_list & list)
-{
-  return 0x1983;
-}
-
-int
-AdlibDriver::snd_initDriver (va_list & list)
-{
-  _lastProcessed = _soundsPlaying = 0;
-  resetAdlibState ();
-  return 0;
-}
-
-int
-AdlibDriver::snd_deinitDriver (va_list & list)
-{
-  resetAdlibState ();
-  return 0;
-}
-
-int
-AdlibDriver::snd_setSoundData (va_list & list)
-{
-  if (_soundData)
-  {
-    delete[]_soundData;
-    _soundData = 0;
-  }
-  _soundData = va_arg (list, uint8 *);
-  return 0;
-}
-
-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);
-  _flags |= 8;
-  _flagTrigger = 1;
-
-  uint8 *ptr = getProgram (songId);
-  uint8 chan = *ptr;
-
-  if ((songId << 1) != 0)
-  {
-    if (chan == 9)
-    {
-      if (_flags & 2)
-        return 0;
-    }
-    else
-    {
-      if (_flags & 1)
-        return 0;
-    }
-  }
-
-  _soundIdTable[_soundsPlaying++] = songId;
-  _soundsPlaying &= 0x0F;
-
-  return 0;
-}
-
-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 loop = value;
-  if (value < 0)
-  {
-    value = 0;
-    loop = 9;
-  }
-  loop -= value;
-  ++loop;
-
-  while (loop--)
-  {
-    _curChannel = value;
-    Channel & channel = _channels[_curChannel];
-    channel.priority = 0;
-    channel.dataptr = 0;
-    if (value != 9)
-    {
-      noteOff (channel);
-    }
-    ++value;
-  }
-
-  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;
-  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;
-  uint8 oldValue = *ptr;
-  *ptr = (uint8) c;
-  return oldValue;
-}
-
-int
-AdlibDriver::snd_getSoundTrigger (va_list & list)
-{
-  return _soundTrigger;
-}
-
-int
-AdlibDriver::snd_unkOpcode4 (va_list & list)
-{
-  warning ("unimplemented snd_unkOpcode4");
-  return 0;
-}
-
-int
-AdlibDriver::snd_dummy (va_list & list)
-{
-  return 0;
-}
-
-int
-AdlibDriver::snd_getNullvar4 (va_list & list)
-{
-  warning ("unimplemented snd_getNullvar4");
-  return 0;
-}
-
-int
-AdlibDriver::snd_setNullvar3 (va_list & list)
-{
-  warning ("unimplemented snd_setNullvar3");
-  return 0;
-}
-
-int
-AdlibDriver::snd_setFlag (va_list & list)
-{
-  int oldFlags = _flags;
-  _flags |= va_arg (list, int);
-  return oldFlags;
-}
-
-int
-AdlibDriver::snd_clearFlag (va_list & list)
-{
-  int oldFlags = _flags;
-  _flags &= ~(va_arg (list, int));
-  return oldFlags;
-}
-
-// timer callback
-
-void
-AdlibDriver::callback ()
-{
-  //    lock();
-  --_flagTrigger;
-  if (_flagTrigger < 0)
-    _flags &= ~8;
-  setupPrograms ();
-  executePrograms ();
-
-  uint8 temp = _unkValue3;
-  _unkValue3 += _tempo;
-  if (_unkValue3 < temp)
-  {
-    if (!(--_unkValue2))
-    {
-      _unkValue2 = _unkValue1;
-      ++_unkValue4;
-    }
-  }
-  //    unlock();
-}
-
-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];
-
-    if (priority >= channel.priority)
-    {
-      initChannel (channel);
-      channel.priority = priority;
-      channel.dataptr = ptr;
-      channel.tempo = 0xFF;
-      channel.position = 0xFF;
-      channel.duration = 1;
-      unkOutput2 (chan);
-    }
-
-    ++_lastProcessed;
-    _lastProcessed &= 0x0F;
-  }
-}
-
-// A few words on opcode parsing and timing:
-//
-// First of all, We simulate a timer callback 72 times per second. Each timeout
-// we update each channel that has something to play.
-//
-// Each channel has its own individual tempo, which is added to its position.
-// This will frequently cause the position to "wrap around" but that is
-// intentional. In fact, it's the signal to go ahead and do more stuff with
-// that channel.
-//
-// Each channel also has a duration, indicating how much time is left on the
-// its current task. This duration is decreased by one. As long as it still has
-// not reached zero, the only thing that can happen is that the note is turned
-// off depending on manual or automatic note spacing. Once the duration reaches
-// zero, a new set of musical opcodes are executed.
-//
-// An opcode is one byte, followed by a variable number of parameters. Since
-// most opcodes have at least one one-byte parameter, we read that as well. Any
-// opcode that doesn't have that one parameter is responsible for moving the
-// data pointer back again.
-//
-// If the most significant bit of the opcode is 1, it's a function; call it.
-// The opcode functions return either 0 (continue), 1 (stop) or 2 (stop, and do
-// not run the effects callbacks).
-//
-// If the most significant bit of the opcode is 0, it's a note, and the first
-// parameter is its duration. (There are cases where the duration is modified
-// but that's an exception.) The note opcode is assumed to return 1, and is the
-// last opcode unless its duration is zero.
-//
-// Finally, most of the times that the callback is called, it will invoke the
-// 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 ()
-{
-  // 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)
-  {
-    int result = 1;
-
-    if (!_channels[_curChannel].dataptr)
-    {
-      continue;
-    }
-
-    Channel & channel = _channels[_curChannel];
-    _curRegOffset = _regOffset[_curChannel];
-
-    if (channel.tempoReset)
-    {
-      channel.tempo = _tempo;
-    }
-
-    uint8 backup = channel.position;
-    channel.position += channel.tempo;
-    if (channel.position < backup)
-    {
-      if (--channel.duration)
-      {
-        if (channel.duration == channel.spacing2)
-          noteOff (channel);
-        if (channel.duration == channel.spacing1 && _curChannel != 9)
-          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
-        // on a copy of the data pointer.
-        //
-        // This fixes a subtle music bug where the
-        // wrong music would play when getting the
-        // quill in Kyra 1.
-        uint8 *dataptr = channel.dataptr;
-        while (dataptr)
-        {
-          uint8 opcode = *dataptr++;
-          uint8 param = *dataptr++;
-
-          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);
-            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)
-            {
-              channel.dataptr = dataptr;
-              break;
-            }
-          }
-        }
-      }
-    }
-
-    if (result == 1)
-    {
-      if (channel.primaryEffect)
-        (this->*(channel.primaryEffect)) (channel);
-      if (channel.secondaryEffect)
-        (this->*(channel.secondaryEffect)) (channel);
-    }
-  }
-}
-
-//
-
-void
-AdlibDriver::resetAdlibState ()
-{
-  debugC (9, kDebugLevelSound, "resetAdlibState()");
-  _rnd = 0x1234;
-
-  // Authorize the control of the waveforms
-  writeOPL (0x01, 0x20);
-
-  // Select FM music mode
-  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);
-
-  int loop = 10;
-  while (loop--)
-  {
-    if (loop != 9)
-    {
-      // Silence the channel
-      writeOPL (0x40 + _regOffset[loop], 0x3F);
-      writeOPL (0x43 + _regOffset[loop], 0x3F);
-    }
-    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::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;
-  // normally here are nullfuncs but we set 0 for now
-  channel.primaryEffect = 0;
-  channel.secondaryEffect = 0;
-  channel.spacing1 = 1;
-}
-
-void
-AdlibDriver::noteOff (Channel & channel)
-{
-  debugC (9, kDebugLevelSound, "noteOff(%lu)", (long) (&channel - _channels));
-
-  // The control channel has no corresponding Adlib channel
-
-  if (_curChannel >= 9)
-    return;
-
-  // When the rhythm section is enabled, channels 6, 7 and 8 are special.
-
-  if (_rhythmSectionBits && _curChannel >= 6)
-    return;
-
-  // This means the "Key On" bit will always be 0
-  channel.regBx &= 0xDF;
-
-  // Octave / F-Number / Key-On
-  writeOPL (0xB0 + _curChannel, channel.regBx);
-}
-
-void
-AdlibDriver::unkOutput2 (uint8 chan)
-{
-  debugC (9, kDebugLevelSound, "unkOutput2(%d)", chan);
-
-  // The control channel has no corresponding Adlib channel
-
-  if (chan >= 9)
-    return;
-
-  // I believe this has to do with channels 6, 7, and 8 being special
-  // when Adlib's rhythm section is enabled.
-
-  if (_rhythmSectionBits && chan >= 6)
-    return;
-
-  uint8 offset = _regOffset[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 (0x80 + offset, 0xFF);
-  writeOPL (0x83 + offset, 0xFF);
-
-  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 -
-  // including the two most significant frequency bit, and the octave -
-  // set to zero.
-  //
-  // This is very strange behaviour, and causes problems with the ancient
-  // FMOPL code we borrowed from AdPlug. I've added a workaround. See
-  // fmopl.cpp for more details.
-  //
-  // More recent versions of the MAME FMOPL don't seem to have this
-  // problem, but cannot currently be used because of licensing and
-  // performance issues.
-  //
-  // Ken Silverman's Adlib emulator (which can be found on his Web page -
-  // 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);
-}
-
-// 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 ()
-{
-  _rnd += 0x9248;
-  uint16 lowBits = _rnd & 7;
-  _rnd >>= 3;
-  _rnd |= (lowBits << 13);
-  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);
-    return;
-  }
-  if (channel.fractionalSpacing)
-  {
-    channel.spacing2 = (duration >> 3) * channel.fractionalSpacing;
-  }
-  channel.duration = duration;
-}
-
-// 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));
-
-  channel.rawNote = rawNote;
-
-  int8 note = (rawNote & 0x0F) + channel.baseNote;
-  int8 octave = ((rawNote + channel.baseOctave) >> 4) & 0x0F;
-
-  // There are only twelve notes. If we go outside that, we have to
-  // adjust the note and octave.
-
-  if (note >= 12)
-  {
-    note -= 12;
-    octave++;
-  }
-  else if (note < 0)
-  {
-    note += 12;
-    octave--;
-  }
-
-  // The calculation of frequency looks quite different from the original
-  // disassembly at a first glance, but when you consider that the
-  // largest possible value would be 0x0246 + 0xFF + 0x47 (and that's if
-  // baseFreq is unsigned), freq is still a 10-bit value, just as it
-  // should be to fit in the Ax and Bx registers.
-  //
-  // If it were larger than that, it could have overflowed into the
-  // octave bits, and that could possibly have been used in some sound.
-  // But as it is now, I can't see any way it would happen.
-
-  uint16 freq = _unkTable[note] + channel.baseFreq;
-
-  // When called from callback 41, the behaviour is slightly different:
-  // We adjust the frequency, even when channel.unk16 is 0.
-
-  if (channel.unk16 || flag)
-  {
-    const uint8 *table;
-
-    if (channel.unk16 >= 0)
-    {
-      table = _unkTables[(channel.rawNote & 0x0F) + 2];
-      freq += table[channel.unk16];
-    }
-    else
-    {
-      table = _unkTables[channel.rawNote & 0x0F];
-      freq -= table[-channel.unk16];
-    }
-  }
-
-  channel.regAx = freq & 0xFF;
-  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);
-}
-
-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++);
-
-  uint8 temp = *dataptr++;
-
-  // Feedback / Algorithm
-
-  // 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);
-
-  // The algorithm bit. I don't pretend to understand this fully, but
-  // "If set to 0, operator 1 modulates operator 2. In this case,
-  // operator 2 is the only one producing sound. If set to 1, both
-  // operators produce sound directly. Complex sounds are more easily
-  // created if the algorithm is set to 0."
-
-  channel.twoChan = temp & 1;
-
-  // Waveform Select
-  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));
-
-  // Attack Rate / Decay Rate
-  writeOPL (0x60 + regOffset, *dataptr++);
-  writeOPL (0x63 + regOffset, *dataptr++);
-
-  // Sustain Level / Release Rate
-  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));
-
-  // The "note on" bit is set, and the current note is played.
-
-  channel.regBx |= 0x20;
-  writeOPL (0xB0 + _curChannel, channel.regBx);
-
-  int8 shift = 9 - channel.unk33;
-  uint16 temp = channel.regAx | (channel.regBx << 8);
-  channel.unk37 = ((temp & 0x3FF) >> shift) & 0xFF;
-  channel.unk38 = channel.unk36;
-}
-
-void
-AdlibDriver::adjustVolume (Channel & channel)
-{
-  debugC (9, kDebugLevelSound, "adjustVolume(%lu)",
-          (long) (&channel - _channels));
-  // Level Key Scaling / Total Level
-
-  writeOPL (0x43 + _regOffset[_curChannel], calculateOpLevel2 (channel));
-  if (channel.twoChan)
-    writeOPL (0x40 + _regOffset[_curChannel], calculateOpLevel1 (channel));
-}
-
-// This is presumably only used for some sound effects, e.g. Malcolm blowing up
-// the trees in the intro (but not the effect where he "booby-traps" the big
-// tree) and turning Kallak to stone. Related functions and variables:
-//
-// update_setupPrimaryEffect1()
-//    - Initialises unk29, unk30 and unk31
-//    - unk29 is not further modified
-//    - unk30 is not further modified, except by update_removePrimaryEffect1()
-//
-// update_removePrimaryEffect1()
-//    - Deinitialises unk30
-//
-// unk29 - determines how often the notes are played
-// 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);
-  uint8 temp = channel.unk31;
-  channel.unk31 += channel.unk29;
-  if (channel.unk31 >= temp)
-    return;
-
-  // Initialise unk1 to the current frequency
-  uint16 unk1 = ((channel.regBx & 3) << 8) | channel.regAx;
-
-  // This is presumably to shift the "note on" bit so far to the left
-  // 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;
-
-  if (unk3 >= 0)
-  {
-    unk1 += unk3;
-    if (unk1 >= 734)
-    {
-      // The new frequency is too high. Shift it down and go
-      // up one octave.
-      unk1 >>= 1;
-      if (!(unk1 & 0x3FF))
-        ++unk1;
-      unk2 = (unk2 & 0xFF00) | ((unk2 + 4) & 0xFF);
-      unk2 &= 0xFF1C;
-    }
-  }
-  else
-  {
-    unk1 += unk3;
-    if (unk1 < 388)
-    {
-      // The new frequency is too low. Shift it up and go
-      // down one octave.
-      unk1 <<= 1;
-      if (!(unk1 & 0x3FF))
-        --unk1;
-      unk2 = (unk2 & 0xFF00) | ((unk2 - 4) & 0xFF);
-      unk2 &= 0xFF1C;
-    }
-  }
-
-  // Make sure that the new frequency is still a 10-bit value.
-  unk1 &= 0x3FF;
-
-  writeOPL (0xA0 + _curChannel, unk1 & 0xFF);
-  channel.regAx = unk1 & 0xFF;
-
-  // Shift down the "note on" bit again.
-  uint8 value = unk1 >> 8;
-  value |= (unk2 >> 8) & 0xFF;
-  value |= unk2 & 0xFF;
-
-  writeOPL (0xB0 + _curChannel, value);
-  channel.regBx = value;
-}
-
-// This is presumably only used for some sound effects, e.g. Malcolm entering
-// and leaving Kallak's hut. Related functions and variables:
-//
-// update_setupPrimaryEffect2()
-//    - Initialises unk32, unk33, unk34, unk35 and unk36
-//    - unk32 is not further modified
-//    - unk33 is not further modified
-//    - unk34 is a countdown that gets reinitialised to unk35 on zero
-//    - unk35 is based on unk34 and not further modified
-//    - unk36 is not further modified
-//
-// noteOn()
-//    - Plays the current note
-//    - Updates unk37 with a new (lower?) frequency
-//    - Copies unk36 to unk38. The unk38 variable is a countdown.
-//
-// unk32 - determines how often the notes are played
-// unk33 - modifies the frequency
-// unk34 - countdown, updates frequency on zero
-// unk35 - initialiser for unk34 countdown
-// unk36 - initialiser for unk38 countdown
-// unk37 - frequency
-// unk38 - countdown, begins playing on zero
-// unk41 - determines how often the notes are played
-//
-// 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)
-  {
-    --channel.unk38;
-    return;
-  }
-
-  uint8 temp = channel.unk41;
-  channel.unk41 += channel.unk32;
-  if (channel.unk41 < temp)
-  {
-    uint16 unk1 = channel.unk37;
-    if (!(--channel.unk34))
-    {
-      unk1 ^= 0xFFFF;
-      ++unk1;
-      channel.unk37 = unk1;
-      channel.unk34 = channel.unk35;
-    }
-
-    uint16 unk2 = (channel.regAx | (channel.regBx << 8)) & 0x3FF;
-    unk2 += unk1;
-
-    channel.regAx = unk2 & 0xFF;
-    channel.regBx = (channel.regBx & 0xFC) | (unk2 >> 8);
-
-    // Octave / F-Number / Key-On
-    writeOPL (0xA0 + _curChannel, channel.regAx);
-    writeOPL (0xB0 + _curChannel, channel.regBx);
-  }
-}
-
-// I don't know where this is used. The same operation is performed several
-// times on the current channel, using a chunk of the _soundData[] buffer for
-// parameters. The parameters are used starting at the end of the chunk.
-//
-// Since we use _curRegOffset to specify the final register, it's quite
-// unlikely that this function is ever used to play notes. It's probably only
-// used to modify the sound. Another thing that supports this idea is that it
-// can be combined with any of the effects callbacks above.
-//
-// Related functions and variables:
-//
-// update_setupSecondaryEffect1()
-//    - Initialies unk18, unk19, unk20, unk21, unk22 and offset
-//    - unk19 is not further modified
-//    - unk20 is not further modified
-//    - unk22 is not further modified
-//    - offset is not further modified
-//
-// unk18 -  determines how often the operation is performed
-// unk19 -  determines how often the operation is performed
-// unk20 -  the start index into the data chunk
-// unk21 -  the current index into the data chunk
-// 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);
-  uint8 temp = channel.unk18;
-  channel.unk18 += channel.unk19;
-  if (channel.unk18 < temp)
-  {
-    if (--channel.unk21 < 0)
-    {
-      channel.unk21 = channel.unk20;
-    }
-    writeOPL (channel.unk22 + _curRegOffset,
-              _soundData[channel.offset + channel.unk21]);
-  }
-}
-
-uint8
-AdlibDriver::calculateOpLevel1 (Channel & channel)
-{
-  int8 value = channel.opLevel1 & 0x3F;
-
-  if (channel.twoChan)
-  {
-    value += channel.opExtraLevel1;
-    value += channel.opExtraLevel2;
-    value += channel.opExtraLevel3;
-  }
-
-  // Preserve the scaling level bits from opLevel1
-
-  return checkValue (value) | (channel.opLevel1 & 0xC0);
-}
-
-uint8
-AdlibDriver::calculateOpLevel2 (Channel & channel)
-{
-  int8 value = channel.opLevel2 & 0x3F;
-
-  value += channel.opExtraLevel1;
-  value += channel.opExtraLevel2;
-  value += channel.opExtraLevel3;
-
-  // Preserve the scaling level bits from opLevel2
-
-  return checkValue (value) | (channel.opLevel2 & 0xC0);
-}
-
-// parser opcodes
-
-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)
-{
-  ++dataptr;
-  if (--channel.repeatCounter)
-  {
-    int16 add = READ_LE_UINT16 (dataptr - 2);
-    dataptr += add;
-  }
-  return 0;
-}
-
-int
-AdlibDriver::update_setupProgram (uint8 * &dataptr, Channel & channel,
-                                  uint8 value)
-{
-  if (value == 0xFF)
-    return 0;
-
-  uint8 *ptr = getProgram (value);
-  uint8 chan = *ptr++;
-  uint8 priority = *ptr++;
-
-  Channel & channel2 = _channels[chan];
-
-  if (priority >= channel2.priority)
-  {
-    _flagTrigger = 1;
-    _flags |= 8;
-    initChannel (channel2);
-    channel2.priority = priority;
-    channel2.dataptr = ptr;
-    channel2.tempo = 0xFF;
-    channel2.position = 0xFF;
-    channel2.duration = 1;
-    unkOutput2 (chan);
-  }
-
-  return 0;
-}
-
-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)
-{
-  --dataptr;
-  int16 add = READ_LE_UINT16 (dataptr);
-  dataptr += 2;
-  dataptr += add;
-  return 0;
-}
-
-int
-AdlibDriver::update_jumpToSubroutine (uint8 * &dataptr, Channel & channel,
-                                      uint8 value)
-{
-  --dataptr;
-  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)
-{
-  dataptr = channel.dataptrStack[--channel.dataptrStackPos];
-  return 0;
-}
-
-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)
-{
-  channel.priority = 0;
-  if (_curChannel != 9)
-  {
-    noteOff (channel);
-  }
-  dataptr = 0;
-  return 2;
-}
-
-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++);
-  return 0;
-}
-
-int
-AdlibDriver::update_setupNoteAndDuration (uint8 * &dataptr, Channel & channel,
-                                          uint8 value)
-{
-  setupNote (value, channel);
-  value = *dataptr++;
-  setupDuration (value, channel);
-  return (value != 0);
-}
-
-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)
-{
-  channel.unk18 = value;
-  channel.unk19 = value;
-  channel.unk20 = channel.unk21 = *dataptr++;
-  channel.unk22 = *dataptr++;
-  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];
-  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);
-  uint8 chan = *ptr;
-
-  if (!_channels[chan].dataptr)
-  {
-    return 0;
-  }
-
-  dataptr -= 2;
-  return 2;
-}
-
-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)
-{
-  channel.unk29 = value;
-  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)
-{
-  --dataptr;
-  channel.primaryEffect = 0;
-  channel.unk30 = 0;
-  return 0;
-}
-
-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)
-{
-  channel.unk32 = value;
-  channel.unk33 = *dataptr++;
-  uint8 temp = *dataptr++;
-  channel.unk34 = temp + 1;
-  channel.unk35 = temp << 1;
-  channel.unk36 = *dataptr++;
-  channel.primaryEffect = &AdlibDriver::primaryEffect2;
-  return 0;
-}
-
-int
-AdlibDriver::update_setPriority (uint8 * &dataptr, Channel & channel,
-                                 uint8 value)
-{
-  channel.priority = value;
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback23 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  value >>= 1;
-  _unkValue1 = _unkValue2 = value;
-  _unkValue3 = 0xFF;
-  _unkValue4 = _unkValue5 = 0;
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback24 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  if (_unkValue5)
-  {
-    if (_unkValue4 & value)
-    {
-      _unkValue5 = 0;
-      return 0;
-    }
-  }
-
-  if (!(value & _unkValue4))
-  {
-    ++_unkValue5;
-  }
-
-  dataptr -= 2;
-  channel.duration = 1;
-  return 2;
-}
-
-int
-AdlibDriver::update_setExtraLevel1 (uint8 * &dataptr, Channel & channel,
-                                    uint8 value)
-{
-  channel.opExtraLevel1 = value;
-  adjustVolume (channel);
-  return 0;
-}
-
-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);
-  return (value != 0);
-}
-
-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)
-{
-  _tempo = value;
-  return 0;
-}
-
-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)
-{
-  channel.tempo = value;
-  return 0;
-}
-
-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 channelBackUp = _curChannel;
-
-  _curChannel = value;
-  Channel & channel2 = _channels[value];
-  channel2.opExtraLevel2 = *dataptr++;
-  adjustVolume (channel2);
-
-  _curChannel = channelBackUp;
-  return 0;
-}
-
-int
-AdlibDriver::update_changeExtraLevel2 (uint8 * &dataptr, Channel & channel,
-                                       uint8 value)
-{
-  int channelBackUp = _curChannel;
-
-  _curChannel = value;
-  Channel & channel2 = _channels[value];
-  channel2.opExtraLevel2 += *dataptr++;
-  adjustVolume (channel2);
-
-  _curChannel = channelBackUp;
-  return 0;
-}
-
-// 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)
-{
-  if (value & 1)
-    _vibratoAndAMDepthBits |= 0x80;
-  else
-    _vibratoAndAMDepthBits &= 0x7F;
-
-  writeOPL (0xBD, _vibratoAndAMDepthBits);
-  return 0;
-}
-
-int
-AdlibDriver::update_setVibratoDepth (uint8 * &dataptr, Channel & channel,
-                                     uint8 value)
-{
-  if (value & 1)
-    _vibratoAndAMDepthBits |= 0x40;
-  else
-    _vibratoAndAMDepthBits &= 0xBF;
-
-  writeOPL (0xBD, _vibratoAndAMDepthBits);
-  return 0;
-}
-
-int
-AdlibDriver::update_changeExtraLevel1 (uint8 * &dataptr, Channel & channel,
-                                       uint8 value)
-{
-  channel.opExtraLevel1 += value;
-  adjustVolume (channel);
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback38 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  int channelBackUp = _curChannel;
-
-  _curChannel = value;
-  Channel & channel2 = _channels[value];
-  channel2.duration = channel2.priority = 0;
-  channel2.dataptr = 0;
-  channel2.opExtraLevel2 = 0;
-
-  if (value != 9)
-  {
-    uint8 outValue = _regOffset[value];
-
-    // Feedback strength / Connection type
-    writeOPL (0xC0 + _curChannel, 0x00);
-
-    // Key scaling level / Operator output level
-    writeOPL (0x43 + outValue, 0x3F);
-
-    // Sustain Level / Release Rate
-    writeOPL (0x83 + outValue, 0xFF);
-
-    // Key On / Octave / Frequency
-    writeOPL (0xB0 + _curChannel, 0x00);
-  }
-
-  _curChannel = channelBackUp;
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback39 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  uint16 unk = *dataptr++;
-  unk |= value << 8;
-  unk &= getRandomNr ();
-
-  uint16 unk2 = ((channel.regBx & 0x1F) << 8) | channel.regAx;
-  unk2 += unk;
-  unk2 |= ((channel.regBx & 0x20) << 8);
-
-  // Frequency
-  writeOPL (0xA0 + _curChannel, unk2 & 0xFF);
-
-  // Key On / Octave / Frequency
-  writeOPL (0xB0 + _curChannel, (unk2 & 0xFF00) >> 8);
-
-  return 0;
-}
-
-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)
-{
-  channel.unk16 = value;
-  setupNote (channel.rawNote, channel, true);
-  return 0;
-}
-
-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)
-{
-  --dataptr;
-  return 0;
-}
-
-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;
-
-  if (tempo <= 0)
-    tempo = 1;
-  else if (tempo > 255)
-    tempo = 255;
-
-  channel.tempo = tempo;
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback46 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  uint8 entry = *dataptr++;
-  _tablePtr1 = _unkTable2[entry++];
-  _tablePtr2 = _unkTable2[entry];
-  if (value == 2)
-  {
-    // Frequency
-    writeOPL (0xA0, _tablePtr2[0]);
-  }
-  return 0;
-}
-
-// 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)
-{
-  --dataptr;
-  return 0;
-}
-
-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);
-  _unkValue6 = channel.opLevel2;
-
-  _curChannel = 7;
-  _curRegOffset = _regOffset[7];
-
-  setupInstrument (_curRegOffset, getInstrument (*dataptr++), channel);
-  _unkValue7 = channel.opLevel1;
-  _unkValue8 = channel.opLevel2;
-
-  _curChannel = 8;
-  _curRegOffset = _regOffset[8];
-
-  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++);
-
-  _channels[7].regBx = *dataptr++ & 0x2F;
-  writeOPL (0xB7, _channels[7].regBx);
-  writeOPL (0xA7, *dataptr++);
-
-  _channels[8].regBx = *dataptr++ & 0x2F;
-  writeOPL (0xB8, _channels[8].regBx);
-  writeOPL (0xA8, *dataptr++);
-
-  _rhythmSectionBits = 0x20;
-
-  _curRegOffset = regOffsetBackUp;
-  _curChannel = channelBackUp;
-  return 0;
-}
-
-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);
-
-  // ...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
-  // useful the cleverness above is. We could perhaps simply turn off all
-  // the rhythm instruments instead.
-
-  _rhythmSectionBits |= value;
-
-  writeOPL (0xBD, _vibratoAndAMDepthBits | 0x20 | _rhythmSectionBits);
-  return 0;
-}
-
-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);
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback51 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  uint8 value2 = *dataptr++;
-
-  if (value & 1)
-  {
-    _unkValue12 = value2;
-
-    // Channel 7, op1: Level Key Scaling / Total Level
-    writeOPL (0x51,
-              checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12));
-  }
-
-  if (value & 2)
-  {
-    _unkValue14 = value2;
-
-    // Channel 8, op2: Level Key Scaling / Total Level
-    writeOPL (0x55,
-              checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14));
-  }
-
-  if (value & 4)
-  {
-    _unkValue15 = value2;
-
-    // Channel 8, op1: Level Key Scaling / Total Level
-    writeOPL (0x52,
-              checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15));
-  }
-
-  if (value & 8)
-  {
-    _unkValue18 = value2;
-
-    // Channel 7, op2: Level Key Scaling / Total Level
-    writeOPL (0x54,
-              checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18));
-  }
-
-  if (value & 16)
-  {
-    _unkValue20 = value2;
-
-    // Channel 6, op2: Level Key Scaling / Total Level
-    writeOPL (0x53,
-              checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20));
-  }
-
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback52 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  uint8 value2 = *dataptr++;
-
-  if (value & 1)
-  {
-    _unkValue11 =
-      checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12);
-
-    // Channel 7, op1: Level Key Scaling / Total Level
-    writeOPL (0x51, _unkValue11);
-  }
-
-  if (value & 2)
-  {
-    _unkValue13 =
-      checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14);
-
-    // Channel 8, op2: Level Key Scaling / Total Level
-    writeOPL (0x55, _unkValue13);
-  }
-
-  if (value & 4)
-  {
-    _unkValue16 =
-      checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15);
-
-    // Channel 8, op1: Level Key Scaling / Total Level
-    writeOPL (0x52, _unkValue16);
-  }
-
-  if (value & 8)
-  {
-    _unkValue17 =
-      checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18);
-
-    // Channel 7, op2: Level Key Scaling / Total Level
-    writeOPL (0x54, _unkValue17);
-  }
-
-  if (value & 16)
-  {
-    _unkValue19 =
-      checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20);
-
-    // Channel 6, op2: Level Key Scaling / Total Level
-    writeOPL (0x53, _unkValue19);
-  }
-
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback53 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  uint8 value2 = *dataptr++;
-
-  if (value & 1)
-  {
-    _unkValue11 = value2;
-
-    // Channel 7, op1: Level Key Scaling / Total Level
-    writeOPL (0x51, checkValue (value2 + _unkValue7 + _unkValue12));
-  }
-
-  if (value & 2)
-  {
-    _unkValue13 = value2;
-
-    // Channel 8, op2: Level Key Scaling / Total Level
-    writeOPL (0x55, checkValue (value2 + _unkValue10 + _unkValue14));
-  }
-
-  if (value & 4)
-  {
-    _unkValue16 = value2;
-
-    // Channel 8, op1: Level Key Scaling / Total Level
-    writeOPL (0x52, checkValue (value2 + _unkValue9 + _unkValue15));
-  }
-
-  if (value & 8)
-  {
-    _unkValue17 = value2;
-
-    // Channel 7, op2: Level Key Scaling / Total Level
-    writeOPL (0x54, checkValue (value2 + _unkValue8 + _unkValue18));
-  }
-
-  if (value & 16)
-  {
-    _unkValue19 = value2;
-
-    // Channel 6, op2: Level Key Scaling / Total Level
-    writeOPL (0x53, checkValue (value2 + _unkValue6 + _unkValue20));
-  }
-
-  return 0;
-}
-
-int
-AdlibDriver::update_setSoundTrigger (uint8 * &dataptr, Channel & channel,
-                                     uint8 value)
-{
-  _soundTrigger = value;
-  return 0;
-}
-
-int
-AdlibDriver::update_setTempoReset (uint8 * &dataptr, Channel & channel,
-                                   uint8 value)
-{
-  channel.tempoReset = value;
-  return 0;
-}
-
-int
-AdlibDriver::updateCallback56 (uint8 * &dataptr, Channel & channel,
-                               uint8 value)
-{
-  channel.unk39 = value;
-  channel.unk40 = *dataptr++;
-  return 0;
-}
-
-// static res
-
-#define COMMAND(x) { &AdlibDriver::x, #x }
-
-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)
-  };
-
-  _opcodeList = opcodeList;
-  _opcodesEntries = ARRAYSIZE (opcodeList);
-}
-
-void
-AdlibDriver::setupParserOpcodeTable ()
-{
-  static const ParserOpcode parserOpcodeTable[] = {
-    // 0
-    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),
-
-    // 8
-    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),
-
-    // 16
-    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),
-
-    // 24
-    COMMAND (update_stopChannel),
-    COMMAND (update_stopChannel),
-    COMMAND (update_setPriority),
-    COMMAND (update_stopChannel),
-
-    // 28
-    COMMAND (updateCallback23),
-    COMMAND (updateCallback24),
-    COMMAND (update_setExtraLevel1),
-    COMMAND (update_stopChannel),
-
-    // 32
-    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),
-
-    // 40
-    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),
-
-    // 48
-    COMMAND (update_changeExtraLevel1),
-    COMMAND (update_stopChannel),
-    COMMAND (update_stopChannel),
-    COMMAND (updateCallback38),
-
-    // 52
-    COMMAND (update_stopChannel),
-    COMMAND (updateCallback39),
-    COMMAND (update_removePrimaryEffect2),
-    COMMAND (update_stopChannel),
-
-    // 56
-    COMMAND (update_stopChannel),
-    COMMAND (updateCallback41),
-    COMMAND (update_resetToGlobalTempo),
-    COMMAND (update_nop1),
-
-    // 60
-    COMMAND (update_setDurationRandomness),
-    COMMAND (update_changeChannelTempo),
-    COMMAND (update_stopChannel),
-    COMMAND (updateCallback46),
-
-    // 64
-    COMMAND (update_nop2),
-    COMMAND (update_setupRhythmSection),
-    COMMAND (update_playRhythmSection),
-    COMMAND (update_removeRhythmSection),
-
-    // 68
-    COMMAND (updateCallback51),
-    COMMAND (updateCallback52),
-    COMMAND (updateCallback53),
-    COMMAND (update_setSoundTrigger),
-
-    // 72
-    COMMAND (update_setTempoReset),
-    COMMAND (updateCallback56),
-    COMMAND (update_stopChannel)
-  };
-
-  _parserOpcodeTable = 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[] = {
-  0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11,
-  0x12
-};
-
-// Given the size of this table, and the range of its values, it's probably the
-// 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[] = {
-  0x0134, 0x0147, 0x015A, 0x016F, 0x0184, 0x019C, 0x01B4, 0x01CE, 0x01E9,
-  0x0207, 0x0225, 0x0246
-};
-
-// 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[] = {
-  AdlibDriver::_unkTable2_1,
-  AdlibDriver::_unkTable2_2,
-  AdlibDriver::_unkTable2_1,
-  AdlibDriver::_unkTable2_2,
-  AdlibDriver::_unkTable2_3,
-  AdlibDriver::_unkTable2_2
-};
-
-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,
-  0x44, 0x44, 0x43, 0x43, 0x42, 0x42, 0x41, 0x41,
-  0x40, 0x40, 0x3F, 0x3F, 0x3E, 0x3E, 0x3D, 0x3D,
-  0x3C, 0x3C, 0x3B, 0x3B, 0x3A, 0x3A, 0x39, 0x39,
-  0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35,
-  0x34, 0x34, 0x33, 0x33, 0x32, 0x32, 0x31, 0x31,
-  0x30, 0x30, 0x2F, 0x2F, 0x2E, 0x2E, 0x2D, 0x2D,
-  0x2C, 0x2C, 0x2B, 0x2B, 0x2A, 0x2A, 0x29, 0x29,
-  0x28, 0x28, 0x27, 0x27, 0x26, 0x26, 0x25, 0x25,
-  0x24, 0x24, 0x23, 0x23, 0x22, 0x22, 0x21, 0x21,
-  0x20, 0x20, 0x1F, 0x1F, 0x1E, 0x1E, 0x1D, 0x1D,
-  0x1C, 0x1C, 0x1B, 0x1B, 0x1A, 0x1A, 0x19, 0x19,
-  0x18, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15,
-  0x14, 0x14, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11,
-  0x10, 0x10
-};
-
-// no don't ask me WHY this table exsits!
-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,
-  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
-  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
-  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
-  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-  0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
-  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-  0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x6F,
-  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
-  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-  0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
-};
-
-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,
-  0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36,
-  0x36, 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x33,
-  0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31, 0x31,
-  0x30, 0x30, 0x30, 0x2F, 0x2F, 0x2F, 0x2E, 0x2E,
-  0x2E, 0x2D, 0x2D, 0x2D, 0x2C, 0x2C, 0x2C, 0x2B,
-  0x2B, 0x2B, 0x2A, 0x2A, 0x2A, 0x29, 0x29, 0x29,
-  0x28, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26,
-  0x26, 0x25, 0x25, 0x25, 0x24, 0x24, 0x24, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21,
-  0x20, 0x20, 0x20, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E,
-  0x1E, 0x1D, 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1B,
-  0x1B, 0x1B, 0x1A, 0x1A, 0x1A, 0x19, 0x19, 0x19,
-  0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16, 0x16,
-  0x16, 0x15
-};
-
-// This table is used to modify the frequency of the notes, depending on the
-// note value and unk16. In theory, we could very well try to access memory
-// outside this table, but in reality that probably won't happen.
-//
-// 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] = {
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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},
-  // 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}
-};
-
-// #pragma mark -
-
-// 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[] = {
-  0, 4, 5, 3
-};
-
-const int
-  CadlPlayer::_kyra1NumSoundTriggers =
-ARRAYSIZE (CadlPlayer::_kyra1SoundTriggers);
-
-CadlPlayer::CadlPlayer (Copl * newopl):CPlayer (newopl), numsubsongs (0), _trackEntries (),
-_soundDataPtr (0)
-{
-  memset (_trackEntries, 0, sizeof (_trackEntries));
-  _driver = new AdlibDriver (newopl);
-  assert (_driver);
-
-  _sfxPlayingSound = -1;
-  //    _soundFileLoaded = "";
-
-  _soundTriggers = _kyra1SoundTriggers;
-  _numSoundTriggers = _kyra1NumSoundTriggers;
-
-  init ();
-}
-
-CadlPlayer::~CadlPlayer ()
-{
-  delete[]_soundDataPtr;
-  _soundDataPtr = 0;
-  delete _driver;
-  _driver = 0;
-}
-
-bool
-CadlPlayer::init ()
-{
-  _driver->callback (2);
-  _driver->callback (16, int (4));
-  return true;
-}
-
-void
-CadlPlayer::process ()
-{
-  uint8 trigger = _driver->callback (11);
-
-  if (trigger < _numSoundTriggers)
-  {
-    int soundId = _soundTriggers[trigger];
-
-    if (soundId)
-    {
-      playTrack (soundId);
-    }
-  }
-  else
-  {
-    warning ("Unknown sound trigger %d", trigger);
-    // TODO: At this point, we really want to clear the trigger...
-  }
-}
-
-// void CadlPlayer::setVolume(int volume) {
-// }
-
-// int CadlPlayer::getVolume() {
-//  return 0;
-// }
-
-// void CadlPlayer::loadMusicFile(const char *file) {
-//  loadSoundFile(file);
-// }
-
-void
-CadlPlayer::playTrack (uint8 track)
-{
-  play (track);
-}
-
-// void CadlPlayer::haltTrack() {
-//  unk1();
-//  unk2();
-//  //_engine->_system->delayMillis(3 * 60);
-// }
-
-void
-CadlPlayer::playSoundEffect (uint8_t track)
-{
-  play (track);
-}
-
-void
-CadlPlayer::play (uint8_t track)
-{
-  uint8 soundId = _trackEntries[track];
-  if ((int8) soundId == -1 || !_soundDataPtr)
-    return;
-  soundId &= 0xFF;
-  _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);
-  //    }
-  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));
-    _sfxPlayingSound = -1;
-  }
-
-  int chan = _driver->callback (9, soundId, int (0));
-
-  if (chan != 9)
-  {
-    _sfxPlayingSound = soundId;
-    _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.
-    //
-    // The extra level is part of the channels "total level", which
-    // is a six-bit value where larger values means softer volume.
-    //
-    // So what seems to be happening here is that sounds which are
-    // started by this function are given a slightly lower priority
-    // and a slightly higher (i.e. softer) extra level 3 than they
-    // would have if they were started from anywhere else. Strange.
-
-    int newVal = ((((-_sfxFourthByteOfSong) + 63) * 0xFF) >> 8) & 0xFF;
-    newVal = -newVal + 63;
-    _driver->callback (10, soundId, int (3), newVal);
-    newVal = ((_sfxPriority * 0xFF) >> 8) & 0xFF;
-    _driver->callback (10, soundId, int (1), newVal);
-  }
-
-  _driver->callback (6, soundId);
-}
-
-// void CadlPlayer::beginFadeOut() {
-//  playSoundEffect(1);
-// }
-
-bool
-CadlPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  std::string filename (vfs_get_filename (fd));
-
-  // file validation section
-  if (!f || !fp.extension (filename, ".adl"))
-  {
-    fp.close (f);
-    return false;
-  }
-
-  //    if (_soundFileLoaded == file)
-  //        return;
-
-  //    if (_soundDataPtr) {
-  //        haltTrack();
-  //    }
-
-  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;
-  //    }
-
-  unk2 ();
-  unk1 ();
-
-  file_size = fp.filesize (f);
-  file_data = new uint8[file_size];
-  f->readString ((char *) file_data, file_size);
-
-  _driver->callback (8, int (-1));
-  _soundDataPtr = 0;
-
-  uint8 *p = file_data;
-  memcpy (_trackEntries, p, 120 * sizeof (uint8));
-  p += 120;
-
-  int soundDataSize = file_size - 120;
-
-  _soundDataPtr = new uint8[soundDataSize];
-  assert (_soundDataPtr);
-
-  memcpy (_soundDataPtr, p, soundDataSize * sizeof (uint8));
-
-  delete[]file_data;
-  file_data = p = 0;
-  file_size = 0;
-
-  _driver->callback (4, _soundDataPtr);
-
-  //    _soundFileLoaded = file;
-
-  // find last subsong
-  for(int i = 199; i >= 0; i--)
-    if(_trackEntries[i] != 0xff) {
-      numsubsongs = i + 1;
-      break;
-    }
-  fp.close (f);
-  cursubsong = 2;
-  rewind();
-  return true;
-}
-
-void
-CadlPlayer::rewind (int subsong)
-{
-  if(subsong == -1) subsong = cursubsong;
-  opl->init ();
-  opl->write (1, 32);
-  playSoundEffect (subsong);
-  cursubsong = subsong;
-  update ();
-}
-
-unsigned int
-CadlPlayer::getsubsongs ()
-{
-  return numsubsongs;
-}
-
-bool
-CadlPlayer::update ()
-{
-  bool songend = true;
-
-//   if(_trackEntries[cursubsong] == 0xff)
-//     return false;
-
-  _driver->callback ();
-
-  for (int i = 0; i < 10; i++)
-    if (_driver->_channels[i].dataptr != NULL)
-      songend = false;
-
-  return !songend;
-}
-
-void
-CadlPlayer::unk1 ()
-{
-  playSoundEffect (0);
-  //_engine->_system->delayMillis(5 * 60);
-}
-
-void
-CadlPlayer::unk2 ()
-{
-  playSoundEffect (0);
-}
-
-CPlayer *
-CadlPlayer::factory (Copl * newopl)
-{
-  return new CadlPlayer (newopl);
-}
diff --git a/src/adplug/core/adl.h b/src/adplug/core/adl.h
index 083093814523..fc3b1f2dc54f 100644
--- a/src/adplug/core/adl.h
+++ b/src/adplug/core/adl.h
@@ -36,7 +36,7 @@ class CadlPlayer: public CPlayer
   CadlPlayer(Copl *newopl);
   ~CadlPlayer();
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong = -1);
 
diff --git a/src/adplug/core/adlibemu.c b/src/adplug/core/adlibemu.c
deleted file mode 100644
index 2b7d56196e06..000000000000
--- a/src/adplug/core/adlibemu.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * ADLIBEMU.C
- * 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
- */
-
-/*
-This file is a digital Adlib emulator for OPL2 and possibly OPL3
-
-Features that could be added in a future version:
-- Amplitude and Frequency Vibrato Bits (not hard, but a big speed hit)
-- Global Keyboard Split Number Bit (need to research this one some more)
-- 2nd Adlib chip for OPL3 (simply need to make my cell array bigger)
-- Advanced connection modes of OPL3 (Just need to add more "docell" cases)
-- L/R Stereo bits of OPL3 (Need adlibgetsample to return stereo)
-
-Features that aren't worth supporting:
-- Anything related to adlib timers&interrupts (Sorry - I always used IRQ0)
-- Composite sine wave mode (CSM) (Supported only on ancient cards)
-
-I'm not sure about a few things in my code:
-- Attack curve.  What function is this anyway?  I chose to use an order-3
-  polynomial to approximate but this doesn't seem right.
-- Attack/Decay/Release constants - my constants may not be exact
-- What should ADJUSTSPEED be?
-- Haven't verified that Global Keyboard Split Number Bit works yet
-- Some of the drums don't always sound right.  It's pretty hard to guess
-  the exact waveform of drums when you look at random data which is
-  slightly randomized due to digital ADC recording.
-- Adlib seems to have a lot more treble than my emulator does.  I'm not
-  sure if this is simply unfixable due to the sound blaster's different
-  filtering on FM and digital playback or if it's a serious bug in my
-  code.
-*/
-
-#include <math.h>
-#include <string.h>
-
-#if !defined(max) && !defined(__cplusplus)
-#define max(a,b)  (((a) > (b)) ? (a) : (b))
-#endif
-#if !defined(min) && !defined(__cplusplus)
-#define min(a,b)  (((a) < (b)) ? (a) : (b))
-#endif
-
-#define PI 3.141592653589793
-#define MAXCELLS 18
-#define WAVPREC 2048
-
-static float AMPSCALE=(8192.0);
-#define FRQSCALE (49716/512.0)
-
-//Constants for Ken's Awe32, on a PII-266 (Ken says: Use these for KSM's!)
-#define MODFACTOR 4.0      //How much of modulator cell goes into carrier
-#define MFBFACTOR 1.0      //How much feedback goes back into modulator
-#define ADJUSTSPEED 0.75   //0<=x<=1  Simulate finite rate of change of state
-
-//Constants for Ken's Awe64G, on a P-133
-//#define MODFACTOR 4.25   //How much of modulator cell goes into carrier
-//#define MFBFACTOR 0.5    //How much feedback goes back into modulator
-//#define ADJUSTSPEED 0.85 //0<=x<=1  Simulate finite rate of change of state
-
-typedef struct
-{
-    float val, t, tinc, vol, sustain, amp, mfb;
-    float a0, a1, a2, a3, decaymul, releasemul;
-    short *waveform;
-    long wavemask;
-    void (*cellfunc)(void *, float);
-    unsigned char flags, dum0, dum1, dum2;
-} celltype;
-
-static long numspeakers, bytespersample;
-static float recipsamp;
-static celltype cell[MAXCELLS];
-static signed short wavtable[WAVPREC*3];
-static float kslmul[4] = {0.0,0.5,0.25,1.0};
-static float frqmul[16] = {.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15}, nfrqmul[16];
-static unsigned char adlibreg[256], ksl[8][16];
-static unsigned char modulatorbase[9] = {0,1,2,8,9,10,16,17,18};
-static unsigned char odrumstat = 0;
-static unsigned char base2cell[22] = {0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8};
-
-float lvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on left speaker
-float rvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on right speaker
-long lplc[9] = {0,0,0,0,0,0,0,0,0};   //Samples to delay on left speaker
-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
-static float *rptr[9], *nrptr[9];
-static float rbuf[9][FIFOSIZ*2];
-static float snd[FIFOSIZ*2];
-
-#ifndef USING_ASM
-#define _inline
-#endif
-
-#ifdef USING_ASM
-static _inline void ftol (float f, long *a)
-{
-    _asm
-	{
-	    mov eax, a
-		fld f
-		fistp dword ptr [eax]
-		}
-}
-#else
-static void ftol(float f, long *a) {
-    *a=f;
-}
-#endif
-
-#define ctc ((celltype *)c)      //A rare attempt to make code easier to read!
-void docell4 (void *c, float modulator) { }
-void docell3 (void *c, float modulator)
-{
-    long i;
-
-    ftol(ctc->t+modulator,&i);
-    ctc->t += ctc->tinc;
-    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
-}
-void docell2 (void *c, float modulator)
-{
-    long i;
-
-    ftol(ctc->t+modulator,&i);
-
-    if ((long)ctc->amp <= 0x37800000)
-    {
-	ctc->amp = 0;
-	ctc->cellfunc = docell4;
-    }
-    ctc->amp *= ctc->releasemul;
-
-    ctc->t += ctc->tinc;
-    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
-}
-void docell1 (void *c, float modulator)
-{
-    long i;
-
-    ftol(ctc->t+modulator,&i);
-
-    if ((long)ctc->amp <= (long)ctc->sustain)
-    {
-	if (ctc->flags&32)
-	{
-	    ctc->amp = ctc->sustain;
-	    ctc->cellfunc = docell3;
-	}
-	else
-	    ctc->cellfunc = docell2;
-    }
-    else
-	ctc->amp *= ctc->decaymul;
-
-    ctc->t += ctc->tinc;
-    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
-}
-void docell0 (void *c, float modulator)
-{
-    long i;
-
-    ftol(ctc->t+modulator,&i);
-
-    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->t += ctc->tinc;
-    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
-}
-
-
-static long waveform[8] = {WAVPREC,WAVPREC>>1,WAVPREC,(WAVPREC*3)>>2,0,0,(WAVPREC*5)>>2,WAVPREC<<1};
-static long wavemask[8] = {WAVPREC-1,WAVPREC-1,(WAVPREC>>1)-1,(WAVPREC>>1)-1,WAVPREC-1,((WAVPREC*3)>>2)-1,WAVPREC>>1,WAVPREC-1};
-static long wavestart[8] = {0,WAVPREC>>1,0,WAVPREC>>2,0,0,0,WAVPREC>>3};
-static float attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744};
-static float decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608};
-void cellon (long i, long j, celltype *c, unsigned char iscarrier)
-{
-    long frn, oct, toff;
-    float f;
-
-    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
-    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
-    toff = (oct<<1) + ((frn>>9)&((frn>>8)|(((adlibreg[8]>>6)&1)^1)));
-    if (!(adlibreg[j+0x20]&16)) toff >>= 2;
-
-    f = pow(2.0,(adlibreg[j+0x60]>>4)+(toff>>2)-1)*attackconst[toff&3]*recipsamp;
-    c->a0 = .0377*f; c->a1 = 10.73*f+1; c->a2 = -17.57*f; c->a3 = 7.42*f;
-    f = -7.4493*decrelconst[toff&3]*recipsamp;
-    c->decaymul = pow(2.0,f*pow(2.0,(adlibreg[j+0x60]&15)+(toff>>2)));
-    c->releasemul = pow(2.0,f*pow(2.0,(adlibreg[j+0x80]&15)+(toff>>2)));
-    c->wavemask = wavemask[adlibreg[j+0xe0]&7];
-    c->waveform = &wavtable[waveform[adlibreg[j+0xe0]&7]];
-    if (!(adlibreg[1]&0x20)) c->waveform = &wavtable[WAVPREC];
-    c->t = wavestart[adlibreg[j+0xe0]&7];
-    c->flags = adlibreg[j+0x20];
-    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);
-    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;
-    if (!(adlibreg[i+0xc0]&14)) c->mfb = 0;
-    c->val = 0;
-}
-
-//This function (and bug fix) written by Chris Moeller
-void cellfreq (signed long i, signed long j, celltype *c)
-{
-    long frn, oct;
-
-    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
-    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
-
-    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);
-}
-
-static long initfirstime = 0;
-void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample)
-{
-    long i, j, frn, oct;
-
-    memset((void *)adlibreg,0,sizeof(adlibreg));
-    memset((void *)cell,0,sizeof(celltype)*MAXCELLS);
-    memset((void *)rbuf,0,sizeof(rbuf));
-    rend = 0; odrumstat = 0;
-
-    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];
-    }
-
-    numspeakers = danumspeakers;
-    bytespersample = dabytespersample;
-
-    recipsamp = 1.0 / (float)dasamplerate;
-    for(i=15;i>=0;i--) nfrqmul[i] = frqmul[i]*recipsamp*FRQSCALE*(WAVPREC/2048.0);
-
-    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;
-	    }
-    }
-    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];
-	}
-    }
-}
-
-void adlib0 (long i, long v)
-{
-    unsigned char tmp = adlibreg[i];
-    adlibreg[i] = 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;
-    }
-    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]);
-    }
-    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]);
-    }
-    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]);
-    }
-
-    //outdata(i,v);
-}
-
-#ifdef USING_ASM
-static long fpuasm;
-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
-		}
-}
-
-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
-		}
-}
-#else
-static void clipit8(float f,unsigned char *a) {
-    f/=256.0;
-    f+=128.0;
-    if (f>254.5) *a=255;
-    else if (f<0.5) *a=0;
-    else *a=f;
-}
-
-static void clipit16(float f,short *a) {
-    if (f>32766.5) *a=32767;
-    else if (f<-32767.5) *a=-32768;
-    else *a=f;
-}
-#endif
-
-void adlibsetvolume(int i) {
-    AMPSCALE=i;
-}
-
-void adlibgetsample (unsigned char *sndptr, long numbytes)
-{
-    long i, j, k=0, ns, endsamples, rptrs, numsamples;
-    celltype *cptr;
-    float f;
-    short *sndptr2=(short *)sndptr;
-
-    numsamples = (numbytes>>(numspeakers+bytespersample-2));
-
-    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;
-    }
-    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-min(max(lplc[i],0),FIFOSIZ);
-		nrplc[rptrs] = rend-min(max(rplc[i],0),FIFOSIZ);
-		rptrs++;
-	    }
-	    rptr[i] = &rbuf[rptrs-1][0];
-	}
-    }
-
-
-    //CPU time used to be somewhat less when emulator was only mono!
-    //   Because of no delay fifos!
-
-    for(ns=0;ns<numsamples;ns+=endsamples)
-    {
-	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.cc b/src/adplug/core/adlibemu.cc
new file mode 100644
index 000000000000..ee3ad93d016d
--- /dev/null
+++ b/src/adplug/core/adlibemu.cc
@@ -0,0 +1,594 @@
+/*
+ * ADLIBEMU.C
+ * 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
+ */
+
+/*
+This file is a digital Adlib emulator for OPL2 and possibly OPL3
+
+Features that could be added in a future version:
+- Amplitude and Frequency Vibrato Bits (not hard, but a big speed hit)
+- Global Keyboard Split Number Bit (need to research this one some more)
+- 2nd Adlib chip for OPL3 (simply need to make my cell array bigger)
+- Advanced connection modes of OPL3 (Just need to add more "docell" cases)
+- L/R Stereo bits of OPL3 (Need adlibgetsample to return stereo)
+
+Features that aren't worth supporting:
+- Anything related to adlib timers&interrupts (Sorry - I always used IRQ0)
+- Composite sine wave mode (CSM) (Supported only on ancient cards)
+
+I'm not sure about a few things in my code:
+- Attack curve.  What function is this anyway?  I chose to use an order-3
+  polynomial to approximate but this doesn't seem right.
+- Attack/Decay/Release constants - my constants may not be exact
+- What should ADJUSTSPEED be?
+- Haven't verified that Global Keyboard Split Number Bit works yet
+- Some of the drums don't always sound right.  It's pretty hard to guess
+  the exact waveform of drums when you look at random data which is
+  slightly randomized due to digital ADC recording.
+- Adlib seems to have a lot more treble than my emulator does.  I'm not
+  sure if this is simply unfixable due to the sound blaster's different
+  filtering on FM and digital playback or if it's a serious bug in my
+  code.
+*/
+
+#include <math.h>
+#include <string.h>
+#include <algorithm>
+
+#define PI 3.141592653589793
+#define MAXCELLS 18
+#define WAVPREC 2048
+
+static float AMPSCALE=(8192.0);
+#define FRQSCALE (49716/512.0)
+
+//Constants for Ken's Awe32, on a PII-266 (Ken says: Use these for KSM's!)
+#define MODFACTOR 4.0      //How much of modulator cell goes into carrier
+#define MFBFACTOR 1.0      //How much feedback goes back into modulator
+#define ADJUSTSPEED 0.75   //0<=x<=1  Simulate finite rate of change of state
+
+//Constants for Ken's Awe64G, on a P-133
+//#define MODFACTOR 4.25   //How much of modulator cell goes into carrier
+//#define MFBFACTOR 0.5    //How much feedback goes back into modulator
+//#define ADJUSTSPEED 0.85 //0<=x<=1  Simulate finite rate of change of state
+
+typedef struct
+{
+    float val, t, tinc, vol, sustain, amp, mfb;
+    float a0, a1, a2, a3, decaymul, releasemul;
+    short *waveform;
+    long wavemask;
+    void (*cellfunc)(void *, float);
+    unsigned char flags, dum0, dum1, dum2;
+} celltype;
+
+static long numspeakers, bytespersample;
+static float recipsamp;
+static celltype cell[MAXCELLS];
+static signed short wavtable[WAVPREC*3];
+static float kslmul[4] = {0.0,0.5,0.25,1.0};
+static float frqmul[16] = {.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15}, nfrqmul[16];
+static unsigned char adlibreg[256], ksl[8][16];
+static unsigned char modulatorbase[9] = {0,1,2,8,9,10,16,17,18};
+static unsigned char odrumstat = 0;
+static unsigned char base2cell[22] = {0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8};
+
+float lvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on left speaker
+float rvol[9] = {1,1,1,1,1,1,1,1,1};  //Volume multiplier on right speaker
+long lplc[9] = {0,0,0,0,0,0,0,0,0};   //Samples to delay on left speaker
+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
+static float *rptr[9], *nrptr[9];
+static float rbuf[9][FIFOSIZ*2];
+static float snd[FIFOSIZ*2];
+
+#ifndef USING_ASM
+#define _inline
+#endif
+
+#ifdef USING_ASM
+static _inline void ftol (float f, long *a)
+{
+    _asm
+	{
+	    mov eax, a
+		fld f
+		fistp dword ptr [eax]
+		}
+}
+#else
+static void ftol(float f, long *a) {
+    *a=f;
+}
+#endif
+
+#define ctc ((celltype *)c)      //A rare attempt to make code easier to read!
+void docell4 (void *c, float modulator) { }
+void docell3 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell2 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    if ((long)ctc->amp <= 0x37800000)
+    {
+	ctc->amp = 0;
+	ctc->cellfunc = docell4;
+    }
+    ctc->amp *= ctc->releasemul;
+
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell1 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    if ((long)ctc->amp <= (long)ctc->sustain)
+    {
+	if (ctc->flags&32)
+	{
+	    ctc->amp = ctc->sustain;
+	    ctc->cellfunc = docell3;
+	}
+	else
+	    ctc->cellfunc = docell2;
+    }
+    else
+	ctc->amp *= ctc->decaymul;
+
+    ctc->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+void docell0 (void *c, float modulator)
+{
+    long i;
+
+    ftol(ctc->t+modulator,&i);
+
+    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->t += ctc->tinc;
+    ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED;
+}
+
+
+static long waveform[8] = {WAVPREC,WAVPREC>>1,WAVPREC,(WAVPREC*3)>>2,0,0,(WAVPREC*5)>>2,WAVPREC<<1};
+static long wavemask[8] = {WAVPREC-1,WAVPREC-1,(WAVPREC>>1)-1,(WAVPREC>>1)-1,WAVPREC-1,((WAVPREC*3)>>2)-1,WAVPREC>>1,WAVPREC-1};
+static long wavestart[8] = {0,WAVPREC>>1,0,WAVPREC>>2,0,0,0,WAVPREC>>3};
+static float attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744};
+static float decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608};
+void cellon (long i, long j, celltype *c, unsigned char iscarrier)
+{
+    long frn, oct, toff;
+    float f;
+
+    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
+    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
+    toff = (oct<<1) + ((frn>>9)&((frn>>8)|(((adlibreg[8]>>6)&1)^1)));
+    if (!(adlibreg[j+0x20]&16)) toff >>= 2;
+
+    f = pow(2.0,(adlibreg[j+0x60]>>4)+(toff>>2)-1)*attackconst[toff&3]*recipsamp;
+    c->a0 = .0377*f; c->a1 = 10.73*f+1; c->a2 = -17.57*f; c->a3 = 7.42*f;
+    f = -7.4493*decrelconst[toff&3]*recipsamp;
+    c->decaymul = pow(2.0,f*pow(2.0,(adlibreg[j+0x60]&15)+(toff>>2)));
+    c->releasemul = pow(2.0,f*pow(2.0,(adlibreg[j+0x80]&15)+(toff>>2)));
+    c->wavemask = wavemask[adlibreg[j+0xe0]&7];
+    c->waveform = &wavtable[waveform[adlibreg[j+0xe0]&7]];
+    if (!(adlibreg[1]&0x20)) c->waveform = &wavtable[WAVPREC];
+    c->t = wavestart[adlibreg[j+0xe0]&7];
+    c->flags = adlibreg[j+0x20];
+    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);
+    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;
+    if (!(adlibreg[i+0xc0]&14)) c->mfb = 0;
+    c->val = 0;
+}
+
+//This function (and bug fix) written by Chris Moeller
+void cellfreq (signed long i, signed long j, celltype *c)
+{
+    long frn, oct;
+
+    frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0];
+    oct = ((((long)adlibreg[i+0xb0])>>2)&7);
+
+    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);
+}
+
+static long initfirstime = 0;
+void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample)
+{
+    long i, j, frn, oct;
+
+    memset((void *)adlibreg,0,sizeof(adlibreg));
+    memset((void *)cell,0,sizeof(celltype)*MAXCELLS);
+    memset((void *)rbuf,0,sizeof(rbuf));
+    rend = 0; odrumstat = 0;
+
+    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];
+    }
+
+    numspeakers = danumspeakers;
+    bytespersample = dabytespersample;
+
+    recipsamp = 1.0 / (float)dasamplerate;
+    for(i=15;i>=0;i--) nfrqmul[i] = frqmul[i]*recipsamp*FRQSCALE*(WAVPREC/2048.0);
+
+    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;
+	    }
+    }
+    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];
+	}
+    }
+}
+
+void adlib0 (long i, long v)
+{
+    unsigned char tmp = adlibreg[i];
+    adlibreg[i] = 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;
+    }
+    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]);
+    }
+    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]);
+    }
+    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]);
+    }
+
+    //outdata(i,v);
+}
+
+#ifdef USING_ASM
+static long fpuasm;
+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
+		}
+}
+
+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
+		}
+}
+#else
+static void clipit8(float f,unsigned char *a) {
+    f/=256.0;
+    f+=128.0;
+    if (f>254.5) *a=255;
+    else if (f<0.5) *a=0;
+    else *a=f;
+}
+
+static void clipit16(float f,short *a) {
+    if (f>32766.5) *a=32767;
+    else if (f<-32767.5) *a=-32768;
+    else *a=f;
+}
+#endif
+
+void adlibsetvolume(int i) {
+    AMPSCALE=i;
+}
+
+void adlibgetsample (unsigned char *sndptr, long numbytes)
+{
+    long i, j, k=0, ns, endsamples, rptrs, numsamples;
+    celltype *cptr;
+    float f;
+    short *sndptr2=(short *)sndptr;
+
+    numsamples = (numbytes>>(numspeakers+bytespersample-2));
+
+    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;
+    }
+    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];
+	}
+    }
+
+
+    //CPU time used to be somewhat less when emulator was only mono!
+    //   Because of no delay fifos!
+
+    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));
+    }
+}
diff --git a/src/adplug/core/adplug.cc b/src/adplug/core/adplug.cc
new file mode 100644
index 000000000000..b2eedc4a89af
--- /dev/null
+++ b/src/adplug/core/adplug.cc
@@ -0,0 +1,266 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2008 Simon Peter <dn.tlp at 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
+ *
+ * adplug.cpp - CAdPlug utility class, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <cstring>
+#include <string>
+#include <binfile.h>
+
+#include "adplug.h"
+#include "debug.h"
+
+/***** Replayer includes *****/
+
+#include "hsc.h"
+#include "amd.h"
+#include "a2m.h"
+#include "imf.h"
+#include "sng.h"
+#include "adtrack.h"
+#include "bam.h"
+#include "cmf.h"
+#include "d00.h"
+#include "dfm.h"
+#include "hsp.h"
+#include "ksm.h"
+#include "mad.h"
+#include "mid.h"
+#include "mkj.h"
+#include "cff.h"
+#include "dmo.h"
+#include "s3m.h"
+#include "dtm.h"
+#include "fmc.h"
+#include "mtk.h"
+#include "rad.h"
+#include "raw.h"
+#include "sa2.h"
+#include "bmf.h"
+#include "flash.h"
+#include "hybrid.h"
+#include "hyp.h"
+#include "psi.h"
+#include "rat.h"
+#include "lds.h"
+#include "u6m.h"
+#include "rol.h"
+#include "xsm.h"
+#include "dro.h"
+#include "dro2.h"
+#include "msc.h"
+#include "rix.h"
+#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
+  CPlayers &
+CAdPlug::init_players (const CPlayerDesc pd[])
+{
+  static CPlayers initplayers;
+  unsigned int 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;
+}
+
+CAdPlugDatabase *
+  CAdPlug::database = 0;
+
+CPlayer *
+CAdPlug::factory (VFSFile & fd, Copl * opl, const CPlayers & pl,
+                  const CFileProvider & fp)
+{
+  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 ());
+
+        if ((p = (*i)->factory (opl)))
+        {
+          if (p->load (fd, 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;
+        }
+      }
+    }
+  }
+
+#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");
+        return p;
+      }
+      else
+        delete p;
+  }
+#endif
+
+  // Unknown file
+  AdPlug_LogWrite ("End of list!\n");
+  AdPlug_LogWrite ("--- CAdPlug::factory ---\n");
+  return 0;
+}
+
+void
+CAdPlug::set_database (CAdPlugDatabase * db)
+{
+  database = db;
+}
+
+std::string CAdPlug::get_version ()
+{
+  return std::string (ADPLUG_VERSION);
+}
+
+void
+CAdPlug::debug_output (const std::string & filename)
+{
+  AdPlug_LogFile (filename.c_str ());
+  AdPlug_LogWrite ("CAdPlug::debug_output(\"%s\"): Redirected.\n",
+                   filename.c_str ());
+}
diff --git a/src/adplug/core/adplug.cxx b/src/adplug/core/adplug.cxx
deleted file mode 100644
index 8415a21b7e55..000000000000
--- a/src/adplug/core/adplug.cxx
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2008 Simon Peter <dn.tlp at 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
- *
- * adplug.cpp - CAdPlug utility class, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <cstring>
-#include <string>
-#include <binfile.h>
-
-#include "adplug.h"
-#include "debug.h"
-
-/***** Replayer includes *****/
-
-#include "hsc.h"
-#include "amd.h"
-#include "a2m.h"
-#include "imf.h"
-#include "sng.h"
-#include "adtrack.h"
-#include "bam.h"
-#include "cmf.h"
-#include "d00.h"
-#include "dfm.h"
-#include "hsp.h"
-#include "ksm.h"
-#include "mad.h"
-#include "mid.h"
-#include "mkj.h"
-#include "cff.h"
-#include "dmo.h"
-#include "s3m.h"
-#include "dtm.h"
-#include "fmc.h"
-#include "mtk.h"
-#include "rad.h"
-#include "raw.h"
-#include "sa2.h"
-#include "bmf.h"
-#include "flash.h"
-#include "hybrid.h"
-#include "hyp.h"
-#include "psi.h"
-#include "rat.h"
-#include "lds.h"
-#include "u6m.h"
-#include "rol.h"
-#include "xsm.h"
-#include "dro.h"
-#include "dro2.h"
-#include "msc.h"
-#include "rix.h"
-#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
-  CPlayers &
-CAdPlug::init_players (const CPlayerDesc pd[])
-{
-  static CPlayers initplayers;
-  unsigned int 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;
-}
-
-CAdPlugDatabase *
-  CAdPlug::database = 0;
-
-CPlayer *
-CAdPlug::factory (VFSFile * fd, Copl * opl, const CPlayers & pl,
-                  const CFileProvider & fp)
-{
-  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 (vfs_get_filename (fd), (*i)->get_extension (j)))
-      {
-        AdPlug_LogWrite ("Trying direct hit: %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");
-            return p;
-          }
-
-          delete p;
-
-          if (vfs_fseek (fd, 0, SEEK_SET) < 0)
-            return 0;
-        }
-      }
-    }
-  }
-
-#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");
-        return p;
-      }
-      else
-        delete p;
-  }
-#endif
-
-  // Unknown file
-  AdPlug_LogWrite ("End of list!\n");
-  AdPlug_LogWrite ("--- CAdPlug::factory ---\n");
-  return 0;
-}
-
-void
-CAdPlug::set_database (CAdPlugDatabase * db)
-{
-  database = db;
-}
-
-std::string CAdPlug::get_version ()
-{
-  return std::string (ADPLUG_VERSION);
-}
-
-void
-CAdPlug::debug_output (const std::string & filename)
-{
-  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 15b676da6c7e..1283ea792846 100644
--- a/src/adplug/core/adplug.h
+++ b/src/adplug/core/adplug.h
@@ -37,7 +37,7 @@ class CAdPlug
 public:
   static const CPlayers& getPlayers();
 
-  static CPlayer *factory(VFSFile *fd, Copl *opl,
+  static CPlayer *factory(VFSFile &fd, Copl *opl,
                           const CPlayers &pl = getPlayers(),
 			  const CFileProvider &fp = CProvider_Filesystem());
 
diff --git a/src/adplug/core/adtrack.cc b/src/adplug/core/adtrack.cc
new file mode 100644
index 000000000000..b4101802afe5
--- /dev/null
+++ b/src/adplug/core/adtrack.cc
@@ -0,0 +1,238 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp at 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
+ *
+ * adtrack.cpp - Adlib Tracker 1.0 Loader by Simon Peter <dn.tlp at gmx.net>
+ *
+ * NOTES:
+ * The original Adlib Tracker 1.0 is behaving a little different from the
+ * official spec: The 'octave' integer from the instrument file is stored
+ * "minus 1" from the actual value, underflowing from 0 to 0xffff.
+ *
+ * I also noticed that my player is playing everything transposed a few tones
+ * higher than the original tracker. As far as i can see, my player perfectly
+ * follows the official spec, so it "must" be the tracker that does something
+ * wrong here...
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "adtrack.h"
+#include "debug.h"
+
+/*** Public methods ***/
+
+CPlayer *
+CadtrackLoader::factory (Copl * newopl)
+{
+  return new CadtrackLoader (newopl);
+}
+
+bool
+CadtrackLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  binistream *instf;
+  char note[2];
+  unsigned short rwp;
+  unsigned char chp, octave, pnote = 0;
+  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;
+  }
+
+  // check for instruments file
+  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;
+  }
+
+  // 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;
+
+  // 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);
+    }
+    convert_instrument (i, &myinst);
+  }
+  fp.close (instf);
+
+  // load file
+  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;
+      case '\0':
+        if (note[1] == '\0')
+          tracks[chp][rwp].note = 127;
+        else
+        {
+          fp.close (f);
+          return false;
+        }
+        break;
+      default:
+        fp.close (f);
+        return false;
+      }
+      if ((*note) != '\0')
+      {
+        tracks[chp][rwp].note = pnote + (octave * 12);
+        tracks[chp][rwp].inst = chp + 1;
+      }
+    }
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+float
+CadtrackLoader::getrefresh ()
+{
+  return 18.2f;
+}
+
+/*** Private methods ***/
+
+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
+  // 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
+
+  // Carrier "Key Scaling / Level" register
+  inst[n].data[10] = (i->op[Carrier].freqrisevollvldn & 3) << 6;
+  inst[n].data[10] += i->op[Carrier].softness & 63;
+  // Modulator...
+  inst[n].data[9] = (i->op[Modulator].freqrisevollvldn & 3) << 6;
+  inst[n].data[9] += i->op[Modulator].softness & 63;
+
+  // Carrier "Attack / Decay" register
+  inst[n].data[4] = (i->op[Carrier].attack & 0x0f) << 4;
+  inst[n].data[4] += i->op[Carrier].decay & 0x0f;
+  // Modulator...
+  inst[n].data[3] = (i->op[Modulator].attack & 0x0f) << 4;
+  inst[n].data[3] += i->op[Modulator].decay & 0x0f;
+
+  // Carrier "Release / Sustain" register
+  inst[n].data[6] = (i->op[Carrier].release & 0x0f) << 4;
+  inst[n].data[6] += i->op[Carrier].sustain & 0x0f;
+  // Modulator...
+  inst[n].data[5] = (i->op[Modulator].release & 0x0f) << 4;
+  inst[n].data[5] += i->op[Modulator].sustain & 0x0f;
+
+  // Channel "Feedback / Connection" register
+  inst[n].data[0] = (i->op[Carrier].feedback & 7) << 1;
+
+  // Carrier/Modulator "Wave Select" registers
+  inst[n].data[8] = i->op[Carrier].waveform & 3;
+  inst[n].data[7] = i->op[Modulator].waveform & 3;
+}
diff --git a/src/adplug/core/adtrack.cxx b/src/adplug/core/adtrack.cxx
deleted file mode 100644
index 214d59268aaf..000000000000
--- a/src/adplug/core/adtrack.cxx
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp at 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
- *
- * adtrack.cpp - Adlib Tracker 1.0 Loader by Simon Peter <dn.tlp at gmx.net>
- *
- * NOTES:
- * The original Adlib Tracker 1.0 is behaving a little different from the
- * official spec: The 'octave' integer from the instrument file is stored
- * "minus 1" from the actual value, underflowing from 0 to 0xffff.
- *
- * I also noticed that my player is playing everything transposed a few tones
- * higher than the original tracker. As far as i can see, my player perfectly
- * follows the official spec, so it "must" be the tracker that does something
- * wrong here...
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "adtrack.h"
-#include "debug.h"
-
-/*** Public methods ***/
-
-CPlayer *
-CadtrackLoader::factory (Copl * newopl)
-{
-  return new CadtrackLoader (newopl);
-}
-
-bool
-CadtrackLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  binistream *instf;
-  char note[2];
-  unsigned short rwp;
-  unsigned char chp, octave, pnote = 0;
-  int i, j;
-  AdTrackInst myinst;
-  std::string filename (vfs_get_filename (fd));
-
-  // file validation
-  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 ('.'));
-  instfilename += ".ins";
-  AdPlug_LogWrite ("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n",
-                   filename.c_str (), instfilename.c_str ());
-
-  VFSFile *instfd = vfs_fopen (instfilename.c_str (), "rb");
-  instf = fp.open (instfd);
-  if (!instf || fp.filesize (instf) != 468)
-  {
-    fp.close (f);
-    vfs_fclose (instfd);
-    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;
-
-  // 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);
-    }
-    convert_instrument (i, &myinst);
-  }
-  fp.close (instf);
-
-  // load file
-  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;
-      case '\0':
-        if (note[1] == '\0')
-          tracks[chp][rwp].note = 127;
-        else
-        {
-          fp.close (f);
-          return false;
-        }
-        break;
-      default:
-        fp.close (f);
-        return false;
-      }
-      if ((*note) != '\0')
-      {
-        tracks[chp][rwp].note = pnote + (octave * 12);
-        tracks[chp][rwp].inst = chp + 1;
-      }
-    }
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-float
-CadtrackLoader::getrefresh ()
-{
-  return 18.2f;
-}
-
-/*** Private methods ***/
-
-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
-  // 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
-
-  // Carrier "Key Scaling / Level" register
-  inst[n].data[10] = (i->op[Carrier].freqrisevollvldn & 3) << 6;
-  inst[n].data[10] += i->op[Carrier].softness & 63;
-  // Modulator...
-  inst[n].data[9] = (i->op[Modulator].freqrisevollvldn & 3) << 6;
-  inst[n].data[9] += i->op[Modulator].softness & 63;
-
-  // Carrier "Attack / Decay" register
-  inst[n].data[4] = (i->op[Carrier].attack & 0x0f) << 4;
-  inst[n].data[4] += i->op[Carrier].decay & 0x0f;
-  // Modulator...
-  inst[n].data[3] = (i->op[Modulator].attack & 0x0f) << 4;
-  inst[n].data[3] += i->op[Modulator].decay & 0x0f;
-
-  // Carrier "Release / Sustain" register
-  inst[n].data[6] = (i->op[Carrier].release & 0x0f) << 4;
-  inst[n].data[6] += i->op[Carrier].sustain & 0x0f;
-  // Modulator...
-  inst[n].data[5] = (i->op[Modulator].release & 0x0f) << 4;
-  inst[n].data[5] += i->op[Modulator].sustain & 0x0f;
-
-  // Channel "Feedback / Connection" register
-  inst[n].data[0] = (i->op[Carrier].feedback & 7) << 1;
-
-  // Carrier/Modulator "Wave Select" registers
-  inst[n].data[8] = i->op[Carrier].waveform & 3;
-  inst[n].data[7] = i->op[Modulator].waveform & 3;
-}
diff --git a/src/adplug/core/adtrack.h b/src/adplug/core/adtrack.h
index 6cf1e1a55398..c4df63381da4 100644
--- a/src/adplug/core/adtrack.h
+++ b/src/adplug/core/adtrack.h
@@ -30,7 +30,7 @@ public:
 		: CmodPlayer(newopl)
 	{ };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	float getrefresh();
 
 	std::string gettype()
diff --git a/src/adplug/core/amd.cc b/src/adplug/core/amd.cc
new file mode 100644
index 000000000000..215a485cb57b
--- /dev/null
+++ b/src/adplug/core/amd.cc
@@ -0,0 +1,231 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * amd.cpp - AMD Loader by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "amd.h"
+#include "debug.h"
+
+CPlayer *
+CamdLoader::factory (Copl * newopl)
+{
+  return new CamdLoader (newopl);
+}
+
+bool
+CamdLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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 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,
+    0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21,
+    0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2b, 0x2d, 0x2e, 0x30, 0x32, 0x35,
+    0x37, 0x3a, 0x3c, 0x3f
+  };
+
+  // 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;
+  }
+
+  // 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);
+  }
+  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;
+    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);
+          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
+            tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4);
+          else
+            tracks[i][j].note = 0;
+          tracks[i][j].inst += (buf & 1) << 4;
+        }
+      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
+      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++)
+          {
+            tracks[i][t].command = 0;
+            tracks[i][t].inst = 0;
+            tracks[i][t].note = 0;
+            tracks[i][t].param1 = 0;
+            tracks[i][t].param2 = 0;
+          }
+          j += buf & 127;
+          continue;
+        }
+        tracks[i][j].param2 = buf % 10;
+        tracks[i][j].param1 = buf / 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
+          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);
+    }
+  }
+  fp.close (f);
+
+  // convert to protracker replay data
+  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];
+    inst[i].data[1] = buf;
+    buf = inst[i].data[2];
+    inst[i].data[2] = inst[i].data[5];
+    buf3 = inst[i].data[3];
+    inst[i].data[3] = buf;
+    buf = inst[i].data[4];
+    inst[i].data[4] = inst[i].data[7];
+    inst[i].data[5] = buf3;
+    buf3 = inst[i].data[6];
+    inst[i].data[6] = inst[i].data[8];
+    inst[i].data[7] = buf;
+    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')
+        instname[i][j] = '\x20';
+  }
+  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)
+        {
+          tracks[i][j].command = 10;
+          tracks[i][j].param1 = tracks[i][j].param2;
+          tracks[i][j].param2 = 0;
+        }
+
+        if (tracks[i][j].param1 == 3)
+        {
+          tracks[i][j].command = 10;
+          tracks[i][j].param1 = 0;
+        }
+      }
+
+      // fix volume
+      if (tracks[i][j].command == 17)
+      {
+        int vol = convvol[tracks[i][j].param1 * 10 + tracks[i][j].param2];
+
+        if (vol > 63)
+          vol = 63;
+        tracks[i][j].param1 = vol / 10;
+        tracks[i][j].param2 = vol % 10;
+      }
+    }
+
+  rewind (0);
+  return true;
+}
+
+float
+CamdLoader::getrefresh ()
+{
+  if (tempo)
+    return (float) (tempo);
+  else
+    return 18.2f;
+}
diff --git a/src/adplug/core/amd.cxx b/src/adplug/core/amd.cxx
deleted file mode 100644
index 1eb49fa28345..000000000000
--- a/src/adplug/core/amd.cxx
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * amd.cpp - AMD Loader by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "amd.h"
-#include "debug.h"
-
-CPlayer *
-CamdLoader::factory (Copl * newopl)
-{
-  return new CamdLoader (newopl);
-}
-
-bool
-CamdLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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 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,
-    0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21,
-    0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2b, 0x2d, 0x2e, 0x30, 0x32, 0x35,
-    0x37, 0x3a, 0x3c, 0x3f
-  };
-
-  // 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;
-  }
-
-  // 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);
-  }
-  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;
-    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);
-          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
-            tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4);
-          else
-            tracks[i][j].note = 0;
-          tracks[i][j].inst += (buf & 1) << 4;
-        }
-      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
-      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++)
-          {
-            tracks[i][t].command = 0;
-            tracks[i][t].inst = 0;
-            tracks[i][t].note = 0;
-            tracks[i][t].param1 = 0;
-            tracks[i][t].param2 = 0;
-          }
-          j += buf & 127;
-          continue;
-        }
-        tracks[i][j].param2 = buf % 10;
-        tracks[i][j].param1 = buf / 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
-          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);
-    }
-  }
-  fp.close (f);
-
-  // convert to protracker replay data
-  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];
-    inst[i].data[1] = buf;
-    buf = inst[i].data[2];
-    inst[i].data[2] = inst[i].data[5];
-    buf3 = inst[i].data[3];
-    inst[i].data[3] = buf;
-    buf = inst[i].data[4];
-    inst[i].data[4] = inst[i].data[7];
-    inst[i].data[5] = buf3;
-    buf3 = inst[i].data[6];
-    inst[i].data[6] = inst[i].data[8];
-    inst[i].data[7] = buf;
-    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')
-        instname[i][j] = '\x20';
-  }
-  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)
-        {
-          tracks[i][j].command = 10;
-          tracks[i][j].param1 = tracks[i][j].param2;
-          tracks[i][j].param2 = 0;
-        }
-
-        if (tracks[i][j].param1 == 3)
-        {
-          tracks[i][j].command = 10;
-          tracks[i][j].param1 = 0;
-        }
-      }
-
-      // fix volume
-      if (tracks[i][j].command == 17)
-      {
-        int vol = convvol[tracks[i][j].param1 * 10 + tracks[i][j].param2];
-
-        if (vol > 63)
-          vol = 63;
-        tracks[i][j].param1 = vol / 10;
-        tracks[i][j].param2 = vol % 10;
-      }
-    }
-
-  rewind (0);
-  return true;
-}
-
-float
-CamdLoader::getrefresh ()
-{
-  if (tempo)
-    return (float) (tempo);
-  else
-    return 18.2f;
-}
diff --git a/src/adplug/core/amd.h b/src/adplug/core/amd.h
index d1bd17d50d5a..ba93d7bf1f52 100644
--- a/src/adplug/core/amd.h
+++ b/src/adplug/core/amd.h
@@ -30,7 +30,7 @@ public:
 		: CmodPlayer(newopl)
 	{ };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	float getrefresh();
 
 	std::string gettype()
diff --git a/src/adplug/core/bam.cc b/src/adplug/core/bam.cc
new file mode 100644
index 000000000000..d542942e895e
--- /dev/null
+++ b/src/adplug/core/bam.cc
@@ -0,0 +1,244 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * bam.cpp - Bob's Adlib Music Player, by Simon Peter <dn.tlp at gmx.net>
+ *
+ * NOTES:
+ * In my player, the loop counter is stored with the label. This can be
+ * dangerous for some situations (see below), but there shouldn't be any BAM
+ * files triggering this situation.
+ *
+ * From SourceForge Bug #476088:
+ * -----------------------------
+ * 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, 
+ * when the player executes the inner jump.
+ * ------------------
+ * Not to worry. my reference implementation of BAM does not
+ * support the multiple loop situation you describe, and
+ * neither do any BAM-creation programs. Then both loops point
+ * to the same label, the inner loop's counter is just allowed
+ * to clobber the outer loop's counter. No stack is neccisary.
+ */
+
+#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
+};
+
+CPlayer *
+CbamPlayer::factory (Copl * newopl)
+{
+  return new CbamPlayer (newopl);
+}
+
+bool
+CbamPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+  }
+
+  song = new unsigned char[size];
+  for (i = 0; i < size; i++)
+    song[i] = f->readInt (1);
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+bool
+CbamPlayer::update ()
+{
+  unsigned char cmd, c;
+
+  if (del)
+  {
+    del--;
+    return !songend;
+  }
+
+  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;
+        }
+      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;
+}
+
+void
+CbamPlayer::rewind (int subsong)
+{
+  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);
+}
diff --git a/src/adplug/core/bam.cxx b/src/adplug/core/bam.cxx
deleted file mode 100644
index 8a50b2ccacd9..000000000000
--- a/src/adplug/core/bam.cxx
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * bam.cpp - Bob's Adlib Music Player, by Simon Peter <dn.tlp at gmx.net>
- *
- * NOTES:
- * In my player, the loop counter is stored with the label. This can be
- * dangerous for some situations (see below), but there shouldn't be any BAM
- * files triggering this situation.
- *
- * From SourceForge Bug #476088:
- * -----------------------------
- * 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, 
- * when the player executes the inner jump.
- * ------------------
- * Not to worry. my reference implementation of BAM does not
- * support the multiple loop situation you describe, and
- * neither do any BAM-creation programs. Then both loops point
- * to the same label, the inner loop's counter is just allowed
- * to clobber the outer loop's counter. No stack is neccisary.
- */
-
-#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
-};
-
-CPlayer *
-CbamPlayer::factory (Copl * newopl)
-{
-  return new CbamPlayer (newopl);
-}
-
-bool
-CbamPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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;
-  }
-
-  song = new unsigned char[size];
-  for (i = 0; i < size; i++)
-    song[i] = f->readInt (1);
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-bool
-CbamPlayer::update ()
-{
-  unsigned char cmd, c;
-
-  if (del)
-  {
-    del--;
-    return !songend;
-  }
-
-  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;
-        }
-      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;
-}
-
-void
-CbamPlayer::rewind (int subsong)
-{
-  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);
-}
diff --git a/src/adplug/core/bam.h b/src/adplug/core/bam.h
index a3b919460060..cf38707720b8 100644
--- a/src/adplug/core/bam.h
+++ b/src/adplug/core/bam.h
@@ -32,7 +32,7 @@ public:
 	~CbamPlayer()
 	{ if(song) delete [] song; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh()
diff --git a/src/adplug/core/binio_virtual.h b/src/adplug/core/binio_virtual.h
index b51a93f632f4..5d7f9ada18b2 100644
--- a/src/adplug/core/binio_virtual.h
+++ b/src/adplug/core/binio_virtual.h
@@ -9,91 +9,81 @@
 #include <binio.h>
 #include <stdio.h>
 
-extern "C" {
 #include <libaudcore/vfs.h>
-};
 
 class vfsistream : public binistream {
 private:
-	VFSFile *fd; bool own;
+	VFSFile *fd = nullptr;
+	VFSFile own;
 
 public:
-	vfsistream(VFSFile *fd = 0) { this->fd = fd; this->own = false; };
+	vfsistream(VFSFile *fd = nullptr) :
+		fd(fd) {}
 
 	void open(const char *file) {
-		if ((this->fd = vfs_fopen(file, "r")))
-			this->own = true;
+		if ((own = VFSFile(file, "r")))
+			fd = &own;
 		else
 			err |= NotFound;
-	};
-
-	void open(std::string &file) { open(file.c_str()); };
+	}
 
-	vfsistream(const char *file) { this->fd = 0; this->own = false; open(file); };
-	vfsistream(std::string &file) {	this->fd = 0; this->own = false; open(file); };
+	void open(std::string &file) { open(file.c_str()); }
 
-	~vfsistream() {
-		if (this->own)
-			vfs_fclose(this->fd);
-		this->fd = 0; this->own = false;
-	};
+	vfsistream(const char *file) { open(file); }
+	vfsistream(std::string &file) {	open(file); }
 
-	Byte getByte(void) {
-		int c = vfs_getc(this->fd);
-		if (c < 0)
+	Byte getByte() {
+		Byte b = (Byte)-1;
+		if (fd->fread(&b, 1, 1) != 1)
 			err |= Eof;
-		return (Byte) c;
-	};
+		return b;
+	}
 
 	void seek(long pos, Offset offs = Set) {
-		int wh = (offs == Add) ? SEEK_CUR : (offs == End) ? SEEK_END : SEEK_SET;
-		if (vfs_fseek(this->fd, pos, wh))
+		VFSSeekType wh = (offs == Add) ? VFS_SEEK_CUR : (offs == End) ? VFS_SEEK_END : VFS_SEEK_SET;
+		if (fd->fseek (pos, wh))
 			err |= Eof;
 	}
 
-	long pos(void) {
-		return vfs_ftell(this->fd);
+	long pos() {
+		return fd->ftell ();
 	}
 };
 
 class vfsostream : public binostream {
 private:
-	VFSFile *fd; bool own;
+	VFSFile *fd = nullptr;
+	VFSFile own;
 
 public:
-	vfsostream(VFSFile *fd = 0) { this->fd = fd; this->own = false; };
+	vfsostream(VFSFile *fd = nullptr) :
+		fd(fd) {}
 
 	void open(const char *file) {
-		if ((this->fd = vfs_fopen(file, "w")))
-			this->own = true;
+		if ((own = VFSFile(file, "w")))
+			fd = &own;
 		else
 			err |= Denied;
-	};
-
-	void open(std::string &file) { open(file.c_str()); };
+	}
 
-	vfsostream(const char *file) { this->fd = 0; this->own = false; open(file); };
-	vfsostream(std::string &file) {	this->fd = 0; this->own = false; open(file); };
+	void open(std::string &file) { open(file.c_str()); }
 
-	~vfsostream() {
-		if (this->own)
-			vfs_fclose(this->fd);
-		this->fd = 0; this->own = false;
-	};
+	vfsostream(const char *file) { open(file); }
+	vfsostream(std::string &file) {	open(file); }
 
 	void putByte(Byte b) {
-		if (vfs_fwrite(&b, 1, 1, this->fd) != 1)
+		if (fd->fwrite (&b, 1, 1) != 1)
 			err |= Fatal;
-	};
+	}
 
 	void seek(long pos, Offset offs = Set) {
-		int wh = (offs == Add) ? SEEK_CUR : (offs == End) ? SEEK_END : SEEK_SET;
-		if (vfs_fseek(this->fd, pos, wh))
+		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 vfs_ftell(this->fd);
+		return fd->ftell ();
 	}
 };
 
diff --git a/src/adplug/core/bmf.cc b/src/adplug/core/bmf.cc
new file mode 100644
index 000000000000..ff546c269e29
--- /dev/null
+++ b/src/adplug/core/bmf.cc
@@ -0,0 +1,636 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003, 2006 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] BMF player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : GAMESNET.COM
+     type : GamesNet advertising intro
+     tune : by (?)The Brain [Razor 1911]
+   player : ver.0.9b by Hammer
+
+  file(s) : 2FAST4U.COM
+     type : Ford Knox BBStro
+     tune : by The Brain [Razor 1911]
+   player : ver.1.1 by ?
+  comment : in original player at 9th channel the feedback adlib register is not C8 but C6.
+
+  file(s) : DATURA.COM
+     type : Datura BBStro
+     tune : by The Brain [Razor 1911]
+   player : ver.1.2 by ?
+  comment : inaccurate replaying, because constant outport; in original player it can be 380 or 382.
+*/
+
+#include <string.h>
+
+#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,
+  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
+};
+
+/* 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 char
+  CxadbmfPlayer::bmf_default_instrument[13] = {
+  0x01, 0x01, 0x3F, 0x3F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+CPlayer *
+CxadbmfPlayer::factory (Copl * newopl)
+{
+  return new CxadbmfPlayer (newopl);
+}
+
+bool
+CxadbmfPlayer::xadplayer_load ()
+{
+  unsigned short ptr = 0;
+  int i;
+
+  if (xad.fmt != BMF)
+    return false;
+
+#ifdef DEBUG
+  AdPlug_LogWrite ("\nbmf_load():\n\n");
+#endif
+  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))
+  {
+    bmf.version = BMF1_1;
+    bmf.timer = 60.0f;
+  }
+  else
+  {
+    bmf.version = BMF0_9B;
+    bmf.timer = 18.2f;
+  }
+
+  // copy title & author
+  if (bmf.version > BMF0_9B)
+  {
+    ptr = 6;
+
+    strncpy (bmf.title, (char *) &tune[ptr], 36);
+
+    while (tune[ptr])
+    {
+      ptr++;
+    }
+    ptr++;
+
+    strncpy (bmf.author, (char *) &tune[ptr], 36);
+
+    while (tune[ptr])
+    {
+      ptr++;
+    }
+    ptr++;
+  }
+  else
+  {
+    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 ?
+
+  // 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;
+
+    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];
+        else
+          for (int j = 0; j < 13; j++)
+            bmf.instruments[i].data[j] = 0;
+      }
+  }
+  else
+  {
+    ptr = 6;
+
+    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;
+    }
+  }
+
+  // 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);
+      else
+        bmf.streams[i][0].cmd = 0xFF;
+  }
+  else
+  {
+    for (i = 0; i < tune[5]; i++)
+      ptr += __bmf_convert_stream (&tune[ptr], i);
+
+    for (i = tune[5]; i < 9; i++)
+      bmf.streams[i][0].cmd = 0xFF;
+  }
+
+  return true;
+}
+
+void
+CxadbmfPlayer::xadplayer_rewind (int subsong)
+{
+  int i, j;
+
+  for (i = 0; i < 9; i++)
+  {
+    bmf.channel[i].stream_position = 0;
+    bmf.channel[i].delay = 0;
+    bmf.channel[i].loop_position = 0;
+    bmf.channel[i].loop_counter = 0;
+  }
+
+  plr.speed = bmf.speed;
+#ifdef DEBUG
+  AdPlug_LogWrite ("speed: %x\n", plr.speed);
+#endif
+
+  bmf.active_streams = 9;
+
+  // OPL initialization
+  if (bmf.version > BMF0_9B)
+  {
+    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]);
+    /* 1.2 */
+    else if (bmf.version == BMF1_2)
+      for (i = 0x20; i < 0x100; i++)
+        opl_write (i, 0xFF);    // very interesting, really!
+  }
+
+  /* ALL */
+
+  opl_write (0x08, 0x00);
+  opl_write (0xBD, 0xC0);
+}
+
+void
+CxadbmfPlayer::xadplayer_update ()
+{
+  for (int i = 0; i < 9; i++)
+    if (bmf.channel[i].stream_position != 0xFFFF)
+    {
+      if (bmf.channel[i].delay)
+        bmf.channel[i].delay--;
+      else
+      {
+#ifdef DEBUG
+        AdPlug_LogWrite ("channel %02X:\n", i);
+#endif
+        bmf_event 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);
+#endif
+
+          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].stream_position =
+                bmf.channel[i].loop_position - 1;
+              bmf.channel[i].loop_counter--;
+            }
+          }
+          else
+            break;
+
+          bmf.channel[i].stream_position++;
+        }                       // while (true)
+
+        // process normal event
+        unsigned short pos = bmf.channel[i].stream_position;
+
+        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)
+            {
+              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)
+
+  // is module loop ?
+  if (!bmf.active_streams)
+  {
+    for (int j = 0; j < 9; j++)
+      bmf.channel[j].stream_position = 0;
+
+    bmf.active_streams = 9;
+
+    plr.looping = 1;
+  }
+}
+
+float
+CxadbmfPlayer::xadplayer_getrefresh ()
+{
+  return bmf.timer;
+}
+
+std::string CxadbmfPlayer::xadplayer_gettype ()
+{
+  return std::string ("xad: BMF Adlib Tracker");
+}
+
+std::string CxadbmfPlayer::xadplayer_gettitle ()
+{
+  return std::string (bmf.title);
+}
+
+std::string CxadbmfPlayer::xadplayer_getauthor ()
+{
+  return std::string (bmf.author);
+}
+
+unsigned int
+CxadbmfPlayer::xadplayer_getinstruments ()
+{
+  return 32;
+}
+
+std::string CxadbmfPlayer::xadplayer_getinstrument (unsigned int i)
+{
+  return std::string (bmf.instruments[i].name);
+}
+
+/* -------- Internal Functions ---------------------------- */
+
+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);
+  unsigned char *last = stream;
+#endif
+  unsigned char *stream_start = stream;
+
+  int pos = 0;
+
+  while (true)
+  {
+    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++;
+
+      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;
+
+      stream += 2;
+    }
+    else if (*stream == 0x7D)
+    {
+      // 0x7D -> 0xFD: Loop Saved Position
+      bmf.streams[channel][pos].cmd = 0xFD;
+
+      stream++;
+    }
+    else
+    {
+      if (*stream & 0x80)
+      {
+        if (*(stream + 1) & 0x80)
+        {
+          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;
+            // byte2: cccccccc = COMMAND
+
+            stream += 2;
+
+            is_cmd = true;
+          }
+          else
+          {
+            // byte0: 1aaaaaaa = NOTE
+            bmf.streams[channel][pos].note = *stream & 0x7F;
+            // byte1: 11bbbbbb = DELAY
+            bmf.streams[channel][pos].delay = *(stream + 1) & 0x3F;
+
+            stream += 2;
+          }                     // if (*(stream+1) & 0x40)
+        }
+        else
+        {
+          // byte0: 1aaaaaaa = NOTE
+          bmf.streams[channel][pos].note = *stream & 0x7F;
+          // byte1: 0bbbbbbb = COMMAND
+
+          stream++;
+
+          is_cmd = true;
+        }                       // if (*(stream+1) & 0x80)
+      }
+      else
+      {
+        // byte0: 0aaaaaaa = NOTE
+        bmf.streams[channel][pos].note = *stream & 0x7F;
+
+        stream++;
+      }                         // if (*stream & 0x80)
+    }                           // if (*stream == 0xFE)
+
+    // is command ?
+    if (is_cmd)
+    {
+
+      /* ALL */
+
+      if ((0x20 <= *stream) && (*stream <= 0x3F))
+      {
+        // 0x20 or higher; 0x3F or lower: Set Instrument
+        bmf.streams[channel][pos].instrument = *stream - 0x20 + 1;
+
+        stream++;
+      }
+      else if (0x40 <= *stream)
+      {
+        // 0x40 or higher: Set Volume
+        bmf.streams[channel][pos].volume = *stream - 0x40 + 1;
+
+        stream++;
+      }
+      else
+      {
+
+        /* 0.9b */
+
+        if (bmf.version == BMF0_9B)
+          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)
+
+#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;
+#endif
+    pos++;
+  }                             // while (true)
+
+  return (stream - stream_start);
+}
diff --git a/src/adplug/core/bmf.cxx b/src/adplug/core/bmf.cxx
deleted file mode 100644
index ff546c269e29..000000000000
--- a/src/adplug/core/bmf.cxx
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003, 2006 Simon Peter, <dn.tlp at 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
- *
- * [xad] BMF player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : GAMESNET.COM
-     type : GamesNet advertising intro
-     tune : by (?)The Brain [Razor 1911]
-   player : ver.0.9b by Hammer
-
-  file(s) : 2FAST4U.COM
-     type : Ford Knox BBStro
-     tune : by The Brain [Razor 1911]
-   player : ver.1.1 by ?
-  comment : in original player at 9th channel the feedback adlib register is not C8 but C6.
-
-  file(s) : DATURA.COM
-     type : Datura BBStro
-     tune : by The Brain [Razor 1911]
-   player : ver.1.2 by ?
-  comment : inaccurate replaying, because constant outport; in original player it can be 380 or 382.
-*/
-
-#include <string.h>
-
-#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,
-  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
-};
-
-/* 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 char
-  CxadbmfPlayer::bmf_default_instrument[13] = {
-  0x01, 0x01, 0x3F, 0x3F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-CPlayer *
-CxadbmfPlayer::factory (Copl * newopl)
-{
-  return new CxadbmfPlayer (newopl);
-}
-
-bool
-CxadbmfPlayer::xadplayer_load ()
-{
-  unsigned short ptr = 0;
-  int i;
-
-  if (xad.fmt != BMF)
-    return false;
-
-#ifdef DEBUG
-  AdPlug_LogWrite ("\nbmf_load():\n\n");
-#endif
-  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))
-  {
-    bmf.version = BMF1_1;
-    bmf.timer = 60.0f;
-  }
-  else
-  {
-    bmf.version = BMF0_9B;
-    bmf.timer = 18.2f;
-  }
-
-  // copy title & author
-  if (bmf.version > BMF0_9B)
-  {
-    ptr = 6;
-
-    strncpy (bmf.title, (char *) &tune[ptr], 36);
-
-    while (tune[ptr])
-    {
-      ptr++;
-    }
-    ptr++;
-
-    strncpy (bmf.author, (char *) &tune[ptr], 36);
-
-    while (tune[ptr])
-    {
-      ptr++;
-    }
-    ptr++;
-  }
-  else
-  {
-    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 ?
-
-  // 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;
-
-    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];
-        else
-          for (int j = 0; j < 13; j++)
-            bmf.instruments[i].data[j] = 0;
-      }
-  }
-  else
-  {
-    ptr = 6;
-
-    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;
-    }
-  }
-
-  // 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);
-      else
-        bmf.streams[i][0].cmd = 0xFF;
-  }
-  else
-  {
-    for (i = 0; i < tune[5]; i++)
-      ptr += __bmf_convert_stream (&tune[ptr], i);
-
-    for (i = tune[5]; i < 9; i++)
-      bmf.streams[i][0].cmd = 0xFF;
-  }
-
-  return true;
-}
-
-void
-CxadbmfPlayer::xadplayer_rewind (int subsong)
-{
-  int i, j;
-
-  for (i = 0; i < 9; i++)
-  {
-    bmf.channel[i].stream_position = 0;
-    bmf.channel[i].delay = 0;
-    bmf.channel[i].loop_position = 0;
-    bmf.channel[i].loop_counter = 0;
-  }
-
-  plr.speed = bmf.speed;
-#ifdef DEBUG
-  AdPlug_LogWrite ("speed: %x\n", plr.speed);
-#endif
-
-  bmf.active_streams = 9;
-
-  // OPL initialization
-  if (bmf.version > BMF0_9B)
-  {
-    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]);
-    /* 1.2 */
-    else if (bmf.version == BMF1_2)
-      for (i = 0x20; i < 0x100; i++)
-        opl_write (i, 0xFF);    // very interesting, really!
-  }
-
-  /* ALL */
-
-  opl_write (0x08, 0x00);
-  opl_write (0xBD, 0xC0);
-}
-
-void
-CxadbmfPlayer::xadplayer_update ()
-{
-  for (int i = 0; i < 9; i++)
-    if (bmf.channel[i].stream_position != 0xFFFF)
-    {
-      if (bmf.channel[i].delay)
-        bmf.channel[i].delay--;
-      else
-      {
-#ifdef DEBUG
-        AdPlug_LogWrite ("channel %02X:\n", i);
-#endif
-        bmf_event 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);
-#endif
-
-          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].stream_position =
-                bmf.channel[i].loop_position - 1;
-              bmf.channel[i].loop_counter--;
-            }
-          }
-          else
-            break;
-
-          bmf.channel[i].stream_position++;
-        }                       // while (true)
-
-        // process normal event
-        unsigned short pos = bmf.channel[i].stream_position;
-
-        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)
-            {
-              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)
-
-  // is module loop ?
-  if (!bmf.active_streams)
-  {
-    for (int j = 0; j < 9; j++)
-      bmf.channel[j].stream_position = 0;
-
-    bmf.active_streams = 9;
-
-    plr.looping = 1;
-  }
-}
-
-float
-CxadbmfPlayer::xadplayer_getrefresh ()
-{
-  return bmf.timer;
-}
-
-std::string CxadbmfPlayer::xadplayer_gettype ()
-{
-  return std::string ("xad: BMF Adlib Tracker");
-}
-
-std::string CxadbmfPlayer::xadplayer_gettitle ()
-{
-  return std::string (bmf.title);
-}
-
-std::string CxadbmfPlayer::xadplayer_getauthor ()
-{
-  return std::string (bmf.author);
-}
-
-unsigned int
-CxadbmfPlayer::xadplayer_getinstruments ()
-{
-  return 32;
-}
-
-std::string CxadbmfPlayer::xadplayer_getinstrument (unsigned int i)
-{
-  return std::string (bmf.instruments[i].name);
-}
-
-/* -------- Internal Functions ---------------------------- */
-
-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);
-  unsigned char *last = stream;
-#endif
-  unsigned char *stream_start = stream;
-
-  int pos = 0;
-
-  while (true)
-  {
-    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++;
-
-      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;
-
-      stream += 2;
-    }
-    else if (*stream == 0x7D)
-    {
-      // 0x7D -> 0xFD: Loop Saved Position
-      bmf.streams[channel][pos].cmd = 0xFD;
-
-      stream++;
-    }
-    else
-    {
-      if (*stream & 0x80)
-      {
-        if (*(stream + 1) & 0x80)
-        {
-          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;
-            // byte2: cccccccc = COMMAND
-
-            stream += 2;
-
-            is_cmd = true;
-          }
-          else
-          {
-            // byte0: 1aaaaaaa = NOTE
-            bmf.streams[channel][pos].note = *stream & 0x7F;
-            // byte1: 11bbbbbb = DELAY
-            bmf.streams[channel][pos].delay = *(stream + 1) & 0x3F;
-
-            stream += 2;
-          }                     // if (*(stream+1) & 0x40)
-        }
-        else
-        {
-          // byte0: 1aaaaaaa = NOTE
-          bmf.streams[channel][pos].note = *stream & 0x7F;
-          // byte1: 0bbbbbbb = COMMAND
-
-          stream++;
-
-          is_cmd = true;
-        }                       // if (*(stream+1) & 0x80)
-      }
-      else
-      {
-        // byte0: 0aaaaaaa = NOTE
-        bmf.streams[channel][pos].note = *stream & 0x7F;
-
-        stream++;
-      }                         // if (*stream & 0x80)
-    }                           // if (*stream == 0xFE)
-
-    // is command ?
-    if (is_cmd)
-    {
-
-      /* ALL */
-
-      if ((0x20 <= *stream) && (*stream <= 0x3F))
-      {
-        // 0x20 or higher; 0x3F or lower: Set Instrument
-        bmf.streams[channel][pos].instrument = *stream - 0x20 + 1;
-
-        stream++;
-      }
-      else if (0x40 <= *stream)
-      {
-        // 0x40 or higher: Set Volume
-        bmf.streams[channel][pos].volume = *stream - 0x40 + 1;
-
-        stream++;
-      }
-      else
-      {
-
-        /* 0.9b */
-
-        if (bmf.version == BMF0_9B)
-          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)
-
-#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;
-#endif
-    pos++;
-  }                             // while (true)
-
-  return (stream - stream_start);
-}
diff --git a/src/adplug/core/cff.cc b/src/adplug/core/cff.cc
new file mode 100644
index 000000000000..7bffae5d195f
--- /dev/null
+++ b/src/adplug/core/cff.cc
@@ -0,0 +1,531 @@
+/*
+  AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2006 Simon Peter <dn.tlp at 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
+
+  cff.cpp - BoomTracker loader by Riven the Mage <riven at ok.ru>
+*/
+/*
+  NOTE: Conversion of slides is not 100% accurate. Original volume slides
+  have effect on carrier volume only. Also, original arpeggio, frequency & volume
+  slides use previous effect data instead of current.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "cff.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *
+CcffLoader::factory (Copl * newopl)
+{
+  return new CcffLoader (newopl);
+}
+
+bool
+CcffLoader::load (VFSFile & fd, 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;
+
+  // '<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;
+  }
+
+  unsigned char *module = new unsigned char[0x10000];
+
+  // packed ?
+  if (header.packed)
+  {
+    cff_unpacker *unpacker = new cff_unpacker;
+
+    unsigned char *packed_module = new unsigned char[header.size + 4];
+
+    memset (packed_module, 0, header.size + 4);
+
+    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;
+    }
+
+    delete unpacker;
+    delete[] packed_module;
+
+    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);
+  }
+
+  // init CmodPlayer
+  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 (j = 0; j < 11; j++)
+      inst[i].data[conv_inst[j]] = instruments[i].data[j];
+
+    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);
+
+  // load order
+  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 (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++;
+    }
+  }
+
+  delete[]module;
+
+  // order loop
+  restartpos = 0;
+
+  // order length
+  for (i = 0; i < 64; i++)
+  {
+    if (order[i] >= 0x80)
+    {
+      length = i;
+      break;
+    }
+  }
+
+  // default tempo
+  bpm = 0x7D;
+
+  rewind (0);
+
+  return true;
+}
+
+void
+CcffLoader::rewind (int subsong)
+{
+  CmodPlayer::rewind (subsong);
+
+  // 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);
+  }
+}
+
+std::string CcffLoader::gettype ()
+{
+  if (header.packed)
+    return std::string ("BoomTracker 4, packed");
+  else
+    return std::string ("BoomTracker 4");
+}
+
+std::string CcffLoader::gettitle ()
+{
+  return std::string (song_title, 20);
+}
+
+std::string CcffLoader::getauthor ()
+{
+  return std::string (song_author, 20);
+}
+
+std::string CcffLoader::getinstrument (unsigned int n)
+{
+  return std::string (instruments[n].name);
+}
+
+unsigned int
+CcffLoader::getinstruments ()
+{
+  return 47;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+/*
+  Lempel-Ziv-Tyr ;-)
+*/
+long
+CcffLoader::cff_unpacker::unpack (unsigned char *ibuf, unsigned char *obuf)
+{
+  if (memcmp (ibuf, "YsComp" "\x07" "CUD1997" "\x1A\x04", 16))
+    return 0;
+
+  input = ibuf + 16;
+  output = obuf;
+
+  output_length = 0;
+
+  heap = (unsigned char *) malloc (0x10000);
+  dictionary = (unsigned char **) malloc (sizeof (unsigned char *) * 0x8000);
+
+  memset (heap, 0, 0x10000);
+  memset (dictionary, 0, 0x8000);
+
+  cleanup ();
+  if (!startup ())
+    goto out;
+
+  // LZW
+  while (1)
+  {
+    new_code = get_code ();
+
+    // 0x00: end of data
+    if (new_code == 0)
+      break;
+
+    // 0x01: end of block
+    if (new_code == 1)
+    {
+      cleanup ();
+      if (!startup ())
+        goto out;
+
+      continue;
+    }
+
+    // 0x02: expand code length
+    if (new_code == 2)
+    {
+      code_length++;
+
+      continue;
+    }
+
+    // 0x03: RLE
+    if (new_code == 3)
+    {
+      unsigned char
+        old_code_length = code_length;
+
+      code_length = 2;
+
+      unsigned char
+        repeat_length = get_code () + 1;
+
+      code_length = 4 << get_code ();
+
+      unsigned long
+        repeat_counter = get_code ();
+
+      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++;
+      }
+
+      code_length = old_code_length;
+
+      if (!startup ())
+        goto out;
+
+      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];
+
+      translate_code (new_code, temp_string);
+
+      the_string[++the_string[0]] = temp_string[1];
+    }
+
+    expand_dictionary (the_string);
+
+    // output <- new.code.string
+    translate_code (new_code, the_string);
+
+    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];
+
+    old_code = new_code;
+  }
+
+out:
+  free (heap);
+  free (dictionary);
+  return output_length;
+}
+
+unsigned long
+CcffLoader::cff_unpacker::get_code ()
+{
+  unsigned long
+    code;
+
+  while (bits_left < code_length)
+  {
+    bits_buffer |= ((*input++) << bits_left);
+    bits_left += 8;
+  }
+
+  code = bits_buffer & ((1 << code_length) - 1);
+
+  bits_buffer >>= code_length;
+  bits_left -= code_length;
+
+  return code;
+}
+
+void
+CcffLoader::cff_unpacker::translate_code (unsigned long code,
+                                          unsigned char *string)
+{
+  unsigned char
+    translated_string[256];
+
+  if (code >= 0x104)
+  {
+    memcpy (translated_string, dictionary[code - 0x104],
+            (*(dictionary[code - 0x104])) + 1);
+  }
+  else
+  {
+    translated_string[0] = 1;
+    translated_string[1] = (code - 4) & 0xFF;
+  }
+
+  memcpy (string, translated_string, 256);
+}
+
+void
+CcffLoader::cff_unpacker::cleanup ()
+{
+  code_length = 9;
+
+  bits_buffer = 0;
+  bits_left = 0;
+
+  heap_length = 0;
+  dictionary_length = 0;
+}
+
+int
+CcffLoader::cff_unpacker::startup ()
+{
+  old_code = get_code ();
+
+  translate_code (old_code, the_string);
+
+  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];
+
+  return 1;
+}
+
+void
+CcffLoader::cff_unpacker::expand_dictionary (unsigned char *string)
+{
+  if (string[0] >= 0xF0)
+    return;
+
+  memcpy (&heap[heap_length], string, string[0] + 1);
+
+  dictionary[dictionary_length] = &heap[heap_length];
+
+  dictionary_length++;
+
+  heap_length += (string[0] + 1);
+}
diff --git a/src/adplug/core/cff.cxx b/src/adplug/core/cff.cxx
deleted file mode 100644
index 7403cc492ee1..000000000000
--- a/src/adplug/core/cff.cxx
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
-  AdPlug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2006 Simon Peter <dn.tlp at 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
-
-  cff.cpp - BoomTracker loader by Riven the Mage <riven at ok.ru>
-*/
-/*
-  NOTE: Conversion of slides is not 100% accurate. Original volume slides
-  have effect on carrier volume only. Also, original arpeggio, frequency & volume
-  slides use previous effect data instead of current.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "cff.h"
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *
-CcffLoader::factory (Copl * newopl)
-{
-  return new CcffLoader (newopl);
-}
-
-bool
-CcffLoader::load (VFSFile * fd, 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;
-
-  // '<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;
-  }
-
-  unsigned char *module = new unsigned char[0x10000];
-
-  // packed ?
-  if (header.packed)
-  {
-    cff_unpacker *unpacker = new cff_unpacker;
-
-    unsigned char *packed_module = new unsigned char[header.size + 4];
-
-    memset (packed_module, 0, header.size + 4);
-
-    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;
-    }
-
-    delete unpacker;
-    delete[] packed_module;
-
-    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);
-  }
-
-  // init CmodPlayer
-  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 (j = 0; j < 11; j++)
-      inst[i].data[conv_inst[j]] = instruments[i].data[j];
-
-    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);
-
-  // load order
-  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 (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++;
-    }
-  }
-
-  delete[]module;
-
-  // order loop
-  restartpos = 0;
-
-  // order length
-  for (i = 0; i < 64; i++)
-  {
-    if (order[i] >= 0x80)
-    {
-      length = i;
-      break;
-    }
-  }
-
-  // default tempo
-  bpm = 0x7D;
-
-  rewind (0);
-
-  return true;
-}
-
-void
-CcffLoader::rewind (int subsong)
-{
-  CmodPlayer::rewind (subsong);
-
-  // 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);
-  }
-}
-
-std::string CcffLoader::gettype ()
-{
-  if (header.packed)
-    return std::string ("BoomTracker 4, packed");
-  else
-    return std::string ("BoomTracker 4");
-}
-
-std::string CcffLoader::gettitle ()
-{
-  return std::string (song_title, 20);
-}
-
-std::string CcffLoader::getauthor ()
-{
-  return std::string (song_author, 20);
-}
-
-std::string CcffLoader::getinstrument (unsigned int n)
-{
-  return std::string (instruments[n].name);
-}
-
-unsigned int
-CcffLoader::getinstruments ()
-{
-  return 47;
-}
-
-/* -------- Private Methods ------------------------------- */
-
-#ifdef _WIN32
-#pragma warning(disable:4244)
-#pragma warning(disable:4018)
-#endif
-
-/*
-  Lempel-Ziv-Tyr ;-)
-*/
-long
-CcffLoader::cff_unpacker::unpack (unsigned char *ibuf, unsigned char *obuf)
-{
-  if (memcmp (ibuf, "YsComp" "\x07" "CUD1997" "\x1A\x04", 16))
-    return 0;
-
-  input = ibuf + 16;
-  output = obuf;
-
-  output_length = 0;
-
-  heap = (unsigned char *) malloc (0x10000);
-  dictionary = (unsigned char **) malloc (sizeof (unsigned char *) * 0x8000);
-
-  memset (heap, 0, 0x10000);
-  memset (dictionary, 0, 0x8000);
-
-  cleanup ();
-  if (!startup ())
-    goto out;
-
-  // LZW
-  while (1)
-  {
-    new_code = get_code ();
-
-    // 0x00: end of data
-    if (new_code == 0)
-      break;
-
-    // 0x01: end of block
-    if (new_code == 1)
-    {
-      cleanup ();
-      if (!startup ())
-        goto out;
-
-      continue;
-    }
-
-    // 0x02: expand code length
-    if (new_code == 2)
-    {
-      code_length++;
-
-      continue;
-    }
-
-    // 0x03: RLE
-    if (new_code == 3)
-    {
-      unsigned char
-        old_code_length = code_length;
-
-      code_length = 2;
-
-      unsigned char
-        repeat_length = get_code () + 1;
-
-      code_length = 4 << get_code ();
-
-      unsigned long
-        repeat_counter = get_code ();
-
-      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++;
-      }
-
-      code_length = old_code_length;
-
-      if (!startup ())
-        goto out;
-
-      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];
-
-      translate_code (new_code, temp_string);
-
-      the_string[++the_string[0]] = temp_string[1];
-    }
-
-    expand_dictionary (the_string);
-
-    // output <- new.code.string
-    translate_code (new_code, the_string);
-
-    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];
-
-    old_code = new_code;
-  }
-
-out:
-  free (heap);
-  free (dictionary);
-  return output_length;
-}
-
-unsigned long
-CcffLoader::cff_unpacker::get_code ()
-{
-  unsigned long
-    code;
-
-  while (bits_left < code_length)
-  {
-    bits_buffer |= ((*input++) << bits_left);
-    bits_left += 8;
-  }
-
-  code = bits_buffer & ((1 << code_length) - 1);
-
-  bits_buffer >>= code_length;
-  bits_left -= code_length;
-
-  return code;
-}
-
-void
-CcffLoader::cff_unpacker::translate_code (unsigned long code,
-                                          unsigned char *string)
-{
-  unsigned char
-    translated_string[256];
-
-  if (code >= 0x104)
-  {
-    memcpy (translated_string, dictionary[code - 0x104],
-            (*(dictionary[code - 0x104])) + 1);
-  }
-  else
-  {
-    translated_string[0] = 1;
-    translated_string[1] = (code - 4) & 0xFF;
-  }
-
-  memcpy (string, translated_string, 256);
-}
-
-void
-CcffLoader::cff_unpacker::cleanup ()
-{
-  code_length = 9;
-
-  bits_buffer = 0;
-  bits_left = 0;
-
-  heap_length = 0;
-  dictionary_length = 0;
-}
-
-int
-CcffLoader::cff_unpacker::startup ()
-{
-  old_code = get_code ();
-
-  translate_code (old_code, the_string);
-
-  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];
-
-  return 1;
-}
-
-void
-CcffLoader::cff_unpacker::expand_dictionary (unsigned char *string)
-{
-  if (string[0] >= 0xF0)
-    return;
-
-  memcpy (&heap[heap_length], string, string[0] + 1);
-
-  dictionary[dictionary_length] = &heap[heap_length];
-
-  dictionary_length++;
-
-  heap_length += (string[0] + 1);
-}
-
-#ifdef _WIN32
-#pragma warning(default:4244)
-#pragma warning(default:4018)
-#endif
diff --git a/src/adplug/core/cff.h b/src/adplug/core/cff.h
index 73b2c10a562d..3cdff6ea8f2e 100644
--- a/src/adplug/core/cff.h
+++ b/src/adplug/core/cff.h
@@ -28,7 +28,7 @@ class CcffLoader: public CmodPlayer
 
 		CcffLoader(Copl *newopl) : CmodPlayer(newopl) { };
 
-		bool	load(VFSFile *fd, const CFileProvider &fp);
+		bool	load(VFSFile &fd, const CFileProvider &fp);
 		void	rewind(int subsong);
 
 		std::string		gettype();
diff --git a/src/adplug/core/cmf.cc b/src/adplug/core/cmf.cc
new file mode 100644
index 000000000000..21f3490bb2c5
--- /dev/null
+++ b/src/adplug/core/cmf.cc
@@ -0,0 +1,788 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2009 Simon Peter, <dn.tlp at 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
+ *
+ * cmf.cpp - CMF player by Adam Nielsen <malvineous at shikadi.net>
+ *   Subset of CMF reader in MOPL code (Malvineous' OPL player), no seeking etc.
+ */
+
+#include <stdint.h> // for uintxx_t
+#include <cassert>
+#include <math.h> // for pow() etc.
+#include <string.h> // for memset
+#include "debug.h"
+#include "cmf.h"
+
+// ------------------------------
+// OPTIONS
+// ------------------------------
+
+// The official Creative Labs CMF player seems to ignore the note velocity
+// (playing every note at the same volume), but you can uncomment this to
+// allow the note velocity to affect the volume (as presumably the composer
+// originally intended.)
+//
+//#define USE_VELOCITY
+//
+// The Xargon demo song is a good example of a song that uses note velocity.
+
+// OPL register offsets
+#define BASE_CHAR_MULT  0x20
+#define BASE_SCAL_LEVL  0x40
+#define BASE_ATCK_DCAY  0x60
+#define BASE_SUST_RLSE  0x80
+#define BASE_FNUM_L     0xA0
+#define BASE_KEYON_FREQ 0xB0
+#define BASE_RHYTHM     0xBD
+#define BASE_WAVE       0xE0
+#define BASE_FEED_CONN  0xC0
+
+#define OPLBIT_KEYON    0x20 // Bit in BASE_KEYON_FREQ register for turning a note on
+
+// Supplied with a channel, return the offset from a base OPL register for the
+// Modulator cell (e.g. channel 4's modulator is at offset 0x09.  Since 0x60 is
+// the attack/decay function, register 0x69 will thus set the attack/decay for
+// channel 4's modulator.)  (channels go from 0 to 8 inclusive)
+#define OPLOFFSET(channel)   (((channel) / 3) * 8 + ((channel) % 3))
+
+// These 16 instruments are repeated to fill up the 128 available slots.  A CMF
+// file can override none/some/all of the 128 slots with custom instruments,
+// so any that aren't overridden are still available for use with these default
+// patches.  The Word Rescue CMFs are good examples of songs that rely on these
+// default patches.
+uint8_t cDefaultPatches[] =
+"\x01\x11\x4F\x00\xF1\xD2\x53\x74\x00\x00\x06"
+"\x07\x12\x4F\x00\xF2\xF2\x60\x72\x00\x00\x08"
+"\x31\xA1\x1C\x80\x51\x54\x03\x67\x00\x00\x0E"
+"\x31\xA1\x1C\x80\x41\x92\x0B\x3B\x00\x00\x0E"
+"\x31\x16\x87\x80\xA1\x7D\x11\x43\x00\x00\x08"
+"\x30\xB1\xC8\x80\xD5\x61\x19\x1B\x00\x00\x0C"
+"\xF1\x21\x01\x00\x97\xF1\x17\x18\x00\x00\x08"
+"\x32\x16\x87\x80\xA1\x7D\x10\x33\x00\x00\x08"
+"\x01\x12\x4F\x00\x71\x52\x53\x7C\x00\x00\x0A"
+"\x02\x03\x8D\x00\xD7\xF5\x37\x18\x00\x00\x04"
+"\x21\x21\xD1\x00\xA3\xA4\x46\x25\x00\x00\x0A"
+"\x22\x22\x0F\x00\xF6\xF6\x95\x36\x00\x00\x0A"
+"\xE1\xE1\x00\x00\x44\x54\x24\x34\x02\x02\x07"
+"\xA5\xB1\xD2\x80\x81\xF1\x03\x05\x00\x00\x02"
+"\x71\x22\xC5\x00\x6E\x8B\x17\x0E\x00\x00\x02"
+"\x32\x21\x16\x80\x73\x75\x24\x57\x00\x00\x0E";
+
+
+CPlayer *CcmfPlayer::factory(Copl *newopl)
+{
+  return new CcmfPlayer(newopl);
+}
+
+CcmfPlayer::CcmfPlayer(Copl *newopl) :
+	CPlayer(newopl),
+	data(nullptr),
+	pInstruments(nullptr),
+	bPercussive(false),
+	iTranspose(0),
+	iPrevCommand(0)
+{
+	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;
+}
+
+bool CcmfPlayer::load(VFSFile & fd, 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
+  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);
+
+  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;
+}
+
+void CcmfPlayer::rewind(int subsong)
+{
+  this->opl->init();
+
+	// 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);
+
+	// 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);
+
+	// 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));
+
+	// 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
+
+	// 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
+  // song in its entirety (with no synth) to determine the song length, which
+  // 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;
+}
+
+// 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
+	}
+}
+
+std::string CcmfPlayer::gettitle()
+{
+	return this->strTitle;
+}
+std::string CcmfPlayer::getauthor()
+{
+	return this->strComposer;
+}
+std::string CcmfPlayer::getdesc()
+{
+	return this->strRemarks;
+}
+
+
+//
+// PROTECTED
+//
+
+// 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;
+}
+
+// iChannel: OPL channel (0-8)
+// iOperator: 0 == Modulator, 1 == Carrier
+//   Source - source operator to read from instrument definition
+//   Dest - destination operator on OPL chip
+// 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);
+
+	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);
+
+	// 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;
+}
+
+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 at 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;
+}
+
+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;
+}
+
+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;
+}
+
+
+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;
+}
+
+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;
+}
diff --git a/src/adplug/core/cmf.cxx b/src/adplug/core/cmf.cxx
deleted file mode 100644
index bca87a48a294..000000000000
--- a/src/adplug/core/cmf.cxx
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2009 Simon Peter, <dn.tlp at 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * cmf.cpp - CMF player by Adam Nielsen <malvineous at shikadi.net>
- *   Subset of CMF reader in MOPL code (Malvineous' OPL player), no seeking etc.
- */
-
-#include <stdint.h> // for uintxx_t
-#include <cassert>
-#include <math.h> // for pow() etc.
-#include <string.h> // for memset
-#include "debug.h"
-#include "cmf.h"
-
-// ------------------------------
-// OPTIONS
-// ------------------------------
-
-// The official Creative Labs CMF player seems to ignore the note velocity
-// (playing every note at the same volume), but you can uncomment this to
-// allow the note velocity to affect the volume (as presumably the composer
-// originally intended.)
-//
-//#define USE_VELOCITY
-//
-// The Xargon demo song is a good example of a song that uses note velocity.
-
-// OPL register offsets
-#define BASE_CHAR_MULT  0x20
-#define BASE_SCAL_LEVL  0x40
-#define BASE_ATCK_DCAY  0x60
-#define BASE_SUST_RLSE  0x80
-#define BASE_FNUM_L     0xA0
-#define BASE_KEYON_FREQ 0xB0
-#define BASE_RHYTHM     0xBD
-#define BASE_WAVE       0xE0
-#define BASE_FEED_CONN  0xC0
-
-#define OPLBIT_KEYON    0x20 // Bit in BASE_KEYON_FREQ register for turning a note on
-
-// Supplied with a channel, return the offset from a base OPL register for the
-// Modulator cell (e.g. channel 4's modulator is at offset 0x09.  Since 0x60 is
-// the attack/decay function, register 0x69 will thus set the attack/decay for
-// channel 4's modulator.)  (channels go from 0 to 8 inclusive)
-#define OPLOFFSET(channel)   (((channel) / 3) * 8 + ((channel) % 3))
-
-// These 16 instruments are repeated to fill up the 128 available slots.  A CMF
-// file can override none/some/all of the 128 slots with custom instruments,
-// so any that aren't overridden are still available for use with these default
-// patches.  The Word Rescue CMFs are good examples of songs that rely on these
-// default patches.
-uint8_t cDefaultPatches[] =
-"\x01\x11\x4F\x00\xF1\xD2\x53\x74\x00\x00\x06"
-"\x07\x12\x4F\x00\xF2\xF2\x60\x72\x00\x00\x08"
-"\x31\xA1\x1C\x80\x51\x54\x03\x67\x00\x00\x0E"
-"\x31\xA1\x1C\x80\x41\x92\x0B\x3B\x00\x00\x0E"
-"\x31\x16\x87\x80\xA1\x7D\x11\x43\x00\x00\x08"
-"\x30\xB1\xC8\x80\xD5\x61\x19\x1B\x00\x00\x0C"
-"\xF1\x21\x01\x00\x97\xF1\x17\x18\x00\x00\x08"
-"\x32\x16\x87\x80\xA1\x7D\x10\x33\x00\x00\x08"
-"\x01\x12\x4F\x00\x71\x52\x53\x7C\x00\x00\x0A"
-"\x02\x03\x8D\x00\xD7\xF5\x37\x18\x00\x00\x04"
-"\x21\x21\xD1\x00\xA3\xA4\x46\x25\x00\x00\x0A"
-"\x22\x22\x0F\x00\xF6\xF6\x95\x36\x00\x00\x0A"
-"\xE1\xE1\x00\x00\x44\x54\x24\x34\x02\x02\x07"
-"\xA5\xB1\xD2\x80\x81\xF1\x03\x05\x00\x00\x02"
-"\x71\x22\xC5\x00\x6E\x8B\x17\x0E\x00\x00\x02"
-"\x32\x21\x16\x80\x73\x75\x24\x57\x00\x00\x0E";
-
-
-CPlayer *CcmfPlayer::factory(Copl *newopl)
-{
-  return new CcmfPlayer(newopl);
-}
-
-CcmfPlayer::CcmfPlayer(Copl *newopl) :
-	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);
-}
-
-CcmfPlayer::~CcmfPlayer()
-{
-	if (this->data) delete[] data;
-	if (this->pInstruments) delete[] pInstruments;
-}
-
-bool CcmfPlayer::load(VFSFile * fd, 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
-  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);
-
-  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;
-}
-
-void CcmfPlayer::rewind(int subsong)
-{
-  this->opl->init();
-
-	// 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);
-
-	// 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);
-
-	// 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));
-
-	// 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
-
-	// 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
-  // song in its entirety (with no synth) to determine the song length, which
-  // 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;
-}
-
-// 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
-	}
-}
-
-std::string CcmfPlayer::gettitle()
-{
-	return this->strTitle;
-}
-std::string CcmfPlayer::getauthor()
-{
-	return this->strComposer;
-}
-std::string CcmfPlayer::getdesc()
-{
-	return this->strRemarks;
-}
-
-
-//
-// PROTECTED
-//
-
-// 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;
-}
-
-// iChannel: OPL channel (0-8)
-// iOperator: 0 == Modulator, 1 == Carrier
-//   Source - source operator to read from instrument definition
-//   Dest - destination operator on OPL chip
-// 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);
-
-	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);
-
-	// 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;
-}
-
-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 at 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;
-}
-
-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;
-}
-
-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;
-}
-
-
-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;
-}
-
-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;
-}
diff --git a/src/adplug/core/cmf.h b/src/adplug/core/cmf.h
index 26e69f17447b..3e9bb0a28169 100644
--- a/src/adplug/core/cmf.h
+++ b/src/adplug/core/cmf.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * cmf.h - CMF player by Adam Nielsen <malvineous at shikadi.net>
  */
@@ -88,7 +88,7 @@ class CcmfPlayer: public CPlayer
 		CcmfPlayer(Copl *newopl);
 		~CcmfPlayer();
 
-		bool load(VFSFile *fd, const CFileProvider &fp);
+		bool load(VFSFile &fd, const CFileProvider &fp);
 		bool update();
 		void rewind(int subsong);
 		float getrefresh();
diff --git a/src/adplug/core/d00.cc b/src/adplug/core/d00.cc
new file mode 100644
index 000000000000..0b53ea04aeb8
--- /dev/null
+++ b/src/adplug/core/d00.cc
@@ -0,0 +1,653 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * d00.c - D00 Player by Simon Peter <dn.tlp at gmx.net>
+ *
+ * NOTES:
+ * Sorry for the goto's, but the code looks so much nicer now.
+ * I tried it with while loops but it was just a mess. If you
+ * can come up with a nicer solution, just tell me.
+ *
+ * BUGS:
+ * Hard restart SR is sometimes wrong
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include "debug.h"
+#include "d00.h"
+
+#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 inline uint16_t
+LE_WORD (const uint16_t * val)
+{
+  const uint8_t *b = (const uint8_t *) val;
+  return (b[1] << 8) + b[0];
+}
+
+/*** public methods *************************************/
+
+CPlayer *
+Cd00Player::factory (Copl * newopl)
+{
+  return new Cd00Player (newopl);
+}
+
+bool
+Cd00Player::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  d00header *checkhead;
+  d00header1 *ch;
+  unsigned long filesize;
+  int i, ver1 = 0;
+  char *str;
+  std::string filename (fd.filename ());
+
+  // file validation section
+  checkhead = new 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)
+  {
+    // Check for version 0 or 1 header (and .d00 file extension)
+    delete checkhead;
+    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;
+    }
+    delete ch;
+    ver1 = 1;
+  }
+  else
+    delete checkhead;
+
+  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;
+    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] == ' ')
+        header->songname[i] = '\0';
+      else
+        break;
+    for (i = 31; i >= 0; i--)
+      if (header->author[i] == ' ')
+        header->author[i] = '\0';
+      else
+        break;
+  }
+  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));
+  }
+  switch (version)
+  {
+  case 0:
+    levpuls = 0;
+    spfx = 0;
+    header1->speed = 70;        // v0 files default to 70Hz
+    break;
+  case 1:
+    levpuls =
+      (struct Slevpuls *) ((char *) filedata + LE_WORD (&header1->lpulptr));
+    spfx = 0;
+    break;
+  case 2:
+    levpuls =
+      (struct Slevpuls *) ((char *) filedata + LE_WORD (&header->spfxptr));
+    spfx = 0;
+    break;
+  case 3:
+    spfx = 0;
+    levpuls = 0;
+    break;
+  case 4:
+    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--;
+    }
+  else                          // old-style block
+    memset ((char *) filedata + filesize, 0, 1);
+
+  rewind (0);
+  return true;
+}
+
+bool
+Cd00Player::update ()
+{
+  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)
+        channel[c].fxdel--;
+      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].modvol = spfx[channel[c].spfx].modlev;
+        setinst (c);
+        if (LE_WORD (&spfx[channel[c].spfx].instnr) & 0x8000)   // locked frequency
+          note = spfx[channel[c].spfx].halfnote;
+        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].modvol += spfx[channel[c].spfx].modlevadd;
+      channel[c].modvol &= 63;
+      setvolume (c);
+    }
+
+    if (channel[c].levpuls != 0xff) // Levelpuls
+    {
+      if (channel[c].frameskip)
+        channel[c].frameskip--;
+      else
+      {
+        channel[c].frameskip = inst[channel[c].inst].timer;
+        if (channel[c].fxdel)
+          channel[c].fxdel--;
+        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)
+            channel[c].modvol = levpuls[channel[c].levpuls].level;
+        }
+        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)
+        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)
+          channel[c].del = channel[c].speed;
+        else
+        {
+          channel[c].del &= 0x7f;
+          channel[c].del += channel[c].speed;
+        }
+      }
+      else
+      {
+        channel[c].seqend = 1;
+        continue;
+      }
+      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]);
+        channel[c].seqend = 1;
+        goto readorder;
+      default:
+        if (ord >= 0x9000)
+        {                       // set speed
+          channel[c].speed = ord & 0xff;
+          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]));
+        break;
+      }
+      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?
+        channel[c].pattpos = 0;
+        channel[c].ordpos++;
+        goto readorder;
+      }
+      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
+        case 0x80:
+          if (!note || version)
+          {
+            channel[c].key = 0;
+            setfreq (c);
+          }
+          // fall through...
+        case 0x7e:             // HOLD event
+          if (version)
+            channel[c].rhcnt = cnt;
+          channel[c].nextnote = 0;
+          break;
+        default:               // play note
+          // restart fx
+          if (!(channel[c].fxflag & 1))
+            channel[c].vibdepth = 0;
+          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)
+              note -= 0x80;
+            else                // unlocked note
+              note += channel[c].transpose;
+            channel[c].note = note; // remember note for 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
+                note = spfx[channel[c].spfx].halfnote;
+              else              // unlocked frequency
+                note += spfx[channel[c].spfx].halfnote;
+              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)
+                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
+              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)
+                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);
+              cnt -= 0x20;      // make count proper
+            }
+            channel[c].rhcnt = cnt;
+          }
+          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);
+          }
+          break;
+        }
+        continue;               // event is complete
+      }
+      else
+      {                         // effect event
+        switch (fx)
+        {
+        case 6:                // Cut/Stop Voice
+          buf = channel[c].inst;
+          channel[c].inst = 0;
+          playnote (c);
+          channel[c].inst = buf;
+          channel[c].rhcnt = fxop;
+          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)
+            channel[c].irhcnt = fxop;
+          break;
+        case 9:                // New Level
+          channel[c].vol = fxop & 63;
+          if (channel[c].vol + channel[c].cvol < 63)    // apply channel volume
+            channel[c].vol += channel[c].cvol;
+          else
+            channel[c].vol = 63;
+          setvolume (c);
+          break;
+        case 0xb:              // v4: Set SpFX
+          if (version == 4)
+            channel[c].ispfx = fxop;
+          break;
+        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
+            channel[c].ilevpuls = inst[fxop].tunelev - 1;
+          else
+          {
+            channel[c].ilevpuls = 0xff;
+            channel[c].levpuls = 0xff;
+          }
+          break;
+        case 0xd:              // Slide up
+          channel[c].slide = fxop;
+          channel[c].fxflag |= 2;
+          break;
+        case 0xe:              // Slide down
+          channel[c].slide = -fxop;
+          channel[c].fxflag |= 2;
+          break;
+        }
+        goto readseq;           // event is incomplete, note follows
+      }
+    }
+
+  for (c = 0; c < 9; c++)
+    if (channel[c].seqend)
+      trackend++;
+  if (trackend == 9)
+    songend = 1;
+
+  return !songend;
+}
+
+void
+Cd00Player::rewind (int subsong)
+{
+  struct Stpoin
+  {
+    unsigned short ptr[9];
+    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)
+      return;
+  }
+  else if (subsong >= header1->subsongs)
+    return;
+
+  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
+      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].cvol = tpoin[subsong].volume[i] & 0x7f;  // our player may savely ignore bit 7
+    channel[i].vol = channel[i].cvol;   // initialize volume
+  }
+  songend = 0;
+  opl->init ();
+  opl->write (1, 32);           // reset OPL chip
+  cursubsong = subsong;
+}
+
+std::string Cd00Player::gettype ()
+{
+  char
+    tmpstr[40];
+
+  sprintf (tmpstr, "EdLib packed (version %d)",
+           version > 1 ? header->version : header1->version);
+  return std::string (tmpstr);
+}
+
+float
+Cd00Player::getrefresh ()
+{
+  if (version > 1)
+    return header->speed;
+  else
+    return header1->speed;
+}
+
+unsigned int
+Cd00Player::getsubsongs ()
+{
+  if (version <= 1)             // return number of subsongs
+    return header1->subsongs;
+  else
+    return header->subsongs;
+}
+
+/*** private methods *************************************/
+
+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));
+  else
+    opl->write (0x40 + op,
+                channel[chan].modvol + (inst[insnr].data[7] & 192));
+}
+
+void
+Cd00Player::setfreq (unsigned char chan)
+{
+  unsigned short freq = channel[chan].freq;
+
+  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);
+  else
+    opl->write (0xb0 + chan, (freq >> 8) & 31);
+}
+
+void
+Cd00Player::setinst (unsigned char chan)
+{
+  unsigned char op = op_table[chan];
+  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]);
+  else
+    opl->write (0xc0 + chan,
+                (inst[insnr].data[10] << 1) + (inst[insnr].tunelev & 1));
+}
+
+void
+Cd00Player::playnote (unsigned char chan)
+{
+  // set misc vars & play
+  opl->write (0xb0 + chan, 0);  // stop old note
+  setinst (chan);
+  channel[chan].key = 1;
+  setfreq (chan);
+  setvolume (chan);
+}
+
+void
+Cd00Player::vibrato (unsigned char chan)
+{
+  if (!channel[chan].vibdepth)
+    return;
+
+  if (channel[chan].trigger)
+    channel[chan].trigger--;
+  else
+  {
+    channel[chan].trigger = channel[chan].vibdepth;
+    channel[chan].vibspeed = -channel[chan].vibspeed;
+  }
+  channel[chan].freq += channel[chan].vibspeed;
+  setfreq (chan);
+}
diff --git a/src/adplug/core/d00.cxx b/src/adplug/core/d00.cxx
deleted file mode 100644
index d084f484edc0..000000000000
--- a/src/adplug/core/d00.cxx
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * d00.c - D00 Player by Simon Peter <dn.tlp at gmx.net>
- *
- * NOTES:
- * Sorry for the goto's, but the code looks so much nicer now.
- * I tried it with while loops but it was just a mess. If you
- * can come up with a nicer solution, just tell me.
- *
- * BUGS:
- * Hard restart SR is sometimes wrong
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <inttypes.h>
-
-#include "debug.h"
-#include "d00.h"
-
-#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 inline uint16_t
-LE_WORD (const uint16_t * val)
-{
-  const uint8_t *b = (const uint8_t *) val;
-  return (b[1] << 8) + b[0];
-}
-
-/*** public methods *************************************/
-
-CPlayer *
-Cd00Player::factory (Copl * newopl)
-{
-  return new Cd00Player (newopl);
-}
-
-bool
-Cd00Player::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  d00header *checkhead;
-  d00header1 *ch;
-  unsigned long filesize;
-  int i, ver1 = 0;
-  char *str;
-  std::string filename (vfs_get_filename (fd));
-
-  // file validation section
-  checkhead = new 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)
-  {
-    // Check for version 0 or 1 header (and .d00 file extension)
-    delete checkhead;
-    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;
-    }
-    delete ch;
-    ver1 = 1;
-  }
-  else
-    delete checkhead;
-
-  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;
-    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] == ' ')
-        header->songname[i] = '\0';
-      else
-        break;
-    for (i = 31; i >= 0; i--)
-      if (header->author[i] == ' ')
-        header->author[i] = '\0';
-      else
-        break;
-  }
-  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));
-  }
-  switch (version)
-  {
-  case 0:
-    levpuls = 0;
-    spfx = 0;
-    header1->speed = 70;        // v0 files default to 70Hz
-    break;
-  case 1:
-    levpuls =
-      (struct Slevpuls *) ((char *) filedata + LE_WORD (&header1->lpulptr));
-    spfx = 0;
-    break;
-  case 2:
-    levpuls =
-      (struct Slevpuls *) ((char *) filedata + LE_WORD (&header->spfxptr));
-    spfx = 0;
-    break;
-  case 3:
-    spfx = 0;
-    levpuls = 0;
-    break;
-  case 4:
-    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--;
-    }
-  else                          // old-style block
-    memset ((char *) filedata + filesize, 0, 1);
-
-  rewind (0);
-  return true;
-}
-
-bool
-Cd00Player::update ()
-{
-  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)
-        channel[c].fxdel--;
-      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].modvol = spfx[channel[c].spfx].modlev;
-        setinst (c);
-        if (LE_WORD (&spfx[channel[c].spfx].instnr) & 0x8000)   // locked frequency
-          note = spfx[channel[c].spfx].halfnote;
-        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].modvol += spfx[channel[c].spfx].modlevadd;
-      channel[c].modvol &= 63;
-      setvolume (c);
-    }
-
-    if (channel[c].levpuls != 0xff) // Levelpuls
-    {
-      if (channel[c].frameskip)
-        channel[c].frameskip--;
-      else
-      {
-        channel[c].frameskip = inst[channel[c].inst].timer;
-        if (channel[c].fxdel)
-          channel[c].fxdel--;
-        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)
-            channel[c].modvol = levpuls[channel[c].levpuls].level;
-        }
-        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)
-        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)
-          channel[c].del = channel[c].speed;
-        else
-        {
-          channel[c].del &= 0x7f;
-          channel[c].del += channel[c].speed;
-        }
-      }
-      else
-      {
-        channel[c].seqend = 1;
-        continue;
-      }
-      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]);
-        channel[c].seqend = 1;
-        goto readorder;
-      default:
-        if (ord >= 0x9000)
-        {                       // set speed
-          channel[c].speed = ord & 0xff;
-          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]));
-        break;
-      }
-      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?
-        channel[c].pattpos = 0;
-        channel[c].ordpos++;
-        goto readorder;
-      }
-      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
-        case 0x80:
-          if (!note || version)
-          {
-            channel[c].key = 0;
-            setfreq (c);
-          }
-          // fall through...
-        case 0x7e:             // HOLD event
-          if (version)
-            channel[c].rhcnt = cnt;
-          channel[c].nextnote = 0;
-          break;
-        default:               // play note
-          // restart fx
-          if (!(channel[c].fxflag & 1))
-            channel[c].vibdepth = 0;
-          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)
-              note -= 0x80;
-            else                // unlocked note
-              note += channel[c].transpose;
-            channel[c].note = note; // remember note for 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
-                note = spfx[channel[c].spfx].halfnote;
-              else              // unlocked frequency
-                note += spfx[channel[c].spfx].halfnote;
-              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)
-                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
-              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)
-                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);
-              cnt -= 0x20;      // make count proper
-            }
-            channel[c].rhcnt = cnt;
-          }
-          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);
-          }
-          break;
-        }
-        continue;               // event is complete
-      }
-      else
-      {                         // effect event
-        switch (fx)
-        {
-        case 6:                // Cut/Stop Voice
-          buf = channel[c].inst;
-          channel[c].inst = 0;
-          playnote (c);
-          channel[c].inst = buf;
-          channel[c].rhcnt = fxop;
-          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)
-            channel[c].irhcnt = fxop;
-          break;
-        case 9:                // New Level
-          channel[c].vol = fxop & 63;
-          if (channel[c].vol + channel[c].cvol < 63)    // apply channel volume
-            channel[c].vol += channel[c].cvol;
-          else
-            channel[c].vol = 63;
-          setvolume (c);
-          break;
-        case 0xb:              // v4: Set SpFX
-          if (version == 4)
-            channel[c].ispfx = fxop;
-          break;
-        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
-            channel[c].ilevpuls = inst[fxop].tunelev - 1;
-          else
-          {
-            channel[c].ilevpuls = 0xff;
-            channel[c].levpuls = 0xff;
-          }
-          break;
-        case 0xd:              // Slide up
-          channel[c].slide = fxop;
-          channel[c].fxflag |= 2;
-          break;
-        case 0xe:              // Slide down
-          channel[c].slide = -fxop;
-          channel[c].fxflag |= 2;
-          break;
-        }
-        goto readseq;           // event is incomplete, note follows
-      }
-    }
-
-  for (c = 0; c < 9; c++)
-    if (channel[c].seqend)
-      trackend++;
-  if (trackend == 9)
-    songend = 1;
-
-  return !songend;
-}
-
-void
-Cd00Player::rewind (int subsong)
-{
-  struct Stpoin
-  {
-    unsigned short ptr[9];
-    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)
-      return;
-  }
-  else if (subsong >= header1->subsongs)
-    return;
-
-  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
-      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].cvol = tpoin[subsong].volume[i] & 0x7f;  // our player may savely ignore bit 7
-    channel[i].vol = channel[i].cvol;   // initialize volume
-  }
-  songend = 0;
-  opl->init ();
-  opl->write (1, 32);           // reset OPL chip
-  cursubsong = subsong;
-}
-
-std::string Cd00Player::gettype ()
-{
-  char
-    tmpstr[40];
-
-  sprintf (tmpstr, "EdLib packed (version %d)",
-           version > 1 ? header->version : header1->version);
-  return std::string (tmpstr);
-}
-
-float
-Cd00Player::getrefresh ()
-{
-  if (version > 1)
-    return header->speed;
-  else
-    return header1->speed;
-}
-
-unsigned int
-Cd00Player::getsubsongs ()
-{
-  if (version <= 1)             // return number of subsongs
-    return header1->subsongs;
-  else
-    return header->subsongs;
-}
-
-/*** private methods *************************************/
-
-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));
-  else
-    opl->write (0x40 + op,
-                channel[chan].modvol + (inst[insnr].data[7] & 192));
-}
-
-void
-Cd00Player::setfreq (unsigned char chan)
-{
-  unsigned short freq = channel[chan].freq;
-
-  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);
-  else
-    opl->write (0xb0 + chan, (freq >> 8) & 31);
-}
-
-void
-Cd00Player::setinst (unsigned char chan)
-{
-  unsigned char op = op_table[chan];
-  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]);
-  else
-    opl->write (0xc0 + chan,
-                (inst[insnr].data[10] << 1) + (inst[insnr].tunelev & 1));
-}
-
-void
-Cd00Player::playnote (unsigned char chan)
-{
-  // set misc vars & play
-  opl->write (0xb0 + chan, 0);  // stop old note
-  setinst (chan);
-  channel[chan].key = 1;
-  setfreq (chan);
-  setvolume (chan);
-}
-
-void
-Cd00Player::vibrato (unsigned char chan)
-{
-  if (!channel[chan].vibdepth)
-    return;
-
-  if (channel[chan].trigger)
-    channel[chan].trigger--;
-  else
-  {
-    channel[chan].trigger = channel[chan].vibdepth;
-    channel[chan].vibspeed = -channel[chan].vibspeed;
-  }
-  channel[chan].freq += channel[chan].vibspeed;
-  setfreq (chan);
-}
diff --git a/src/adplug/core/d00.h b/src/adplug/core/d00.h
index 05fcc46eb7a9..2071c2ff9e68 100644
--- a/src/adplug/core/d00.h
+++ b/src/adplug/core/d00.h
@@ -35,7 +35,7 @@ class Cd00Player: public CPlayer
 	~Cd00Player()
 	{ if(filedata) delete [] filedata; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh();
diff --git a/src/adplug/core/database.cc b/src/adplug/core/database.cc
new file mode 100644
index 000000000000..035c284ed205
--- /dev/null
+++ b/src/adplug/core/database.cc
@@ -0,0 +1,520 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (c) 1999 - 2006 Simon Peter <dn.tlp at 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
+ *
+ * database.cpp - AdPlug database class
+ * Copyright (c) 2002 Riven the Mage <riven at ok.ru>
+ * Copyright (c) 2002, 2003, 2006 Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include "binio_virtual.h"
+#include <string.h>
+
+#include "database.h"
+
+#define DB_FILEID_V10	"AdPlug Module Information Database 1.0\x10"
+
+/***** CAdPlugDatabase *****/
+
+const unsigned short
+  CAdPlugDatabase::hash_radix = 0xfff1; // should be prime
+
+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);
+}
+
+CAdPlugDatabase::~CAdPlugDatabase ()
+{
+  unsigned long i;
+
+  for (i = 0; i < linear_length; i++)
+    delete db_linear[i];
+
+  delete[]db_linear;
+  delete[]db_hashed;
+}
+
+bool
+CAdPlugDatabase::load (std::string db_name)
+{
+  vfsistream f (db_name);
+  if (f.error ())
+    return false;
+  return load (f);
+}
+
+bool
+CAdPlugDatabase::load (binistream & f)
+{
+  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.readString (id, idlen);
+  if (memcmp (id, DB_FILEID_V10, idlen))
+  {
+    delete[]id;
+    return false;
+  }
+  delete[]id;
+  length = f.readInt (4);
+
+  // read records
+  for (unsigned long i = 0; i < length; i++)
+    insert (CRecord::factory (f));
+
+  return true;
+}
+
+bool
+CAdPlugDatabase::save (std::string db_name)
+{
+  vfsostream f (db_name);
+  if (f.error ())
+    return false;
+  return save (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.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);
+
+  return true;
+}
+
+CAdPlugDatabase::CRecord * CAdPlugDatabase::search (CKey const &key)
+{
+  if (lookup (key))
+    return get_record ();
+  else
+    return 0;
+}
+
+bool
+CAdPlugDatabase::lookup (CKey const &key)
+{
+  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)
+  {
+    linear_index = bucket->index;
+    return true;
+  }
+
+  // in-chain hit ?
+  bucket = db_hashed[index]->chain;
+
+  while (bucket)
+  {
+    if (!bucket->deleted && bucket->record->key == key)
+    {
+      linear_index = bucket->index;
+      return true;
+    }
+
+    bucket = bucket->chain;
+  }
+
+  return false;
+}
+
+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
+
+  // make bucket
+  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++;
+
+  // add to hashed list
+  index = make_hash (record->key);
+
+  if (!db_hashed[index])        // First entry in hashtable
+    db_hashed[index] = bucket;
+  else
+  {                             // Add entry in chained list
+    DB_Bucket *chain = db_hashed[index];
+
+    while (chain->chain)
+      chain = chain->chain;
+    chain->chain = bucket;
+  }
+
+  return true;
+}
+
+void
+CAdPlugDatabase::wipe (CRecord * record)
+{
+  if (!lookup (record->key))
+    return;
+  wipe ();
+}
+
+void
+CAdPlugDatabase::wipe ()
+{
+  if (!linear_length)
+    return;
+
+  DB_Bucket *bucket = db_linear[linear_index];
+
+  if (!bucket->deleted)
+  {
+    delete bucket->record;
+    linear_logic_length--;
+    bucket->deleted = true;
+  }
+}
+
+CAdPlugDatabase::CRecord * CAdPlugDatabase::get_record ()
+{
+  if (!linear_length)
+    return 0;
+  return db_linear[linear_index]->record;
+}
+
+bool
+CAdPlugDatabase::go_forward ()
+{
+  if (linear_index + 1 < linear_length)
+  {
+    linear_index++;
+    return true;
+  }
+  else
+    return false;
+}
+
+bool
+CAdPlugDatabase::go_backward ()
+{
+  if (!linear_index)
+    return false;
+  linear_index--;
+  return true;
+}
+
+void
+CAdPlugDatabase::goto_begin ()
+{
+  if (linear_length)
+    linear_index = 0;
+}
+
+void
+CAdPlugDatabase::goto_end ()
+{
+  if (linear_length)
+    linear_index = linear_length - 1;
+}
+
+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 ()
+{
+  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 (binistream & in)
+{
+  RecordType
+    type;
+  unsigned long
+    size;
+  CRecord *
+    rec;
+
+  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);
+    return rec;
+  }
+  else
+  {
+    // skip this record, cause we don't know about it
+    in.seek (size, binio::Add);
+    return 0;
+  }
+}
+
+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);
+
+  write_own (out);
+}
+
+bool
+CAdPlugDatabase::CRecord::user_read (std::istream & in, std::ostream & out)
+{
+  return user_read_own (in, 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;
+  }
+  out << 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);
+}
+
+/***** CAdPlugDatabase::CRecord::CKey *****/
+
+CAdPlugDatabase::CKey::CKey (binistream & buf)
+{
+  make (buf);
+}
+
+bool
+CAdPlugDatabase::CKey::operator== (const CKey & key)
+{
+  return ((crc16 == key.crc16) && (crc32 == key.crc32));
+}
+
+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;
+
+  crc16 = 0;
+  crc32 = ~0;
+
+  while (!buf.eof ())
+  {
+    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;
+}
+
+/***** CInfoRecord *****/
+
+CInfoRecord::CInfoRecord ()
+{
+  type = SongInfo;
+}
+
+void
+CInfoRecord::read_own (binistream & in)
+{
+  title = in.readString ('\0');
+  author = in.readString ('\0');
+}
+
+void
+CInfoRecord::write_own (binostream & out)
+{
+  out.writeString (title);
+  out.writeInt ('\0', 1);
+  out.writeString (author);
+  out.writeInt ('\0', 1);
+}
+
+unsigned long
+CInfoRecord::get_size ()
+{
+  return title.length () + author.length () + 2;
+}
+
+bool
+CInfoRecord::user_read_own (std::istream & in, std::ostream & out)
+{
+  out << "Title: ";
+  in >> title;
+  out << "Author: ";
+  in >> author;
+  return true;
+}
+
+bool
+CInfoRecord::user_write_own (std::ostream & out)
+{
+  out << "Title: " << title << std::endl;
+  out << "Author: " << author << std::endl;
+  return true;
+}
+
+/***** CClockRecord *****/
+
+CClockRecord::CClockRecord ():clock (0.0f)
+{
+  type = ClockSpeed;
+}
+
+void
+CClockRecord::read_own (binistream & in)
+{
+  clock = in.readFloat (binio::Single);
+}
+
+void
+CClockRecord::write_own (binostream & out)
+{
+  out.writeFloat (clock, binio::Single);
+}
+
+unsigned long
+CClockRecord::get_size ()
+{
+  return 4;
+}
+
+bool
+CClockRecord::user_read_own (std::istream & in, std::ostream & out)
+{
+  out << "Clockspeed: ";
+  in >> clock;
+  return true;
+}
+
+bool
+CClockRecord::user_write_own (std::ostream & out)
+{
+  out << "Clock speed: " << clock << " Hz" << std::endl;
+  return true;
+}
diff --git a/src/adplug/core/database.cxx b/src/adplug/core/database.cxx
deleted file mode 100644
index 035c284ed205..000000000000
--- a/src/adplug/core/database.cxx
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (c) 1999 - 2006 Simon Peter <dn.tlp at 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
- *
- * database.cpp - AdPlug database class
- * Copyright (c) 2002 Riven the Mage <riven at ok.ru>
- * Copyright (c) 2002, 2003, 2006 Simon Peter <dn.tlp at gmx.net>
- */
-
-#include "binio_virtual.h"
-#include <string.h>
-
-#include "database.h"
-
-#define DB_FILEID_V10	"AdPlug Module Information Database 1.0\x10"
-
-/***** CAdPlugDatabase *****/
-
-const unsigned short
-  CAdPlugDatabase::hash_radix = 0xfff1; // should be prime
-
-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);
-}
-
-CAdPlugDatabase::~CAdPlugDatabase ()
-{
-  unsigned long i;
-
-  for (i = 0; i < linear_length; i++)
-    delete db_linear[i];
-
-  delete[]db_linear;
-  delete[]db_hashed;
-}
-
-bool
-CAdPlugDatabase::load (std::string db_name)
-{
-  vfsistream f (db_name);
-  if (f.error ())
-    return false;
-  return load (f);
-}
-
-bool
-CAdPlugDatabase::load (binistream & f)
-{
-  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.readString (id, idlen);
-  if (memcmp (id, DB_FILEID_V10, idlen))
-  {
-    delete[]id;
-    return false;
-  }
-  delete[]id;
-  length = f.readInt (4);
-
-  // read records
-  for (unsigned long i = 0; i < length; i++)
-    insert (CRecord::factory (f));
-
-  return true;
-}
-
-bool
-CAdPlugDatabase::save (std::string db_name)
-{
-  vfsostream f (db_name);
-  if (f.error ())
-    return false;
-  return save (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.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);
-
-  return true;
-}
-
-CAdPlugDatabase::CRecord * CAdPlugDatabase::search (CKey const &key)
-{
-  if (lookup (key))
-    return get_record ();
-  else
-    return 0;
-}
-
-bool
-CAdPlugDatabase::lookup (CKey const &key)
-{
-  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)
-  {
-    linear_index = bucket->index;
-    return true;
-  }
-
-  // in-chain hit ?
-  bucket = db_hashed[index]->chain;
-
-  while (bucket)
-  {
-    if (!bucket->deleted && bucket->record->key == key)
-    {
-      linear_index = bucket->index;
-      return true;
-    }
-
-    bucket = bucket->chain;
-  }
-
-  return false;
-}
-
-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
-
-  // make bucket
-  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++;
-
-  // add to hashed list
-  index = make_hash (record->key);
-
-  if (!db_hashed[index])        // First entry in hashtable
-    db_hashed[index] = bucket;
-  else
-  {                             // Add entry in chained list
-    DB_Bucket *chain = db_hashed[index];
-
-    while (chain->chain)
-      chain = chain->chain;
-    chain->chain = bucket;
-  }
-
-  return true;
-}
-
-void
-CAdPlugDatabase::wipe (CRecord * record)
-{
-  if (!lookup (record->key))
-    return;
-  wipe ();
-}
-
-void
-CAdPlugDatabase::wipe ()
-{
-  if (!linear_length)
-    return;
-
-  DB_Bucket *bucket = db_linear[linear_index];
-
-  if (!bucket->deleted)
-  {
-    delete bucket->record;
-    linear_logic_length--;
-    bucket->deleted = true;
-  }
-}
-
-CAdPlugDatabase::CRecord * CAdPlugDatabase::get_record ()
-{
-  if (!linear_length)
-    return 0;
-  return db_linear[linear_index]->record;
-}
-
-bool
-CAdPlugDatabase::go_forward ()
-{
-  if (linear_index + 1 < linear_length)
-  {
-    linear_index++;
-    return true;
-  }
-  else
-    return false;
-}
-
-bool
-CAdPlugDatabase::go_backward ()
-{
-  if (!linear_index)
-    return false;
-  linear_index--;
-  return true;
-}
-
-void
-CAdPlugDatabase::goto_begin ()
-{
-  if (linear_length)
-    linear_index = 0;
-}
-
-void
-CAdPlugDatabase::goto_end ()
-{
-  if (linear_length)
-    linear_index = linear_length - 1;
-}
-
-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 ()
-{
-  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 (binistream & in)
-{
-  RecordType
-    type;
-  unsigned long
-    size;
-  CRecord *
-    rec;
-
-  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);
-    return rec;
-  }
-  else
-  {
-    // skip this record, cause we don't know about it
-    in.seek (size, binio::Add);
-    return 0;
-  }
-}
-
-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);
-
-  write_own (out);
-}
-
-bool
-CAdPlugDatabase::CRecord::user_read (std::istream & in, std::ostream & out)
-{
-  return user_read_own (in, 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;
-  }
-  out << 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);
-}
-
-/***** CAdPlugDatabase::CRecord::CKey *****/
-
-CAdPlugDatabase::CKey::CKey (binistream & buf)
-{
-  make (buf);
-}
-
-bool
-CAdPlugDatabase::CKey::operator== (const CKey & key)
-{
-  return ((crc16 == key.crc16) && (crc32 == key.crc32));
-}
-
-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;
-
-  crc16 = 0;
-  crc32 = ~0;
-
-  while (!buf.eof ())
-  {
-    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;
-}
-
-/***** CInfoRecord *****/
-
-CInfoRecord::CInfoRecord ()
-{
-  type = SongInfo;
-}
-
-void
-CInfoRecord::read_own (binistream & in)
-{
-  title = in.readString ('\0');
-  author = in.readString ('\0');
-}
-
-void
-CInfoRecord::write_own (binostream & out)
-{
-  out.writeString (title);
-  out.writeInt ('\0', 1);
-  out.writeString (author);
-  out.writeInt ('\0', 1);
-}
-
-unsigned long
-CInfoRecord::get_size ()
-{
-  return title.length () + author.length () + 2;
-}
-
-bool
-CInfoRecord::user_read_own (std::istream & in, std::ostream & out)
-{
-  out << "Title: ";
-  in >> title;
-  out << "Author: ";
-  in >> author;
-  return true;
-}
-
-bool
-CInfoRecord::user_write_own (std::ostream & out)
-{
-  out << "Title: " << title << std::endl;
-  out << "Author: " << author << std::endl;
-  return true;
-}
-
-/***** CClockRecord *****/
-
-CClockRecord::CClockRecord ():clock (0.0f)
-{
-  type = ClockSpeed;
-}
-
-void
-CClockRecord::read_own (binistream & in)
-{
-  clock = in.readFloat (binio::Single);
-}
-
-void
-CClockRecord::write_own (binostream & out)
-{
-  out.writeFloat (clock, binio::Single);
-}
-
-unsigned long
-CClockRecord::get_size ()
-{
-  return 4;
-}
-
-bool
-CClockRecord::user_read_own (std::istream & in, std::ostream & out)
-{
-  out << "Clockspeed: ";
-  in >> clock;
-  return true;
-}
-
-bool
-CClockRecord::user_write_own (std::ostream & out)
-{
-  out << "Clock speed: " << clock << " Hz" << std::endl;
-  return true;
-}
diff --git a/src/adplug/core/debug.c b/src/adplug/core/debug.c
deleted file mode 100644
index aa028a86a1f8..000000000000
--- a/src/adplug/core/debug.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp at 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
- *
- * debug.h - AdPlug Debug Logger
- * Copyright (c) 2002 Riven the Mage <riven at ok.ru>
- * Copyright (c) 2002 Simon Peter <dn.tlp at gmx.net>
- */
-
-#ifdef DEBUG
-
-#include <stdio.h>
-#include <stdarg.h>
-
-static FILE *log = NULL;
-
-void AdPlug_LogFile(const char *filename)
-{
-  if(log) fclose(log);
-  log = fopen(filename,"wt");
-}
-
-void AdPlug_LogWrite(const char *fmt, ...)
-{
-  va_list argptr;
-
-  va_start(argptr, fmt);
-
-  if(log) {
-    vfprintf(log, fmt, argptr);
-    fflush(log);
-  } else
-    vfprintf(stderr, fmt, argptr);
-
-  va_end(argptr);
-}
-
-#else
-
-void AdPlug_LogFile(char *filename) { }
-void AdPlug_LogWrite(char *fmt, ...) { }
-
-#endif
diff --git a/src/adplug/core/debug.cc b/src/adplug/core/debug.cc
new file mode 100644
index 000000000000..e49b1373d300
--- /dev/null
+++ b/src/adplug/core/debug.cc
@@ -0,0 +1,57 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp at 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
+ *
+ * debug.h - AdPlug Debug Logger
+ * Copyright (c) 2002 Riven the Mage <riven at ok.ru>
+ * Copyright (c) 2002 Simon Peter <dn.tlp at gmx.net>
+ */
+
+#ifdef DEBUG
+
+#include <stdio.h>
+#include <stdarg.h>
+
+static FILE *log = nullptr;
+
+void AdPlug_LogFile(const char *filename)
+{
+  if(log) fclose(log);
+  log = fopen(filename,"wt");
+}
+
+void AdPlug_LogWrite(const char *fmt, ...)
+{
+  va_list argptr;
+
+  va_start(argptr, fmt);
+
+  if(log) {
+    vfprintf(log, fmt, argptr);
+    fflush(log);
+  } else
+    vfprintf(stderr, fmt, argptr);
+
+  va_end(argptr);
+}
+
+#else
+
+void AdPlug_LogFile(const char *filename) { }
+void AdPlug_LogWrite(const char *fmt, ...) { }
+
+#endif
diff --git a/src/adplug/core/debug.h b/src/adplug/core/debug.h
index 2c3fc6b18963..0abd9337aa58 100644
--- a/src/adplug/core/debug.h
+++ b/src/adplug/core/debug.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2002 Simon Peter <dn.tlp at 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
@@ -34,10 +34,7 @@
 
 #define ADL_DEBUG
 
-extern "C"
-{
-        void AdPlug_LogFile(const char *filename);
-        void AdPlug_LogWrite(const char *fmt, ...);
-}
+void AdPlug_LogFile(const char *filename);
+void AdPlug_LogWrite(const char *fmt, ...);
 
 #endif
diff --git a/src/adplug/core/dfm.cc b/src/adplug/core/dfm.cc
new file mode 100644
index 000000000000..cb00aa563474
--- /dev/null
+++ b/src/adplug/core/dfm.cc
@@ -0,0 +1,137 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * dfm.cpp - Digital-FM Loader by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "dfm.h"
+#include "debug.h"
+
+CPlayer *
+CdfmLoader::factory (Copl * newopl)
+{
+  return new CdfmLoader (newopl);
+}
+
+bool
+CdfmLoader::load (VFSFile & fd, 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 };
+
+  // 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;
+  }
+
+  // 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);
+  }
+  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
+        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
+              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;
+            }
+          }
+        }
+
+      }
+  }
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+std::string CdfmLoader::gettype ()
+{
+  char
+    tmpstr[20];
+
+  sprintf (tmpstr, "Digital-FM %d.%d", header.hiver, header.lover);
+  return std::string (tmpstr);
+}
+
+float
+CdfmLoader::getrefresh ()
+{
+  return 125.0f;
+}
diff --git a/src/adplug/core/dfm.cxx b/src/adplug/core/dfm.cxx
deleted file mode 100644
index c8edc03b59c7..000000000000
--- a/src/adplug/core/dfm.cxx
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * dfm.cpp - Digital-FM Loader by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "dfm.h"
-#include "debug.h"
-
-CPlayer *
-CdfmLoader::factory (Copl * newopl)
-{
-  return new CdfmLoader (newopl);
-}
-
-bool
-CdfmLoader::load (VFSFile * fd, 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 };
-
-  // 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;
-  }
-
-  // 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);
-  }
-  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
-        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
-              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;
-            }
-          }
-        }
-
-      }
-  }
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-std::string CdfmLoader::gettype ()
-{
-  char
-    tmpstr[20];
-
-  sprintf (tmpstr, "Digital-FM %d.%d", header.hiver, header.lover);
-  return std::string (tmpstr);
-}
-
-float
-CdfmLoader::getrefresh ()
-{
-  return 125.0f;
-}
diff --git a/src/adplug/core/dfm.h b/src/adplug/core/dfm.h
index 8cbe47d7489b..0d7770e0cf97 100644
--- a/src/adplug/core/dfm.h
+++ b/src/adplug/core/dfm.h
@@ -30,7 +30,7 @@ public:
 		: CmodPlayer(newopl)
 	{ };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	float getrefresh();
 
 	std::string gettype();
diff --git a/src/adplug/core/dmo.cc b/src/adplug/core/dmo.cc
new file mode 100644
index 000000000000..bf9d22243284
--- /dev/null
+++ b/src/adplug/core/dmo.cc
@@ -0,0 +1,456 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2004, 2006 Simon Peter, <dn.tlp at 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
+
+  dmo.cpp - TwinTeam loader by Riven the Mage <riven at ok.ru>
+*/
+/*
+  NOTES:
+  Panning is ignored.
+
+  A WORD ist 16 bits, a DWORD is 32 bits and a BYTE is 8 bits in this context.
+*/
+
+#include <string.h>
+#include <binstr.h>
+
+#include "dmo.h"
+#include "debug.h"
+
+#define LOWORD(l) ((l) & 0xffff)
+#define HIWORD(l) ((l) >> 16)
+#define LOBYTE(w) ((w) & 0xff)
+#define HIBYTE(w) ((w) >> 8)
+
+#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 CHARP_AS_WORD(p)	(((*(p + 1)) << 8) + (*p))
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *
+CdmoLoader::factory (Copl * newopl)
+{
+  return new CdmoLoader (newopl);
+}
+
+bool
+CdmoLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  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 (!f)
+  {
+    delete unpacker;
+    return false;
+  }
+  if (!fp.extension (filename, ".dmo"))
+  {
+    delete unpacker;
+    return false;
+  }
+
+  f->readString ((char *) chkhdr, 16);
+
+  if (!unpacker->decrypt (chkhdr, 16))
+  {
+    delete unpacker;
+    fp.close (f);
+    return false;
+  }
+
+  // get file size
+  long packed_length = fp.filesize (f);
+  f->seek (0);
+
+  unsigned char *packed_module = new unsigned char[packed_length];
+
+  // load file
+  f->readString ((char *) packed_module, packed_length);
+  fp.close (f);
+
+  // decrypt
+  unpacker->decrypt (packed_module, packed_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;
+  }
+
+  delete unpacker;
+  delete[]packed_module;
+
+  // "TwinTeam" - signed ?
+  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);
+
+  memset (&header, 0, sizeof (s3mheader));
+
+  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);
+
+  memset (header.chanset, 0xFF, 32);
+
+  for (i = 0; i < 9; i++)
+    header.chanset[i] = 0x10 + i;
+
+  uf.ignore (32);               // ignore panning settings for all 32 channels
+
+  // load orders
+  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);
+
+  // 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);
+  }
+
+  // load patterns
+  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);
+
+        if (!token)
+          break;
+
+        unsigned char chan = token & 31;
+
+        // note + instrument ?
+        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);
+        }
+
+        // volume ?
+        if (token & 64)
+          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);
+        }
+      }
+    }
+
+    uf.seek (cur_pos + my_patlen[i]);
+  }
+
+  delete[]module;
+  rewind (0);
+  return true;
+}
+
+std::string CdmoLoader::gettype ()
+{
+  return std::string ("TwinTeam (packed S3M)");
+}
+
+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");
+}
+
+/* -------- Private Methods ------------------------------- */
+
+unsigned short
+CdmoLoader::dmo_unpacker::brand (unsigned short range)
+{
+  unsigned short
+    ax,
+    bx,
+    cx,
+    dx;
+
+  ax = LOWORD (bseed);
+  bx = HIWORD (bseed);
+  cx = ax;
+  ax = LOWORD (cx * 0x8405);
+  dx = HIWORD (cx * 0x8405);
+  cx <<= 3;
+  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);
+  bx <<= 5;
+  dx = (((HIBYTE (dx) + LOBYTE (bx)) & 0xFF) << 8) + LOBYTE (dx);
+  ax += 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);
+}
+
+bool
+CdmoLoader::dmo_unpacker::decrypt (unsigned char *buf, long len)
+{
+  unsigned long
+    seed = 0;
+  int
+    i;
+
+  bseed = ARRAY_AS_DWORD (buf, 0);
+
+  for (i = 0; i < ARRAY_AS_WORD (buf, 4) + 1; i++)
+    seed += brand (0xffff);
+
+  bseed = seed ^ ARRAY_AS_DWORD (buf, 6);
+
+  if (ARRAY_AS_WORD (buf, 10) != brand (0xffff))
+    return false;
+
+  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)
+{
+  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;
+
+      if (opos + cx >= oend)
+        return -1;
+
+      for (int i = 0; i < cx; i++)
+        *opos++ = *ipos++;
+
+      continue;
+    }
+
+    // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1)
+    if ((code >> 6) == 1)
+    {
+      par1 = *ipos++;
+
+      ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1;
+      cx = (par1 & 0x1F) + 3;
+
+      if (opos + cx >= oend)
+        return -1;
+
+      for (int i = 0; i < cx; i++) {
+        *opos = *(opos - ax);
+        opos++;
+      }
+
+      continue;
+    }
+
+    // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes
+    if ((code >> 6) == 2)
+    {
+      int
+        i;
+
+      par1 = *ipos++;
+
+      ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1;
+      cx = ((par1 & 0x70) >> 4) + 3;
+      bx = par1 & 0x0F;
+
+      if (opos + bx + cx >= oend)
+        return -1;
+
+      for (i = 0; i < cx; i++) {
+        *opos = *(opos - ax);
+        opos++;
+      }
+
+      for (i = 0; i < bx; i++)
+        *opos++ = *ipos++;
+
+      continue;
+    }
+
+    // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes
+    if ((code >> 6) == 3)
+    {
+      int
+        i;
+
+      par1 = *ipos++;
+      par2 = *ipos++;
+
+      bx = ((code & 0x3F) << 7) + (par1 >> 1);
+      cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4;
+      ax = par2 & 0x0F;
+
+      if (opos + ax + cx >= oend)
+        return -1;
+
+      for (i = 0; i < cx; i++) {
+        *opos = *(opos - bx);
+        opos++;
+      }
+
+      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
+    olen = 0;
+  unsigned short
+    block_count = CHARP_AS_WORD (ibuf);
+
+  ibuf += 2;
+  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);
+
+    if (unpack_block (ibuf + 2, CHARP_AS_WORD (block_length) - 2, obuf) !=
+        bul)
+      return 0;
+
+    obuf += bul;
+    olen += bul;
+
+    ibuf += CHARP_AS_WORD (block_length);
+    block_length += 2;
+  }
+
+  return olen;
+}
diff --git a/src/adplug/core/dmo.cxx b/src/adplug/core/dmo.cxx
deleted file mode 100644
index 9d39d38841fe..000000000000
--- a/src/adplug/core/dmo.cxx
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
-  Adplug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2004, 2006 Simon Peter, <dn.tlp at 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
-
-  dmo.cpp - TwinTeam loader by Riven the Mage <riven at ok.ru>
-*/
-/*
-  NOTES:
-  Panning is ignored.
-
-  A WORD ist 16 bits, a DWORD is 32 bits and a BYTE is 8 bits in this context.
-*/
-
-#include <string.h>
-#include <binstr.h>
-
-#include "dmo.h"
-#include "debug.h"
-
-#define LOWORD(l) ((l) & 0xffff)
-#define HIWORD(l) ((l) >> 16)
-#define LOBYTE(w) ((w) & 0xff)
-#define HIBYTE(w) ((w) >> 8)
-
-#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 CHARP_AS_WORD(p)	(((*(p + 1)) << 8) + (*p))
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *
-CdmoLoader::factory (Copl * newopl)
-{
-  return new CdmoLoader (newopl);
-}
-
-bool
-CdmoLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  int i, j;
-  binistream *f;
-  std::string filename (vfs_get_filename (fd));
-
-  // check header
-  dmo_unpacker *unpacker = new dmo_unpacker;
-  unsigned char chkhdr[16];
-
-  f = fp.open (fd);
-  if (!f)
-  {
-    delete unpacker;
-    return false;
-  }
-  if (!fp.extension (filename, ".dmo"))
-  {
-    delete unpacker;
-    return false;
-  }
-
-  f->readString ((char *) chkhdr, 16);
-
-  if (!unpacker->decrypt (chkhdr, 16))
-  {
-    delete unpacker;
-    fp.close (f);
-    return false;
-  }
-
-  // get file size
-  long packed_length = fp.filesize (f);
-  f->seek (0);
-
-  unsigned char *packed_module = new unsigned char[packed_length];
-
-  // load file
-  f->readString ((char *) packed_module, packed_length);
-  fp.close (f);
-
-  // decrypt
-  unpacker->decrypt (packed_module, packed_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;
-  }
-
-  delete unpacker;
-  delete[]packed_module;
-
-  // "TwinTeam" - signed ?
-  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);
-
-  memset (&header, 0, sizeof (s3mheader));
-
-  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);
-
-  memset (header.chanset, 0xFF, 32);
-
-  for (i = 0; i < 9; i++)
-    header.chanset[i] = 0x10 + i;
-
-  uf.ignore (32);               // ignore panning settings for all 32 channels
-
-  // load orders
-  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);
-
-  // 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);
-  }
-
-  // load patterns
-  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);
-
-        if (!token)
-          break;
-
-        unsigned char chan = token & 31;
-
-        // note + instrument ?
-        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);
-        }
-
-        // volume ?
-        if (token & 64)
-          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);
-        }
-      }
-    }
-
-    uf.seek (cur_pos + my_patlen[i]);
-  }
-
-  delete[]module;
-  rewind (0);
-  return true;
-}
-
-std::string CdmoLoader::gettype ()
-{
-  return std::string ("TwinTeam (packed S3M)");
-}
-
-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");
-}
-
-/* -------- Private Methods ------------------------------- */
-
-unsigned short
-CdmoLoader::dmo_unpacker::brand (unsigned short range)
-{
-  unsigned short
-    ax,
-    bx,
-    cx,
-    dx;
-
-  ax = LOWORD (bseed);
-  bx = HIWORD (bseed);
-  cx = ax;
-  ax = LOWORD (cx * 0x8405);
-  dx = HIWORD (cx * 0x8405);
-  cx <<= 3;
-  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);
-  bx <<= 5;
-  dx = (((HIBYTE (dx) + LOBYTE (bx)) & 0xFF) << 8) + LOBYTE (dx);
-  ax += 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);
-}
-
-bool
-CdmoLoader::dmo_unpacker::decrypt (unsigned char *buf, long len)
-{
-  unsigned long
-    seed = 0;
-  int
-    i;
-
-  bseed = ARRAY_AS_DWORD (buf, 0);
-
-  for (i = 0; i < ARRAY_AS_WORD (buf, 4) + 1; i++)
-    seed += brand (0xffff);
-
-  bseed = seed ^ ARRAY_AS_DWORD (buf, 6);
-
-  if (ARRAY_AS_WORD (buf, 10) != brand (0xffff))
-    return false;
-
-  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)
-{
-  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;
-
-      if (opos + cx >= oend)
-        return -1;
-
-      for (int i = 0; i < cx; i++)
-        *opos++ = *ipos++;
-
-      continue;
-    }
-
-    // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1)
-    if ((code >> 6) == 1)
-    {
-      par1 = *ipos++;
-
-      ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1;
-      cx = (par1 & 0x1F) + 3;
-
-      if (opos + cx >= oend)
-        return -1;
-
-      for (int i = 0; i < cx; i++) {
-        *opos = *(opos - ax);
-        opos++;
-      }
-
-      continue;
-    }
-
-    // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes
-    if ((code >> 6) == 2)
-    {
-      int
-        i;
-
-      par1 = *ipos++;
-
-      ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1;
-      cx = ((par1 & 0x70) >> 4) + 3;
-      bx = par1 & 0x0F;
-
-      if (opos + bx + cx >= oend)
-        return -1;
-
-      for (i = 0; i < cx; i++) {
-        *opos = *(opos - ax);
-        opos++;
-      }
-
-      for (i = 0; i < bx; i++)
-        *opos++ = *ipos++;
-
-      continue;
-    }
-
-    // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes
-    if ((code >> 6) == 3)
-    {
-      int
-        i;
-
-      par1 = *ipos++;
-      par2 = *ipos++;
-
-      bx = ((code & 0x3F) << 7) + (par1 >> 1);
-      cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4;
-      ax = par2 & 0x0F;
-
-      if (opos + ax + cx >= oend)
-        return -1;
-
-      for (i = 0; i < cx; i++) {
-        *opos = *(opos - bx);
-        opos++;
-      }
-
-      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
-    olen = 0;
-  unsigned short
-    block_count = CHARP_AS_WORD (ibuf);
-
-  ibuf += 2;
-  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);
-
-    if (unpack_block (ibuf + 2, CHARP_AS_WORD (block_length) - 2, obuf) !=
-        bul)
-      return 0;
-
-    obuf += bul;
-    olen += bul;
-
-    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 38962a1711bb..2ae068fcda61 100644
--- a/src/adplug/core/dmo.h
+++ b/src/adplug/core/dmo.h
@@ -28,7 +28,7 @@ class CdmoLoader: public Cs3mPlayer
 
   CdmoLoader(Copl *newopl) : Cs3mPlayer(newopl) { };
 
-  bool	load(VFSFile *fd, const CFileProvider &fp);
+  bool	load(VFSFile &fd, const CFileProvider &fp);
 
   std::string	gettype();
   std::string	getauthor();
diff --git a/src/adplug/core/dro.cc b/src/adplug/core/dro.cc
new file mode 100644
index 000000000000..f93bb2c4004d
--- /dev/null
+++ b/src/adplug/core/dro.cc
@@ -0,0 +1,151 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet at zophar.net>
+ *
+ * upgraded by matthew gambrell <zeromus at zeromus.org>
+ *
+ * NOTES: 3-oct-04: the DRO format is not yet finalized. beware.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "dro.h"
+
+/*** public methods *************************************/
+
+CPlayer *
+CdroPlayer::factory (Copl * newopl)
+{
+  return new CdroPlayer (newopl);
+}
+
+CdroPlayer::CdroPlayer (Copl * newopl):CPlayer (newopl), data (0)
+{
+  if (opl->gettype () == Copl::TYPE_OPL2)
+    opl3_mode = 0;
+  else
+    opl3_mode = 1;
+}
+
+bool
+CdroPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+  }
+
+  // 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);
+  return true;
+}
+
+bool
+CdroPlayer::update ()
+{
+  if (delay > 500)
+  {
+    delay -= 500;
+    return true;
+  }
+  else
+    delay = 0;
+
+  while (pos < length)
+  {
+    unsigned char cmd = data[pos++];
+    switch (cmd)
+    {
+    case 0:
+      delay = 1 + data[pos++];
+      return true;
+    case 1:
+      delay = 1 + data[pos] + (data[pos + 1] << 8);
+      pos += 2;
+      return true;
+    case 2:
+      index = 0;
+      opl->setchip (0);
+      break;
+    case 3:
+      index = 1;
+      opl->setchip (1);
+      break;
+    default:
+      if (cmd == 4)
+        cmd = data[pos++];      //data override
+      if (index == 0 || opl3_mode)
+        opl->write (cmd, data[pos++]);
+      break;
+    }
+  }
+
+  return pos < length;
+}
+
+void
+CdroPlayer::rewind (int subsong)
+{
+  delay = 1;
+  pos = index = 0;
+  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);
+
+  opl->setchip (1);
+  for (int i = 0; i < 256; i++)
+    opl->write (i, 0);
+  opl->setchip (0);
+}
+
+float
+CdroPlayer::getrefresh ()
+{
+  if (delay > 500)
+    return 1000 / 500;
+  else
+    return 1000 / (double) delay;
+}
diff --git a/src/adplug/core/dro.cxx b/src/adplug/core/dro.cxx
deleted file mode 100644
index a45ac741b492..000000000000
--- a/src/adplug/core/dro.cxx
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet at zophar.net>
- *
- * upgraded by matthew gambrell <zeromus at zeromus.org>
- *
- * NOTES: 3-oct-04: the DRO format is not yet finalized. beware.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "dro.h"
-
-/*** public methods *************************************/
-
-CPlayer *
-CdroPlayer::factory (Copl * newopl)
-{
-  return new CdroPlayer (newopl);
-}
-
-CdroPlayer::CdroPlayer (Copl * newopl):CPlayer (newopl), data (0)
-{
-  if (opl->gettype () == Copl::TYPE_OPL2)
-    opl3_mode = 0;
-  else
-    opl3_mode = 1;
-}
-
-bool
-CdroPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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;
-  }
-
-  // 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);
-  return true;
-}
-
-bool
-CdroPlayer::update ()
-{
-  if (delay > 500)
-  {
-    delay -= 500;
-    return true;
-  }
-  else
-    delay = 0;
-
-  while (pos < length)
-  {
-    unsigned char cmd = data[pos++];
-    switch (cmd)
-    {
-    case 0:
-      delay = 1 + data[pos++];
-      return true;
-    case 1:
-      delay = 1 + data[pos] + (data[pos + 1] << 8);
-      pos += 2;
-      return true;
-    case 2:
-      index = 0;
-      opl->setchip (0);
-      break;
-    case 3:
-      index = 1;
-      opl->setchip (1);
-      break;
-    default:
-      if (cmd == 4)
-        cmd = data[pos++];      //data override
-      if (index == 0 || opl3_mode)
-        opl->write (cmd, data[pos++]);
-      break;
-    }
-  }
-
-  return pos < length;
-}
-
-void
-CdroPlayer::rewind (int subsong)
-{
-  delay = 1;
-  pos = index = 0;
-  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);
-
-  opl->setchip (1);
-  for (int i = 0; i < 256; i++)
-    opl->write (i, 0);
-  opl->setchip (0);
-}
-
-float
-CdroPlayer::getrefresh ()
-{
-  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 af7337e6e226..e1c2bc0f42e3 100644
--- a/src/adplug/core/dro.h
+++ b/src/adplug/core/dro.h
@@ -33,7 +33,7 @@ class CdroPlayer: public CPlayer
 	delete [] data;
     }
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, 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
new file mode 100644
index 000000000000..a3aab339d22d
--- /dev/null
+++ b/src/adplug/core/dro2.cc
@@ -0,0 +1,142 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * dro2.cpp - DOSBox Raw OPL v2.0 player by Adam Nielsen <malvineous at shikadi.net>
+ */
+
+#include <cstring>
+#include <stdio.h>
+
+#include "dro2.h"
+
+CPlayer *Cdro2Player::factory(Copl *newopl)
+{
+  return new Cdro2Player(newopl);
+}
+
+Cdro2Player::Cdro2Player(Copl *newopl) :
+	CPlayer(newopl),
+	piConvTable(nullptr),
+	data(0)
+{
+}
+
+Cdro2Player::~Cdro2Player()
+{
+	if (this->data) delete[] this->data;
+	if (this->piConvTable) delete[] this->piConvTable;
+}
+
+bool Cdro2Player::load(VFSFile & fd, 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;
+}
+
+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.
+  return this->iPos < this->iLength;
+}
+
+void Cdro2Player::rewind(int subsong)
+{
+	this->iDelay = 0;
+	this->iPos = 0;
+  opl->init();
+}
+
+float Cdro2Player::getrefresh()
+{
+	if (this->iDelay > 0) return 1000.0 / this->iDelay;
+	else return 1000.0;
+}
diff --git a/src/adplug/core/dro2.cxx b/src/adplug/core/dro2.cxx
deleted file mode 100644
index 8fe27ff0b68b..000000000000
--- a/src/adplug/core/dro2.cxx
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * dro2.cpp - DOSBox Raw OPL v2.0 player by Adam Nielsen <malvineous at shikadi.net>
- */
-
-#include <cstring>
-#include <stdio.h>
-
-#include "dro2.h"
-
-CPlayer *Cdro2Player::factory(Copl *newopl)
-{
-  return new Cdro2Player(newopl);
-}
-
-Cdro2Player::Cdro2Player(Copl *newopl) :
-	CPlayer(newopl),
-	piConvTable(NULL),
-	data(0)
-{
-}
-
-Cdro2Player::~Cdro2Player()
-{
-	if (this->data) delete[] this->data;
-	if (this->piConvTable) delete[] this->piConvTable;
-}
-
-bool Cdro2Player::load(VFSFile * fd, 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;
-}
-
-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.
-  return this->iPos < this->iLength;
-}
-
-void Cdro2Player::rewind(int subsong)
-{
-	this->iDelay = 0;
-	this->iPos = 0;
-  opl->init(); 
-}
-
-float Cdro2Player::getrefresh()
-{
-	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 c2bd793342ba..1a893108ccd0 100644
--- a/src/adplug/core/dro2.h
+++ b/src/adplug/core/dro2.h
@@ -41,7 +41,7 @@ class Cdro2Player: public CPlayer
 		Cdro2Player(Copl *newopl);
 		~Cdro2Player();
 
-		bool load(VFSFile *fd, const CFileProvider &fp);
+		bool load(VFSFile &fd, const CFileProvider &fp);
 		bool update();
 		void rewind(int subsong);
 		float getrefresh();
diff --git a/src/adplug/core/dtm.cc b/src/adplug/core/dtm.cc
new file mode 100644
index 000000000000..9b8bcc58eb6c
--- /dev/null
+++ b/src/adplug/core/dtm.cc
@@ -0,0 +1,338 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+
+  dtm.cpp - DTM loader by Riven the Mage <riven at ok.ru>
+*/
+/*
+  NOTE: Panning (Ex) effect is ignored.
+*/
+
+#include <string.h>
+
+#include "dtm.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *
+CdtmLoader::factory (Copl * newopl)
+{
+  return new CdtmLoader (newopl);
+}
+
+bool
+CdtmLoader::load (VFSFile & fd, 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;
+
+  // 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);
+
+  // signature exists ? good version ?
+  if (memcmp (header.id, "DeFy DTM ", 9) || header.version != 0x10)
+  {
+    fp.close (f);
+    return false;
+  }
+
+  header.numinst++;
+
+  // load description
+  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)
+    {
+      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;
+
+      bufstr[bufstr_length] = 0;
+
+      strcat (desc, bufstr);
+    }
+
+    strcat (desc, "\n");
+  }
+
+  // init CmodPlayer
+  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);
+
+    if (name_length)
+      f->readString (instruments[i].name, name_length);
+
+    instruments[i].name[name_length] = 0;
+
+    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];
+  }
+
+  // load order
+  for (i = 0; i < 100; i++)
+    order[i] = f->readInt (1);
+
+  nop = header.numpat;
+
+  unsigned char *pattern = new unsigned char[0x480];
+
+  // load tracks
+  for (i = 0; i < nop; i++)
+  {
+    unsigned short packed_length;
+
+    packed_length = f->readInt (2);
+
+    unsigned char *packed_pattern = new unsigned char[packed_length];
+
+    for (j = 0; j < packed_length; j++)
+      packed_pattern[j] = f->readInt (1);
+
+    long unpacked_length =
+      unpack_pattern (packed_pattern, packed_length, pattern, 0x480);
+
+    delete[]packed_pattern;
+
+    if (!unpacked_length)
+    {
+      delete[] pattern;
+      fp.close (f);
+      return false;
+    }
+
+    // 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 (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++;
+    }
+  }
+
+  delete[]pattern;
+  fp.close (f);
+
+  // order length
+  for (i = 0; i < 100; i++)
+  {
+    if (order[i] >= 0x80)
+    {
+      length = i;
+
+      if (order[i] == 0xFF)
+        restartpos = 0;
+      else
+        restartpos = order[i] - 0x80;
+
+      break;
+    }
+  }
+
+  // initial speed
+  initspeed = 2;
+
+  rewind (0);
+
+  return true;
+}
+
+void
+CdtmLoader::rewind (int subsong)
+{
+  CmodPlayer::rewind (subsong);
+
+  // 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);
+  }
+}
+
+float
+CdtmLoader::getrefresh ()
+{
+  return 18.2f;
+}
+
+std::string CdtmLoader::gettype ()
+{
+  return std::string ("DeFy Adlib Tracker");
+}
+
+std::string CdtmLoader::gettitle ()
+{
+  return std::string (header.title);
+}
+
+std::string CdtmLoader::getauthor ()
+{
+  return std::string (header.author);
+}
+
+std::string CdtmLoader::getdesc ()
+{
+  return std::string (desc);
+}
+
+std::string CdtmLoader::getinstrument (unsigned int n)
+{
+  return std::string (instruments[n].name);
+}
+
+unsigned int
+CdtmLoader::getinstruments ()
+{
+  return header.numinst;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+long
+CdtmLoader::unpack_pattern (unsigned char *ibuf, long ilen,
+                            unsigned char *obuf, long olen)
+{
+  unsigned char *input = ibuf;
+  unsigned char *output = obuf;
+
+  long input_length = 0;
+  long output_length = 0;
+
+  unsigned char repeat_byte, repeat_counter;
+
+  // 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;
+    }
+  }
+
+  return output_length;
+}
diff --git a/src/adplug/core/dtm.cxx b/src/adplug/core/dtm.cxx
deleted file mode 100644
index f91b3a64a452..000000000000
--- a/src/adplug/core/dtm.cxx
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
-  Adplug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
-
-  dtm.cpp - DTM loader by Riven the Mage <riven at ok.ru>
-*/
-/*
-  NOTE: Panning (Ex) effect is ignored.
-*/
-
-#include <string.h>
-
-#include "dtm.h"
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *
-CdtmLoader::factory (Copl * newopl)
-{
-  return new CdtmLoader (newopl);
-}
-
-bool
-CdtmLoader::load (VFSFile * fd, 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;
-
-  // 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);
-
-  // signature exists ? good version ?
-  if (memcmp (header.id, "DeFy DTM ", 9) || header.version != 0x10)
-  {
-    fp.close (f);
-    return false;
-  }
-
-  header.numinst++;
-
-  // load description
-  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)
-    {
-      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;
-
-      bufstr[bufstr_length] = 0;
-
-      strcat (desc, bufstr);
-    }
-
-    strcat (desc, "\n");
-  }
-
-  // init CmodPlayer
-  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);
-
-    if (name_length)
-      f->readString (instruments[i].name, name_length);
-
-    instruments[i].name[name_length] = 0;
-
-    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];
-  }
-
-  // load order
-  for (i = 0; i < 100; i++)
-    order[i] = f->readInt (1);
-
-  nop = header.numpat;
-
-  unsigned char *pattern = new unsigned char[0x480];
-
-  // load tracks
-  for (i = 0; i < nop; i++)
-  {
-    unsigned short packed_length;
-
-    packed_length = f->readInt (2);
-
-    unsigned char *packed_pattern = new unsigned char[packed_length];
-
-    for (j = 0; j < packed_length; j++)
-      packed_pattern[j] = f->readInt (1);
-
-    long unpacked_length =
-      unpack_pattern (packed_pattern, packed_length, pattern, 0x480);
-
-    delete[]packed_pattern;
-
-    if (!unpacked_length)
-    {
-      delete[] pattern;
-      fp.close (f);
-      return false;
-    }
-
-    // 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 (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++;
-    }
-  }
-
-  delete[]pattern;
-  fp.close (f);
-
-  // order length
-  for (i = 0; i < 100; i++)
-  {
-    if (order[i] >= 0x80)
-    {
-      length = i;
-
-      if (order[i] == 0xFF)
-        restartpos = 0;
-      else
-        restartpos = order[i] - 0x80;
-
-      break;
-    }
-  }
-
-  // initial speed
-  initspeed = 2;
-
-  rewind (0);
-
-  return true;
-}
-
-void
-CdtmLoader::rewind (int subsong)
-{
-  CmodPlayer::rewind (subsong);
-
-  // 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);
-  }
-}
-
-float
-CdtmLoader::getrefresh ()
-{
-  return 18.2f;
-}
-
-std::string CdtmLoader::gettype ()
-{
-  return std::string ("DeFy Adlib Tracker");
-}
-
-std::string CdtmLoader::gettitle ()
-{
-  return std::string (header.title);
-}
-
-std::string CdtmLoader::getauthor ()
-{
-  return std::string (header.author);
-}
-
-std::string CdtmLoader::getdesc ()
-{
-  return std::string (desc);
-}
-
-std::string CdtmLoader::getinstrument (unsigned int n)
-{
-  return std::string (instruments[n].name);
-}
-
-unsigned int
-CdtmLoader::getinstruments ()
-{
-  return header.numinst;
-}
-
-/* -------- Private Methods ------------------------------- */
-
-long
-CdtmLoader::unpack_pattern (unsigned char *ibuf, long ilen,
-                            unsigned char *obuf, long olen)
-{
-  unsigned char *input = ibuf;
-  unsigned char *output = obuf;
-
-  long input_length = 0;
-  long output_length = 0;
-
-  unsigned char repeat_byte, repeat_counter;
-
-  // 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;
-    }
-  }
-
-  return output_length;
-}
diff --git a/src/adplug/core/dtm.h b/src/adplug/core/dtm.h
index 1aa31541586a..de33dfea735c 100644
--- a/src/adplug/core/dtm.h
+++ b/src/adplug/core/dtm.h
@@ -28,7 +28,7 @@ class CdtmLoader: public CmodPlayer
 
 		CdtmLoader(Copl *newopl) : CmodPlayer(newopl) { };
 
-		bool	load(VFSFile *fd, const CFileProvider &fp);
+		bool	load(VFSFile &fd, const CFileProvider &fp);
 		void	rewind(int subsong);
 		float	getrefresh();
 
diff --git a/src/adplug/core/emuopl.cc b/src/adplug/core/emuopl.cc
new file mode 100644
index 000000000000..c3284c7d3d3a
--- /dev/null
+++ b/src/adplug/core/emuopl.cc
@@ -0,0 +1,166 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp at 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
+ *
+ * emuopl.cpp - Emulated OPL, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include "emuopl.h"
+
+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);
+
+  currType = TYPE_DUAL_OPL2;
+
+  init ();
+}
+
+CEmuopl::~CEmuopl ()
+{
+  OPLDestroy (opl[0]);
+  OPLDestroy (opl[1]);
+
+  if (mixbufSamples)
+  {
+    delete[]mixbuf0;
+    delete[]mixbuf1;
+  }
+}
+
+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;
+    }
+    mixbufSamples = samples;
+
+    //*2 = make room for stereo, if we need it
+    mixbuf0 = new short[samples * 2];
+    mixbuf1 = new short[samples * 2];
+  }
+
+  //data should be rendered to outbuf
+  //tempbuf should be used as a temporary buffer
+  //if we are supposed to generate 16bit output,
+  //then outbuf may point directly to the actual waveform output "buf"
+  //if we are supposed to generate 8bit output,
+  //then outbuf cannot point to "buf" (because there will not be enough room)
+  //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;
+  //...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)
+  {
+  case TYPE_OPL2:
+    //for opl2 mode:
+    //render chip0 to the output buffer
+    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];
+      }
+    break;
+
+  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);
+
+    //output stereo:
+    //then we need to interleave the two buffers
+    if (stereo)
+    {
+      //first, spread tempbuf's samples across left channel
+      //left channel
+      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
+      //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);
+    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;
+}
+
+void
+CEmuopl::write (int reg, int val)
+{
+  switch (currType)
+  {
+  case TYPE_OPL2:
+  case TYPE_DUAL_OPL2:
+    OPLWrite (opl[currChip], 0, reg);
+    OPLWrite (opl[currChip], 1, val);
+    break;
+  case TYPE_OPL3:              // unsupported
+    break;
+  }
+}
+
+void
+CEmuopl::init ()
+{
+  OPLResetChip (opl[0]);
+  OPLResetChip (opl[1]);
+  currChip = 0;
+}
+
+void
+CEmuopl::settype (ChipType type)
+{
+  currType = type;
+}
diff --git a/src/adplug/core/emuopl.cxx b/src/adplug/core/emuopl.cxx
deleted file mode 100644
index c3284c7d3d3a..000000000000
--- a/src/adplug/core/emuopl.cxx
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp at 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
- *
- * emuopl.cpp - Emulated OPL, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include "emuopl.h"
-
-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);
-
-  currType = TYPE_DUAL_OPL2;
-
-  init ();
-}
-
-CEmuopl::~CEmuopl ()
-{
-  OPLDestroy (opl[0]);
-  OPLDestroy (opl[1]);
-
-  if (mixbufSamples)
-  {
-    delete[]mixbuf0;
-    delete[]mixbuf1;
-  }
-}
-
-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;
-    }
-    mixbufSamples = samples;
-
-    //*2 = make room for stereo, if we need it
-    mixbuf0 = new short[samples * 2];
-    mixbuf1 = new short[samples * 2];
-  }
-
-  //data should be rendered to outbuf
-  //tempbuf should be used as a temporary buffer
-  //if we are supposed to generate 16bit output,
-  //then outbuf may point directly to the actual waveform output "buf"
-  //if we are supposed to generate 8bit output,
-  //then outbuf cannot point to "buf" (because there will not be enough room)
-  //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;
-  //...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)
-  {
-  case TYPE_OPL2:
-    //for opl2 mode:
-    //render chip0 to the output buffer
-    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];
-      }
-    break;
-
-  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);
-
-    //output stereo:
-    //then we need to interleave the two buffers
-    if (stereo)
-    {
-      //first, spread tempbuf's samples across left channel
-      //left channel
-      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
-      //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);
-    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;
-}
-
-void
-CEmuopl::write (int reg, int val)
-{
-  switch (currType)
-  {
-  case TYPE_OPL2:
-  case TYPE_DUAL_OPL2:
-    OPLWrite (opl[currChip], 0, reg);
-    OPLWrite (opl[currChip], 1, val);
-    break;
-  case TYPE_OPL3:              // unsupported
-    break;
-  }
-}
-
-void
-CEmuopl::init ()
-{
-  OPLResetChip (opl[0]);
-  OPLResetChip (opl[1]);
-  currChip = 0;
-}
-
-void
-CEmuopl::settype (ChipType type)
-{
-  currType = type;
-}
diff --git a/src/adplug/core/emuopl.h b/src/adplug/core/emuopl.h
index dd2f29e4b9e5..51ea06e3fd19 100644
--- a/src/adplug/core/emuopl.h
+++ b/src/adplug/core/emuopl.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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,9 +23,7 @@
 #define H_ADPLUG_EMUOPL
 
 #include "opl.h"
-extern "C" {
 #include "fmopl.h"
-}
 
 class CEmuopl: public Copl
 {
diff --git a/src/adplug/core/flash.cc b/src/adplug/core/flash.cc
new file mode 100644
index 000000000000..30df8b0c3774
--- /dev/null
+++ b/src/adplug/core/flash.cc
@@ -0,0 +1,259 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] FLASH player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : LA-INTRO.EXE
+     type : Lunatic Asylum BBStro
+     tune : by Rogue [Logic Design]
+   player : by Flash [Logic Design]
+*/
+
+#include "flash.h"
+#include "debug.h"
+
+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,
+  0x2B, 0x28, 0x4B, 0x48, 0x6B, 0x68, 0x8B, 0x88, 0xC3, 0xEB, 0xE8,
+  0x2C, 0x29, 0x4C, 0x49, 0x6C, 0x69, 0x8C, 0x89, 0xC4, 0xEC, 0xE9,
+  0x2D, 0x2A, 0x4D, 0x4A, 0x6D, 0x6A, 0x8D, 0x8A, 0xC5, 0xED, 0xEA,
+  0x33, 0x30, 0x53, 0x50, 0x73, 0x70, 0x93, 0x90, 0xC6, 0xF3, 0xF0,
+  0x34, 0x31, 0x54, 0x51, 0x74, 0x71, 0x94, 0x91, 0xC7, 0xF4, 0xF1,
+  0x35, 0x32, 0x55, 0x52, 0x75, 0x72, 0x95, 0x92, 0xC8, 0xF5, 0xF2
+};
+
+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,
+  0x115, 0x215, 0x315
+};
+
+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] = {
+  0x00, 0x00, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+CPlayer *
+CxadflashPlayer::factory (Copl * newopl)
+{
+  return new CxadflashPlayer (newopl);
+}
+
+void
+CxadflashPlayer::xadplayer_rewind (int subsong)
+{
+  int i;
+
+  plr.speed = xad.speed;
+
+  flash.order_pos = 0;
+  flash.pattern_pos = 0;
+
+  opl_write (0x08, 0x00);
+  opl_write (0xBD, 0x00);
+
+  // assign default instrument
+  for (i = 0; i < 9; i++)
+  {
+    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]);
+}
+
+void
+CxadflashPlayer::xadplayer_update ()
+{
+  unsigned short event_pos = (tune[0x600 + flash.order_pos] * 1152) +
+    (flash.pattern_pos * 18) + 0x633;
+
+  for (int i = 0; i < 9; 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);
+#endif
+
+    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]);
+    }
+    else
+    {
+      if (event_b1 == 0x01)
+        flash.pattern_pos = 0x3F;   // 1.0x01: Pattern Break
+
+      unsigned char fx = (event_b1 >> 4);
+      unsigned char fx_p = (event_b1 & 0x0F);
+
+      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 0x0E:                      // 1.0xEy: ? (increase some value)
+      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);
+
+        // is note ?
+        if (event_b0 != 0x7F)
+        {
+          unsigned short note_encoded = flash_notes_encoded[event_b0];
+          unsigned short freq = flash_notes[(note_encoded >> 8) - 1];
+
+          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);
+        }
+      }
+
+      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);
+      }
+      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);
+      }
+    }
+  }
+
+  // next row
+  flash.pattern_pos++;
+
+  // end of pattern ?
+  if (flash.pattern_pos >= 0x40)
+  {
+    flash.pattern_pos = 0;
+
+    flash.order_pos++;
+
+    // end of module ?
+    if (tune[0x600 + flash.order_pos] == 0xFF)
+    {
+      flash.order_pos = 0;
+
+      plr.looping = 1;
+    }
+  }
+}
+
+float
+CxadflashPlayer::xadplayer_getrefresh ()
+{
+  return 17.5f;
+}
+
+std::string CxadflashPlayer::xadplayer_gettype ()
+{
+  return std::string ("xad: flash player");
+}
+
+unsigned int
+CxadflashPlayer::xadplayer_getinstruments ()
+{
+  return 32;
+}
diff --git a/src/adplug/core/flash.cxx b/src/adplug/core/flash.cxx
deleted file mode 100644
index 30df8b0c3774..000000000000
--- a/src/adplug/core/flash.cxx
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * [xad] FLASH player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : LA-INTRO.EXE
-     type : Lunatic Asylum BBStro
-     tune : by Rogue [Logic Design]
-   player : by Flash [Logic Design]
-*/
-
-#include "flash.h"
-#include "debug.h"
-
-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,
-  0x2B, 0x28, 0x4B, 0x48, 0x6B, 0x68, 0x8B, 0x88, 0xC3, 0xEB, 0xE8,
-  0x2C, 0x29, 0x4C, 0x49, 0x6C, 0x69, 0x8C, 0x89, 0xC4, 0xEC, 0xE9,
-  0x2D, 0x2A, 0x4D, 0x4A, 0x6D, 0x6A, 0x8D, 0x8A, 0xC5, 0xED, 0xEA,
-  0x33, 0x30, 0x53, 0x50, 0x73, 0x70, 0x93, 0x90, 0xC6, 0xF3, 0xF0,
-  0x34, 0x31, 0x54, 0x51, 0x74, 0x71, 0x94, 0x91, 0xC7, 0xF4, 0xF1,
-  0x35, 0x32, 0x55, 0x52, 0x75, 0x72, 0x95, 0x92, 0xC8, 0xF5, 0xF2
-};
-
-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,
-  0x115, 0x215, 0x315
-};
-
-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] = {
-  0x00, 0x00, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-CPlayer *
-CxadflashPlayer::factory (Copl * newopl)
-{
-  return new CxadflashPlayer (newopl);
-}
-
-void
-CxadflashPlayer::xadplayer_rewind (int subsong)
-{
-  int i;
-
-  plr.speed = xad.speed;
-
-  flash.order_pos = 0;
-  flash.pattern_pos = 0;
-
-  opl_write (0x08, 0x00);
-  opl_write (0xBD, 0x00);
-
-  // assign default instrument
-  for (i = 0; i < 9; i++)
-  {
-    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]);
-}
-
-void
-CxadflashPlayer::xadplayer_update ()
-{
-  unsigned short event_pos = (tune[0x600 + flash.order_pos] * 1152) +
-    (flash.pattern_pos * 18) + 0x633;
-
-  for (int i = 0; i < 9; 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);
-#endif
-
-    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]);
-    }
-    else
-    {
-      if (event_b1 == 0x01)
-        flash.pattern_pos = 0x3F;   // 1.0x01: Pattern Break
-
-      unsigned char fx = (event_b1 >> 4);
-      unsigned char fx_p = (event_b1 & 0x0F);
-
-      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 0x0E:                      // 1.0xEy: ? (increase some value)
-      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);
-
-        // is note ?
-        if (event_b0 != 0x7F)
-        {
-          unsigned short note_encoded = flash_notes_encoded[event_b0];
-          unsigned short freq = flash_notes[(note_encoded >> 8) - 1];
-
-          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);
-        }
-      }
-
-      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);
-      }
-      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);
-      }
-    }
-  }
-
-  // next row
-  flash.pattern_pos++;
-
-  // end of pattern ?
-  if (flash.pattern_pos >= 0x40)
-  {
-    flash.pattern_pos = 0;
-
-    flash.order_pos++;
-
-    // end of module ?
-    if (tune[0x600 + flash.order_pos] == 0xFF)
-    {
-      flash.order_pos = 0;
-
-      plr.looping = 1;
-    }
-  }
-}
-
-float
-CxadflashPlayer::xadplayer_getrefresh ()
-{
-  return 17.5f;
-}
-
-std::string CxadflashPlayer::xadplayer_gettype ()
-{
-  return std::string ("xad: flash player");
-}
-
-unsigned int
-CxadflashPlayer::xadplayer_getinstruments ()
-{
-  return 32;
-}
diff --git a/src/adplug/core/fmc.cc b/src/adplug/core/fmc.cc
new file mode 100644
index 000000000000..c92bfba897c7
--- /dev/null
+++ b/src/adplug/core/fmc.cc
@@ -0,0 +1,243 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2007 Simon Peter <dn.tlp at 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
+
+  fmc.cpp - FMC Loader by Riven the Mage <riven at ok.ru>
+*/
+
+#include <string.h>
+
+#include "fmc.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *
+CfmcLoader::factory (Copl * newopl)
+{
+  return new CfmcLoader (newopl);
+}
+
+bool
+CfmcLoader::load (VFSFile & fd, 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 };
+
+  int i, j, k, t = 0;
+
+  // read header
+  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;
+  }
+
+  // init CmodPlayer
+  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);
+
+  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);
+  }
+
+  // load tracks
+  for (i = 0; i < 64; i++)
+  {
+    if (f->ateof ())
+      break;
+
+    for (j = 0; j < header.numchan; j++)
+    {
+      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++;
+    }
+  }
+  fp.close (f);
+
+  // convert instruments
+  for (i = 0; i < 31; i++)
+    buildinst (i);
+
+  // order length
+  for (i = 0; i < 256; i++)
+  {
+    if (order[i] >= 0xFE)
+    {
+      length = i;
+      break;
+    }
+  }
+
+  // data for Protracker
+  activechan = (0xffffffff >> (32 - header.numchan)) << (32 - header.numchan);
+  nop = t / header.numchan;
+  restartpos = 0;
+
+  // flags
+  flags = Faust;
+
+  rewind (0);
+
+  return true;
+}
+
+float
+CfmcLoader::getrefresh ()
+{
+  return 50.0f;
+}
+
+std::string CfmcLoader::gettype ()
+{
+  return std::string ("Faust Music Creator");
+}
+
+std::string CfmcLoader::gettitle ()
+{
+  return std::string (header.title);
+}
+
+std::string CfmcLoader::getinstrument (unsigned int n)
+{
+  return std::string (instruments[n].name);
+}
+
+unsigned int
+CfmcLoader::getinstruments ()
+{
+  return 32;
+}
+
+/* -------- Private Methods ------------------------------- */
+
+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[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;
+}
diff --git a/src/adplug/core/fmc.cxx b/src/adplug/core/fmc.cxx
deleted file mode 100644
index d853e9332499..000000000000
--- a/src/adplug/core/fmc.cxx
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
-  Adplug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2007 Simon Peter <dn.tlp at 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
-
-  fmc.cpp - FMC Loader by Riven the Mage <riven at ok.ru>
-*/
-
-#include <string.h>
-
-#include "fmc.h"
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *
-CfmcLoader::factory (Copl * newopl)
-{
-  return new CfmcLoader (newopl);
-}
-
-bool
-CfmcLoader::load (VFSFile * fd, 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 };
-
-  int i, j, k, t = 0;
-
-  // read header
-  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;
-  }
-
-  // init CmodPlayer
-  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);
-
-  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);
-  }
-
-  // load tracks
-  for (i = 0; i < 64; i++)
-  {
-    if (f->ateof ())
-      break;
-
-    for (j = 0; j < header.numchan; j++)
-    {
-      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++;
-    }
-  }
-  fp.close (f);
-
-  // convert instruments
-  for (i = 0; i < 31; i++)
-    buildinst (i);
-
-  // order length
-  for (i = 0; i < 256; i++)
-  {
-    if (order[i] >= 0xFE)
-    {
-      length = i;
-      break;
-    }
-  }
-
-  // data for Protracker
-  activechan = (0xffffffff >> (32 - header.numchan)) << (32 - header.numchan);
-  nop = t / header.numchan;
-  restartpos = 0;
-
-  // flags
-  flags = Faust;
-
-  rewind (0);
-
-  return true;
-}
-
-float
-CfmcLoader::getrefresh ()
-{
-  return 50.0f;
-}
-
-std::string CfmcLoader::gettype ()
-{
-  return std::string ("Faust Music Creator");
-}
-
-std::string CfmcLoader::gettitle ()
-{
-  return std::string (header.title);
-}
-
-std::string CfmcLoader::getinstrument (unsigned int n)
-{
-  return std::string (instruments[n].name);
-}
-
-unsigned int
-CfmcLoader::getinstruments ()
-{
-  return 32;
-}
-
-/* -------- Private Methods ------------------------------- */
-
-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[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;
-}
diff --git a/src/adplug/core/fmc.h b/src/adplug/core/fmc.h
index 95ef0f4ca366..3f4eab68ec1f 100644
--- a/src/adplug/core/fmc.h
+++ b/src/adplug/core/fmc.h
@@ -28,7 +28,7 @@ class CfmcLoader: public CmodPlayer
 
 		CfmcLoader(Copl *newopl) : CmodPlayer(newopl) { };
 
-		bool	load(VFSFile *fd, const CFileProvider &fp);
+		bool	load(VFSFile &fd, const CFileProvider &fp);
 		float	getrefresh();
 
 		std::string	gettype();
diff --git a/src/adplug/core/fmopl.c b/src/adplug/core/fmopl.c
deleted file mode 100644
index 81d645981b9a..000000000000
--- a/src/adplug/core/fmopl.c
+++ /dev/null
@@ -1,1389 +0,0 @@
-/*
-**
-** File: fmopl.c -- software implementation of FM sound generator
-**
-** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
-**
-** Version 0.37a
-**
-*/
-
-/*
-	preliminary :
-	Problem :
-	note:
-*/
-
-/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
- *
- * 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
- */
-
-#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 "fmopl.h"
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-/* -------------------- for debug --------------------- */
-/* #define OPL_OUTPUT_LOG */
-#ifdef OPL_OUTPUT_LOG
-static FILE *opl_dbg_fp = NULL;
-static FM_OPL *opl_dbg_opl[16];
-static int opl_dbg_maxchip,opl_dbg_chip;
-#endif
-
-/* -------------------- preliminary define section --------------------- */
-/* attack/decay rate time rate */
-#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
-#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
-
-#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
-
-#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_MAXOUT (0x7fff<<OPL_OUTSB)
-#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
-
-/* -------------------- quality selection --------------------- */
-
-/* sinwave entries */
-/* used static memory = SIN_ENT * 4 (byte) */
-#define SIN_ENT 2048
-
-/* output level entries (envelope,sinwave) */
-/* envelope counter lower bits */
-#define ENV_BITS 16
-/* envelope output entries */
-#define EG_ENT   4096
-/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
-/* used static  memory = EG_ENT*4 (byte)                     */
-
-#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
-#define EG_DED   EG_OFF
-#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
-#define EG_AED   EG_DST
-#define EG_AST   0                       /* ATTACK START */
-
-#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
-
-/* LFO table entries */
-#define VIB_ENT 512
-#define VIB_SHIFT (32-9)
-#define AMS_ENT 512
-#define AMS_SHIFT (32-9)
-
-#define VIB_RATE 256
-
-/* -------------------- local defines , macros --------------------- */
-
-/* register number to channel number , slot offset */
-#define SLOT1 0
-#define SLOT2 1
-
-/* envelope phase */
-#define ENV_MOD_RR  0x00
-#define ENV_MOD_DR  0x01
-#define ENV_MOD_AR  0x02
-
-/* -------------------- 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
-};
-
-/* key scale level */
-/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
-#define DV (EG_STEP/2)
-static const UINT32 KSL_TABLE[8*16]=
-{
-	/* OCT 0 */
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	/* OCT 1 */
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
-	 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
-	/* OCT 2 */
-	 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
-	 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
-	 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
-	 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
-	/* OCT 3 */
-	 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
-	 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
-	 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
-	 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
-	/* OCT 4 */
-	 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
-	 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
-	 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
-	10.875/DV,11.250/DV,11.625/DV,12.000/DV,
-	/* OCT 5 */
-	 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
-	 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
-	12.000/DV,12.750/DV,13.125/DV,13.500/DV,
-	13.875/DV,14.250/DV,14.625/DV,15.000/DV,
-	/* OCT 6 */
-	 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
-	12.000/DV,13.125/DV,13.875/DV,14.625/DV,
-	15.000/DV,15.750/DV,16.125/DV,16.500/DV,
-	16.875/DV,17.250/DV,17.625/DV,18.000/DV,
-	/* OCT 7 */
-	 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
-	15.000/DV,16.125/DV,16.875/DV,17.625/DV,
-	18.000/DV,18.750/DV,19.125/DV,19.500/DV,
-	19.875/DV,20.250/DV,20.625/DV,21.000/DV
-};
-#undef DV
-
-/* sustain lebel table (3db per step) */
-/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
-#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
-static const INT32 SL_TABLE[16]={
- SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
- SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
-};
-#undef SC
-
-#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
-/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
-/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
-/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
-static INT32 *TL_TABLE;
-
-/* pointers to TL_TABLE with sinwave output offset */
-static INT32 **SIN_TABLE;
-
-/* LFO table */
-static INT32 *AMS_TABLE;
-static INT32 *VIB_TABLE;
-
-/* envelope output curve table */
-/* attack + decay + OFF */
-static INT32 ENV_CURVE[2*EG_ENT+1];
-
-/* multiple table */
-#define ML 2
-static const UINT32 MUL_TABLE[16]= {
-/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
-   0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
-   8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
-};
-#undef ML
-
-/* dummy attack / decay rate ( when rate == 0 ) */
-static INT32 RATE_0[16]=
-{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-/* -------------------- static state --------------------- */
-
-/* lock level of common table */
-static int num_lock = 0;
-
-/* work table */
-static void *cur_chip = NULL;	/* current chip point */
-/* currenct chip state */
-/* static OPLSAMPLE  *bufL,*bufR; */
-static OPL_CH *S_CH;
-static OPL_CH *E_CH;
-OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
-
-static INT32 outd[1];
-static INT32 ams;
-static INT32 vib;
-INT32  *ams_table;
-INT32  *vib_table;
-static INT32 amsIncr;
-static INT32 vibIncr;
-static INT32 feedback2;		/* connect for SLOT 2 */
-
-/* log output level */
-#define LOG_ERR  3      /* ERROR       */
-#define LOG_WAR  2      /* WARNING     */
-#define LOG_INF  1      /* INFORMATION */
-
-//#define LOG_LEVEL LOG_INF
-#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;
-
-	return val;
-}
-
-/* status set and IRQ handling */
-static 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);
-		}
-	}
-}
-
-/* status reset and IRQ handling */
-static 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);
-		}
-	}
-}
-
-/* IRQ mask set */
-static 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);
-}
-
-/* ----- key on  ----- */
-static 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;
-}
-/* ----- key off ----- */
-static 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;
-	}
-}
-
-/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
-/* return : envelope output */
-static 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);
-}
-
-/* set algorythm connection */
-static void set_algorythm( OPL_CH *CH)
-{
-	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)
-{
-	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)
-{
-	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)
-{
-	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 */
-
-	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)
-{
-	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)
-{
-	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 )
-{
-	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 )
-{
-	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;
-	}
-	for (i = 60;i < 76;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) ));
-	}
-#endif
-}
-
-/* ---------- generic table initialize ---------- */
-static int OPLOpenTable( void )
-{
-	int s,t;
-	double rate;
-	int i,j;
-	double pom;
-
-	/* allocate dynamic tables */
-	if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
-		return 0;
-	if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
-	{
-		free(TL_TABLE);
-		return 0;
-	}
-	if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
-	{
-		free(TL_TABLE);
-		free(SIN_TABLE);
-		return 0;
-	}
-	if( (VIB_TABLE = 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];
-        /* 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;
-}
-
-
-static void OPLCloseTable( void )
-{
-	free(TL_TABLE);
-	free(SIN_TABLE);
-	free(AMS_TABLE);
-	free(VIB_TABLE);
-}
-
-/* CSM Key Controll */
-static 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 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;
-}
-
-/* ---------- 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;
-#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;
-#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;
-#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)
-			{
-#if 0
-				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;
-	}
-}
-
-/* lock/unlock for common table */
-static int OPL_LockTable(void)
-{
-	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)
-{
-	if(num_lock) num_lock--;
-	if(num_lock) return;
-	/* last time */
-	cur_chip = NULL;
-	OPLCloseTable();
-}
-
-#if (BUILD_YM3812 || BUILD_YM3526)
-/*******************************************************************************/
-/*		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;
-    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;
-#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);
-	}
-#endif
-}
-#endif /* (BUILD_YM3812 || BUILD_YM3526) */
-
-#if BUILD_Y8950
-
-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;
-    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;
-}
-#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;
-		}
-	}
-#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);
-	}
-#endif
-}
-
-/* ----------  Create one of vietual YM3812 ----------       */
-/* '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 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);
-#endif
-	/* allocate memory block */
-	ptr = 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);
-#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);
-#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++;
-	}
-#endif
-	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 = NULL;
-	}
-#endif
-	OPL_UnLockTable();
-	free(OPL);
-}
-
-/* ----------  Option handlers ----------       */
-
-void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
-{
-	OPL->TimerHandler   = TimerHandler;
-	OPL->TimerParam = channelOffset;
-}
-void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
-{
-	OPL->IRQHandler     = IRQHandler;
-	OPL->IRQParam = param;
-}
-void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int 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;
-}
-
-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;
-}
-#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);
-#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);
-	}
-#endif
-		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 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;
-}
-
-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;
-}
diff --git a/src/adplug/core/fmopl.cc b/src/adplug/core/fmopl.cc
new file mode 100644
index 000000000000..348e51c36659
--- /dev/null
+++ b/src/adplug/core/fmopl.cc
@@ -0,0 +1,1393 @@
+/*
+**
+** File: fmopl.c -- software implementation of FM sound generator
+**
+** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
+**
+** Version 0.37a
+**
+*/
+
+/*
+	preliminary :
+	Problem :
+	note:
+*/
+
+/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
+ *
+ * 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
+ */
+
+#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 "fmopl.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+/* -------------------- for debug --------------------- */
+/* #define OPL_OUTPUT_LOG */
+#ifdef OPL_OUTPUT_LOG
+static FILE *opl_dbg_fp = nullptr;
+static FM_OPL *opl_dbg_opl[16];
+static int opl_dbg_maxchip,opl_dbg_chip;
+#endif
+
+/* -------------------- preliminary define section --------------------- */
+/* attack/decay rate time rate */
+#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
+#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
+
+#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
+
+#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_MAXOUT (0x7fff<<OPL_OUTSB)
+#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
+
+/* -------------------- quality selection --------------------- */
+
+/* sinwave entries */
+/* used static memory = SIN_ENT * 4 (byte) */
+#define SIN_ENT 2048
+
+/* output level entries (envelope,sinwave) */
+/* envelope counter lower bits */
+#define ENV_BITS 16
+/* envelope output entries */
+#define EG_ENT   4096
+/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
+/* used static  memory = EG_ENT*4 (byte)                     */
+
+#define EG_OFF   ((2*EG_ENT)<<ENV_BITS)  /* OFF          */
+#define EG_DED   EG_OFF
+#define EG_DST   (EG_ENT<<ENV_BITS)      /* DECAY  START */
+#define EG_AED   EG_DST
+#define EG_AST   0                       /* ATTACK START */
+
+#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
+
+/* LFO table entries */
+#define VIB_ENT 512
+#define VIB_SHIFT (32-9)
+#define AMS_ENT 512
+#define AMS_SHIFT (32-9)
+
+#define VIB_RATE 256
+
+/* -------------------- local defines , macros --------------------- */
+
+/* register number to channel number , slot offset */
+#define SLOT1 0
+#define SLOT2 1
+
+/* envelope phase */
+#define ENV_MOD_RR  0x00
+#define ENV_MOD_DR  0x01
+#define ENV_MOD_AR  0x02
+
+/* -------------------- 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
+};
+
+/* key scale level */
+/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
+#define DV (EG_STEP/2)
+#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)
+};
+#undef U
+#undef DV
+
+/* sustain lebel table (3db per step) */
+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
+#define SC(db) (INT32)((db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST)
+static const INT32 SL_TABLE[16]={
+ SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+ SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
+};
+#undef SC
+
+#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
+/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
+/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
+/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
+static INT32 *TL_TABLE;
+
+/* pointers to TL_TABLE with sinwave output offset */
+static INT32 **SIN_TABLE;
+
+/* LFO table */
+static INT32 *AMS_TABLE;
+static INT32 *VIB_TABLE;
+
+/* envelope output curve table */
+/* attack + decay + OFF */
+static INT32 ENV_CURVE[2*EG_ENT+1];
+
+/* multiple table */
+#define ML 2
+static const UINT32 MUL_TABLE[16]= {
+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
+   ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML,
+   8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML
+};
+#undef ML
+
+/* dummy attack / decay rate ( when rate == 0 ) */
+static INT32 RATE_0[16]=
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+/* -------------------- static state --------------------- */
+
+/* lock level of common table */
+static int num_lock = 0;
+
+/* work table */
+static void *cur_chip = nullptr;	/* current chip point */
+/* currenct chip state */
+/* static OPLSAMPLE  *bufL,*bufR; */
+static OPL_CH *S_CH;
+static OPL_CH *E_CH;
+OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
+
+static INT32 outd[1];
+static INT32 ams;
+static INT32 vib;
+INT32  *ams_table;
+INT32  *vib_table;
+static INT32 amsIncr;
+static INT32 vibIncr;
+static INT32 feedback2;		/* connect for SLOT 2 */
+
+/* log output level */
+#define LOG_ERR  3      /* ERROR       */
+#define LOG_WAR  2      /* WARNING     */
+#define LOG_INF  1      /* INFORMATION */
+
+//#define LOG_LEVEL LOG_INF
+#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;
+
+	return val;
+}
+
+/* status set and IRQ handling */
+static 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);
+		}
+	}
+}
+
+/* status reset and IRQ handling */
+static 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);
+		}
+	}
+}
+
+/* IRQ mask set */
+static 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);
+}
+
+/* ----- key on  ----- */
+static 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;
+}
+/* ----- key off ----- */
+static 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;
+	}
+}
+
+/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
+/* return : envelope output */
+static 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);
+}
+
+/* set algorythm connection */
+static void set_algorythm( OPL_CH *CH)
+{
+	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)
+{
+	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)
+{
+	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)
+{
+	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 */
+
+	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)
+{
+	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)
+{
+	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 )
+{
+	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 )
+{
+	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];
+	}
+#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) ));
+	}
+#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 */
+
+        /* degree 0   -  90    , degree 180 -  90 : plus section */
+		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;
+}
+
+
+static void OPLCloseTable( void )
+{
+	free(TL_TABLE);
+	free(SIN_TABLE);
+	free(AMS_TABLE);
+	free(VIB_TABLE);
+}
+
+/* CSM Key Controll */
+static 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 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;
+}
+
+/* ---------- 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;
+#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;
+#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;
+#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)
+			{
+#if 0
+				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;
+	}
+}
+
+/* lock/unlock for common table */
+static int OPL_LockTable(void)
+{
+	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;
+}
+
+static void OPL_UnLockTable(void)
+{
+	if(num_lock) num_lock--;
+	if(num_lock) return;
+	/* last time */
+	cur_chip = nullptr;
+	OPLCloseTable();
+}
+
+#if (BUILD_YM3812 || BUILD_YM3526)
+/*******************************************************************************/
+/*		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;
+    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;
+#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);
+	}
+#endif
+}
+#endif /* (BUILD_YM3812 || BUILD_YM3526) */
+
+#if BUILD_Y8950
+
+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;
+    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;
+}
+#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;
+		}
+	}
+#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);
+	}
+#endif
+}
+
+/* ----------  Create one of vietual YM3812 ----------       */
+/* '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;
+#if BUILD_Y8950
+	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;
+#if BUILD_Y8950
+	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);
+#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++;
+	}
+#endif
+	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;
+	}
+#endif
+	OPL_UnLockTable();
+	free(OPL);
+}
+
+/* ----------  Option handlers ----------       */
+
+void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
+{
+	OPL->TimerHandler   = TimerHandler;
+	OPL->TimerParam = channelOffset;
+}
+void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
+{
+	OPL->IRQHandler     = IRQHandler;
+	OPL->IRQParam = param;
+}
+void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int 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;
+}
+
+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;
+}
+#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);
+#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);
+	}
+#endif
+		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 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;
+}
+
+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;
+}
diff --git a/src/adplug/core/fprovide.cc b/src/adplug/core/fprovide.cc
new file mode 100644
index 000000000000..7b6c66507722
--- /dev/null
+++ b/src/adplug/core/fprovide.cc
@@ -0,0 +1,73 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp at 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
+ *
+ * fprovide.cpp - File provider class framework, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+#include <binio.h>
+#include <binfile.h>
+
+#include "fprovide.h"
+
+#include <libaudcore/audstrings.h>
+
+/***** CFileProvider *****/
+
+bool CFileProvider::extension(const std::string &filename,
+			      const std::string &extension)
+{
+  return str_has_suffix_nocase(filename.c_str(), extension.c_str());
+}
+
+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;
+}
+
+/***** CProvider_Filesystem *****/
+
+binistream *CProvider_Filesystem::open(VFSFile &fd) const
+{
+  if(!fd) return 0;
+
+  vfsistream *f = new vfsistream(&fd);
+
+  if(!f) return 0;
+  if(f->error()) { delete f; return 0; }
+
+  // Open all files as little endian with IEEE floats by default
+  f->setFlag(binio::BigEndian, false); f->setFlag(binio::FloatIEEE);
+
+  return f;
+}
+
+void CProvider_Filesystem::close(binistream *f) const
+{
+  vfsistream *ff = (vfsistream *)f;
+
+  if(f) {
+    delete ff;
+  }
+}
diff --git a/src/adplug/core/fprovide.cxx b/src/adplug/core/fprovide.cxx
deleted file mode 100644
index 0d6b57b7ad3a..000000000000
--- a/src/adplug/core/fprovide.cxx
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp at 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
- *
- * fprovide.cpp - File provider class framework, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-#include <binio.h>
-#include <binfile.h>
-
-#include <glib.h>
-
-#include "fprovide.h"
-
-/***** CFileProvider *****/
-
-bool CFileProvider::extension(const std::string &filename,
-			      const std::string &extension)
-{
-  const char *fname = filename.c_str(), *ext = extension.c_str();
-
-  if(strlen(fname) < strlen(ext) ||
-     g_ascii_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;
-}
-
-/***** CProvider_Filesystem *****/
-
-binistream *CProvider_Filesystem::open(VFSFile *fd) const
-{
-  vfsistream *f = new vfsistream(fd);
-
-  if(!f) return 0;
-  if(f->error()) { delete f; return 0; }
-
-  // Open all files as little endian with IEEE floats by default
-  f->setFlag(binio::BigEndian, false); f->setFlag(binio::FloatIEEE);
-
-  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 ec4d9b5f4784..6755ee9b86f9 100644
--- a/src/adplug/core/fprovide.h
+++ b/src/adplug/core/fprovide.h
@@ -32,7 +32,7 @@ public:
     {
     }
 
-  virtual binistream *open(VFSFile *) const = 0;
+  virtual binistream *open(VFSFile &) const = 0;
   virtual void close(binistream *) const = 0;
 
   static bool extension(const std::string &filename,
@@ -43,7 +43,7 @@ public:
 class CProvider_Filesystem: public CFileProvider
 {
 public:
-  virtual binistream *open(VFSFile *) const;
+  virtual binistream *open(VFSFile &) const;
   virtual void close(binistream *f) const;
 };
 
diff --git a/src/adplug/core/hsc.cc b/src/adplug/core/hsc.cc
new file mode 100644
index 000000000000..121d2d2bf321
--- /dev/null
+++ b/src/adplug/core/hsc.cc
@@ -0,0 +1,389 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
+ *
+ * hsc.cpp - HSC Player by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "hsc.h"
+#include "debug.h"
+
+/*** public methods **************************************/
+
+CPlayer *
+ChscPlayer::factory (Copl * newopl)
+{
+  return new ChscPlayer (newopl);
+}
+
+bool
+ChscPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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);
+    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
+    instr[i][2] ^= (instr[i][2] & 0x40) << 1;
+    instr[i][3] ^= (instr[i][3] & 0x40) << 1;
+    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);
+
+  fp.close (f);
+  rewind (0);                   // rewind module
+  return true;
+}
+
+bool
+ChscPlayer::update ()
+{
+  // general vars
+  unsigned char chan, pattnr, note, effect, eff_op, inst, vol, Okt, db;
+  unsigned short Fnr;
+  unsigned long pattoff;
+
+  del--;                        // player speed handling
+  if (del)
+    return !songend;            // nothing done
+
+  if (fadein)                   // fade-in handling
+    fadein--;
+
+  pattnr = song[songpos];
+  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;
+  }
+
+  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);
+      continue;
+    }
+    eff_op = effect & 0x0f;
+    inst = channel[chan].inst;
+    if (note)
+      channel[chan].slide = 0;
+
+    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)
+       * 04 - Set Mainvolume to 0
+       *
+       * 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
+      }
+      break;
+    case 0x20:
+    case 0x10:                 // manual slides
+      if (effect & 0x10)
+      {
+        channel[chan].freq += eff_op;
+        channel[chan].slide += eff_op;
+      }
+      else
+      {
+        channel[chan].freq -= eff_op;
+        channel[chan].slide -= eff_op;
+      }
+      if (!note)
+        setfreq (chan, channel[chan].freq);
+      break;
+    case 0x50:                 // set percussion instrument (unimplemented)
+      break;
+    case 0x60:                 // set feedback
+      opl->write (0xc0 + chan,
+                  (instr[channel[chan].inst][8] & 1) + (eff_op << 1));
+      break;
+    case 0xa0:                 // set carrier volume
+      vol = eff_op << 2;
+      opl->write (0x43 + op_table[chan],
+                  vol | (instr[channel[chan].inst][2] & ~63));
+      break;
+    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));
+      else
+        opl->write (0x40 + op_table[chan], vol | (instr[inst][3] & ~63));
+      break;
+    case 0xc0:                 // set instrument volume
+      db = eff_op << 2;
+      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));
+      break;
+    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 (!note)                  // note handling
+      continue;
+    note--;
+
+    if ((note == 0x7f - 1) || ((note / 12) & ~7))
+    {                           // pause (7fh)
+      adl_freq[chan] &= ~32;
+      opl->write (0xb0 + chan, adl_freq[chan]);
+      continue;
+    }
+
+    // play the note
+    if (mtkmode)                // imitate MPU-401 Trakker bug
+      note--;
+    Okt = ((note / 12) & 7) << 2;
+    Fnr = note_table[(note % 12)] + instr[inst][11] + channel[chan].slide;
+    channel[chan].freq = Fnr;
+    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
+      }
+      opl->write (0xbd, bd);
+    }
+  }
+
+  del = speed;                  // player speed-timing
+  if (pattbreak)
+  {                             // do post-effect handling
+    pattpos = 0;                // pattern break!
+    pattbreak = 0;
+    songpos++;
+    songpos %= 50;
+    if (!songpos)
+      songend = 1;
+  }
+  else
+  {
+    pattpos++;
+    pattpos &= 63;              // advance in pattern data
+    if (!pattpos)
+    {
+      songpos++;
+      songpos %= 50;
+      if (!songpos)
+        songend = 1;
+    }
+  }
+  return !songend;              // still playing
+}
+
+void
+ChscPlayer::rewind (int subsong)
+{
+  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
+}
+
+unsigned int
+ChscPlayer::getpatterns ()
+{
+  unsigned char poscnt, pattcnt = 0;
+
+  // count patterns
+  for (poscnt = 0; poscnt < 51 && song[poscnt] != 0xff; poscnt++)
+    if (song[poscnt] > pattcnt)
+      pattcnt = song[poscnt];
+
+  return (pattcnt + 1);
+}
+
+unsigned int
+ChscPlayer::getorders ()
+{
+  unsigned char poscnt;
+
+  // count positions
+  for (poscnt = 0; poscnt < 51; poscnt++)
+    if (song[poscnt] == 0xff)
+      break;
+
+  return poscnt;
+}
+
+unsigned int
+ChscPlayer::getinstruments ()
+{
+  unsigned char instcnt, instnum = 0, i;
+  bool isinst;
+
+  // count instruments
+  for (instcnt = 0; instcnt < 128; instcnt++)
+  {
+    isinst = false;
+    for (i = 0; i < 12; i++)
+      if (instr[instcnt][i])
+        isinst = true;
+    if (isinst)
+      instnum++;
+  }
+
+  return instnum;
+}
+
+/*** private methods *************************************/
+
+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]);
+}
+
+void
+ChscPlayer::setvolume (unsigned char chan, int volc, int volm)
+{
+  unsigned char *ins = instr[channel[chan].inst];
+  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));
+  else
+    opl->write (0x40 + op, ins[3]); // modulator
+}
+
+void
+ChscPlayer::setinstr (unsigned char chan, unsigned char insnr)
+{
+  unsigned char *ins = instr[insnr];
+  char op = op_table[chan];
+
+  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);
+}
diff --git a/src/adplug/core/hsc.cxx b/src/adplug/core/hsc.cxx
deleted file mode 100644
index e3e01123ed07..000000000000
--- a/src/adplug/core/hsc.cxx
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
- *
- * hsc.cpp - HSC Player by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "hsc.h"
-#include "debug.h"
-
-/*** public methods **************************************/
-
-CPlayer *
-ChscPlayer::factory (Copl * newopl)
-{
-  return new ChscPlayer (newopl);
-}
-
-bool
-ChscPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  int i;
-
-  // file validation section
-  if (!f || !fp.extension (vfs_get_filename (fd), ".hsc") || fp.filesize (f) > 59187)
-  {
-    AdPlug_LogWrite ("ChscPlayer::load(\"%s\"): Not a HSC file!\n",
-     vfs_get_filename (fd));
-    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
-    instr[i][2] ^= (instr[i][2] & 0x40) << 1;
-    instr[i][3] ^= (instr[i][3] & 0x40) << 1;
-    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);
-
-  fp.close (f);
-  rewind (0);                   // rewind module
-  return true;
-}
-
-bool
-ChscPlayer::update ()
-{
-  // general vars
-  unsigned char chan, pattnr, note, effect, eff_op, inst, vol, Okt, db;
-  unsigned short Fnr;
-  unsigned long pattoff;
-
-  del--;                        // player speed handling
-  if (del)
-    return !songend;            // nothing done
-
-  if (fadein)                   // fade-in handling
-    fadein--;
-
-  pattnr = song[songpos];
-  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;
-  }
-
-  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);
-      continue;
-    }
-    eff_op = effect & 0x0f;
-    inst = channel[chan].inst;
-    if (note)
-      channel[chan].slide = 0;
-
-    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)
-       * 04 - Set Mainvolume to 0
-       *
-       * 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
-      }
-      break;
-    case 0x20:
-    case 0x10:                 // manual slides
-      if (effect & 0x10)
-      {
-        channel[chan].freq += eff_op;
-        channel[chan].slide += eff_op;
-      }
-      else
-      {
-        channel[chan].freq -= eff_op;
-        channel[chan].slide -= eff_op;
-      }
-      if (!note)
-        setfreq (chan, channel[chan].freq);
-      break;
-    case 0x50:                 // set percussion instrument (unimplemented)
-      break;
-    case 0x60:                 // set feedback
-      opl->write (0xc0 + chan,
-                  (instr[channel[chan].inst][8] & 1) + (eff_op << 1));
-      break;
-    case 0xa0:                 // set carrier volume
-      vol = eff_op << 2;
-      opl->write (0x43 + op_table[chan],
-                  vol | (instr[channel[chan].inst][2] & ~63));
-      break;
-    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));
-      else
-        opl->write (0x40 + op_table[chan], vol | (instr[inst][3] & ~63));
-      break;
-    case 0xc0:                 // set instrument volume
-      db = eff_op << 2;
-      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));
-      break;
-    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 (!note)                  // note handling
-      continue;
-    note--;
-
-    if ((note == 0x7f - 1) || ((note / 12) & ~7))
-    {                           // pause (7fh)
-      adl_freq[chan] &= ~32;
-      opl->write (0xb0 + chan, adl_freq[chan]);
-      continue;
-    }
-
-    // play the note
-    if (mtkmode)                // imitate MPU-401 Trakker bug
-      note--;
-    Okt = ((note / 12) & 7) << 2;
-    Fnr = note_table[(note % 12)] + instr[inst][11] + channel[chan].slide;
-    channel[chan].freq = Fnr;
-    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
-      }
-      opl->write (0xbd, bd);
-    }
-  }
-
-  del = speed;                  // player speed-timing
-  if (pattbreak)
-  {                             // do post-effect handling
-    pattpos = 0;                // pattern break!
-    pattbreak = 0;
-    songpos++;
-    songpos %= 50;
-    if (!songpos)
-      songend = 1;
-  }
-  else
-  {
-    pattpos++;
-    pattpos &= 63;              // advance in pattern data
-    if (!pattpos)
-    {
-      songpos++;
-      songpos %= 50;
-      if (!songpos)
-        songend = 1;
-    }
-  }
-  return !songend;              // still playing
-}
-
-void
-ChscPlayer::rewind (int subsong)
-{
-  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
-}
-
-unsigned int
-ChscPlayer::getpatterns ()
-{
-  unsigned char poscnt, pattcnt = 0;
-
-  // count patterns
-  for (poscnt = 0; poscnt < 51 && song[poscnt] != 0xff; poscnt++)
-    if (song[poscnt] > pattcnt)
-      pattcnt = song[poscnt];
-
-  return (pattcnt + 1);
-}
-
-unsigned int
-ChscPlayer::getorders ()
-{
-  unsigned char poscnt;
-
-  // count positions
-  for (poscnt = 0; poscnt < 51; poscnt++)
-    if (song[poscnt] == 0xff)
-      break;
-
-  return poscnt;
-}
-
-unsigned int
-ChscPlayer::getinstruments ()
-{
-  unsigned char instcnt, instnum = 0, i;
-  bool isinst;
-
-  // count instruments
-  for (instcnt = 0; instcnt < 128; instcnt++)
-  {
-    isinst = false;
-    for (i = 0; i < 12; i++)
-      if (instr[instcnt][i])
-        isinst = true;
-    if (isinst)
-      instnum++;
-  }
-
-  return instnum;
-}
-
-/*** private methods *************************************/
-
-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]);
-}
-
-void
-ChscPlayer::setvolume (unsigned char chan, int volc, int volm)
-{
-  unsigned char *ins = instr[channel[chan].inst];
-  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));
-  else
-    opl->write (0x40 + op, ins[3]); // modulator
-}
-
-void
-ChscPlayer::setinstr (unsigned char chan, unsigned char insnr)
-{
-  unsigned char *ins = instr[insnr];
-  char op = op_table[chan];
-
-  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);
-}
diff --git a/src/adplug/core/hsc.h b/src/adplug/core/hsc.h
index 80b88c3b50f8..b5a2ae7b6d6a 100644
--- a/src/adplug/core/hsc.h
+++ b/src/adplug/core/hsc.h
@@ -31,7 +31,7 @@ class ChscPlayer: public CPlayer
 
   ChscPlayer(Copl *newopl): CPlayer(newopl), mtkmode(0) {}
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong);
   float getrefresh() { return 18.2f; };	// refresh rate is fixed at 18.2Hz
diff --git a/src/adplug/core/hsp.cc b/src/adplug/core/hsp.cc
new file mode 100644
index 000000000000..e2eaf7a5d9cc
--- /dev/null
+++ b/src/adplug/core/hsp.cc
@@ -0,0 +1,86 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
+ *
+ * hsp.cpp - HSP Loader by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "hsp.h"
+
+CPlayer *
+ChspLoader::factory (Copl * newopl)
+{
+  return new ChspLoader (newopl);
+}
+
+bool
+ChspLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+  }
+
+  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);
+
+  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);
+  }
+  delete[]cmp;
+
+  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;
+
+  rewind (0);
+  return true;
+}
diff --git a/src/adplug/core/hsp.cxx b/src/adplug/core/hsp.cxx
deleted file mode 100644
index 81b983c00703..000000000000
--- a/src/adplug/core/hsp.cxx
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
- *
- * hsp.cpp - HSP Loader by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "hsp.h"
-
-CPlayer *
-ChspLoader::factory (Copl * newopl)
-{
-  return new ChspLoader (newopl);
-}
-
-bool
-ChspLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  unsigned long i, j, orgsize, filesize;
-  unsigned char *cmp, *org;
-  std::string filename (vfs_get_filename (fd));
-
-  // file validation section
-  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;
-  }
-
-  // load section
-  cmp = new unsigned char[filesize];
-  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);
-  }
-  delete[]cmp;
-
-  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;
-
-  rewind (0);
-  return true;
-}
diff --git a/src/adplug/core/hsp.h b/src/adplug/core/hsp.h
index caeb5ba8792c..691220d0e09c 100644
--- a/src/adplug/core/hsp.h
+++ b/src/adplug/core/hsp.h
@@ -33,7 +33,7 @@ public:
 		: ChscPlayer(newopl)
 	{};
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 };
 
 #endif
diff --git a/src/adplug/core/hybrid.cc b/src/adplug/core/hybrid.cc
new file mode 100644
index 000000000000..7333c4edfd45
--- /dev/null
+++ b/src/adplug/core/hybrid.cc
@@ -0,0 +1,268 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] HYBRID player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : HYBRID.EXE
+     type : Hybrid cracktro for Apache Longbow CD-RIP
+     tune : from 'Mig-29 Super Fulcrum' game by Domark
+   player : from 'Mig-29 Super Fulcrum' game by Domark
+*/
+
+#include "hybrid.h"
+#include "debug.h"
+
+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,
+  0xE8, 0x68, 0x88, 0x28, 0x48, 0xEB, 0x6B, 0x8B, 0x2B, 0x4B, 0xC3,
+  0xE9, 0x69, 0x89, 0x29, 0x49, 0xEC, 0x6C, 0x8C, 0x2C, 0x4C, 0xC4,
+  0xEA, 0x6A, 0x8A, 0x2A, 0x4A, 0xED, 0x6D, 0x8D, 0x2D, 0x4D, 0xC5,
+  0xF0, 0x70, 0x90, 0x30, 0x50, 0xF3, 0x73, 0x93, 0x33, 0x53, 0xC6,
+  0xF1, 0x71, 0x91, 0x31, 0x51, 0xF4, 0x74, 0x94, 0x34, 0x54, 0xC7,
+  0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8
+};
+
+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
+};
+
+const unsigned char
+  CxadhybridPlayer::hyb_default_instrument[11] = {
+  0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00
+};
+
+CPlayer *
+CxadhybridPlayer::factory (Copl * newopl)
+{
+  return new CxadhybridPlayer (newopl);
+}
+
+bool
+CxadhybridPlayer::xadplayer_load ()
+{
+  if (xad.fmt != HYBRID)
+    return false;
+
+  // load instruments
+  hyb.inst = (hyb_instrument *) & tune[0];
+
+  // load order
+  hyb.order = &tune[0x1D4];
+
+  return true;
+}
+
+void
+CxadhybridPlayer::xadplayer_rewind (int subsong)
+{
+  int i;
+
+  hyb.order_pos = 0;
+  hyb.pattern_pos = 0;
+
+  hyb.speed = 6;
+  hyb.speed_counter = 1;
+
+  plr.speed = 1;
+
+  // init channel data
+  for (i = 0; i < 9; i++)
+  {
+    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);
+
+  // init OPL channels
+  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] */ );
+
+    opl_write (0xA0 + i, 0x00);
+    opl_write (0xB0 + i, 0x20);
+  }
+}
+
+void
+CxadhybridPlayer::xadplayer_update ()
+{
+  int i, j;
+  unsigned char patpos, ordpos;
+
+  if (--hyb.speed_counter)
+    goto update_slides;
+
+  hyb.speed_counter = hyb.speed;
+
+  patpos = hyb.pattern_pos;
+  ordpos = hyb.order_pos;
+
+  // process channels
+  for (i = 0; i < 9; i++)
+  {
+    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);
+#endif
+
+    // calculate variables
+    unsigned char note = event >> 9;
+    unsigned char ins = ((event & 0x01F0) >> 4);
+    unsigned char slide = event & 0x000F;
+
+    // play event
+    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;
+    }
+  }
+
+  hyb.pattern_pos++;
+
+  // end of pattern ?
+  if (hyb.pattern_pos >= 0x40)
+  {
+    hyb.pattern_pos = 0;
+
+    hyb.order_pos++;
+  }
+
+update_slides:
+#ifdef DEBUG
+  AdPlug_LogWrite ("slides:\n");
+#endif
+  // update fine frequency slides
+  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;
+
+      opl_write (0xA0 + i, hyb.channel[i].freq & 0xFF);
+      opl_write (0xB0 + i, hyb.channel[i].freq >> 8);
+    }
+}
+
+float
+CxadhybridPlayer::xadplayer_getrefresh ()
+{
+  return 50.0f;
+}
+
+std::string CxadhybridPlayer::xadplayer_gettype ()
+{
+  return (std::string ("xad: hybrid player"));
+}
+
+std::string CxadhybridPlayer::xadplayer_getinstrument (unsigned int i)
+{
+  return (std::string (hyb.inst[i].name, 7));
+}
+
+unsigned int
+CxadhybridPlayer::xadplayer_getinstruments ()
+{
+  return 26;
+}
diff --git a/src/adplug/core/hybrid.cxx b/src/adplug/core/hybrid.cxx
deleted file mode 100644
index 7333c4edfd45..000000000000
--- a/src/adplug/core/hybrid.cxx
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * [xad] HYBRID player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : HYBRID.EXE
-     type : Hybrid cracktro for Apache Longbow CD-RIP
-     tune : from 'Mig-29 Super Fulcrum' game by Domark
-   player : from 'Mig-29 Super Fulcrum' game by Domark
-*/
-
-#include "hybrid.h"
-#include "debug.h"
-
-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,
-  0xE8, 0x68, 0x88, 0x28, 0x48, 0xEB, 0x6B, 0x8B, 0x2B, 0x4B, 0xC3,
-  0xE9, 0x69, 0x89, 0x29, 0x49, 0xEC, 0x6C, 0x8C, 0x2C, 0x4C, 0xC4,
-  0xEA, 0x6A, 0x8A, 0x2A, 0x4A, 0xED, 0x6D, 0x8D, 0x2D, 0x4D, 0xC5,
-  0xF0, 0x70, 0x90, 0x30, 0x50, 0xF3, 0x73, 0x93, 0x33, 0x53, 0xC6,
-  0xF1, 0x71, 0x91, 0x31, 0x51, 0xF4, 0x74, 0x94, 0x34, 0x54, 0xC7,
-  0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8
-};
-
-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
-};
-
-const unsigned char
-  CxadhybridPlayer::hyb_default_instrument[11] = {
-  0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00
-};
-
-CPlayer *
-CxadhybridPlayer::factory (Copl * newopl)
-{
-  return new CxadhybridPlayer (newopl);
-}
-
-bool
-CxadhybridPlayer::xadplayer_load ()
-{
-  if (xad.fmt != HYBRID)
-    return false;
-
-  // load instruments
-  hyb.inst = (hyb_instrument *) & tune[0];
-
-  // load order
-  hyb.order = &tune[0x1D4];
-
-  return true;
-}
-
-void
-CxadhybridPlayer::xadplayer_rewind (int subsong)
-{
-  int i;
-
-  hyb.order_pos = 0;
-  hyb.pattern_pos = 0;
-
-  hyb.speed = 6;
-  hyb.speed_counter = 1;
-
-  plr.speed = 1;
-
-  // init channel data
-  for (i = 0; i < 9; i++)
-  {
-    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);
-
-  // init OPL channels
-  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] */ );
-
-    opl_write (0xA0 + i, 0x00);
-    opl_write (0xB0 + i, 0x20);
-  }
-}
-
-void
-CxadhybridPlayer::xadplayer_update ()
-{
-  int i, j;
-  unsigned char patpos, ordpos;
-
-  if (--hyb.speed_counter)
-    goto update_slides;
-
-  hyb.speed_counter = hyb.speed;
-
-  patpos = hyb.pattern_pos;
-  ordpos = hyb.order_pos;
-
-  // process channels
-  for (i = 0; i < 9; i++)
-  {
-    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);
-#endif
-
-    // calculate variables
-    unsigned char note = event >> 9;
-    unsigned char ins = ((event & 0x01F0) >> 4);
-    unsigned char slide = event & 0x000F;
-
-    // play event
-    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;
-    }
-  }
-
-  hyb.pattern_pos++;
-
-  // end of pattern ?
-  if (hyb.pattern_pos >= 0x40)
-  {
-    hyb.pattern_pos = 0;
-
-    hyb.order_pos++;
-  }
-
-update_slides:
-#ifdef DEBUG
-  AdPlug_LogWrite ("slides:\n");
-#endif
-  // update fine frequency slides
-  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;
-
-      opl_write (0xA0 + i, hyb.channel[i].freq & 0xFF);
-      opl_write (0xB0 + i, hyb.channel[i].freq >> 8);
-    }
-}
-
-float
-CxadhybridPlayer::xadplayer_getrefresh ()
-{
-  return 50.0f;
-}
-
-std::string CxadhybridPlayer::xadplayer_gettype ()
-{
-  return (std::string ("xad: hybrid player"));
-}
-
-std::string CxadhybridPlayer::xadplayer_getinstrument (unsigned int i)
-{
-  return (std::string (hyb.inst[i].name, 7));
-}
-
-unsigned int
-CxadhybridPlayer::xadplayer_getinstruments ()
-{
-  return 26;
-}
diff --git a/src/adplug/core/hyp.cc b/src/adplug/core/hyp.cc
new file mode 100644
index 000000000000..5358a65beb98
--- /dev/null
+++ b/src/adplug/core/hyp.cc
@@ -0,0 +1,129 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] HYP player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : HT-EF2.COM, HT-EF3.COM
+     type : Eiserne Front BBStro
+     tune : by Shadowdancer [Hypnosis]
+   player : by (?)Hetero [LKCC/SAC]
+*/
+
+#include "hyp.h"
+#include "debug.h"
+
+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,
+  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3,
+  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4,
+  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5,
+  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6,
+  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7,
+  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8
+};
+
+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,
+  0x1198, 0x11B1, 0x11C9, 0x11E5, 0x1203, 0x1221, 0x1241, 0x1263, 0x1286,
+  0x1556, 0x156B, 0x1580, 0x1598, 0x15B1, 0x15C9, 0x15E5, 0x1603, 0x1621,
+  0x1641, 0x1663, 0x1686, 0x1956, 0x196B, 0x1980, 0x1998, 0x19B1, 0x19C9,
+  0x19E5, 0x1A03, 0x1A21, 0x1A41, 0x1A63, 0x1A86, 0x1D56, 0x1D6B, 0x1D80,
+  0x1D98, 0x1DB1, 0x1DC9, 0x1DE5, 0x1E03, 0x1E21, 0x1E41, 0x1E63, 0x1E86
+};
+
+CPlayer *
+CxadhypPlayer::factory (Copl * newopl)
+{
+  return new CxadhypPlayer (newopl);
+}
+
+void
+CxadhypPlayer::xadplayer_rewind (int subsong)
+{
+  int i;
+
+  plr.speed = tune[5];
+
+  opl_write (0xBD, 0xC0);
+
+  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]);
+
+  hyp.pointer = 0x69;
+}
+
+void
+CxadhypPlayer::xadplayer_update ()
+{
+  for (int i = 0; i < 9; i++)
+  {
+    unsigned char event = tune[hyp.pointer++];
+
+    if (event)
+    {
+      unsigned short freq = hyp_notes[event & 0x3F];
+
+      unsigned char lofreq = (freq & 0xFF);
+      unsigned char hifreq = (freq >> 8);
+
+      opl_write (0xB0 + i, adlib[0xB0 + i]);
+
+      if (!(event & 0x40))
+      {
+        opl_write (0xA0 + i, lofreq);
+        opl_write (0xB0 + i, hifreq | 0x20);
+      }
+
+      adlib[0xB0 + i] &= 0xDF;
+    }
+  }
+
+  hyp.pointer += 3;
+
+  if (hyp.pointer >= tune_size)
+  {
+    hyp.pointer = 0x69;
+    plr.looping = 1;
+  }
+}
+
+float
+CxadhypPlayer::xadplayer_getrefresh ()
+{
+  return 60.0f;
+}
+
+std::string CxadhypPlayer::xadplayer_gettype ()
+{
+  return std::string ("xad: hypnosis player");
+}
diff --git a/src/adplug/core/hyp.cxx b/src/adplug/core/hyp.cxx
deleted file mode 100644
index 5358a65beb98..000000000000
--- a/src/adplug/core/hyp.cxx
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * [xad] HYP player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : HT-EF2.COM, HT-EF3.COM
-     type : Eiserne Front BBStro
-     tune : by Shadowdancer [Hypnosis]
-   player : by (?)Hetero [LKCC/SAC]
-*/
-
-#include "hyp.h"
-#include "debug.h"
-
-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,
-  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3,
-  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4,
-  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5,
-  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6,
-  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7,
-  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8
-};
-
-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,
-  0x1198, 0x11B1, 0x11C9, 0x11E5, 0x1203, 0x1221, 0x1241, 0x1263, 0x1286,
-  0x1556, 0x156B, 0x1580, 0x1598, 0x15B1, 0x15C9, 0x15E5, 0x1603, 0x1621,
-  0x1641, 0x1663, 0x1686, 0x1956, 0x196B, 0x1980, 0x1998, 0x19B1, 0x19C9,
-  0x19E5, 0x1A03, 0x1A21, 0x1A41, 0x1A63, 0x1A86, 0x1D56, 0x1D6B, 0x1D80,
-  0x1D98, 0x1DB1, 0x1DC9, 0x1DE5, 0x1E03, 0x1E21, 0x1E41, 0x1E63, 0x1E86
-};
-
-CPlayer *
-CxadhypPlayer::factory (Copl * newopl)
-{
-  return new CxadhypPlayer (newopl);
-}
-
-void
-CxadhypPlayer::xadplayer_rewind (int subsong)
-{
-  int i;
-
-  plr.speed = tune[5];
-
-  opl_write (0xBD, 0xC0);
-
-  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]);
-
-  hyp.pointer = 0x69;
-}
-
-void
-CxadhypPlayer::xadplayer_update ()
-{
-  for (int i = 0; i < 9; i++)
-  {
-    unsigned char event = tune[hyp.pointer++];
-
-    if (event)
-    {
-      unsigned short freq = hyp_notes[event & 0x3F];
-
-      unsigned char lofreq = (freq & 0xFF);
-      unsigned char hifreq = (freq >> 8);
-
-      opl_write (0xB0 + i, adlib[0xB0 + i]);
-
-      if (!(event & 0x40))
-      {
-        opl_write (0xA0 + i, lofreq);
-        opl_write (0xB0 + i, hifreq | 0x20);
-      }
-
-      adlib[0xB0 + i] &= 0xDF;
-    }
-  }
-
-  hyp.pointer += 3;
-
-  if (hyp.pointer >= tune_size)
-  {
-    hyp.pointer = 0x69;
-    plr.looping = 1;
-  }
-}
-
-float
-CxadhypPlayer::xadplayer_getrefresh ()
-{
-  return 60.0f;
-}
-
-std::string CxadhypPlayer::xadplayer_gettype ()
-{
-  return std::string ("xad: hypnosis player");
-}
diff --git a/src/adplug/core/imf.cc b/src/adplug/core/imf.cc
new file mode 100644
index 000000000000..109d6cd6d0c3
--- /dev/null
+++ b/src/adplug/core/imf.cc
@@ -0,0 +1,229 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter <dn.tlp at 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
+ *
+ * imf.cpp - IMF Player by Simon Peter <dn.tlp at gmx.net>
+ *
+ * FILE FORMAT:
+ * There seem to be 2 different flavors of IMF formats out there. One version
+ * contains just the raw IMF music data. In this case, the first word of the
+ * file is always 0 (because the music data starts this way). This is already
+ * the music data! So read in the entire file and play it.
+ *
+ * If this word is greater than 0, it specifies the size of the following
+ * song data in bytes. In this case, the file has a footer that contains
+ * arbitrary infos about it. Mostly, this is plain ASCII text with some words
+ * of the author. Read and play the specified amount of song data and display
+ * the remaining data as ASCII text.
+ *
+ * NOTES:
+ * This player handles the two above mentioned formats, as well as a third
+ * type, invented by Martin Fernandez <mfernan at cnba.uba.ar>, that's got a
+ * proper header to add title/game name information. After the header starts
+ * the normal IMF file in one of the two above mentioned formats.
+ *
+ * This player also handles a special footer format by Adam Nielsen,
+ * which has defined fields of information about the song, the author
+ * and more.
+ */
+
+#include <string.h>
+
+#include "imf.h"
+#include "database.h"
+
+/*** public methods *************************************/
+
+CPlayer *
+CimfPlayer::factory (Copl * newopl)
+{
+  return new CimfPlayer (newopl);
+}
+
+bool
+CimfPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  unsigned long fsize, flsize, mfsize = 0;
+  unsigned int i;
+
+  // file validation section
+  {
+    char header[5];
+    int version;
+
+    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"))
+      {
+        // It's no IMF file at all
+        fp.close (f);
+        return false;
+      }
+      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;
+    }
+  }
+
+  // load section
+  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);
+    else
+      f->seek (-2, binio::Add);
+    size = (flsize - mfsize) / 4;
+  }
+  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);
+  }
+
+  // read footer, if any
+  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
+    {
+      // Generic footer
+      unsigned long footerlen = flsize - fsize - 2 - mfsize;
+
+      footer = new char[footerlen + 1];
+      f->readString (footer, footerlen);
+      footer[footerlen] = '\0'; // Make ASCIIZ string
+    }
+  }
+
+  rate = getrate (fd.filename (), fp, f);
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+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;
+}
+
+void
+CimfPlayer::rewind (int subsong)
+{
+  pos = 0;
+  del = 0;
+  timer = rate;
+  songend = false;
+  opl->init ();
+  opl->write (1, 32);           // go to OPL2 mode
+}
+
+std::string CimfPlayer::gettitle ()
+{
+  std::string title;
+
+  title = track_name;
+
+  if (!track_name.empty () && !game_name.empty ())
+    title += " - ";
+
+  title += game_name;
+
+  return title;
+}
+
+std::string CimfPlayer::getdesc ()
+{
+  std::string desc;
+
+  if (footer)
+    desc = std::string (footer);
+
+  if (!remarks.empty () && footer)
+    desc += "\n\n";
+
+  desc += remarks;
+
+  return desc;
+}
+
+/*** private methods *************************************/
+
+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 (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
+}
diff --git a/src/adplug/core/imf.cxx b/src/adplug/core/imf.cxx
deleted file mode 100644
index 863512e43b19..000000000000
--- a/src/adplug/core/imf.cxx
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter <dn.tlp at 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
- *
- * imf.cpp - IMF Player by Simon Peter <dn.tlp at gmx.net>
- *
- * FILE FORMAT:
- * There seem to be 2 different flavors of IMF formats out there. One version
- * contains just the raw IMF music data. In this case, the first word of the
- * file is always 0 (because the music data starts this way). This is already
- * the music data! So read in the entire file and play it.
- *
- * If this word is greater than 0, it specifies the size of the following
- * song data in bytes. In this case, the file has a footer that contains
- * arbitrary infos about it. Mostly, this is plain ASCII text with some words
- * of the author. Read and play the specified amount of song data and display
- * the remaining data as ASCII text.
- *
- * NOTES:
- * This player handles the two above mentioned formats, as well as a third
- * type, invented by Martin Fernandez <mfernan at cnba.uba.ar>, that's got a
- * proper header to add title/game name information. After the header starts
- * the normal IMF file in one of the two above mentioned formats.
- *
- * This player also handles a special footer format by Adam Nielsen,
- * which has defined fields of information about the song, the author
- * and more.
- */
-
-#include <string.h>
-
-#include "imf.h"
-#include "database.h"
-
-/*** public methods *************************************/
-
-CPlayer *
-CimfPlayer::factory (Copl * newopl)
-{
-  return new CimfPlayer (newopl);
-}
-
-bool
-CimfPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  unsigned long fsize, flsize, mfsize = 0;
-  unsigned int i;
-
-  // file validation section
-  {
-    char header[5];
-    int version;
-
-    f->readString (header, 5);
-    version = f->readInt (1);
-
-    if (strncmp (header, "ADLIB", 5) || version != 1)
-    {
-      if (!fp.extension (vfs_get_filename (fd), ".imf") && !fp.extension (vfs_get_filename (fd), ".wlf"))
-      {
-        // It's no IMF file at all
-        fp.close (f);
-        return false;
-      }
-      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;
-    }
-  }
-
-  // load section
-  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);
-    else
-      f->seek (-2, binio::Add);
-    size = (flsize - mfsize) / 4;
-  }
-  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);
-  }
-
-  // read footer, if any
-  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
-    {
-      // Generic footer
-      unsigned long footerlen = flsize - fsize - 2 - mfsize;
-
-      footer = new char[footerlen + 1];
-      f->readString (footer, footerlen);
-      footer[footerlen] = '\0'; // Make ASCIIZ string
-    }
-  }
-
-  rate = getrate (vfs_get_filename (fd), fp, f);
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-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;
-}
-
-void
-CimfPlayer::rewind (int subsong)
-{
-  pos = 0;
-  del = 0;
-  timer = rate;
-  songend = false;
-  opl->init ();
-  opl->write (1, 32);           // go to OPL2 mode
-}
-
-std::string CimfPlayer::gettitle ()
-{
-  std::string title;
-
-  title = track_name;
-
-  if (!track_name.empty () && !game_name.empty ())
-    title += " - ";
-
-  title += game_name;
-
-  return title;
-}
-
-std::string CimfPlayer::getdesc ()
-{
-  std::string desc;
-
-  if (footer)
-    desc = std::string (footer);
-
-  if (!remarks.empty () && footer)
-    desc += "\n\n";
-
-  desc += remarks;
-
-  return desc;
-}
-
-/*** private methods *************************************/
-
-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 (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
-}
diff --git a/src/adplug/core/imf.h b/src/adplug/core/imf.h
index 17063dc7acec..9eb3a6edf3ab 100644
--- a/src/adplug/core/imf.h
+++ b/src/adplug/core/imf.h
@@ -35,7 +35,7 @@ public:
 	~CimfPlayer()
 	  { if(data) delete [] data; if(footer) delete [] footer; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh()
diff --git a/src/adplug/core/jbm.cc b/src/adplug/core/jbm.cc
new file mode 100644
index 000000000000..c9658049f839
--- /dev/null
+++ b/src/adplug/core/jbm.cc
@@ -0,0 +1,294 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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.
+ *
+ * Johannes Bjerregaard's JBM Adlib Music Format player for AdPlug
+ * Written by Dennis Lindroos <lindroos at nls.fi>, February-March 2007
+ * - Designed and coded from scratch (only frequency-table taken from MUSIC.BIN)
+ * - The percussion mode is buggy (?) but i'm not good enough to find them
+ *   and honestly i think the melodic-mode tunes are much better ;)
+ *
+ * This version doesn't use the binstr.h functions (coded with custom func.)
+ * This is my first attempt on writing a musicplayer for AdPlug, and i'm not
+ * coding C++ very often..
+ *
+ * Released under the terms of the GNU General Public License.
+ */
+
+#include "jbm.h"
+
+static const unsigned short notetable[96] = {
+  0x0158, 0x016d, 0x0183, 0x019a, 0x01b2, 0x01cc, 0x01e7, 0x0204,
+  0x0223, 0x0244, 0x0266, 0x028b, 0x0558, 0x056d, 0x0583, 0x059a,
+  0x05b2, 0x05cc, 0x05e7, 0x0604, 0x0623, 0x0644, 0x0666, 0x068b,
+  0x0958, 0x096d, 0x0983, 0x099a, 0x09b2, 0x09cc, 0x09e7, 0x0a04,
+  0x0a23, 0x0a44, 0x0a66, 0x0a8b, 0x0d58, 0x0d6d, 0x0d83, 0x0d9a,
+  0x0db2, 0x0dcc, 0x0de7, 0x0e04, 0x0e23, 0x0e44, 0x0e66, 0x0e8b,
+  0x1158, 0x116d, 0x1183, 0x119a, 0x11b2, 0x11cc, 0x11e7, 0x1204,
+  0x1223, 0x1244, 0x1266, 0x128b, 0x1558, 0x156d, 0x1583, 0x159a,
+  0x15b2, 0x15cc, 0x15e7, 0x1604, 0x1623, 0x1644, 0x1666, 0x168b,
+  0x1958, 0x196d, 0x1983, 0x199a, 0x19b2, 0x19cc, 0x19e7, 0x1a04,
+  0x1a23, 0x1a44, 0x1a66, 0x1a8b, 0x1d58, 0x1d6d, 0x1d83, 0x1d9a,
+  0x1db2, 0x1dcc, 0x1de7, 0x1e04, 0x1e23, 0x1e44, 0x1e66, 0x1e8b
+};
+
+static const unsigned char percmx_tab[4] = { 0x14, 0x12, 0x15, 0x11 };
+static const unsigned char perchn_tab[5] = { 6, 7, 8, 8, 7 };
+static unsigned char percmaskoff[5] = { 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
+static unsigned char percmaskon[5] =  { 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+static inline unsigned short GET_WORD(unsigned char *b, int x)
+{
+  return ((unsigned short)(b[x+1] << 8) | b[x]);
+}
+
+/*** public methods *************************************/
+
+CPlayer *CjbmPlayer::factory(Copl *newopl)
+{
+  return new CjbmPlayer(newopl);
+}
+
+bool CjbmPlayer::load(VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  std::string filename (fd.filename ());
+  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;
+
+  fp.close(f);
+
+  // The known .jbm files always seem to start with the number 0x0002
+
+  if (GET_WORD(m, 0) != 0x0002)
+    return false;
+
+  // Song tempo
+
+  i = GET_WORD(m, 2);
+  timer = 1193810.0 / (i ? i : 0xffff);
+
+  seqtable = GET_WORD(m, 4);
+  instable = GET_WORD(m, 6);
+
+  // The flags word has atleast 1 bit, the Adlib's rhythm mode, but
+  // currently we don't support that :(
+
+  flags = GET_WORD(m, 8);
+
+  // Instrument datas are directly addressed with m[]
+
+  inscount = (filelen - instable) >> 4;
+
+  // Voice' and sequence pointers
+
+  seqcount = 0xffff;
+  for (i = 0; i < 11; i++) {
+    voice[i].trkpos = voice[i].trkstart = GET_WORD(m, 10 + (i<<1));
+    if (voice[i].trkpos && voice[i].trkpos < seqcount)
+      seqcount = voice[i].trkpos;
+  }
+  seqcount = (seqcount - seqtable) >> 1;
+  sequences = new unsigned short[seqcount];
+  for (i = 0; i < seqcount; i++)
+    sequences[i] = GET_WORD(m, seqtable + (i<<1));
+
+  rewind(0);
+  return true;
+ loaderr:
+  fp.close(f);
+  return false;
+}
+
+bool CjbmPlayer::update()
+{
+  short c, spos, frq;
+
+  for (c = 0; c < 11; c++) {
+    if (!voice[c].trkpos)		// Unused channel
+      continue;
+
+    if (--voice[c].delay)
+      continue;
+
+    // Turn current note/percussion off
+
+    if (voice[c].note&0x7f)
+      opl_noteonoff(c, &voice[c], 0);
+
+    // Process events until we have a note
+
+    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;
+      }
+    }
+    voice[c].seqpos = spos;
+
+    // Write new volume to the carrier operator, or percussion
+
+    if (flags&1 && c > 6)
+      opl->write(0x40 + percmx_tab[c-7], voice[c].vol ^ 0x3f);
+    else
+      opl->write(0x43 + op_table[c], voice[c].vol ^ 0x3f);
+
+    // Write new frequencies and Gate bit
+
+    opl_noteonoff(c, &voice[c], !(voice[c].note & 0x80));
+  }
+  return (voicemask);
+}
+
+void CjbmPlayer::rewind(int subsong)
+{
+  int c;
+
+  voicemask = 0;
+
+  for (c = 0; c < 11; c++) {
+    voice[c].trkpos = voice[c].trkstart;
+
+    if (!voice[c].trkpos) continue;
+
+    voicemask |= (1<<c);
+
+    voice[c].seqno = m[voice[c].trkpos];
+    voice[c].seqpos = sequences[voice[c].seqno];
+
+    voice[c].note = 0;
+    voice[c].delay = 1;
+  }
+
+  opl->init();
+  opl->write(0x01, 32);
+
+  // Set rhythm mode if flags bit #0 is set
+  // AM and Vibrato are full depths (taken from DosBox RAW output)
+  bdreg = 0xC0 | (flags&1)<<5;
+
+  opl->write(0xbd, bdreg);
+
+#if 0
+  if (flags&1) {
+    voice[7].frq[0] = 0x58; voice[7].frq[1] = 0x09; // XXX
+    voice[8].frq[0] = 0x04; voice[8].frq[1] = 0x0a; // XXX
+    opl_noteonoff(7, &voice[7], 0);
+    opl_noteonoff(8, &voice[8], 0);
+  }
+#endif
+
+  return;
+}
+
+/*** private methods ************************************/
+
+void CjbmPlayer::opl_noteonoff(int channel, JBMVoice *v, bool state)
+{
+  if (flags&1 && channel > 5) {
+    // Percussion
+    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]);
+  } 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);
+  }
+  return;
+}
+
+
+void CjbmPlayer::set_opl_instrument(int channel, JBMVoice *v)
+{
+  short i = instable + (v->instr << 4);
+
+  // Sanity check on instr number - or we'll be reading outside m[] !
+
+  if (v->instr >= inscount)
+    return;
+
+  // For rhythm mode, multiplexed drums. I don't care about waveforms!
+  if ((flags&1) & (channel > 6)) {
+    opl->write(0x20 + percmx_tab[channel-7], m[i+0]);
+    opl->write(0x40 + percmx_tab[channel-7], m[i+1] ^ 0x3f);
+    opl->write(0x60 + percmx_tab[channel-7], m[i+2]);
+    opl->write(0x80 + percmx_tab[channel-7], m[i+3]);
+
+    opl->write(0xc0 + perchn_tab[channel-6], m[i+8]&15);
+    return;
+  }
+
+  // AM/VIB/EG/KSR/FRQMUL, KSL/OUTPUT, ADSR for 1st operator
+  opl->write(0x20 + op_table[channel], m[i+0]);
+  opl->write(0x40 + op_table[channel], m[i+1] ^ 0x3f);
+  opl->write(0x60 + op_table[channel], m[i+2]);
+  opl->write(0x80 + op_table[channel], m[i+3]);
+
+  // AM/VIB/EG/KSR/FRQMUL, KSL/OUTPUT, ADSR for 2nd operator
+  opl->write(0x23 + op_table[channel], m[i+4]);
+  opl->write(0x43 + op_table[channel], m[i+5] ^ 0x3f);
+  opl->write(0x63 + op_table[channel], m[i+6]);
+  opl->write(0x83 + op_table[channel], m[i+7]);
+
+  // WAVEFORM for operators
+  opl->write(0xe0 + op_table[channel], (m[i+8]>>4)&3);
+  opl->write(0xe3 + op_table[channel], (m[i+8]>>6)&3);
+
+  // FEEDBACK/FM mode
+  opl->write(0xc0 + channel, m[i+8]&15);
+
+  return;
+}
diff --git a/src/adplug/core/jbm.cxx b/src/adplug/core/jbm.cxx
deleted file mode 100644
index dc920d906545..000000000000
--- a/src/adplug/core/jbm.cxx
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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.
- *
- * Johannes Bjerregaard's JBM Adlib Music Format player for AdPlug
- * Written by Dennis Lindroos <lindroos at nls.fi>, February-March 2007
- * - Designed and coded from scratch (only frequency-table taken from MUSIC.BIN)
- * - The percussion mode is buggy (?) but i'm not good enough to find them
- *   and honestly i think the melodic-mode tunes are much better ;)
- *
- * This version doesn't use the binstr.h functions (coded with custom func.)
- * This is my first attempt on writing a musicplayer for AdPlug, and i'm not
- * coding C++ very often..
- *
- * Released under the terms of the GNU General Public License.
- */
-
-#include "jbm.h"
-
-static const unsigned short notetable[96] = {
-  0x0158, 0x016d, 0x0183, 0x019a, 0x01b2, 0x01cc, 0x01e7, 0x0204,
-  0x0223, 0x0244, 0x0266, 0x028b, 0x0558, 0x056d, 0x0583, 0x059a,
-  0x05b2, 0x05cc, 0x05e7, 0x0604, 0x0623, 0x0644, 0x0666, 0x068b,
-  0x0958, 0x096d, 0x0983, 0x099a, 0x09b2, 0x09cc, 0x09e7, 0x0a04,
-  0x0a23, 0x0a44, 0x0a66, 0x0a8b, 0x0d58, 0x0d6d, 0x0d83, 0x0d9a,
-  0x0db2, 0x0dcc, 0x0de7, 0x0e04, 0x0e23, 0x0e44, 0x0e66, 0x0e8b,
-  0x1158, 0x116d, 0x1183, 0x119a, 0x11b2, 0x11cc, 0x11e7, 0x1204,
-  0x1223, 0x1244, 0x1266, 0x128b, 0x1558, 0x156d, 0x1583, 0x159a,
-  0x15b2, 0x15cc, 0x15e7, 0x1604, 0x1623, 0x1644, 0x1666, 0x168b,
-  0x1958, 0x196d, 0x1983, 0x199a, 0x19b2, 0x19cc, 0x19e7, 0x1a04,
-  0x1a23, 0x1a44, 0x1a66, 0x1a8b, 0x1d58, 0x1d6d, 0x1d83, 0x1d9a,
-  0x1db2, 0x1dcc, 0x1de7, 0x1e04, 0x1e23, 0x1e44, 0x1e66, 0x1e8b
-};
-
-static const unsigned char percmx_tab[4] = { 0x14, 0x12, 0x15, 0x11 };
-static const unsigned char perchn_tab[5] = { 6, 7, 8, 8, 7 };
-static unsigned char percmaskoff[5] = { 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
-static unsigned char percmaskon[5] =  { 0x10, 0x08, 0x04, 0x02, 0x01 };
-
-static inline unsigned short GET_WORD(unsigned char *b, int x)
-{
-  return ((unsigned short)(b[x+1] << 8) | b[x]);
-}
-
-/*** public methods *************************************/
-
-CPlayer *CjbmPlayer::factory(Copl *newopl)
-{
-  return new CjbmPlayer(newopl);
-}
-
-bool CjbmPlayer::load(VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  std::string filename (vfs_get_filename (fd));
-  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;
-
-  fp.close(f);
-
-  // The known .jbm files always seem to start with the number 0x0002
-
-  if (GET_WORD(m, 0) != 0x0002)
-    return false;
-
-  // Song tempo
-
-  i = GET_WORD(m, 2);
-  timer = 1193810.0 / (i ? i : 0xffff);
-
-  seqtable = GET_WORD(m, 4);
-  instable = GET_WORD(m, 6);
-
-  // The flags word has atleast 1 bit, the Adlib's rhythm mode, but
-  // currently we don't support that :(
-
-  flags = GET_WORD(m, 8);
-
-  // Instrument datas are directly addressed with m[]
-
-  inscount = (filelen - instable) >> 4;
-
-  // Voice' and sequence pointers
-
-  seqcount = 0xffff;
-  for (i = 0; i < 11; i++) {
-    voice[i].trkpos = voice[i].trkstart = GET_WORD(m, 10 + (i<<1));
-    if (voice[i].trkpos && voice[i].trkpos < seqcount)
-      seqcount = voice[i].trkpos;
-  }
-  seqcount = (seqcount - seqtable) >> 1;
-  sequences = new unsigned short[seqcount];
-  for (i = 0; i < seqcount; i++)
-    sequences[i] = GET_WORD(m, seqtable + (i<<1));
-
-  rewind(0);
-  return true;
- loaderr:
-  fp.close(f);
-  return false;
-}
-
-bool CjbmPlayer::update()
-{
-  short c, spos, frq;
-
-  for (c = 0; c < 11; c++) {
-    if (!voice[c].trkpos)		// Unused channel
-      continue;
-
-    if (--voice[c].delay)
-      continue;
-
-    // Turn current note/percussion off
-
-    if (voice[c].note&0x7f)
-      opl_noteonoff(c, &voice[c], 0);
-
-    // Process events until we have a note
-
-    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;
-      }
-    }
-    voice[c].seqpos = spos;
-
-    // Write new volume to the carrier operator, or percussion
-
-    if (flags&1 && c > 6)
-      opl->write(0x40 + percmx_tab[c-7], voice[c].vol ^ 0x3f);
-    else
-      opl->write(0x43 + op_table[c], voice[c].vol ^ 0x3f);
-
-    // Write new frequencies and Gate bit
-
-    opl_noteonoff(c, &voice[c], !(voice[c].note & 0x80));
-  }
-  return (voicemask);
-}
-
-void CjbmPlayer::rewind(int subsong)
-{
-  int c;
-
-  voicemask = 0;
-
-  for (c = 0; c < 11; c++) {
-    voice[c].trkpos = voice[c].trkstart;
-
-    if (!voice[c].trkpos) continue;
-
-    voicemask |= (1<<c);
-
-    voice[c].seqno = m[voice[c].trkpos];
-    voice[c].seqpos = sequences[voice[c].seqno];
-
-    voice[c].note = 0;
-    voice[c].delay = 1;
-  }
-
-  opl->init();
-  opl->write(0x01, 32);
-
-  // Set rhythm mode if flags bit #0 is set
-  // AM and Vibrato are full depths (taken from DosBox RAW output)
-  bdreg = 0xC0 | (flags&1)<<5;
-
-  opl->write(0xbd, bdreg);
-
-#if 0
-  if (flags&1) {
-    voice[7].frq[0] = 0x58; voice[7].frq[1] = 0x09; // XXX
-    voice[8].frq[0] = 0x04; voice[8].frq[1] = 0x0a; // XXX
-    opl_noteonoff(7, &voice[7], 0);
-    opl_noteonoff(8, &voice[8], 0);
-  }
-#endif
-
-  return;
-}
-
-/*** private methods ************************************/
-
-void CjbmPlayer::opl_noteonoff(int channel, JBMVoice *v, bool state)
-{
-  if (flags&1 && channel > 5) {
-    // Percussion
-    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]);
-  } 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);
-  }
-  return;
-}
-
-
-void CjbmPlayer::set_opl_instrument(int channel, JBMVoice *v)
-{
-  short i = instable + (v->instr << 4);
-
-  // Sanity check on instr number - or we'll be reading outside m[] !
-
-  if (v->instr >= inscount)
-    return;
-
-  // For rhythm mode, multiplexed drums. I don't care about waveforms!
-  if ((flags&1) & (channel > 6)) {
-    opl->write(0x20 + percmx_tab[channel-7], m[i+0]);
-    opl->write(0x40 + percmx_tab[channel-7], m[i+1] ^ 0x3f);
-    opl->write(0x60 + percmx_tab[channel-7], m[i+2]);
-    opl->write(0x80 + percmx_tab[channel-7], m[i+3]);
-
-    opl->write(0xc0 + perchn_tab[channel-6], m[i+8]&15);
-    return;
-  }
-
-  // AM/VIB/EG/KSR/FRQMUL, KSL/OUTPUT, ADSR for 1st operator
-  opl->write(0x20 + op_table[channel], m[i+0]);
-  opl->write(0x40 + op_table[channel], m[i+1] ^ 0x3f);
-  opl->write(0x60 + op_table[channel], m[i+2]);
-  opl->write(0x80 + op_table[channel], m[i+3]);
-
-  // AM/VIB/EG/KSR/FRQMUL, KSL/OUTPUT, ADSR for 2nd operator
-  opl->write(0x23 + op_table[channel], m[i+4]);
-  opl->write(0x43 + op_table[channel], m[i+5] ^ 0x3f);
-  opl->write(0x63 + op_table[channel], m[i+6]);
-  opl->write(0x83 + op_table[channel], m[i+7]);
-
-  // WAVEFORM for operators
-  opl->write(0xe0 + op_table[channel], (m[i+8]>>4)&3);
-  opl->write(0xe3 + op_table[channel], (m[i+8]>>6)&3);
-
-  // FEEDBACK/FM mode
-  opl->write(0xc0 + channel, m[i+8]&15);
-
-  return;
-}
diff --git a/src/adplug/core/jbm.h b/src/adplug/core/jbm.h
index 11191257a4d0..cb9e4cb634a1 100644
--- a/src/adplug/core/jbm.h
+++ b/src/adplug/core/jbm.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2007 Simon Peter <dn.tlp at 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,9 +32,9 @@ class CjbmPlayer: public CPlayer
   CjbmPlayer(Copl *newopl) : CPlayer(newopl), m(0)
     { }
   ~CjbmPlayer()
-    { if(m != NULL) delete [] m; }
+    { if(m != nullptr) delete [] m; }
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong);
 
@@ -57,7 +57,7 @@ class CjbmPlayer: public CPlayer
   unsigned short seqtable, seqcount;
   unsigned short instable, inscount;
   unsigned short *sequences;
-  unsigned char bdreg; 
+  unsigned char bdreg;
 
   typedef struct {
     unsigned short trkpos, trkstart, seqpos;
@@ -73,7 +73,7 @@ class CjbmPlayer: public CPlayer
 
  private:
   //void calc_opl_frequency(JBMVoice *);
-  void set_opl_instrument(int, JBMVoice *); 
+  void set_opl_instrument(int, JBMVoice *);
   void opl_noteonoff(int, JBMVoice *, bool);
 };
 
diff --git a/src/adplug/core/kemuopl.h b/src/adplug/core/kemuopl.h
index d68785fa9256..bdee9d78029a 100644
--- a/src/adplug/core/kemuopl.h
+++ b/src/adplug/core/kemuopl.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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,9 +24,7 @@
 #define H_ADPLUG_KEMUOPL
 
 #include "opl.h"
-extern "C" {
 #include "adlibemu.h"
-}
 
 class CKemuopl: public Copl
 {
diff --git a/src/adplug/core/ksm.cc b/src/adplug/core/ksm.cc
new file mode 100644
index 000000000000..9b9bea5d6bea
--- /dev/null
+++ b/src/adplug/core/ksm.cc
@@ -0,0 +1,419 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "ksm.h"
+#include "debug.h"
+
+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
+};
+
+/*** public methods **************************************/
+
+CPlayer *
+CksmPlayer::factory (Copl * newopl)
+{
+  return new CksmPlayer (newopl);
+}
+
+bool
+CksmPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f;
+  int i;
+  std::string filename (fd.filename ());
+  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;
+    return false;
+  }
+  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] == '\\')
+      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");
+    return false;
+  }
+  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);
+
+  if (!trchan[11])
+  {
+    drumstat = 0;
+    numchans = 9;
+  }
+  else
+  {
+    drumstat = 32;
+    numchans = 6;
+  }
+
+  rewind (0);
+  AdPlug_LogWrite ("--- CksmPlayer::load ---\n");
+  return true;
+}
+
+bool
+CksmPlayer::update ()
+{
+  int quanter, chan = 0, drumnum = 0, 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)
+        {
+          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))
+            {
+              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;
+      }
+      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]);
+  }
+  return !songend;
+}
+
+void
+CksmPlayer::rewind (int subsong)
+{
+  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);
+
+  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[i] = inst[trinst[12]][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[i] = inst[trinst[14]][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]);
+  }
+
+  for (i = 0; i < numchans; i++)
+  {
+    chantrack[i] = 0;
+    chanage[i] = 0;
+  }
+  j = 0;
+  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++;
+      }
+    }
+  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;
+  nownote = 0;
+}
+
+std::string CksmPlayer::getinstrument (unsigned int n)
+{
+  if (trchan[n])
+    return std::string (instname[trinst[n]]);
+  else
+    return std::string ();
+}
+
+/*** private methods *************************************/
+
+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);
+  }
+}
+
+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);
+  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);
+}
diff --git a/src/adplug/core/ksm.cxx b/src/adplug/core/ksm.cxx
deleted file mode 100644
index 4346fbeb757e..000000000000
--- a/src/adplug/core/ksm.cxx
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "ksm.h"
-#include "debug.h"
-
-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
-};
-
-/*** public methods **************************************/
-
-CPlayer *
-CksmPlayer::factory (Copl * newopl)
-{
-  return new CksmPlayer (newopl);
-}
-
-bool
-CksmPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f;
-  int i;
-  std::string filename (vfs_get_filename (fd));
-  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;
-    return false;
-  }
-  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] == '\\')
-      break;
-  strcpy (fn + i + 1, "insts.dat");
-  AdPlug_LogWrite ("Instruments file: \"%s\"\n", fn);
-  VFSFile *instfd = vfs_fopen (fn, "rb");
-  f = fp.open (instfd);
-  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);
-  vfs_fclose (instfd);
-
-  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);
-
-  if (!trchan[11])
-  {
-    drumstat = 0;
-    numchans = 9;
-  }
-  else
-  {
-    drumstat = 32;
-    numchans = 6;
-  }
-
-  rewind (0);
-  AdPlug_LogWrite ("--- CksmPlayer::load ---\n");
-  return true;
-}
-
-bool
-CksmPlayer::update ()
-{
-  int quanter, chan = 0, drumnum = 0, 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)
-        {
-          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))
-            {
-              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;
-      }
-      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]);
-  }
-  return !songend;
-}
-
-void
-CksmPlayer::rewind (int subsong)
-{
-  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);
-
-  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[i] = inst[trinst[12]][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[i] = inst[trinst[14]][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]);
-  }
-
-  for (i = 0; i < numchans; i++)
-  {
-    chantrack[i] = 0;
-    chanage[i] = 0;
-  }
-  j = 0;
-  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++;
-      }
-    }
-  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;
-  nownote = 0;
-}
-
-std::string CksmPlayer::getinstrument (unsigned int n)
-{
-  if (trchan[n])
-    return std::string (instname[trinst[n]]);
-  else
-    return std::string ();
-}
-
-/*** private methods *************************************/
-
-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);
-  }
-}
-
-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);
-  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);
-}
diff --git a/src/adplug/core/ksm.h b/src/adplug/core/ksm.h
index 5cd424604dc8..3137df9dee07 100644
--- a/src/adplug/core/ksm.h
+++ b/src/adplug/core/ksm.h
@@ -32,7 +32,7 @@ public:
 	~CksmPlayer()
 	{ if(note) delete [] note; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh()
diff --git a/src/adplug/core/lds.cc b/src/adplug/core/lds.cc
new file mode 100644
index 000000000000..93789a25595b
--- /dev/null
+++ b/src/adplug/core/lds.cc
@@ -0,0 +1,817 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
+ *
+ * lds.cpp - LOUDNESS Player by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "lds.h"
+#include "debug.h"
+
+// Note frequency table (16 notes / octave)
+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,
+  395, 396, 398, 399, 401, 402, 403, 405, 406, 408, 409, 411, 412,
+  414, 415, 417, 418, 420, 421, 423, 424, 426, 427, 429, 430, 432,
+  434, 435, 437, 438, 440, 442, 443, 445, 446, 448, 450, 451, 453,
+  454, 456, 458, 459, 461, 463, 464, 466, 468, 469, 471, 473, 475,
+  476, 478, 480, 481, 483, 485, 487, 488, 490, 492, 494, 496, 497,
+  499, 501, 503, 505, 506, 508, 510, 512, 514, 516, 518, 519, 521,
+  523, 525, 527, 529, 531, 533, 535, 537, 538, 540, 542, 544, 546,
+  548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 571, 573,
+  575, 577, 579, 581, 583, 585, 587, 589, 591, 594, 596, 598, 600,
+  602, 604, 607, 609, 611, 613, 615, 618, 620, 622, 624, 627, 629,
+  631, 633, 636, 638, 640, 643, 645, 647, 650, 652, 654, 657, 659,
+  662, 664, 666, 669, 671, 674, 676, 678, 681, 683
+};
+
+// Vibrato (sine) table
+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,
+  231, 225, 219, 212, 205, 197, 189, 180, 171, 162, 152, 142, 131,
+  120, 109, 98, 86, 74, 62, 50, 37, 25, 13
+};
+
+// Tremolo (sine * sine) table
+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,
+  213, 218, 222, 226, 230, 234, 237, 240, 243, 245, 248, 250, 251,
+  253, 254, 254, 255, 255, 255, 254, 254, 253, 251, 250, 248, 245,
+  243, 240, 237, 234, 230, 226, 222, 218, 213, 208, 203, 198, 193,
+  188, 182, 176, 170, 165, 158, 152, 146, 140, 134, 127, 121, 115,
+  109, 103, 97, 90, 85, 79, 73, 67, 62, 57, 52, 47, 42, 37, 33, 29,
+  25, 21, 18, 15, 12, 10, 7, 5, 4, 2, 1, 1, 0
+};
+
+// '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;
+
+/*** public methods *************************************/
+
+CldsPlayer::CldsPlayer (Copl * newopl):CPlayer (newopl), soundbank (0), positions (0),
+patterns (0)
+{
+}
+
+CldsPlayer::~CldsPlayer ()
+{
+  if (soundbank)
+    delete[]soundbank;
+  if (positions)
+    delete[]positions;
+  if (patterns)
+    delete[]patterns;
+}
+
+bool
+CldsPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f;
+  unsigned int i, j;
+  SoundBank *sb;
+  std::string filename (fd.filename ());
+
+  // file validation section (actually just an extension check)
+  f = fp.open (fd);
+  if (!f)
+    return false;
+  if (!fp.extension (filename, ".lds"))
+    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);
+
+  // load patches
+  numpatch = f->readInt (2);
+  soundbank = new SoundBank[numpatch];
+  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);
+  }
+
+  // load positions
+  numposi = f->readInt (2);
+  positions = new Position[9 * numposi];
+  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);
+    }
+
+  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);
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+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;
+
+  if (!playing)
+    return false;
+
+  // handle fading
+  if (fadeonoff)
+  {
+    if (fadeonoff <= 128)
+    {
+      if (allvolume > fadeonoff || allvolume == 0)
+        allvolume -= fadeonoff;
+      else
+      {
+        allvolume = 1;
+        fadeonoff = 0;
+        if (hardfade != 0)
+        {
+          playing = false;
+          hardfade = 0;
+          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;
+    }
+  }
+
+  // handle channel delay
+  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);
+  }
+
+  // handle notes
+  if (!tempo_now)
+  {
+    vbreak = false;
+    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;
+
+        comword = patterns[patnum + c->packpos];
+        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 (!chandelay[chan])
+              playsound (sound, chan, high);
+            else
+            {
+              c->chancheat.chandelay = chandelay[chan];
+              c->chancheat.sound = sound;
+              c->chancheat.high = high;
+            }
+          }
+        }
+
+        c->packpos++;
+      }
+      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;
+       }
+     */
+    pattplay++;
+    if (vbreak)
+    {
+      pattplay = 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
+    tempo_now--;
+
+  // make effects
+  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);
+      c->keycount--;
+    }
+
+    // arpeggio
+    if (c->arp_size == 0)
+      arpreg = 0;
+    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;
+        arpreg = c->arp_tab[0] << 4;
+      }
+
+      if (c->arp_count == c->arp_speed)
+      {
+        c->arp_pos++;
+        if (c->arp_pos >= c->arp_size)
+          c->arp_pos = 0;
+        c->arp_count = 0;
+      }
+      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)
+          c->lasttune = c->gototune;
+        else
+          c->lasttune -= c->portspeed;
+      }
+      else
+      {
+        if (c->gototune - c->lasttune < c->portspeed)
+          c->lasttune = c->gototune;
+        else
+          c->lasttune += c->portspeed;
+      }
+
+      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
+    {
+      // vibrato
+      if (!c->vibwait)
+      {
+        if (c->vibrate)
+        {
+          wibc = vibtab[c->vibcount & 0x3f] * c->vibrate;
+
+          if ((c->vibcount & 0x40) == 0)
+            tune = c->lasttune + (wibc >> 8);
+          else
+            tune = c->lasttune - (wibc >> 8);
+
+          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);
+          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;
+
+          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)
+            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);
+        }
+      }
+    }
+
+    // tremolo (modulator)
+    if (!c->trmwait)
+    {
+      if (c->trmrate)
+      {
+        tremc = tremtab[c->trmcount & 0x7f] * c->trmrate;
+        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);
+        else
+          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
+    {
+      c->trmwait--;
+      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)
+      {
+        tremc = tremtab[c->trccount & 0x7f] * c->trcrate;
+        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);
+        else
+          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
+    {
+      c->trcwait--;
+      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)
+{
+  int i;
+
+  // init all with 0
+  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));
+
+  // 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);
+  }
+}
+
+/*** private methods *************************************/
+
+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;
+
+  // 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 (arpcalc > 0x800)
+      tunehigh = tunehigh - (arpcalc ^ 0xff0) - 16;
+    else
+      tunehigh += arpcalc;
+  }
+
+  // glide handling
+  if (c->glideto != 0)
+  {
+    c->gototune = tunehigh;
+    c->portspeed = c->glideto;
+    c->glideto = c->finetune = 0;
+    return;
+  }
+
+  // set modulator registers
+  setregs (0x20 + regnum, i->mod_misc);
+  volcalc = i->mod_vol;
+  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);
+  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);
+
+  // Set carrier registers
+  setregs (0x23 + regnum, i->car_misc);
+  volcalc = i->car_vol;
+  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);
+  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
+
+  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));
+      c->lasttune = c->gototune = tunehigh;
+    }
+    else
+    {
+      c->gototune = tunehigh;
+      c->portspeed = i->portamento;
+      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));
+    c->lasttune = tunehigh;
+    c->gototune = tunehigh + ((i->glide + 0x80) & 0xff) - 0x80; // set destination
+    c->portspeed = i->portamento;
+  }
+
+  if (!i->vibrato)
+    c->vibwait = c->vibspeed = c->vibrate = 0;
+  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))
+  {
+    c->trmwait = (i->tremwait & 0xf0) >> 3;
+    // PASCAL:    c->trmspeed = (i->mod_trem >> 4) & 15;
+    c->trmspeed = i->mod_trem >> 4;
+    c->trmrate = i->mod_trem & 15;
+    c->trmcount = 0;
+  }
+
+  if (!(c->trmstay & 0x0f))
+  {
+    c->trcwait = (i->tremwait & 15) << 1;
+    // PASCAL:    c->trcspeed = (i->car_trem >> 4) & 15;
+    c->trcspeed = i->car_trem >> 4;
+    c->trcrate = i->car_trem & 15;
+    c->trccount = 0;
+  }
+
+  c->arp_size = i->arpeggio & 15;
+  c->arp_speed = i->arpeggio >> 4;
+  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;
+}
+
+inline void
+CldsPlayer::setregs (unsigned char reg, unsigned char val)
+{
+  if (fmchip[reg] == val)
+    return;
+
+  fmchip[reg] = val;
+  opl->write (reg, val);
+}
+
+inline void
+CldsPlayer::setregs_adv (unsigned char reg, unsigned char mask,
+                         unsigned char val)
+{
+  setregs (reg, (fmchip[reg] & mask) | val);
+}
diff --git a/src/adplug/core/lds.cxx b/src/adplug/core/lds.cxx
deleted file mode 100644
index 1580c51e986f..000000000000
--- a/src/adplug/core/lds.cxx
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
- *
- * lds.cpp - LOUDNESS Player by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "lds.h"
-#include "debug.h"
-
-// Note frequency table (16 notes / octave)
-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,
-  395, 396, 398, 399, 401, 402, 403, 405, 406, 408, 409, 411, 412,
-  414, 415, 417, 418, 420, 421, 423, 424, 426, 427, 429, 430, 432,
-  434, 435, 437, 438, 440, 442, 443, 445, 446, 448, 450, 451, 453,
-  454, 456, 458, 459, 461, 463, 464, 466, 468, 469, 471, 473, 475,
-  476, 478, 480, 481, 483, 485, 487, 488, 490, 492, 494, 496, 497,
-  499, 501, 503, 505, 506, 508, 510, 512, 514, 516, 518, 519, 521,
-  523, 525, 527, 529, 531, 533, 535, 537, 538, 540, 542, 544, 546,
-  548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 571, 573,
-  575, 577, 579, 581, 583, 585, 587, 589, 591, 594, 596, 598, 600,
-  602, 604, 607, 609, 611, 613, 615, 618, 620, 622, 624, 627, 629,
-  631, 633, 636, 638, 640, 643, 645, 647, 650, 652, 654, 657, 659,
-  662, 664, 666, 669, 671, 674, 676, 678, 681, 683
-};
-
-// Vibrato (sine) table
-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,
-  231, 225, 219, 212, 205, 197, 189, 180, 171, 162, 152, 142, 131,
-  120, 109, 98, 86, 74, 62, 50, 37, 25, 13
-};
-
-// Tremolo (sine * sine) table
-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,
-  213, 218, 222, 226, 230, 234, 237, 240, 243, 245, 248, 250, 251,
-  253, 254, 254, 255, 255, 255, 254, 254, 253, 251, 250, 248, 245,
-  243, 240, 237, 234, 230, 226, 222, 218, 213, 208, 203, 198, 193,
-  188, 182, 176, 170, 165, 158, 152, 146, 140, 134, 127, 121, 115,
-  109, 103, 97, 90, 85, 79, 73, 67, 62, 57, 52, 47, 42, 37, 33, 29,
-  25, 21, 18, 15, 12, 10, 7, 5, 4, 2, 1, 1, 0
-};
-
-// '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;
-
-/*** public methods *************************************/
-
-CldsPlayer::CldsPlayer (Copl * newopl):CPlayer (newopl), soundbank (0), positions (0),
-patterns (0)
-{
-}
-
-CldsPlayer::~CldsPlayer ()
-{
-  if (soundbank)
-    delete[]soundbank;
-  if (positions)
-    delete[]positions;
-  if (patterns)
-    delete[]patterns;
-}
-
-bool
-CldsPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f;
-  unsigned int i, j;
-  SoundBank *sb;
-  std::string filename (vfs_get_filename (fd));
-
-  // file validation section (actually just an extension check)
-  f = fp.open (fd);
-  if (!f)
-    return false;
-  if (!fp.extension (filename, ".lds"))
-    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);
-
-  // load patches
-  numpatch = f->readInt (2);
-  soundbank = new SoundBank[numpatch];
-  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);
-  }
-
-  // load positions
-  numposi = f->readInt (2);
-  positions = new Position[9 * numposi];
-  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);
-    }
-
-  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);
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-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;
-
-  if (!playing)
-    return false;
-
-  // handle fading
-  if (fadeonoff)
-  {
-    if (fadeonoff <= 128)
-    {
-      if (allvolume > fadeonoff || allvolume == 0)
-        allvolume -= fadeonoff;
-      else
-      {
-        allvolume = 1;
-        fadeonoff = 0;
-        if (hardfade != 0)
-        {
-          playing = false;
-          hardfade = 0;
-          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;
-    }
-  }
-
-  // handle channel delay
-  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);
-  }
-
-  // handle notes
-  if (!tempo_now)
-  {
-    vbreak = false;
-    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;
-
-        comword = patterns[patnum + c->packpos];
-        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 (!chandelay[chan])
-              playsound (sound, chan, high);
-            else
-            {
-              c->chancheat.chandelay = chandelay[chan];
-              c->chancheat.sound = sound;
-              c->chancheat.high = high;
-            }
-          }
-        }
-
-        c->packpos++;
-      }
-      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;
-       }
-     */
-    pattplay++;
-    if (vbreak)
-    {
-      pattplay = 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
-    tempo_now--;
-
-  // make effects
-  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);
-      c->keycount--;
-    }
-
-    // arpeggio
-    if (c->arp_size == 0)
-      arpreg = 0;
-    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;
-        arpreg = c->arp_tab[0] << 4;
-      }
-
-      if (c->arp_count == c->arp_speed)
-      {
-        c->arp_pos++;
-        if (c->arp_pos >= c->arp_size)
-          c->arp_pos = 0;
-        c->arp_count = 0;
-      }
-      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)
-          c->lasttune = c->gototune;
-        else
-          c->lasttune -= c->portspeed;
-      }
-      else
-      {
-        if (c->gototune - c->lasttune < c->portspeed)
-          c->lasttune = c->gototune;
-        else
-          c->lasttune += c->portspeed;
-      }
-
-      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
-    {
-      // vibrato
-      if (!c->vibwait)
-      {
-        if (c->vibrate)
-        {
-          wibc = vibtab[c->vibcount & 0x3f] * c->vibrate;
-
-          if ((c->vibcount & 0x40) == 0)
-            tune = c->lasttune + (wibc >> 8);
-          else
-            tune = c->lasttune - (wibc >> 8);
-
-          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);
-          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;
-
-          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)
-            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);
-        }
-      }
-    }
-
-    // tremolo (modulator)
-    if (!c->trmwait)
-    {
-      if (c->trmrate)
-      {
-        tremc = tremtab[c->trmcount & 0x7f] * c->trmrate;
-        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);
-        else
-          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
-    {
-      c->trmwait--;
-      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)
-      {
-        tremc = tremtab[c->trccount & 0x7f] * c->trcrate;
-        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);
-        else
-          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
-    {
-      c->trcwait--;
-      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)
-{
-  int i;
-
-  // init all with 0
-  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));
-
-  // 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);
-  }
-}
-
-/*** private methods *************************************/
-
-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;
-
-  // 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 (arpcalc > 0x800)
-      tunehigh = tunehigh - (arpcalc ^ 0xff0) - 16;
-    else
-      tunehigh += arpcalc;
-  }
-
-  // glide handling
-  if (c->glideto != 0)
-  {
-    c->gototune = tunehigh;
-    c->portspeed = c->glideto;
-    c->glideto = c->finetune = 0;
-    return;
-  }
-
-  // set modulator registers
-  setregs (0x20 + regnum, i->mod_misc);
-  volcalc = i->mod_vol;
-  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);
-  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);
-
-  // Set carrier registers
-  setregs (0x23 + regnum, i->car_misc);
-  volcalc = i->car_vol;
-  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);
-  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
-
-  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));
-      c->lasttune = c->gototune = tunehigh;
-    }
-    else
-    {
-      c->gototune = tunehigh;
-      c->portspeed = i->portamento;
-      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));
-    c->lasttune = tunehigh;
-    c->gototune = tunehigh + ((i->glide + 0x80) & 0xff) - 0x80; // set destination
-    c->portspeed = i->portamento;
-  }
-
-  if (!i->vibrato)
-    c->vibwait = c->vibspeed = c->vibrate = 0;
-  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))
-  {
-    c->trmwait = (i->tremwait & 0xf0) >> 3;
-    // PASCAL:    c->trmspeed = (i->mod_trem >> 4) & 15;
-    c->trmspeed = i->mod_trem >> 4;
-    c->trmrate = i->mod_trem & 15;
-    c->trmcount = 0;
-  }
-
-  if (!(c->trmstay & 0x0f))
-  {
-    c->trcwait = (i->tremwait & 15) << 1;
-    // PASCAL:    c->trcspeed = (i->car_trem >> 4) & 15;
-    c->trcspeed = i->car_trem >> 4;
-    c->trcrate = i->car_trem & 15;
-    c->trccount = 0;
-  }
-
-  c->arp_size = i->arpeggio & 15;
-  c->arp_speed = i->arpeggio >> 4;
-  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;
-}
-
-inline void
-CldsPlayer::setregs (unsigned char reg, unsigned char val)
-{
-  if (fmchip[reg] == val)
-    return;
-
-  fmchip[reg] = val;
-  opl->write (reg, val);
-}
-
-inline void
-CldsPlayer::setregs_adv (unsigned char reg, unsigned char mask,
-                         unsigned char val)
-{
-  setregs (reg, (fmchip[reg] & mask) | val);
-}
diff --git a/src/adplug/core/lds.h b/src/adplug/core/lds.h
index aac36e3a30d1..5e421298b62d 100644
--- a/src/adplug/core/lds.h
+++ b/src/adplug/core/lds.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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 @@ class CldsPlayer: public CPlayer
   CldsPlayer(Copl *newopl);
   virtual ~CldsPlayer();
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   virtual bool update();
   virtual void rewind(int subsong = -1);
   float getrefresh() { return 70.0f; }
@@ -82,7 +82,7 @@ class CldsPlayer: public CPlayer
     tempo_now, pattplay, tempo, regbd, chandelay[9], mode, pattlen;
   unsigned short	posplay, jumppos, *patterns, speed;
   bool			playing, songlooped;
-  unsigned int		numpatch, numposi, patterns_size, mainvolume;
+  unsigned int		numpatch, numposi, mainvolume;
 
   void		playsound(int inst_number, int channel_number, int tunehigh);
   inline void	setregs(unsigned char reg, unsigned char val);
diff --git a/src/adplug/core/mad.cc b/src/adplug/core/mad.cc
new file mode 100644
index 000000000000..f87b3b469e46
--- /dev/null
+++ b/src/adplug/core/mad.cc
@@ -0,0 +1,146 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+
+  mad.cpp - MAD loader by Riven the Mage <riven at ok.ru>
+*/
+
+#include <string.h>
+
+#include "mad.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CPlayer *
+CmadLoader::factory (Copl * newopl)
+{
+  return new CmadLoader (newopl);
+}
+
+bool
+CmadLoader::load (VFSFile & fd, 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 };
+  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;
+  }
+
+  // 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);
+  }
+
+  f->ignore (1);
+
+  // data for Protracker
+  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 ();
+
+  // load tracks
+  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);
+
+        // convert event
+        if (event < 0x61)
+          tracks[t][k].note = event;
+        if (event == 0xFF)      // 0xFF: Release note
+          tracks[t][k].command = 8;
+        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;
+
+  fp.close (f);
+
+  // convert instruments
+  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);
+  return true;
+}
+
+void
+CmadLoader::rewind (int subsong)
+{
+  CmodPlayer::rewind (subsong);
+
+  // 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);
+  }
+}
+
+float
+CmadLoader::getrefresh ()
+{
+  return (float) timer;
+}
+
+std::string CmadLoader::gettype ()
+{
+  return std::string ("Mlat Adlib Tracker");
+}
+
+std::string CmadLoader::getinstrument (unsigned int n)
+{
+  return std::string (instruments[n].name, 8);
+}
+
+unsigned int
+CmadLoader::getinstruments ()
+{
+  return 9;
+}
diff --git a/src/adplug/core/mad.cxx b/src/adplug/core/mad.cxx
deleted file mode 100644
index 5ce37b94a8a2..000000000000
--- a/src/adplug/core/mad.cxx
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-  Adplug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
-
-  mad.cpp - MAD loader by Riven the Mage <riven at ok.ru>
-*/
-
-#include <string.h>
-
-#include "mad.h"
-
-/* -------- Public Methods -------------------------------- */
-
-CPlayer *
-CmadLoader::factory (Copl * newopl)
-{
-  return new CmadLoader (newopl);
-}
-
-bool
-CmadLoader::load (VFSFile * fd, 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 };
-  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;
-  }
-
-  // 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);
-  }
-
-  f->ignore (1);
-
-  // data for Protracker
-  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 ();
-
-  // load tracks
-  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);
-
-        // convert event
-        if (event < 0x61)
-          tracks[t][k].note = event;
-        if (event == 0xFF)      // 0xFF: Release note
-          tracks[t][k].command = 8;
-        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;
-
-  fp.close (f);
-
-  // convert instruments
-  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);
-  return true;
-}
-
-void
-CmadLoader::rewind (int subsong)
-{
-  CmodPlayer::rewind (subsong);
-
-  // 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);
-  }
-}
-
-float
-CmadLoader::getrefresh ()
-{
-  return (float) timer;
-}
-
-std::string CmadLoader::gettype ()
-{
-  return std::string ("Mlat Adlib Tracker");
-}
-
-std::string CmadLoader::getinstrument (unsigned int n)
-{
-  return std::string (instruments[n].name, 8);
-}
-
-unsigned int
-CmadLoader::getinstruments ()
-{
-  return 9;
-}
diff --git a/src/adplug/core/mad.h b/src/adplug/core/mad.h
index 836d8c006eb0..7631de9cd819 100644
--- a/src/adplug/core/mad.h
+++ b/src/adplug/core/mad.h
@@ -28,7 +28,7 @@ public:
 
 	CmadLoader(Copl *newopl) : CmodPlayer(newopl) { };
 
-	bool	load(VFSFile *fd, const CFileProvider &fp);
+	bool	load(VFSFile &fd, const CFileProvider &fp);
 	void	rewind(int subsong);
 	float	getrefresh();
 
diff --git a/src/adplug/core/mid.cc b/src/adplug/core/mid.cc
new file mode 100644
index 000000000000..3f78c31bb342
--- /dev/null
+++ b/src/adplug/core/mid.cc
@@ -0,0 +1,1101 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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
+ *
+ *
+ * MIDI & MIDI-like file player - Last Update: 10/15/2005
+ *                  by Phil Hassey - www.imitationpickles.org
+ *                                   philhassey at hotmail.com
+ *
+ * Can play the following
+ *      .LAA - a raw save of a Lucas Arts Adlib music
+ *             or
+ *             a raw save of a LucasFilm Adlib music
+ *      .SCI - the sierra "midi" format.
+ *             Files must be in the form
+ *             xxxNAME.sci
+ *             So that the loader can load the right patch file:
+ *             xxxPATCH.003  (patch.003 must be saved from the
+ *                            sierra resource from each game.)
+ *
+ * Other acknowledgements:
+ *  Allegro - for the midi instruments and the midi volume table
+ *  SCUMM Revisited - for getting the .LAA / .MIDs out of those
+ *                    LucasArts files.
+ *  FreeSCI - for some information on the sci music files
+ *  SD - the SCI Decoder (to get all .sci out of the Sierra files)
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "mid.h"
+#include "mididata.h"
+
+/*#define TESTING*/
+#ifdef TESTING
+#define midiprintf printf
+#else
+void
+CmidPlayer::midiprintf (const char *format, ...)
+{
+}
+#endif
+
+#define LUCAS_STYLE   1
+#define CMF_STYLE     2
+#define MIDI_STYLE    4
+#define SIERRA_STYLE  8
+
+// AdLib melodic and rhythm mode defines
+#define ADLIB_MELODIC	0
+#define ADLIB_RYTHM	1
+
+// File types
+#define FILE_LUCAS      1
+#define FILE_MIDI       2
+#define FILE_CMF        3
+#define FILE_SIERRA     4
+#define FILE_ADVSIERRA  5
+#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 };
+
+// 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 };
+
+// Standard AdLib frequency table
+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 };
+
+CPlayer *
+CmidPlayer::factory (Copl * newopl)
+{
+  return new CmidPlayer (newopl);
+}
+
+CmidPlayer::CmidPlayer (Copl * newopl):CPlayer (newopl), author (&emptystr), title (&emptystr), remarks (&emptystr),
+emptystr ('\0'), flen (0), data (0)
+{
+}
+
+unsigned char
+CmidPlayer::datalook (long pos)
+{
+  if (pos < 0 || pos >= flen)
+    return (0);
+  return (data[pos]);
+}
+
+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
+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);
+}
+
+unsigned long
+CmidPlayer::getval ()
+{
+  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);
+}
+
+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");
+
+  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);
+
+      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;
+}
+
+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;
+}
+
+bool
+CmidPlayer::load (VFSFile & fd, 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;
+    }
+  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;
+}
+
+void
+CmidPlayer::midi_write_adlib (unsigned int r, unsigned char v)
+{
+  opl->write (r, v);
+  adlib_data[r] = v;
+}
+
+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);
+    }
+  }
+
+  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]);
+}
+
+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]);
+}
+
+void
+CmidPlayer::midi_fm_volume (int voice, int volume)
+{
+  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_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)
+{
+  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));
+
+  c = ((freq & 0x300) >> 8) + (oct << 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)
+{
+  //midi_fm_volume(voice,0);
+  //midi_write_adlib(0xb0+voice,0);
+
+  midi_write_adlib (0xb0 + voice,
+                    (unsigned char) (adlib_data[0xb0 + voice] & (255 - 32)));
+}
+
+void
+CmidPlayer::midi_fm_reset ()
+{
+  int i;
+
+  opl->init ();
+
+  for (i = 0; i < 256; i++)
+    midi_write_adlib (i, 0);
+
+  midi_write_adlib (0x01, 0x20);
+  midi_write_adlib (0xBD, 0xc0);
+}
+
+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;
+  }
+
+  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)
+        {
+          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)
+                {
+                  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)
+                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)));
+              }
+
+            }
+            else
+            {
+              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;
+                  }
+              }
+              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 ("\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;
+        }
+
+        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
+             }
+           */
+        }
+        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..
+
+    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;
+
+
+    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");
+    }
+
+  /*
+     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;
+}
+
+float
+CmidPlayer::getrefresh ()
+{
+  return (fwait > 0.01f ? fwait : 0.01f);
+}
+
+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++;
+    }
+
+    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;
+    }
+
+  doing = 1;
+  midi_fm_reset ();
+}
+
+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");
+  }
+}
diff --git a/src/adplug/core/mid.cxx b/src/adplug/core/mid.cxx
deleted file mode 100644
index f12305fc29bc..000000000000
--- a/src/adplug/core/mid.cxx
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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
- *
- *
- * MIDI & MIDI-like file player - Last Update: 10/15/2005
- *                  by Phil Hassey - www.imitationpickles.org
- *                                   philhassey at hotmail.com
- *
- * Can play the following
- *      .LAA - a raw save of a Lucas Arts Adlib music
- *             or
- *             a raw save of a LucasFilm Adlib music
- *      .SCI - the sierra "midi" format.
- *             Files must be in the form
- *             xxxNAME.sci
- *             So that the loader can load the right patch file:
- *             xxxPATCH.003  (patch.003 must be saved from the
- *                            sierra resource from each game.)
- *
- * Other acknowledgements:
- *  Allegro - for the midi instruments and the midi volume table
- *  SCUMM Revisited - for getting the .LAA / .MIDs out of those
- *                    LucasArts files.
- *  FreeSCI - for some information on the sci music files
- *  SD - the SCI Decoder (to get all .sci out of the Sierra files)
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include "mid.h"
-#include "mididata.h"
-
-/*#define TESTING*/
-#ifdef TESTING
-#define midiprintf printf
-#else
-void
-CmidPlayer::midiprintf (const char *format, ...)
-{
-}
-#endif
-
-#define LUCAS_STYLE   1
-#define CMF_STYLE     2
-#define MIDI_STYLE    4
-#define SIERRA_STYLE  8
-
-// AdLib melodic and rhythm mode defines
-#define ADLIB_MELODIC	0
-#define ADLIB_RYTHM	1
-
-// File types
-#define FILE_LUCAS      1
-#define FILE_MIDI       2
-#define FILE_CMF        3
-#define FILE_SIERRA     4
-#define FILE_ADVSIERRA  5
-#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 };
-
-// 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 };
-
-// Standard AdLib frequency table
-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 };
-
-CPlayer *
-CmidPlayer::factory (Copl * newopl)
-{
-  return new CmidPlayer (newopl);
-}
-
-CmidPlayer::CmidPlayer (Copl * newopl):CPlayer (newopl), author (&emptystr), title (&emptystr), remarks (&emptystr),
-emptystr ('\0'), flen (0), data (0)
-{
-}
-
-unsigned char
-CmidPlayer::datalook (long pos)
-{
-  if (pos < 0 || pos >= flen)
-    return (0);
-  return (data[pos]);
-}
-
-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
-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);
-}
-
-unsigned long
-CmidPlayer::getval ()
-{
-  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);
-}
-
-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");
-
-  VFSFile *instfd = vfs_fopen (pfilename, "rb");
-  f = fp.open (instfd);
-  free (pfilename);
-  if (!f)
-  {
-    vfs_fclose (instfd);
-    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);
-
-      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);
-  vfs_fclose (instfd);
-  memcpy (smyinsbank, myinsbank, 128 * 16);
-  return true;
-}
-
-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;
-}
-
-bool
-CmidPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  int good;
-  unsigned char s[6];
-  std::string filename (vfs_get_filename (fd));
-
-  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;
-    }
-  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;
-}
-
-void
-CmidPlayer::midi_write_adlib (unsigned int r, unsigned char v)
-{
-  opl->write (r, v);
-  adlib_data[r] = v;
-}
-
-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);
-    }
-  }
-
-  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]);
-}
-
-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]);
-}
-
-void
-CmidPlayer::midi_fm_volume (int voice, int volume)
-{
-  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_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)
-{
-  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));
-
-  c = ((freq & 0x300) >> 8) + (oct << 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)
-{
-  //midi_fm_volume(voice,0);
-  //midi_write_adlib(0xb0+voice,0);
-
-  midi_write_adlib (0xb0 + voice,
-                    (unsigned char) (adlib_data[0xb0 + voice] & (255 - 32)));
-}
-
-void
-CmidPlayer::midi_fm_reset ()
-{
-  int i;
-
-  opl->init ();
-
-  for (i = 0; i < 256; i++)
-    midi_write_adlib (i, 0);
-
-  midi_write_adlib (0x01, 0x20);
-  midi_write_adlib (0xBD, 0xc0);
-}
-
-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;
-  }
-
-  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)
-        {
-          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)
-                {
-                  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)
-                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)));
-              }
-
-            }
-            else
-            {
-              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;
-                  }
-              }
-              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 ("\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;
-        }
-
-        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
-             }
-           */
-        }
-        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..
-
-    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;
-
-
-    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");
-    }
-
-  /*
-     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;
-}
-
-float
-CmidPlayer::getrefresh ()
-{
-  return (fwait > 0.01f ? fwait : 0.01f);
-}
-
-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++;
-    }
-
-    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;
-    }
-
-  doing = 1;
-  midi_fm_reset ();
-}
-
-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");
-  }
-}
diff --git a/src/adplug/core/mid.h b/src/adplug/core/mid.h
index f1b36dc69ebb..737bd70b2928 100644
--- a/src/adplug/core/mid.h
+++ b/src/adplug/core/mid.h
@@ -30,7 +30,7 @@ public:
   ~CmidPlayer()
     { if(data) delete [] data; }
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong);
   float getrefresh();
diff --git a/src/adplug/core/mkj.cc b/src/adplug/core/mkj.cc
new file mode 100644
index 000000000000..de4bf2d285f0
--- /dev/null
+++ b/src/adplug/core/mkj.cc
@@ -0,0 +1,225 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
+ *
+ * mkj.cpp - MKJamz Player, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "mkj.h"
+#include "debug.h"
+
+CPlayer *
+CmkjPlayer::factory (Copl * newopl)
+{
+  return new CmkjPlayer (newopl);
+}
+
+bool
+CmkjPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  char id[6];
+  float ver;
+  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;
+  }
+
+  // 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]);
+  }
+  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);
+  return true;
+}
+
+bool
+CmkjPlayer::update ()
+{
+  int c, i;
+  short note;
+
+  for (c = 0; c < maxchannel; c++)
+  {
+    if (!channel[c].defined)    // skip if channel is disabled
+      continue;
+
+    if (channel[c].pstat)
+    {
+      channel[c].pstat--;
+      continue;
+    }
+
+    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)
+          channel[c].pstat = channel[c].speed;
+      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
+        channel[c].songptr += maxchannel;
+        channel[c].pstat = songbuf[channel[c].songptr];
+        break;
+      case 254:                // set octave
+        channel[c].songptr += maxchannel;
+        channel[c].octave = songbuf[channel[c].songptr];
+        break;
+      case 253:                // set speed
+        channel[c].songptr += maxchannel;
+        channel[c].speed = songbuf[channel[c].songptr];
+        break;
+      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);
+        else
+          opl->write (0xe0 + c, channel[c].waveform);
+        break;
+      case 251:                // song end
+        for (i = 0; i < maxchannel; i++)
+          channel[i].songptr = i;
+        songend = true;
+        return false;
+      }
+
+      if (channel[c].songptr - c < maxnotes)
+        channel[c].songptr += maxchannel;
+      else
+        channel[c].songptr = c;
+    } while (!channel[c].pstat);
+  }
+
+  return !songend;
+}
+
+void
+CmkjPlayer::rewind (int subsong)
+{
+  int i;
+
+  for (i = 0; i < maxchannel; i++)
+  {
+    channel[i].pstat = 0;
+    channel[i].speed = 0;
+    channel[i].waveform = 0;
+    channel[i].songptr = i;
+    channel[i].octave = 4;
+  }
+
+  songend = false;
+}
+
+float
+CmkjPlayer::getrefresh ()
+{
+  return 100.0f;
+}
diff --git a/src/adplug/core/mkj.cxx b/src/adplug/core/mkj.cxx
deleted file mode 100644
index 6f7087e69b76..000000000000
--- a/src/adplug/core/mkj.cxx
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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
- *
- * mkj.cpp - MKJamz Player, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <assert.h>
-#include <string.h>
-
-#include "mkj.h"
-#include "debug.h"
-
-CPlayer *
-CmkjPlayer::factory (Copl * newopl)
-{
-  return new CmkjPlayer (newopl);
-}
-
-bool
-CmkjPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  char id[6];
-  float ver;
-  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;
-  }
-
-  // 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]);
-  }
-  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", vfs_get_filename (fd), ver, maxchannel, maxnotes);
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-bool
-CmkjPlayer::update ()
-{
-  int c, i;
-  short note;
-
-  for (c = 0; c < maxchannel; c++)
-  {
-    if (!channel[c].defined)    // skip if channel is disabled
-      continue;
-
-    if (channel[c].pstat)
-    {
-      channel[c].pstat--;
-      continue;
-    }
-
-    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)
-          channel[c].pstat = channel[c].speed;
-      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
-        channel[c].songptr += maxchannel;
-        channel[c].pstat = songbuf[channel[c].songptr];
-        break;
-      case 254:                // set octave
-        channel[c].songptr += maxchannel;
-        channel[c].octave = songbuf[channel[c].songptr];
-        break;
-      case 253:                // set speed
-        channel[c].songptr += maxchannel;
-        channel[c].speed = songbuf[channel[c].songptr];
-        break;
-      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);
-        else
-          opl->write (0xe0 + c, channel[c].waveform);
-        break;
-      case 251:                // song end
-        for (i = 0; i < maxchannel; i++)
-          channel[i].songptr = i;
-        songend = true;
-        return false;
-      }
-
-      if (channel[c].songptr - c < maxnotes)
-        channel[c].songptr += maxchannel;
-      else
-        channel[c].songptr = c;
-    } while (!channel[c].pstat);
-  }
-
-  return !songend;
-}
-
-void
-CmkjPlayer::rewind (int subsong)
-{
-  int i;
-
-  for (i = 0; i < maxchannel; i++)
-  {
-    channel[i].pstat = 0;
-    channel[i].speed = 0;
-    channel[i].waveform = 0;
-    channel[i].songptr = i;
-    channel[i].octave = 4;
-  }
-
-  songend = false;
-}
-
-float
-CmkjPlayer::getrefresh ()
-{
-  return 100.0f;
-}
diff --git a/src/adplug/core/mkj.h b/src/adplug/core/mkj.h
index 0979489f79b7..748012835bc0 100644
--- a/src/adplug/core/mkj.h
+++ b/src/adplug/core/mkj.h
@@ -32,7 +32,7 @@ public:
 	~CmkjPlayer()
 	{ if(songbuf) delete [] songbuf; }
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh();
diff --git a/src/adplug/core/msc.cc b/src/adplug/core/msc.cc
new file mode 100644
index 000000000000..7b04a97e70b7
--- /dev/null
+++ b/src/adplug/core/msc.cc
@@ -0,0 +1,338 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * msc.c - MSC Player by Lubomir Bulej (pallas at kadan.cz)
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "msc.h"
+#include "debug.h"
+
+const unsigned char
+  CmscPlayer::msc_signature[MSC_SIGN_LEN] = {
+  'C', 'e', 'r', 'e', 's', ' ', '\x13', ' ',
+  'M', 'S', 'C', 'p', 'l', 'a', 'y', ' '
+};
+
+/*** public methods *************************************/
+
+CPlayer *
+CmscPlayer::factory (Copl * newopl)
+{
+  return new CmscPlayer (newopl);
+}
+
+CmscPlayer::CmscPlayer (Copl * newopl):CPlayer (newopl)
+{
+  desc = nullptr;
+  msc_data = nullptr;
+  raw_data = nullptr;
+  nr_blocks = 0;
+}
+
+CmscPlayer::~CmscPlayer ()
+{
+  if (raw_data != nullptr)
+    delete[]raw_data;
+
+  if (msc_data != nullptr)
+  {
+    // 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;
+    }
+
+    delete[]msc_data;
+  }
+
+  if (desc != nullptr)
+    delete[]desc;
+}
+
+bool
+CmscPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *bf;
+  msc_header hdr;
+
+  // open and validate the file
+  bf = fp.open (fd);
+  if (!bf)
+    return false;
+
+  if (!load_header (bf, &hdr))
+  {
+    fp.close (bf);
+    return false;
+  }
+
+  // get stuff from the header
+  version = hdr.mh_ver;
+  timer_div = hdr.mh_timer;
+  nr_blocks = hdr.mh_nr_blocks;
+  block_len = hdr.mh_block_len;
+
+  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];
+
+  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);
+    }
+
+    msc_data[blk_num] = blk;
+  }
+
+  // clean up & initialize
+  fp.close (bf);
+  rewind (0);
+
+  return true;
+}
+
+bool
+CmscPlayer::update ()
+{
+  // output data
+  while (!delay)
+  {
+    u8 cmnd;
+    u8 data;
+
+    // decode data
+    if (!decode_octet (&cmnd))
+      return false;
+
+    if (!decode_octet (&data))
+      return false;
+
+    // check for special commands
+    switch (cmnd)
+    {
+
+      // delay
+    case 0xff:
+      delay = 1 + (u8) (data - 1);
+      break;
+
+      // play command & data
+    default:
+      opl->write (cmnd, data);
+
+    }                           // command switch
+  }                             // play pass
+
+
+  // count delays
+  if (delay)
+    delay--;
+
+  // advance player position
+  play_pos++;
+  return true;
+}
+
+void
+CmscPlayer::rewind (int subsong)
+{
+  // reset state
+  dec_prefix = 0;
+  block_num = 0;
+  block_pos = 0;
+  play_pos = 0;
+  raw_pos = 0;
+  delay = 0;
+
+  // init the OPL chip and go to OPL2 mode
+  opl->init ();
+  opl->write (1, 32);
+}
+
+float
+CmscPlayer::getrefresh ()
+{
+  // PC timer oscillator frequency / wait register
+  return 1193180 / (float) (timer_div ? timer_div : 0xffff);
+}
+
+std::string CmscPlayer::gettype ()
+{
+  char
+    vstr[40];
+
+  sprintf (vstr, "AdLib MSCplay (version %d)", version);
+  return std::string (vstr);
+}
+
+/*** private methods *************************************/
+
+bool
+CmscPlayer::load_header (binistream * bf, msc_header * hdr)
+{
+  // check signature
+  bf->readString ((char *) hdr->mh_sign, sizeof (hdr->mh_sign));
+  if (memcmp (msc_signature, hdr->mh_sign, MSC_SIGN_LEN) != 0)
+    return false;
+
+  // check version
+  hdr->mh_ver = bf->readInt (2);
+  if (hdr->mh_ver != 0)
+    return false;
+
+  bf->readString ((char *) hdr->mh_desc, sizeof (hdr->mh_desc));
+  hdr->mh_timer = bf->readInt (2);
+  hdr->mh_nr_blocks = bf->readInt (2);
+  hdr->mh_block_len = bf->readInt (2);
+  return true;
+}
+
+bool
+CmscPlayer::decode_octet (u8 * output)
+{
+  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
+
+    // advance to next block if necessary
+    if (block_pos >= blk.mb_length && dec_len == 0)
+    {
+      block_num++;
+      if (block_num >= nr_blocks)
+        return false;
+
+      blk = msc_data[block_num];
+      block_pos = 0;
+      raw_pos = 0;
+    }
+
+    // decode the compressed music data
+    switch (dec_prefix)
+    {
+
+      // decode prefix
+    case 155:
+    case 175:
+      octet = blk.mb_data[block_pos++];
+      if (octet == 0)
+      {
+        // invalid prefix, output original
+        octet = dec_prefix;
+        dec_prefix = 0;
+        break;
+      }
+
+      // isolate length and distance
+      dec_len = (octet & 0x0F);
+      len_corr = 2;
+
+      dec_dist = (octet & 0xF0) >> 4;
+      if (dec_prefix == 155)
+        dec_dist++;
+
+      // next decode step for respective prefix type
+      dec_prefix++;
+      continue;
+
+
+      // check for extended length
+    case 156:
+      if (dec_len == 15)
+        dec_len += blk.mb_data[block_pos++];
+
+      // add length correction and go for copy mode
+      dec_len += len_corr;
+      dec_prefix = 255;
+      continue;
+
+
+      // get extended distance
+    case 176:
+      dec_dist += 17 + 16 * blk.mb_data[block_pos++];
+      len_corr = 3;
+
+      // check for extended length
+      dec_prefix = 156;
+      continue;
+
+
+      // 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");
+        octet = 0;
+      }
+
+      dec_len--;
+      if (dec_len == 0)
+      {
+        // back to normal mode
+        dec_prefix = 0;
+      }
+
+      break;
+
+
+      // normal mode
+    default:
+      octet = blk.mb_data[block_pos++];
+      if (octet == 155 || octet == 175)
+      {
+        // it's a prefix, restart
+        dec_prefix = octet;
+        continue;
+      }
+    }                           // prefix switch
+
+
+    // output the octet
+    if (output != nullptr)
+      *output = octet;
+
+    raw_data[raw_pos++] = octet;
+    break;
+  };                            // decode pass
+
+  return true;
+}
diff --git a/src/adplug/core/msc.cxx b/src/adplug/core/msc.cxx
deleted file mode 100644
index 2fe4c72220c8..000000000000
--- a/src/adplug/core/msc.cxx
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * msc.c - MSC Player by Lubomir Bulej (pallas at kadan.cz)
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "msc.h"
-#include "debug.h"
-
-const unsigned char
-  CmscPlayer::msc_signature[MSC_SIGN_LEN] = {
-  'C', 'e', 'r', 'e', 's', ' ', '\x13', ' ',
-  'M', 'S', 'C', 'p', 'l', 'a', 'y', ' '
-};
-
-/*** public methods *************************************/
-
-CPlayer *
-CmscPlayer::factory (Copl * newopl)
-{
-  return new CmscPlayer (newopl);
-}
-
-CmscPlayer::CmscPlayer (Copl * newopl):CPlayer (newopl)
-{
-  desc = NULL;
-  msc_data = NULL;
-  raw_data = NULL;
-  nr_blocks = 0;
-}
-
-CmscPlayer::~CmscPlayer ()
-{
-  if (raw_data != NULL)
-    delete[]raw_data;
-
-  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 != NULL)
-        delete[]msc_data[blk_num].mb_data;
-    }
-
-    delete[]msc_data;
-  }
-
-  if (desc != NULL)
-    delete[]desc;
-}
-
-bool
-CmscPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *bf;
-  msc_header hdr;
-
-  // open and validate the file
-  bf = fp.open (fd);
-  if (!bf)
-    return false;
-
-  if (!load_header (bf, &hdr))
-  {
-    fp.close (bf);
-    return false;
-  }
-
-  // get stuff from the header
-  version = hdr.mh_ver;
-  timer_div = hdr.mh_timer;
-  nr_blocks = hdr.mh_nr_blocks;
-  block_len = hdr.mh_block_len;
-
-  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];
-
-  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);
-    }
-
-    msc_data[blk_num] = blk;
-  }
-
-  // clean up & initialize
-  fp.close (bf);
-  rewind (0);
-
-  return true;
-}
-
-bool
-CmscPlayer::update ()
-{
-  // output data
-  while (!delay)
-  {
-    u8 cmnd;
-    u8 data;
-
-    // decode data
-    if (!decode_octet (&cmnd))
-      return false;
-
-    if (!decode_octet (&data))
-      return false;
-
-    // check for special commands
-    switch (cmnd)
-    {
-
-      // delay
-    case 0xff:
-      delay = 1 + (u8) (data - 1);
-      break;
-
-      // play command & data
-    default:
-      opl->write (cmnd, data);
-
-    }                           // command switch
-  }                             // play pass
-
-
-  // count delays
-  if (delay)
-    delay--;
-
-  // advance player position
-  play_pos++;
-  return true;
-}
-
-void
-CmscPlayer::rewind (int subsong)
-{
-  // reset state
-  dec_prefix = 0;
-  block_num = 0;
-  block_pos = 0;
-  play_pos = 0;
-  raw_pos = 0;
-  delay = 0;
-
-  // init the OPL chip and go to OPL2 mode
-  opl->init ();
-  opl->write (1, 32);
-}
-
-float
-CmscPlayer::getrefresh ()
-{
-  // PC timer oscillator frequency / wait register
-  return 1193180 / (float) (timer_div ? timer_div : 0xffff);
-}
-
-std::string CmscPlayer::gettype ()
-{
-  char
-    vstr[40];
-
-  sprintf (vstr, "AdLib MSCplay (version %d)", version);
-  return std::string (vstr);
-}
-
-/*** private methods *************************************/
-
-bool
-CmscPlayer::load_header (binistream * bf, msc_header * hdr)
-{
-  // check signature
-  bf->readString ((char *) hdr->mh_sign, sizeof (hdr->mh_sign));
-  if (memcmp (msc_signature, hdr->mh_sign, MSC_SIGN_LEN) != 0)
-    return false;
-
-  // check version
-  hdr->mh_ver = bf->readInt (2);
-  if (hdr->mh_ver != 0)
-    return false;
-
-  bf->readString ((char *) hdr->mh_desc, sizeof (hdr->mh_desc));
-  hdr->mh_timer = bf->readInt (2);
-  hdr->mh_nr_blocks = bf->readInt (2);
-  hdr->mh_block_len = bf->readInt (2);
-  return true;
-}
-
-bool
-CmscPlayer::decode_octet (u8 * output)
-{
-  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
-
-    // advance to next block if necessary
-    if (block_pos >= blk.mb_length && dec_len == 0)
-    {
-      block_num++;
-      if (block_num >= nr_blocks)
-        return false;
-
-      blk = msc_data[block_num];
-      block_pos = 0;
-      raw_pos = 0;
-    }
-
-    // decode the compressed music data
-    switch (dec_prefix)
-    {
-
-      // decode prefix
-    case 155:
-    case 175:
-      octet = blk.mb_data[block_pos++];
-      if (octet == 0)
-      {
-        // invalid prefix, output original
-        octet = dec_prefix;
-        dec_prefix = 0;
-        break;
-      }
-
-      // isolate length and distance
-      dec_len = (octet & 0x0F);
-      len_corr = 2;
-
-      dec_dist = (octet & 0xF0) >> 4;
-      if (dec_prefix == 155)
-        dec_dist++;
-
-      // next decode step for respective prefix type
-      dec_prefix++;
-      continue;
-
-
-      // check for extended length
-    case 156:
-      if (dec_len == 15)
-        dec_len += blk.mb_data[block_pos++];
-
-      // add length correction and go for copy mode
-      dec_len += len_corr;
-      dec_prefix = 255;
-      continue;
-
-
-      // get extended distance
-    case 176:
-      dec_dist += 17 + 16 * blk.mb_data[block_pos++];
-      len_corr = 3;
-
-      // check for extended length
-      dec_prefix = 156;
-      continue;
-
-
-      // 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");
-        octet = 0;
-      }
-
-      dec_len--;
-      if (dec_len == 0)
-      {
-        // back to normal mode
-        dec_prefix = 0;
-      }
-
-      break;
-
-
-      // normal mode
-    default:
-      octet = blk.mb_data[block_pos++];
-      if (octet == 155 || octet == 175)
-      {
-        // it's a prefix, restart
-        dec_prefix = octet;
-        continue;
-      }
-    }                           // prefix switch
-
-
-    // output the octet
-    if (output != NULL)
-      *output = octet;
-
-    raw_data[raw_pos++] = octet;
-    break;
-  };                            // decode pass
-
-  return true;
-}
diff --git a/src/adplug/core/msc.h b/src/adplug/core/msc.h
index fbdf3a97c881..67b3fb594e77 100644
--- a/src/adplug/core/msc.h
+++ b/src/adplug/core/msc.h
@@ -32,7 +32,7 @@ public:
 	CmscPlayer (Copl * newopl);
 	~CmscPlayer ();
 	
-	bool load (VFSFile *fd, const CFileProvider &fp);
+	bool load (VFSFile &fd, const CFileProvider &fp);
 	bool update ();
 	void rewind (int subsong);
 	float getrefresh ();
diff --git a/src/adplug/core/mtk.cc b/src/adplug/core/mtk.cc
new file mode 100644
index 000000000000..dc7c321689e1
--- /dev/null
+++ b/src/adplug/core/mtk.cc
@@ -0,0 +1,168 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * mtk.cpp - MPU-401 Trakker Loader by Simon Peter (dn.tlp at gmx.net)
+ */
+
+#include <string.h>
+
+#include "mtk.h"
+
+/*** public methods **************************************/
+
+CPlayer *
+CmtkLoader::factory (Copl * newopl)
+{
+  return new CmtkLoader (newopl);
+}
+
+bool
+CmtkLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  struct
+  {
+    char id[18];
+    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];
+  } *data;
+  unsigned char *cmp, *org;
+  unsigned int i;
+  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);
+
+  // file validation section
+  if (strncmp (header.id, "mpu401tr\x92kk\xeer at data", 18))
+  {
+    fp.close (f);
+    return false;
+  }
+
+  // load section
+  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);
+
+  while (cmpptr < cmpsize)
+  {                             // decompress
+    ctrlmask >>= 1;
+    if (!ctrlmask)
+    {
+      ctrlbits = cmp[cmpptr] + (cmp[cmpptr + 1] << 8);
+      cmpptr += 2;
+      ctrlmask = 0x8000;
+    }
+    if (!(ctrlbits & ctrlmask))
+    {                           // uncompressed data
+      if (orgptr >= header.size)
+        goto err;
+
+      org[orgptr] = cmp[cmpptr];
+      orgptr++;
+      cmpptr++;
+      continue;
+    }
+
+    // compressed data
+    cmd = (cmp[cmpptr] >> 4) & 0x0f;
+    cnt = cmp[cmpptr] & 0x0f;
+    cmpptr++;
+    switch (cmd)
+    {
+    case 0:
+      if (orgptr + cnt > header.size)
+        goto err;
+      cnt += 3;
+      memset (&org[orgptr], cmp[cmpptr], cnt);
+      cmpptr++;
+      orgptr += cnt;
+      break;
+
+    case 1:
+      if (orgptr + cnt > header.size)
+        goto err;
+      cnt += (cmp[cmpptr] << 4) + 19;
+      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);
+      orgptr += cnt;
+      break;
+
+    default:
+      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;
+  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
+    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);
+  return true;
+
+err:
+  delete[]cmp;
+  delete[]org;
+  return false;
+}
diff --git a/src/adplug/core/mtk.cxx b/src/adplug/core/mtk.cxx
deleted file mode 100644
index f404b14f3ea5..000000000000
--- a/src/adplug/core/mtk.cxx
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * mtk.cpp - MPU-401 Trakker Loader by Simon Peter (dn.tlp at gmx.net)
- */
-
-#include <string.h>
-
-#include "mtk.h"
-
-/*** public methods **************************************/
-
-CPlayer *
-CmtkLoader::factory (Copl * newopl)
-{
-  return new CmtkLoader (newopl);
-}
-
-bool
-CmtkLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  struct
-  {
-    char id[18];
-    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];
-  } *data;
-  unsigned char *cmp, *org;
-  unsigned int i;
-  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);
-
-  // file validation section
-  if (strncmp (header.id, "mpu401tr\x92kk\xeer at data", 18))
-  {
-    fp.close (f);
-    return false;
-  }
-
-  // load section
-  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);
-
-  while (cmpptr < cmpsize)
-  {                             // decompress
-    ctrlmask >>= 1;
-    if (!ctrlmask)
-    {
-      ctrlbits = cmp[cmpptr] + (cmp[cmpptr + 1] << 8);
-      cmpptr += 2;
-      ctrlmask = 0x8000;
-    }
-    if (!(ctrlbits & ctrlmask))
-    {                           // uncompressed data
-      if (orgptr >= header.size)
-        goto err;
-
-      org[orgptr] = cmp[cmpptr];
-      orgptr++;
-      cmpptr++;
-      continue;
-    }
-
-    // compressed data
-    cmd = (cmp[cmpptr] >> 4) & 0x0f;
-    cnt = cmp[cmpptr] & 0x0f;
-    cmpptr++;
-    switch (cmd)
-    {
-    case 0:
-      if (orgptr + cnt > header.size)
-        goto err;
-      cnt += 3;
-      memset (&org[orgptr], cmp[cmpptr], cnt);
-      cmpptr++;
-      orgptr += cnt;
-      break;
-
-    case 1:
-      if (orgptr + cnt > header.size)
-        goto err;
-      cnt += (cmp[cmpptr] << 4) + 19;
-      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);
-      orgptr += cnt;
-      break;
-
-    default:
-      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;
-  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
-    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);
-  return true;
-
-err:
-  delete[]cmp;
-  delete[]org;
-  return false;
-}
diff --git a/src/adplug/core/mtk.h b/src/adplug/core/mtk.h
index 30d12e94a845..4d68ac7f96f6 100644
--- a/src/adplug/core/mtk.h
+++ b/src/adplug/core/mtk.h
@@ -32,7 +32,7 @@ class CmtkLoader: public ChscPlayer
 		mtkmode = 1;
 	};
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 
 	std::string gettype()
 	{ return std::string("MPU-401 Trakker"); };
diff --git a/src/adplug/core/player.cc b/src/adplug/core/player.cc
new file mode 100644
index 000000000000..a70d435bbbd7
--- /dev/null
+++ b/src/adplug/core/player.cc
@@ -0,0 +1,73 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * player.cpp - Replayer base class, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include "player.h"
+#include "adplug.h"
+#include "silentopl.h"
+
+/***** CPlayer *****/
+
+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 };
+
+CPlayer::CPlayer (Copl * newopl):opl (newopl), db (CAdPlug::database)
+{
+}
+
+CPlayer::~CPlayer ()
+{
+}
+
+unsigned long
+CPlayer::songlength (int subsong)
+{
+  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);
+
+  // restore original OPL and return
+  opl = saveopl;
+  return (unsigned long) slength;
+}
+
+void
+CPlayer::seek (unsigned long ms)
+{
+  float pos = 0.0f;
+
+  rewind ();
+  while (pos < ms && update ()) // seek to new position
+    pos += 1000 / getrefresh ();
+}
diff --git a/src/adplug/core/player.cxx b/src/adplug/core/player.cxx
deleted file mode 100644
index a70d435bbbd7..000000000000
--- a/src/adplug/core/player.cxx
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * player.cpp - Replayer base class, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include "player.h"
-#include "adplug.h"
-#include "silentopl.h"
-
-/***** CPlayer *****/
-
-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 };
-
-CPlayer::CPlayer (Copl * newopl):opl (newopl), db (CAdPlug::database)
-{
-}
-
-CPlayer::~CPlayer ()
-{
-}
-
-unsigned long
-CPlayer::songlength (int subsong)
-{
-  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);
-
-  // restore original OPL and return
-  opl = saveopl;
-  return (unsigned long) slength;
-}
-
-void
-CPlayer::seek (unsigned long ms)
-{
-  float pos = 0.0f;
-
-  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 0231f2f3e555..55472e38389b 100644
--- a/src/adplug/core/player.h
+++ b/src/adplug/core/player.h
@@ -37,7 +37,7 @@ public:
 /***** Operational methods *****/
 	void seek(unsigned long ms);
 
-	virtual bool load(VFSFile *fd,	// loads file
+	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
diff --git a/src/adplug/core/players.cc b/src/adplug/core/players.cc
new file mode 100644
index 000000000000..5553b77eb333
--- /dev/null
+++ b/src/adplug/core/players.cc
@@ -0,0 +1,107 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp at 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
+ *
+ * players.h - Players enumeration, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "players.h"
+
+#include <libaudcore/audstrings.h>
+
+/***** CPlayerDesc *****/
+
+CPlayerDesc::CPlayerDesc()
+  : factory(0), extensions(0), extlength(0)
+{
+}
+
+CPlayerDesc::CPlayerDesc(const CPlayerDesc &pd)
+  : factory(pd.factory), filetype(pd.filetype), extlength(pd.extlength)
+{
+  if(pd.extensions) {
+    extensions = (char *)malloc(extlength);
+    memcpy(extensions, pd.extensions, extlength);
+  } else
+    extensions = 0;
+}
+
+CPlayerDesc::CPlayerDesc(Factory f, const std::string &type, const char *ext)
+  : factory(f), filetype(type), extensions(0)
+{
+  const char *i = 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
+
+  extensions = (char *)malloc(extlength);
+  memcpy(extensions, ext, extlength);
+}
+
+CPlayerDesc::~CPlayerDesc()
+{
+  if(extensions) free(extensions);
+}
+
+void CPlayerDesc::add_extension(const char *ext)
+{
+  unsigned long newlength = extlength + strlen(ext) + 1;
+
+  extensions = (char *)realloc(extensions, newlength);
+  strcpy(extensions + extlength - 1, ext);
+  extensions[newlength - 1] = '\0';
+  extlength = newlength;
+}
+
+const char *CPlayerDesc::get_extension(unsigned int n) const
+{
+  const char	*i = extensions;
+  unsigned int	j;
+
+  for(j = 0; j < n && (*i); j++, i += strlen(i) + 1) ;
+  return (*i != '\0' ? i : 0);
+}
+
+/***** CPlayers *****/
+
+const CPlayerDesc *CPlayers::lookup_filetype(const std::string &ftype) const
+{
+  const_iterator	i;
+
+  for(i = begin(); i != end(); i++)
+    if((*i)->filetype == ftype)
+      return *i;
+
+  return 0;
+}
+
+const CPlayerDesc *CPlayers::lookup_extension(const std::string &extension) const
+{
+  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;
+
+  return 0;
+}
diff --git a/src/adplug/core/players.cxx b/src/adplug/core/players.cxx
deleted file mode 100644
index cf04e28cfcfb..000000000000
--- a/src/adplug/core/players.cxx
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp at 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
- *
- * players.h - Players enumeration, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "players.h"
-
-/***** CPlayerDesc *****/
-
-CPlayerDesc::CPlayerDesc()
-  : factory(0), extensions(0), extlength(0)
-{
-}
-
-CPlayerDesc::CPlayerDesc(const CPlayerDesc &pd)
-  : factory(pd.factory), filetype(pd.filetype), extlength(pd.extlength)
-{
-  if(pd.extensions) {
-    extensions = (char *)malloc(extlength);
-    memcpy(extensions, pd.extensions, extlength);
-  } else
-    extensions = 0;
-}
-
-CPlayerDesc::CPlayerDesc(Factory f, const std::string &type, const char *ext)
-  : factory(f), filetype(type), extensions(0)
-{
-  const char *i = 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
-
-  extensions = (char *)malloc(extlength);
-  memcpy(extensions, ext, extlength);
-}
-
-CPlayerDesc::~CPlayerDesc()
-{
-  if(extensions) free(extensions);
-}
-
-void CPlayerDesc::add_extension(const char *ext)
-{
-  unsigned long newlength = extlength + strlen(ext) + 1;
-
-  extensions = (char *)realloc(extensions, newlength);
-  strcpy(extensions + extlength - 1, ext);
-  extensions[newlength - 1] = '\0';
-  extlength = newlength;
-}
-
-const char *CPlayerDesc::get_extension(unsigned int n) const
-{
-  const char	*i = extensions;
-  unsigned int	j;
-
-  for(j = 0; j < n && (*i); j++, i += strlen(i) + 1) ;
-  return (*i != '\0' ? i : 0);
-}
-
-/***** CPlayers *****/
-
-const CPlayerDesc *CPlayers::lookup_filetype(const std::string &ftype) const
-{
-  const_iterator	i;
-
-  for(i = begin(); i != end(); i++)
-    if((*i)->filetype == ftype)
-      return *i;
-
-  return 0;
-}
-
-const CPlayerDesc *CPlayers::lookup_extension(const std::string &extension) const
-{
-  const_iterator	i;
-  unsigned int		j;
-
-  for(i = begin(); i != end(); i++)
-    for(j = 0; (*i)->get_extension(j); j++)
-      if(!g_ascii_strcasecmp(extension.c_str(), (*i)->get_extension(j)))
-	return *i;
-
-  return 0;
-}
diff --git a/src/adplug/core/protrack.cc b/src/adplug/core/protrack.cc
new file mode 100644
index 000000000000..ba43cae143f3
--- /dev/null
+++ b/src/adplug/core/protrack.cc
@@ -0,0 +1,996 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * protrack.cpp - Generic Protracker Player
+ *
+ * NOTES:
+ * This is a generic Protracker-based formats player. It offers all Protracker
+ * features, plus a good set of extensions to be compatible to other Protracker
+ * derivatives. It is derived from the former SA2 player. If you got a
+ * Protracker-like format, this is most certainly the player you want to use.
+ */
+
+#include <string.h>
+
+#include "protrack.h"
+#include "debug.h"
+
+#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 };
+
+// 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 };
+
+/*** 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)
+{
+  realloc_order (128);
+  realloc_patterns (64, 64, 9);
+  realloc_instruments (250);
+  init_notetable (sa2_notetable);
+}
+
+CmodPlayer::~CmodPlayer ()
+{
+  dealloc ();
+}
+
+bool
+CmodPlayer::update ()
+{
+  unsigned char pattbreak = 0, donote, pattnr, chan, oplchan, info1,
+    info2, info, pattern_delay;
+  unsigned short track;
+  unsigned long row;
+
+  if (!speed)                   // song full stop
+    return !songend;
+
+  // effect handling (timer dependant)
+  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)
+        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);
+          }
+        }
+        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)
+      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);
+      }
+      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);
+      else
+        vol_down (chan, info2);
+      setvolume (chan);
+      break;
+    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);
+      else
+        vol_down_alt (chan, info2);
+      setvolume (chan);
+      break;
+    case 20:                   // RAD volume slide
+      if (info < 50)
+        vol_down_alt (chan, info);
+      else
+        vol_up_alt (chan, info - 50);
+      setvolume (chan);
+      break;
+    case 26:                   // volume slide
+      if (info1)
+        vol_up (chan, info1);
+      else
+        vol_down (chan, info2);
+      setvolume (chan);
+      break;
+    case 28:
+      if (info1)
+      {
+        slide_up (chan, 1);
+        channel[chan].info1--;
+      }
+      if (info2)
+      {
+        slide_down (chan, 1);
+        channel[chan].info2--;
+      }
+      setfreq (chan);
+      break;
+    }
+  }
+
+  if (del)
+  {                             // speed compensation
+    del--;
+    return !songend;
+  }
+
+  // arrangement handling
+  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);
+
+  // play row
+  pattern_delay = 0;
+  row = rw;
+  for (chan = 0; chan < nchans; chan++)
+  {
+    oplchan = set_opl_chip (chan);
+
+    if (!(activechan >> (31 - chan)) & 1)
+    {                           // channel active?
+      AdPlug_LogWrite ("N/A|");
+      continue;
+    }
+    if (!(track = trackord[pattnr][chan]))
+    {                           // resolve track
+      AdPlug_LogWrite ("------------|");
+      continue;
+    }
+    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);
+
+    donote = 0;
+    if (tracks[track][row].inst)
+    {
+      channel[chan].inst = tracks[track][row].inst - 1;
+      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);
+      }
+    }
+
+    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);
+      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
+        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);
+
+    // command handling (row dependant)
+    info1 = channel[chan].info1;
+    info2 = channel[chan].info2;
+    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)
+          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];
+        channel[chan].nextoct = (tracks[track][row].note - 1) / 12;
+        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
+        channel[chan].portainfo = info;
+      break;
+
+    case 4:                    // vibrato (remember vars)
+      if (info)
+      {
+        channel[chan].vibinfo1 = info1;
+        channel[chan].vibinfo2 = info2;
+      }
+      break;
+
+    case 7:
+      tempo = info;
+      break;                    // set tempo
+
+    case 8:
+      channel[chan].key = 0;
+      setfreq (chan);
+      break;                    // release sustaining note
+
+    case 9:                    // set carrier/modulator volume
+      if (info1)
+        channel[chan].vol1 = info1 * 7;
+      else
+        channel[chan].vol2 = info2 * 7;
+      setvolume (chan);
+      break;
+
+    case 11:                   // position jump
+      pattbreak = 1;
+      rw = 0;
+      if (info < ord)
+        songend = 1;
+      ord = info;
+      break;
+
+    case 12:                   // set volume
+      channel[chan].vol1 = info;
+      channel[chan].vol2 = info;
+      if (channel[chan].vol1 > 63)
+        channel[chan].vol1 = 63;
+      if (channel[chan].vol2 > 63)
+        channel[chan].vol2 = 63;
+      setvolume (chan);
+      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)
+          regbd |= 128;
+        else
+          regbd &= 127;
+        opl->write (0xbd, regbd);
+        break;
+
+      case 1:                  // define cell-vibrato
+        if (info2)
+          regbd |= 64;
+        else
+          regbd &= 191;
+        opl->write (0xbd, regbd);
+        break;
+
+      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);
+        break;
+
+      case 6:                  // manual slide up
+        slide_up (chan, info2);
+        setfreq (chan);
+        break;
+
+      case 7:                  // manual slide down
+        slide_down (chan, info2);
+        setfreq (chan);
+        break;
+
+      case 8:                  // pattern delay (rows)
+        pattern_delay = info2 * speed;
+        break;
+      }
+      break;
+
+    case 15:                   // SA2 set speed
+      if (info <= 0x1f)
+        speed = info;
+      if (info >= 0x32)
+        tempo = info;
+      if (!info)
+        songend = 1;
+      break;
+
+    case 17:                   // alternate set volume
+      channel[chan].vol1 = info;
+      if (channel[chan].vol1 > 63)
+        channel[chan].vol1 = 63;
+      if (inst[channel[chan].inst].data[0] & 1)
+      {
+        channel[chan].vol2 = info;
+        if (channel[chan].vol2 > 63)
+          channel[chan].vol2 = 63;
+      }
+
+      setvolume (chan);
+      break;
+
+    case 18:                   // AMD set speed
+      if (info <= 31 && info > 0)
+        speed = info;
+      if (info > 31 || !info)
+        tempo = info;
+      break;
+
+    case 19:                   // RAD/A2M set speed
+      speed = (info ? info : info + 1);
+      break;
+
+    case 21:                   // set modulator volume
+      if (info <= 63)
+        channel[chan].vol2 = info;
+      else
+        channel[chan].vol2 = 63;
+      setvolume (chan);
+      break;
+
+    case 22:                   // set carrier volume
+      if (info <= 63)
+        channel[chan].vol1 = info;
+      else
+        channel[chan].vol1 = 63;
+      setvolume (chan);
+      break;
+
+    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);
+      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);
+      break;
+
+    case 27:                   // set chip tremolo/vibrato
+      if (info1)
+        regbd |= 128;
+      else
+        regbd &= 127;
+      if (info2)
+        regbd |= 64;
+      else
+        regbd &= 191;
+      opl->write (0xbd, regbd);
+      break;
+
+    case 29:                   // pattern delay (frames)
+      pattern_delay = info;
+      break;
+    }
+  }
+
+  // speed compensation
+  del = speed - 1 + pattern_delay;
+
+  if (!pattbreak)
+  {                             // next row (only if no manual advance)
+    rw++;
+    if (rw >= nrows)
+    {
+      rw = 0;
+      ord++;
+    }
+  }
+
+  resolve_order ();             // so we can report songend right away
+  AdPlug_LogWrite ("\n");
+  return !songend;
+}
+
+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
+   * number.
+   */
+{
+  int newchip = chan < 9 ? 0 : 1;
+
+  if (newchip != curchip)
+  {
+    opl->setchip (newchip);
+    curchip = newchip;
+  }
+
+  return chan % 9;
+}
+
+bool
+CmodPlayer::resolve_order ()
+  /*
+   * Resolves current orderlist entry, checking for jumps and loops.
+   *
+   * Returns true on correct processing, false if immediate recursive loop
+   * has been detected.
+   */
+{
+  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;
+      ord = neword;
+    }
+  }
+  else
+  {
+    songend = 1;
+    ord = restartpos;
+  }
+
+  return true;
+}
+
+void
+CmodPlayer::rewind (int subsong)
+{
+  unsigned long i;
+
+  // Reset playing variables
+  songend = del = ord = rw = regbd = 0;
+  tempo = bpm;
+  speed = initspeed;
+
+  // Reset channel data
+  memset (channel, 0, sizeof (Channel) * nchans);
+
+  // Compute number of patterns, if needed
+  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
+
+  // Enable OPL3 extensions if flagged
+  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);
+}
+
+float
+CmodPlayer::getrefresh ()
+{
+  return (float) (tempo / 2.5);
+}
+
+void
+CmodPlayer::init_trackord ()
+{
+  unsigned long i;
+
+  for (i = 0; i < npats * nchans; i++)
+    trackord[i / nchans][i % nchans] = i + 1;
+}
+
+bool
+CmodPlayer::init_specialarp ()
+{
+  arplist = new unsigned char[SPECIALARPLEN];
+  arpcmd = new unsigned char[SPECIALARPLEN];
+
+  return true;
+}
+
+void
+CmodPlayer::init_notetable (const unsigned short *newnotetable)
+{
+  memcpy (notetable, newnotetable, 12 * 2);
+}
+
+bool
+CmodPlayer::realloc_order (unsigned long len)
+{
+  if (order)
+    delete[]order;
+  order = new unsigned char[len];
+  return true;
+}
+
+bool
+CmodPlayer::realloc_patterns (unsigned long pats, unsigned long rows,
+                              unsigned long chans)
+{
+  unsigned long i;
+
+  dealloc_patterns ();
+
+  // set new number of tracks, rows and channels
+  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];
+  trackord = new unsigned short *[pats];
+  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);
+
+  return true;
+}
+
+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;
+  }
+}
+
+bool
+CmodPlayer::realloc_instruments (unsigned long len)
+{
+  // dealloc previous instance, if any
+  if (inst)
+    delete[]inst;
+
+  inst = new Instrument[len];
+  memset (inst, 0, sizeof (Instrument) * len);  // reset instruments
+  return true;
+}
+
+void
+CmodPlayer::dealloc ()
+{
+  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)
+{
+  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));
+  }
+}
+
+void
+CmodPlayer::setvolume_alt (unsigned char 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));
+}
+
+void
+CmodPlayer::setfreq (unsigned char 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));
+  else
+    opl->write (0xb0 + oplchan,
+                ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
+}
+
+void
+CmodPlayer::playnote (unsigned char 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
+
+  // 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
+
+  // set frequency, volume & play
+  channel[chan].key = 1;
+  setfreq (chan);
+
+  if (flags & Faust)
+  {
+    channel[chan].vol2 = 63;
+    channel[chan].vol1 = 63;
+  }
+  setvolume (chan);
+}
+
+void
+CmodPlayer::setnote (unsigned char chan, int note)
+{
+  if (note > 96)
+  {
+    if (note == 127)
+    {                           // key off
+      channel[chan].key = 0;
+      setfreq (chan);
+      return;
+    }
+    else
+      note = 96;
+  }
+
+  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];
+  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)
+{
+  channel[chan].freq -= amount;
+  if (channel[chan].freq <= 342)
+  {
+    if (channel[chan].oct)
+    {
+      channel[chan].oct--;
+      channel[chan].freq <<= 1;
+    }
+    else
+      channel[chan].freq = 342;
+  }
+}
+
+void
+CmodPlayer::slide_up (unsigned char chan, int amount)
+{
+  channel[chan].freq += amount;
+  if (channel[chan].freq >= 686)
+  {
+    if (channel[chan].oct < 7)
+    {
+      channel[chan].oct++;
+      channel[chan].freq >>= 1;
+    }
+    else
+      channel[chan].freq = 686;
+  }
+}
+
+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))
+    {
+      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))
+    {
+      channel[chan].freq = channel[chan].nextfreq;
+      channel[chan].oct = channel[chan].nextoct;
+    }
+  }
+  setfreq (chan);
+}
+
+void
+CmodPlayer::vibrato (unsigned char chan, unsigned char speed,
+                     unsigned char depth)
+{
+  int i;
+
+  if (!speed || !depth)
+    return;
+
+  if (depth > 14)
+    depth = 14;
+
+  for (i = 0; i < speed; i++)
+  {
+    channel[chan].trigger++;
+    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));
+  }
+  setfreq (chan);
+}
+
+void
+CmodPlayer::vol_up (unsigned char chan, int amount)
+{
+  if (channel[chan].vol1 + amount < 63)
+    channel[chan].vol1 += amount;
+  else
+    channel[chan].vol1 = 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)
+{
+  if (channel[chan].vol1 - amount > 0)
+    channel[chan].vol1 -= amount;
+  else
+    channel[chan].vol1 = 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)
+{
+  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)
+      channel[chan].vol2 += amount;
+    else
+      channel[chan].vol2 = 63;
+  }
+}
+
+void
+CmodPlayer::vol_down_alt (unsigned char chan, int amount)
+{
+  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)
+      channel[chan].vol2 -= amount;
+    else
+      channel[chan].vol2 = 0;
+  }
+}
diff --git a/src/adplug/core/protrack.cxx b/src/adplug/core/protrack.cxx
deleted file mode 100644
index ba43cae143f3..000000000000
--- a/src/adplug/core/protrack.cxx
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * protrack.cpp - Generic Protracker Player
- *
- * NOTES:
- * This is a generic Protracker-based formats player. It offers all Protracker
- * features, plus a good set of extensions to be compatible to other Protracker
- * derivatives. It is derived from the former SA2 player. If you got a
- * Protracker-like format, this is most certainly the player you want to use.
- */
-
-#include <string.h>
-
-#include "protrack.h"
-#include "debug.h"
-
-#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 };
-
-// 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 };
-
-/*** 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)
-{
-  realloc_order (128);
-  realloc_patterns (64, 64, 9);
-  realloc_instruments (250);
-  init_notetable (sa2_notetable);
-}
-
-CmodPlayer::~CmodPlayer ()
-{
-  dealloc ();
-}
-
-bool
-CmodPlayer::update ()
-{
-  unsigned char pattbreak = 0, donote, pattnr, chan, oplchan, info1,
-    info2, info, pattern_delay;
-  unsigned short track;
-  unsigned long row;
-
-  if (!speed)                   // song full stop
-    return !songend;
-
-  // effect handling (timer dependant)
-  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)
-        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);
-          }
-        }
-        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)
-      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);
-      }
-      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);
-      else
-        vol_down (chan, info2);
-      setvolume (chan);
-      break;
-    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);
-      else
-        vol_down_alt (chan, info2);
-      setvolume (chan);
-      break;
-    case 20:                   // RAD volume slide
-      if (info < 50)
-        vol_down_alt (chan, info);
-      else
-        vol_up_alt (chan, info - 50);
-      setvolume (chan);
-      break;
-    case 26:                   // volume slide
-      if (info1)
-        vol_up (chan, info1);
-      else
-        vol_down (chan, info2);
-      setvolume (chan);
-      break;
-    case 28:
-      if (info1)
-      {
-        slide_up (chan, 1);
-        channel[chan].info1--;
-      }
-      if (info2)
-      {
-        slide_down (chan, 1);
-        channel[chan].info2--;
-      }
-      setfreq (chan);
-      break;
-    }
-  }
-
-  if (del)
-  {                             // speed compensation
-    del--;
-    return !songend;
-  }
-
-  // arrangement handling
-  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);
-
-  // play row
-  pattern_delay = 0;
-  row = rw;
-  for (chan = 0; chan < nchans; chan++)
-  {
-    oplchan = set_opl_chip (chan);
-
-    if (!(activechan >> (31 - chan)) & 1)
-    {                           // channel active?
-      AdPlug_LogWrite ("N/A|");
-      continue;
-    }
-    if (!(track = trackord[pattnr][chan]))
-    {                           // resolve track
-      AdPlug_LogWrite ("------------|");
-      continue;
-    }
-    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);
-
-    donote = 0;
-    if (tracks[track][row].inst)
-    {
-      channel[chan].inst = tracks[track][row].inst - 1;
-      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);
-      }
-    }
-
-    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);
-      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
-        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);
-
-    // command handling (row dependant)
-    info1 = channel[chan].info1;
-    info2 = channel[chan].info2;
-    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)
-          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];
-        channel[chan].nextoct = (tracks[track][row].note - 1) / 12;
-        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
-        channel[chan].portainfo = info;
-      break;
-
-    case 4:                    // vibrato (remember vars)
-      if (info)
-      {
-        channel[chan].vibinfo1 = info1;
-        channel[chan].vibinfo2 = info2;
-      }
-      break;
-
-    case 7:
-      tempo = info;
-      break;                    // set tempo
-
-    case 8:
-      channel[chan].key = 0;
-      setfreq (chan);
-      break;                    // release sustaining note
-
-    case 9:                    // set carrier/modulator volume
-      if (info1)
-        channel[chan].vol1 = info1 * 7;
-      else
-        channel[chan].vol2 = info2 * 7;
-      setvolume (chan);
-      break;
-
-    case 11:                   // position jump
-      pattbreak = 1;
-      rw = 0;
-      if (info < ord)
-        songend = 1;
-      ord = info;
-      break;
-
-    case 12:                   // set volume
-      channel[chan].vol1 = info;
-      channel[chan].vol2 = info;
-      if (channel[chan].vol1 > 63)
-        channel[chan].vol1 = 63;
-      if (channel[chan].vol2 > 63)
-        channel[chan].vol2 = 63;
-      setvolume (chan);
-      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)
-          regbd |= 128;
-        else
-          regbd &= 127;
-        opl->write (0xbd, regbd);
-        break;
-
-      case 1:                  // define cell-vibrato
-        if (info2)
-          regbd |= 64;
-        else
-          regbd &= 191;
-        opl->write (0xbd, regbd);
-        break;
-
-      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);
-        break;
-
-      case 6:                  // manual slide up
-        slide_up (chan, info2);
-        setfreq (chan);
-        break;
-
-      case 7:                  // manual slide down
-        slide_down (chan, info2);
-        setfreq (chan);
-        break;
-
-      case 8:                  // pattern delay (rows)
-        pattern_delay = info2 * speed;
-        break;
-      }
-      break;
-
-    case 15:                   // SA2 set speed
-      if (info <= 0x1f)
-        speed = info;
-      if (info >= 0x32)
-        tempo = info;
-      if (!info)
-        songend = 1;
-      break;
-
-    case 17:                   // alternate set volume
-      channel[chan].vol1 = info;
-      if (channel[chan].vol1 > 63)
-        channel[chan].vol1 = 63;
-      if (inst[channel[chan].inst].data[0] & 1)
-      {
-        channel[chan].vol2 = info;
-        if (channel[chan].vol2 > 63)
-          channel[chan].vol2 = 63;
-      }
-
-      setvolume (chan);
-      break;
-
-    case 18:                   // AMD set speed
-      if (info <= 31 && info > 0)
-        speed = info;
-      if (info > 31 || !info)
-        tempo = info;
-      break;
-
-    case 19:                   // RAD/A2M set speed
-      speed = (info ? info : info + 1);
-      break;
-
-    case 21:                   // set modulator volume
-      if (info <= 63)
-        channel[chan].vol2 = info;
-      else
-        channel[chan].vol2 = 63;
-      setvolume (chan);
-      break;
-
-    case 22:                   // set carrier volume
-      if (info <= 63)
-        channel[chan].vol1 = info;
-      else
-        channel[chan].vol1 = 63;
-      setvolume (chan);
-      break;
-
-    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);
-      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);
-      break;
-
-    case 27:                   // set chip tremolo/vibrato
-      if (info1)
-        regbd |= 128;
-      else
-        regbd &= 127;
-      if (info2)
-        regbd |= 64;
-      else
-        regbd &= 191;
-      opl->write (0xbd, regbd);
-      break;
-
-    case 29:                   // pattern delay (frames)
-      pattern_delay = info;
-      break;
-    }
-  }
-
-  // speed compensation
-  del = speed - 1 + pattern_delay;
-
-  if (!pattbreak)
-  {                             // next row (only if no manual advance)
-    rw++;
-    if (rw >= nrows)
-    {
-      rw = 0;
-      ord++;
-    }
-  }
-
-  resolve_order ();             // so we can report songend right away
-  AdPlug_LogWrite ("\n");
-  return !songend;
-}
-
-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
-   * number.
-   */
-{
-  int newchip = chan < 9 ? 0 : 1;
-
-  if (newchip != curchip)
-  {
-    opl->setchip (newchip);
-    curchip = newchip;
-  }
-
-  return chan % 9;
-}
-
-bool
-CmodPlayer::resolve_order ()
-  /*
-   * Resolves current orderlist entry, checking for jumps and loops.
-   *
-   * Returns true on correct processing, false if immediate recursive loop
-   * has been detected.
-   */
-{
-  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;
-      ord = neword;
-    }
-  }
-  else
-  {
-    songend = 1;
-    ord = restartpos;
-  }
-
-  return true;
-}
-
-void
-CmodPlayer::rewind (int subsong)
-{
-  unsigned long i;
-
-  // Reset playing variables
-  songend = del = ord = rw = regbd = 0;
-  tempo = bpm;
-  speed = initspeed;
-
-  // Reset channel data
-  memset (channel, 0, sizeof (Channel) * nchans);
-
-  // Compute number of patterns, if needed
-  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
-
-  // Enable OPL3 extensions if flagged
-  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);
-}
-
-float
-CmodPlayer::getrefresh ()
-{
-  return (float) (tempo / 2.5);
-}
-
-void
-CmodPlayer::init_trackord ()
-{
-  unsigned long i;
-
-  for (i = 0; i < npats * nchans; i++)
-    trackord[i / nchans][i % nchans] = i + 1;
-}
-
-bool
-CmodPlayer::init_specialarp ()
-{
-  arplist = new unsigned char[SPECIALARPLEN];
-  arpcmd = new unsigned char[SPECIALARPLEN];
-
-  return true;
-}
-
-void
-CmodPlayer::init_notetable (const unsigned short *newnotetable)
-{
-  memcpy (notetable, newnotetable, 12 * 2);
-}
-
-bool
-CmodPlayer::realloc_order (unsigned long len)
-{
-  if (order)
-    delete[]order;
-  order = new unsigned char[len];
-  return true;
-}
-
-bool
-CmodPlayer::realloc_patterns (unsigned long pats, unsigned long rows,
-                              unsigned long chans)
-{
-  unsigned long i;
-
-  dealloc_patterns ();
-
-  // set new number of tracks, rows and channels
-  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];
-  trackord = new unsigned short *[pats];
-  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);
-
-  return true;
-}
-
-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;
-  }
-}
-
-bool
-CmodPlayer::realloc_instruments (unsigned long len)
-{
-  // dealloc previous instance, if any
-  if (inst)
-    delete[]inst;
-
-  inst = new Instrument[len];
-  memset (inst, 0, sizeof (Instrument) * len);  // reset instruments
-  return true;
-}
-
-void
-CmodPlayer::dealloc ()
-{
-  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)
-{
-  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));
-  }
-}
-
-void
-CmodPlayer::setvolume_alt (unsigned char 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));
-}
-
-void
-CmodPlayer::setfreq (unsigned char 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));
-  else
-    opl->write (0xb0 + oplchan,
-                ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
-}
-
-void
-CmodPlayer::playnote (unsigned char 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
-
-  // 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
-
-  // set frequency, volume & play
-  channel[chan].key = 1;
-  setfreq (chan);
-
-  if (flags & Faust)
-  {
-    channel[chan].vol2 = 63;
-    channel[chan].vol1 = 63;
-  }
-  setvolume (chan);
-}
-
-void
-CmodPlayer::setnote (unsigned char chan, int note)
-{
-  if (note > 96)
-  {
-    if (note == 127)
-    {                           // key off
-      channel[chan].key = 0;
-      setfreq (chan);
-      return;
-    }
-    else
-      note = 96;
-  }
-
-  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];
-  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)
-{
-  channel[chan].freq -= amount;
-  if (channel[chan].freq <= 342)
-  {
-    if (channel[chan].oct)
-    {
-      channel[chan].oct--;
-      channel[chan].freq <<= 1;
-    }
-    else
-      channel[chan].freq = 342;
-  }
-}
-
-void
-CmodPlayer::slide_up (unsigned char chan, int amount)
-{
-  channel[chan].freq += amount;
-  if (channel[chan].freq >= 686)
-  {
-    if (channel[chan].oct < 7)
-    {
-      channel[chan].oct++;
-      channel[chan].freq >>= 1;
-    }
-    else
-      channel[chan].freq = 686;
-  }
-}
-
-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))
-    {
-      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))
-    {
-      channel[chan].freq = channel[chan].nextfreq;
-      channel[chan].oct = channel[chan].nextoct;
-    }
-  }
-  setfreq (chan);
-}
-
-void
-CmodPlayer::vibrato (unsigned char chan, unsigned char speed,
-                     unsigned char depth)
-{
-  int i;
-
-  if (!speed || !depth)
-    return;
-
-  if (depth > 14)
-    depth = 14;
-
-  for (i = 0; i < speed; i++)
-  {
-    channel[chan].trigger++;
-    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));
-  }
-  setfreq (chan);
-}
-
-void
-CmodPlayer::vol_up (unsigned char chan, int amount)
-{
-  if (channel[chan].vol1 + amount < 63)
-    channel[chan].vol1 += amount;
-  else
-    channel[chan].vol1 = 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)
-{
-  if (channel[chan].vol1 - amount > 0)
-    channel[chan].vol1 -= amount;
-  else
-    channel[chan].vol1 = 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)
-{
-  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)
-      channel[chan].vol2 += amount;
-    else
-      channel[chan].vol2 = 63;
-  }
-}
-
-void
-CmodPlayer::vol_down_alt (unsigned char chan, int amount)
-{
-  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)
-      channel[chan].vol2 -= amount;
-    else
-      channel[chan].vol2 = 0;
-  }
-}
diff --git a/src/adplug/core/protrack.h b/src/adplug/core/protrack.h
index c399c6ff3061..7cd8c77309b2 100644
--- a/src/adplug/core/protrack.h
+++ b/src/adplug/core/protrack.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
@@ -94,7 +94,7 @@ public:
   static const unsigned char vibratotab[32];
 
   unsigned char speed, del, songend, regbd;
-  unsigned short rows, notetable[12];
+  unsigned short notetable[12];
   unsigned long rw, ord, nrows, npats, nchans;
 
   void setvolume(unsigned char chan);
diff --git a/src/adplug/core/psi.cc b/src/adplug/core/psi.cc
new file mode 100644
index 000000000000..3835ecf6c02b
--- /dev/null
+++ b/src/adplug/core/psi.cc
@@ -0,0 +1,187 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] PSI player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : 4BIDDEN.COM, PGRID.EXE
+     type : Forbidden Dreams BBStro
+            Power Grid BBStro
+     tune : by Friar Tuck [Shadow Faction/ICE]
+   player : by Psi [Future Crew]
+  comment : seems to me what 4bidden tune & player was ripped from pgrid
+
+  file(s) : MYSTRUNE.COM
+     type : Mystical Runes BBStro
+     tune : by ?
+   player : by Psi [Future Crew]
+*/
+
+#include "psi.h"
+#include "debug.h"
+
+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,
+  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xE8, 0xEB, 0xC3,
+  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xE9, 0xEC, 0xC4,
+  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xEA, 0xED, 0xC5,
+  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xF0, 0xF3, 0xC6,
+  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xF1, 0xF4, 0xC7,
+  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xF2, 0xF5, 0xC8
+};
+
+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
+};
+
+CPlayer *
+CxadpsiPlayer::factory (Copl * newopl)
+{
+  return new CxadpsiPlayer (newopl);
+}
+
+void
+CxadpsiPlayer::xadplayer_rewind (int subsong)
+{
+  opl_write (0x01, 0x20);
+  opl_write (0x08, 0x00);
+  opl_write (0xBD, 0x00);
+
+  // get header
+  header.instr_ptr = (tune[1] << 8) + tune[0];
+  header.seq_ptr = (tune[3] << 8) + tune[2];
+
+  // define instruments
+  psi.instr_table = &tune[header.instr_ptr];
+
+  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];
+
+      opl_write (psi_adlib_registers[i * 11 + j], tune[inspos + j]);
+    }
+
+    opl_write (0xA0 + i, 0x00);
+    opl_write (0xB0 + i, 0x00);
+
+    psi.note_delay[i] = 1;
+    psi.note_curdelay[i] = 1;
+    psi.looping[i] = 0;
+  }
+
+  // calculate sequence pointer
+  psi.seq_table = &tune[header.seq_ptr];
+}
+
+void
+CxadpsiPlayer::xadplayer_update ()
+{
+  unsigned short ptr;
+
+  for (int i = 0; i < 8; i++)
+  {
+    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);
+
+      unsigned char event = tune[ptr++];
+#ifdef DEBUG
+      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];
+
+        event = tune[ptr++];
+#ifdef DEBUG
+        AdPlug_LogWrite (" channel %02X, event %02X:\n", i + 1, event);
+#endif
+
+        // set sequence loop flag
+        psi.looping[i] = 1;
+
+        // module loop ?
+        plr.looping = 1;
+        for (int j = 0; j < 8; j++)
+          plr.looping &= psi.looping[j];
+      }
+
+      // new note delay ?
+      if (event & 0x80)
+      {
+        psi.note_delay[i] = (event & 0x7F);
+
+        event = tune[ptr++];
+#ifdef DEBUG
+        AdPlug_LogWrite ("  channel %02X, event %02X:\n", i + 1, event);
+#endif
+      }
+
+      psi.note_curdelay[i] = psi.note_delay[i];
+
+      // play note
+      unsigned short note = psi_notes[event & 0x0F];
+
+      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;
+    }
+  }
+}
+
+float
+CxadpsiPlayer::xadplayer_getrefresh ()
+{
+  return 70.0f;
+}
+
+std::string CxadpsiPlayer::xadplayer_gettype ()
+{
+  return std::string ("xad: psi player");
+}
+
+unsigned int
+CxadpsiPlayer::xadplayer_getinstruments ()
+{
+  return 8;
+}
diff --git a/src/adplug/core/psi.cxx b/src/adplug/core/psi.cxx
deleted file mode 100644
index 3835ecf6c02b..000000000000
--- a/src/adplug/core/psi.cxx
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * [xad] PSI player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : 4BIDDEN.COM, PGRID.EXE
-     type : Forbidden Dreams BBStro
-            Power Grid BBStro
-     tune : by Friar Tuck [Shadow Faction/ICE]
-   player : by Psi [Future Crew]
-  comment : seems to me what 4bidden tune & player was ripped from pgrid
-
-  file(s) : MYSTRUNE.COM
-     type : Mystical Runes BBStro
-     tune : by ?
-   player : by Psi [Future Crew]
-*/
-
-#include "psi.h"
-#include "debug.h"
-
-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,
-  0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xE8, 0xEB, 0xC3,
-  0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xE9, 0xEC, 0xC4,
-  0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xEA, 0xED, 0xC5,
-  0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xF0, 0xF3, 0xC6,
-  0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xF1, 0xF4, 0xC7,
-  0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xF2, 0xF5, 0xC8
-};
-
-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
-};
-
-CPlayer *
-CxadpsiPlayer::factory (Copl * newopl)
-{
-  return new CxadpsiPlayer (newopl);
-}
-
-void
-CxadpsiPlayer::xadplayer_rewind (int subsong)
-{
-  opl_write (0x01, 0x20);
-  opl_write (0x08, 0x00);
-  opl_write (0xBD, 0x00);
-
-  // get header
-  header.instr_ptr = (tune[1] << 8) + tune[0];
-  header.seq_ptr = (tune[3] << 8) + tune[2];
-
-  // define instruments
-  psi.instr_table = &tune[header.instr_ptr];
-
-  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];
-
-      opl_write (psi_adlib_registers[i * 11 + j], tune[inspos + j]);
-    }
-
-    opl_write (0xA0 + i, 0x00);
-    opl_write (0xB0 + i, 0x00);
-
-    psi.note_delay[i] = 1;
-    psi.note_curdelay[i] = 1;
-    psi.looping[i] = 0;
-  }
-
-  // calculate sequence pointer
-  psi.seq_table = &tune[header.seq_ptr];
-}
-
-void
-CxadpsiPlayer::xadplayer_update ()
-{
-  unsigned short ptr;
-
-  for (int i = 0; i < 8; i++)
-  {
-    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);
-
-      unsigned char event = tune[ptr++];
-#ifdef DEBUG
-      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];
-
-        event = tune[ptr++];
-#ifdef DEBUG
-        AdPlug_LogWrite (" channel %02X, event %02X:\n", i + 1, event);
-#endif
-
-        // set sequence loop flag
-        psi.looping[i] = 1;
-
-        // module loop ?
-        plr.looping = 1;
-        for (int j = 0; j < 8; j++)
-          plr.looping &= psi.looping[j];
-      }
-
-      // new note delay ?
-      if (event & 0x80)
-      {
-        psi.note_delay[i] = (event & 0x7F);
-
-        event = tune[ptr++];
-#ifdef DEBUG
-        AdPlug_LogWrite ("  channel %02X, event %02X:\n", i + 1, event);
-#endif
-      }
-
-      psi.note_curdelay[i] = psi.note_delay[i];
-
-      // play note
-      unsigned short note = psi_notes[event & 0x0F];
-
-      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;
-    }
-  }
-}
-
-float
-CxadpsiPlayer::xadplayer_getrefresh ()
-{
-  return 70.0f;
-}
-
-std::string CxadpsiPlayer::xadplayer_gettype ()
-{
-  return std::string ("xad: psi player");
-}
-
-unsigned int
-CxadpsiPlayer::xadplayer_getinstruments ()
-{
-  return 8;
-}
diff --git a/src/adplug/core/rad.cc b/src/adplug/core/rad.cc
new file mode 100644
index 000000000000..d9ae560f673b
--- /dev/null
+++ b/src/adplug/core/rad.cc
@@ -0,0 +1,155 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * rad.cpp - RAD Loader by Simon Peter <dn.tlp at gmx.net>
+ *
+ * BUGS:
+ * some volumes are dropped out
+ */
+
+#include <string.h>
+
+#include "rad.h"
+
+CPlayer *
+CradLoader::factory (Copl * newopl)
+{
+  return new CradLoader (newopl);
+}
+
+bool
+CradLoader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  if (!f)
+    return false;
+  char id[16];
+  unsigned char buf, ch, c, b, inp;
+  char bufstr[2] = "\0";
+  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 };
+
+  // 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;
+  }
+
+  // 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, " ");
+      else
+      {
+        *bufstr = buf;
+        strcat (desc, bufstr);
+      }
+  }
+  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);
+  }
+  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);
+
+  // convert replay data
+  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)
+        tracks[i][j].note -= 4 * (tracks[i][j].note >> 4);
+      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;
+
+  rewind (0);
+  return true;
+}
+
+float
+CradLoader::getrefresh ()
+{
+  if (tempo)
+    return (float) (tempo);
+  else
+    return 18.2f;
+}
diff --git a/src/adplug/core/rad.cxx b/src/adplug/core/rad.cxx
deleted file mode 100644
index d02d0f07c95e..000000000000
--- a/src/adplug/core/rad.cxx
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * rad.cpp - RAD Loader by Simon Peter <dn.tlp at gmx.net>
- *
- * BUGS:
- * some volumes are dropped out
- */
-
-#include <string.h>
-
-#include "rad.h"
-
-CPlayer *
-CradLoader::factory (Copl * newopl)
-{
-  return new CradLoader (newopl);
-}
-
-bool
-CradLoader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  if (!f)
-    return false;
-  char id[16];
-  unsigned char buf, ch, c, b, inp;
-  char bufstr[2] = "\0";
-  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 };
-
-  // 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;
-  }
-
-  // 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, " ");
-      else
-      {
-        *bufstr = buf;
-        strcat (desc, bufstr);
-      }
-  }
-  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);
-  }
-  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);
-
-  // convert replay data
-  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)
-        tracks[i][j].note -= 4 * (tracks[i][j].note >> 4);
-      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;
-
-  rewind (0);
-  return true;
-}
-
-float
-CradLoader::getrefresh ()
-{
-  if (tempo)
-    return (float) (tempo);
-  else
-    return 18.2f;
-}
diff --git a/src/adplug/core/rad.h b/src/adplug/core/rad.h
index 6bf8ac76f099..693bb33629b2 100644
--- a/src/adplug/core/rad.h
+++ b/src/adplug/core/rad.h
@@ -30,7 +30,7 @@ public:
 		: CmodPlayer(newopl)
 	{ *desc = '\0'; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	float getrefresh();
 
 	std::string gettype()
diff --git a/src/adplug/core/rat.cc b/src/adplug/core/rat.cc
new file mode 100644
index 000000000000..ee26b20031b2
--- /dev/null
+++ b/src/adplug/core/rat.cc
@@ -0,0 +1,311 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * [xad] RAT player, by Riven the Mage <riven at ok.ru>
+ */
+
+/*
+    - discovery -
+
+  file(s) : PINA.EXE
+     type : Experimental Connection BBStro tune
+     tune : by (?)Ratt/GRIF
+   player : by (?)Ratt/GRIF
+  comment : there are bug in original replayer's adlib_init(): wrong frequency registers.
+*/
+
+#include <string.h>
+
+#include "rat.h"
+#include "debug.h"
+
+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
+};
+
+CPlayer *
+CxadratPlayer::factory (Copl * newopl)
+{
+  return new CxadratPlayer (newopl);
+}
+
+bool
+CxadratPlayer::xadplayer_load ()
+{
+  if (xad.fmt != RAT)
+    return false;
+
+  // load header
+  memcpy (&rat.hdr, &tune[0], sizeof (rat_header));
+
+  // is 'RAT'-signed ?
+  if (strncmp (rat.hdr.id, "RAT", 3))
+    return false;
+
+  // is version 1.0 ?
+  if (rat.hdr.version != 0x10)
+    return false;
+
+  // load order
+  rat.order = &tune[0x40];
+
+  // load instruments
+  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++)
+      {
+        memcpy (&rat.tracks[i][j][k], event_ptr, sizeof (rat_event));
+
+        event_ptr += sizeof (rat_event);
+      }
+
+  return true;
+}
+
+void
+CxadratPlayer::xadplayer_rewind (int subsong)
+{
+  int i;
+
+  rat.order_pos = rat.hdr.order_start;
+  rat.pattern_pos = 0;
+  rat.volume = rat.hdr.volume;
+
+  plr.speed = rat.hdr.speed;
+
+  // clear channel data
+  memset (&rat.channel, 0, sizeof (rat.channel[0]) * 9);
+
+  // init OPL
+  opl_write (0x01, 0x20);
+  opl_write (0x08, 0x00);
+  opl_write (0xBD, 0x00);
+
+  // set default frequencies
+  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);
+  }
+
+  // set default volumes
+  for (i = 0; i < 0x1F; i++)
+    opl_write (0x40 + i, 0x3F);
+}
+
+void
+CxadratPlayer::xadplayer_update ()
+{
+  int i;
+
+  rat_event event;
+
+  // process events
+  for (i = 0; i < rat.hdr.numchan; i++)
+  {
+    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);
+#endif
+
+    // is instrument ?
+    if (event.instrument != 0xFF)
+    {
+      rat.channel[i].instrument = event.instrument - 1;
+      rat.channel[i].volume = rat.inst[event.instrument - 1].volume;
+    }
+
+    // is volume ?
+    if (event.volume != 0xFF)
+      rat.channel[i].volume = event.volume;
+
+    // is note ?
+    if (event.note != 0xFF)
+    {
+      // mute channel
+      opl_write (0xB0 + i, 0x00);
+      opl_write (0xA0 + i, 0x00);
+
+      // if note != 0xFE then play
+      if (event.note != 0xFE)
+      {
+        unsigned char ins = rat.channel[i].instrument;
+
+        // synthesis/feedback
+        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);
+
+        // 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));
+
+        // 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);
+
+        // 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);
+
+        // 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);
+
+        // octave/frequency
+        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);
+      }
+    }
+
+    // is effect ?
+    if (event.fx != 0xFF)
+    {
+      rat.channel[i].fx = event.fx;
+      rat.channel[i].fxp = event.fxp;
+    }
+  }
+
+  // next row
+  rat.pattern_pos++;
+
+  // process effects
+  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;
+    }
+
+    rat.channel[i].fx = 0;
+  }
+
+  // end of pattern ?
+  if (rat.pattern_pos >= 0x40)
+  {
+    rat.pattern_pos = 0;
+
+    rat.order_pos++;
+
+    // end of module ?
+    if (rat.order_pos == rat.hdr.order_end)
+    {
+      rat.order_pos = rat.hdr.order_loop;
+
+      plr.looping = 1;
+    }
+  }
+}
+
+float
+CxadratPlayer::xadplayer_getrefresh ()
+{
+  return 60.0f;
+}
+
+std::string CxadratPlayer::xadplayer_gettype ()
+{
+  return (std::string ("xad: rat player"));
+}
+
+std::string CxadratPlayer::xadplayer_gettitle ()
+{
+  return (std::string (rat.hdr.title, 32));
+}
+
+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)
+{
+#ifdef DEBUG
+  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 & 0xC0;
+
+  return vol;
+}
diff --git a/src/adplug/core/rat.cxx b/src/adplug/core/rat.cxx
deleted file mode 100644
index ee26b20031b2..000000000000
--- a/src/adplug/core/rat.cxx
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * [xad] RAT player, by Riven the Mage <riven at ok.ru>
- */
-
-/*
-    - discovery -
-
-  file(s) : PINA.EXE
-     type : Experimental Connection BBStro tune
-     tune : by (?)Ratt/GRIF
-   player : by (?)Ratt/GRIF
-  comment : there are bug in original replayer's adlib_init(): wrong frequency registers.
-*/
-
-#include <string.h>
-
-#include "rat.h"
-#include "debug.h"
-
-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
-};
-
-CPlayer *
-CxadratPlayer::factory (Copl * newopl)
-{
-  return new CxadratPlayer (newopl);
-}
-
-bool
-CxadratPlayer::xadplayer_load ()
-{
-  if (xad.fmt != RAT)
-    return false;
-
-  // load header
-  memcpy (&rat.hdr, &tune[0], sizeof (rat_header));
-
-  // is 'RAT'-signed ?
-  if (strncmp (rat.hdr.id, "RAT", 3))
-    return false;
-
-  // is version 1.0 ?
-  if (rat.hdr.version != 0x10)
-    return false;
-
-  // load order
-  rat.order = &tune[0x40];
-
-  // load instruments
-  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++)
-      {
-        memcpy (&rat.tracks[i][j][k], event_ptr, sizeof (rat_event));
-
-        event_ptr += sizeof (rat_event);
-      }
-
-  return true;
-}
-
-void
-CxadratPlayer::xadplayer_rewind (int subsong)
-{
-  int i;
-
-  rat.order_pos = rat.hdr.order_start;
-  rat.pattern_pos = 0;
-  rat.volume = rat.hdr.volume;
-
-  plr.speed = rat.hdr.speed;
-
-  // clear channel data
-  memset (&rat.channel, 0, sizeof (rat.channel[0]) * 9);
-
-  // init OPL
-  opl_write (0x01, 0x20);
-  opl_write (0x08, 0x00);
-  opl_write (0xBD, 0x00);
-
-  // set default frequencies
-  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);
-  }
-
-  // set default volumes
-  for (i = 0; i < 0x1F; i++)
-    opl_write (0x40 + i, 0x3F);
-}
-
-void
-CxadratPlayer::xadplayer_update ()
-{
-  int i;
-
-  rat_event event;
-
-  // process events
-  for (i = 0; i < rat.hdr.numchan; i++)
-  {
-    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);
-#endif
-
-    // is instrument ?
-    if (event.instrument != 0xFF)
-    {
-      rat.channel[i].instrument = event.instrument - 1;
-      rat.channel[i].volume = rat.inst[event.instrument - 1].volume;
-    }
-
-    // is volume ?
-    if (event.volume != 0xFF)
-      rat.channel[i].volume = event.volume;
-
-    // is note ?
-    if (event.note != 0xFF)
-    {
-      // mute channel
-      opl_write (0xB0 + i, 0x00);
-      opl_write (0xA0 + i, 0x00);
-
-      // if note != 0xFE then play
-      if (event.note != 0xFE)
-      {
-        unsigned char ins = rat.channel[i].instrument;
-
-        // synthesis/feedback
-        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);
-
-        // 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));
-
-        // 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);
-
-        // 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);
-
-        // 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);
-
-        // octave/frequency
-        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);
-      }
-    }
-
-    // is effect ?
-    if (event.fx != 0xFF)
-    {
-      rat.channel[i].fx = event.fx;
-      rat.channel[i].fxp = event.fxp;
-    }
-  }
-
-  // next row
-  rat.pattern_pos++;
-
-  // process effects
-  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;
-    }
-
-    rat.channel[i].fx = 0;
-  }
-
-  // end of pattern ?
-  if (rat.pattern_pos >= 0x40)
-  {
-    rat.pattern_pos = 0;
-
-    rat.order_pos++;
-
-    // end of module ?
-    if (rat.order_pos == rat.hdr.order_end)
-    {
-      rat.order_pos = rat.hdr.order_loop;
-
-      plr.looping = 1;
-    }
-  }
-}
-
-float
-CxadratPlayer::xadplayer_getrefresh ()
-{
-  return 60.0f;
-}
-
-std::string CxadratPlayer::xadplayer_gettype ()
-{
-  return (std::string ("xad: rat player"));
-}
-
-std::string CxadratPlayer::xadplayer_gettitle ()
-{
-  return (std::string (rat.hdr.title, 32));
-}
-
-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)
-{
-#ifdef DEBUG
-  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 & 0xC0;
-
-  return vol;
-}
diff --git a/src/adplug/core/raw.cc b/src/adplug/core/raw.cc
new file mode 100644
index 000000000000..4dfc8f3645b2
--- /dev/null
+++ b/src/adplug/core/raw.cc
@@ -0,0 +1,129 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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
+ *
+ * raw.c - RAW Player by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "raw.h"
+
+/*** public methods *************************************/
+
+CPlayer *
+CrawPlayer::factory (Copl * newopl)
+{
+  return new CrawPlayer (newopl);
+}
+
+bool
+CrawPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+  }
+
+  // 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);
+  }
+
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+bool
+CrawPlayer::update ()
+{
+  bool setspeed;
+
+  if (pos >= length)
+    return false;
+
+  if (del)
+  {
+    del--;
+    return !songend;
+  }
+
+  do
+  {
+    setspeed = false;
+    switch (data[pos].command)
+    {
+    case 0:
+      del = data[pos].param - 1;
+      break;
+    case 2:
+      if (!data[pos].param)
+      {
+        pos++;
+        speed = data[pos].param + (data[pos].command << 8);
+        setspeed = true;
+      }
+      else
+        opl->setchip (data[pos].param - 1);
+      break;
+    case 0xff:
+      if (data[pos].param == 0xff)
+      {
+        rewind (0);             // auto-rewind song
+        songend = true;
+        return !songend;
+      }
+      break;
+    default:
+      opl->write (data[pos].command, data[pos].param);
+      break;
+    }
+  } while (data[pos++].command || setspeed);
+
+  return !songend;
+}
+
+void
+CrawPlayer::rewind (int subsong)
+{
+  pos = del = 0;
+  speed = clock;
+  songend = false;
+  opl->init ();
+  opl->write (1, 32);           // go to 9 channel mode
+}
+
+float
+CrawPlayer::getrefresh ()
+{
+  return 1193180.0 / (speed ? speed : 0xffff);  // timer oscillator speed / wait register = clock frequency
+}
diff --git a/src/adplug/core/raw.cxx b/src/adplug/core/raw.cxx
deleted file mode 100644
index fe0a3dcc4103..000000000000
--- a/src/adplug/core/raw.cxx
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp at 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
- *
- * raw.c - RAW Player by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "raw.h"
-
-/*** public methods *************************************/
-
-CPlayer *
-CrawPlayer::factory (Copl * newopl)
-{
-  return new CrawPlayer (newopl);
-}
-
-bool
-CrawPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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;
-  }
-
-  // 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);
-  }
-
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-bool
-CrawPlayer::update ()
-{
-  bool setspeed;
-
-  if (pos >= length)
-    return false;
-
-  if (del)
-  {
-    del--;
-    return !songend;
-  }
-
-  do
-  {
-    setspeed = false;
-    switch (data[pos].command)
-    {
-    case 0:
-      del = data[pos].param - 1;
-      break;
-    case 2:
-      if (!data[pos].param)
-      {
-        pos++;
-        speed = data[pos].param + (data[pos].command << 8);
-        setspeed = true;
-      }
-      else
-        opl->setchip (data[pos].param - 1);
-      break;
-    case 0xff:
-      if (data[pos].param == 0xff)
-      {
-        rewind (0);             // auto-rewind song
-        songend = true;
-        return !songend;
-      }
-      break;
-    default:
-      opl->write (data[pos].command, data[pos].param);
-      break;
-    }
-  } while (data[pos++].command || setspeed);
-
-  return !songend;
-}
-
-void
-CrawPlayer::rewind (int subsong)
-{
-  pos = del = 0;
-  speed = clock;
-  songend = false;
-  opl->init ();
-  opl->write (1, 32);           // go to 9 channel mode
-}
-
-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 b3920015b16a..113b84378c08 100644
--- a/src/adplug/core/raw.h
+++ b/src/adplug/core/raw.h
@@ -32,7 +32,7 @@ public:
 	~CrawPlayer()
 	{ if(data) delete [] data; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh();
diff --git a/src/adplug/core/rix.cc b/src/adplug/core/rix.cc
new file mode 100644
index 000000000000..7ac365e74bf4
--- /dev/null
+++ b/src/adplug/core/rix.cc
@@ -0,0 +1,611 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * rix.cpp - Softstar RIX OPL Format Player by palxex <palxex.ys168.com>
+ *                                             BSPAL <BSPAL.ys168.com>
+ */
+
+#include <cstdlib>
+#include <string.h>
+
+#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;
+
+/*** public methods *************************************/
+
+CPlayer *
+CrixPlayer::factory (Copl * newopl)
+{
+  return new CrixPlayer (newopl);
+}
+
+CrixPlayer::CrixPlayer (Copl * newopl):CPlayer (newopl), flag_mkf (0), file_buffer (0),
+buf_addr (0)
+{
+}
+
+CrixPlayer::~CrixPlayer ()
+{
+  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 ());
+
+  if (str_has_suffix_nocase (filename.c_str (), ".mkf"))
+  {
+    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);
+  return true;
+}
+
+bool
+CrixPlayer::update ()
+{
+  int_08h_entry ();
+  return !play_end;
+}
+
+void
+CrixPlayer::rewind (int subsong)
+{
+  I = 0;
+  T = 0;
+  mus_block = 0;
+  ins_block = 0;
+  rhythm = 0;
+  music_on = 0;
+  pause_flag = 0;
+  band = 0;
+  band_low = 0;
+  e0_reg_flag = 0;
+  bd_modify = 0;
+  sustain = 0;
+  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)
+  {
+    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 ();
+}
+
+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;
+}
+
+float
+CrixPlayer::getrefresh ()
+{
+  return 70.0f;
+}
+
+/*------------------Implemention----------------------------*/
+inline void
+CrixPlayer::set_new_int ()
+{
+//   if(!ad_initial()) exit(1);
+  ad_initial ();
+}
+
+/*----------------------------------------------------------*/
+inline void
+CrixPlayer::Pause ()
+{
+  unsigned short i;
+  pause_flag = 1;
+  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)
+{
+//   unsigned short i = p2+a0b0_data2[index];
+  a0b0_data4[index] = p3;
+  a0b0_data3[index] = p2;
+}
+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);
+  }
+  bd_modify = 0;
+  //    ad_bd_reg();
+  band = 0;
+  music_on = 1;
+}
+
+/*----------------------------------------------------------*/
+inline unsigned short
+CrixPlayer::ad_initial ()
+{
+  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);
+  }
+  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();
+}
+
+/*----------------------------------------------------------*/
+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);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::int_08h_entry ()
+{
+  unsigned short band_sus = 1;
+  while (band_sus)
+  {
+    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;
+    }
+  }
+}
+
+/*--------------------------------------------------------------*/
+inline unsigned short
+CrixPlayer::rix_proc ()
+{
+  unsigned char ctrl = 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)
+    {
+    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;
+  }
+  music_ctrl ();
+  I = mus_block + 1;
+  band = 0;
+  music_on = 1;
+  return 0;
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::rix_get_ins ()
+{
+  int i;
+  unsigned char *baddr = (&buf_addr[ins_block]) + (band_low << 6);
+
+  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)
+{
+  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;
+  }
+}
+
+/*--------------------------------------------------------------*/
+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;
+}
+
+/*--------------------------------------------------------------*/
+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)
+    {
+      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;
+  displace[index] = low;
+}
+
+/*--------------------------------------------------------------*/
+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];
+  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);
+}
+
+/*--------------------------------------------------------------*/
+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];
+  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);
+}
+
+/*--------------------------------------------------------------*/
+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;
+  }
+  else
+  {
+    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;
+  }
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::switch_ad_bd (unsigned short index)
+{
+
+  if (rhythm == 0 || index < 6)
+    ad_a0b0l_reg (index, a0b0_data3[index], 0);
+  else
+  {
+    bd_modify &= (~bd_reg_data[index]), ad_bd_reg ();
+  }
+}
+
+/*--------------------------------------------------------------*/
+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);
+}
+
+/*--------------------------------------------------------------*/
+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);
+}
+
+/*--------------------------------------------------------------*/
+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);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::ad_80_reg (unsigned short index)
+{
+  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);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::ad_60_reg (unsigned short index)
+{
+  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);
+}
+
+/*--------------------------------------------------------------*/
+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);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::ad_40_reg (unsigned short index)
+{
+  unsigned int res = 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);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::ad_bd_reg ()
+{
+  unsigned short data = rhythm < 1 ? 0 : 0x20;
+  data |= bd_modify;
+  ad_bop (0xBD, data);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::ad_a0b0_reg (unsigned short index)
+{
+  ad_bop (0xA0 + index, 0);
+  ad_bop (0xB0 + index, 0);
+}
+
+/*--------------------------------------------------------------*/
+inline void
+CrixPlayer::music_ctrl ()
+{
+  int i;
+  for (i = 0; i < 11; i++)
+    switch_ad_bd (i);
+}
diff --git a/src/adplug/core/rix.cxx b/src/adplug/core/rix.cxx
deleted file mode 100644
index ccafac592826..000000000000
--- a/src/adplug/core/rix.cxx
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * rix.cpp - Softstar RIX OPL Format Player by palxex <palxex.ys168.com>
- *                                             BSPAL <BSPAL.ys168.com>
- */
-
-#include <cstdlib>
-#include <string.h>
-
-#include <glib.h>
-
-#include "rix.h"
-#include "debug.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;
-
-/*** public methods *************************************/
-
-CPlayer *
-CrixPlayer::factory (Copl * newopl)
-{
-  return new CrixPlayer (newopl);
-}
-
-CrixPlayer::CrixPlayer (Copl * newopl):CPlayer (newopl), flag_mkf (0), file_buffer (0),
-buf_addr (0)
-{
-}
-
-CrixPlayer::~CrixPlayer ()
-{
-  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 (vfs_get_filename (fd));
-
-  if (g_ascii_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);
-  }
-  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 ()
-{
-  int_08h_entry ();
-  return !play_end;
-}
-
-void
-CrixPlayer::rewind (int subsong)
-{
-  I = 0;
-  T = 0;
-  mus_block = 0;
-  ins_block = 0;
-  rhythm = 0;
-  music_on = 0;
-  pause_flag = 0;
-  band = 0;
-  band_low = 0;
-  e0_reg_flag = 0;
-  bd_modify = 0;
-  sustain = 0;
-  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)
-  {
-    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 ();
-}
-
-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;
-}
-
-float
-CrixPlayer::getrefresh ()
-{
-  return 70.0f;
-}
-
-/*------------------Implemention----------------------------*/
-inline void
-CrixPlayer::set_new_int ()
-{
-//   if(!ad_initial()) exit(1);
-  ad_initial ();
-}
-
-/*----------------------------------------------------------*/
-inline void
-CrixPlayer::Pause ()
-{
-  register unsigned short i;
-  pause_flag = 1;
-  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)
-{
-//   unsigned short i = p2+a0b0_data2[index];
-  a0b0_data4[index] = p3;
-  a0b0_data3[index] = p2;
-}
-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);
-  }
-  bd_modify = 0;
-  //    ad_bd_reg();
-  band = 0;
-  music_on = 1;
-}
-
-/*----------------------------------------------------------*/
-inline unsigned short
-CrixPlayer::ad_initial ()
-{
-  register 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);
-  }
-  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();
-}
-
-/*----------------------------------------------------------*/
-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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::int_08h_entry ()
-{
-  unsigned short band_sus = 1;
-  while (band_sus)
-  {
-    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;
-    }
-  }
-}
-
-/*--------------------------------------------------------------*/
-inline unsigned short
-CrixPlayer::rix_proc ()
-{
-  unsigned char ctrl = 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)
-    {
-    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;
-  }
-  music_ctrl ();
-  I = mus_block + 1;
-  band = 0;
-  music_on = 1;
-  return 0;
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::rix_get_ins ()
-{
-  int i;
-  unsigned char *baddr = (&buf_addr[ins_block]) + (band_low << 6);
-
-  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)
-{
-  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;
-  }
-}
-
-/*--------------------------------------------------------------*/
-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;
-}
-
-/*--------------------------------------------------------------*/
-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)
-    {
-      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;
-  displace[index] = low;
-}
-
-/*--------------------------------------------------------------*/
-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];
-  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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::rix_B0_pro (unsigned short ctrl_l, unsigned short index)
-{
-  register int temp = 0;
-  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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::rix_C0_pro (unsigned short ctrl_l, unsigned short index)
-{
-  register 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);
-      }
-    }
-    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)
-{
-
-  if (rhythm == 0 || index < 6)
-    ad_a0b0l_reg (index, a0b0_data3[index], 0);
-  else
-  {
-    bd_modify &= (~bd_reg_data[index]), ad_bd_reg ();
-  }
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ins_to_reg (unsigned short index, unsigned short *insb,
-                        unsigned short value)
-{
-  register 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);
-}
-
-/*--------------------------------------------------------------*/
-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);
-}
-
-/*--------------------------------------------------------------*/
-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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ad_80_reg (unsigned short index)
-{
-  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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ad_60_reg (unsigned short index)
-{
-  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);
-}
-
-/*--------------------------------------------------------------*/
-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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ad_40_reg (unsigned short index)
-{
-  unsigned int res = 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);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ad_bd_reg ()
-{
-  unsigned short data = rhythm < 1 ? 0 : 0x20;
-  data |= bd_modify;
-  ad_bop (0xBD, data);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::ad_a0b0_reg (unsigned short index)
-{
-  ad_bop (0xA0 + index, 0);
-  ad_bop (0xB0 + index, 0);
-}
-
-/*--------------------------------------------------------------*/
-inline void
-CrixPlayer::music_ctrl ()
-{
-  register int 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 1e349226cdb5..5c83ac4cb101 100644
--- a/src/adplug/core/rix.h
+++ b/src/adplug/core/rix.h
@@ -30,7 +30,7 @@ class CrixPlayer: public CPlayer
   CrixPlayer(Copl *newopl);
   ~CrixPlayer();
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong);
   float getrefresh();
diff --git a/src/adplug/core/rol.cc b/src/adplug/core/rol.cc
new file mode 100644
index 000000000000..a910218acc45
--- /dev/null
+++ b/src/adplug/core/rol.cc
@@ -0,0 +1,747 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * rol.h - ROL Player by OPLx <oplx at yahoo.com>
+ *
+ * Visit:  http://tenacity.hispeed.com/aomit/oplx/
+ */
+#include <algorithm>
+#include <string.h>
+
+#include "rol.h"
+#include "debug.h"
+
+int   const CrolPlayer::kSizeofDataRecord    =  30;
+int   const CrolPlayer::kMaxTickBeat         =  60;
+int   const CrolPlayer::kSilenceNote         = -12;
+int   const CrolPlayer::kNumMelodicVoices    =  9;
+int   const CrolPlayer::kNumPercussiveVoices = 11;
+int   const CrolPlayer::kBassDrumChannel     =  6;
+int   const CrolPlayer::kSnareDrumChannel    =  7;
+int   const CrolPlayer::kTomtomChannel       =  8;
+int   const CrolPlayer::kTomtomFreq          =  2;//4;
+int   const CrolPlayer::kSnareDrumFreq       =  2;//kTomtomFreq + 7;
+float const CrolPlayer::kDefaultUpdateTme    = 18.2f;
+float const CrolPlayer::kPitchFactor         = 400.0f;
+
+static const unsigned char drum_table[4] = {0x14, 0x12, 0x15, 0x11};
+
+CrolPlayer::uint16 const CrolPlayer::kNoteTable[12] =
+{
+    340, // C
+    363, // C#
+    385, // D
+    408, // D#
+    432, // E
+    458, // F
+    485, // F#
+    514, // G
+    544, // G#
+    577, // A
+    611, // A#
+    647  // B
+};
+
+/*** public methods **************************************/
+
+CPlayer *CrolPlayer::factory(Copl *newopl)
+{
+  return new CrolPlayer(newopl);
+}
+//---------------------------------------------------------
+CrolPlayer::CrolPlayer(Copl *newopl)
+:  CPlayer         ( newopl )
+  ,rol_header      ( nullptr )
+  ,mNextTempoEvent ( 0 )
+  ,mCurrTick       ( 0 )
+  ,mTimeOfLastNote ( 0 )
+  ,mRefresh        ( kDefaultUpdateTme )
+  ,bdRegister      ( 0 )
+{
+    int n;
+
+    memset(bxRegister,  0, sizeof(bxRegister) );
+    memset(volumeCache, 0, sizeof(volumeCache) );
+    memset(freqCache,   0, sizeof(freqCache) );
+
+    for(n=0; n<11; n++)
+      pitchCache[n]=1.0f;
+}
+//---------------------------------------------------------
+CrolPlayer::~CrolPlayer()
+{
+    if(rol_header)
+    {
+        delete rol_header;
+        rol_header = 0;
+    }
+}
+//---------------------------------------------------------
+bool CrolPlayer::load(VFSFile &fd, const CFileProvider &fp)
+{
+    binistream *f = fp.open(fd); if(!f) return false;
+    std::string filename(fd.filename ());
+
+    char *fn = new char[filename.length()+12];
+    int i;
+    std::string bnk_filename;
+
+    AdPlug_LogWrite("*** CrolPlayer::load(f, \"%s\") ***\n", filename.c_str());
+    strcpy(fn,filename.data());
+    for (i=strlen(fn)-1; i>=0; i--)
+      if (fn[i] == '/' || fn[i] == '\\')
+	break;
+    strcpy(fn+i+1,"standard.bnk");
+    bnk_filename = fn;
+    delete [] fn; fn = 0;
+    AdPlug_LogWrite("bnk_filename = \"%s\"\n",bnk_filename.c_str());
+
+    rol_header = new SRolHeader;
+    memset( rol_header, 0, sizeof(SRolHeader) );
+
+    rol_header->version_major = f->readInt( 2 );
+    rol_header->version_minor = f->readInt( 2 );
+
+    // 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);
+      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+      fp.close(f);
+      return false;
+    }
+
+    f->seek( 40, binio::Add );
+
+    rol_header->ticks_per_beat    = f->readInt( 2 );
+    rol_header->beats_per_measure = f->readInt( 2 );
+    rol_header->edit_scale_y      = f->readInt( 2 );
+    rol_header->edit_scale_x      = f->readInt( 2 );
+
+    f->seek( 1, binio::Add );
+
+    rol_header->mode = f->readInt(1);
+
+    f->seek( 90+38+15, binio::Add );
+
+    rol_header->basic_tempo = f->readFloat( binio::Single );
+
+    load_tempo_events( f );
+
+    mTimeOfLastNote = 0;
+
+    if( load_voice_data( f, bnk_filename, fp ) != true )
+    {
+      AdPlug_LogWrite("CrolPlayer::load_voice_data(f) failed!\n");
+      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+
+      fp.close( f );
+      return false;
+    }
+
+    fp.close( f );
+
+    rewind( 0 );
+    AdPlug_LogWrite("--- CrolPlayer::load ---\n");
+    return true;
+}
+//---------------------------------------------------------
+bool CrolPlayer::update()
+{
+    if( mNextTempoEvent < mTempoEvents.size() &&
+        mTempoEvents[mNextTempoEvent].time == mCurrTick )
+    {
+        SetRefresh( mTempoEvents[mNextTempoEvent].multiplier );
+        ++mNextTempoEvent;
+    }
+
+    TVoiceData::iterator curr = voice_data.begin();
+    TVoiceData::iterator end  = voice_data.end();
+    int voice                 = 0;
+
+    while( curr != end )
+    {
+        UpdateVoice( voice, *curr );
+        ++curr;
+        ++voice;
+    }
+
+    ++mCurrTick;
+
+    if( mCurrTick > mTimeOfLastNote )
+    {
+        return false;
+    }
+
+    return true;
+    //return ( mCurrTick > mTimeOfLastNote ) ? false : true;
+}
+//---------------------------------------------------------
+void CrolPlayer::rewind( int subsong )
+{
+    TVoiceData::iterator curr = voice_data.begin();
+    TVoiceData::iterator end  = voice_data.end();
+
+    while( curr != end )
+    {
+        CVoiceData &voice = *curr;
+
+        voice.Reset();
+        ++curr;
+    }
+
+    memset(bxRegister,  0, sizeof(bxRegister) );
+    memset(volumeCache, 0, sizeof(volumeCache) );
+
+    bdRegister = 0;
+
+    opl->init();        // initialize to melodic by default
+    opl->write(1,0x20); // Enable waveform select (bit 5)
+
+    if( rol_header->mode == 0 )
+    {
+        opl->write( 0xbd, 0x20 ); // select rhythm mode (bit 5)
+        bdRegister = 0x20;
+
+        SetFreq( kTomtomChannel,    24 );
+        SetFreq( kSnareDrumChannel, 31 );
+    }
+
+    mNextTempoEvent = 0;
+    mCurrTick       = 0;
+
+    SetRefresh(1.0f);
+}
+//---------------------------------------------------------
+inline float fmin( int const a, int const b )
+{
+    return static_cast<float>( a < b ? a : b );
+}
+//---------------------------------------------------------
+void CrolPlayer::SetRefresh( float const multiplier )
+{
+    float const tickBeat = fmin(kMaxTickBeat, rol_header->ticks_per_beat);
+
+    mRefresh =  (tickBeat*rol_header->basic_tempo*multiplier) / 60.0f;
+}
+//---------------------------------------------------------
+float CrolPlayer::getrefresh()
+{
+    return mRefresh;
+}
+//---------------------------------------------------------
+void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData )
+{
+    TNoteEvents const &nEvents = voiceData.note_events;
+
+    if( nEvents.empty() || voiceData.mEventStatus & CVoiceData::kES_NoteEnd )
+    {
+        return; // no note data to process, don't bother doing anything.
+    }
+
+    TInstrumentEvents  &iEvents = voiceData.instrument_events;
+    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 )
+    {
+        if( voiceData.next_instrument_event < iEvents.size() )
+        {
+            send_ins_data_to_chip( voice, iEvents[voiceData.next_instrument_event].ins_index );
+            ++voiceData.next_instrument_event;
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_InstrEnd;
+        }
+    }
+
+    if (vEvents.empty()) {
+        return;  // prevent out-of-bounds access
+    }
+    if( !(voiceData.mEventStatus & CVoiceData::kES_VolumeEnd ) &&
+        vEvents[voiceData.next_volume_event].time == mCurrTick )
+    {
+      SVolumeEvent const &volumeEvent = vEvents[voiceData.next_volume_event];
+
+        if(  voiceData.next_volume_event < vEvents.size() )
+        {
+            int const volume = (int)(63.0f*(1.0f - volumeEvent.multiplier));
+
+            SetVolume( voice, volume );
+
+            ++voiceData.next_volume_event; // move to next volume event
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_VolumeEnd;
+        }
+    }
+
+    if( voiceData.mForceNote || voiceData.current_note_duration > voiceData.mNoteDuration-1 )
+    {
+        if( mCurrTick != 0 )
+        {
+            ++voiceData.current_note;
+        }
+
+        if( voiceData.current_note < nEvents.size() )
+        {
+            SNoteEvent const &noteEvent = nEvents[voiceData.current_note];
+
+            SetNote( voice, noteEvent.number );
+            voiceData.current_note_duration = 0;
+            voiceData.mNoteDuration         = noteEvent.duration;
+            voiceData.mForceNote            = false;
+        }
+        else
+        {
+            SetNote( voice, kSilenceNote );
+            voiceData.mEventStatus |= CVoiceData::kES_NoteEnd;
+            return;
+        }
+    }
+
+    if (pEvents.empty()) {
+        return;  // prevent out-of-bounds access
+    }
+    if( !(voiceData.mEventStatus & CVoiceData::kES_PitchEnd ) &&
+        pEvents[voiceData.next_pitch_event].time == mCurrTick )
+    {
+        if( voiceData.next_pitch_event < pEvents.size() )
+        {
+            SetPitch(voice,pEvents[voiceData.next_pitch_event].variation);
+            ++voiceData.next_pitch_event;
+        }
+        else
+        {
+            voiceData.mEventStatus |= CVoiceData::kES_PitchEnd;
+        }
+    }
+
+    ++voiceData.current_note_duration;
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNote( int const voice, int const note )
+{
+    if( voice < kBassDrumChannel || rol_header->mode )
+    {
+        SetNoteMelodic( voice, note );
+    }
+    else
+    {
+        SetNotePercussive( voice, note );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNotePercussive( int const voice, int const note )
+{
+    int const bit_pos = 4-voice+kBassDrumChannel;
+
+    bdRegister &= ~( 1<<bit_pos );
+    opl->write( 0xbd, bdRegister );
+
+    if( note != kSilenceNote )
+    {
+        switch( voice )
+        {
+            case kTomtomChannel:
+                SetFreq( kSnareDrumChannel, note+7 );
+            case kBassDrumChannel:
+                SetFreq( voice, note );
+                break;
+        }
+
+        bdRegister |= 1<<bit_pos;
+        opl->write( 0xbd, bdRegister );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetNoteMelodic( int const voice, int const note )
+{
+    opl->write( 0xb0+voice, bxRegister[voice] & ~0x20 );
+
+    if( note != kSilenceNote )
+    {
+        SetFreq( voice, note, true );
+    }
+}
+//---------------------------------------------------------
+void CrolPlayer::SetPitch(int const voice, real32 const variation)
+{
+  pitchCache[voice] = variation;
+  freqCache[voice] += (uint16)((((float)freqCache[voice])*(variation-1.0f)) / kPitchFactor);
+
+  opl->write(0xa0+voice,freqCache[voice] & 0xff);
+}
+//---------------------------------------------------------
+void CrolPlayer::SetFreq( int const voice, int const note, bool const keyOn )
+{
+    uint16 freq = kNoteTable[note%12] + ((note/12) << 10);
+    freq += (uint16)((((float)freq)*(pitchCache[voice]-1.0f))/kPitchFactor);
+
+    freqCache[voice] = freq;
+    bxRegister[voice] = ((freq >> 8) & 0x1f);
+
+    opl->write( 0xa0+voice, freq & 0xff );
+    opl->write( 0xb0+voice, bxRegister[voice] | (keyOn ? 0x20 : 0x0) );
+}
+//---------------------------------------------------------
+void CrolPlayer::SetVolume( int const voice, int const volume )
+{
+    volumeCache[voice] = (volumeCache[voice] &0xc0) | volume;
+
+    int const op_offset = ( voice < kSnareDrumChannel || rol_header->mode ) ?
+                          op_table[voice]+3 : drum_table[voice-kSnareDrumChannel];
+
+    opl->write( 0x40+op_offset, volumeCache[voice] );
+}
+//---------------------------------------------------------
+void CrolPlayer::send_ins_data_to_chip( int const voice, int const ins_index )
+{
+    SRolInstrument &instrument = ins_list[ins_index].instrument;
+
+    send_operator( voice, instrument.modulator, instrument.carrier );
+}
+//---------------------------------------------------------
+void CrolPlayer::send_operator( int const voice, SOPL2Op const &modulator,  SOPL2Op const &carrier )
+{
+    if( voice < kSnareDrumChannel || rol_header->mode )
+    {
+        int const op_offset = op_table[voice];
+
+        opl->write( 0x20+op_offset, modulator.ammulti  );
+        opl->write( 0x40+op_offset, modulator.ksltl    );
+        opl->write( 0x60+op_offset, modulator.ardr     );
+        opl->write( 0x80+op_offset, modulator.slrr     );
+        opl->write( 0xc0+voice    , modulator.fbc      );
+        opl->write( 0xe0+op_offset, modulator.waveform );
+
+        volumeCache[voice] = (carrier.ksltl & 0xc0) | (volumeCache[voice] & 0x3f);
+
+        opl->write( 0x23+op_offset, carrier.ammulti  );
+        opl->write( 0x43+op_offset, volumeCache[voice]    );
+        opl->write( 0x63+op_offset, carrier.ardr     );
+        opl->write( 0x83+op_offset, carrier.slrr     );
+//        opl->write( 0xc3+voice    , carrier.fbc      ); <- don't bother writing this.
+        opl->write( 0xe3+op_offset, carrier.waveform );
+    }
+    else
+    {
+        int const op_offset = drum_table[voice-kSnareDrumChannel];
+
+        volumeCache[voice] = (modulator.ksltl & 0xc0) | (volumeCache[voice] & 0x3f);
+
+        opl->write( 0x20+op_offset, modulator.ammulti  );
+        opl->write( 0x40+op_offset, volumeCache[voice]      );
+        opl->write( 0x60+op_offset, modulator.ardr     );
+        opl->write( 0x80+op_offset, modulator.slrr     );
+        opl->write( 0xc0+voice    , modulator.fbc      );
+        opl->write( 0xe0+op_offset, modulator.waveform );
+    }
+}
+//---------------------------------------------------------
+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)
+    {
+        STempoEvent event;
+
+        event.time       = f->readInt( 2 );
+        event.multiplier = f->readFloat( binio::Single );
+        mTempoEvents.push_back( event );
+    }
+}
+//---------------------------------------------------------
+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);
+
+    if( bnk_file )
+    {
+        load_bnk_info( bnk_file, bnk_header );
+
+        int const numVoices = rol_header->mode ? kNumMelodicVoices : kNumPercussiveVoices;
+
+        voice_data.reserve( numVoices );
+        for(int i=0; i<numVoices; ++i)
+        {
+            CVoiceData voice;
+
+            load_note_events( f, voice );
+            load_instrument_events( f, voice, bnk_file, bnk_header );
+            load_volume_events( f, voice );
+            load_pitch_events( f, voice );
+
+            voice_data.push_back( voice );
+        }
+
+        fp.close(bnk_file);
+
+        return true;
+    }
+
+    return false;
+}
+//---------------------------------------------------------
+void CrolPlayer::load_note_events( binistream *f, CVoiceData &voice )
+{
+    f->seek( 15, binio::Add );
+
+    int16 const time_of_last_note = f->readInt( 2 );
+
+    if( time_of_last_note != 0 )
+    {
+        TNoteEvents &note_events = voice.note_events;
+        int16 total_duration     = 0;
+
+        do
+        {
+            SNoteEvent event;
+
+            event.number   = f->readInt( 2 );
+            event.duration = f->readInt( 2 );
+
+            event.number += kSilenceNote; // adding -12
+
+            note_events.push_back( event );
+
+            total_duration += event.duration;
+        } while( total_duration < time_of_last_note );
+
+        if( time_of_last_note > mTimeOfLastNote )
+        {
+            mTimeOfLastNote = time_of_last_note;
+        }
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+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;
+
+    instrument_events.reserve( number_of_instrument_events );
+
+    for(int i=0; i<number_of_instrument_events; ++i)
+    {
+        SInstrumentEvent event;
+        event.time = f->readInt( 2 );
+        f->readString( event.name, 9 );
+
+	    std::string event_name = event.name;
+        event.ins_index = load_rol_instrument( bnk_file, bnk_header, event_name );
+
+        instrument_events.push_back( event );
+
+        f->seek( 1+2, binio::Add );
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+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;
+
+    volume_events.reserve( number_of_volume_events );
+
+    for(int i=0; i<number_of_volume_events; ++i)
+    {
+        SVolumeEvent event;
+        event.time       = f->readInt( 2 );
+        event.multiplier = f->readFloat( binio::Single );
+
+        volume_events.push_back( event );
+    }
+
+    f->seek( 15, binio::Add );
+}
+//---------------------------------------------------------
+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;
+
+    pitch_events.reserve( number_of_pitch_events );
+
+    for(int i=0; i<number_of_pitch_events; ++i)
+    {
+        SPitchEvent event;
+        event.time      = f->readInt( 2 );
+        event.variation = f->readFloat( binio::Single );
+
+        pitch_events.push_back( event );
+    }
+}
+//---------------------------------------------------------
+bool CrolPlayer::load_bnk_info( binistream *f, SBnkHeader &header )
+{
+  header.version_major = f->readInt(1);
+  header.version_minor = f->readInt(1);
+  f->readString( header.signature, 6 );
+
+  header.number_of_list_entries_used  = f->readInt( 2 );
+  header.total_number_of_list_entries = f->readInt( 2 );
+
+  header.abs_offset_of_name_list = f->readInt( 4 );
+  header.abs_offset_of_data      = f->readInt( 4 );
+
+  f->seek( header.abs_offset_of_name_list, binio::Set );
+
+  TInstrumentNames &ins_name_list = header.ins_name_list;
+  ins_name_list.reserve( header.number_of_list_entries_used );
+
+  for(int i=0; i<header.number_of_list_entries_used; ++i)
+    {
+      SInstrumentName instrument;
+
+      instrument.index = f->readInt( 2 );
+      instrument.record_used = f->readInt(1);
+      f->readString( instrument.name, 9 );
+
+      // printf("%s = #%d\n", instrument.name, i );
+
+      ins_name_list.push_back( instrument );
+    }
+
+  //std::sort( ins_name_list.begin(), ins_name_list.end(), StringCompare() );
+
+  return true;
+}
+//---------------------------------------------------------
+int CrolPlayer::load_rol_instrument( binistream *f, SBnkHeader const &header, std::string &name )
+{
+    TInstrumentNames const &ins_name_list = header.ins_name_list;
+
+    int const ins_index = get_ins_index( name );
+
+    if( ins_index != -1 )
+    {
+        return ins_index;
+    }
+
+    typedef TInstrumentNames::const_iterator TInsIter;
+    typedef std::pair<TInsIter, TInsIter>    TInsIterPair;
+
+    TInsIterPair range = std::equal_range( ins_name_list.begin(),
+                                           ins_name_list.end(),
+                                           name,
+                                           StringCompare() );
+
+    if( range.first != range.second )
+    {
+        int const seekOffs = header.abs_offset_of_data + (range.first->index*kSizeofDataRecord);
+        f->seek( seekOffs, binio::Set );
+    }
+
+    SUsedList usedIns;
+    usedIns.name = name;
+
+    if( range.first != range.second )
+    {
+        read_rol_instrument( f, usedIns.instrument );
+    }
+    else
+    {
+        // set up default instrument data here
+        memset( &usedIns.instrument, 0, sizeof(usedIns.instrument) );
+    }
+    ins_list.push_back( usedIns );
+
+    return ins_list.size()-1;
+}
+//---------------------------------------------------------
+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 )
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+//---------------------------------------------------------
+void CrolPlayer::read_rol_instrument( binistream *f, SRolInstrument &ins )
+{
+  ins.mode = f->readInt(1);
+  ins.voice_number = f->readInt(1);
+
+  read_fm_operator( f, ins.modulator );
+  read_fm_operator( f, ins.carrier );
+
+  ins.modulator.waveform = f->readInt(1);
+  ins.carrier.waveform = f->readInt(1);
+}
+//---------------------------------------------------------
+void CrolPlayer::read_fm_operator( binistream *f, SOPL2Op &opl2_op )
+{
+  SFMOperator fm_op;
+
+  fm_op.key_scale_level = f->readInt(1);
+  fm_op.freq_multiplier = f->readInt(1);
+  fm_op.feed_back = f->readInt(1);
+  fm_op.attack_rate = f->readInt(1);
+  fm_op.sustain_level = f->readInt(1);
+  fm_op.sustaining_sound = f->readInt(1);
+  fm_op.decay_rate = f->readInt(1);
+  fm_op.release_rate = f->readInt(1);
+  fm_op.output_level = f->readInt(1);
+  fm_op.amplitude_vibrato = f->readInt(1);
+  fm_op.frequency_vibrato = f->readInt(1);
+  fm_op.envelope_scaling = f->readInt(1);
+  fm_op.fm_type = f->readInt(1);
+
+  opl2_op.ammulti = fm_op.amplitude_vibrato << 7 | fm_op.frequency_vibrato << 6 | fm_op.sustaining_sound << 5 | fm_op.envelope_scaling << 4 | fm_op.freq_multiplier;
+  opl2_op.ksltl   = fm_op.key_scale_level   << 6 | fm_op.output_level;
+  opl2_op.ardr    = fm_op.attack_rate       << 4 | fm_op.decay_rate;
+  opl2_op.slrr    = fm_op.sustain_level     << 4 | fm_op.release_rate;
+  opl2_op.fbc     = fm_op.feed_back         << 1 | (fm_op.fm_type ^ 1);
+}
diff --git a/src/adplug/core/rol.cxx b/src/adplug/core/rol.cxx
deleted file mode 100644
index c7d06746f14c..000000000000
--- a/src/adplug/core/rol.cxx
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * rol.h - ROL Player by OPLx <oplx at yahoo.com>
- *
- * Visit:  http://tenacity.hispeed.com/aomit/oplx/
- */
-#include <algorithm>
-#include <string.h>
-
-#include <glib.h>
-
-#include "rol.h"
-#include "debug.h"
-
-int   const CrolPlayer::kSizeofDataRecord    =  30;
-int   const CrolPlayer::kMaxTickBeat         =  60;
-int   const CrolPlayer::kSilenceNote         = -12;
-int   const CrolPlayer::kNumMelodicVoices    =  9;
-int   const CrolPlayer::kNumPercussiveVoices = 11;
-int   const CrolPlayer::kBassDrumChannel     =  6;
-int   const CrolPlayer::kSnareDrumChannel    =  7;
-int   const CrolPlayer::kTomtomChannel       =  8;
-int   const CrolPlayer::kTomtomFreq          =  2;//4;
-int   const CrolPlayer::kSnareDrumFreq       =  2;//kTomtomFreq + 7;
-float const CrolPlayer::kDefaultUpdateTme    = 18.2f;
-float const CrolPlayer::kPitchFactor         = 400.0f;
-
-static const unsigned char drum_table[4] = {0x14, 0x12, 0x15, 0x11};
-
-CrolPlayer::uint16 const CrolPlayer::kNoteTable[12] =
-{
-    340, // C
-    363, // C#
-    385, // D
-    408, // D#
-    432, // E
-    458, // F
-    485, // F#
-    514, // G
-    544, // G#
-    577, // A
-    611, // A#
-    647  // B
-};
-
-/*** public methods **************************************/
-
-CPlayer *CrolPlayer::factory(Copl *newopl)
-{
-  return new CrolPlayer(newopl);
-}
-//---------------------------------------------------------
-CrolPlayer::CrolPlayer(Copl *newopl)
-:  CPlayer         ( newopl )
-  ,rol_header      ( NULL )
-  ,mNextTempoEvent ( 0 )
-  ,mCurrTick       ( 0 )
-  ,mTimeOfLastNote ( 0 )
-  ,mRefresh        ( kDefaultUpdateTme )
-  ,bdRegister      ( 0 )
-{
-    int n;
-
-    memset(bxRegister,  0, sizeof(bxRegister) );
-    memset(volumeCache, 0, sizeof(volumeCache) );
-    memset(freqCache,   0, sizeof(freqCache) );
-
-    for(n=0; n<11; n++)
-      pitchCache[n]=1.0f;
-}
-//---------------------------------------------------------
-CrolPlayer::~CrolPlayer()
-{
-    if(rol_header)
-    {
-        delete rol_header;
-        rol_header = 0;
-    }
-}
-//---------------------------------------------------------
-bool CrolPlayer::load(VFSFile *fd, const CFileProvider &fp)
-{
-    binistream *f = fp.open(fd); if(!f) return false;
-    std::string filename(vfs_get_filename (fd));
-
-    char *fn = new char[filename.length()+12];
-    int i;
-    std::string bnk_filename;
-
-    AdPlug_LogWrite("*** CrolPlayer::load(f, \"%s\") ***\n", filename.c_str());
-    strcpy(fn,filename.data());
-    for (i=strlen(fn)-1; i>=0; i--)
-      if (fn[i] == '/' || fn[i] == '\\')
-	break;
-    strcpy(fn+i+1,"standard.bnk");
-    bnk_filename = fn;
-    delete [] fn; fn = 0;
-    AdPlug_LogWrite("bnk_filename = \"%s\"\n",bnk_filename.c_str());
-
-    rol_header = new SRolHeader;
-    memset( rol_header, 0, sizeof(SRolHeader) );
-
-    rol_header->version_major = f->readInt( 2 );
-    rol_header->version_minor = f->readInt( 2 );
-
-    // 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);
-      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
-      fp.close(f);
-      return false;
-    }
-
-    f->seek( 40, binio::Add );
-
-    rol_header->ticks_per_beat    = f->readInt( 2 );
-    rol_header->beats_per_measure = f->readInt( 2 );
-    rol_header->edit_scale_y      = f->readInt( 2 );
-    rol_header->edit_scale_x      = f->readInt( 2 );
-
-    f->seek( 1, binio::Add );
-
-    rol_header->mode = f->readInt(1);
-
-    f->seek( 90+38+15, binio::Add );
-
-    rol_header->basic_tempo = f->readFloat( binio::Single );
-
-    load_tempo_events( f );
-
-    mTimeOfLastNote = 0;
-
-    if( load_voice_data( f, bnk_filename, fp ) != true )
-    {
-      AdPlug_LogWrite("CrolPlayer::load_voice_data(f) failed!\n");
-      AdPlug_LogWrite("--- CrolPlayer::load ---\n");
-
-      fp.close( f );
-      return false;
-    }
-
-    fp.close( f );
-
-    rewind( 0 );
-    AdPlug_LogWrite("--- CrolPlayer::load ---\n");
-    return true;
-}
-//---------------------------------------------------------
-bool CrolPlayer::update()
-{
-    if( mNextTempoEvent < mTempoEvents.size() &&
-        mTempoEvents[mNextTempoEvent].time == mCurrTick )
-    {
-        SetRefresh( mTempoEvents[mNextTempoEvent].multiplier );
-        ++mNextTempoEvent;
-    }
-
-    TVoiceData::iterator curr = voice_data.begin();
-    TVoiceData::iterator end  = voice_data.end();
-    int voice                 = 0;
-
-    while( curr != end )
-    {
-        UpdateVoice( voice, *curr );
-        ++curr;
-        ++voice;
-    }
-
-    ++mCurrTick;
-
-    if( mCurrTick > mTimeOfLastNote )
-    {
-        return false;
-    }
-
-    return true;
-    //return ( mCurrTick > mTimeOfLastNote ) ? false : true;
-}
-//---------------------------------------------------------
-void CrolPlayer::rewind( int subsong )
-{
-    TVoiceData::iterator curr = voice_data.begin();
-    TVoiceData::iterator end  = voice_data.end();
-
-    while( curr != end )
-    {
-        CVoiceData &voice = *curr;
-
-        voice.Reset();
-        ++curr;
-    }
-
-    memset(bxRegister,  0, sizeof(bxRegister) );
-    memset(volumeCache, 0, sizeof(volumeCache) );
-
-    bdRegister = 0;
-
-    opl->init();        // initialize to melodic by default
-    opl->write(1,0x20); // Enable waveform select (bit 5)
-
-    if( rol_header->mode == 0 )
-    {
-        opl->write( 0xbd, 0x20 ); // select rhythm mode (bit 5)
-        bdRegister = 0x20;
-
-        SetFreq( kTomtomChannel,    24 );
-        SetFreq( kSnareDrumChannel, 31 );
-    }
-
-    mNextTempoEvent = 0;
-    mCurrTick       = 0;
-
-    SetRefresh(1.0f);
-}
-//---------------------------------------------------------
-inline float fmin( int const a, int const b )
-{
-    return static_cast<float>( a < b ? a : b );
-}
-//---------------------------------------------------------
-void CrolPlayer::SetRefresh( float const multiplier )
-{
-    float const tickBeat = fmin(kMaxTickBeat, rol_header->ticks_per_beat);
-
-    mRefresh =  (tickBeat*rol_header->basic_tempo*multiplier) / 60.0f;
-}
-//---------------------------------------------------------
-float CrolPlayer::getrefresh()
-{
-    return mRefresh;
-}
-//---------------------------------------------------------
-void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData )
-{
-    TNoteEvents const &nEvents = voiceData.note_events;
-
-    if( nEvents.empty() || voiceData.mEventStatus & CVoiceData::kES_NoteEnd )
-    {
-        return; // no note data to process, don't bother doing anything.
-    }
-
-    TInstrumentEvents  &iEvents = voiceData.instrument_events;
-    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 )
-    {
-        if( voiceData.next_instrument_event < iEvents.size() )
-        {
-            send_ins_data_to_chip( voice, iEvents[voiceData.next_instrument_event].ins_index );
-            ++voiceData.next_instrument_event;
-        }
-        else
-        {
-            voiceData.mEventStatus |= CVoiceData::kES_InstrEnd;
-        }
-    }
-
-    if (vEvents.empty()) {
-        return;  // prevent out-of-bounds access
-    }
-    if( !(voiceData.mEventStatus & CVoiceData::kES_VolumeEnd ) &&
-        vEvents[voiceData.next_volume_event].time == mCurrTick )
-    {
-      SVolumeEvent const &volumeEvent = vEvents[voiceData.next_volume_event];
-
-        if(  voiceData.next_volume_event < vEvents.size() )
-        {
-            int const volume = (int)(63.0f*(1.0f - volumeEvent.multiplier));
-
-            SetVolume( voice, volume );
-
-            ++voiceData.next_volume_event; // move to next volume event
-        }
-        else
-        {
-            voiceData.mEventStatus |= CVoiceData::kES_VolumeEnd;
-        }
-    }
-
-    if( voiceData.mForceNote || voiceData.current_note_duration > voiceData.mNoteDuration-1 )
-    {
-        if( mCurrTick != 0 )
-        {
-            ++voiceData.current_note;
-        }
-
-        if( voiceData.current_note < nEvents.size() )
-        {
-            SNoteEvent const &noteEvent = nEvents[voiceData.current_note];
-
-            SetNote( voice, noteEvent.number );
-            voiceData.current_note_duration = 0;
-            voiceData.mNoteDuration         = noteEvent.duration;
-            voiceData.mForceNote            = false;
-        }
-        else
-        {
-            SetNote( voice, kSilenceNote );
-            voiceData.mEventStatus |= CVoiceData::kES_NoteEnd;
-            return;
-        }
-    }
-
-    if (pEvents.empty()) {
-        return;  // prevent out-of-bounds access
-    }
-    if( !(voiceData.mEventStatus & CVoiceData::kES_PitchEnd ) &&
-        pEvents[voiceData.next_pitch_event].time == mCurrTick )
-    {
-        if( voiceData.next_pitch_event < pEvents.size() )
-        {
-            SetPitch(voice,pEvents[voiceData.next_pitch_event].variation);
-            ++voiceData.next_pitch_event;
-        }
-        else
-        {
-            voiceData.mEventStatus |= CVoiceData::kES_PitchEnd;
-        }
-    }
-
-    ++voiceData.current_note_duration;
-}
-//---------------------------------------------------------
-void CrolPlayer::SetNote( int const voice, int const note )
-{
-    if( voice < kBassDrumChannel || rol_header->mode )
-    {
-        SetNoteMelodic( voice, note );
-    }
-    else
-    {
-        SetNotePercussive( voice, note );
-    }
-}
-//---------------------------------------------------------
-void CrolPlayer::SetNotePercussive( int const voice, int const note )
-{
-    int const bit_pos = 4-voice+kBassDrumChannel;
-
-    bdRegister &= ~( 1<<bit_pos );
-    opl->write( 0xbd, bdRegister );
-
-    if( note != kSilenceNote )
-    {
-        switch( voice )
-        {
-            case kTomtomChannel:
-                SetFreq( kSnareDrumChannel, note+7 );
-            case kBassDrumChannel:
-                SetFreq( voice, note );
-                break;
-        }
-
-        bdRegister |= 1<<bit_pos;
-        opl->write( 0xbd, bdRegister );
-    }
-}
-//---------------------------------------------------------
-void CrolPlayer::SetNoteMelodic( int const voice, int const note )
-{
-    opl->write( 0xb0+voice, bxRegister[voice] & ~0x20 );
-
-    if( note != kSilenceNote )
-    {
-        SetFreq( voice, note, true );
-    }
-}
-//---------------------------------------------------------
-void CrolPlayer::SetPitch(int const voice, real32 const variation)
-{
-  pitchCache[voice] = variation;
-  freqCache[voice] += (uint16)((((float)freqCache[voice])*(variation-1.0f)) / kPitchFactor);
-
-  opl->write(0xa0+voice,freqCache[voice] & 0xff);
-}
-//---------------------------------------------------------
-void CrolPlayer::SetFreq( int const voice, int const note, bool const keyOn )
-{
-    uint16 freq = kNoteTable[note%12] + ((note/12) << 10);
-    freq += (uint16)((((float)freq)*(pitchCache[voice]-1.0f))/kPitchFactor);
-
-    freqCache[voice] = freq;
-    bxRegister[voice] = ((freq >> 8) & 0x1f);
-
-    opl->write( 0xa0+voice, freq & 0xff );
-    opl->write( 0xb0+voice, bxRegister[voice] | (keyOn ? 0x20 : 0x0) );
-}
-//---------------------------------------------------------
-void CrolPlayer::SetVolume( int const voice, int const volume )
-{
-    volumeCache[voice] = (volumeCache[voice] &0xc0) | volume;
-
-    int const op_offset = ( voice < kSnareDrumChannel || rol_header->mode ) ?
-                          op_table[voice]+3 : drum_table[voice-kSnareDrumChannel];
-
-    opl->write( 0x40+op_offset, volumeCache[voice] );
-}
-//---------------------------------------------------------
-void CrolPlayer::send_ins_data_to_chip( int const voice, int const ins_index )
-{
-    SRolInstrument &instrument = ins_list[ins_index].instrument;
-
-    send_operator( voice, instrument.modulator, instrument.carrier );
-}
-//---------------------------------------------------------
-void CrolPlayer::send_operator( int const voice, SOPL2Op const &modulator,  SOPL2Op const &carrier )
-{
-    if( voice < kSnareDrumChannel || rol_header->mode )
-    {
-        int const op_offset = op_table[voice];
-
-        opl->write( 0x20+op_offset, modulator.ammulti  );
-        opl->write( 0x40+op_offset, modulator.ksltl    );
-        opl->write( 0x60+op_offset, modulator.ardr     );
-        opl->write( 0x80+op_offset, modulator.slrr     );
-        opl->write( 0xc0+voice    , modulator.fbc      );
-        opl->write( 0xe0+op_offset, modulator.waveform );
-
-        volumeCache[voice] = (carrier.ksltl & 0xc0) | (volumeCache[voice] & 0x3f);
-
-        opl->write( 0x23+op_offset, carrier.ammulti  );
-        opl->write( 0x43+op_offset, volumeCache[voice]    );
-        opl->write( 0x63+op_offset, carrier.ardr     );
-        opl->write( 0x83+op_offset, carrier.slrr     );
-//        opl->write( 0xc3+voice    , carrier.fbc      ); <- don't bother writing this.
-        opl->write( 0xe3+op_offset, carrier.waveform );
-    }
-    else
-    {
-        int const op_offset = drum_table[voice-kSnareDrumChannel];
-
-        volumeCache[voice] = (modulator.ksltl & 0xc0) | (volumeCache[voice] & 0x3f);
-
-        opl->write( 0x20+op_offset, modulator.ammulti  );
-        opl->write( 0x40+op_offset, volumeCache[voice]      );
-        opl->write( 0x60+op_offset, modulator.ardr     );
-        opl->write( 0x80+op_offset, modulator.slrr     );
-        opl->write( 0xc0+voice    , modulator.fbc      );
-        opl->write( 0xe0+op_offset, modulator.waveform );
-    }
-}
-//---------------------------------------------------------
-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)
-    {
-        STempoEvent event;
-
-        event.time       = f->readInt( 2 );
-        event.multiplier = f->readFloat( binio::Single );
-        mTempoEvents.push_back( event );
-    }
-}
-//---------------------------------------------------------
-bool CrolPlayer::load_voice_data( binistream *f, std::string const &bnk_filename, const CFileProvider &fp )
-{
-    SBnkHeader bnk_header;
-    VFSFile *fd = vfs_fopen(bnk_filename.c_str(), "rb");
-    binistream *bnk_file = fp.open(fd);
-
-    if( bnk_file )
-    {
-        load_bnk_info( bnk_file, bnk_header );
-
-        int const numVoices = rol_header->mode ? kNumMelodicVoices : kNumPercussiveVoices;
-
-        voice_data.reserve( numVoices );
-        for(int i=0; i<numVoices; ++i)
-        {
-            CVoiceData voice;
-
-            load_note_events( f, voice );
-            load_instrument_events( f, voice, bnk_file, bnk_header );
-            load_volume_events( f, voice );
-            load_pitch_events( f, voice );
-
-            voice_data.push_back( voice );
-        }
-
-        fp.close(bnk_file);
-        vfs_fclose(fd);
-
-        return true;
-    }
-
-    return false;
-}
-//---------------------------------------------------------
-void CrolPlayer::load_note_events( binistream *f, CVoiceData &voice )
-{
-    f->seek( 15, binio::Add );
-
-    int16 const time_of_last_note = f->readInt( 2 );
-
-    if( time_of_last_note != 0 )
-    {
-        TNoteEvents &note_events = voice.note_events;
-        int16 total_duration     = 0;
-
-        do
-        {
-            SNoteEvent event;
-
-            event.number   = f->readInt( 2 );
-            event.duration = f->readInt( 2 );
-
-            event.number += kSilenceNote; // adding -12
-
-            note_events.push_back( event );
-
-            total_duration += event.duration;
-        } while( total_duration < time_of_last_note );
-
-        if( time_of_last_note > mTimeOfLastNote )
-        {
-            mTimeOfLastNote = time_of_last_note;
-        }
-    }
-
-    f->seek( 15, binio::Add );
-}
-//---------------------------------------------------------
-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;
-
-    instrument_events.reserve( number_of_instrument_events );
-
-    for(int i=0; i<number_of_instrument_events; ++i)
-    {
-        SInstrumentEvent event;
-        event.time = f->readInt( 2 );
-        f->readString( event.name, 9 );
-
-	    std::string event_name = event.name;
-        event.ins_index = load_rol_instrument( bnk_file, bnk_header, event_name );
-
-        instrument_events.push_back( event );
-
-        f->seek( 1+2, binio::Add );
-    }
-
-    f->seek( 15, binio::Add );
-}
-//---------------------------------------------------------
-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;
-
-    volume_events.reserve( number_of_volume_events );
-
-    for(int i=0; i<number_of_volume_events; ++i)
-    {
-        SVolumeEvent event;
-        event.time       = f->readInt( 2 );
-        event.multiplier = f->readFloat( binio::Single );
-
-        volume_events.push_back( event );
-    }
-
-    f->seek( 15, binio::Add );
-}
-//---------------------------------------------------------
-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;
-
-    pitch_events.reserve( number_of_pitch_events );
-
-    for(int i=0; i<number_of_pitch_events; ++i)
-    {
-        SPitchEvent event;
-        event.time      = f->readInt( 2 );
-        event.variation = f->readFloat( binio::Single );
-
-        pitch_events.push_back( event );
-    }
-}
-//---------------------------------------------------------
-bool CrolPlayer::load_bnk_info( binistream *f, SBnkHeader &header )
-{
-  header.version_major = f->readInt(1);
-  header.version_minor = f->readInt(1);
-  f->readString( header.signature, 6 );
-
-  header.number_of_list_entries_used  = f->readInt( 2 );
-  header.total_number_of_list_entries = f->readInt( 2 );
-
-  header.abs_offset_of_name_list = f->readInt( 4 );
-  header.abs_offset_of_data      = f->readInt( 4 );
-
-  f->seek( header.abs_offset_of_name_list, binio::Set );
-
-  TInstrumentNames &ins_name_list = header.ins_name_list;
-  ins_name_list.reserve( header.number_of_list_entries_used );
-
-  for(int i=0; i<header.number_of_list_entries_used; ++i)
-    {
-      SInstrumentName instrument;
-
-      instrument.index = f->readInt( 2 );
-      instrument.record_used = f->readInt(1);
-      f->readString( instrument.name, 9 );
-
-      // printf("%s = #%d\n", instrument.name, i );
-
-      ins_name_list.push_back( instrument );
-    }
-
-  //std::sort( ins_name_list.begin(), ins_name_list.end(), StringCompare() );
-
-  return true;
-}
-//---------------------------------------------------------
-int CrolPlayer::load_rol_instrument( binistream *f, SBnkHeader const &header, std::string &name )
-{
-    TInstrumentNames const &ins_name_list = header.ins_name_list;
-
-    int const ins_index = get_ins_index( name );
-
-    if( ins_index != -1 )
-    {
-        return ins_index;
-    }
-
-    typedef TInstrumentNames::const_iterator TInsIter;
-    typedef std::pair<TInsIter, TInsIter>    TInsIterPair;
-
-    TInsIterPair range = std::equal_range( ins_name_list.begin(),
-                                           ins_name_list.end(),
-                                           name,
-                                           StringCompare() );
-
-    if( range.first != range.second )
-    {
-        int const seekOffs = header.abs_offset_of_data + (range.first->index*kSizeofDataRecord);
-        f->seek( seekOffs, binio::Set );
-    }
-
-    SUsedList usedIns;
-    usedIns.name = name;
-
-    if( range.first != range.second )
-    {
-        read_rol_instrument( f, usedIns.instrument );
-    }
-    else
-    {
-        // set up default instrument data here
-        memset( &usedIns.instrument, 0, sizeof(usedIns.instrument) );
-    }
-    ins_list.push_back( usedIns );
-
-    return ins_list.size()-1;
-}
-//---------------------------------------------------------
-int CrolPlayer::get_ins_index( std::string const &name ) const
-{
-    for(unsigned int i=0; i<ins_list.size(); ++i)
-    {
-        if( g_ascii_strcasecmp(ins_list[i].name.c_str(), name.c_str()) == 0 )
-        {
-            return i;
-        }
-    }
-
-    return -1;
-}
-//---------------------------------------------------------
-void CrolPlayer::read_rol_instrument( binistream *f, SRolInstrument &ins )
-{
-  ins.mode = f->readInt(1);
-  ins.voice_number = f->readInt(1);
-
-  read_fm_operator( f, ins.modulator );
-  read_fm_operator( f, ins.carrier );
-
-  ins.modulator.waveform = f->readInt(1);
-  ins.carrier.waveform = f->readInt(1);
-}
-//---------------------------------------------------------
-void CrolPlayer::read_fm_operator( binistream *f, SOPL2Op &opl2_op )
-{
-  SFMOperator fm_op;
-
-  fm_op.key_scale_level = f->readInt(1);
-  fm_op.freq_multiplier = f->readInt(1);
-  fm_op.feed_back = f->readInt(1);
-  fm_op.attack_rate = f->readInt(1);
-  fm_op.sustain_level = f->readInt(1);
-  fm_op.sustaining_sound = f->readInt(1);
-  fm_op.decay_rate = f->readInt(1);
-  fm_op.release_rate = f->readInt(1);
-  fm_op.output_level = f->readInt(1);
-  fm_op.amplitude_vibrato = f->readInt(1);
-  fm_op.frequency_vibrato = f->readInt(1);
-  fm_op.envelope_scaling = f->readInt(1);
-  fm_op.fm_type = f->readInt(1);
-
-  opl2_op.ammulti = fm_op.amplitude_vibrato << 7 | fm_op.frequency_vibrato << 6 | fm_op.sustaining_sound << 5 | fm_op.envelope_scaling << 4 | fm_op.freq_multiplier;
-  opl2_op.ksltl   = fm_op.key_scale_level   << 6 | fm_op.output_level;
-  opl2_op.ardr    = fm_op.attack_rate       << 4 | fm_op.decay_rate;
-  opl2_op.slrr    = fm_op.sustain_level     << 4 | fm_op.release_rate;
-  opl2_op.fbc     = fm_op.feed_back         << 1 | (fm_op.fm_type ^ 1);
-}
diff --git a/src/adplug/core/rol.h b/src/adplug/core/rol.h
index 6b3b7d4c5052..510efeea5e80 100644
--- a/src/adplug/core/rol.h
+++ b/src/adplug/core/rol.h
@@ -26,10 +26,10 @@
 #include <vector>
 #include <string>
 
-#include <glib.h>
-
 #include "player.h"
 
+#include <libaudcore/audstrings.h>
+
 class CrolPlayer: public CPlayer
 {
 public:
@@ -39,7 +39,7 @@ public:
 
     ~CrolPlayer();
 
-    bool  load      (VFSFile *fd, const CFileProvider &fp);
+    bool  load      (VFSFile &fd, const CFileProvider &fp);
     bool  update    ();
     void  rewind    (int subsong);	// rewinds to specified subsong
     float getrefresh();			// returns needed timer refresh rate
@@ -271,7 +271,7 @@ private:
     private:
         bool keyLess( const char *const lhs, const char *const rhs ) const
         {
-            return g_ascii_strcasecmp(lhs, rhs) < 0;
+            return strcmp_nocase(lhs, rhs) < 0;
         }
     };
 
diff --git a/src/adplug/core/s3m.cc b/src/adplug/core/s3m.cc
new file mode 100644
index 000000000000..b8cc94c5e408
--- /dev/null
+++ b/src/adplug/core/s3m.cc
@@ -0,0 +1,728 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * s3m.c - S3M Player by Simon Peter <dn.tlp at gmx.net>
+ *
+ * BUGS:
+ * Extra Fine Slides (EEx, FEx) & Fine Vibrato (Uxy) are inaccurate
+ */
+
+#include <string.h>
+
+#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 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 };
+
+/*** public methods *************************************/
+
+CPlayer *
+Cs3mPlayer::factory (Copl * newopl)
+{
+  return new Cs3mPlayer (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++)
+      {
+        pattern[i][j][k].instrument = 0;
+        pattern[i][j][k].info = 0;
+      }
+}
+
+bool
+Cs3mPlayer::load (VFSFile & fd, 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;
+
+  // 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;
+      }
+    }
+    delete checkhead;
+    if (!adlibins)
+    {
+      fp.close (f);
+      return false;
+    }
+  }
+
+  // load section
+  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);
+    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.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);
+        }
+        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);
+  }
+
+  fp.close (f);
+  rewind (0);
+  return true;                  // done
+}
+
+bool
+Cs3mPlayer::update ()
+{
+  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)
+    {
+    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;
+      }
+      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);
+      break;
+    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);
+      }
+      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
+      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++;
+        }
+        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++;
+        }
+        break;
+      }
+      if (channel[realchan].trigger < 2)
+        channel[realchan].trigger++;
+      else
+        channel[realchan].trigger = 0;
+      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
+    }
+  }
+
+  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
+    ord = 0;
+    pattnr = orders[ord];
+    if (pattnr == 0xff)
+      return !songend;
+  }
+  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
+      realchan = chnresolv[header.chanset[chan] & 127];
+    else
+      realchan = -1;            // channel disabled
+    if (realchan != -1)
+    {                           // channel playable?
+      // set channel values
+      donote = 0;
+      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];
+          channel[realchan].nextoct = pattern[pattnr][row][chan].oct;
+        }
+        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;
+          channel[realchan].key = 1;
+          donote = 1;
+        }
+      }
+      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);
+      }
+      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))
+        {
+          channel[realchan].freq = channel[realchan].nextfreq;
+          channel[realchan].oct = channel[realchan].nextoct;
+          setfreq (realchan);
+        }
+      if (pattern[pattnr][row][chan].instrument)
+      {                         // set instrument
+        channel[realchan].inst = pattern[pattnr][row][chan].instrument - 1;
+        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)
+          donote = 1;
+      }
+      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].info = pattern[pattnr][row][chan].info;
+
+      // some commands reset the infobyte memory
+      switch (channel[realchan].fx)
+      {
+      case 1:
+      case 2:
+      case 3:
+      case 20:
+        channel[realchan].info = pattern[pattnr][row][chan].info;
+        break;
+      }
+
+      // play note
+      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;
+        }
+        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);
+        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);
+        }
+        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);
+        }
+        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;
+        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)
+          {
+            loopcnt = info & 0x0f;
+            crow = loopstart;
+            pattbreak = 1;
+          }
+          else if (--loopcnt > 0)
+          {
+            crow = loopstart;
+            pattbreak = 1;
+          }
+        }
+        if ((info & 0xf0) == 0xe0)  // patterndelay
+          del = speed * (info & 0x0f) - 1;
+        break;
+      case 20:
+        tempo = info;
+        break;                  // set tempo
+      }
+    }
+  }
+
+  if (!del)
+    del = speed - 1;            // speed compensation
+  if (!pattbreak)
+  {                             // next row (only if no manual advance)
+    crow++;
+    if (crow > 63)
+    {
+      crow = 0;
+      ord++;
+      loopstart = 0;
+    }
+  }
+
+  return !songend;              // still playing
+}
+
+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
+}
+
+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.??");
+  }
+
+  return (std::string ("Scream Tracker ") + filever);
+}
+
+float
+Cs3mPlayer::getrefresh ()
+{
+  return (float) (tempo / 2.5);
+}
+
+/*** private methods *************************************/
+
+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);
+}
+
+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));
+}
+
+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);
+  else
+    opl->write (0xb0 + chan,
+                ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
+}
+
+void
+Cs3mPlayer::playnote (unsigned char chan)
+{
+  unsigned char op = op_table[chan], insnr = channel[chan].inst;
+
+  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);
+
+  // set frequency & play
+  channel[chan].key = 1;
+  setfreq (chan);
+}
+
+void
+Cs3mPlayer::slide_down (unsigned char chan, unsigned char amount)
+{
+  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;
+}
+
+void
+Cs3mPlayer::slide_up (unsigned char chan, unsigned char amount)
+{
+  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;
+}
+
+void
+Cs3mPlayer::vibrato (unsigned char chan, unsigned char info)
+{
+  unsigned char i, speed, depth;
+
+  speed = info >> 4;
+  depth = (info & 0x0f) / 2;
+
+  for (i = 0; i < speed; i++)
+  {
+    channel[chan].trigger++;
+    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)));
+  }
+  setfreq (chan);
+}
+
+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);
+}
diff --git a/src/adplug/core/s3m.cxx b/src/adplug/core/s3m.cxx
deleted file mode 100644
index 141383a4ef3d..000000000000
--- a/src/adplug/core/s3m.cxx
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * s3m.c - S3M Player by Simon Peter <dn.tlp at gmx.net>
- *
- * BUGS:
- * Extra Fine Slides (EEx, FEx) & Fine Vibrato (Uxy) are inaccurate
- */
-
-#include <string.h>
-
-#include "s3m.h"
-
-const 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 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)
-{
-  return new Cs3mPlayer (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++)
-      {
-        pattern[i][j][k].instrument = 0;
-        pattern[i][j][k].info = 0;
-      }
-}
-
-bool
-Cs3mPlayer::load (VFSFile * fd, 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;
-
-  // 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;
-      }
-    }
-    delete checkhead;
-    if (!adlibins)
-    {
-      fp.close (f);
-      return false;
-    }
-  }
-
-  // load section
-  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);
-    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.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);
-        }
-        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);
-  }
-
-  fp.close (f);
-  rewind (0);
-  return true;                  // done
-}
-
-bool
-Cs3mPlayer::update ()
-{
-  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)
-    {
-    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;
-      }
-      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);
-      break;
-    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);
-      }
-      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
-      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++;
-        }
-        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++;
-        }
-        break;
-      }
-      if (channel[realchan].trigger < 2)
-        channel[realchan].trigger++;
-      else
-        channel[realchan].trigger = 0;
-      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
-    }
-  }
-
-  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
-    ord = 0;
-    pattnr = orders[ord];
-    if (pattnr == 0xff)
-      return !songend;
-  }
-  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
-      realchan = chnresolv[header.chanset[chan] & 127];
-    else
-      realchan = -1;            // channel disabled
-    if (realchan != -1)
-    {                           // channel playable?
-      // set channel values
-      donote = 0;
-      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];
-          channel[realchan].nextoct = pattern[pattnr][row][chan].oct;
-        }
-        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;
-          channel[realchan].key = 1;
-          donote = 1;
-        }
-      }
-      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);
-      }
-      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))
-        {
-          channel[realchan].freq = channel[realchan].nextfreq;
-          channel[realchan].oct = channel[realchan].nextoct;
-          setfreq (realchan);
-        }
-      if (pattern[pattnr][row][chan].instrument)
-      {                         // set instrument
-        channel[realchan].inst = pattern[pattnr][row][chan].instrument - 1;
-        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)
-          donote = 1;
-      }
-      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].info = pattern[pattnr][row][chan].info;
-
-      // some commands reset the infobyte memory
-      switch (channel[realchan].fx)
-      {
-      case 1:
-      case 2:
-      case 3:
-      case 20:
-        channel[realchan].info = pattern[pattnr][row][chan].info;
-        break;
-      }
-
-      // play note
-      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;
-        }
-        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);
-        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);
-        }
-        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);
-        }
-        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;
-        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)
-          {
-            loopcnt = info & 0x0f;
-            crow = loopstart;
-            pattbreak = 1;
-          }
-          else if (--loopcnt > 0)
-          {
-            crow = loopstart;
-            pattbreak = 1;
-          }
-        }
-        if ((info & 0xf0) == 0xe0)  // patterndelay
-          del = speed * (info & 0x0f) - 1;
-        break;
-      case 20:
-        tempo = info;
-        break;                  // set tempo
-      }
-    }
-  }
-
-  if (!del)
-    del = speed - 1;            // speed compensation
-  if (!pattbreak)
-  {                             // next row (only if no manual advance)
-    crow++;
-    if (crow > 63)
-    {
-      crow = 0;
-      ord++;
-      loopstart = 0;
-    }
-  }
-
-  return !songend;              // still playing
-}
-
-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
-}
-
-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.??");
-  }
-
-  return (std::string ("Scream Tracker ") + filever);
-}
-
-float
-Cs3mPlayer::getrefresh ()
-{
-  return (float) (tempo / 2.5);
-}
-
-/*** private methods *************************************/
-
-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);
-}
-
-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));
-}
-
-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);
-  else
-    opl->write (0xb0 + chan,
-                ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
-}
-
-void
-Cs3mPlayer::playnote (unsigned char chan)
-{
-  unsigned char op = op_table[chan], insnr = channel[chan].inst;
-
-  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);
-
-  // set frequency & play
-  channel[chan].key = 1;
-  setfreq (chan);
-}
-
-void
-Cs3mPlayer::slide_down (unsigned char chan, unsigned char amount)
-{
-  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;
-}
-
-void
-Cs3mPlayer::slide_up (unsigned char chan, unsigned char amount)
-{
-  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;
-}
-
-void
-Cs3mPlayer::vibrato (unsigned char chan, unsigned char info)
-{
-  unsigned char i, speed, depth;
-
-  speed = info >> 4;
-  depth = (info & 0x0f) / 2;
-
-  for (i = 0; i < speed; i++)
-  {
-    channel[chan].trigger++;
-    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)));
-  }
-  setfreq (chan);
-}
-
-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);
-}
diff --git a/src/adplug/core/s3m.h b/src/adplug/core/s3m.h
index 9ad16ed742f1..bee1a94ba2d4 100644
--- a/src/adplug/core/s3m.h
+++ b/src/adplug/core/s3m.h
@@ -31,7 +31,7 @@ public:
 
 	Cs3mPlayer(Copl *newopl);
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh();
@@ -90,7 +90,7 @@ protected:
 	unsigned char crow,ord,speed,tempo,del,songend,loopstart,loopcnt;
 
 private:
-	static const char chnresolv[];
+	static const signed char chnresolv[];
 	static const unsigned short notetable[12];
 	static const unsigned char vibratotab[32];
 
diff --git a/src/adplug/core/sa2.cc b/src/adplug/core/sa2.cc
new file mode 100644
index 000000000000..b1c80e61d393
--- /dev/null
+++ b/src/adplug/core/sa2.cc
@@ -0,0 +1,314 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
+ *
+ * sa2.cpp - SAdT2 Loader by Simon Peter <dn.tlp at gmx.net>
+ *           SAdT Loader by Mamiya <mamiya at users.sourceforge.net>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "sa2.h"
+#include "debug.h"
+
+CPlayer *
+Csa2Loader::factory (Copl * newopl)
+{
+  return new Csa2Loader (newopl);
+}
+
+bool
+Csa2Loader::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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 };
+  unsigned char sat_type;
+  enum SAT_TYPE
+  {
+    HAS_ARPEGIOLIST = (1 << 7),
+    HAS_V7PATTERNS = (1 << 6),
+    HAS_ACTIVECHANNELS = (1 << 5),
+    HAS_TRACKORDER = (1 << 4),
+    HAS_ARPEGIO = (1 << 3),
+    HAS_OLDBPM = (1 << 2),
+    HAS_OLDPATTERNS = (1 << 1),
+    HAS_UNKNOWN127 = (1 << 0)
+  };
+
+  // read header
+  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)
+  {
+  case 1:
+    notedis = +0x18;
+    sat_type = HAS_UNKNOWN127 | HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 2:
+    notedis = +0x18;
+    sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 3:
+    notedis = +0x0c;
+    sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 4:
+    notedis = +0x0c;
+    sat_type = HAS_ARPEGIO | HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 5:
+    notedis = +0x0c;
+    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 6:
+    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
+    break;
+  case 7:
+    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_V7PATTERNS;
+    break;
+  case 8:
+    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER;
+    break;
+  case 9:
+    sat_type =
+      HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER | HAS_ACTIVECHANNELS;
+    break;
+  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);
+      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);
+      inst[i].arpstart = 0;
+      inst[i].arpspeed = 0;
+      inst[i].arppos = 0;
+      inst[i].arpspdcnt = 0;
+    }
+    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);
+
+  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);
+
+  // 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
+  }
+
+  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;
+      }
+    }
+  }
+
+  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);
+
+  // track data
+  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);
+        }
+      }
+      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;
+        }
+      }
+      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;
+      }
+      i++;
+    }
+  }
+  fp.close (f);
+
+  // fix instrument names
+  for (i = 0; i < 29; i++)
+    for (j = 0; j < 17; j++)
+      if (!instname[i][j])
+        instname[i][j] = ' ';
+
+  rewind (0);                   // rewind module
+  return true;
+}
+
+std::string Csa2Loader::gettype ()
+{
+  char
+    tmpstr[40];
+
+  sprintf (tmpstr, "Surprise! Adlib Tracker 2 (version %d)", header.version);
+  return std::string (tmpstr);
+}
+
+std::string Csa2Loader::gettitle ()
+{
+  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] == ' ')
+        buf[ptr] = '\0';
+      else
+      {
+        if (ptr < 16)
+          buf[ptr + 1] = ' ';
+        break;
+      }
+    strcat (bufinst, buf);
+  }
+
+  if (strchr (bufinst, '"'))
+    return std::string (bufinst, strchr (bufinst, '"') - bufinst + 1,
+                        strrchr (bufinst, '"') - strchr (bufinst, '"') - 1);
+  else
+    return std::string ();
+}
diff --git a/src/adplug/core/sa2.cxx b/src/adplug/core/sa2.cxx
deleted file mode 100644
index 8a664fa9c86e..000000000000
--- a/src/adplug/core/sa2.cxx
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp at 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
- *
- * sa2.cpp - SAdT2 Loader by Simon Peter <dn.tlp at gmx.net>
- *           SAdT Loader by Mamiya <mamiya at users.sourceforge.net>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "sa2.h"
-#include "debug.h"
-
-CPlayer *
-Csa2Loader::factory (Copl * newopl)
-{
-  return new Csa2Loader (newopl);
-}
-
-bool
-Csa2Loader::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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 };
-  unsigned char sat_type;
-  enum SAT_TYPE
-  {
-    HAS_ARPEGIOLIST = (1 << 7),
-    HAS_V7PATTERNS = (1 << 6),
-    HAS_ACTIVECHANNELS = (1 << 5),
-    HAS_TRACKORDER = (1 << 4),
-    HAS_ARPEGIO = (1 << 3),
-    HAS_OLDBPM = (1 << 2),
-    HAS_OLDPATTERNS = (1 << 1),
-    HAS_UNKNOWN127 = (1 << 0)
-  };
-
-  // read header
-  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)
-  {
-  case 1:
-    notedis = +0x18;
-    sat_type = HAS_UNKNOWN127 | HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 2:
-    notedis = +0x18;
-    sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 3:
-    notedis = +0x0c;
-    sat_type = HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 4:
-    notedis = +0x0c;
-    sat_type = HAS_ARPEGIO | HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 5:
-    notedis = +0x0c;
-    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 6:
-    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_OLDPATTERNS | HAS_OLDBPM;
-    break;
-  case 7:
-    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_V7PATTERNS;
-    break;
-  case 8:
-    sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER;
-    break;
-  case 9:
-    sat_type =
-      HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER | HAS_ACTIVECHANNELS;
-    break;
-  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);
-      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);
-      inst[i].arpstart = 0;
-      inst[i].arpspeed = 0;
-      inst[i].arppos = 0;
-      inst[i].arpspdcnt = 0;
-    }
-    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);
-
-  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);
-
-  // 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
-  }
-
-  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;
-      }
-    }
-  }
-
-  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",
-                   vfs_get_filename (fd), sat_type, nop, length, restartpos, activechan,
-                   bpm);
-
-  // track data
-  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);
-        }
-      }
-      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;
-        }
-      }
-      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;
-      }
-      i++;
-    }
-  }
-  fp.close (f);
-
-  // fix instrument names
-  for (i = 0; i < 29; i++)
-    for (j = 0; j < 17; j++)
-      if (!instname[i][j])
-        instname[i][j] = ' ';
-
-  rewind (0);                   // rewind module
-  return true;
-}
-
-std::string Csa2Loader::gettype ()
-{
-  char
-    tmpstr[40];
-
-  sprintf (tmpstr, "Surprise! Adlib Tracker 2 (version %d)", header.version);
-  return std::string (tmpstr);
-}
-
-std::string Csa2Loader::gettitle ()
-{
-  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] == ' ')
-        buf[ptr] = '\0';
-      else
-      {
-        if (ptr < 16)
-          buf[ptr + 1] = ' ';
-        break;
-      }
-    strcat (bufinst, buf);
-  }
-
-  if (strchr (bufinst, '"'))
-    return std::string (bufinst, strchr (bufinst, '"') - bufinst + 1,
-                        strrchr (bufinst, '"') - strchr (bufinst, '"') - 1);
-  else
-    return std::string ();
-}
diff --git a/src/adplug/core/sa2.h b/src/adplug/core/sa2.h
index 39900f47b365..617638196560 100644
--- a/src/adplug/core/sa2.h
+++ b/src/adplug/core/sa2.h
@@ -31,7 +31,7 @@ public:
 		: CmodPlayer(newopl)
 	{ }
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 
 	std::string gettype();
 	std::string gettitle();
diff --git a/src/adplug/core/sng.cc b/src/adplug/core/sng.cc
new file mode 100644
index 000000000000..104c40c45419
--- /dev/null
+++ b/src/adplug/core/sng.cc
@@ -0,0 +1,113 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp at 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
+ *
+ * sng.cpp - SNG Player by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "sng.h"
+
+CPlayer *
+CsngPlayer::factory (Copl * newopl)
+{
+  return new CsngPlayer (newopl);
+}
+
+bool
+CsngPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+
+  // file validation section
+  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);
+  }
+
+  rewind (0);
+  fp.close (f);
+  return true;
+}
+
+bool
+CsngPlayer::update ()
+{
+  if (header.compressed && del)
+  {
+    del--;
+    return !songend;
+  }
+
+  while (data[pos].reg)
+  {
+    opl->write (data[pos].reg, data[pos].val);
+    pos++;
+    if (pos >= header.length)
+    {
+      songend = true;
+      pos = header.loop;
+    }
+  }
+
+  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;
+  }
+  return !songend;
+}
+
+void
+CsngPlayer::rewind (int subsong)
+{
+  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.cxx b/src/adplug/core/sng.cxx
deleted file mode 100644
index c84f8766b292..000000000000
--- a/src/adplug/core/sng.cxx
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp at 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
- *
- * sng.cpp - SNG Player by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "sng.h"
-
-CPlayer *
-CsngPlayer::factory (Copl * newopl)
-{
-  return new CsngPlayer (newopl);
-}
-
-bool
-CsngPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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;
-
-  // file validation section
-  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);
-  }
-
-  rewind (0);
-  fp.close (f);
-  return true;
-}
-
-bool
-CsngPlayer::update ()
-{
-  if (header.compressed && del)
-  {
-    del--;
-    return !songend;
-  }
-
-  while (data[pos].reg)
-  {
-    opl->write (data[pos].reg, data[pos].val);
-    pos++;
-    if (pos >= header.length)
-    {
-      songend = true;
-      pos = header.loop;
-    }
-  }
-
-  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;
-  }
-  return !songend;
-}
-
-void
-CsngPlayer::rewind (int subsong)
-{
-  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 d0bd5e44e412..195a2f0a98a8 100644
--- a/src/adplug/core/sng.h
+++ b/src/adplug/core/sng.h
@@ -35,7 +35,7 @@ public:
 
 	~CsngPlayer() { if(data) delete [] data; data = 0; };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh()
diff --git a/src/adplug/core/temuopl.cc b/src/adplug/core/temuopl.cc
new file mode 100644
index 000000000000..f0f5aab16cea
--- /dev/null
+++ b/src/adplug/core/temuopl.cc
@@ -0,0 +1,85 @@
+/*
+ * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2004 Simon Peter <dn.tlp at 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
+ *
+ * temuopl.cpp - Tatsuyuki Satoh's OPL2 emulator, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include "temuopl.h"
+
+CTemuopl::CTemuopl (int rate, bool bit16, bool usestereo):
+use16bit (bit16),
+stereo (usestereo)
+{
+  opl = OPLCreate (OPL_TYPE_YM3812, 3579545, rate);
+}
+
+CTemuopl::~CTemuopl ()
+{
+  OPLDestroy (opl);
+}
+
+void
+CTemuopl::update (short *buf, int samples)
+{
+  int i;
+
+  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];
+      }
+  }
+  else
+  {
+    short *tempbuf = new short[stereo ? samples * 2 : samples];
+    int i;
+
+    YM3812UpdateOne (opl, tempbuf, samples);
+
+    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;
+
+    delete[]tempbuf;
+    tempbuf = 0;
+  }
+}
+
+void
+CTemuopl::write (int reg, int val)
+{
+  OPLWrite (opl, 0, reg);
+  OPLWrite (opl, 1, val);
+}
+
+void
+CTemuopl::init ()
+{
+  OPLResetChip (opl);
+}
diff --git a/src/adplug/core/temuopl.cxx b/src/adplug/core/temuopl.cxx
deleted file mode 100644
index f0f5aab16cea..000000000000
--- a/src/adplug/core/temuopl.cxx
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * AdPlug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2004 Simon Peter <dn.tlp at 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
- *
- * temuopl.cpp - Tatsuyuki Satoh's OPL2 emulator, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include "temuopl.h"
-
-CTemuopl::CTemuopl (int rate, bool bit16, bool usestereo):
-use16bit (bit16),
-stereo (usestereo)
-{
-  opl = OPLCreate (OPL_TYPE_YM3812, 3579545, rate);
-}
-
-CTemuopl::~CTemuopl ()
-{
-  OPLDestroy (opl);
-}
-
-void
-CTemuopl::update (short *buf, int samples)
-{
-  int i;
-
-  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];
-      }
-  }
-  else
-  {
-    short *tempbuf = new short[stereo ? samples * 2 : samples];
-    int i;
-
-    YM3812UpdateOne (opl, tempbuf, samples);
-
-    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;
-
-    delete[]tempbuf;
-    tempbuf = 0;
-  }
-}
-
-void
-CTemuopl::write (int reg, int val)
-{
-  OPLWrite (opl, 0, reg);
-  OPLWrite (opl, 1, val);
-}
-
-void
-CTemuopl::init ()
-{
-  OPLResetChip (opl);
-}
diff --git a/src/adplug/core/temuopl.h b/src/adplug/core/temuopl.h
index ab34b5ef0584..37908c0811b1 100644
--- a/src/adplug/core/temuopl.h
+++ b/src/adplug/core/temuopl.h
@@ -1,17 +1,17 @@
 /*
  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
  * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp at 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,9 +23,7 @@
 #define H_ADPLUG_TEMUOPL
 
 #include "opl.h"
-extern "C" {
 #include "fmopl.h"
-}
 
 class CTemuopl: public Copl
 {
diff --git a/src/adplug/core/u6m.cc b/src/adplug/core/u6m.cc
new file mode 100644
index 000000000000..ce67a3ae29fd
--- /dev/null
+++ b/src/adplug/core/u6m.cc
@@ -0,0 +1,1064 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
+ *
+ * u6m.cpp - Ultima 6 Music Player by Marc Winterrowd.
+ * This code extends the Adlib Winamp plug-in by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include "u6m.h"
+
+// Makes security checks on output buffer before writing
+#define SAVE_OUTPUT_ROOT(c, d, p) \
+if(p < d.size) \
+  output_root(c, d.data, p); \
+else \
+  return false;
+
+CPlayer *
+Cu6mPlayer::factory (Copl * newopl)
+{
+  return new Cu6mPlayer (newopl);
+}
+
+bool
+Cu6mPlayer::load (VFSFile & fd, 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);
+
+  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);
+    }
+  }
+  else
+  {
+    fp.close (f);
+    return (false);
+  }
+
+  // load section
+  song_data = new unsigned char[decompressed_filesize];
+  unsigned char *compressed_song_data = new unsigned char[filesize - 3];
+
+  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.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);
+  }
+
+  // deallocation section
+  delete[]compressed_song_data;
+  compressed_song_data = 0;
+
+  rewind (0);
+  return (true);
+}
+
+
+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)
+        {
+          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;
+  }
+
+  return !songend;
+}
+
+
+void
+Cu6mPlayer::rewind (int subsong)
+{
+  played_ticks = 0;
+  songend = false;
+
+  // set the driver's internal variables
+  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
+
+  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
+}
+
+
+float
+Cu6mPlayer::getrefresh ()
+{
+  return ((float) 60);          // the Ultima 6 music driver expects to be called at 60 Hz
+}
+
+
+// ============================================================================================
+//
+//
+//    Functions called by load()
+//
+//
+// ============================================================================================
+
+
+// decompress from memory to memory
+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;
+
+  long bytes_written = 0;
+
+  int cW, 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)
+        {
+          if (codeword_size < max_codeword_length)
+          {
+            codeword_size += 1;
+            dictionary_size *= 2;
+          }
+        }
+      };
+      break;
+    }
+    // shift roles - the current cW becomes the new pW
+    pW = cW;
+  }
+
+  return (true);                // indicate successful decompression
+}
+
+
+// --------------------
+// Additional functions
+// --------------------
+
+
+// Read the next code word from the source buffer
+int
+Cu6mPlayer::get_next_codeword (long &bits_read, unsigned char *source,
+                               int codeword_size)
+{
+  unsigned char b0, b1, b2;
+  int codeword;
+
+  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;
+  }
+
+  bits_read += codeword_size;
+  return (codeword);
+}
+
+
+// output a root to memory
+void
+Cu6mPlayer::output_root (unsigned char root, unsigned char *destination,
+                         long &position)
+{
+  destination[position] = root;
+  position++;
+}
+
+
+// output the string represented by a codeword
+void
+Cu6mPlayer::get_string (int codeword, Cu6mPlayer::MyDict & dictionary,
+                        std::stack < unsigned char >&root_stack)
+{
+  unsigned char root;
+  int current_codeword;
+
+  current_codeword = codeword;
+
+  while (current_codeword > 0xff)
+  {
+    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);
+}
+
+
+// ============================================================================================
+//
+//
+//    Functions called by update()
+//
+//
+// ============================================================================================
+
+
+// This function reads the song data and executes the embedded commands.
+void
+Cu6mPlayer::command_loop ()
+{
+  unsigned char command_byte;   // current command byte
+  int command_nibble_hi;        // command byte, bits 4-7
+  int command_nibble_lo;        // command byte, bite 0-3
+  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?
+    }
+
+  } while (repeat_loop);
+}
+
+
+// --------------------------------------------------------
+//    The commands supported by the U6 music file format
+// --------------------------------------------------------
+
+// ----------------------------------------
+// Set octave and frequency, note off
+// Format: 0c nn
+// c = channel, nn = packed Adlib frequency
+// ----------------------------------------
+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);
+}
+
+
+// ---------------------------------------------------
+// Set octave and frequency, old note off, new note on
+// Format: 1c nn
+// c = channel, nn = packed Adlib frequency
+// ---------------------------------------------------
+void
+Cu6mPlayer::command_1 (int channel)
+{
+  unsigned char freq_byte;
+  byte_pair freq_word;
+
+  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_word.hi = freq_word.hi | 0x20;   // note on
+  set_adlib_freq (channel, freq_word);
+}
+
+
+// ----------------------------------------
+// Set octave and frequency, note on
+// Format: 2c nn
+// c = channel, nn = packed Adlib frequency
+// ----------------------------------------
+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);
+}
+
+
+// --------------------------------------
+// Set "carrier mute factor"==not(volume)
+// Format: 3c nn
+// c = channel, nn = mute factor
+// --------------------------------------
+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);
+}
+
+
+// ----------------------------------------
+// set "modulator mute factor"==not(volume)
+// Format: 4c nn
+// c = channel, nn = mute factor
+// ----------------------------------------
+void
+Cu6mPlayer::command_4 (int channel)
+{
+  unsigned char mf_byte;
+
+  mf_byte = read_song_byte ();
+  set_modulator_mf (channel, mf_byte);
+}
+
+
+// --------------------------------------------
+// Set portamento (pitch slide)
+// Format: 5c nn
+// c = channel, nn = signed channel pitch delta
+// --------------------------------------------
+void
+Cu6mPlayer::command_5 (int channel)
+{
+  channel_freq_signed_delta[channel] = read_signed_song_byte ();
+}
+
+
+// --------------------------------------------
+// Set vibrato paramters
+// Format: 6c mn
+// c = channel
+// m = vibrato double amplitude
+// n = vibrato multiplier
+// --------------------------------------------
+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_multiplier[channel] = vb_parameters & 0xF; // low nibble
+}
+
+
+// ----------------------------------------
+// Assign Adlib instrument to Adlib channel
+// Format: 7c nn
+// c = channel, nn = instrument number
+// ----------------------------------------
+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));
+}
+
+
+// -------------------------------------------
+// Branch to a new subsong
+// Format: 81 nn aa bb
+// nn == number of times to repeat the subsong
+// aa == subsong offset (low byte)
+// bb == subsong offset (high byte)
+// -------------------------------------------
+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.continue_pos = song_pos;
+
+  subsong_stack.push (new_ss_info);
+  song_pos = new_ss_info.subsong_start;
+}
+
+
+// ------------------------------------------------------------
+// Stop interpreting commands for this timer tick
+// Format: 82 nn
+// nn == delay (in timer ticks) until further data will be read
+// ------------------------------------------------------------
+void
+Cu6mPlayer::command_82 ()
+{
+  read_delay = read_song_byte ();
+}
+
+
+// -----------------------------
+// Adlib instrument data follows
+// Format: 83 nn <11 bytes>
+// nn == instrument number
+// -----------------------------
+void
+Cu6mPlayer::command_83 ()
+{
+  unsigned char instrument_number = read_song_byte ();
+  instrument_offsets[instrument_number] = song_pos;
+  song_pos += 11;
+}
+
+
+// ----------------------------------------------
+// Set -1 mute factor slide (upward volume slide)
+// Format: 85 cn
+// c == channel
+// n == slide delay
+// ----------------------------------------------
+void
+Cu6mPlayer::command_85 ()
+{
+  unsigned char data_byte = read_song_byte ();
+  int channel = data_byte >> 4; // high 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;
+}
+
+
+// ------------------------------------------------
+// Set +1 mute factor slide (downward volume slide)
+// Format: 86 cn
+// c == channel
+// n == slide speed
+// ------------------------------------------------
+void
+Cu6mPlayer::command_86 ()
+{
+  unsigned char data_byte = read_song_byte ();
+  int channel = data_byte >> 4; // high 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;
+}
+
+
+// --------------
+// Set loop point
+// Format: E?
+// --------------
+void
+Cu6mPlayer::command_E ()
+{
+  loop_position = song_pos;
+}
+
+
+// ---------------------------
+// Return from current subsong
+// Format: 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)
+    {
+      song_pos = temp.continue_pos;
+    }
+    else
+    {
+      song_pos = temp.subsong_start;
+      subsong_stack.push (temp);
+    }
+  }
+  else
+  {
+    song_pos = loop_position;
+    songend = true;
+  }
+}
+
+
+// --------------------
+// Additional functions
+// --------------------
+
+// This function decrements its argument, without allowing it to become negative.
+void
+Cu6mPlayer::dec_clip (int &param)
+{
+  param--;
+  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 song_byte;
+  song_byte = song_data[song_pos];
+  song_pos++;
+  return (song_byte);
+}
+
+
+// Same as read_song_byte(), except that it returns a signed 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;
+  }
+  else
+  {
+    signed_value = (int) song_byte - 0x100;
+  }
+  return ((signed char) signed_value);
+}
+
+
+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;
+
+  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;
+  }
+
+  freq_word.hi = freq_table[packed_freq].hi + (octave << 2);
+  freq_word.lo = freq_table[packed_freq].lo;
+
+  return (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);
+  // 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)
+{
+  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)
+{
+  out_adlib_opcell (channel, true, 0x40, mute_factor);
+  carrier_mf[channel] = mute_factor;
+}
+
+
+void
+Cu6mPlayer::set_modulator_mf (int channel, unsigned char mute_factor)
+{
+  out_adlib_opcell (channel, false, 0x40, mute_factor);
+}
+
+
+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;
+  }
+
+  freq.lo = freq_word & 0xFF;
+  freq.hi = (freq_word >> 8) & 0xFF;
+  set_adlib_freq (channel, freq);
+}
+
+
+void
+Cu6mPlayer::vibrato (int channel)
+{
+  byte_pair freq;
+
+  if (vb_current_value[channel] >= vb_double_amplitude[channel])
+  {
+    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]++;
+  }
+  else
+  {
+    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.lo = freq_word & 0xFF;
+  freq.hi = (freq_word >> 8) & 0xFF;
+  set_adlib_freq_no_update (channel, freq);
+}
+
+
+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)
+    {
+      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);
+  }
+}
+
+
+void
+Cu6mPlayer::out_adlib (unsigned char adlib_register, unsigned char 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)
+{
+  const unsigned char adlib_channel_to_carrier_offset[9] =
+    { 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 };
+
+  if (carrier)
+  {
+    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);
+  }
+}
+
+
+// ============================================================================================
+//
+//
+//    The Dictionary
+//
+//
+// ============================================================================================
+
+
+Cu6mPlayer::MyDict::MyDict ()
+{
+  dict_size = default_dict_size;
+  dictionary = new dict_entry[dict_size - 0x100];   // don't allocate space for the roots
+  contains = 0x102;
+}
+
+
+Cu6mPlayer::MyDict::MyDict (int max_size)
+{
+  dict_size = max_size;
+  dictionary = new dict_entry[dict_size - 0x100];   // don't allocate space for the roots
+  contains = 0x102;
+}
+
+
+Cu6mPlayer::MyDict::~MyDict ()
+{
+  delete[]dictionary;
+  dictionary = 0;
+}
+
+// re-initializes the dictionary
+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)
+{
+  if (contains < dict_size)
+  {
+    dictionary[contains - 0x100].root = root;
+    dictionary[contains - 0x100].codeword = codeword;
+    contains++;
+  }
+}
+
+
+unsigned char
+Cu6mPlayer::MyDict::get_root (int codeword)
+{
+  return (dictionary[codeword - 0x100].root);
+}
+
+
+int
+Cu6mPlayer::MyDict::get_codeword (int codeword)
+{
+  return (dictionary[codeword - 0x100].codeword);
+}
diff --git a/src/adplug/core/u6m.cxx b/src/adplug/core/u6m.cxx
deleted file mode 100644
index c2267febc1cf..000000000000
--- a/src/adplug/core/u6m.cxx
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp at 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
- *
- * u6m.cpp - Ultima 6 Music Player by Marc Winterrowd.
- * This code extends the Adlib Winamp plug-in by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include "u6m.h"
-
-// Makes security checks on output buffer before writing
-#define SAVE_OUTPUT_ROOT(c, d, p) \
-if(p < d.size) \
-  output_root(c, d.data, p); \
-else \
-  return false;
-
-CPlayer *
-Cu6mPlayer::factory (Copl * newopl)
-{
-  return new Cu6mPlayer (newopl);
-}
-
-bool
-Cu6mPlayer::load (VFSFile * fd, 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);
-
-  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);
-    }
-  }
-  else
-  {
-    fp.close (f);
-    return (false);
-  }
-
-  // load section
-  song_data = new unsigned char[decompressed_filesize];
-  unsigned char *compressed_song_data = new unsigned char[filesize - 3];
-
-  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.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);
-  }
-
-  // deallocation section
-  delete[]compressed_song_data;
-  compressed_song_data = 0;
-
-  rewind (0);
-  return (true);
-}
-
-
-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)
-        {
-          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;
-  }
-
-  return !songend;
-}
-
-
-void
-Cu6mPlayer::rewind (int subsong)
-{
-  played_ticks = 0;
-  songend = false;
-
-  // set the driver's internal variables
-  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
-
-  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
-}
-
-
-float
-Cu6mPlayer::getrefresh ()
-{
-  return ((float) 60);          // the Ultima 6 music driver expects to be called at 60 Hz
-}
-
-
-// ============================================================================================
-//
-//
-//    Functions called by load()
-//
-//
-// ============================================================================================
-
-
-// decompress from memory to memory
-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;
-
-  long bytes_written = 0;
-
-  int cW, 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)
-        {
-          if (codeword_size < max_codeword_length)
-          {
-            codeword_size += 1;
-            dictionary_size *= 2;
-          }
-        }
-      };
-      break;
-    }
-    // shift roles - the current cW becomes the new pW
-    pW = cW;
-  }
-
-  return (true);                // indicate successful decompression
-}
-
-
-// --------------------
-// Additional functions
-// --------------------
-
-
-// Read the next code word from the source buffer
-int
-Cu6mPlayer::get_next_codeword (long &bits_read, unsigned char *source,
-                               int codeword_size)
-{
-  unsigned char b0, b1, b2;
-  int codeword;
-
-  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;
-  }
-
-  bits_read += codeword_size;
-  return (codeword);
-}
-
-
-// output a root to memory
-void
-Cu6mPlayer::output_root (unsigned char root, unsigned char *destination,
-                         long &position)
-{
-  destination[position] = root;
-  position++;
-}
-
-
-// output the string represented by a codeword
-void
-Cu6mPlayer::get_string (int codeword, Cu6mPlayer::MyDict & dictionary,
-                        std::stack < unsigned char >&root_stack)
-{
-  unsigned char root;
-  int current_codeword;
-
-  current_codeword = codeword;
-
-  while (current_codeword > 0xff)
-  {
-    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);
-}
-
-
-// ============================================================================================
-//
-//
-//    Functions called by update()
-//
-//
-// ============================================================================================
-
-
-// This function reads the song data and executes the embedded commands.
-void
-Cu6mPlayer::command_loop ()
-{
-  unsigned char command_byte;   // current command byte
-  int command_nibble_hi;        // command byte, bits 4-7
-  int command_nibble_lo;        // command byte, bite 0-3
-  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?
-    }
-
-  } while (repeat_loop);
-}
-
-
-// --------------------------------------------------------
-//    The commands supported by the U6 music file format
-// --------------------------------------------------------
-
-// ----------------------------------------
-// Set octave and frequency, note off
-// Format: 0c nn
-// c = channel, nn = packed Adlib frequency
-// ----------------------------------------
-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);
-}
-
-
-// ---------------------------------------------------
-// Set octave and frequency, old note off, new note on
-// Format: 1c nn
-// c = channel, nn = packed Adlib frequency
-// ---------------------------------------------------
-void
-Cu6mPlayer::command_1 (int channel)
-{
-  unsigned char freq_byte;
-  byte_pair freq_word;
-
-  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_word.hi = freq_word.hi | 0x20;   // note on
-  set_adlib_freq (channel, freq_word);
-}
-
-
-// ----------------------------------------
-// Set octave and frequency, note on
-// Format: 2c nn
-// c = channel, nn = packed Adlib frequency
-// ----------------------------------------
-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);
-}
-
-
-// --------------------------------------
-// Set "carrier mute factor"==not(volume)
-// Format: 3c nn
-// c = channel, nn = mute factor
-// --------------------------------------
-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);
-}
-
-
-// ----------------------------------------
-// set "modulator mute factor"==not(volume)
-// Format: 4c nn
-// c = channel, nn = mute factor
-// ----------------------------------------
-void
-Cu6mPlayer::command_4 (int channel)
-{
-  unsigned char mf_byte;
-
-  mf_byte = read_song_byte ();
-  set_modulator_mf (channel, mf_byte);
-}
-
-
-// --------------------------------------------
-// Set portamento (pitch slide)
-// Format: 5c nn
-// c = channel, nn = signed channel pitch delta
-// --------------------------------------------
-void
-Cu6mPlayer::command_5 (int channel)
-{
-  channel_freq_signed_delta[channel] = read_signed_song_byte ();
-}
-
-
-// --------------------------------------------
-// Set vibrato paramters
-// Format: 6c mn
-// c = channel
-// m = vibrato double amplitude
-// n = vibrato multiplier
-// --------------------------------------------
-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_multiplier[channel] = vb_parameters & 0xF; // low nibble
-}
-
-
-// ----------------------------------------
-// Assign Adlib instrument to Adlib channel
-// Format: 7c nn
-// c = channel, nn = instrument number
-// ----------------------------------------
-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));
-}
-
-
-// -------------------------------------------
-// Branch to a new subsong
-// Format: 81 nn aa bb
-// nn == number of times to repeat the subsong
-// aa == subsong offset (low byte)
-// bb == subsong offset (high byte)
-// -------------------------------------------
-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.continue_pos = song_pos;
-
-  subsong_stack.push (new_ss_info);
-  song_pos = new_ss_info.subsong_start;
-}
-
-
-// ------------------------------------------------------------
-// Stop interpreting commands for this timer tick
-// Format: 82 nn
-// nn == delay (in timer ticks) until further data will be read
-// ------------------------------------------------------------
-void
-Cu6mPlayer::command_82 ()
-{
-  read_delay = read_song_byte ();
-}
-
-
-// -----------------------------
-// Adlib instrument data follows
-// Format: 83 nn <11 bytes>
-// nn == instrument number
-// -----------------------------
-void
-Cu6mPlayer::command_83 ()
-{
-  unsigned char instrument_number = read_song_byte ();
-  instrument_offsets[instrument_number] = song_pos;
-  song_pos += 11;
-}
-
-
-// ----------------------------------------------
-// Set -1 mute factor slide (upward volume slide)
-// Format: 85 cn
-// c == channel
-// n == slide delay
-// ----------------------------------------------
-void
-Cu6mPlayer::command_85 ()
-{
-  unsigned char data_byte = read_song_byte ();
-  int channel = data_byte >> 4; // high 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;
-}
-
-
-// ------------------------------------------------
-// Set +1 mute factor slide (downward volume slide)
-// Format: 86 cn
-// c == channel
-// n == slide speed
-// ------------------------------------------------
-void
-Cu6mPlayer::command_86 ()
-{
-  unsigned char data_byte = read_song_byte ();
-  int channel = data_byte >> 4; // high 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;
-}
-
-
-// --------------
-// Set loop point
-// Format: E?
-// --------------
-void
-Cu6mPlayer::command_E ()
-{
-  loop_position = song_pos;
-}
-
-
-// ---------------------------
-// Return from current subsong
-// Format: 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)
-    {
-      song_pos = temp.continue_pos;
-    }
-    else
-    {
-      song_pos = temp.subsong_start;
-      subsong_stack.push (temp);
-    }
-  }
-  else
-  {
-    song_pos = loop_position;
-    songend = true;
-  }
-}
-
-
-// --------------------
-// Additional functions
-// --------------------
-
-// This function decrements its argument, without allowing it to become negative.
-void
-Cu6mPlayer::dec_clip (int &param)
-{
-  param--;
-  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 song_byte;
-  song_byte = song_data[song_pos];
-  song_pos++;
-  return (song_byte);
-}
-
-
-// Same as read_song_byte(), except that it returns a signed 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;
-  }
-  else
-  {
-    signed_value = (int) song_byte - 0x100;
-  }
-  return ((signed char) signed_value);
-}
-
-
-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;
-
-  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;
-  }
-
-  freq_word.hi = freq_table[packed_freq].hi + (octave << 2);
-  freq_word.lo = freq_table[packed_freq].lo;
-
-  return (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);
-  // 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)
-{
-  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)
-{
-  out_adlib_opcell (channel, true, 0x40, mute_factor);
-  carrier_mf[channel] = mute_factor;
-}
-
-
-void
-Cu6mPlayer::set_modulator_mf (int channel, unsigned char mute_factor)
-{
-  out_adlib_opcell (channel, false, 0x40, mute_factor);
-}
-
-
-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;
-  }
-
-  freq.lo = freq_word & 0xFF;
-  freq.hi = (freq_word >> 8) & 0xFF;
-  set_adlib_freq (channel, freq);
-}
-
-
-void
-Cu6mPlayer::vibrato (int channel)
-{
-  byte_pair freq;
-
-  if (vb_current_value[channel] >= vb_double_amplitude[channel])
-  {
-    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]++;
-  }
-  else
-  {
-    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.lo = freq_word & 0xFF;
-  freq.hi = (freq_word >> 8) & 0xFF;
-  set_adlib_freq_no_update (channel, freq);
-}
-
-
-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)
-    {
-      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);
-  }
-}
-
-
-void
-Cu6mPlayer::out_adlib (unsigned char adlib_register, unsigned char 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)
-{
-  const unsigned char adlib_channel_to_carrier_offset[9] =
-    { 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 };
-
-  if (carrier)
-  {
-    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);
-  }
-}
-
-
-// ============================================================================================
-//
-//
-//    The Dictionary
-//
-//
-// ============================================================================================
-
-
-Cu6mPlayer::MyDict::MyDict ()
-{
-  dict_size = default_dict_size;
-  dictionary = new dict_entry[dict_size - 0x100];   // don't allocate space for the roots
-  contains = 0x102;
-}
-
-
-Cu6mPlayer::MyDict::MyDict (int max_size)
-{
-  dict_size = max_size;
-  dictionary = new dict_entry[dict_size - 0x100];   // don't allocate space for the roots
-  contains = 0x102;
-}
-
-
-Cu6mPlayer::MyDict::~MyDict ()
-{
-  delete[]dictionary;
-  dictionary = 0;
-}
-
-// re-initializes the dictionary
-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)
-{
-  if (contains < dict_size)
-  {
-    dictionary[contains - 0x100].root = root;
-    dictionary[contains - 0x100].codeword = codeword;
-    contains++;
-  }
-}
-
-
-unsigned char
-Cu6mPlayer::MyDict::get_root (int codeword)
-{
-  return (dictionary[codeword - 0x100].root);
-}
-
-
-int
-Cu6mPlayer::MyDict::get_codeword (int codeword)
-{
-  return (dictionary[codeword - 0x100].codeword);
-}
diff --git a/src/adplug/core/u6m.h b/src/adplug/core/u6m.h
index 9876ffbdd425..302047bb6625 100644
--- a/src/adplug/core/u6m.h
+++ b/src/adplug/core/u6m.h
@@ -42,7 +42,7 @@ class Cu6mPlayer: public CPlayer
         if(song_data) { delete[] song_data; song_data = 0; }
     };
 
-	bool load(VFSFile *fd, const CFileProvider &fp);
+	bool load(VFSFile &fd, const CFileProvider &fp);
 	bool update();
 	void rewind(int subsong);
 	float getrefresh();
@@ -165,4 +165,3 @@ class Cu6mPlayer: public CPlayer
     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
new file mode 100644
index 000000000000..f5b406c81caa
--- /dev/null
+++ b/src/adplug/core/xad.cc
@@ -0,0 +1,155 @@
+/*
+  Adplug - Replayer for many OPL2/OPL3 audio file formats.
+  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+
+  xad.cpp - XAD shell player by Riven the Mage <riven at ok.ru>
+*/
+
+#include "xad.h"
+#include "debug.h"
+
+/* -------- Public Methods -------------------------------- */
+
+CxadPlayer::CxadPlayer (Copl * newopl):CPlayer (newopl)
+{
+  tune = 0;
+}
+
+CxadPlayer::~CxadPlayer ()
+{
+  if (tune)
+  {
+    delete[]tune;
+    tune = 0;
+  }
+}
+
+bool
+CxadPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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!' - signed ?
+  if (xad.id != 0x21444158)
+  {
+    fp.close (f);
+    return false;
+  }
+
+  // get file size
+  tune_size = fp.filesize (f) - 80;
+
+  // load()
+  tune = new unsigned char[tune_size];
+  f->readString ((char *) tune, tune_size);
+  fp.close (f);
+
+  ret = xadplayer_load ();
+
+  if (ret)
+    rewind (0);
+
+  return ret;
+}
+
+void
+CxadPlayer::rewind (int subsong)
+{
+  opl->init ();
+
+  plr.speed = xad.speed;
+  plr.speed_counter = 1;
+  plr.playing = 1;
+  plr.looping = 0;
+
+  // rewind()
+  xadplayer_rewind (subsong);
+
+#ifdef DEBUG
+  AdPlug_LogWrite ("-----------\n");
+#endif
+}
+
+bool
+CxadPlayer::update ()
+{
+  if (--plr.speed_counter)
+    goto update_end;
+
+  plr.speed_counter = plr.speed;
+
+  // update()
+  xadplayer_update ();
+
+update_end:
+  return (plr.playing && (!plr.looping));
+}
+
+float
+CxadPlayer::getrefresh ()
+{
+  return xadplayer_getrefresh ();
+}
+
+std::string CxadPlayer::gettype ()
+{
+  return xadplayer_gettype ();
+}
+
+std::string CxadPlayer::gettitle ()
+{
+  return xadplayer_gettitle ();
+}
+
+std::string CxadPlayer::getauthor ()
+{
+  return xadplayer_getauthor ();
+}
+
+std::string CxadPlayer::getinstrument (unsigned int i)
+{
+  return xadplayer_getinstrument (i);
+}
+
+unsigned int
+CxadPlayer::getinstruments ()
+{
+  return xadplayer_getinstruments ();
+}
+
+/* -------- Protected Methods ------------------------------- */
+
+void
+CxadPlayer::opl_write (int reg, int val)
+{
+  adlib[reg] = val;
+#ifdef DEBUG
+  AdPlug_LogWrite ("[ %02X ] = %02X\n", reg, val);
+#endif
+  opl->write (reg, val);
+}
diff --git a/src/adplug/core/xad.cxx b/src/adplug/core/xad.cxx
deleted file mode 100644
index 4b14752bf8ab..000000000000
--- a/src/adplug/core/xad.cxx
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-  Adplug - Replayer for many OPL2/OPL3 audio file formats.
-  Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
-
-  xad.cpp - XAD shell player by Riven the Mage <riven at ok.ru>
-*/
-
-#include "xad.h"
-#include "debug.h"
-
-/* -------- Public Methods -------------------------------- */
-
-CxadPlayer::CxadPlayer (Copl * newopl):CPlayer (newopl)
-{
-  tune = 0;
-}
-
-CxadPlayer::~CxadPlayer ()
-{
-  if (tune)
-  {
-    delete[]tune;
-    tune = 0;
-  }
-}
-
-bool
-CxadPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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!' - signed ?
-  if (xad.id != 0x21444158)
-  {
-    fp.close (f);
-    return false;
-  }
-
-  // get file size
-  tune_size = fp.filesize (f) - 80;
-
-  // load()
-  tune = new unsigned char[tune_size];
-  f->readString ((char *) tune, tune_size);
-  fp.close (f);
-
-  ret = xadplayer_load ();
-
-  if (ret)
-    rewind (0);
-
-  return ret;
-}
-
-void
-CxadPlayer::rewind (int subsong)
-{
-  opl->init ();
-
-  plr.speed = xad.speed;
-  plr.speed_counter = 1;
-  plr.playing = 1;
-  plr.looping = 0;
-
-  // rewind()
-  xadplayer_rewind (subsong);
-
-#ifdef DEBUG
-  AdPlug_LogWrite ("-----------\n");
-#endif
-}
-
-bool
-CxadPlayer::update ()
-{
-  if (--plr.speed_counter)
-    goto update_end;
-
-  plr.speed_counter = plr.speed;
-
-  // update()
-  xadplayer_update ();
-
-update_end:
-  return (plr.playing && (!plr.looping));
-}
-
-float
-CxadPlayer::getrefresh ()
-{
-  return xadplayer_getrefresh ();
-}
-
-std::string CxadPlayer::gettype ()
-{
-  return xadplayer_gettype ();
-}
-
-std::string CxadPlayer::gettitle ()
-{
-  return xadplayer_gettitle ();
-}
-
-std::string CxadPlayer::getauthor ()
-{
-  return xadplayer_getauthor ();
-}
-
-std::string CxadPlayer::getinstrument (unsigned int i)
-{
-  return xadplayer_getinstrument (i);
-}
-
-unsigned int
-CxadPlayer::getinstruments ()
-{
-  return xadplayer_getinstruments ();
-}
-
-/* -------- Protected Methods ------------------------------- */
-
-void
-CxadPlayer::opl_write (int reg, int val)
-{
-  adlib[reg] = val;
-#ifdef DEBUG
-  AdPlug_LogWrite ("[ %02X ] = %02X\n", reg, val);
-#endif
-  opl->write (reg, val);
-}
diff --git a/src/adplug/core/xad.h b/src/adplug/core/xad.h
index 15e4c1dab42f..8dd89127b61e 100644
--- a/src/adplug/core/xad.h
+++ b/src/adplug/core/xad.h
@@ -32,7 +32,7 @@ public:
         CxadPlayer(Copl * newopl);
         ~CxadPlayer();
 
-        bool	load(VFSFile *fd, const CFileProvider &fp);
+        bool	load(VFSFile &fd, const CFileProvider &fp);
         bool	update();
         void	rewind(int subsong);
         float	getrefresh();
diff --git a/src/adplug/core/xsm.cc b/src/adplug/core/xsm.cc
new file mode 100644
index 000000000000..e943769f31cf
--- /dev/null
+++ b/src/adplug/core/xsm.cc
@@ -0,0 +1,136 @@
+/*
+ * Adplug - Replayer for many OPL2/OPL3 audio file formats.
+ * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
+ *
+ * xsm.cpp - eXtra Simple Music Player, by Simon Peter <dn.tlp at gmx.net>
+ */
+
+#include <string.h>
+
+#include "xsm.h"
+
+CxsmPlayer::CxsmPlayer (Copl * newopl):CPlayer (newopl), music (0)
+{
+}
+
+CxsmPlayer::~CxsmPlayer ()
+{
+  if (music)
+  {
+    delete[]music;
+    music = 0;
+  }
+}
+
+bool
+CxsmPlayer::load (VFSFile & fd, const CFileProvider & fp)
+{
+  binistream *f = fp.open (fd);
+  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;
+  }
+
+  // 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);
+  }
+
+  // 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);
+
+  // success
+  fp.close (f);
+  rewind (0);
+  return true;
+}
+
+bool
+CxsmPlayer::update ()
+{
+  int c;
+
+  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])
+      play_note (c, music[notenum * 9 + c] % 12, music[notenum * 9 + c] / 12);
+    else
+      play_note (c, 0, 0);
+  }
+
+  last = notenum;
+  notenum++;
+  return !songend;
+}
+
+void
+CxsmPlayer::rewind (int subsong)
+{
+  notenum = last = 0;
+  songend = false;
+}
+
+float
+CxsmPlayer::getrefresh ()
+{
+  return 5.0f;
+}
+
+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));
+}
diff --git a/src/adplug/core/xsm.cxx b/src/adplug/core/xsm.cxx
deleted file mode 100644
index 310084c23b9f..000000000000
--- a/src/adplug/core/xsm.cxx
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Adplug - Replayer for many OPL2/OPL3 audio file formats.
- * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp at 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
- *
- * xsm.cpp - eXtra Simple Music Player, by Simon Peter <dn.tlp at gmx.net>
- */
-
-#include <string.h>
-
-#include "xsm.h"
-
-CxsmPlayer::CxsmPlayer (Copl * newopl):CPlayer (newopl), music (0)
-{
-}
-
-CxsmPlayer::~CxsmPlayer ()
-{
-  if (music)
-  {
-    delete[]music;
-    music = 0;
-  }
-}
-
-bool
-CxsmPlayer::load (VFSFile * fd, const CFileProvider & fp)
-{
-  binistream *f = fp.open (fd);
-  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;
-  }
-
-  // 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);
-  }
-
-  // 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);
-
-  // success
-  fp.close (f);
-  rewind (0);
-  return true;
-}
-
-bool
-CxsmPlayer::update ()
-{
-  int c;
-
-  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])
-      play_note (c, music[notenum * 9 + c] % 12, music[notenum * 9 + c] / 12);
-    else
-      play_note (c, 0, 0);
-  }
-
-  last = notenum;
-  notenum++;
-  return !songend;
-}
-
-void
-CxsmPlayer::rewind (int subsong)
-{
-  notenum = last = 0;
-  songend = false;
-}
-
-float
-CxsmPlayer::getrefresh ()
-{
-  return 5.0f;
-}
-
-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));
-}
diff --git a/src/adplug/core/xsm.h b/src/adplug/core/xsm.h
index 2a3fdfd7a86e..714a0af320e9 100644
--- a/src/adplug/core/xsm.h
+++ b/src/adplug/core/xsm.h
@@ -29,7 +29,7 @@ public:
   CxsmPlayer(Copl *newopl);
   ~CxsmPlayer();
 
-  bool load(VFSFile *fd, const CFileProvider &fp);
+  bool load(VFSFile &fd, const CFileProvider &fp);
   bool update();
   void rewind(int subsong);
   float getrefresh();
diff --git a/src/adplug/plugin.c b/src/adplug/plugin.c
deleted file mode 100644
index 8e7170b89395..000000000000
--- a/src/adplug/plugin.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-#include "adplug-xmms.h"
-static const char * fmts[] =
-    { "a2m", "adl", "amd", "bam", "cff", "cmf", "d00", "dfm", "dmo", "dro",
-      "dtm", "hsc", "hsp", "ins", "jbm", "ksm", "laa", "lds", "m", "mad",
-      "mkj", "msc", "rad", "raw", "rix", "rol", "s3m", "sa2", "sat", "sci",
-      "sng", "wlf", "xad", "xsm",
-      NULL };
-
-AUD_INPUT_PLUGIN
-(
-  .name = N_("AdPlug (AdLib Player)"),
-  .domain = PACKAGE,
-  .init = adplug_init,
-  .cleanup = adplug_quit,
-  .play = adplug_play,
-  .probe_for_tuple = adplug_get_tuple,
-  .is_our_file_from_vfs = adplug_is_our_fd,
-  .extensions = fmts,
-)
diff --git a/src/alarm/Makefile b/src/alarm/Makefile
index 2e8b7611f21b..03357bdad7db 100644
--- a/src/alarm/Makefile
+++ b/src/alarm/Makefile
@@ -1,13 +1,15 @@
 PLUGIN = alarm${PLUGIN_SUFFIX}
 
-SRCS = alarm.c		\
-       interface.c
+SRCS = alarm.cc		\
+       interface.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 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} ${GTK_CFLAGS} -I../..
+LIBS += ${GTK_LIBS} -laudgui
diff --git a/src/alarm/alarm.c b/src/alarm/alarm.c
deleted file mode 100644
index 3e3848f33a17..000000000000
--- a/src/alarm/alarm.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * Copyright (C) Adam Feakin <adamf at snika.uklinux.net>
- *
- * modified by Daniel Stodden <stodden at in.tum.de>
- *
- * 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.
- */
-
-#include <stdlib.h>
-
-#include <time.h>
-#if TM_IN_SYS_TIME
-# include <sys/time.h>
-#endif
-
-#include <string.h>
-#include <stdio.h>
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-#include <pthread.h>
-#include <assert.h>
-#include <math.h>
-
-#include <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "alarm.h"
-#include "interface.h"
-#include "callbacks.h"
-
-static const gchar * const alarm_defaults[] = {
- /* general */
- "alarm_h", "6",
- "alarm_m", "30",
- "cmd_on", "FALSE",
- "fading", "60",
- "quietvol", "25",
- "reminder_on", "FALSE",
- "stop_h", "1",
- "stop_m", "0",
- "stop_on", "TRUE",
- "volume", "80",
-
- /* days */
- "sun_flags", "3",
- "sun_h", "6",
- "sun_m", "30",
- "mon_flags", "2",
- "mon_h", "6",
- "mon_m", "30",
- "tue_flags", "2",
- "tue_h", "6",
- "tue_m", "30",
- "wed_flags", "2",
- "wed_h", "6",
- "wed_m", "30",
- "thu_flags", "2",
- "thu_h", "6",
- "thu_m", "30",
- "fri_flags", "2",
- "fri_h", "6",
- "fri_m", "30",
- "sat_flags", "2",
- "sat_h", "6",
- "sat_m", "30",
- NULL};
-
-typedef struct
-{
-    pthread_t tid;
-    volatile gboolean  is_valid;
-} alarm_thread_t;
-
-static gint timeout_source;
-static time_t play_start;
-
-static alarm_thread_t stop;     /* thread id of stop loop */
-static pthread_mutex_t fader_lock = PTHREAD_MUTEX_INITIALIZER;
-
-static GeneralPlugin alarm_plugin;
-
-/* string tokens to allow loops and shorten code */
-static char day_cb[7][7] = {"sun_cb", "mon_cb", "tue_cb",
-                            "wed_cb", "thu_cb", "fri_cb", "sat_cb"};
-
-static char day_flags[7][10] = {"sun_flags", "mon_flags", "tue_flags",
-                                "wed_flags", "thu_flags", "fri_flags", "sat_flags"};
-
-static char day_h[7][6] = {"sun_h", "mon_h", "tue_h",
-                           "wed_h", "thu_h", "fri_h", "sat_h"};
-
-static char day_m[7][6] = {"sun_m", "mon_m", "tue_m",
-                           "wed_m", "thu_m", "fri_m", "sat_m"};
-
-static char day_def[7][8] = {"sun_def", "mon_def", "tue_def",
-                             "wed_def", "thu_def", "fri_def", "sat_def"};
-
-static struct
-{
-    GtkSpinButton *alarm_h;
-    GtkSpinButton *alarm_m;
-
-    GtkToggleButton *stop_on;
-    GtkSpinButton *stop_h;
-    GtkSpinButton *stop_m;
-
-    GtkRange *volume;
-    GtkRange *quietvol;
-
-    GtkSpinButton *fading;
-
-    GtkEntry *cmdstr;
-    GtkToggleButton *cmd_on;
-
-    GtkEntry *playlist;
-
-    int default_hour;
-    int default_min;
-
-    // array allows looping of days
-    alarmday day[7];
-
-
-    GtkEntry *reminder;
-    GtkToggleButton *reminder_cb;
-    gboolean reminder_on;
-}
-alarm_conf;
-
-static gint alarm_h, alarm_m;
-
-static gboolean stop_on;
-static gint stop_h, stop_m;
-
-static gint volume, quietvol;
-
-static gint fading;
-
-static gboolean cmd_on;
-
-static GtkWidget *config_dialog = NULL;
-static GtkWidget *alarm_dialog = NULL;
-
-static GtkWidget *lookup_widget(GtkWidget *w, const gchar *name)
-{
-    GtkWidget * widget = g_object_get_data ((GObject *) w, name);
-    g_return_val_if_fail(widget != NULL, NULL);
-
-    return widget;
-}
-
-/*
- * the callback function that is called when the save button is
- * pressed saves configuration to ~/.bmp/alarmconfig
- */
-void alarm_save(void)
-{
-    int daynum = 0;  // used to identify day number
-
-    /*
-     * update the live values and write them out
-     */
-    alarm_h = alarm_conf.default_hour = gtk_spin_button_get_value_as_int (alarm_conf.alarm_h);
-    aud_set_int ("alarm", "alarm_h", alarm_h);
-
-    alarm_m = alarm_conf.default_min = gtk_spin_button_get_value_as_int (alarm_conf.alarm_m);
-    aud_set_int ("alarm", "alarm_m", alarm_m);
-
-    stop_h = gtk_spin_button_get_value_as_int (alarm_conf.stop_h);
-    stop_m = gtk_spin_button_get_value_as_int (alarm_conf.stop_m);
-    stop_on = gtk_toggle_button_get_active (alarm_conf.stop_on);
-
-    /* days of the week */
-    for(; daynum < 7; daynum++)
-    {
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb)))
-            alarm_conf.day[daynum].flags = 0;
-        else
-            alarm_conf.day[daynum].flags = ALARM_OFF;
-
-        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def)))
-            alarm_conf.day[daynum].flags |= ALARM_DEFAULT;
-
-        alarm_conf.day[daynum].hour =
-         gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_hr);
-        alarm_conf.day[daynum].min =
-         gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_min);
-
-        aud_set_int ("alarm", day_flags[daynum], alarm_conf.day[daynum].flags);
-        aud_set_int ("alarm", day_h[daynum], alarm_conf.day[daynum].hour);
-        aud_set_int ("alarm", day_m[daynum], alarm_conf.day[daynum].min);
-    }
-
-    /* END: days of week */
-
-    volume = gtk_range_get_value (alarm_conf.volume);
-    aud_set_int ("alarm", "volume", volume);
-
-    quietvol = gtk_range_get_value (alarm_conf.quietvol);
-    aud_set_int ("alarm", "quietvol", quietvol);
-
-    fading = gtk_spin_button_get_value_as_int (alarm_conf.fading);
-
-    /* write the new values */
-    aud_set_int ("alarm", "stop_h", stop_h);
-    aud_set_int ("alarm", "stop_m", stop_m);
-    aud_set_int ("alarm", "fading", fading);
-    aud_set_bool ("alarm", "stop_on", stop_on);
-
-    char * cmdstr = gtk_editable_get_chars ((GtkEditable *) alarm_conf.cmdstr, 0, -1);
-    aud_set_str ("alarm", "cmdstr", cmdstr);
-    g_free (cmdstr);
-
-    cmd_on = gtk_toggle_button_get_active (alarm_conf.cmd_on);
-    aud_set_bool ("alarm", "cmd_on", cmd_on);
-
-    char * playlist = gtk_editable_get_chars ((GtkEditable *) alarm_conf.playlist, 0, -1);
-    aud_set_str ("alarm", "playlist", playlist);
-    g_free (playlist);
-
-    /* reminder */
-    char * reminder_msg = gtk_editable_get_chars ((GtkEditable *) alarm_conf.reminder, 0, -1);
-    aud_set_str ("alarm", "reminder_msg", reminder_msg);
-    g_free (reminder_msg);
-
-    alarm_conf.reminder_on = gtk_toggle_button_get_active (alarm_conf.reminder_cb);
-    aud_set_bool ("alarm", "reminder_on", alarm_conf.reminder_on);
-}
-
-/*
- * read the current configuration from the file
- */
-static void alarm_read_config(void)
-{
-    int daynum = 0;   // used for day number
-
-    aud_config_set_defaults ("alarm", alarm_defaults);
-
-    alarm_h = aud_get_int ("alarm", "alarm_h");
-    alarm_m = aud_get_int ("alarm", "alarm_m");
-
-    /* save them here too */
-    alarm_conf.default_hour = alarm_h;
-    alarm_conf.default_min = alarm_m;
-
-    stop_h = aud_get_int ("alarm", "stop_h");
-    stop_m = aud_get_int ("alarm", "stop_m");
-    stop_on = aud_get_bool ("alarm", "stop_on");
-
-    volume = aud_get_int ("alarm", "volume");
-    quietvol = aud_get_int ("alarm", "quietvol");
-
-    fading = aud_get_int ("alarm", "fading");
-
-    cmd_on = aud_get_bool ("alarm", "cmd_on");
-
-    alarm_conf.reminder_on = aud_get_bool ("alarm", "reminder_on");
-
-    /* day flags and times */
-    for(; daynum < 7; daynum++)
-    {
-        /* read the flags */
-        alarm_conf.day[daynum].flags = aud_get_int ("alarm", day_flags[daynum]);
-
-        /* read the times */
-        alarm_conf.day[daynum].hour = aud_get_int ("alarm", day_h[daynum]);
-        alarm_conf.day[daynum].min = aud_get_int ("alarm", day_m[daynum]);
-    }
-}
-
-/*
- * displays the configuration window and opens the config file.
- */
-static void alarm_configure(void)
-{
-    int daynum = 0;  // used to loop days
-    GtkWidget *w;
-
-    if (config_dialog)
-    {
-        gtk_window_present(GTK_WINDOW(config_dialog));
-        return;
-    }
-
-    alarm_read_config();
-
-    /*
-     * Create the widgets
-     */
-    config_dialog = create_config_dialog();
-
-    w = lookup_widget(config_dialog, "alarm_h_spin");
-    alarm_conf.alarm_h = GTK_SPIN_BUTTON(w);
-    gtk_spin_button_set_value(alarm_conf.alarm_h, alarm_h);
-
-    w = lookup_widget(config_dialog, "alarm_m_spin");
-    alarm_conf.alarm_m =  GTK_SPIN_BUTTON(w);
-    gtk_spin_button_set_value(alarm_conf.alarm_m, alarm_m);
-
-    w = lookup_widget(config_dialog, "stop_h_spin");
-    alarm_conf.stop_h = GTK_SPIN_BUTTON(w);
-    gtk_spin_button_set_value(alarm_conf.stop_h, stop_h);
-
-    w = lookup_widget(config_dialog, "stop_m_spin");
-    alarm_conf.stop_m = GTK_SPIN_BUTTON(w);
-    gtk_spin_button_set_value(alarm_conf.stop_m, stop_m);
-
-    w = lookup_widget(config_dialog, "stop_checkb");
-    alarm_conf.stop_on = GTK_TOGGLE_BUTTON(w);
-    gtk_toggle_button_set_active(alarm_conf.stop_on, stop_on);
-
-    w = lookup_widget(config_dialog, "vol_scale");
-    alarm_conf.volume = GTK_RANGE(w);
-    gtk_range_set_adjustment(alarm_conf.volume,
-     GTK_ADJUSTMENT(gtk_adjustment_new(volume, 0, 100, 1, 5, 0)));
-
-    w = lookup_widget(config_dialog, "quiet_vol_scale");
-    alarm_conf.quietvol = GTK_RANGE(w);
-    gtk_range_set_adjustment(alarm_conf.quietvol,
-     GTK_ADJUSTMENT(gtk_adjustment_new(quietvol, 0, 100, 1, 5, 0)));
-
-    /* days of week */
-    for(; daynum < 7; daynum++)
-    {
-        w = lookup_widget(config_dialog, day_cb[daynum]);
-        alarm_conf.day[daynum].cb = GTK_CHECK_BUTTON(w);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb),
-         !(alarm_conf.day[daynum].flags & ALARM_OFF));
-
-        w = lookup_widget(config_dialog, day_def[daynum]);
-        alarm_conf.day[daynum].cb_def = GTK_CHECK_BUTTON(w);
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def),
-         alarm_conf.day[daynum].flags & ALARM_DEFAULT);
-
-
-        /* Changed to show default time instead of set time when ALARM_DEFAULT set,
-         * as suggested by Mark Brown
-         */
-/*      w = lookup_widget(config_dialog, day_h[daynum]);
-        alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
-        gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.day[daynum].hour);
-
-        w = lookup_widget(config_dialog, day_m[daynum]);
-        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);
-*/
-        if(alarm_conf.day[daynum].flags & ALARM_DEFAULT)
-        {
-            w = lookup_widget(config_dialog, day_h[daynum]);
-            alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
-            gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.default_hour);
-
-            w = lookup_widget(config_dialog, day_m[daynum]);
-            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);
-        }
-        else
-        {
-            w = lookup_widget(config_dialog, day_h[daynum]);
-            alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
-            gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.day[daynum].hour);
-
-            w = lookup_widget(config_dialog, day_m[daynum]);
-            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);
-        }
-    }
-
-   /* END: days of week */
-
-    w = lookup_widget(config_dialog,"fading_spin");
-    alarm_conf.fading = GTK_SPIN_BUTTON(w);
-    gtk_spin_button_set_value(alarm_conf.fading, fading);
-
-    char * cmdstr = aud_get_str ("alarm", "cmdstr");
-    w = lookup_widget(config_dialog, "cmd_entry");
-    alarm_conf.cmdstr = GTK_ENTRY(w);
-    gtk_entry_set_text(alarm_conf.cmdstr, cmdstr);
-    str_unref (cmdstr);
-
-    w = lookup_widget(config_dialog, "cmd_checkb");
-    alarm_conf.cmd_on = GTK_TOGGLE_BUTTON(w);
-    gtk_toggle_button_set_active(alarm_conf.cmd_on, cmd_on);
-
-    char * playlist = aud_get_str ("alarm", "playlist");
-    w = lookup_widget(config_dialog, "playlist");
-    alarm_conf.playlist = GTK_ENTRY(w);
-    gtk_entry_set_text(alarm_conf.playlist, playlist);
-    str_unref (playlist);
-
-    char * reminder_msg = aud_get_str ("alarm", "reminder_msg");
-    w = lookup_widget(config_dialog, "reminder_text");
-    alarm_conf.reminder = GTK_ENTRY(w);
-    gtk_entry_set_text(alarm_conf.reminder, reminder_msg);
-    str_unref (reminder_msg);
-
-    w = lookup_widget(config_dialog, "reminder_cb");
-    alarm_conf.reminder_cb = GTK_TOGGLE_BUTTON(w);
-    gtk_toggle_button_set_active(alarm_conf.reminder_cb, alarm_conf.reminder_on);
-
-    g_signal_connect (config_dialog, "destroy", (GCallback) gtk_widget_destroyed,
-     & config_dialog);
-
-    AUDDBG("END alarm_configure\n");
-}
-
-/* functions for greying out the time for days */
-void on_day_def_toggled(GtkToggleButton *togglebutton, gpointer user_data, int daynum)
-{
-    GtkWidget *w;
-
-    /* change the time shown too */
-    w = lookup_widget(config_dialog, day_h[daynum]);
-    if(w == NULL)
-        return;
-
-    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);
-    }
-    else
-    {
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].hour);
-        gtk_widget_set_sensitive(w, TRUE);
-    }
-
-    w = lookup_widget(config_dialog, day_m[daynum]);
-    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);
-    }
-    else
-    {
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].min);
-        gtk_widget_set_sensitive(w, TRUE);
-    }
-}
-
-void on_sun_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 0);
-}
-
-void on_mon_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 1);
-}
-
-void on_tue_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 2);
-}
-
-void on_wed_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 3);
-}
-
-void on_thu_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 4);
-}
-
-void on_fri_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 5);
-}
-
-void on_sat_def_toggled(GtkToggleButton *togglebutton, gpointer user_data)
-{
-    on_day_def_toggled(togglebutton, user_data, 6);
-}
-
-/* END: greying things */
-
-void alarm_current_volume(GtkButton *button, gpointer data)
-{
-    gint vol;
-    GtkAdjustment *adj;
-
-    AUDDBG("on_current_button_clicked\n");
-
-    aud_drct_get_volume_main(&vol);
-
-    adj = gtk_range_get_adjustment(alarm_conf.volume);
-    gtk_adjustment_set_value(adj, (gfloat)vol);
-}
-
-/*
- * a thread safe sleeping function -
- * and it even works in solaris (I think)
- */
-static void threadsleep(float x)
-{
-    AUDDBG("threadsleep: waiting %f seconds\n", x);
-
-    g_usleep((int) ((float) x * (float) 1000000.0));
-
-    return;
-}
-
-static inline alarm_thread_t alarm_thread_create(void *(*start_routine)(void *), void *args, unsigned int detach)
-{
-    alarm_thread_t thrd;
-    pthread_attr_t attr;
-
-    pthread_attr_init(&attr);
-
-    if(detach != 0)
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
-    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
-    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
-
-    thrd.is_valid = (pthread_create(&thrd.tid, &attr, start_routine, args) == 0);
-
-    return thrd;
-}
-
-static void *alarm_fade(void *arg)
-{
-    fader *vols = (fader *)arg;
-    guint i;
-    gint v;
-    gint inc, diff, adiff;
-
-    /* lock */
-    pthread_mutex_lock(&fader_lock);
-
-    /* slide volume */
-    /* the Kaspar Giger way of fading, check the current mixer volume and
-     * increment from there so that if you have some other app lowering the
-     * volume at the same time, the alarm plugin will not ignore it.  If you have
-     * some other app increasing the volume, then it could get louder than you expect
-     * though - because the loop does not recalculate the difference each time.
-     */
-
-    /* difference between the 2 volumes */
-    diff = vols->end - vols->start;
-    adiff = abs(diff);
-
-    /* Are we going up or down? */
-    if(diff < 0)
-        inc = -1;
-    else
-        inc = 1;
-
-    aud_drct_set_volume_main((gint)vols->start);
-    //for(i=0;i<(vols->end - vols->start);i++)
-    for(i=0;i<adiff;i++)
-    {
-        //threadsleep((gfloat)fading / (vols->end - vols->start));
-        threadsleep((gfloat)fading / (gfloat)adiff);
-        aud_drct_get_volume_main(&v);
-        aud_drct_set_volume_main(v + inc);
-    }
-    /* Setting the volume to the end volume sort of defeats the point if having
-     * the code in there to allow other apps to control volume too :)
-     */
-    //aud_drct_set_volume_main((gint)vols->end);
-
-    /* and */
-    pthread_mutex_unlock(&fader_lock);
-
-    AUDDBG("volume = %f%%\n", (gdouble)vols->end);
-    return 0;
-}
-
-static void *alarm_stop_thread(void *args)
-{
-    gint currvol;
-    fader fade_vols;
-    alarm_thread_t f;
-
-    AUDDBG("alarm_stop_thread\n");
-
-
-    /* sleep for however long we are meant to be sleeping for until
-     * its time to shut up
-     */
-    threadsleep(((stop_h * 60) + stop_m) * 60);
-
-    AUDDBG("alarm_stop triggered\n");
-
-    if (alarm_dialog)
-        gtk_widget_destroy(alarm_dialog);
-
-    aud_drct_get_volume_main(&currvol),
-
-    /* fade back to zero */
-    fade_vols.start = currvol;
-    fade_vols.end = 0;
-
-    /* The fader thread locks the fader_mutex now */
-    f = alarm_thread_create(alarm_fade, &fade_vols, 0);
-
-    pthread_join(f.tid, NULL);
-    aud_drct_stop();
-
-    /* might as well set the volume to something higher than zero so we
-     * dont confuse the poor people who just woke up and cant work out why
-     * theres no music playing when they press the little play button :)
-     */
-    aud_drct_set_volume_main(currvol);
-
-    AUDDBG("alarm_stop done\n");
-    return(NULL);
-}
-
-void alarm_stop_cancel(GtkWidget *w, gpointer data)
-{
-    AUDDBG("alarm_stop_cancel\n");
-    if (pthread_cancel(stop.tid) == 0)
-        stop.is_valid = FALSE;
-}
-
-/* the main alarm thread */
-static gboolean alarm_timeout (void * unused)
-{
-    struct tm *currtime;
-    time_t timenow;
-    guint today;
-
-    AUDDBG("Getting time\n");
-    timenow = time(NULL);
-    currtime = localtime(&timenow);
-    today = currtime->tm_wday;
-    AUDDBG("Today is %d\n", today);
-
-    /* already went off? */
-    if (timenow < play_start + 60)
-        return TRUE;
-
-    if(alarm_conf.day[today].flags & ALARM_OFF)
-        return TRUE;
-    else
-    {
-        /* set the alarm_h and alarm_m for today, if not default */
-        if(!(alarm_conf.day[today].flags & ALARM_DEFAULT))
-        {
-            alarm_h = alarm_conf.day[today].hour;
-            alarm_m = alarm_conf.day[today].min;
-        }
-        else
-        {
-            alarm_h = alarm_conf.default_hour;
-            alarm_m = alarm_conf.default_min;
-        }
-    }
-
-    AUDDBG("Alarm time is %d:%d (def: %d:%d)\n", alarm_h, alarm_m,
-    alarm_conf.default_hour, alarm_conf.default_min);
-
-    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;
-
-    if(cmd_on == TRUE)
-    {
-        char * cmdstr = aud_get_str ("alarm", "cmdstr");
-        AUDDBG("Executing %s, cmd_on is true\n", cmdstr);
-        if(system(cmdstr) == -1)
-            AUDDBG("Executing %s failed\n",cmdstr);
-        str_unref (cmdstr);
-    }
-
-    bool_t started = FALSE;
-
-    char * playlist = aud_get_str ("alarm", "playlist");
-    if (playlist[0])
-    {
-        aud_drct_pl_open (playlist);
-        started = TRUE;
-    }
-    str_unref (playlist);
-
-    if(fading)
-    {
-        fader fade_vols;
-
-        AUDDBG("Fading is true\n");
-        aud_drct_set_volume_main(quietvol);
-
-        /* start playing */
-        play_start = time(NULL);
-
-        if (! started)
-            aud_drct_play ();
-
-        /* fade volume */
-        fade_vols.start = quietvol;
-        fade_vols.end = volume;
-
-        //alarm_fade(quietvol, volume);
-        alarm_thread_create(alarm_fade, &fade_vols, 0);
-    }
-    else
-    {
-        /* no fading */
-
-        /* set volume */
-        aud_drct_set_volume_main(volume);
-
-        /* start playing */
-        play_start = time(NULL);
-        aud_drct_play();
-    }
-
-    if(alarm_conf.reminder_on == TRUE)
-    {
-        char * reminder_msg = aud_get_str ("alarm", "reminder_msg");
-        GtkWidget *reminder_dialog;
-        AUDDBG("Showing reminder '%s'\n", reminder_msg);
-
-        reminder_dialog = (GtkWidget*) create_reminder_dialog(reminder_msg);
-        gtk_widget_show_all(reminder_dialog);
-        str_unref (reminder_msg);
-    }
-
-    /* bring up the wakeup call dialog if stop_on is set TRUE, this
-     * has been moved to after making Audacious play so that it doesnt
-     * get in the way for people with manual window placement turned on
-     *
-     * 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)
-    {
-        alarm_dialog = create_alarm_dialog();
-
-        AUDDBG("now starting stop thread\n");
-        stop = alarm_thread_create(alarm_stop_thread, NULL, 0);
-        AUDDBG("Created wakeup dialog and started stop thread\n");
-    }
-
-    return TRUE;
-}
-
-/*
- * initialization
- * opens the config file and reads the value, creates a new
- * config in memory if the file doesnt exist and sets default vals
- */
-static gboolean alarm_init (void)
-{
-    AUDDBG("alarm_init\n");
-
-    alarm_read_config();
-
-    timeout_source = g_timeout_add_seconds (10, alarm_timeout, NULL);
-
-    aud_plugin_menu_add (AUD_MENU_MAIN, alarm_configure, _("Set Alarm ..."), "appointment-new");
-
-    return TRUE;
-}
-
-/*
- * kill the main thread
- */
-static void alarm_cleanup(void)
-{
-    AUDDBG("alarm_cleanup\n");
-
-    aud_plugin_menu_remove (AUD_MENU_MAIN, alarm_configure);
-
-    if (timeout_source)
-    {
-        g_source_remove (timeout_source);
-        timeout_source = 0;
-    }
-
-    if (stop.is_valid)
-    {
-        pthread_cancel(stop.tid);
-        stop.is_valid = FALSE;
-    }
-}
-
-static const char alarm_about[] =
- N_("A plugin that can be used to start playing at a certain time.\n\n"
-    "Originally written by Adam Feakin and Daniel Stodden.");
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Alarm"),
-    .domain = PACKAGE,
-    .about_text = alarm_about,
-    .init = alarm_init,
-    .configure = alarm_configure,
-    .cleanup = alarm_cleanup,
-)
diff --git a/src/alarm/alarm.cc b/src/alarm/alarm.cc
new file mode 100644
index 000000000000..80a97b3ab8a2
--- /dev/null
+++ b/src/alarm/alarm.cc
@@ -0,0 +1,822 @@
+/*
+ * Copyright (C) Adam Feakin <adamf at snika.uklinux.net>
+ *
+ * modified by Daniel Stodden <stodden at in.tum.de>
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <pthread.h>
+#include <assert.h>
+#include <math.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+#include "alarm.h"
+#include "interface.h"
+#include "callbacks.h"
+
+class AlarmPlugin : public GeneralPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Alarm"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr AlarmPlugin () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT AlarmPlugin aud_plugin_instance;
+
+const char * const AlarmPlugin::defaults[] = {
+ /* general */
+ "alarm_h", "6",
+ "alarm_m", "30",
+ "cmd_on", "FALSE",
+ "fading", "60",
+ "quietvol", "25",
+ "reminder_on", "FALSE",
+ "stop_h", "1",
+ "stop_m", "0",
+ "stop_on", "TRUE",
+ "volume", "80",
+
+ /* days */
+ "sun_flags", "3",
+ "sun_h", "6",
+ "sun_m", "30",
+ "mon_flags", "2",
+ "mon_h", "6",
+ "mon_m", "30",
+ "tue_flags", "2",
+ "tue_h", "6",
+ "tue_m", "30",
+ "wed_flags", "2",
+ "wed_h", "6",
+ "wed_m", "30",
+ "thu_flags", "2",
+ "thu_h", "6",
+ "thu_m", "30",
+ "fri_flags", "2",
+ "fri_h", "6",
+ "fri_m", "30",
+ "sat_flags", "2",
+ "sat_h", "6",
+ "sat_m", "30",
+ nullptr};
+
+typedef struct
+{
+    pthread_t tid;
+    volatile gboolean  is_valid;
+} alarm_thread_t;
+
+static int timeout_source;
+static time_t play_start;
+
+static alarm_thread_t stop;     /* thread id of stop loop */
+static pthread_mutex_t fader_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* string tokens to allow loops and shorten code */
+static char day_cb[7][7] = {"sun_cb", "mon_cb", "tue_cb",
+                            "wed_cb", "thu_cb", "fri_cb", "sat_cb"};
+
+static char day_flags[7][10] = {"sun_flags", "mon_flags", "tue_flags",
+                                "wed_flags", "thu_flags", "fri_flags", "sat_flags"};
+
+static char day_h[7][6] = {"sun_h", "mon_h", "tue_h",
+                           "wed_h", "thu_h", "fri_h", "sat_h"};
+
+static char day_m[7][6] = {"sun_m", "mon_m", "tue_m",
+                           "wed_m", "thu_m", "fri_m", "sat_m"};
+
+static char day_def[7][8] = {"sun_def", "mon_def", "tue_def",
+                             "wed_def", "thu_def", "fri_def", "sat_def"};
+
+static struct
+{
+    GtkSpinButton *alarm_h;
+    GtkSpinButton *alarm_m;
+
+    GtkToggleButton *stop_on;
+    GtkSpinButton *stop_h;
+    GtkSpinButton *stop_m;
+
+    GtkRange *volume;
+    GtkRange *quietvol;
+
+    GtkSpinButton *fading;
+
+    GtkEntry *cmdstr;
+    GtkToggleButton *cmd_on;
+
+    GtkEntry *playlist;
+
+    int default_hour;
+    int default_min;
+
+    // array allows looping of days
+    alarmday day[7];
+
+
+    GtkEntry *reminder;
+    GtkToggleButton *reminder_cb;
+    gboolean reminder_on;
+}
+alarm_conf;
+
+static int alarm_h, alarm_m;
+
+static gboolean stop_on;
+static int stop_h, stop_m;
+
+static int volume, quietvol;
+
+static int fading;
+
+static gboolean cmd_on;
+
+static GtkWidget *config_notebook = nullptr;
+static GtkWidget *alarm_dialog = nullptr;
+
+static GtkWidget *lookup_widget(GtkWidget *w, const char *name)
+{
+    GtkWidget * widget = (GtkWidget *) g_object_get_data ((GObject *) w, name);
+    g_return_val_if_fail(widget != nullptr, nullptr);
+
+    return widget;
+}
+
+/*
+ * the callback function that is called when the save button is
+ * pressed saves configuration to ~/.bmp/alarmconfig
+ */
+static void alarm_save(void)
+{
+    int daynum = 0;  // used to identify day number
+
+    /*
+     * update the live values and write them out
+     */
+    alarm_h = alarm_conf.default_hour = gtk_spin_button_get_value_as_int (alarm_conf.alarm_h);
+    aud_set_int ("alarm", "alarm_h", alarm_h);
+
+    alarm_m = alarm_conf.default_min = gtk_spin_button_get_value_as_int (alarm_conf.alarm_m);
+    aud_set_int ("alarm", "alarm_m", alarm_m);
+
+    stop_h = gtk_spin_button_get_value_as_int (alarm_conf.stop_h);
+    stop_m = gtk_spin_button_get_value_as_int (alarm_conf.stop_m);
+    stop_on = gtk_toggle_button_get_active (alarm_conf.stop_on);
+
+    /* days of the week */
+    for(; daynum < 7; daynum++)
+    {
+        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb)))
+            alarm_conf.day[daynum].flags = 0;
+        else
+            alarm_conf.day[daynum].flags = ALARM_OFF;
+
+        if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def)))
+            alarm_conf.day[daynum].flags |= ALARM_DEFAULT;
+
+        alarm_conf.day[daynum].hour =
+         gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_hr);
+        alarm_conf.day[daynum].min =
+         gtk_spin_button_get_value_as_int(alarm_conf.day[daynum].spin_min);
+
+        aud_set_int ("alarm", day_flags[daynum], alarm_conf.day[daynum].flags);
+        aud_set_int ("alarm", day_h[daynum], alarm_conf.day[daynum].hour);
+        aud_set_int ("alarm", day_m[daynum], alarm_conf.day[daynum].min);
+    }
+
+    /* END: days of week */
+
+    volume = gtk_range_get_value (alarm_conf.volume);
+    aud_set_int ("alarm", "volume", volume);
+
+    quietvol = gtk_range_get_value (alarm_conf.quietvol);
+    aud_set_int ("alarm", "quietvol", quietvol);
+
+    fading = gtk_spin_button_get_value_as_int (alarm_conf.fading);
+
+    /* write the new values */
+    aud_set_int ("alarm", "stop_h", stop_h);
+    aud_set_int ("alarm", "stop_m", stop_m);
+    aud_set_int ("alarm", "fading", fading);
+    aud_set_bool ("alarm", "stop_on", stop_on);
+
+    char * cmdstr = gtk_editable_get_chars ((GtkEditable *) alarm_conf.cmdstr, 0, -1);
+    aud_set_str ("alarm", "cmdstr", cmdstr);
+    g_free (cmdstr);
+
+    cmd_on = gtk_toggle_button_get_active (alarm_conf.cmd_on);
+    aud_set_bool ("alarm", "cmd_on", cmd_on);
+
+    char * playlist = gtk_editable_get_chars ((GtkEditable *) alarm_conf.playlist, 0, -1);
+    aud_set_str ("alarm", "playlist", playlist);
+    g_free (playlist);
+
+    /* reminder */
+    char * reminder_msg = gtk_editable_get_chars ((GtkEditable *) alarm_conf.reminder, 0, -1);
+    aud_set_str ("alarm", "reminder_msg", reminder_msg);
+    g_free (reminder_msg);
+
+    alarm_conf.reminder_on = gtk_toggle_button_get_active (alarm_conf.reminder_cb);
+    aud_set_bool ("alarm", "reminder_on", alarm_conf.reminder_on);
+}
+
+/*
+ * read the current configuration from the file
+ */
+static void alarm_read_config(void)
+{
+    int daynum = 0;   // used for day number
+
+    alarm_h = aud_get_int ("alarm", "alarm_h");
+    alarm_m = aud_get_int ("alarm", "alarm_m");
+
+    /* save them here too */
+    alarm_conf.default_hour = alarm_h;
+    alarm_conf.default_min = alarm_m;
+
+    stop_h = aud_get_int ("alarm", "stop_h");
+    stop_m = aud_get_int ("alarm", "stop_m");
+    stop_on = aud_get_bool ("alarm", "stop_on");
+
+    volume = aud_get_int ("alarm", "volume");
+    quietvol = aud_get_int ("alarm", "quietvol");
+
+    fading = aud_get_int ("alarm", "fading");
+
+    cmd_on = aud_get_bool ("alarm", "cmd_on");
+
+    alarm_conf.reminder_on = aud_get_bool ("alarm", "reminder_on");
+
+    /* day flags and times */
+    for(; daynum < 7; daynum++)
+    {
+        /* read the flags */
+        alarm_conf.day[daynum].flags = aud_get_int ("alarm", day_flags[daynum]);
+
+        /* read the times */
+        alarm_conf.day[daynum].hour = aud_get_int ("alarm", day_h[daynum]);
+        alarm_conf.day[daynum].min = aud_get_int ("alarm", day_m[daynum]);
+    }
+}
+
+/*
+ * displays the configuration window and opens the config file.
+ */
+static void *alarm_make_config_widget(void)
+{
+    int daynum = 0;  // used to loop days
+    GtkWidget *w;
+
+    alarm_read_config();
+
+    /*
+     * Create the widgets
+     */
+    config_notebook = create_config_notebook();
+
+    w = lookup_widget(config_notebook, "alarm_h_spin");
+    alarm_conf.alarm_h = GTK_SPIN_BUTTON(w);
+    gtk_spin_button_set_value(alarm_conf.alarm_h, alarm_h);
+
+    w = lookup_widget(config_notebook, "alarm_m_spin");
+    alarm_conf.alarm_m =  GTK_SPIN_BUTTON(w);
+    gtk_spin_button_set_value(alarm_conf.alarm_m, alarm_m);
+
+    w = lookup_widget(config_notebook, "stop_h_spin");
+    alarm_conf.stop_h = GTK_SPIN_BUTTON(w);
+    gtk_spin_button_set_value(alarm_conf.stop_h, stop_h);
+
+    w = lookup_widget(config_notebook, "stop_m_spin");
+    alarm_conf.stop_m = GTK_SPIN_BUTTON(w);
+    gtk_spin_button_set_value(alarm_conf.stop_m, stop_m);
+
+    w = lookup_widget(config_notebook, "stop_checkb");
+    alarm_conf.stop_on = GTK_TOGGLE_BUTTON(w);
+    gtk_toggle_button_set_active(alarm_conf.stop_on, stop_on);
+
+    w = lookup_widget(config_notebook, "vol_scale");
+    alarm_conf.volume = GTK_RANGE(w);
+    gtk_range_set_adjustment(alarm_conf.volume,
+     GTK_ADJUSTMENT(gtk_adjustment_new(volume, 0, 100, 1, 5, 0)));
+
+    w = lookup_widget(config_notebook, "quiet_vol_scale");
+    alarm_conf.quietvol = GTK_RANGE(w);
+    gtk_range_set_adjustment(alarm_conf.quietvol,
+     GTK_ADJUSTMENT(gtk_adjustment_new(quietvol, 0, 100, 1, 5, 0)));
+
+    /* days of week */
+    for(; daynum < 7; daynum++)
+    {
+        w = lookup_widget(config_notebook, day_cb[daynum]);
+        alarm_conf.day[daynum].cb = GTK_CHECK_BUTTON(w);
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb),
+         !(alarm_conf.day[daynum].flags & ALARM_OFF));
+
+        w = lookup_widget(config_notebook, day_def[daynum]);
+        alarm_conf.day[daynum].cb_def = GTK_CHECK_BUTTON(w);
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(alarm_conf.day[daynum].cb_def),
+         alarm_conf.day[daynum].flags & ALARM_DEFAULT);
+
+
+        /* Changed to show default time instead of set time when ALARM_DEFAULT set,
+         * as suggested by Mark Brown
+         */
+/*      w = lookup_widget(config_dialog, day_h[daynum]);
+        alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
+        gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.day[daynum].hour);
+
+        w = lookup_widget(config_dialog, day_m[daynum]);
+        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);
+*/
+        if(alarm_conf.day[daynum].flags & ALARM_DEFAULT)
+        {
+            w = lookup_widget(config_notebook, day_h[daynum]);
+            alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
+            gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.default_hour);
+
+            w = lookup_widget(config_notebook, day_m[daynum]);
+            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);
+        }
+        else
+        {
+            w = lookup_widget(config_notebook, day_h[daynum]);
+            alarm_conf.day[daynum].spin_hr = GTK_SPIN_BUTTON(w);
+            gtk_spin_button_set_value(alarm_conf.day[daynum].spin_hr, alarm_conf.day[daynum].hour);
+
+            w = lookup_widget(config_notebook, day_m[daynum]);
+            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);
+        }
+    }
+
+   /* END: days of week */
+
+    w = lookup_widget(config_notebook,"fading_spin");
+    alarm_conf.fading = GTK_SPIN_BUTTON(w);
+    gtk_spin_button_set_value(alarm_conf.fading, fading);
+
+    String cmdstr = aud_get_str ("alarm", "cmdstr");
+    w = lookup_widget(config_notebook, "cmd_entry");
+    alarm_conf.cmdstr = GTK_ENTRY(w);
+    gtk_entry_set_text(alarm_conf.cmdstr, cmdstr);
+
+    w = lookup_widget(config_notebook, "cmd_checkb");
+    alarm_conf.cmd_on = GTK_TOGGLE_BUTTON(w);
+    gtk_toggle_button_set_active(alarm_conf.cmd_on, cmd_on);
+
+    String playlist = aud_get_str ("alarm", "playlist");
+    w = lookup_widget(config_notebook, "playlist");
+    alarm_conf.playlist = GTK_ENTRY(w);
+    gtk_entry_set_text(alarm_conf.playlist, playlist);
+
+    String reminder_msg = aud_get_str ("alarm", "reminder_msg");
+    w = lookup_widget(config_notebook, "reminder_text");
+    alarm_conf.reminder = GTK_ENTRY(w);
+    gtk_entry_set_text(alarm_conf.reminder, reminder_msg);
+
+    w = lookup_widget(config_notebook, "reminder_cb");
+    alarm_conf.reminder_cb = GTK_TOGGLE_BUTTON(w);
+    gtk_toggle_button_set_active(alarm_conf.reminder_cb, alarm_conf.reminder_on);
+
+    AUDDBG("END alarm_configure\n");
+
+    return config_notebook;
+}
+
+/* functions for greying out the time for days */
+static void on_day_def_toggled(GtkToggleButton *togglebutton, void * user_data, int daynum)
+{
+    GtkWidget *w;
+
+    /* change the time shown too */
+    w = lookup_widget(config_notebook, day_h[daynum]);
+    if(w == nullptr)
+        return;
+
+    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);
+    }
+    else
+    {
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].hour);
+        gtk_widget_set_sensitive(w, TRUE);
+    }
+
+    w = lookup_widget(config_notebook, day_m[daynum]);
+    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);
+    }
+    else
+    {
+        gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].min);
+        gtk_widget_set_sensitive(w, TRUE);
+    }
+}
+
+void on_sun_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 0);
+}
+
+void on_mon_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 1);
+}
+
+void on_tue_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 2);
+}
+
+void on_wed_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 3);
+}
+
+void on_thu_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 4);
+}
+
+void on_fri_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 5);
+}
+
+void on_sat_def_toggled(GtkToggleButton *togglebutton, void * user_data)
+{
+    on_day_def_toggled(togglebutton, user_data, 6);
+}
+
+/* END: greying things */
+
+void alarm_current_volume(GtkButton *button, void * data)
+{
+    GtkAdjustment *adj;
+
+    AUDDBG("on_current_button_clicked\n");
+
+    adj = gtk_range_get_adjustment(alarm_conf.volume);
+    gtk_adjustment_set_value(adj, aud_drct_get_volume_main());
+}
+
+/*
+ * a thread safe sleeping function -
+ * and it even works in solaris (I think)
+ */
+static void threadsleep(float x)
+{
+    AUDDBG("threadsleep: waiting %f seconds\n", x);
+
+    g_usleep((int) ((float) x * (float) 1000000.0));
+
+    return;
+}
+
+static inline alarm_thread_t alarm_thread_create(void *(*start_routine)(void *), void *args, unsigned int detach)
+{
+    alarm_thread_t thrd;
+    pthread_attr_t attr;
+
+    pthread_attr_init(&attr);
+
+    if(detach != 0)
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
+    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+
+    thrd.is_valid = (pthread_create(&thrd.tid, &attr, start_routine, args) == 0);
+
+    return thrd;
+}
+
+static void *alarm_fade(void *arg)
+{
+    fader *vols = (fader *)arg;
+    int inc, diff, adiff;
+
+    /* lock */
+    pthread_mutex_lock(&fader_lock);
+
+    /* slide volume */
+    /* the Kaspar Giger way of fading, check the current mixer volume and
+     * increment from there so that if you have some other app lowering the
+     * volume at the same time, the alarm plugin will not ignore it.  If you have
+     * some other app increasing the volume, then it could get louder than you expect
+     * though - because the loop does not recalculate the difference each time.
+     */
+
+    /* difference between the 2 volumes */
+    diff = vols->end - vols->start;
+    adiff = abs(diff);
+
+    /* Are we going up or down? */
+    if(diff < 0)
+        inc = -1;
+    else
+        inc = 1;
+
+    aud_drct_set_volume_main((int)vols->start);
+
+    for (int i = 0; i < adiff; i ++)
+    {
+        threadsleep((float)fading / (float)adiff);
+        aud_drct_set_volume_main(aud_drct_get_volume_main() + inc);
+    }
+    /* Setting the volume to the end volume sort of defeats the point if having
+     * the code in there to allow other apps to control volume too :)
+     */
+    //aud_drct_set_volume_main((int)vols->end);
+
+    /* and */
+    pthread_mutex_unlock(&fader_lock);
+
+    AUDDBG("volume = %f%%\n", (double)vols->end);
+    return 0;
+}
+
+static void *alarm_stop_thread(void *args)
+{
+    int currvol;
+    fader fade_vols;
+    alarm_thread_t f;
+
+    AUDDBG("alarm_stop_thread\n");
+
+
+    /* sleep for however long we are meant to be sleeping for until
+     * its time to shut up
+     */
+    threadsleep(((stop_h * 60) + stop_m) * 60);
+
+    AUDDBG("alarm_stop triggered\n");
+
+    if (alarm_dialog)
+        gtk_widget_destroy(alarm_dialog);
+
+    currvol = aud_drct_get_volume_main(),
+
+    /* fade back to zero */
+    fade_vols.start = currvol;
+    fade_vols.end = 0;
+
+    /* The fader thread locks the fader_mutex now */
+    f = alarm_thread_create(alarm_fade, &fade_vols, 0);
+
+    pthread_join(f.tid, nullptr);
+    aud_drct_stop();
+
+    /* might as well set the volume to something higher than zero so we
+     * dont confuse the poor people who just woke up and cant work out why
+     * theres no music playing when they press the little play button :)
+     */
+    aud_drct_set_volume_main(currvol);
+
+    AUDDBG("alarm_stop done\n");
+    return(nullptr);
+}
+
+void alarm_stop_cancel(GtkWidget *w, void * data)
+{
+    AUDDBG("alarm_stop_cancel\n");
+    if (pthread_cancel(stop.tid) == 0)
+        stop.is_valid = FALSE;
+}
+
+/* the main alarm thread */
+static gboolean alarm_timeout (void * unused)
+{
+    struct tm *currtime;
+    time_t timenow;
+    unsigned today;
+
+    AUDDBG("Getting time\n");
+    timenow = time(nullptr);
+    currtime = localtime(&timenow);
+    today = currtime->tm_wday;
+    AUDDBG("Today is %d\n", today);
+
+    /* already went off? */
+    if (timenow < play_start + 60)
+        return TRUE;
+
+    if(alarm_conf.day[today].flags & ALARM_OFF)
+        return TRUE;
+    else
+    {
+        /* set the alarm_h and alarm_m for today, if not default */
+        if(!(alarm_conf.day[today].flags & ALARM_DEFAULT))
+        {
+            alarm_h = alarm_conf.day[today].hour;
+            alarm_m = alarm_conf.day[today].min;
+        }
+        else
+        {
+            alarm_h = alarm_conf.default_hour;
+            alarm_m = alarm_conf.default_min;
+        }
+    }
+
+    AUDDBG("Alarm time is %d:%d (def: %d:%d)\n", alarm_h, alarm_m,
+    alarm_conf.default_hour, alarm_conf.default_min);
+
+    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;
+
+    if(cmd_on == TRUE)
+    {
+        String cmdstr = aud_get_str ("alarm", "cmdstr");
+        AUDDBG("Executing %s, cmd_on is true\n", (const char *) cmdstr);
+        if(system(cmdstr) == -1)
+            AUDDBG("Executing %s failed\n", (const char *) cmdstr);
+    }
+
+    gboolean started = FALSE;
+
+    String playlist = aud_get_str ("alarm", "playlist");
+    if (playlist[0])
+    {
+        aud_drct_pl_open (playlist);
+        started = TRUE;
+    }
+
+    if(fading)
+    {
+        fader fade_vols;
+
+        AUDDBG("Fading is true\n");
+        aud_drct_set_volume_main(quietvol);
+
+        /* start playing */
+        play_start = time(nullptr);
+
+        if (! started)
+            aud_drct_play ();
+
+        /* fade volume */
+        fade_vols.start = quietvol;
+        fade_vols.end = volume;
+
+        //alarm_fade(quietvol, volume);
+        alarm_thread_create(alarm_fade, &fade_vols, 0);
+    }
+    else
+    {
+        /* no fading */
+
+        /* set volume */
+        aud_drct_set_volume_main(volume);
+
+        /* start playing */
+        play_start = time(nullptr);
+        aud_drct_play();
+    }
+
+    if(alarm_conf.reminder_on == TRUE)
+    {
+        String reminder_msg = aud_get_str ("alarm", "reminder_msg");
+        GtkWidget *reminder_dialog;
+        AUDDBG("Showing reminder '%s'\n", (const char *) reminder_msg);
+
+        reminder_dialog = (GtkWidget*) create_reminder_dialog(reminder_msg);
+        gtk_widget_show_all(reminder_dialog);
+    }
+
+    /* bring up the wakeup call dialog if stop_on is set TRUE, this
+     * has been moved to after making Audacious play so that it doesnt
+     * get in the way for people with manual window placement turned on
+     *
+     * 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)
+    {
+        alarm_dialog = create_alarm_dialog();
+
+        AUDDBG("now starting stop thread\n");
+        stop = alarm_thread_create(alarm_stop_thread, nullptr, 0);
+        AUDDBG("Created wakeup dialog and started stop thread\n");
+    }
+
+    return TRUE;
+}
+
+static void alarm_configure ()
+{
+    audgui_show_plugin_prefs (aud_plugin_by_header (& aud_plugin_instance));
+}
+
+/*
+ * initialization
+ * opens the config file and reads the value, creates a new
+ * config in memory if the file doesnt exist and sets default vals
+ */
+bool AlarmPlugin::init ()
+{
+    AUDDBG("alarm_init\n");
+
+    aud_config_set_defaults ("alarm", defaults);
+
+    alarm_read_config();
+
+    timeout_source = g_timeout_add_seconds (10, alarm_timeout, nullptr);
+
+    aud_plugin_menu_add (AudMenuID::Main, alarm_configure, _("Set Alarm ..."), "appointment-new");
+
+    return true;
+}
+
+/*
+ * kill the main thread
+ */
+void AlarmPlugin::cleanup ()
+{
+    AUDDBG("alarm_cleanup\n");
+
+    aud_plugin_menu_remove (AudMenuID::Main, alarm_configure);
+
+    if (timeout_source)
+    {
+        g_source_remove (timeout_source);
+        timeout_source = 0;
+    }
+
+    if (stop.is_valid)
+    {
+        pthread_cancel(stop.tid);
+        stop.is_valid = FALSE;
+    }
+}
+
+const char AlarmPlugin::about[] =
+ N_("A plugin that can be used to start playing at a certain time.\n\n"
+    "Originally written by Adam Feakin and Daniel Stodden.");
+
+const PreferencesWidget AlarmPlugin::widgets[] = {
+    WidgetCustomGTK (alarm_make_config_widget)
+};
+
+const PluginPreferences AlarmPlugin::prefs = {
+    {widgets},
+    nullptr,  // init
+    alarm_save,
+    nullptr  // cleanup
+};
diff --git a/src/alarm/alarm.h b/src/alarm/alarm.h
index 2bd08c98e855..cbfd5fd70b73 100644
--- a/src/alarm/alarm.h
+++ b/src/alarm/alarm.h
@@ -28,7 +28,7 @@ typedef struct AlarmDay {
 
 
 typedef struct Fader {
-  guint start, end;
+  unsigned start, end;
 } fader;
 
 
diff --git a/src/alarm/callbacks.h b/src/alarm/callbacks.h
index 44eae137d766..823bb8d1277b 100644
--- a/src/alarm/callbacks.h
+++ b/src/alarm/callbacks.h
@@ -3,24 +3,22 @@
 
 #include <gtk/gtk.h>
 
-void alarm_save (void);
+void alarm_current_volume (GtkButton *button, void * data);
 
-void alarm_current_volume (GtkButton *button, gpointer data);
+void alarm_stop_cancel (GtkWidget *widget, void * data);
 
-void alarm_stop_cancel (GtkWidget *widget, gpointer data);
+void on_mon_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_mon_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_tue_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_tue_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_wed_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_wed_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_thu_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_thu_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_fri_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_fri_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_sat_def_toggled (GtkToggleButton *togglebutton, void * data);
 
-void on_sat_def_toggled (GtkToggleButton *togglebutton, gpointer data);
-
-void on_sun_def_toggled (GtkToggleButton *togglebutton, gpointer data);
+void on_sun_def_toggled (GtkToggleButton *togglebutton, void * data);
 
 #endif
diff --git a/src/alarm/interface.c b/src/alarm/interface.c
deleted file mode 100644
index 897131ed65c2..000000000000
--- a/src/alarm/interface.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * interface.c
- * Copyright 2012 Thomas Lange
- *
- * 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 <gtk/gtk.h>
-#include <audacious/i18n.h>
-#include <libaudgui/libaudgui.h>
-
-#include "callbacks.h"
-
-#if GTK_CHECK_VERSION (3, 12, 0)
-    #define gtk_widget_set_margin_right(w, m) gtk_widget_set_margin_end(w, m)
-#endif
-
-const gchar *help[] =
-{
-   N_("Time\n"
-    "  Alarm at:\n"
-    "    The time for the alarm to come on.\n\n"
-
-    "  Quiet after:\n"
-    "    Stop alarm after this amount of time.\n"
-    "       (if the wakeup dialog is not closed)\n\n\n"
-
-    "Days\n"
-    "  Day:\n"
-    "    Select the days for the alarm to activate.\n\n"
-
-    "  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"),
-
-   N_("Volume\n"
-    "  Fading:\n"
-    "    Fade the volume up to the chosen volume\n"
-    "    for this amount of time.\n\n"
-
-    "  Start at:\n"
-    "    Start fading from this volume.\n\n"
-
-    "  Final:\n"
-    "    The volume to stop fading at.  If the fading\n"
-    "    time is 0 then set volume to this and start\n"
-    "    playing.\n\n\n"
-
-    "Options:\n"
-    "  Additional Command:\n"
-    "    Run this command at the alarm time.\n\n"),
-
-   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"
-    "    can also be entered here.\n\n"
-
-    "  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."),
-
-    NULL
-};
-
-GtkWidget *create_alarm_dialog (void)
-{
-    GtkWidget *alarm_dialog;
-
-    alarm_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
-     GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("This is your wakeup call."));
-    gtk_window_set_title (GTK_WINDOW (alarm_dialog), _("Alarm"));
-
-    g_signal_connect (alarm_dialog, "response",
-     G_CALLBACK (alarm_stop_cancel), NULL);
-    g_signal_connect_swapped (alarm_dialog, "response",
-     G_CALLBACK (gtk_widget_destroy), alarm_dialog);
-
-    gtk_widget_show_all (alarm_dialog);
-
-    return alarm_dialog;
-}
-
-GtkWidget *create_reminder_dialog (const gchar *reminder_msg)
-{
-    GtkWidget *reminder_dialog;
-
-    reminder_dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
-     GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("Your reminder for today is..."));
-    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (reminder_dialog), "%s", reminder_msg);
-    gtk_window_set_title (GTK_WINDOW (reminder_dialog), _("Reminder"));
-
-    g_signal_connect_swapped (reminder_dialog, "response",
-     G_CALLBACK (gtk_widget_destroy), reminder_dialog);
-
-    return reminder_dialog;
-}
-
-static void file_set_cb (GtkFileChooserButton *button, gpointer entry)
-{
-    gchar *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (button));
-    gtk_entry_set_text (GTK_ENTRY (entry), uri);
-    g_free (uri);
-}
-
-static void config_dialog_response (GtkWidget *dialog, gint response)
-{
-    if (response == GTK_RESPONSE_OK)
-        alarm_save ();
-
-    gtk_widget_destroy (dialog);
-}
-
-GtkWidget *create_config_dialog (void)
-{
-    /* General */
-    GtkWidget *config_dialog, *content_area, *notebook;
-    GtkWidget *vbox, *hbox, *label, *frame, *grid;
-    GtkAdjustment *adjustment;
-
-    /* Page 1 */
-    GtkWidget *alarm_h_spin, *alarm_m_spin;
-    GtkWidget *stop_checkb, *stop_h_spin, *stop_m_spin;
-
-    /* Page 2 */
-    gint i, j;
-    GtkWidget *checkbutton;
-    GtkWidget *widget[21];
-
-    const gchar *weekdays[] = { _("Monday"), _("Tuesday"), _("Wednesday"),
-                                _("Thursday"), _("Friday"), _("Saturday"), _("Sunday") };
-
-    const gchar *day_cb[] = { "mon_cb", "tue_cb", "wed_cb", "thu_cb",
-                              "fri_cb", "sat_cb", "sun_cb" };
-
-    const gchar *day_def[] = { "mon_def", "tue_def", "wed_def", "thu_def",
-                               "fri_def", "sat_def", "sun_def", };
-
-    const gchar *day_h[] = { "mon_h", "tue_h", "wed_h", "thu_h",
-                             "fri_h", "sat_h", "sun_h" };
-
-    const gchar *day_m[] = { "mon_m", "tue_m", "wed_m", "thu_m",
-                             "fri_m", "sat_m", "sun_m" };
-
-    const GCallback cb_def[] = { G_CALLBACK (on_mon_def_toggled), G_CALLBACK (on_tue_def_toggled),
-                                 G_CALLBACK (on_wed_def_toggled), G_CALLBACK (on_thu_def_toggled),
-                                 G_CALLBACK (on_fri_def_toggled), G_CALLBACK (on_sat_def_toggled),
-                                 G_CALLBACK (on_sun_def_toggled) };
-
-    /* Page 3 */
-    GtkWidget *vbox2, *hbox2;
-    GtkWidget *fading_spin, *quiet_vol_scale, *vol_scale, *separator, *current_button;
-
-    /* Page 4 */
-    GtkWidget  *cmd_entry, *playlist_entry, *reminder_text;
-    GtkWidget *cmd_checkb, *reminder_checkb, *file_chooser_button;
-
-    /* Page 5 */
-    GtkWidget *view, *scrolled_window;
-    GtkTextBuffer *text_buffer;
-    gchar *help_text;
-
-
-    /* General */
-    config_dialog = gtk_dialog_new_with_buttons (_("Alarm Settings"), NULL, 0,
-     _("_OK"), GTK_RESPONSE_OK, _("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
-    gtk_dialog_set_default_response (GTK_DIALOG (config_dialog), GTK_RESPONSE_OK);
-    content_area = gtk_dialog_get_content_area (GTK_DIALOG (config_dialog));
-    notebook = gtk_notebook_new ();
-    gtk_box_pack_start (GTK_BOX (content_area), notebook, TRUE, TRUE, 0);
-
-
-    /* Page 1 */
-    frame = gtk_frame_new (_("Time"));
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    grid = gtk_grid_new ();
-    gtk_grid_set_column_spacing (GTK_GRID (grid), 3);
-    gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
-    gtk_container_set_border_width (GTK_CONTAINER (grid), 5);
-
-    label = gtk_label_new (_("Alarm at (default):"));
-    gtk_widget_set_margin_right (label, 10);
-    gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-    adjustment = gtk_adjustment_new (6, 0, 23, 1, 10, 0);
-    alarm_h_spin = gtk_spin_button_new (adjustment, 1, 0);
-    g_object_set_data (G_OBJECT (config_dialog), "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_grid_attach (GTK_GRID (grid), alarm_h_spin, 1, 0, 1, 1);
-
-    label = gtk_label_new (":");
-    gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
-
-    adjustment = gtk_adjustment_new (30, 0, 59, 1, 10, 0);
-    alarm_m_spin = gtk_spin_button_new (adjustment, 1, 0);
-    g_object_set_data (G_OBJECT (config_dialog), "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_grid_attach (GTK_GRID (grid), alarm_m_spin, 3, 0, 1, 1);
-
-    label = gtk_label_new (_("h"));
-    gtk_widget_set_halign (label, GTK_ALIGN_START);
-    gtk_grid_attach (GTK_GRID (grid), label, 4, 0, 1, 1);
-
-    stop_checkb = gtk_check_button_new_with_label (_("Quiet after:"));
-    g_object_set_data (G_OBJECT (config_dialog), "stop_checkb", stop_checkb);
-    gtk_widget_set_margin_right (stop_checkb, 10);
-    gtk_widget_set_valign (stop_checkb, GTK_ALIGN_CENTER);
-    gtk_grid_attach (GTK_GRID (grid), stop_checkb, 0, 1, 1, 1);
-
-    adjustment = gtk_adjustment_new (0, 0, 100, 1, 10, 0);
-    stop_h_spin = gtk_spin_button_new (adjustment, 1, 0);
-    g_object_set_data (G_OBJECT (config_dialog), "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_grid_attach (GTK_GRID (grid), stop_h_spin, 1, 1, 1, 1);
-
-    label = gtk_label_new (_("hours"));
-    gtk_widget_set_margin_right (label, 10);
-    gtk_grid_attach (GTK_GRID (grid), label, 2, 1, 1, 1);
-
-    adjustment = gtk_adjustment_new (0, 0, 59, 1, 10, 0);
-    stop_m_spin = gtk_spin_button_new (adjustment, 1, 0);
-    g_object_set_data (G_OBJECT (config_dialog), "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_grid_attach (GTK_GRID (grid), stop_m_spin, 3, 1, 1, 1);
-
-    label = gtk_label_new (_("minutes"));
-    gtk_grid_attach (GTK_GRID (grid), label, 4, 1, 1, 1);
-    gtk_container_add (GTK_CONTAINER (frame), grid);
-
-    label = gtk_label_new (_("Time"));
-    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
-
-
-    /* Page 2 */
-    frame = gtk_frame_new (_("Choose the days for the alarm to come on"));
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    grid = gtk_grid_new ();
-    gtk_grid_set_column_spacing (GTK_GRID (grid), 15);
-    gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
-    gtk_container_set_border_width (GTK_CONTAINER (grid), 5);
-
-    label = gtk_label_new (_("Day"));
-    gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-    label = gtk_label_new (_("Time"));
-    gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 3, 1);
-
-    for (i = 0; i < 7; i ++)
-    {
-        widget[i] = gtk_check_button_new_with_label (weekdays[i]);
-        g_object_set_data (G_OBJECT (config_dialog), day_cb[i], widget[i]);
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget[i]), TRUE);
-        gtk_widget_set_valign (widget[i], GTK_ALIGN_CENTER);
-        gtk_grid_attach (GTK_GRID (grid), widget[i], 0, i + 1, 1, 1);
-    }
-    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 (config_dialog), day_def[i], checkbutton);
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), TRUE);
-        gtk_widget_set_valign (checkbutton, GTK_ALIGN_CENTER);
-        g_signal_connect (checkbutton, "toggled", G_CALLBACK (cb_def[i]), NULL);
-        gtk_grid_attach (GTK_GRID (grid), checkbutton, 1, i + 1, 1, 1);
-    }
-
-    for (i = 7, j = 0; i < 14; i ++, j ++)
-    {
-        adjustment = gtk_adjustment_new (6, 0, 23, 1, 10, 0);
-        widget[i] = gtk_spin_button_new (adjustment, 1, 0);
-        g_object_set_data (G_OBJECT (config_dialog), day_h[j], widget[i]);
-        gtk_grid_attach (GTK_GRID (grid), widget[i], 2, j + 1, 1, 1);
-    }
-
-    for (i = 0; i < 7; i ++)
-    {
-        label = gtk_label_new (":");
-        gtk_grid_attach (GTK_GRID (grid), label, 3, i + 1, 1, 1);
-    }
-
-    for (i = 14, j = 0; i < 21; i ++, j ++)
-    {
-        adjustment = gtk_adjustment_new (30, 0, 59, 1, 10, 0);
-        widget[i] = gtk_spin_button_new (adjustment, 1, 0);
-        g_object_set_data (G_OBJECT (config_dialog), day_m[j], widget[i]);
-        gtk_grid_attach (GTK_GRID (grid), widget[i], 4, j + 1, 1, 1);
-    }
-
-    label = gtk_label_new (_("Days"));
-    gtk_container_add (GTK_CONTAINER (frame), grid);
-    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
-
-
-    /* Page 3 */
-    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
-    frame = gtk_frame_new (_("Fading"));
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
-    adjustment = gtk_adjustment_new (120, 0, 3600, 1, 10, 0);
-    fading_spin = gtk_spin_button_new (adjustment, 1, 0);
-    g_object_set_data (G_OBJECT (config_dialog), "fading_spin", fading_spin);
-    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_container_add (GTK_CONTAINER (hbox), fading_spin);
-    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 3);
-    gtk_container_add (GTK_CONTAINER (frame), hbox);
-    gtk_container_add (GTK_CONTAINER (vbox), frame);
-
-    frame = gtk_frame_new (_("Volume"));
-    vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox2), 8);
-
-    label = gtk_label_new (_("Start at"));
-    gtk_widget_set_margin_bottom (label, 2);
-    gtk_widget_set_halign (label, GTK_ALIGN_START);
-    gtk_container_add (GTK_CONTAINER (vbox2), label);
-
-    quiet_vol_scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, gtk_adjustment_new (20, 0, 100, 1, 5, 0));
-    g_object_set_data (G_OBJECT (config_dialog), "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_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
-    gtk_box_pack_start (GTK_BOX (hbox2), quiet_vol_scale, TRUE, TRUE, 0);
-    gtk_container_add (GTK_CONTAINER (hbox2), label);
-    gtk_container_add (GTK_CONTAINER (vbox2), hbox2);
-
-    separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
-    gtk_box_pack_start (GTK_BOX (vbox2), separator, FALSE, FALSE, 10);
-
-    label = gtk_label_new (_("Final"));
-    gtk_widget_set_margin_bottom (label, 2);
-    gtk_widget_set_halign (label, GTK_ALIGN_START);
-    gtk_container_add (GTK_CONTAINER (vbox2), label);
-
-    vol_scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, gtk_adjustment_new (80, 0, 100, 1, 5, 0));
-    g_object_set_data (G_OBJECT (config_dialog), "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_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
-    gtk_box_pack_start (GTK_BOX (hbox2), vol_scale, TRUE, TRUE, 0);
-    gtk_container_add (GTK_CONTAINER (hbox2), label);
-    gtk_container_add (GTK_CONTAINER (vbox2), hbox2);
-
-    current_button = gtk_button_new_with_label (_("Current"));
-    gtk_widget_set_margin_top (current_button, 10);
-    gtk_widget_set_halign (current_button, GTK_ALIGN_END);
-    g_signal_connect (current_button, "clicked", G_CALLBACK (alarm_current_volume), NULL);
-    gtk_container_add (GTK_CONTAINER (vbox2), current_button);
-
-    gtk_container_add (GTK_CONTAINER (frame), vbox2);
-    gtk_container_add (GTK_CONTAINER (vbox), frame);
-
-    label = gtk_label_new (_("Volume"));
-    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
-
-
-    /* Page 4 */
-    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-    frame = gtk_frame_new (_("Additional Command"));
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
-    cmd_entry = gtk_entry_new ();
-    g_object_set_data (G_OBJECT (config_dialog), "cmd_entry", cmd_entry);
-    cmd_checkb = gtk_check_button_new_with_label (_("enable"));
-    g_object_set_data (G_OBJECT (config_dialog), "cmd_checkb", cmd_checkb);
-    gtk_box_pack_start (GTK_BOX (hbox), cmd_entry, TRUE, TRUE, 0);
-    gtk_container_add (GTK_CONTAINER (hbox), cmd_checkb);
-    gtk_container_add (GTK_CONTAINER (frame), hbox);
-    gtk_container_add (GTK_CONTAINER (vbox), frame);
-
-    frame = gtk_frame_new (_("Playlist (optional)"));
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
-    playlist_entry = gtk_entry_new ();
-    g_object_set_data (G_OBJECT (config_dialog), "playlist", playlist_entry);
-
-    file_chooser_button = gtk_file_chooser_button_new (_("Select a playlist"), GTK_FILE_CHOOSER_ACTION_OPEN);
-    gtk_widget_set_valign (file_chooser_button, GTK_ALIGN_CENTER);
-    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_container_add (GTK_CONTAINER (hbox), file_chooser_button);
-    gtk_container_add (GTK_CONTAINER (frame), hbox);
-    gtk_container_add (GTK_CONTAINER (vbox), frame);
-
-    frame = gtk_frame_new (_("Reminder"));
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
-    reminder_text = gtk_entry_new ();
-    reminder_checkb = gtk_check_button_new_with_label (_("enable"));
-    g_object_set_data (G_OBJECT (config_dialog), "reminder_text", reminder_text);
-    g_object_set_data (G_OBJECT (config_dialog), "reminder_cb", reminder_checkb);
-    gtk_box_pack_start (GTK_BOX (hbox), reminder_text, TRUE, TRUE, 0);
-    gtk_container_add (GTK_CONTAINER (hbox), reminder_checkb);
-    gtk_container_add (GTK_CONTAINER (frame), hbox);
-    gtk_container_add (GTK_CONTAINER (vbox), frame);
-
-    label = gtk_label_new (_("Options"));
-    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label);
-
-
-    /* Page 5 */
-    frame = gtk_frame_new (_("What do these options mean?"));
-    gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
-    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);
-    text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-    help_text = g_strconcat (_(help[0]), _(help[1]), _(help[2]), NULL);
-    gtk_text_buffer_set_text (text_buffer, help_text, -1);
-    g_free (help_text);
-    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-    gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 5);
-    gtk_container_add (GTK_CONTAINER (scrolled_window), view);
-    gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (scrolled_window));
-
-    label = gtk_label_new (_("Help"));
-    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
-
-    g_signal_connect (config_dialog, "response", G_CALLBACK (config_dialog_response), NULL);
-
-    gtk_widget_show_all (config_dialog);
-
-    return config_dialog;
-}
diff --git a/src/alarm/interface.cc b/src/alarm/interface.cc
new file mode 100644
index 000000000000..a396d9210269
--- /dev/null
+++ b/src/alarm/interface.cc
@@ -0,0 +1,424 @@
+/*
+ * interface.c
+ * Copyright 2012 Thomas Lange
+ *
+ * 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 <gtk/gtk.h>
+#include <libaudcore/i18n.h>
+#include <libaudgui/libaudgui.h>
+
+#include "callbacks.h"
+
+const char *help[] =
+{
+   N_("Time\n"
+    "  Alarm at:\n"
+    "    The time for the alarm to come on.\n\n"
+
+    "  Quiet after:\n"
+    "    Stop alarm after this amount of time.\n"
+    "       (if the wakeup dialog is not closed)\n\n\n"
+
+    "Days\n"
+    "  Day:\n"
+    "    Select the days for the alarm to activate.\n\n"
+
+    "  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"),
+
+   N_("Volume\n"
+    "  Fading:\n"
+    "    Fade the volume up to the chosen volume\n"
+    "    for this amount of time.\n\n"
+
+    "  Start at:\n"
+    "    Start fading from this volume.\n\n"
+
+    "  Final:\n"
+    "    The volume to stop fading at.  If the fading\n"
+    "    time is 0 then set volume to this and start\n"
+    "    playing.\n\n\n"
+
+    "Options:\n"
+    "  Additional Command:\n"
+    "    Run this command at the alarm time.\n\n"),
+
+   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"
+    "    can also be entered here.\n\n"
+
+    "  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
+};
+
+GtkWidget *create_alarm_dialog (void)
+{
+    GtkWidget *alarm_dialog;
+
+    alarm_dialog = gtk_message_dialog_new (nullptr, GTK_DIALOG_DESTROY_WITH_PARENT,
+     GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("This is your wakeup call."));
+    gtk_window_set_title (GTK_WINDOW (alarm_dialog), _("Alarm"));
+
+    g_signal_connect (alarm_dialog, "response",
+     G_CALLBACK (alarm_stop_cancel), nullptr);
+    g_signal_connect_swapped (alarm_dialog, "response",
+     G_CALLBACK (gtk_widget_destroy), alarm_dialog);
+
+    gtk_widget_show_all (alarm_dialog);
+
+    return alarm_dialog;
+}
+
+GtkWidget *create_reminder_dialog (const char *reminder_msg)
+{
+    GtkWidget *reminder_dialog;
+
+    reminder_dialog = gtk_message_dialog_new (nullptr, GTK_DIALOG_DESTROY_WITH_PARENT,
+     GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("Your reminder for today is..."));
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (reminder_dialog), "%s", reminder_msg);
+    gtk_window_set_title (GTK_WINDOW (reminder_dialog), _("Reminder"));
+
+    g_signal_connect_swapped (reminder_dialog, "response",
+     G_CALLBACK (gtk_widget_destroy), reminder_dialog);
+
+    return reminder_dialog;
+}
+
+static void file_set_cb (GtkFileChooserButton *button, void * entry)
+{
+    char *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (button));
+    gtk_entry_set_text (GTK_ENTRY (entry), uri);
+    g_free (uri);
+}
+
+GtkWidget *create_config_notebook (void)
+{
+    /* General */
+    GtkWidget *notebook;
+    GtkWidget *vbox, *hbox, *label, *frame, *grid;
+    GtkAdjustment *adjustment;
+
+    /* Page 1 */
+    GtkWidget *alarm_h_spin, *alarm_m_spin;
+    GtkWidget *stop_checkb, *stop_h_spin, *stop_m_spin;
+
+    /* Page 2 */
+    int i, j;
+    GtkWidget *checkbutton;
+    GtkWidget *widget[21];
+
+    const char *weekdays[] = { _("Monday"), _("Tuesday"), _("Wednesday"),
+                                _("Thursday"), _("Friday"), _("Saturday"), _("Sunday") };
+
+    const char *day_cb[] = { "mon_cb", "tue_cb", "wed_cb", "thu_cb",
+                              "fri_cb", "sat_cb", "sun_cb" };
+
+    const char *day_def[] = { "mon_def", "tue_def", "wed_def", "thu_def",
+                               "fri_def", "sat_def", "sun_def", };
+
+    const char *day_h[] = { "mon_h", "tue_h", "wed_h", "thu_h",
+                             "fri_h", "sat_h", "sun_h" };
+
+    const char *day_m[] = { "mon_m", "tue_m", "wed_m", "thu_m",
+                             "fri_m", "sat_m", "sun_m" };
+
+    const GCallback cb_def[] = { G_CALLBACK (on_mon_def_toggled), G_CALLBACK (on_tue_def_toggled),
+                                 G_CALLBACK (on_wed_def_toggled), G_CALLBACK (on_thu_def_toggled),
+                                 G_CALLBACK (on_fri_def_toggled), G_CALLBACK (on_sat_def_toggled),
+                                 G_CALLBACK (on_sun_def_toggled) };
+
+    /* Page 3 */
+    GtkWidget *vbox2, *hbox2;
+    GtkWidget *fading_spin, *quiet_vol_scale, *vol_scale, *separator, *current_button;
+
+    /* Page 4 */
+    GtkWidget  *cmd_entry, *playlist_entry, *reminder_text;
+    GtkWidget *cmd_checkb, *reminder_checkb, *file_chooser_button;
+
+    /* Page 5 */
+    GtkWidget *view, *scrolled_window;
+    GtkTextBuffer *text_buffer;
+    char *help_text;
+
+
+    /* General */
+    notebook = gtk_notebook_new ();
+
+
+    /* Page 1 */
+    frame = gtk_frame_new (_("Time"));
+    gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
+    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);
+
+    label = gtk_label_new (_("Alarm at (default):"));
+    gtk_table_attach (GTK_TABLE (grid), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    adjustment = (GtkAdjustment *) gtk_adjustment_new (6, 0, 23, 1, 10, 0);
+    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_table_attach (GTK_TABLE (grid), alarm_h_spin, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    label = gtk_label_new (":");
+    gtk_table_attach (GTK_TABLE (grid), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    adjustment = (GtkAdjustment *) gtk_adjustment_new (30, 0, 59, 1, 10, 0);
+    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_table_attach (GTK_TABLE (grid), alarm_m_spin, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    label = gtk_label_new (_("h"));
+    gtk_table_attach (GTK_TABLE (grid), label, 4, 5, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    stop_checkb = gtk_check_button_new_with_label (_("Quiet after:"));
+    g_object_set_data (G_OBJECT (notebook), "stop_checkb", stop_checkb);
+    gtk_table_attach (GTK_TABLE (grid), stop_checkb, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+    adjustment = (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 10, 0);
+    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_table_attach (GTK_TABLE (grid), stop_h_spin, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+    label = gtk_label_new (_("hours"));
+    gtk_table_attach (GTK_TABLE (grid), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+    adjustment = (GtkAdjustment *) gtk_adjustment_new (0, 0, 59, 1, 10, 0);
+    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_table_attach (GTK_TABLE (grid), stop_m_spin, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+    label = gtk_label_new (_("minutes"));
+    gtk_table_attach (GTK_TABLE (grid), label, 4, 5, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+    gtk_container_add (GTK_CONTAINER (frame), grid);
+
+    label = gtk_label_new (_("Time"));
+    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+
+
+    /* 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);
+    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);
+
+    label = gtk_label_new (_("Day"));
+    gtk_table_attach (GTK_TABLE (grid), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    label = gtk_label_new (_("Time"));
+    gtk_table_attach (GTK_TABLE (grid), label, 2, 5, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+
+    for (i = 0; i < 7; 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_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);
+
+    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);
+        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);
+    }
+
+    for (i = 7, j = 0; i < 14; i ++, j ++)
+    {
+        adjustment = (GtkAdjustment *) gtk_adjustment_new (6, 0, 23, 1, 10, 0);
+        widget[i] = gtk_spin_button_new (adjustment, 1, 0);
+        g_object_set_data (G_OBJECT (notebook), day_h[j], widget[i]);
+        gtk_table_attach (GTK_TABLE (grid), widget[i], 2, 3, j + 1, j + 2, GTK_FILL, GTK_FILL, 0, 0);
+    }
+
+    for (i = 0; i < 7; i ++)
+    {
+        label = gtk_label_new (":");
+        gtk_table_attach (GTK_TABLE (grid), label, 3, 4, i + 1, i + 2, GTK_FILL, GTK_FILL, 0, 0);
+    }
+
+    for (i = 14, j = 0; i < 21; i ++, j ++)
+    {
+        adjustment = (GtkAdjustment *) gtk_adjustment_new (30, 0, 59, 1, 10, 0);
+        widget[i] = gtk_spin_button_new (adjustment, 1, 0);
+        g_object_set_data (G_OBJECT (notebook), day_m[j], widget[i]);
+        gtk_table_attach (GTK_TABLE (grid), widget[i], 4, 5, j + 1, j + 2, GTK_FILL, GTK_FILL, 0, 0);
+    }
+
+    label = gtk_label_new (_("Days"));
+    gtk_container_add (GTK_CONTAINER (frame), grid);
+    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+
+
+    /* Page 3 */
+    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);
+    gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
+    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_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_container_add (GTK_CONTAINER (frame), hbox);
+    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+    frame = gtk_frame_new (_("Volume"));
+    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);
+
+    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);
+
+    separator = gtk_hseparator_new ();
+    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);
+
+    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);
+
+    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_container_add (GTK_CONTAINER (frame), vbox2);
+    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);
+    frame = gtk_frame_new (_("Additional Command"));
+    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_container_add (GTK_CONTAINER (frame), hbox);
+    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+    frame = gtk_frame_new (_("Playlist (optional)"));
+    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 ();
+    g_object_set_data (G_OBJECT (notebook), "playlist", playlist_entry);
+
+    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_container_add (GTK_CONTAINER (frame), hbox);
+    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+    frame = gtk_frame_new (_("Reminder"));
+    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_container_add (GTK_CONTAINER (frame), hbox);
+    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);
+
+
+    /* Page 5 */
+    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);
+    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);
+    scrolled_window = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 6);
+    gtk_container_add (GTK_CONTAINER (scrolled_window), view);
+    gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (scrolled_window));
+
+    label = gtk_label_new (_("Help"));
+    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+
+    return notebook;
+}
diff --git a/src/alarm/interface.h b/src/alarm/interface.h
index cb76cb94daad..cea945744656 100644
--- a/src/alarm/interface.h
+++ b/src/alarm/interface.h
@@ -2,7 +2,7 @@
 #define __INTERFACE_H
 
 GtkWidget* create_alarm_dialog (void);
-GtkWidget* create_config_dialog (void);
-GtkWidget* create_reminder_dialog (const gchar *reminder_msg);
+GtkWidget* create_config_notebook (void);
+GtkWidget* create_reminder_dialog (const char *reminder_msg);
 
 #endif
diff --git a/src/albumart-qt/Makefile b/src/albumart-qt/Makefile
new file mode 100644
index 000000000000..84be51b113e0
--- /dev/null
+++ b/src/albumart-qt/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = albumart-qt${PLUGIN_SUFFIX}
+
+SRCS = albumart.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/albumart-qt/albumart.cc b/src/albumart-qt/albumart.cc
new file mode 100644
index 000000000000..3d53c48b41d6
--- /dev/null
+++ b/src/albumart-qt/albumart.cc
@@ -0,0 +1,89 @@
+/*
+ * albumart.cc
+ * Copyright 2014 William Pitcock
+ *
+ * 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 <QLabel>
+#include <QPixmap>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/hook.h>
+
+#include <libaudqt/libaudqt.h>
+
+class AlbumArtQt : public GeneralPlugin {
+public:
+    static constexpr PluginInfo info = {
+        N_("Album Art (Qt)"),
+        PACKAGE
+    };
+
+    constexpr AlbumArtQt () : GeneralPlugin (info, false) {}
+    void * get_qt_widget ();
+
+private:
+    static void update (void * unused, QLabel * widget);
+    static void clear (void * unused, QLabel * widget);
+    static void widget_cleanup (QObject * widget);
+};
+
+void AlbumArtQt::update (void * unused, QLabel * widget)
+{
+    if (! aud_drct_get_playing ())
+        return;
+
+    if (! widget)
+        return;
+
+    QSize size = widget->size ();
+    widget->setPixmap (audqt::art_request_current (size.width (), size.height ()));
+}
+
+void AlbumArtQt::clear (void * unused, QLabel * widget)
+{
+    if (! widget)
+        return;
+
+    widget->setPixmap (QPixmap ());
+}
+
+void AlbumArtQt::widget_cleanup (QObject * widget)
+{
+    hook_dissociate ("playback begin", (HookFunction) update, widget);
+    hook_dissociate ("current art ready", (HookFunction) update, widget);
+    hook_dissociate ("playback stop", (HookFunction) clear, widget);
+}
+
+void * AlbumArtQt::get_qt_widget ()
+{
+    QLabel * widget = new QLabel;
+
+    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 stop", (HookFunction) clear, widget);
+
+    widget->resize (96, 96);
+    update (nullptr, widget);
+
+    return widget;
+}
+
+EXPORT AlbumArtQt aud_plugin_instance;
diff --git a/src/albumart/Makefile b/src/albumart/Makefile
index fe066cd1833a..8b97ab4d38d9 100644
--- a/src/albumart/Makefile
+++ b/src/albumart/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = albumart${PLUGIN_SUFFIX}
 
-SRCS = albumart.c
+SRCS = albumart.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GTK_CFLAGS}
-LIBS += ${GTK_LIBS}
+LIBS += ${GTK_LIBS} -laudgui
diff --git a/src/albumart/albumart.c b/src/albumart/albumart.c
deleted file mode 100644
index 69d63a8aa9c4..000000000000
--- a/src/albumart/albumart.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * albumart.c
- * Copyright 2012-2013 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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-static void album_update (void * unused, GtkWidget * widget)
-{
-    if (! aud_drct_get_playing ())
-        return;
-
-    GdkPixbuf * pixbuf = audgui_pixbuf_request_current ();
-
-    if (! pixbuf)
-        pixbuf = audgui_pixbuf_fallback ();
-
-    audgui_scaled_image_set (widget, pixbuf);
-
-    if (pixbuf)
-        g_object_unref (pixbuf);
-}
-
-static void album_clear (void * unused, GtkWidget * widget)
-{
-    audgui_scaled_image_set (widget, NULL);
-}
-
-static void album_cleanup (GtkWidget * widget)
-{
-    hook_dissociate_full ("playback begin", (HookFunction) album_update, widget);
-    hook_dissociate_full ("current art ready", (HookFunction) album_update, widget);
-    hook_dissociate_full ("playback stop", (HookFunction) album_clear, widget);
-}
-
-static void * album_get_widget (void)
-{
-    GtkWidget * widget = audgui_scaled_image_new (NULL);
-    gtk_widget_set_size_request (widget, 96, 96);
-
-    g_signal_connect (widget, "destroy", (GCallback) album_cleanup, NULL);
-
-    hook_associate ("playback begin", (HookFunction) album_update, widget);
-    hook_associate ("current art ready", (HookFunction) album_update, widget);
-    hook_associate ("playback stop", (HookFunction) album_clear, widget);
-
-    album_update (NULL, widget);
-
-    return widget;
-}
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Album Art"),
-    .domain = PACKAGE,
-    .get_widget = album_get_widget
-)
diff --git a/src/albumart/albumart.cc b/src/albumart/albumart.cc
new file mode 100644
index 000000000000..42de4c56b71e
--- /dev/null
+++ b/src/albumart/albumart.cc
@@ -0,0 +1,88 @@
+/*
+ * albumart.c
+ * Copyright 2012-2013 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 <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/hook.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+class AlbumArtPlugin : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Album Art"),
+        PACKAGE
+    };
+
+    constexpr AlbumArtPlugin () : GeneralPlugin (info, false) {}
+
+    void * get_gtk_widget ();
+};
+
+EXPORT AlbumArtPlugin aud_plugin_instance;
+
+static void album_update (void * unused, GtkWidget * widget)
+{
+    if (! aud_drct_get_playing ())
+        return;
+
+    GdkPixbuf * pixbuf = audgui_pixbuf_request_current ();
+
+    if (! pixbuf)
+        pixbuf = audgui_pixbuf_fallback ();
+
+    audgui_scaled_image_set (widget, pixbuf);
+
+    if (pixbuf)
+        g_object_unref (pixbuf);
+}
+
+static void album_clear (void * unused, 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 stop", (HookFunction) album_clear, widget);
+
+    audgui_cleanup ();
+}
+
+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 stop", (HookFunction) album_clear, widget);
+
+    album_update (nullptr, widget);
+
+    return widget;
+}
diff --git a/src/alsa/Makefile b/src/alsa/Makefile
index c600c5a1c17e..802ca9ce9b2e 100644
--- a/src/alsa/Makefile
+++ b/src/alsa/Makefile
@@ -1,14 +1,15 @@
 PLUGIN = alsa${PLUGIN_SUFFIX}
 
-SRCS = alsa.c \
-       config.c \
-       plugin.c \
+SRCS = alsa.cc \
+       config.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${GTK_CFLAGS} ${ALSA_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${ALSA_LIBS}
+CPPFLAGS += ${ALSA_CFLAGS} -I../..
+LIBS += ${ALSA_LIBS}
diff --git a/src/alsa/alsa.c b/src/alsa/alsa.c
deleted file mode 100644
index 73a8ba6e37a6..000000000000
--- a/src/alsa/alsa.c
+++ /dev/null
@@ -1,743 +0,0 @@
-/*
- * ALSA Output Plugin for Audacious
- * Copyright 2009-2012 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.
- */
-
-/*
- * Because ALSA is not thread-safe (despite claims to the contrary) we use non-
- * blocking output in the pump thread with the mutex locked, then unlock the
- * mutex and wait for more room in the buffer with poll() while other threads
- * lock the mutex and read the output time.  We poll a pipe of our own as well
- * as the ALSA file descriptors so that we can wake up the pump thread when
- * needed.
- *
- * When paused, or when it comes to the end of the data given it, the pump will
- * wait on alsa_cond for the signal to continue.  When it has more data waiting,
- * however, it will be sitting in poll() waiting for ALSA's signal that more
- * data can be written.
- *
- * * After adding more data to the buffer, and after resuming from pause,
- *   signal on alsa_cond to wake the pump.  (There is no need to signal when
- *   entering pause.)
- * * After setting the pump_quit flag, signal on alsa_cond AND the poll_pipe
- *   before joining the thread.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include <alsa/asoundlib.h>
-
-#include <audacious/debug.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-
-#include "alsa.h"
-
-#define CHECK_VAL_RECOVER(value, function, ...) \
-do { \
-    (value) = function (__VA_ARGS__); \
-    if ((value) < 0) { \
-        CHECK (snd_pcm_recover, alsa_handle, (value), 0); \
-        CHECK_VAL ((value), function, __VA_ARGS__); \
-    } \
-} while (0)
-
-#define CHECK_RECOVER(function, ...) \
-do { \
-    int CHECK_RECOVER_error; \
-    CHECK_VAL_RECOVER (CHECK_RECOVER_error, function, __VA_ARGS__); \
-} while (0)
-
-static snd_pcm_t * alsa_handle;
-static pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t alsa_cond = PTHREAD_COND_INITIALIZER;
-
-static snd_pcm_format_t alsa_format;
-static int alsa_channels, alsa_rate;
-
-static void * alsa_buffer;
-static int alsa_buffer_length, alsa_buffer_data_start, alsa_buffer_data_length;
-static int alsa_period; /* milliseconds */
-
-static int64_t alsa_written; /* frames */
-static char alsa_prebuffer, alsa_paused;
-static int alsa_paused_delay; /* frames */
-
-static int poll_pipe[2];
-static int poll_count;
-static struct pollfd * poll_handles;
-
-static char pump_quit;
-static pthread_t pump_thread;
-
-static snd_mixer_t * alsa_mixer;
-static snd_mixer_elem_t * alsa_mixer_element;
-
-static char poll_setup (void)
-{
-    if (pipe (poll_pipe))
-    {
-        ERROR ("Failed to create pipe: %s.\n", strerror (errno));
-        return 0;
-    }
-
-    if (fcntl (poll_pipe[0], F_SETFL, O_NONBLOCK))
-    {
-        ERROR ("Failed to set O_NONBLOCK on pipe: %s.\n", strerror (errno));
-        close (poll_pipe[0]);
-        close (poll_pipe[1]);
-        return 0;
-    }
-
-    poll_count = 1 + snd_pcm_poll_descriptors_count (alsa_handle);
-    poll_handles = g_new (struct pollfd, poll_count);
-    poll_handles[0].fd = poll_pipe[0];
-    poll_handles[0].events = POLLIN;
-    poll_count = 1 + snd_pcm_poll_descriptors (alsa_handle, poll_handles + 1,
-     poll_count - 1);
-
-    return 1;
-}
-
-static void poll_sleep (void)
-{
-    if (poll (poll_handles, poll_count, -1) < 0)
-    {
-        ERROR ("Failed to poll: %s.\n", strerror (errno));
-        return;
-    }
-
-    if (poll_handles[0].revents & POLLIN)
-    {
-        char c;
-        while (read (poll_pipe[0], & c, 1) == 1)
-            ;
-    }
-}
-
-static void poll_wake (void)
-{
-    const char c = 0;
-    if (write (poll_pipe[1], & c, 1) < 0)
-        ERROR ("Failed to write to pipe: %s.\n", strerror (errno));
-}
-
-static void poll_cleanup (void)
-{
-    close (poll_pipe[0]);
-    close (poll_pipe[1]);
-    g_free (poll_handles);
-}
-
-static void * pump (void * unused)
-{
-    pthread_mutex_lock (& alsa_mutex);
-    pthread_cond_broadcast (& alsa_cond); /* signal thread started */
-
-    char failed = 0;
-    char workaround = 0;
-    int slept = 0;
-
-    while (! pump_quit)
-    {
-        if (alsa_prebuffer || alsa_paused || ! snd_pcm_bytes_to_frames
-         (alsa_handle, alsa_buffer_data_length))
-        {
-            pthread_cond_wait (& alsa_cond, & alsa_mutex);
-            continue;
-        }
-
-        int length;
-        CHECK_VAL_RECOVER (length, snd_pcm_avail_update, alsa_handle);
-
-        if (! length)
-            goto WAIT;
-
-        slept = 0;
-
-        length = snd_pcm_frames_to_bytes (alsa_handle, length);
-        length = MIN (length, alsa_buffer_data_length);
-        length = MIN (length, alsa_buffer_length - alsa_buffer_data_start);
-        length = snd_pcm_bytes_to_frames (alsa_handle, length);
-
-        int written;
-        CHECK_VAL_RECOVER (written, snd_pcm_writei, alsa_handle, (char *)
-         alsa_buffer + alsa_buffer_data_start, length);
-
-        failed = 0;
-
-        written = snd_pcm_frames_to_bytes (alsa_handle, written);
-        alsa_buffer_data_start += written;
-        alsa_buffer_data_length -= written;
-
-        pthread_cond_broadcast (& alsa_cond); /* signal write complete */
-
-        if (alsa_buffer_data_start == alsa_buffer_length)
-        {
-            alsa_buffer_data_start = 0;
-            continue;
-        }
-
-        if (! snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer_data_length))
-            continue;
-
-    WAIT:
-        pthread_mutex_unlock (& alsa_mutex);
-
-        if (slept > 4)
-        {
-            AUDDBG ("Activating timer workaround.\n");
-            workaround = 1;
-        }
-
-        if (workaround && slept)
-        {
-            const struct timespec delay = {.tv_sec = 0, .tv_nsec = 600000 *
-             alsa_period};
-            nanosleep (& delay, NULL);
-        }
-        else
-        {
-            poll_sleep ();
-            slept ++;
-        }
-
-        pthread_mutex_lock (& alsa_mutex);
-        continue;
-
-    FAILED:
-        if (failed)
-            break;
-
-        failed = 1;
-        CHECK (snd_pcm_prepare, alsa_handle);
-    }
-
-    pthread_mutex_unlock (& alsa_mutex);
-    return NULL;
-}
-
-static void pump_start (void)
-{
-    AUDDBG ("Starting pump.\n");
-    pthread_create (& pump_thread, NULL, pump, NULL);
-    pthread_cond_wait (& alsa_cond, & alsa_mutex);
-}
-
-static void pump_stop (void)
-{
-    AUDDBG ("Stopping pump.\n");
-    pump_quit = 1;
-    pthread_cond_broadcast (& alsa_cond);
-    poll_wake ();
-    pthread_mutex_unlock (& alsa_mutex);
-    pthread_join (pump_thread, NULL);
-    pthread_mutex_lock (& alsa_mutex);
-    pump_quit = 0;
-}
-
-static void start_playback (void)
-{
-    AUDDBG ("Starting playback.\n");
-    CHECK (snd_pcm_prepare, alsa_handle);
-
-FAILED:
-    alsa_prebuffer = 0;
-    pthread_cond_broadcast (& alsa_cond);
-}
-
-static int get_delay (void)
-{
-    snd_pcm_sframes_t delay = 0;
-
-    CHECK_RECOVER (snd_pcm_delay, alsa_handle, & delay);
-
-FAILED:
-    return delay;
-}
-
-int alsa_init (void)
-{
-    AUDDBG ("Initialize.\n");
-    alsa_config_load ();
-    alsa_open_mixer ();
-    return 1;
-}
-
-void alsa_cleanup (void)
-{
-    AUDDBG ("Cleanup.\n");
-    alsa_close_mixer ();
-    alsa_config_save ();
-}
-
-static int convert_aud_format (int aud_format)
-{
-    const struct
-    {
-        int aud_format, format;
-    }
-    table[] =
-    {
-        {FMT_FLOAT, SND_PCM_FORMAT_FLOAT},
-        {FMT_S8, SND_PCM_FORMAT_S8},
-        {FMT_U8, SND_PCM_FORMAT_U8},
-        {FMT_S16_LE, SND_PCM_FORMAT_S16_LE},
-        {FMT_S16_BE, SND_PCM_FORMAT_S16_BE},
-        {FMT_U16_LE, SND_PCM_FORMAT_U16_LE},
-        {FMT_U16_BE, SND_PCM_FORMAT_U16_BE},
-        {FMT_S24_LE, SND_PCM_FORMAT_S24_LE},
-        {FMT_S24_BE, SND_PCM_FORMAT_S24_BE},
-        {FMT_U24_LE, SND_PCM_FORMAT_U24_LE},
-        {FMT_U24_BE, SND_PCM_FORMAT_U24_BE},
-        {FMT_S32_LE, SND_PCM_FORMAT_S32_LE},
-        {FMT_S32_BE, SND_PCM_FORMAT_S32_BE},
-        {FMT_U32_LE, SND_PCM_FORMAT_U32_LE},
-        {FMT_U32_BE, SND_PCM_FORMAT_U32_BE},
-    };
-
-    for (int count = 0; count < ARRAY_LEN (table); count ++)
-    {
-        if (table[count].aud_format == aud_format)
-            return table[count].format;
-    }
-
-    return SND_PCM_FORMAT_UNKNOWN;
-}
-
-int alsa_open_audio (int aud_format, int rate, int channels)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    assert (alsa_handle == NULL);
-
-    int format = convert_aud_format (aud_format);
-    AUDDBG ("Opening PCM device %s for %s, %d channels, %d Hz.\n",
-     alsa_config_pcm, snd_pcm_format_name (format), channels, rate);
-    CHECK_NOISY (snd_pcm_open, & alsa_handle, alsa_config_pcm,
-     SND_PCM_STREAM_PLAYBACK, 0);
-
-    snd_pcm_hw_params_t * params;
-    snd_pcm_hw_params_alloca (& params);
-    CHECK_NOISY (snd_pcm_hw_params_any, alsa_handle, params);
-    CHECK_NOISY (snd_pcm_hw_params_set_access, alsa_handle, params,
-     SND_PCM_ACCESS_RW_INTERLEAVED);
-
-    CHECK_NOISY (snd_pcm_hw_params_set_format, alsa_handle, params, format);
-    CHECK_NOISY (snd_pcm_hw_params_set_channels, alsa_handle, params, channels);
-    CHECK_NOISY (snd_pcm_hw_params_set_rate, alsa_handle, params, rate, 0);
-
-    alsa_format = format;
-    alsa_channels = channels;
-    alsa_rate = rate;
-
-    int total_buffer = aud_get_int (NULL, "output_buffer_size");
-    unsigned int useconds = 1000 * MIN (1000, total_buffer / 2);
-    int direction = 0;
-    CHECK_NOISY (snd_pcm_hw_params_set_buffer_time_near, alsa_handle, params,
-     & useconds, & direction);
-    int hard_buffer = useconds / 1000;
-
-    useconds = 1000 * (hard_buffer / 4);
-    direction = 0;
-    CHECK_NOISY (snd_pcm_hw_params_set_period_time_near, alsa_handle, params,
-     & useconds, & direction);
-    alsa_period = useconds / 1000;
-
-    CHECK_NOISY (snd_pcm_hw_params, alsa_handle, params);
-
-    int soft_buffer = MAX (total_buffer / 2, total_buffer - hard_buffer);
-    AUDDBG ("Buffer: hardware %d ms, software %d ms, period %d ms.\n",
-     hard_buffer, soft_buffer, alsa_period);
-
-    alsa_buffer_length = snd_pcm_frames_to_bytes (alsa_handle, (int64_t)
-     soft_buffer * rate / 1000);
-    alsa_buffer = g_malloc (alsa_buffer_length);
-    alsa_buffer_data_start = 0;
-    alsa_buffer_data_length = 0;
-
-    alsa_written = 0;
-    alsa_prebuffer = 1;
-    alsa_paused = 0;
-    alsa_paused_delay = 0;
-
-    if (! poll_setup ())
-        goto FAILED;
-
-    pump_start ();
-
-    pthread_mutex_unlock (& alsa_mutex);
-    return 1;
-
-FAILED:
-    if (alsa_handle != NULL)
-    {
-        snd_pcm_close (alsa_handle);
-        alsa_handle = NULL;
-    }
-
-    pthread_mutex_unlock (& alsa_mutex);
-    return 0;
-}
-
-void alsa_close_audio (void)
-{
-    AUDDBG ("Closing audio.\n");
-    pthread_mutex_lock (& alsa_mutex);
-
-    assert (alsa_handle != NULL);
-
-    pump_stop ();
-    CHECK (snd_pcm_drop, alsa_handle);
-
-FAILED:
-    g_free (alsa_buffer);
-    poll_cleanup ();
-    snd_pcm_close (alsa_handle);
-    alsa_handle = NULL;
-
-    pthread_mutex_unlock (& alsa_mutex);
-}
-
-int alsa_buffer_free (void)
-{
-    pthread_mutex_lock (& alsa_mutex);
-    int avail = alsa_buffer_length - alsa_buffer_data_length;
-    pthread_mutex_unlock (& alsa_mutex);
-    return avail;
-}
-
-void alsa_write_audio (void * data, int length)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    int start = (alsa_buffer_data_start + alsa_buffer_data_length) %
-     alsa_buffer_length;
-
-    assert (length <= alsa_buffer_length - alsa_buffer_data_length);
-
-    if (length > alsa_buffer_length - start)
-    {
-        int part = alsa_buffer_length - start;
-
-        memcpy ((char *) alsa_buffer + start, data, part);
-        memcpy (alsa_buffer, (char *) data + part, length - part);
-    }
-    else
-        memcpy ((char *) alsa_buffer + start, data, length);
-
-    alsa_buffer_data_length += length;
-    alsa_written += snd_pcm_bytes_to_frames (alsa_handle, length);
-
-    if (! alsa_paused)
-        pthread_cond_broadcast (& alsa_cond);
-
-    pthread_mutex_unlock (& alsa_mutex);
-}
-
-void alsa_period_wait (void)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    while (alsa_buffer_data_length == alsa_buffer_length)
-    {
-        if (! alsa_paused)
-        {
-            if (alsa_prebuffer)
-                start_playback ();
-            else
-                pthread_cond_broadcast (& alsa_cond);
-        }
-
-        pthread_cond_wait (& alsa_cond, & alsa_mutex);
-    }
-
-    pthread_mutex_unlock (& alsa_mutex);
-}
-
-void alsa_drain (void)
-{
-    AUDDBG ("Drain.\n");
-    pthread_mutex_lock (& alsa_mutex);
-
-    assert (! alsa_paused);
-
-    if (alsa_prebuffer)
-        start_playback ();
-
-    while (snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer_data_length))
-        pthread_cond_wait (& alsa_cond, & alsa_mutex);
-
-    pump_stop ();
-
-    if (alsa_config_drain_workaround)
-    {
-        int d = get_delay () * 1000 / alsa_rate;
-        struct timespec delay = {.tv_sec = d / 1000, .tv_nsec = d % 1000 *
-         1000000};
-
-        pthread_mutex_unlock (& alsa_mutex);
-        nanosleep (& delay, NULL);
-        pthread_mutex_lock (& alsa_mutex);
-    }
-    else
-    {
-        while (1)
-        {
-            int state;
-            CHECK_VAL (state, snd_pcm_state, alsa_handle);
-
-            if (state != SND_PCM_STATE_RUNNING && state !=
-             SND_PCM_STATE_DRAINING)
-                break;
-
-            pthread_mutex_unlock (& alsa_mutex);
-            poll_sleep ();
-            pthread_mutex_lock (& alsa_mutex);
-        }
-    }
-
-    pump_start ();
-
-FAILED:
-    pthread_mutex_unlock (& alsa_mutex);
-    return;
-}
-
-int alsa_output_time (void)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    int64_t frames = alsa_written - snd_pcm_bytes_to_frames (alsa_handle,
-     alsa_buffer_data_length);
-
-    if (alsa_prebuffer || alsa_paused)
-        frames -= alsa_paused_delay;
-    else
-        frames -= get_delay ();
-
-    int time = frames * 1000 / alsa_rate;
-
-    pthread_mutex_unlock (& alsa_mutex);
-    return time;
-}
-
-void alsa_flush (int time)
-{
-    AUDDBG ("Seek requested; discarding buffer.\n");
-    pthread_mutex_lock (& alsa_mutex);
-
-    pump_stop ();
-    CHECK (snd_pcm_drop, alsa_handle);
-
-FAILED:
-    alsa_buffer_data_start = 0;
-    alsa_buffer_data_length = 0;
-
-    alsa_written = (int64_t) time * alsa_rate / 1000;
-    alsa_prebuffer = 1;
-    alsa_paused_delay = 0;
-
-    pthread_cond_broadcast (& alsa_cond); /* interrupt period wait */
-
-    pump_start ();
-
-    pthread_mutex_unlock (& alsa_mutex);
-}
-
-void alsa_pause (int pause)
-{
-    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
-    pthread_mutex_lock (& alsa_mutex);
-
-    alsa_paused = pause;
-
-    if (! alsa_prebuffer)
-    {
-        if (pause)
-            alsa_paused_delay = get_delay ();
-
-        CHECK (snd_pcm_pause, alsa_handle, pause);
-    }
-
-DONE:
-    if (! pause)
-        pthread_cond_broadcast (& alsa_cond);
-
-    pthread_mutex_unlock (& alsa_mutex);
-    return;
-
-FAILED:
-    AUDDBG ("Trying to work around broken pause.\n");
-
-    if (pause)
-        snd_pcm_drop (alsa_handle);
-    else
-        snd_pcm_prepare (alsa_handle);
-
-    goto DONE;
-}
-
-void alsa_open_mixer (void)
-{
-    snd_mixer_selem_id_t * selem_id;
-
-    alsa_mixer = NULL;
-
-    if (alsa_config_mixer_element == NULL)
-        goto FAILED;
-
-    AUDDBG ("Opening mixer card %s.\n", alsa_config_mixer);
-    CHECK_NOISY (snd_mixer_open, & alsa_mixer, 0);
-    CHECK_NOISY (snd_mixer_attach, alsa_mixer, alsa_config_mixer);
-    CHECK_NOISY (snd_mixer_selem_register, alsa_mixer, NULL, NULL);
-    CHECK_NOISY (snd_mixer_load, alsa_mixer);
-
-    snd_mixer_selem_id_alloca (& selem_id);
-    snd_mixer_selem_id_set_name (selem_id, alsa_config_mixer_element);
-    alsa_mixer_element = snd_mixer_find_selem (alsa_mixer, selem_id);
-
-    if (alsa_mixer_element == NULL)
-    {
-        ERROR_NOISY ("snd_mixer_find_selem failed.\n");
-        goto FAILED;
-    }
-
-    CHECK (snd_mixer_selem_set_playback_volume_range, alsa_mixer_element, 0, 100);
-    return;
-
-FAILED:
-    if (alsa_mixer != NULL)
-    {
-        snd_mixer_close (alsa_mixer);
-        alsa_mixer = NULL;
-    }
-}
-
-void alsa_close_mixer (void)
-{
-    if (alsa_mixer != NULL)
-        snd_mixer_close (alsa_mixer);
-}
-
-void alsa_get_volume (int * left, int * right)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    long left_l = 0, right_l = 0;
-
-    if (alsa_mixer == NULL)
-        goto FAILED;
-
-    CHECK (snd_mixer_handle_events, alsa_mixer);
-
-    if (snd_mixer_selem_is_playback_mono (alsa_mixer_element))
-    {
-        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_MONO, & left_l);
-        right_l = left_l;
-
-        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
-        {
-            int on = 0;
-            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
-             SND_MIXER_SCHN_MONO, & on);
-
-            if (! on)
-                left_l = right_l = 0;
-        }
-    }
-    else
-    {
-        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_FRONT_LEFT, & left_l);
-        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_FRONT_RIGHT, & right_l);
-
-        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
-        {
-            int left_on = 0, right_on = 0;
-            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
-             SND_MIXER_SCHN_FRONT_LEFT, & left_on);
-            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
-             SND_MIXER_SCHN_FRONT_RIGHT, & right_on);
-
-            if (! left_on)
-                left_l = 0;
-            if (! right_on)
-                right_l = 0;
-        }
-    }
-
-FAILED:
-    pthread_mutex_unlock (& alsa_mutex);
-
-    * left = left_l;
-    * right = right_l;
-}
-
-void alsa_set_volume (int left, int right)
-{
-    pthread_mutex_lock (& alsa_mutex);
-
-    if (alsa_mixer == NULL)
-        goto FAILED;
-
-    if (snd_mixer_selem_is_playback_mono (alsa_mixer_element))
-    {
-        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_MONO, MAX (left, right));
-
-        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
-            CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
-             SND_MIXER_SCHN_MONO, MAX (left, right) != 0);
-    }
-    else
-    {
-        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_FRONT_LEFT, left);
-        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
-         SND_MIXER_SCHN_FRONT_RIGHT, right);
-
-        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
-        {
-            if (snd_mixer_selem_has_playback_switch_joined (alsa_mixer_element))
-                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
-                 SND_MIXER_SCHN_FRONT_LEFT, MAX (left, right) != 0);
-            else
-            {
-                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
-                 SND_MIXER_SCHN_FRONT_LEFT, left != 0);
-                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
-                 SND_MIXER_SCHN_FRONT_RIGHT, right != 0);
-            }
-        }
-    }
-
-    CHECK (snd_mixer_handle_events, alsa_mixer);
-
-FAILED:
-    pthread_mutex_unlock (& alsa_mutex);
-}
diff --git a/src/alsa/alsa.cc b/src/alsa/alsa.cc
new file mode 100644
index 000000000000..1d46f12a1932
--- /dev/null
+++ b/src/alsa/alsa.cc
@@ -0,0 +1,675 @@
+/*
+ * ALSA Output Plugin for Audacious
+ * Copyright 2009-2014 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.
+ */
+
+/*
+ * Because ALSA is not thread-safe (despite claims to the contrary) we use non-
+ * blocking output in the pump thread with the mutex locked, then unlock the
+ * mutex and wait for more room in the buffer with poll() while other threads
+ * lock the mutex and read the output time.  We poll a pipe of our own as well
+ * as the ALSA file descriptors so that we can wake up the pump thread when
+ * needed.
+ *
+ * When paused, or when it comes to the end of the data given it, the pump will
+ * wait on alsa_cond for the signal to continue.  When it has more data waiting,
+ * however, it will be sitting in poll() waiting for ALSA's signal that more
+ * data can be written.
+ *
+ * * After adding more data to the buffer, and after resuming from pause,
+ *   signal on alsa_cond to wake the pump.  (There is no need to signal when
+ *   entering pause.)
+ * * After setting the pump_quit flag, signal on alsa_cond AND the poll_pipe
+ *   before joining the thread.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <alsa/asoundlib.h>
+#include <libaudcore/ringbuf.h>
+
+#include "alsa.h"
+
+EXPORT ALSAPlugin aud_plugin_instance;
+
+#define CHECK_VAL_RECOVER(value, function, ...) \
+do { \
+    (value) = function (__VA_ARGS__); \
+    if ((value) < 0) { \
+        CHECK (snd_pcm_recover, alsa_handle, (value), 0); \
+        CHECK_VAL ((value), function, __VA_ARGS__); \
+    } \
+} while (0)
+
+#define CHECK_RECOVER(function, ...) \
+do { \
+    int CHECK_RECOVER_error; \
+    CHECK_VAL_RECOVER (CHECK_RECOVER_error, function, __VA_ARGS__); \
+} while (0)
+
+static snd_pcm_t * alsa_handle;
+static pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t alsa_cond = PTHREAD_COND_INITIALIZER;
+
+static snd_pcm_format_t alsa_format;
+static int alsa_channels, alsa_rate;
+
+static RingBuf<char> alsa_buffer;
+static int alsa_period; /* milliseconds */
+
+static bool alsa_prebuffer, alsa_paused;
+static int alsa_paused_delay; /* milliseconds */
+
+static int poll_pipe[2];
+static int poll_count;
+static pollfd * poll_handles;
+
+static bool pump_quit;
+static pthread_t pump_thread;
+
+static snd_mixer_t * alsa_mixer;
+static snd_mixer_elem_t * alsa_mixer_element;
+
+static bool poll_setup ()
+{
+    if (pipe (poll_pipe))
+    {
+        ERROR ("Failed to create pipe: %s.\n", strerror (errno));
+        return false;
+    }
+
+    if (fcntl (poll_pipe[0], F_SETFL, O_NONBLOCK))
+    {
+        ERROR ("Failed to set O_NONBLOCK on pipe: %s.\n", strerror (errno));
+        close (poll_pipe[0]);
+        close (poll_pipe[1]);
+        return false;
+    }
+
+    poll_count = 1 + snd_pcm_poll_descriptors_count (alsa_handle);
+    poll_handles = new pollfd[poll_count];
+    poll_handles[0].fd = poll_pipe[0];
+    poll_handles[0].events = POLLIN;
+    poll_count = 1 + snd_pcm_poll_descriptors (alsa_handle, poll_handles + 1,
+     poll_count - 1);
+
+    return true;
+}
+
+static void poll_sleep ()
+{
+    if (poll (poll_handles, poll_count, -1) < 0)
+    {
+        ERROR ("Failed to poll: %s.\n", strerror (errno));
+        return;
+    }
+
+    if (poll_handles[0].revents & POLLIN)
+    {
+        char c;
+        while (read (poll_pipe[0], & c, 1) == 1)
+            ;
+    }
+}
+
+static void poll_wake ()
+{
+    const char c = 0;
+    if (write (poll_pipe[1], & c, 1) < 0)
+        ERROR ("Failed to write to pipe: %s.\n", strerror (errno));
+}
+
+static void poll_cleanup ()
+{
+    close (poll_pipe[0]);
+    close (poll_pipe[1]);
+    delete[] poll_handles;
+}
+
+static void * pump (void *)
+{
+    pthread_mutex_lock (& alsa_mutex);
+    pthread_cond_broadcast (& alsa_cond); /* signal thread started */
+
+    bool failed_once = false;
+    bool use_timed_wait = false;
+    int wakeups_since_write = 0;
+
+    while (! pump_quit)
+    {
+        int writable = snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer.linear ());
+
+        if (alsa_prebuffer || alsa_paused || ! writable)
+        {
+            pthread_cond_wait (& alsa_cond, & alsa_mutex);
+            continue;
+        }
+
+        int avail;
+        CHECK_VAL_RECOVER (avail, snd_pcm_avail_update, alsa_handle);
+
+        if (avail)
+        {
+            wakeups_since_write = 0;
+
+            int written;
+            CHECK_VAL_RECOVER (written, snd_pcm_writei, alsa_handle,
+             & alsa_buffer[0], aud::min (writable, avail));
+
+            failed_once = false;
+
+            alsa_buffer.discard (snd_pcm_frames_to_bytes (alsa_handle, written));
+
+            pthread_cond_broadcast (& alsa_cond); /* signal write complete */
+
+            if (writable < avail)
+                continue;
+        }
+
+        pthread_mutex_unlock (& alsa_mutex);
+
+        if (wakeups_since_write > 4)
+        {
+            AUDDBG ("Activating timer workaround.\n");
+            use_timed_wait = true;
+        }
+
+        if (use_timed_wait && wakeups_since_write)
+        {
+            timespec delay = {0, 600000 * alsa_period};
+            nanosleep (& delay, nullptr);
+        }
+        else
+        {
+            poll_sleep ();
+            wakeups_since_write ++;
+        }
+
+        pthread_mutex_lock (& alsa_mutex);
+        continue;
+
+    FAILED:
+        if (failed_once)
+            break;
+
+        failed_once = true;
+        CHECK (snd_pcm_prepare, alsa_handle);
+    }
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return nullptr;
+}
+
+static void pump_start ()
+{
+    AUDDBG ("Starting pump.\n");
+    pthread_create (& pump_thread, nullptr, pump, nullptr);
+    pthread_cond_wait (& alsa_cond, & alsa_mutex);
+}
+
+static void pump_stop ()
+{
+    AUDDBG ("Stopping pump.\n");
+    pump_quit = true;
+    pthread_cond_broadcast (& alsa_cond);
+    poll_wake ();
+    pthread_mutex_unlock (& alsa_mutex);
+    pthread_join (pump_thread, nullptr);
+    pthread_mutex_lock (& alsa_mutex);
+    pump_quit = false;
+}
+
+static void start_playback ()
+{
+    AUDDBG ("Starting playback.\n");
+    CHECK (snd_pcm_prepare, alsa_handle);
+
+FAILED:
+    alsa_prebuffer = false;
+    pthread_cond_broadcast (& alsa_cond);
+}
+
+static int get_delay_locked ()
+{
+    snd_pcm_sframes_t delay = 0;
+    CHECK_RECOVER (snd_pcm_delay, alsa_handle, & delay);
+
+FAILED:
+    return aud::rescale ((int) delay, alsa_rate, 1000);
+}
+
+bool ALSAPlugin::init ()
+{
+    AUDDBG ("Initialize.\n");
+    init_config ();
+    open_mixer ();
+    return true;
+}
+
+void ALSAPlugin::cleanup ()
+{
+    AUDDBG ("Cleanup.\n");
+    close_mixer ();
+}
+
+static snd_pcm_format_t convert_aud_format (int aud_format)
+{
+    static const struct
+    {
+        int aud_format;
+        snd_pcm_format_t format;
+    }
+    table[] =
+    {
+        {FMT_FLOAT, SND_PCM_FORMAT_FLOAT},
+        {FMT_S8, SND_PCM_FORMAT_S8},
+        {FMT_U8, SND_PCM_FORMAT_U8},
+        {FMT_S16_LE, SND_PCM_FORMAT_S16_LE},
+        {FMT_S16_BE, SND_PCM_FORMAT_S16_BE},
+        {FMT_U16_LE, SND_PCM_FORMAT_U16_LE},
+        {FMT_U16_BE, SND_PCM_FORMAT_U16_BE},
+        {FMT_S24_LE, SND_PCM_FORMAT_S24_LE},
+        {FMT_S24_BE, SND_PCM_FORMAT_S24_BE},
+        {FMT_U24_LE, SND_PCM_FORMAT_U24_LE},
+        {FMT_U24_BE, SND_PCM_FORMAT_U24_BE},
+        {FMT_S32_LE, SND_PCM_FORMAT_S32_LE},
+        {FMT_S32_BE, SND_PCM_FORMAT_S32_BE},
+        {FMT_U32_LE, SND_PCM_FORMAT_U32_LE},
+        {FMT_U32_BE, SND_PCM_FORMAT_U32_BE},
+    };
+
+    for (auto & conv : table)
+    {
+        if (conv.aud_format == aud_format)
+            return conv.format;
+    }
+
+    return SND_PCM_FORMAT_UNKNOWN;
+}
+
+bool ALSAPlugin::open_audio (int aud_format, int rate, int channels)
+{
+    int total_buffer, hard_buffer, soft_buffer, buffer_frames;
+    unsigned useconds;
+    int direction;
+
+    pthread_mutex_lock (& alsa_mutex);
+
+    assert (! alsa_handle);
+
+    String pcm = aud_get_str ("alsa", "pcm");
+    snd_pcm_format_t format = convert_aud_format (aud_format);
+    AUDDBG ("Opening PCM device %s for %s, %d channels, %d Hz.\n",
+     (const char *) pcm, snd_pcm_format_name (format), channels, rate);
+    CHECK_NOISY (snd_pcm_open, & alsa_handle, pcm, SND_PCM_STREAM_PLAYBACK, 0);
+
+    snd_pcm_hw_params_t * params;
+    snd_pcm_hw_params_alloca (& params);
+    CHECK_NOISY (snd_pcm_hw_params_any, alsa_handle, params);
+    CHECK_NOISY (snd_pcm_hw_params_set_access, alsa_handle, params,
+     SND_PCM_ACCESS_RW_INTERLEAVED);
+
+    CHECK_NOISY (snd_pcm_hw_params_set_format, alsa_handle, params, format);
+    CHECK_NOISY (snd_pcm_hw_params_set_channels, alsa_handle, params, channels);
+    CHECK_NOISY (snd_pcm_hw_params_set_rate, alsa_handle, params, rate, 0);
+
+    alsa_format = format;
+    alsa_channels = channels;
+    alsa_rate = rate;
+
+    total_buffer = aud_get_int (nullptr, "output_buffer_size");
+    useconds = 1000 * aud::min (1000, total_buffer / 2);
+    direction = 0;
+    CHECK_NOISY (snd_pcm_hw_params_set_buffer_time_near, alsa_handle, params,
+     & useconds, & direction);
+    hard_buffer = useconds / 1000;
+
+    useconds = 1000 * (hard_buffer / 4);
+    direction = 0;
+    CHECK_NOISY (snd_pcm_hw_params_set_period_time_near, alsa_handle, params,
+     & useconds, & direction);
+    alsa_period = useconds / 1000;
+
+    CHECK_NOISY (snd_pcm_hw_params, alsa_handle, params);
+
+    soft_buffer = aud::max (total_buffer / 2, total_buffer - hard_buffer);
+    AUDDBG ("Buffer: hardware %d ms, software %d ms, period %d ms.\n",
+     hard_buffer, soft_buffer, alsa_period);
+
+    buffer_frames = aud::rescale<int64_t> (soft_buffer, 1000, rate);
+    alsa_buffer.alloc (snd_pcm_frames_to_bytes (alsa_handle, buffer_frames));
+
+    alsa_prebuffer = true;
+    alsa_paused = false;
+    alsa_paused_delay = 0;
+
+    if (! poll_setup ())
+        goto FAILED;
+
+    pump_start ();
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return true;
+
+FAILED:
+    if (alsa_handle)
+    {
+        snd_pcm_close (alsa_handle);
+        alsa_handle = nullptr;
+    }
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return false;
+}
+
+void ALSAPlugin::close_audio ()
+{
+    AUDDBG ("Closing audio.\n");
+    pthread_mutex_lock (& alsa_mutex);
+
+    assert (alsa_handle);
+
+    pump_stop ();
+    CHECK (snd_pcm_drop, alsa_handle);
+
+FAILED:
+    alsa_buffer.destroy ();
+    poll_cleanup ();
+    snd_pcm_close (alsa_handle);
+    alsa_handle = nullptr;
+
+    pthread_mutex_unlock (& alsa_mutex);
+}
+
+int ALSAPlugin::write_audio (const void * data, int length)
+{
+    pthread_mutex_lock (& alsa_mutex);
+
+    length = aud::min (length, alsa_buffer.space ());
+    alsa_buffer.copy_in ((const char *) data, length);
+
+    if (! alsa_paused)
+        pthread_cond_broadcast (& alsa_cond);
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return length;
+}
+
+void ALSAPlugin::period_wait ()
+{
+    pthread_mutex_lock (& alsa_mutex);
+
+    while (! alsa_buffer.space ())
+    {
+        if (! alsa_paused)
+        {
+            if (alsa_prebuffer)
+                start_playback ();
+            else
+                pthread_cond_broadcast (& alsa_cond);
+        }
+
+        pthread_cond_wait (& alsa_cond, & alsa_mutex);
+    }
+
+    pthread_mutex_unlock (& alsa_mutex);
+}
+
+void ALSAPlugin::drain ()
+{
+    AUDDBG ("Drain.\n");
+    pthread_mutex_lock (& alsa_mutex);
+
+    assert (! alsa_paused);
+
+    if (alsa_prebuffer)
+        start_playback ();
+
+    while (snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer.len ()))
+        pthread_cond_wait (& alsa_cond, & alsa_mutex);
+
+    pump_stop ();
+
+    int d = get_delay_locked ();
+    timespec delay = {d / 1000, d % 1000 * 1000000};
+
+    pthread_mutex_unlock (& alsa_mutex);
+    nanosleep (& delay, nullptr);
+    pthread_mutex_lock (& alsa_mutex);
+
+    pump_start ();
+
+    pthread_mutex_unlock (& alsa_mutex);
+}
+
+int ALSAPlugin::get_delay ()
+{
+    pthread_mutex_lock (& alsa_mutex);
+
+    int buffered = snd_pcm_bytes_to_frames (alsa_handle, alsa_buffer.len ());
+    int delay = aud::rescale (buffered, alsa_rate, 1000);
+
+    if (alsa_prebuffer || alsa_paused)
+        delay += alsa_paused_delay;
+    else
+        delay += get_delay_locked ();
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return delay;
+}
+
+void ALSAPlugin::flush ()
+{
+    AUDDBG ("Seek requested; discarding buffer.\n");
+    pthread_mutex_lock (& alsa_mutex);
+
+    pump_stop ();
+    CHECK (snd_pcm_drop, alsa_handle);
+
+FAILED:
+    alsa_buffer.discard ();
+
+    alsa_prebuffer = true;
+    alsa_paused_delay = 0;
+
+    pthread_cond_broadcast (& alsa_cond); /* interrupt period wait */
+
+    pump_start ();
+
+    pthread_mutex_unlock (& alsa_mutex);
+}
+
+void ALSAPlugin::pause (bool pause)
+{
+    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
+    pthread_mutex_lock (& alsa_mutex);
+
+    alsa_paused = pause;
+
+    if (! alsa_prebuffer)
+    {
+        if (pause)
+            alsa_paused_delay = get_delay_locked ();
+
+        CHECK (snd_pcm_pause, alsa_handle, pause);
+    }
+
+DONE:
+    if (! pause)
+        pthread_cond_broadcast (& alsa_cond);
+
+    pthread_mutex_unlock (& alsa_mutex);
+    return;
+
+FAILED:
+    AUDDBG ("Trying to work around broken pause.\n");
+
+    if (pause)
+        snd_pcm_drop (alsa_handle);
+    else
+        snd_pcm_prepare (alsa_handle);
+
+    goto DONE;
+}
+
+void ALSAPlugin::open_mixer ()
+{
+    alsa_mixer = nullptr;
+
+    String mixer = aud_get_str ("alsa", "mixer");
+    String mixer_element = aud_get_str ("alsa", "mixer-element");
+
+    if (! mixer_element[0])
+        goto FAILED;
+
+    AUDDBG ("Opening mixer card %s.\n", (const char *) mixer);
+    CHECK_NOISY (snd_mixer_open, & alsa_mixer, 0);
+    CHECK_NOISY (snd_mixer_attach, alsa_mixer, mixer);
+    CHECK_NOISY (snd_mixer_selem_register, alsa_mixer, nullptr, nullptr);
+    CHECK_NOISY (snd_mixer_load, alsa_mixer);
+
+    snd_mixer_selem_id_t * selem_id;
+    snd_mixer_selem_id_alloca (& selem_id);
+    snd_mixer_selem_id_set_name (selem_id, mixer_element);
+    alsa_mixer_element = snd_mixer_find_selem (alsa_mixer, selem_id);
+
+    if (! alsa_mixer_element)
+    {
+        ERROR_NOISY ("snd_mixer_find_selem failed.\n");
+        goto FAILED;
+    }
+
+    CHECK (snd_mixer_selem_set_playback_volume_range, alsa_mixer_element, 0, 100);
+    return;
+
+FAILED:
+    if (alsa_mixer)
+    {
+        snd_mixer_close (alsa_mixer);
+        alsa_mixer = nullptr;
+    }
+}
+
+void ALSAPlugin::close_mixer ()
+{
+    if (alsa_mixer)
+        snd_mixer_close (alsa_mixer);
+}
+
+StereoVolume ALSAPlugin::get_volume ()
+{
+    pthread_mutex_lock (& alsa_mutex);
+
+    long left = 0, right = 0;
+
+    if (! alsa_mixer)
+        goto FAILED;
+
+    CHECK (snd_mixer_handle_events, alsa_mixer);
+
+    if (snd_mixer_selem_is_playback_mono (alsa_mixer_element))
+    {
+        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_MONO, & left);
+        right = left;
+
+        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
+        {
+            int on = 0;
+            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
+             SND_MIXER_SCHN_MONO, & on);
+
+            if (! on)
+                left = right = 0;
+        }
+    }
+    else
+    {
+        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_FRONT_LEFT, & left);
+        CHECK (snd_mixer_selem_get_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_FRONT_RIGHT, & right);
+
+        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
+        {
+            int left_on = 0, right_on = 0;
+            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
+             SND_MIXER_SCHN_FRONT_LEFT, & left_on);
+            CHECK (snd_mixer_selem_get_playback_switch, alsa_mixer_element,
+             SND_MIXER_SCHN_FRONT_RIGHT, & right_on);
+
+            if (! left_on)
+                left = 0;
+            if (! right_on)
+                right = 0;
+        }
+    }
+
+FAILED:
+    pthread_mutex_unlock (& alsa_mutex);
+    return {(int) left, (int) right};
+}
+
+void ALSAPlugin::set_volume (StereoVolume v)
+{
+    pthread_mutex_lock (& alsa_mutex);
+
+    if (! alsa_mixer)
+        goto FAILED;
+
+    if (snd_mixer_selem_is_playback_mono (alsa_mixer_element))
+    {
+        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_MONO, aud::max (v.left, v.right));
+
+        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
+            CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
+             SND_MIXER_SCHN_MONO, aud::max (v.left, v.right) != 0);
+    }
+    else
+    {
+        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_FRONT_LEFT, v.left);
+        CHECK (snd_mixer_selem_set_playback_volume, alsa_mixer_element,
+         SND_MIXER_SCHN_FRONT_RIGHT, v.right);
+
+        if (snd_mixer_selem_has_playback_switch (alsa_mixer_element))
+        {
+            if (snd_mixer_selem_has_playback_switch_joined (alsa_mixer_element))
+                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
+                 SND_MIXER_SCHN_FRONT_LEFT, aud::max (v.left, v.right) != 0);
+            else
+            {
+                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
+                 SND_MIXER_SCHN_FRONT_LEFT, v.left != 0);
+                CHECK (snd_mixer_selem_set_playback_switch, alsa_mixer_element,
+                 SND_MIXER_SCHN_FRONT_RIGHT, v.right != 0);
+            }
+        }
+    }
+
+    CHECK (snd_mixer_handle_events, alsa_mixer);
+
+FAILED:
+    pthread_mutex_unlock (& alsa_mutex);
+}
diff --git a/src/alsa/alsa.h b/src/alsa/alsa.h
index 294e38c12b3f..f59c24cb770f 100644
--- a/src/alsa/alsa.h
+++ b/src/alsa/alsa.h
@@ -1,6 +1,6 @@
 /*
  * ALSA Output Plugin for Audacious
- * Copyright 2009-2012 John Lindgren
+ * Copyright 2009-2014 John Lindgren
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -20,15 +20,16 @@
 #ifndef AUDACIOUS_ALSA_H
 #define AUDACIOUS_ALSA_H
 
-#include <stdio.h>
-#include <audacious/misc.h>
 #include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
 
-#define ERROR(...) fprintf (stderr, "alsa: " __VA_ARGS__)
+#define ERROR AUDERR
 
 #define ERROR_NOISY(...) do { \
-    SPRINTF (ERROR_NOISY_buf, "ALSA error: " __VA_ARGS__); \
-    aud_interface_show_error (ERROR_NOISY_buf); \
+    aud_ui_show_error (str_printf ("ALSA error: " __VA_ARGS__)); \
 } while (0)
 
 #define CHECK_VAL(value, function, ...) \
@@ -55,30 +56,51 @@ do { \
     } \
 } while (0)
 
-/* alsa.c */
-int alsa_init (void);
-void alsa_cleanup (void);
-int alsa_open_audio (int aud_format, int rate, int channels);
-void alsa_close_audio (void);
-int alsa_buffer_free (void);
-void alsa_write_audio (void * data, int length);
-void alsa_period_wait (void);
-void alsa_drain (void);
-int alsa_output_time (void);
-void alsa_flush (int time);
-void alsa_pause (int pause);
-void alsa_open_mixer (void);
-void alsa_close_mixer (void);
-void alsa_get_volume (int * left, int * right);
-void alsa_set_volume (int left, int right);
-
-/* config.c */
-extern char * alsa_config_pcm, * alsa_config_mixer, * alsa_config_mixer_element;
-extern int alsa_config_drop_workaround, alsa_config_drain_workaround,
- alsa_config_delay_workaround;
-
-void alsa_config_load (void);
-void alsa_config_save (void);
-void * alsa_create_config_widget (void);
+struct PreferencesWidget;
+
+class ALSAPlugin : public OutputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("ALSA Output"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr ALSAPlugin () : OutputPlugin (info, 5) {}
+
+    bool init ();
+    void cleanup ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int aud_format, int rate, int chans);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+
+private:
+    static void open_mixer ();
+    static void close_mixer ();
+
+    static void init_config ();
+    static void pcm_changed ();
+    static void mixer_changed ();
+    static void element_changed ();
+};
 
 #endif
diff --git a/src/alsa/config.c b/src/alsa/config.c
deleted file mode 100644
index cee3bc86e096..000000000000
--- a/src/alsa/config.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * ALSA Output Plugin for Audacious
- * Copyright 2009-2012 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 <alsa/asoundlib.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-
-#include "alsa.h"
-
-char * alsa_config_pcm = NULL, * alsa_config_mixer = NULL,
- * alsa_config_mixer_element = NULL;
-int alsa_config_drain_workaround = 1;
-
-static GtkListStore * pcm_list, * mixer_list, * mixer_element_list;
-static GtkWidget * pcm_combo, * mixer_combo, * mixer_element_combo, * drain_workaround_check;
-
-static GtkTreeIter * list_lookup_member (GtkListStore * list, const char * text)
-{
-    static GtkTreeIter iter;
-
-    if (! gtk_tree_model_get_iter_first ((GtkTreeModel *) list, & iter))
-        return NULL;
-
-    do
-    {
-        char * iter_text;
-
-        gtk_tree_model_get ((GtkTreeModel *) list, & iter, 0, & iter_text, -1);
-
-        if (! strcmp (iter_text, text))
-        {
-            g_free (iter_text);
-            return & iter;
-        }
-
-        g_free (iter_text);
-    }
-    while (gtk_tree_model_iter_next ((GtkTreeModel *) list, & iter));
-
-    return NULL;
-}
-
-static int list_has_member (GtkListStore * list, const char * text)
-{
-    return (list_lookup_member (list, text) != NULL);
-}
-
-static void get_defined_devices (const char * type, int capture, void (* found)
- (const char * name, const char * description))
-{
-    void * * hints = NULL;
-    int count;
-
-    CHECK (snd_device_name_hint, -1, type, & hints);
-
-    for (count = 0; hints[count] != NULL; count ++)
-    {
-        char * type = snd_device_name_get_hint (hints[count], "IOID");
-
-        if (type == NULL || ! strcmp (type, capture ? "Input" : "Output"))
-        {
-            char * name = snd_device_name_get_hint (hints[count], "NAME");
-            char * description = snd_device_name_get_hint (hints[count], "DESC");
-
-            found (name, description);
-            g_free (name);
-            g_free (description);
-        }
-
-        g_free (type);
-    }
-
-FAILED:
-    if (hints != NULL)
-        snd_device_name_free_hint (hints);
-}
-
-static char * get_card_description (int card)
-{
-    char * description = NULL;
-
-    CHECK (snd_card_get_name, card, & description);
-
-FAILED:
-    return description;
-}
-
-static void get_cards (void (* found) (int card, const char * description))
-{
-    int card = -1;
-
-    while (1)
-    {
-        char * description;
-
-        CHECK (snd_card_next, & card);
-
-        if (card < 0)
-            break;
-
-        if ((description = get_card_description (card)) != NULL)
-        {
-            found (card, description);
-            g_free (description);
-        }
-    }
-
-FAILED:
-    return;
-}
-
-static char * get_device_description (snd_ctl_t * control, int device, int
- capture)
-{
-    snd_pcm_info_t * info;
-
-    snd_pcm_info_alloca (& info);
-    snd_pcm_info_set_device (info, device);
-    snd_pcm_info_set_stream (info, capture ? SND_PCM_STREAM_CAPTURE :
-     SND_PCM_STREAM_PLAYBACK);
-
-    switch (snd_ctl_pcm_info (control, info))
-    {
-    case 0:
-        return g_strdup (snd_pcm_info_get_name (info));
-
-    case -ENOENT: /* capture but we want playback (or other way around) */
-        return NULL;
-    }
-
-    CHECK (snd_ctl_pcm_info, control, info);
-
-FAILED:
-    return NULL;
-}
-
-static void get_devices (int card, int capture, void (* found) (const char *
- name, const char * description))
-{
-    char card_name[16];
-    snd_ctl_t * control = NULL;
-    int device = -1;
-
-    snprintf (card_name, sizeof card_name, "hw:%d", card);
-    CHECK (snd_ctl_open, & control, card_name, 0);
-
-    while (1)
-    {
-        char name[16];
-        char * description;
-
-        CHECK (snd_ctl_pcm_next_device, control, & device);
-
-        if (device < 0)
-            break;
-
-        snprintf (name, sizeof name, "hw:%d,%d", card, device);
-        description = get_device_description (control, device, capture);
-
-        if (description != NULL)
-            found (name, description);
-
-        g_free (description);
-    }
-
-FAILED:
-    if (control != NULL)
-        snd_ctl_close (control);
-}
-
-static void pcm_found (const char * name, const char * description)
-{
-    GtkTreeIter iter;
-    char new[512];
-
-    gtk_list_store_append (pcm_list, & iter);
-    snprintf (new, sizeof new, "(%s)", description);
-    gtk_list_store_set (pcm_list, & iter, 0, name, 1, new, -1);
-}
-
-static void pcm_card_found (int card, const char * description)
-{
-    get_devices (card, 0, pcm_found);
-}
-
-static void pcm_list_fill (void)
-{
-    if (pcm_list)
-        return;
-
-    pcm_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-    pcm_found ("default", _("Default PCM device"));
-    get_defined_devices ("pcm", 0, pcm_found);
-    get_cards (pcm_card_found);
-}
-
-static void mixer_found (const char * name, const char * description)
-{
-    GtkTreeIter iter;
-    char new[512];
-
-    gtk_list_store_append (mixer_list, & iter);
-    snprintf (new, sizeof new, "(%s)", description);
-    gtk_list_store_set (mixer_list, & iter, 0, name, 1, new, -1);
-}
-
-static void mixer_card_found (int card, const char * description)
-{
-    char name[16];
-
-    snprintf (name, sizeof name, "hw:%d", card);
-    mixer_found (name, description);
-}
-
-static void mixer_list_fill (void)
-{
-    if (mixer_list)
-        return;
-
-    mixer_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-    mixer_found ("default", _("Default mixer device"));
-    get_defined_devices ("ctl", 0, mixer_found);
-    get_cards (mixer_card_found);
-}
-
-static void get_mixer_elements (const char * mixer, void (* found)
- (const char * name))
-{
-    snd_mixer_t * mixer_handle = NULL;
-    snd_mixer_elem_t * element;
-
-    CHECK (snd_mixer_open, & mixer_handle, 0);
-    CHECK (snd_mixer_attach, mixer_handle, mixer);
-    CHECK (snd_mixer_selem_register, mixer_handle, NULL, NULL);
-    CHECK (snd_mixer_load, mixer_handle);
-
-    element = snd_mixer_first_elem (mixer_handle);
-
-    while (element != NULL)
-    {
-        if (snd_mixer_selem_has_playback_volume (element))
-            found (snd_mixer_selem_get_name (element));
-
-        element = snd_mixer_elem_next (element);
-    }
-
-FAILED:
-    if (mixer_handle != NULL)
-        snd_mixer_close (mixer_handle);
-}
-
-static void mixer_element_found (const char * name)
-{
-    GtkTreeIter iter;
-
-    gtk_list_store_append (mixer_element_list, & iter);
-    gtk_list_store_set (mixer_element_list, & iter, 0, name, -1);
-}
-
-static void mixer_element_list_fill (void)
-{
-    if (mixer_element_list)
-        return;
-
-    mixer_element_list = gtk_list_store_new (1, G_TYPE_STRING);
-    get_mixer_elements (alsa_config_mixer, mixer_element_found);
-}
-
-static void mixer_element_list_refill (void)
-{
-    gtk_list_store_clear (mixer_element_list);
-    get_mixer_elements (alsa_config_mixer, mixer_element_found);
-}
-
-static void guess_mixer_element (void)
-{
-    mixer_element_list_fill ();
-
-    static const char * guesses[] = {"Master", "PCM", "Wave"};
-    for (int count = 0; count < ARRAY_LEN (guesses); count ++)
-    {
-        if (list_has_member (mixer_element_list, guesses[count]))
-        {
-            str_unref (alsa_config_mixer_element);
-            alsa_config_mixer_element = str_get (guesses[count]);
-            return;
-        }
-    }
-
-    ERROR_NOISY ("No suitable mixer element found.\n");
-}
-
-static const gchar * const alsa_defaults[] = {
- "pcm", "default",
- "mixer", "default",
- "drain-workaround", "TRUE",
- NULL};
-
-void alsa_config_load (void)
-{
-    aud_config_set_defaults ("alsa", alsa_defaults);
-
-    alsa_config_pcm = aud_get_str ("alsa", "pcm");
-    alsa_config_mixer = aud_get_str ("alsa", "mixer");
-    alsa_config_mixer_element = aud_get_str ("alsa", "mixer-element");
-    alsa_config_drain_workaround = aud_get_bool ("alsa", "drain-workaround");
-
-    if (! alsa_config_mixer_element[0])
-        guess_mixer_element ();
-}
-
-void alsa_config_save (void)
-{
-    if (pcm_list)
-    {
-        g_object_unref (pcm_list);
-        pcm_list = NULL;
-    }
-
-    if (mixer_list)
-    {
-        g_object_unref (mixer_list);
-        mixer_list = NULL;
-    }
-
-    if (mixer_element_list)
-    {
-        g_object_unref (mixer_element_list);
-        mixer_element_list = NULL;
-    }
-
-    aud_set_str ("alsa", "pcm", alsa_config_pcm);
-    aud_set_str ("alsa", "mixer", alsa_config_mixer);
-    aud_set_str ("alsa", "mixer-element", alsa_config_mixer_element);
-    aud_set_bool ("alsa", "drain-workaround", alsa_config_drain_workaround);
-
-    str_unref (alsa_config_pcm);
-    alsa_config_pcm = NULL;
-    str_unref (alsa_config_mixer);
-    alsa_config_mixer = NULL;
-    str_unref (alsa_config_mixer_element);
-    alsa_config_mixer_element = NULL;
-}
-
-static GtkWidget * combo_new (const char * title, GtkListStore * list,
- GtkWidget * * combo, int has_description)
-{
-    GtkWidget * hbox, * label;
-    GtkCellRenderer * cell;
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-
-    label = gtk_label_new (title);
-    gtk_box_pack_start ((GtkBox *) hbox, label, 0, 0, 0);
-
-    * combo = gtk_combo_box_new_with_model ((GtkTreeModel *) list);
-    gtk_box_pack_start ((GtkBox *) hbox, * combo, 1, 1, 0);
-
-    cell = gtk_cell_renderer_text_new ();
-    gtk_cell_layout_pack_start ((GtkCellLayout *) * combo, cell, 0);
-    gtk_cell_layout_set_attributes ((GtkCellLayout *) * combo, cell, "text", 0,
-     NULL);
-
-    if (has_description)
-    {
-        cell = gtk_cell_renderer_text_new ();
-        gtk_cell_layout_pack_start ((GtkCellLayout *) * combo, cell, 0);
-        gtk_cell_layout_set_attributes ((GtkCellLayout *) * combo, cell, "text",
-         1, NULL);
-    }
-
-    return hbox;
-}
-
-static void combo_select_by_text (GtkWidget * combo, GtkListStore * list,
- const char * text)
-{
-    GtkTreeIter * iter;
-
-    if (text == NULL)
-    {
-        gtk_combo_box_set_active ((GtkComboBox *) combo, -1);
-        return;
-    }
-
-    iter = list_lookup_member (list, text);
-
-    if (iter == NULL)
-        return;
-
-    gtk_combo_box_set_active_iter ((GtkComboBox *) combo, iter);
-}
-
-static const char * combo_selected_text (GtkWidget * combo, GtkListStore * list)
-{
-    GtkTreeIter iter;
-    const char * text;
-
-    if (! gtk_combo_box_get_active_iter ((GtkComboBox *) combo, & iter))
-        return NULL;
-
-    gtk_tree_model_get ((GtkTreeModel *) list, & iter, 0, & text, -1);
-    return text;
-}
-
-static GtkWidget * create_vbox (void)
-{
-    GtkWidget * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-
-    gtk_box_pack_start ((GtkBox *) vbox, combo_new (_("PCM device:"), pcm_list,
-     & pcm_combo, 1), 0, 0, 0);
-    gtk_box_pack_start ((GtkBox *) vbox, combo_new (_("Mixer device:"),
-     mixer_list, & mixer_combo, 1), 0, 0, 0);
-    gtk_box_pack_start ((GtkBox *) vbox, combo_new (_("Mixer element:"),
-     mixer_element_list, & mixer_element_combo, 0), 0, 0, 0);
-
-    drain_workaround_check = gtk_check_button_new_with_label (_("Work around "
-     "drain hangup"));
-    gtk_toggle_button_set_active ((GtkToggleButton *) drain_workaround_check,
-     alsa_config_drain_workaround);
-    gtk_box_pack_start ((GtkBox *) vbox, drain_workaround_check, 0, 0, 0);
-
-    return vbox;
-}
-
-static void pcm_changed (GtkComboBox * combo, void * unused)
-{
-    const char * new = combo_selected_text (pcm_combo, pcm_list);
-
-    if (new == NULL || ! strcmp (new, alsa_config_pcm))
-        return;
-
-    str_unref (alsa_config_pcm);
-    alsa_config_pcm = str_get (combo_selected_text (pcm_combo, pcm_list));
-
-    aud_output_reset (OUTPUT_RESET_SOFT);
-}
-
-static void mixer_changed (GtkComboBox * combo, void * unused)
-{
-    const char * new = combo_selected_text (mixer_combo, mixer_list);
-
-    if (new == NULL || ! strcmp (new, alsa_config_mixer))
-        return;
-
-    str_unref (alsa_config_mixer);
-    alsa_config_mixer = str_get (new);
-
-    mixer_element_list_refill ();
-    guess_mixer_element ();
-    combo_select_by_text (mixer_element_combo, mixer_element_list,
-     alsa_config_mixer_element);
-
-    alsa_close_mixer ();
-    alsa_open_mixer ();
-}
-
-static void mixer_element_changed (GtkComboBox * combo, void * unused)
-{
-    const char * new = combo_selected_text (mixer_element_combo,
-     mixer_element_list);
-
-    if (new == NULL || (alsa_config_mixer_element != NULL && ! strcmp (new,
-     alsa_config_mixer_element)))
-        return;
-
-    str_unref (alsa_config_mixer_element);
-    alsa_config_mixer_element = str_get (new);
-
-    alsa_close_mixer ();
-    alsa_open_mixer ();
-}
-
-static void boolean_toggled (GtkToggleButton * button, void * data)
-{
-    * (int *) data = gtk_toggle_button_get_active (button);
-}
-
-static void connect_callbacks (void)
-{
-    g_signal_connect ((GObject *) pcm_combo, "changed", (GCallback) pcm_changed,
-     NULL);
-    g_signal_connect ((GObject *) mixer_combo, "changed", (GCallback)
-     mixer_changed, NULL);
-    g_signal_connect ((GObject *) mixer_element_combo, "changed", (GCallback)
-     mixer_element_changed, NULL);
-    g_signal_connect ((GObject *) drain_workaround_check, "toggled", (GCallback)
-     boolean_toggled, & alsa_config_drain_workaround);
-}
-
-void * alsa_create_config_widget (void)
-{
-    pcm_list_fill ();
-    mixer_list_fill ();
-    mixer_element_list_fill ();
-
-    GtkWidget * vbox = create_vbox ();
-
-    combo_select_by_text (pcm_combo, pcm_list, alsa_config_pcm);
-    combo_select_by_text (mixer_combo, mixer_list, alsa_config_mixer);
-    combo_select_by_text (mixer_element_combo, mixer_element_list,
-     alsa_config_mixer_element);
-
-    connect_callbacks ();
-
-    return vbox;
-}
diff --git a/src/alsa/config.cc b/src/alsa/config.cc
new file mode 100644
index 000000000000..ffe95766a45b
--- /dev/null
+++ b/src/alsa/config.cc
@@ -0,0 +1,330 @@
+/*
+ * ALSA Output Plugin for Audacious
+ * Copyright 2009-2014 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 <alsa/asoundlib.h>
+
+#include <libaudcore/hook.h>
+#include <libaudcore/preferences.h>
+
+#include "alsa.h"
+
+const char ALSAPlugin::about[] =
+ N_("ALSA Output Plugin for Audacious\n"
+    "Copyright 2009-2012 John Lindgren\n\n"
+    "My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
+    "code served as a reference when the ALSA manual was not enough.");
+
+struct NameDescPair {
+    String name, desc;
+};
+
+static Index<NameDescPair> pcm_list;
+static Index<NameDescPair> mixer_list;
+static Index<String> element_list;
+
+static Index<ComboItem> pcm_combo_items;
+static Index<ComboItem> mixer_combo_items;
+static Index<ComboItem> element_combo_items;
+
+static void get_defined_devices (const char * type,
+ void (* found) (const char * name, const char * description))
+{
+    void * * hints = nullptr;
+    CHECK (snd_device_name_hint, -1, type, & hints);
+
+    for (int i = 0; hints[i]; i ++)
+    {
+        char * type = snd_device_name_get_hint (hints[i], "IOID");
+
+        if (! type || ! strcmp (type, "Output"))
+        {
+            char * name = snd_device_name_get_hint (hints[i], "NAME");
+            char * description = snd_device_name_get_hint (hints[i], "DESC");
+
+            if (name && strcmp (name, "default"))
+                found (name, description ? description : _("(no description)"));
+
+            free (name);
+            free (description);
+        }
+
+        free (type);
+    }
+
+FAILED:
+    if (hints)
+        snd_device_name_free_hint (hints);
+}
+
+static char * get_card_description (int card)
+{
+    char * description = nullptr;
+    CHECK (snd_card_get_name, card, & description);
+
+FAILED:
+    return description;
+}
+
+static void get_cards (void (* found) (int card, const char * description))
+{
+    for (int card = -1;;)
+    {
+        CHECK (snd_card_next, & card);
+        if (card < 0)
+            break;
+
+        char * description = get_card_description (card);
+        if (description)
+        {
+            found (card, description);
+            free (description);
+        }
+    }
+
+FAILED:
+    return;
+}
+
+static String get_device_description (snd_ctl_t * control, int device)
+{
+    snd_pcm_info_t * info;
+    snd_pcm_info_alloca (& info);
+    snd_pcm_info_set_device (info, device);
+    snd_pcm_info_set_stream (info, SND_PCM_STREAM_PLAYBACK);
+
+    switch (snd_ctl_pcm_info (control, info))
+    {
+    case 0:
+        return String (snd_pcm_info_get_name (info));
+
+    case -ENOENT: /* capture device? */
+        return String ();
+    }
+
+    CHECK (snd_ctl_pcm_info, control, info);
+
+FAILED:
+    return String ();
+}
+
+static void get_devices (int card, void (* found) (const char * name, const char * description))
+{
+    snd_ctl_t * control = nullptr;
+    CHECK (snd_ctl_open, & control, str_printf ("hw:%d", card), 0);
+
+    for (int device = -1;;)
+    {
+        CHECK (snd_ctl_pcm_next_device, control, & device);
+        if (device < 0)
+            break;
+
+        StringBuf name = str_printf ("hw:%d,%d", card, device);
+        String description = get_device_description (control, device);
+
+        if (description)
+            found (name, description);
+    }
+
+FAILED:
+    if (control)
+        snd_ctl_close (control);
+}
+
+static void pcm_found (const char * name, const char * description)
+{
+    NameDescPair & pair = pcm_list.append (
+        String (name),
+        String (str_concat ({name, " – ", description}))
+    );
+
+    pcm_combo_items.append (pair.desc, pair.name);
+}
+
+static void pcm_card_found (int card, const char * description)
+{
+    get_devices (card, pcm_found);
+}
+
+static void pcm_list_fill ()
+{
+    pcm_found ("default", _("Default PCM device"));
+    get_defined_devices ("pcm", pcm_found);
+    get_cards (pcm_card_found);
+}
+
+static void mixer_found (const char * name, const char * description)
+{
+    NameDescPair & pair = mixer_list.append (
+        String (name),
+        String (str_concat ({name, " – ", description}))
+    );
+
+    mixer_combo_items.append (pair.desc, pair.name);
+}
+
+static void mixer_card_found (int card, const char * description)
+{
+    mixer_found (str_printf ("hw:%d", card), description);
+}
+
+static void mixer_list_fill ()
+{
+    mixer_found ("default", _("Default mixer device"));
+    get_defined_devices ("ctl", mixer_found);
+    get_cards (mixer_card_found);
+}
+
+static void get_elements (void (* found) (const char * name))
+{
+    snd_mixer_t * mixer_handle = nullptr;
+    CHECK (snd_mixer_open, & mixer_handle, 0);
+    CHECK (snd_mixer_attach, mixer_handle, aud_get_str ("alsa", "mixer"));
+    CHECK (snd_mixer_selem_register, mixer_handle, nullptr, nullptr);
+    CHECK (snd_mixer_load, mixer_handle);
+
+    for (snd_mixer_elem_t * element = snd_mixer_first_elem (mixer_handle);
+     element; element = snd_mixer_elem_next (element))
+    {
+        if (snd_mixer_selem_has_playback_volume (element))
+            found (snd_mixer_selem_get_name (element));
+    }
+
+FAILED:
+    if (mixer_handle)
+        snd_mixer_close (mixer_handle);
+}
+
+static void element_found (const char * name)
+{
+    String & str = element_list.append (String (name));
+    element_combo_items.append (str, str);
+}
+
+static void element_list_fill ()
+{
+    get_elements (element_found);
+}
+
+static void guess_element ()
+{
+    for (const char * guess : {"Master", "PCM", "Wave"})
+    {
+        for (const String & element : element_list)
+        {
+            if (! strcmp (element, guess))
+            {
+                aud_set_str ("alsa", "mixer-element", guess);
+                return;
+            }
+        }
+    }
+
+    ERROR_NOISY ("No suitable mixer element found.\n");
+}
+
+const char * const ALSAPlugin::defaults[] = {
+    "pcm", "default",
+    "mixer", "default",
+    nullptr
+};
+
+void ALSAPlugin::init_config ()
+{
+    aud_config_set_defaults ("alsa", defaults);
+
+    String element = aud_get_str ("alsa", "mixer-element");
+
+    if (! element[0])
+    {
+        element_list_fill ();
+        guess_element ();
+
+        element_list.clear ();
+        element_combo_items.clear ();
+    }
+}
+
+void ALSAPlugin::pcm_changed ()
+{
+    aud_output_reset (OutputReset::ReopenStream);
+}
+
+void ALSAPlugin::mixer_changed ()
+{
+    element_list.clear ();
+    element_combo_items.clear ();
+
+    element_list_fill ();
+    guess_element ();
+
+    hook_call ("alsa mixer changed", nullptr);
+
+    close_mixer ();
+    open_mixer ();
+}
+
+void ALSAPlugin::element_changed ()
+{
+    close_mixer ();
+    open_mixer ();
+}
+
+static ArrayRef<ComboItem> pcm_combo_fill ()
+    { return {pcm_combo_items.begin (), pcm_combo_items.len ()}; }
+static ArrayRef<ComboItem> mixer_combo_fill ()
+    { return {mixer_combo_items.begin (), mixer_combo_items.len ()}; }
+static ArrayRef<ComboItem> element_combo_fill ()
+    { return {element_combo_items.begin (), element_combo_items.len ()}; }
+
+const PreferencesWidget ALSAPlugin::widgets[] = {
+    WidgetCombo (N_("PCM device:"),
+        WidgetString ("alsa", "pcm", pcm_changed),
+        {nullptr, pcm_combo_fill}),
+    WidgetCombo (N_("Mixer device:"),
+        WidgetString ("alsa", "mixer", mixer_changed),
+        {nullptr, mixer_combo_fill}),
+    WidgetCombo (N_("Mixer element:"),
+        WidgetString ("alsa", "mixer-element", element_changed, "alsa mixer changed"),
+        {nullptr, element_combo_fill})
+};
+
+static void alsa_prefs_init ()
+{
+    pcm_list_fill ();
+    mixer_list_fill ();
+    element_list_fill ();
+}
+
+static void alsa_prefs_cleanup ()
+{
+    pcm_list.clear ();
+    mixer_list.clear ();
+    element_list.clear ();
+
+    pcm_combo_items.clear ();
+    mixer_combo_items.clear ();
+    element_combo_items.clear ();
+}
+
+const PluginPreferences ALSAPlugin::prefs = {
+    {widgets},
+    alsa_prefs_init,
+    nullptr,  // apply
+    alsa_prefs_cleanup
+};
diff --git a/src/alsa/plugin.c b/src/alsa/plugin.c
deleted file mode 100644
index c54517f110c5..000000000000
--- a/src/alsa/plugin.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * ALSA Output Plugin for Audacious
- * Copyright 2009-2012 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 <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#include "alsa.h"
-
-static const char alsa_about[] =
- N_("ALSA Output Plugin for Audacious\n"
-    "Copyright 2009-2012 John Lindgren\n\n"
-    "My thanks to William Pitcock, author of the ALSA Output Plugin NG, whose "
-    "code served as a reference when the ALSA manual was not enough.");
-
-static const PreferencesWidget alsa_widgets[] = {
- {WIDGET_CUSTOM, .data = {.populate = alsa_create_config_widget}}};
-
-static const PluginPreferences alsa_prefs = {
- .widgets = alsa_widgets,
- .n_widgets = ARRAY_LEN (alsa_widgets)};
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("ALSA Output"),
-    .domain = PACKAGE,
-    .about_text = alsa_about,
-    .probe_priority = 5,
-    .init = alsa_init,
-    .cleanup = alsa_cleanup,
-    .open_audio = alsa_open_audio,
-    .close_audio = alsa_close_audio,
-    .buffer_free = alsa_buffer_free,
-    .write_audio = alsa_write_audio,
-    .period_wait = alsa_period_wait,
-    .drain = alsa_drain,
-    .output_time = alsa_output_time,
-    .flush = alsa_flush,
-    .pause = alsa_pause,
-    .set_volume = alsa_set_volume,
-    .get_volume = alsa_get_volume,
-    .prefs = & alsa_prefs,
-)
diff --git a/src/amidi-plug/Makefile b/src/amidi-plug/Makefile
index 40edc8e1e180..dac6d08ee311 100644
--- a/src/amidi-plug/Makefile
+++ b/src/amidi-plug/Makefile
@@ -1,18 +1,19 @@
 PLUGIN = amidi-plug${PLUGIN_SUFFIX}
 
-SRCS = amidi-plug.c		\
-       backend-fluidsynth/b-fluidsynth.c \
-       i_midi.c			\
-       i_configure.c		\
-       i_configure-fluidsynth.c	\
-       i_utils.c		\
-       i_fileinfo.c
+SRCS = amidi-plug.cc		\
+       backend-fluidsynth/b-fluidsynth.cc \
+       i_midi.cc			\
+       i_configure.cc		\
+       i_configure-fluidsynth.cc	\
+       i_fileinfo.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${FLUIDSYNTH_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} ${FLUIDSYNTH_LIBS} -lm
diff --git a/src/amidi-plug/amidi-plug.c b/src/amidi-plug/amidi-plug.c
deleted file mode 100644
index 9c765eff2616..000000000000
--- a/src/amidi-plug/amidi-plug.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-
-#include "i_backend.h"
-#include "i_configure.h"
-#include "i_fileinfo.h"
-#include "i_midi.h"
-#include "i_utils.h"
-
-enum
-{
-    AMIDIPLUG_STOP,
-    AMIDIPLUG_PLAY,
-    AMIDIPLUG_ERR
-};
-
-static void amidiplug_play_loop (void);
-
-static bool_t amidiplug_play (const char * filename_uri, VFSFile * file);
-static Tuple * amidiplug_get_song_tuple (const char * filename_uri, VFSFile * file);
-static void amidiplug_skipto (int playing_tick);
-
-static midifile_t midifile;
-
-static const char * const amidiplug_vfs_extensions[] = {"mid", "midi", "rmi", "rmid", NULL};
-
-static void amidiplug_cleanup (void)
-{
-    backend_cleanup ();
-}
-
-static bool_t amidiplug_init (void)
-{
-    static const char * const defaults[] =
-    {
-        "ap_opts_transpose_value", "0",
-        "ap_opts_drumshift_value", "0",
-        "ap_opts_lyrics_extract", "0",
-        "ap_opts_comments_extract", "0",
-        "fsyn_synth_samplerate", "44100",
-        "fsyn_synth_gain", "-1",
-        "fsyn_synth_polyphony", "-1",
-        "fsyn_synth_reverb", "-1",
-        "fsyn_synth_chorus", "-1",
-        NULL
-    };
-
-    aud_config_set_defaults ("amidiplug", defaults);
-
-    backend_init ();
-
-    return TRUE;
-}
-
-static int amidiplug_is_our_file_from_vfs (const char * filename_uri, VFSFile * fp)
-{
-    char magic_bytes[4];
-
-    if (fp == NULL)
-        return FALSE;
-
-    if (vfs_fread (magic_bytes, 1, 4, fp) != 4)
-        return FALSE;
-
-    if (!strncmp (magic_bytes, "MThd", 4))
-    {
-        AUDDBG ("MIDI found, %s is a standard midi file\n", filename_uri);
-        return TRUE;
-    }
-
-    if (!strncmp (magic_bytes, "RIFF", 4))
-    {
-        /* skip the four bytes after RIFF,
-           then read the next four */
-        if (vfs_fseek (fp, 4, SEEK_CUR) != 0)
-            return FALSE;
-
-        if (vfs_fread (magic_bytes, 1, 4, fp) != 4)
-            return FALSE;
-
-        if (!strncmp (magic_bytes, "RMID", 4))
-        {
-            AUDDBG ("MIDI found, %s is a riff midi file\n", filename_uri);
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-}
-
-static Tuple * amidiplug_get_song_tuple (const char * filename_uri, VFSFile *
-        file)
-{
-    /* song title, get it from the filename */
-    Tuple * tuple = tuple_new_from_filename (filename_uri);
-    midifile_t mf;
-
-    if (i_midi_parse_from_filename (filename_uri, &mf))
-        tuple_set_int (tuple, FIELD_LENGTH, mf.length / 1000);
-
-    i_midi_free (&mf);
-
-    return tuple;
-}
-
-
-static int s_samplerate, s_channels;
-static int s_bufsize;
-static void * s_buf;
-
-static bool_t audio_init (void)
-{
-    int bitdepth;
-
-    backend_audio_info (& s_channels, & bitdepth, & s_samplerate);
-
-    if (bitdepth != 16 || ! aud_input_open_audio (FMT_S16_NE, s_samplerate, s_channels))
-        return FALSE;
-
-    s_bufsize = 2 * s_channels * (s_samplerate / 4);
-    s_buf = g_malloc (s_bufsize);
-
-    return TRUE;
-}
-
-static void audio_generate (double seconds)
-{
-    int total = 2 * s_channels * (int) round (seconds * s_samplerate);
-
-    while (total)
-    {
-        int chunk = (total < s_bufsize) ? total : s_bufsize;
-
-        backend_generate_audio (s_buf, chunk);
-        aud_input_write_audio (s_buf, chunk);
-
-        total -= chunk;
-    }
-}
-
-static void audio_cleanup (void)
-{
-    g_free (s_buf);
-}
-
-static bool_t amidiplug_play (const char * filename_uri, VFSFile * file)
-{
-    if (g_atomic_int_compare_and_exchange (& backend_settings_changed, TRUE, FALSE))
-    {
-        AUDDBG ("Settings changed, reinitializing backend\n");
-        backend_cleanup ();
-        backend_init ();
-    }
-
-    if (! audio_init ())
-        return FALSE;
-
-    AUDDBG ("PLAY requested, midifile init\n");
-    /* midifile init */
-    i_midi_init (&midifile);
-
-    AUDDBG ("PLAY requested, opening file: %s\n", filename_uri);
-    midifile.file_pointer = file;
-    midifile.file_name = g_strdup (filename_uri);
-
-    switch (i_midi_file_read_id (&midifile))
-    {
-    case MAKE_ID ('R', 'I', 'F', 'F') :
-        AUDDBG ("PLAY requested, RIFF chunk found, processing...\n");
-
-        /* read riff chunk */
-        if (!i_midi_file_parse_riff (&midifile))
-        {
-            fprintf (stderr, "%s: invalid file format (riff parser)\n", filename_uri);
-            goto ERR;
-        }
-
-        /* if that was read correctly, go ahead and read smf data */
-
-    case MAKE_ID ('M', 'T', 'h', 'd') :
-        AUDDBG ("PLAY requested, MThd chunk found, processing...\n");
-
-        if (!i_midi_file_parse_smf (&midifile, 1))
-        {
-            fprintf (stderr, "%s: invalid file format (smf parser)\n", filename_uri);
-            goto ERR;
-        }
-
-        if (midifile.time_division < 1)
-        {
-            fprintf (stderr, "%s: invalid time division (%i)\n", filename_uri, midifile.time_division);
-            goto ERR;
-        }
-
-        AUDDBG ("PLAY requested, setting ppq and tempo...\n");
-
-        /* fill midifile.ppq and midifile.tempo using time_division */
-        if (!i_midi_setget_tempo (&midifile))
-        {
-            fprintf (stderr, "%s: invalid values while setting ppq and tempo\n", filename_uri);
-            goto ERR;
-        }
-
-        /* fill midifile.length, keeping in count tempo-changes */
-        i_midi_setget_length (&midifile);
-        AUDDBG ("PLAY requested, song length calculated: %i msec\n", (int) (midifile.length / 1000));
-
-        /* done with file */
-        midifile.file_pointer = NULL;
-
-        /* play play play! */
-        AUDDBG ("PLAY requested, starting play thread\n");
-        amidiplug_play_loop ();
-        break;
-
-    default:
-        fprintf (stderr, "%s is not a Standard MIDI File\n", filename_uri);
-        goto ERR;
-    }
-
-    audio_cleanup ();
-    return TRUE;
-
-ERR:
-    audio_cleanup ();
-    return FALSE;
-}
-
-static void generate_to_tick (int tick)
-{
-    double ticksecs = (double) midifile.current_tempo / midifile.ppq / 1000000;
-    audio_generate (ticksecs * (tick - midifile.playing_tick));
-    midifile.playing_tick = tick;
-}
-
-static void amidiplug_play_loop ()
-{
-    bool_t stopped = FALSE;
-
-    backend_prepare ();
-
-    /* initialize current position in each track */
-    for (int j = 0; j < midifile.num_tracks; ++j)
-        midifile.tracks[j].current_event = midifile.tracks[j].first_event;
-
-    while (! (stopped = aud_input_check_stop ()))
-    {
-        int seektime = aud_input_check_seek ();
-        if (seektime >= 0)
-            amidiplug_skipto ((int64_t) seektime * 1000 / midifile.avg_microsec_per_tick);
-
-        midievent_t * event = NULL;
-        midifile_track_t * event_track = NULL;
-        int i, min_tick = midifile.max_tick + 1;
-
-        /* search next event */
-        for (i = 0; i < midifile.num_tracks; ++i)
-        {
-            midifile_track_t * track = &midifile.tracks[i];
-            midievent_t * e2 = track->current_event;
-
-            if ((e2) && (e2->tick < min_tick))
-            {
-                min_tick = e2->tick;
-                event = e2;
-                event_track = track;
-            }
-        }
-
-        if (!event)
-            break; /* end of song reached */
-
-        /* advance pointer to next event */
-        event_track->current_event = event->next;
-
-        if (event->tick > midifile.playing_tick)
-            generate_to_tick (event->tick);
-
-        switch (event->type)
-        {
-        case SND_SEQ_EVENT_NOTEON:
-            seq_event_noteon (event);
-            break;
-
-        case SND_SEQ_EVENT_NOTEOFF:
-            seq_event_noteoff (event);
-            break;
-
-        case SND_SEQ_EVENT_KEYPRESS:
-            seq_event_keypress (event);
-            break;
-
-        case SND_SEQ_EVENT_CONTROLLER:
-            seq_event_controller (event);
-            break;
-
-        case SND_SEQ_EVENT_PGMCHANGE:
-            seq_event_pgmchange (event);
-            break;
-
-        case SND_SEQ_EVENT_CHANPRESS:
-            seq_event_chanpress (event);
-            break;
-
-        case SND_SEQ_EVENT_PITCHBEND:
-            seq_event_pitchbend (event);
-            break;
-
-        case SND_SEQ_EVENT_SYSEX:
-            seq_event_sysex (event);
-            break;
-
-        case SND_SEQ_EVENT_TEMPO:
-            seq_event_tempo (event);
-            AUDDBG ("PLAY thread, processing tempo event with value %i on tick %i\n",
-                      event->data.tempo, event->tick);
-            midifile.current_tempo = event->data.tempo;
-            break;
-
-        case SND_SEQ_EVENT_META_TEXT:
-            /* do nothing */
-            break;
-
-        case SND_SEQ_EVENT_META_LYRIC:
-            /* do nothing */
-            break;
-
-        default:
-            AUDDBG ("PLAY thread, encountered invalid event type %i\n", event->type);
-            break;
-        }
-    }
-
-    if (! stopped)
-        generate_to_tick (midifile.max_tick);
-
-    backend_reset ();
-
-    i_midi_free (& midifile);
-}
-
-
-/* amidigplug_skipto: re-do all events that influence the playing of our
-   midi file; re-do them using a time-tick of 0, so they are processed
-   istantaneously and proceed this way until the playing_tick is reached */
-static void amidiplug_skipto (int playing_tick)
-{
-    backend_reset ();
-
-    /* this check is always made, for safety*/
-    if (playing_tick >= midifile.max_tick)
-        playing_tick = midifile.max_tick - 1;
-
-    /* initialize current position in each track */
-    for (int i = 0; i < midifile.num_tracks; ++i)
-        midifile.tracks[i].current_event = midifile.tracks[i].first_event;
-
-    for (;;)
-    {
-        midievent_t * event = NULL;
-        midifile_track_t * event_track = NULL;
-        int i, min_tick = midifile.max_tick + 1;
-
-        /* search next event */
-        for (i = 0; i < midifile.num_tracks; ++i)
-        {
-            midifile_track_t * track = &midifile.tracks[i];
-            midievent_t * e2 = track->current_event;
-
-            if ((e2) && (e2->tick < min_tick))
-            {
-                min_tick = e2->tick;
-                event = e2;
-                event_track = track;
-            }
-        }
-
-        /* unlikely here... unless very strange MIDI files are played :) */
-        if (!event)
-        {
-            AUDDBG ("SKIPTO request, reached the last event but not the requested tick (!)\n");
-            break; /* end of song reached */
-        }
-
-        /* reached the requested tick, job done */
-        if (event->tick >= playing_tick)
-        {
-            AUDDBG ("SKIPTO request, reached the requested tick, exiting from skipto loop\n");
-            break;
-        }
-
-        /* advance pointer to next event */
-        event_track->current_event = event->next;
-
-        switch (event->type)
-        {
-            /* do nothing for these
-            case SND_SEQ_EVENT_NOTEON:
-            case SND_SEQ_EVENT_NOTEOFF:
-            case SND_SEQ_EVENT_KEYPRESS:
-            {
-              break;
-            } */
-        case SND_SEQ_EVENT_CONTROLLER:
-            seq_event_controller (event);
-            break;
-
-        case SND_SEQ_EVENT_PGMCHANGE:
-            seq_event_pgmchange (event);
-            break;
-
-        case SND_SEQ_EVENT_CHANPRESS:
-            seq_event_chanpress (event);
-            break;
-
-        case SND_SEQ_EVENT_PITCHBEND:
-            seq_event_pitchbend (event);
-            break;
-
-        case SND_SEQ_EVENT_SYSEX:
-            seq_event_sysex (event);
-            break;
-
-        case SND_SEQ_EVENT_TEMPO:
-            seq_event_tempo (event);
-            midifile.current_tempo = event->data.tempo;
-            break;
-        }
-    }
-
-    midifile.playing_tick = playing_tick;
-}
-
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("AMIDI-Plug (MIDI Player)"),
-    .domain = PACKAGE,
-    .init = amidiplug_init,
-    .about = i_about_gui,
-    .prefs = & amidiplug_prefs,
-    .play = amidiplug_play,
-    .cleanup = amidiplug_cleanup,
-    .probe_for_tuple = amidiplug_get_song_tuple,
-    .file_info_box = i_fileinfo_gui,
-    .is_our_file_from_vfs = amidiplug_is_our_file_from_vfs,
-    .extensions = amidiplug_vfs_extensions,
-)
diff --git a/src/amidi-plug/amidi-plug.cc b/src/amidi-plug/amidi-plug.cc
new file mode 100644
index 000000000000..fcb3b9d44390
--- /dev/null
+++ b/src/amidi-plug/amidi-plug.cc
@@ -0,0 +1,450 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#include "i_backend.h"
+#include "i_configure.h"
+#include "i_fileinfo.h"
+#include "i_midi.h"
+
+class AMIDIPlug : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("AMIDI-Plug (MIDI Player)"),
+        PACKAGE,
+        about,
+        & amidiplug_prefs
+    };
+
+    static constexpr auto iinfo = InputInfo ()
+        .with_exts (exts);
+
+    constexpr AMIDIPlug () : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    void cleanup ();
+
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+
+    bool file_info_box (const char * filename, VFSFile & file)
+        { i_fileinfo_gui (filename, file); return true; }
+
+protected:
+    bool m_backend_initialized = false;
+
+    static bool audio_init ();
+    static void audio_generate (double seconds);
+    static void audio_cleanup ();
+
+    static void generate_ticks (midifile_t & midifile, int num_ticks);
+    static void play_loop (midifile_t & midifile);
+    static int skip_to (midifile_t & midifile, int seektime);
+};
+
+EXPORT AMIDIPlug aud_plugin_instance;
+
+const char * const AMIDIPlug::exts[] = {"mid", "midi", "rmi", "rmid", nullptr};
+
+void AMIDIPlug::cleanup ()
+{
+    if (m_backend_initialized)
+    {
+        backend_cleanup ();
+        m_backend_initialized = false;
+    }
+}
+
+bool AMIDIPlug::init ()
+{
+    static const char * const defaults[] =
+    {
+        "ap_opts_transpose_value", "0",
+        "ap_opts_drumshift_value", "0",
+        "fsyn_synth_samplerate", "44100",
+        "fsyn_synth_gain", "-1",
+        "fsyn_synth_polyphony", "-1",
+        "fsyn_synth_reverb", "-1",
+        "fsyn_synth_chorus", "-1",
+        "skip_leading", "FALSE",
+        "skip_trailing", "FALSE",
+        nullptr
+    };
+
+    aud_config_set_defaults ("amidiplug", defaults);
+
+    return true;
+}
+
+bool AMIDIPlug::is_our_file (const char * filename, VFSFile & file)
+{
+    char magic_bytes[4];
+
+    if (file.fread (magic_bytes, 1, 4) != 4)
+        return false;
+
+    if (!strncmp (magic_bytes, "MThd", 4))
+    {
+        AUDDBG ("MIDI found, %s is a standard midi file\n", filename);
+        return true;
+    }
+
+    if (!strncmp (magic_bytes, "RIFF", 4))
+    {
+        /* skip the four bytes after RIFF,
+           then read the next four */
+        if (file.fseek (4, VFS_SEEK_CUR) != 0)
+            return false;
+
+        if (file.fread (magic_bytes, 1, 4) != 4)
+            return false;
+
+        if (!strncmp (magic_bytes, "RMID", 4))
+        {
+            AUDDBG ("MIDI found, %s is a riff midi file\n", filename);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+Tuple AMIDIPlug::read_tuple (const char * filename, VFSFile & file)
+{
+    /* song title, get it from the filename */
+    Tuple tuple;
+    tuple.set_filename (filename);
+    tuple.set_str (Tuple::Codec, "MIDI");
+
+    midifile_t mf;
+
+    if (mf.parse_from_file (filename, file))
+        tuple.set_int (Tuple::Length, mf.length / 1000);
+
+    return tuple;
+}
+
+
+static int s_samplerate, s_channels;
+static int s_bufsize;
+static int16_t * s_buf;
+
+bool AMIDIPlug::audio_init ()
+{
+    int bitdepth;
+
+    backend_audio_info (& s_channels, & bitdepth, & s_samplerate);
+
+    if (bitdepth != 16)
+        return false;
+
+    open_audio (FMT_S16_NE, s_samplerate, s_channels);
+
+    s_bufsize = 2 * s_channels * (s_samplerate / 4);
+    s_buf = new int16_t[s_bufsize / 2];
+
+    return true;
+}
+
+void AMIDIPlug::audio_generate (double seconds)
+{
+    int total = 2 * s_channels * (int) round (seconds * s_samplerate);
+
+    while (total)
+    {
+        int chunk = (total < s_bufsize) ? total : s_bufsize;
+
+        backend_generate_audio (s_buf, chunk);
+        write_audio (s_buf, chunk);
+
+        total -= chunk;
+    }
+}
+
+void AMIDIPlug::audio_cleanup ()
+{
+    delete[] s_buf;
+}
+
+bool AMIDIPlug::play (const char * filename, VFSFile & file)
+{
+    if (__sync_bool_compare_and_swap (& backend_settings_changed, true, false)
+     && m_backend_initialized)
+    {
+        AUDDBG ("Settings changed, reinitializing backend\n");
+        backend_cleanup ();
+        m_backend_initialized = false;
+    }
+
+    if (! m_backend_initialized)
+    {
+        backend_init ();
+        m_backend_initialized = true;
+    }
+
+    if (! audio_init ())
+        return false;
+
+    AUDDBG ("PLAY requested, midifile init\n");
+    /* midifile init */
+    midifile_t midifile;
+
+    if (! midifile.parse_from_file (filename, file))
+    {
+        audio_cleanup ();
+        return false;
+    }
+
+    AUDDBG ("PLAY requested, starting play thread\n");
+    play_loop (midifile);
+
+    audio_cleanup ();
+    return true;
+}
+
+void AMIDIPlug::generate_ticks (midifile_t & midifile, int num_ticks)
+{
+    double ticksecs = (double) midifile.current_tempo / midifile.ppq / 1000000;
+    audio_generate (ticksecs * num_ticks);
+}
+
+void AMIDIPlug::play_loop (midifile_t & midifile)
+{
+    int tick = midifile.start_tick;
+    bool stopped = false;
+
+    /* initialize current position in each track */
+    for (midifile_track_t & track : midifile.tracks)
+        track.current_event = track.events.head ();
+
+    while (! (stopped = check_stop ()))
+    {
+        int seektime = check_seek ();
+        if (seektime >= 0)
+            tick = skip_to (midifile, seektime);
+
+        midievent_t * event = nullptr;
+        midifile_track_t * event_track = nullptr;
+        int min_tick = midifile.max_tick + 1;
+
+        /* search next event */
+        for (midifile_track_t & track : midifile.tracks)
+        {
+            midievent_t * e2 = track.current_event;
+
+            if ((e2) && (e2->tick < min_tick))
+            {
+                min_tick = e2->tick;
+                event = e2;
+                event_track = & track;
+            }
+        }
+
+        if (!event)
+            break; /* end of song reached */
+
+        /* advance pointer to next event */
+        event_track->current_event = event_track->events.next (event);
+
+        if (event->tick > tick)
+        {
+            generate_ticks (midifile, event->tick - tick);
+            tick = event->tick;
+        }
+
+        switch (event->type)
+        {
+        case SND_SEQ_EVENT_NOTEON:
+            seq_event_noteon (event);
+            break;
+
+        case SND_SEQ_EVENT_NOTEOFF:
+            seq_event_noteoff (event);
+            break;
+
+        case SND_SEQ_EVENT_KEYPRESS:
+            seq_event_keypress (event);
+            break;
+
+        case SND_SEQ_EVENT_CONTROLLER:
+            seq_event_controller (event);
+            break;
+
+        case SND_SEQ_EVENT_PGMCHANGE:
+            seq_event_pgmchange (event);
+            break;
+
+        case SND_SEQ_EVENT_CHANPRESS:
+            seq_event_chanpress (event);
+            break;
+
+        case SND_SEQ_EVENT_PITCHBEND:
+            seq_event_pitchbend (event);
+            break;
+
+        case SND_SEQ_EVENT_SYSEX:
+            seq_event_sysex (event);
+            break;
+
+        case SND_SEQ_EVENT_TEMPO:
+            seq_event_tempo (event);
+            AUDDBG ("PLAY thread, processing tempo event with value %i on tick %i\n",
+                      event->tempo, event->tick);
+            midifile.current_tempo = event->tempo;
+            break;
+
+        case SND_SEQ_EVENT_META_TEXT:
+            /* do nothing */
+            break;
+
+        case SND_SEQ_EVENT_META_LYRIC:
+            /* do nothing */
+            break;
+
+        default:
+            AUDDBG ("PLAY thread, encountered invalid event type %i\n", event->type);
+            break;
+        }
+    }
+
+    if (! stopped)
+        generate_ticks (midifile, midifile.max_tick - tick);
+
+    backend_reset ();
+}
+
+
+/* amidigplug_skipto: re-do all events that influence the playing of our
+   midi file; re-do them using a time-tick of 0, so they are processed
+   istantaneously and proceed this way until the playing_tick is reached */
+int AMIDIPlug::skip_to (midifile_t & midifile, int seektime)
+{
+    backend_reset ();
+
+    int tick = midifile.start_tick;
+    if (midifile.avg_microsec_per_tick > 0)
+        tick += (int64_t) seektime * 1000 / midifile.avg_microsec_per_tick;
+
+    /* initialize current position in each track */
+    for (midifile_track_t & track : midifile.tracks)
+        track.current_event = track.events.head ();
+
+    for (;;)
+    {
+        midievent_t * event = nullptr;
+        midifile_track_t * event_track = nullptr;
+        int min_tick = midifile.max_tick + 1;
+
+        /* search next event */
+        for (midifile_track_t & track : midifile.tracks)
+        {
+            midievent_t * e2 = track.current_event;
+
+            if ((e2) && (e2->tick < min_tick))
+            {
+                min_tick = e2->tick;
+                event = e2;
+                event_track = & track;
+            }
+        }
+
+        /* unlikely here... unless very strange MIDI files are played :) */
+        if (!event)
+        {
+            AUDDBG ("SKIPTO request, reached the last event but not the requested tick (!)\n");
+            break; /* end of song reached */
+        }
+
+        /* reached the requested tick, job done */
+        if (event->tick >= tick)
+        {
+            AUDDBG ("SKIPTO request, reached the requested tick, exiting from skipto loop\n");
+            break;
+        }
+
+        /* advance pointer to next event */
+        event_track->current_event = event_track->events.next (event);
+
+        switch (event->type)
+        {
+            /* do nothing for these
+            case SND_SEQ_EVENT_NOTEON:
+            case SND_SEQ_EVENT_NOTEOFF:
+            case SND_SEQ_EVENT_KEYPRESS:
+            {
+              break;
+            } */
+        case SND_SEQ_EVENT_CONTROLLER:
+            seq_event_controller (event);
+            break;
+
+        case SND_SEQ_EVENT_PGMCHANGE:
+            seq_event_pgmchange (event);
+            break;
+
+        case SND_SEQ_EVENT_CHANPRESS:
+            seq_event_chanpress (event);
+            break;
+
+        case SND_SEQ_EVENT_PITCHBEND:
+            seq_event_pitchbend (event);
+            break;
+
+        case SND_SEQ_EVENT_SYSEX:
+            seq_event_sysex (event);
+            break;
+
+        case SND_SEQ_EVENT_TEMPO:
+            seq_event_tempo (event);
+            midifile.current_tempo = event->tempo;
+            break;
+        }
+    }
+
+    return tick;
+}
+
+const char AMIDIPlug::about[] =
+ N_("AMIDI-Plug\n"
+    "modular MIDI music player\n"
+    "http://www.develia.org/projects.php?p=amidiplug\n\n"
+    "written by Giacomo Lozito\n"
+    "<james at develia.org>\n\n"
+    "special thanks to...\n\n"
+    "Clemens Ladisch and Jaroslav Kysela\n"
+    "for their cool programs aplaymidi and amixer; those\n"
+    "were really useful, along with alsa-lib docs, in order\n"
+    "to learn more about the ALSA API\n\n"
+    "Alfredo Spadafina\n"
+    "for the nice midi keyboard logo\n\n"
+    "Tony Vroon\n"
+    "for the good help with alpha testing");
diff --git a/src/amidi-plug/amidi-plug.logo.xpm b/src/amidi-plug/amidi-plug.logo.xpm
deleted file mode 100644
index e165582687a6..000000000000
--- a/src/amidi-plug/amidi-plug.logo.xpm
+++ /dev/null
@@ -1,743 +0,0 @@
-/* XPM */
-static char * amidiplug_xpm_logo[] = {
-"398 123 617 2",
-"  	c #FFFFFF",
-". 	c #FCFCFC",
-"+ 	c #FAFAFA",
-"@ 	c #F9F9F9",
-"# 	c #F8F8F8",
-"$ 	c #F7F7F7",
-"% 	c #F5F5F5",
-"& 	c #F4F4F4",
-"* 	c #F3F3F3",
-"= 	c #F1F1F1",
-"- 	c #EFEFEF",
-"; 	c #EEEEEE",
-"> 	c #F0F0F0",
-", 	c #EDEDED",
-"' 	c #EBEBEB",
-") 	c #EAEAEA",
-"! 	c #E9E9E9",
-"~ 	c #E8E8E8",
-"{ 	c #E3E3E3",
-"] 	c #E2E2E2",
-"^ 	c #E0E0E0",
-"/ 	c #DEDEDE",
-"( 	c #E4E4E4",
-"_ 	c #DADADA",
-": 	c #5C5C5C",
-"< 	c #4B4B4B",
-"[ 	c #4A4A4A",
-"} 	c #464646",
-"| 	c #454545",
-"1 	c #414141",
-"2 	c #404040",
-"3 	c #3C3C3C",
-"4 	c #383838",
-"5 	c #373737",
-"6 	c #393939",
-"7 	c #3A3A3A",
-"8 	c #3B3B3B",
-"9 	c #363636",
-"0 	c #3D3D3D",
-"a 	c #3E3E3E",
-"b 	c #3F3F3F",
-"c 	c #424242",
-"d 	c #434343",
-"e 	c #444444",
-"f 	c #474747",
-"g 	c #484848",
-"h 	c #494949",
-"i 	c #4C4C4C",
-"j 	c #4D4D4D",
-"k 	c #4E4E4E",
-"l 	c #343434",
-"m 	c #333333",
-"n 	c #323232",
-"o 	c #313131",
-"p 	c #303030",
-"q 	c #2F2F2F",
-"r 	c #2E2E2E",
-"s 	c #2D2D2D",
-"t 	c #2C2C2C",
-"u 	c #2B2B2B",
-"v 	c #2A2A2A",
-"w 	c #292929",
-"x 	c #282828",
-"y 	c #272727",
-"z 	c #262626",
-"A 	c #252525",
-"B 	c #1E1E1E",
-"C 	c #1C1C1C",
-"D 	c #1B1B1B",
-"E 	c #1A1A1A",
-"F 	c #181818",
-"G 	c #161616",
-"H 	c #202020",
-"I 	c #A0A0A0",
-"J 	c #FEFEFE",
-"K 	c #747474",
-"L 	c #000000",
-"M 	c #010101",
-"N 	c #020202",
-"O 	c #030303",
-"P 	c #040404",
-"Q 	c #050505",
-"R 	c #060606",
-"S 	c #070707",
-"T 	c #080808",
-"U 	c #090909",
-"V 	c #0A0A0A",
-"W 	c #0C0C0C",
-"X 	c #0D0D0D",
-"Y 	c #0E0E0E",
-"Z 	c #0F0F0F",
-"` 	c #101010",
-" .	c #111111",
-"..	c #121212",
-"+.	c #131313",
-"@.	c #141414",
-"#.	c #151515",
-"$.	c #171717",
-"%.	c #191919",
-"&.	c #1D1D1D",
-"*.	c #1F1F1F",
-"=.	c #DFDFDF",
-"-.	c #232323",
-";.	c #252523",
-">.	c #2B2B28",
-",.	c #2C2C29",
-"'.	c #2C2C2A",
-").	c #2D2D2A",
-"!.	c #2D2D2B",
-"~.	c #2E2E2B",
-"{.	c #2E2E2C",
-"].	c #2F2F2C",
-"^.	c #30302D",
-"/.	c #242423",
-"(.	c #272723",
-"_.	c #272724",
-":.	c #282824",
-"<.	c #292925",
-"[.	c #292926",
-"}.	c #2A2A26",
-"|.	c #2D2D28",
-"1.	c #2E2E2A",
-"2.	c #2F2F2A",
-"3.	c #30302B",
-"4.	c #2E302F",
-"5.	c #2E3131",
-"6.	c #303333",
-"7.	c #313434",
-"8.	c #303434",
-"9.	c #2F312F",
-"0.	c #2E2E29",
-"a.	c #2C2C28",
-"b.	c #2C2C27",
-"c.	c #2B2B26",
-"d.	c #2C2C26",
-"e.	c #2E2E28",
-"f.	c #2E2E27",
-"g.	c #2D2D27",
-"h.	c #1E1E1B",
-"i.	c #282825",
-"j.	c #33332F",
-"k.	c #32322F",
-"l.	c #32322E",
-"m.	c #31312E",
-"n.	c #30302C",
-"o.	c #242422",
-"p.	c #A4A4A4",
-"q.	c #868686",
-"r.	c #0B0B0B",
-"s.	c #171716",
-"t.	c #A2A295",
-"u.	c #BEBEAE",
-"v.	c #BEBEAF",
-"w.	c #BEBEB0",
-"x.	c #BFBFB0",
-"y.	c #C0C0B0",
-"z.	c #C0C0B2",
-"A.	c #C1C1B2",
-"B.	c #C2C2B2",
-"C.	c #7E7E74",
-"D.	c #5F5F4F",
-"E.	c #B9B998",
-"F.	c #BCBC99",
-"G.	c #BCBC9A",
-"H.	c #BDBD9A",
-"I.	c #BEBE9A",
-"J.	c #BEBE9B",
-"K.	c #C1C19E",
-"L.	c #C2C29E",
-"M.	c #C3C39F",
-"N.	c #9EAA9F",
-"O.	c #92A4A4",
-"P.	c #92A5A5",
-"Q.	c #93A6A6",
-"R.	c #94A6A6",
-"S.	c #A8B3A3",
-"T.	c #C4C4A0",
-"U.	c #C5C5A0",
-"V.	c #C6C6A1",
-"W.	c #C6C6A0",
-"X.	c #C7C7A1",
-"Y.	c #C9C9A2",
-"Z.	c #7C7C65",
-"`.	c #949487",
-" +	c #CDCDBC",
-".+	c #CDCDBB",
-"++	c #A3A394",
-"@+	c #0B0B0A",
-"#+	c #191918",
-"$+	c #8B8B80",
-"%+	c #9E9E92",
-"&+	c #9F9F92",
-"*+	c #A0A093",
-"=+	c #A0A094",
-"-+	c #A1A194",
-";+	c #67675F",
-">+	c #686857",
-",+	c #D2D2AB",
-"'+	c #D3D3AC",
-")+	c #D4D4AD",
-"!+	c #D5D5AD",
-"~+	c #D5D5AE",
-"{+	c #D6D6AE",
-"]+	c #D6D6AF",
-"^+	c #D7D7AF",
-"/+	c #AEB6A0",
-"(+	c #9AA69A",
-"_+	c #9AA698",
-":+	c #9AA699",
-"<+	c #B5BCA3",
-"[+	c #DBDBB1",
-"}+	c #DADAB1",
-"|+	c #DBDBB0",
-"1+	c #DADAB0",
-"2+	c #969679",
-"3+	c #6C6C64",
-"4+	c #9E9E91",
-"5+	c #9E9E90",
-"6+	c #99998C",
-"7+	c #98988B",
-"8+	c #848478",
-"9+	c #111110",
-"0+	c #B0B0B0",
-"a+	c #959595",
-"b+	c #0C0C0E",
-"c+	c #0E0E10",
-"d+	c #131314",
-"e+	c #696957",
-"f+	c #D8D8B0",
-"g+	c #D6D6AD",
-"h+	c #D7D7AE",
-"i+	c #D8D8AF",
-"j+	c #DBDBB2",
-"k+	c #DCDCB2",
-"l+	c #DCDCB1",
-"m+	c #A8A888",
-"n+	c #0F0F11",
-"o+	c #0E0E0F",
-"p+	c #0A0A0C",
-"q+	c #09090A",
-"r+	c #080809",
-"s+	c #070708",
-"t+	c #060608",
-"u+	c #0B0B0C",
-"v+	c #181817",
-"w+	c #1C1C1B",
-"x+	c #6F6F5C",
-"y+	c #D7D7B0",
-"z+	c #D9D9B0",
-"A+	c #D9D9B1",
-"B+	c #DADAB2",
-"C+	c #B9B995",
-"D+	c #161615",
-"E+	c #161614",
-"F+	c #141413",
-"G+	c #C0C0C0",
-"H+	c #A5A5A5",
-"I+	c #A4A497",
-"J+	c #AAAA9C",
-"K+	c #AAAA9D",
-"L+	c #ABAB9D",
-"M+	c #ACAC9E",
-"N+	c #ACAC9F",
-"O+	c #ADAD9F",
-"P+	c #AEAEA0",
-"Q+	c #5B5B54",
-"R+	c #777762",
-"S+	c #DCDCB3",
-"T+	c #DDDDB3",
-"U+	c #DDDDB2",
-"V+	c #C5C59F",
-"W+	c #4F4F46",
-"X+	c #B6B6A6",
-"Y+	c #BABAAA",
-"Z+	c #B9B9AA",
-"`+	c #B8B8A8",
-" @	c #4F4F49",
-".@	c #595959",
-"+@	c #3C3C39",
-"@@	c #BCBCAD",
-"#@	c #BDBDAE",
-"$@	c #C0C0B1",
-"%@	c #5B5B55",
-"&@	c #808069",
-"*@	c #DBDBB3",
-"=@	c #DCDCB4",
-"-@	c #DDDDB4",
-";@	c #DEDEB4",
-">@	c #CECEA6",
-",@	c #57574C",
-"'@	c #BDBDAC",
-")@	c #C4C4B3",
-"!@	c #C3C3B2",
-"~@	c #63635B",
-"{@	c #CBCBCB",
-"]@	c #ABABAB",
-"^@	c #282826",
-"/@	c #292927",
-"(@	c #2A2A28",
-"_@	c #2B2B29",
-":@	c #84846C",
-"<@	c #D6D6B0",
-"[@	c #DEDEB3",
-"}@	c #DEDEB2",
-"|@	c #D5D5AC",
-"1@	c #3F3F36",
-"2@	c #232321",
-"3@	c #222220",
-"4@	c #212120",
-"5@	c #21211F",
-"6@	c #20201E",
-"7@	c #1F1F1D",
-"8@	c #6B6B6B",
-"9@	c #FBFBFB",
-"0@	c #515144",
-"a@	c #80806A",
-"b@	c #81816A",
-"c@	c #81816B",
-"d@	c #82826B",
-"e@	c #82826C",
-"f@	c #83836C",
-"g@	c #84846D",
-"h@	c #84846E",
-"i@	c #85856E",
-"j@	c #86866E",
-"k@	c #85856D",
-"l@	c #7E7E67",
-"m@	c #7E7E66",
-"n@	c #7D7D66",
-"o@	c #7A7A63",
-"p@	c #D3D3D3",
-"q@	c #BCBCBC",
-"r@	c #212121",
-"s@	c #222222",
-"t@	c #242424",
-"u@	c #525252",
-"v@	c #D4D4D4",
-"w@	c #AFAFAF",
-"x@	c #636363",
-"y@	c #D6D6D6",
-"z@	c #353535",
-"A@	c #505050",
-"B@	c #C3C3C3",
-"C@	c #818181",
-"D@	c #4F4F4F",
-"E@	c #565656",
-"F@	c #585858",
-"G@	c #5D5D5D",
-"H@	c #5E5E5E",
-"I@	c #5F5F5F",
-"J@	c #606060",
-"K@	c #646464",
-"L@	c #676767",
-"M@	c #666666",
-"N@	c #686868",
-"O@	c #6A6A6A",
-"P@	c #656565",
-"Q@	c #6C6C6C",
-"R@	c #707070",
-"S@	c #616161",
-"T@	c #717171",
-"U@	c #727272",
-"V@	c #6E6E6E",
-"W@	c #737373",
-"X@	c #7A7A7A",
-"Y@	c #757575",
-"Z@	c #777777",
-"`@	c #797979",
-" #	c #535353",
-".#	c #7B7B7B",
-"+#	c #767676",
-"@#	c #6D6D6D",
-"##	c #7E7E7E",
-"$#	c #575757",
-"%#	c #515151",
-"&#	c #626262",
-"*#	c #7C7C7C",
-"=#	c #838383",
-"-#	c #848484",
-";#	c #858585",
-">#	c #888888",
-",#	c #5A5A5A",
-"'#	c #7D7D7D",
-")#	c #8C8C8C",
-"!#	c #8D8D8D",
-"~#	c #909090",
-"{#	c #919191",
-"]#	c #929292",
-"^#	c #939393",
-"/#	c #949494",
-"(#	c #898989",
-"_#	c #969696",
-":#	c #979797",
-"<#	c #555555",
-"[#	c #989898",
-"}#	c #828282",
-"|#	c #8E8E8E",
-"1#	c #8B8B8B",
-"2#	c #8F8F8F",
-"3#	c #545454",
-"4#	c #787878",
-"5#	c #878787",
-"6#	c #999999",
-"7#	c #8A8A8A",
-"8#	c #ECECEC",
-"9#	c #7F7F7F",
-"0#	c #5B5B5B",
-"a#	c #6F6F6F",
-"b#	c #696969",
-"c#	c #9A9A9A",
-"d#	c #FDFDFD",
-"e#	c #AAAAAA",
-"f#	c #808080",
-"g#	c #9B9B9B",
-"h#	c #9C9C9C",
-"i#	c #C1C1C1",
-"j#	c #F2F2F2",
-"k#	c #CCCCCC",
-"l#	c #9D9D9D",
-"m#	c #E5E5E5",
-"n#	c #9E9E9E",
-"o#	c #F6F6F6",
-"p#	c #C8C8C8",
-"q#	c #9F9F9F",
-"r#	c #BFBFBF",
-"s#	c #A1A1A1",
-"t#	c #BEBEBE",
-"u#	c #DDDDDD",
-"v#	c #BABABA",
-"w#	c #A2A2A2",
-"x#	c #DCDCDC",
-"y#	c #A3A3A3",
-"z#	c #A6A6A6",
-"A#	c #ACACAC",
-"B#	c #ADADAD",
-"C#	c #AEAEAE",
-"D#	c #B1B1B1",
-"E#	c #B2B2B2",
-"F#	c #B4B4B4",
-"G#	c #B8B8B8",
-"H#	c #B9B9B9",
-"I#	c #BBBBBB",
-"J#	c #BDBDBD",
-"K#	c #C6C6C6",
-"L#	c #C7C7C7",
-"M#	c #CACACA",
-"N#	c #CECECE",
-"O#	c #D2D2D2",
-"P#	c #D8D8D8",
-"Q#	c #D9D9D9",
-"R#	c #D7D7D7",
-"S#	c #DBDBDB",
-"T#	c #A8A8A8",
-"U#	c #D1D1D1",
-"V#	c #D0D0D0",
-"W#	c #CFCFCF",
-"X#	c #C9C9C9",
-"Y#	c #B7B7B7",
-"Z#	c #C5C5C5",
-"`#	c #C4C4C4",
-" $	c #B6B6B6",
-".$	c #B5B5B5",
-"+$	c #B3B3B3",
-"@$	c #A7A7A7",
-"#$	c #A9A9A9",
-"$$	c #C2C2C2",
-"%$	c #D5D5D5",
-"&$	c #CDCDCD",
-"*$	c #E6E6E6",
-"=$	c #E7E7E7",
-"-$	c #E1E1E1",
-";$	c #8A8989",
-">$	c #6D6B6B",
-",$	c #646262",
-"'$	c #A4A3A3",
-")$	c #AEADAD",
-"!$	c #D4D3D3",
-"~$	c #818080",
-"{$	c #969595",
-"]$	c #A5A4A4",
-"^$	c #8A8888",
-"/$	c #838181",
-"($	c #727070",
-"_$	c #817F7F",
-":$	c #858484",
-"<$	c #868484",
-"[$	c #777575",
-"}$	c #6E6C6C",
-"|$	c #888686",
-"1$	c #BFBEBE",
-"2$	c #898888",
-"3$	c #797878",
-"4$	c #706E6E",
-"5$	c #9F9E9E",
-"6$	c #7A7878",
-"7$	c #DFDEDE",
-"8$	c #656363",
-"9$	c #8D8B8B",
-"0$	c #747373",
-"a$	c #666464",
-"b$	c #C6C5C5",
-"c$	c #EAE9E9",
-"d$	c #999898",
-"e$	c #BDBCBC",
-"f$	c #939292",
-"g$	c #CAC9C9",
-"h$	c #9A9999",
-"i$	c #7E7D7D",
-"j$	c #6C6A6A",
-"k$	c #686666",
-"l$	c #8C8B8B",
-"m$	c #6F6D6D",
-"n$	c #D8D7D7",
-"o$	c #7B7979",
-"p$	c #8E8D8D",
-"q$	c #AAA9A9",
-"r$	c #9E9D9D",
-"s$	c #AFAEAE",
-"t$	c #8B8A8A",
-"u$	c #7E7C7C",
-"v$	c #959494",
-"w$	c #919090",
-"x$	c #8F8E8E",
-"y$	c #6B6969",
-"z$	c #767575",
-"A$	c #929191",
-"B$	c #7C7B7B",
-"C$	c #6F6E6E",
-"D$	c #949393",
-"E$	c #737171",
-"F$	c #828181",
-"G$	c #B7B6B6",
-"H$	c #A9A8A8",
-"I$	c #939191",
-"J$	c #B2B1B1",
-"K$	c #B5B4B4",
-"L$	c #FAF9F9",
-"M$	c #ABA9A9",
-"N$	c #7F7D7D",
-"O$	c #BEBDBD",
-"P$	c #878585",
-"Q$	c #747272",
-"R$	c #D1D0D0",
-"S$	c #A6A4A4",
-"T$	c #9B9999",
-"U$	c #C1C0C0",
-"V$	c #BCBBBB",
-"W$	c #DAD9D9",
-"X$	c #C0BFBF",
-"Y$	c #B1B0B0",
-"Z$	c #969494",
-"`$	c #908F8F",
-" %	c #ABAAAA",
-".%	c #9C9B9B",
-"+%	c #D7D6D6",
-"@%	c #DEDDDD",
-"#%	c #C7C6C6",
-"$%	c #A6A5A5",
-"%%	c #807F7F",
-"&%	c #7C7A7A",
-"*%	c #CDCCCC",
-"=%	c #CFCECE",
-"-%	c #676565",
-";%	c #9A9898",
-">%	c #716F6F",
-",%	c #696767",
-"'%	c #797777",
-")%	c #C5C4C4",
-"!%	c #B9B8B8",
-"~%	c #706F6F",
-"{%	c #727171",
-"]%	c #A1A0A0",
-"^%	c #6A6868",
-"/%	c #7D7B7B",
-"(%	c #8D8C8C",
-"_%	c #B3B2B2",
-":%	c #BAB9B9",
-"<%	c #CBCACA",
-"[%	c #696868",
-"}%	c #717070",
-"|%	c #9D9B9B",
-"1%	c #7A7979",
-"2%	c #C3C2C2",
-"3%	c #ECEBEB",
-"4%	c #EFEEEE",
-"5%	c #8E8C8C",
-"6%	c #767474",
-"7%	c #ADACAC",
-"8%	c #989696",
-"9%	c #B4B3B3",
-"0%	c #ACABAB",
-"a%	c #757373",
-"b%	c #C4C3C3",
-"c%	c #807E7E",
-"d%	c #787676",
-"e%	c #A7A6A6",
-"f%	c #8F8D8D",
-"g%	c #BBBABA",
-"h%	c #908E8E",
-"i%	c #D0CFCF",
-"j%	c #7D7C7C",
-"k%	c #838282",
-"l%	c #9D9C9C",
-"m%	c #868585",
-"n%	c #9B9A9A",
-"o%	c #8C8A8A",
-"p%	c #A3A2A2",
-"q%	c #C8C7C7",
-"r%	c #DBDADA",
-"s%	c #9E9C9C",
-"t%	c #E1E0E0",
-"u%	c #848383",
-"v%	c #888787",
-"w%	c #858383",
-"x%	c #848282",
-"y%	c #757474",
-"z%	c #A09F9F",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                        . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ # # # # # # # # # # # # # # # # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = = = = = = = = = = = = = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - - - - - - - - - - - - - > > > > > > ; , , , ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; , ' ' ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ~ ~ ~ ~ ~ ~ { ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ / / / / / ( #                                                                       ",
-"                                                                      _ : < [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ } } } } } } } } } } } } } } } } | 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 6 6 6 6 7 7 7 7 7 7 8 8 3 3 3 4 4 4 4 6 6 6 6 7 7 7 7 7 4 9 9 9 9 9 5 5 4 4 4 4 4 4 4 6 7 7 7 7 8 8 3 3 3 0 0 a a b 2 2 1 1 c c d e e | } } | e e } } } f g g h [ [ [ < i i i i i j j j k k k j j j j j j i i i < < [ [ h g g f e c c 1 2 b b a 0 3 8 7 7 4 4 5 9 9 l l m n n o p p q r r s s t t u v v w x x x y y z A B C C C C C C C C D D D E E E E E E E E F G G G G G H I J                                                                     ",
-"                                                                    . K L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T U V W W X Y Y Z `  .....+. at .#.G G $.F F %.E D D C C &.&.B B B B B *.*.*.*.*.*.*.B B B B &.&.C C D D E E F F F G G #. at .@.+... .` ` Z Y Y X W W V U T T S R R Q P P P O N N N N N N N N N N M M M M M M M M M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L m '                                                                     ",
-"                                                                    =.-.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O P P Q Q R S T U V W X X V ;.>.,.'.).!.~.{.].^./.E (._.:.:.<.[.}.|.1.2.2.2.3.3.4.5.5.6.7.8.8.8.8.8.9.2.2.1.1.0.0.|.a.b.b.c.d.e.f.g.g.h.i.j.k.l.l.m.^.n.n.].o.R T S R Q Q P O O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L O p.J                                                                   ",
-"                                                                  J q.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N O O P P Q R R S T U r.W X X Y s.t.u.v.w.x.y.y.z.A.B.C.D.E.F.G.H.I.J.J.K.L.L.M.M.M.M.N.O.O.P.Q.Q.R.R.R.R.S.T.T.U.V.W.W.W.W.W.W.W.X.Y.Y.Y.Y.Z.`. + + + +.+.+.+.+.+++ at +U T S R Q Q P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L a >                                                                   ",
-"                                                                  ] x L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W W X Y Y #+$+%+%+&+&+*+=+-+-+t.;+>+,+,+'+'+)+)+!+~+{+{+]+^+^+^+/+(+_+_+:+(+(+(+(+(+<+[+}+}+[+[+[+[+[+[+[+[+|+|+|+1+|+2+3+%+%+%+4+5+5+5+6+7+8+9+V T T R R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L T 0+                                                                  ",
-"                                                                J a+L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O P P Q R R S T V V W X X Y Z Y ` b+c+`  ...d+ at .#.G F e+,+'+'+)+)+~+~+{+]+^+^+f+f+f+{+!+g+{+{+{+h+h+h+h+i+j+j+j+k+k+k+k+k+k+l+l+[+[+[+[+|+m+n+` o+b+p+q+r+r+T s+t+U V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L k %                                                                 ",
-"                                                                ) o L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R T T V r.W X Y Y Z u+ at .@. at .#.G s.v+F %.w+E x+'+'+)+!+~+{+{+]+^+y+f+f+z+A+A+}+B+B+B+j+j+j+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+l+l+l+C+v+E F v+s.s.D+E+ at .F+D+@+V V T S R R Q P P O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L W G+                                                                ",
-"                                                                H+L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W W X Y Z ` ,.I+J+K+L+M+M+N+O+P+P+Q+R+'+)+!+~+{+]+^+y+f+f+f+A+A+B+B+B+j+j+j+S+S+S+S+S+S+S+S+S+T+T+T+T+T+U+U+k+k+k+k+k+k+V+W+X+Y+Y+Y+Y+Y+Y+Y+Z+`+ @r.V T T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L .@$                                                               ",
-"                                                              - 8 L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T V V W X Y Y Z ` +@`+@@#@#@u.v.x.y.$@y.%@&@)+!+~+{+]+^+y+f+f+A+A+B+B+B+j+j+*@S+S+S+=@=@- at -@- at -@- at -@- at -@;@T+T+T+T+T+T+U+U+U+U+>@,@'@)@)@!@!@!@!@!@!@!@~@W V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ` {@                                                              ",
-"                                                              ]@Q L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V r.W X Y Y Z ` #.^@^@^@/@(@(@_@'.'.{.*.:@{+{+{+<@f+f+f+A+B+B+B+B+j+S+=@=@=@=@-@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@;@[@}@|@1 at o.2@2 at 3@4 at 5@6 at 6@7 at 7@9+W V V T S R R Q P P O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 8 at 9@                                                            ",
-"                                                            & [ L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O O P P Q R S T U V W W X Y Z ` ` ....+. at .#.G G F F %.E D 0 at a@a at a@b at c@d at e@e at f@g at g@h at h@h at i@i at i@i at j@j at j@j at j@j at j@j at j@j at j@j at i@i at k@g@:@&@l at l@l at m@n at o@<.G @. at .+... .` Z Y Y X W r.V T T R R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L F p@                                                            ",
-"                                                            q at V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R S T V r.W X Y Y Z `  .....+. at .#.G $.F %.E E D C &.B B *.H r at r@s at s@-.-.t at t@t at A A A A A A A A t at t@t at -.-.s@s at r@H H *.B B &.C D E %.F F G G #. at .+... .` ` Z Y X W W V U T S R Q Q P O O N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L K 9@                                                          ",
-"                                                          % u at L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N M M M N P R S T U U Q Q Q R T Z `  ...+.Z V V r.r.#.%.E D C C B B *.H H r at s@s at -.-.G  . ...#.t at A A A A r at .... .` D -.-.s at s@r at H H *.B &.C C E E %.$.W T T T V .... .` Z V P P O O S T S R R P N M M L L N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L D v@                                                          ",
-"                                                        J w at r.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N M L L L L O Q R S T S L L L L O Y Z ` `  .V L L L L ..$.F F %.E D D C C &.B B *.H *.r.N N N T H s at s@s at r@D N N N N +.H *.B B &.&.C C D E E F F $.G @.P L L L N ` ` ` ` Y R L L L L P V U T T P L L L L L P Q Q P P P P P P P P P P P P N L L L L L N P P P P L L L L L L O O O O O O O O O O O O N N O M L L L L L M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L x@&                                                         ",
-"                                                        y at A L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M L L L L L N N N N N M L L M M O P Q R R R R S T T T T T U T R O N N N P W Y Y Y T Q O O O N U ..+.+. at .@. at .G G $.$.F %.E E F O L M L L M C -.t at A G L L L L L Z r q p p W L L L L L w 6 7 7 8 3 3 a a a b b 2 2 2 A L L L L L r at b b a 3 Z L L L L O p 6 4 4 5 9 z at l m n o p q r s E L L L L L +.*.C F +.N L L L L L N N M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L T a+.                                                       ",
-"                                                      , A at L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M L L L L L M M M M N N N N N M L N O O O O Q R R R L L O P O O Q V V r.r.W W Y Z Y Y Z ` ` +. .L L M M M L @.D C H ` L L L L L T z z y x U L L L L L C r r r r q o p p p p p p p o C L L L L L ` q s t t U L L L L L E z -.s at r@r at B E &.E %.F $.G G ` L L L L L Q ...... at .N L L L L L P r.T T Q L L L L L L N P N N Q O M P N N N N N X  .V L L L L L L L L L L L L L L L L L G B@                                                      ",
-"                                                    + C at L L L L L L L L L L L L L L L L L L L L R A Z W W W M L L L L L L U X X V L L L L L L Y l 9 9 9 5 5 4 B B 4 &.` ` ` O L L L L L P ` ` ` X L L L L L L t at .. . .T L L L L L +.2 c c c c d d C w e e A @. at . .L L L L L @.d &. at .@.r.L L L L L b j j j k k D at 2 Z j u at u@| F F G N L L L L 2 E at 4 F F ` L L L L &.F at .@t %.E U M M M N < G at G@H at H@H at I@b F J at K@K at K@d C C r.P P P  .H at L@M at n C F P P P P t at N@O at O@O at O@O at P@#.k O at 8@8 at Q@O at p E R M M M M 1 R at R@N at t@ .L L L L T S at T@U at G@%.P L L L L B V at U@U at U@U at Q@G E at W@W at W@W at W@W at 4 P L L L L T P at X@X at Y@*.L L L L L &.K X at X@X at X@< -.Z at X@X@`@`@`@`@: P L L L L M  #.#.#+#*.L L L L L ..@#X at X@F at O L L L L L t Y at Z@Z at Z@i p W at +#+#+#Y at Y@.###N at Z L L L L L L L L L L L L L L L L L 7 ]                                                     ",
-"                                                  J 0+Z L L L L L L L L L L L L L L L L L L L L A l F F F ` L L L L L L Q $.%.F V L L L L L L 9 E at E@E@$#$#$#H at 0 h u at r@D D G N L L L L L G C C C ` L L L L L  .4 C C C T L L L L L 6 K at K@P at P@M at M@L at n %#L at P@r B B G L L L L L 6 K at A *.*.W L L L L W &#R at T@T at T@U at U@. at H T at K K . at H r@&.M L L L P K@`@} s at s@@.L L L L 9 ##*#7 t at t@W M M M T V@=#-#-#;#;#q.$#s@=#>#>#>#,#y z Z P Q Q +.'#)#!#k y s at R Q Q Q w )#~#~#~#~#{#)#-.J@]#]#]#]#]#A at A W N M M M c ^#/#~#8 C L L L L N U at a+a+>#u W L L L L $.(#_#_#:#:#a+6 <#:#:#:#:#[#[#M at V L L L L L : [#[#:#A at L L L L L V *#[#[#[#[#C at r@}#[#[#[#:#:#:#|#r at L L L L L p {#_#a+I at L L L L L L : /#/#1#z L L L L L W +#{#{#~#-#0 U@~#2#2#|#|#|#|#!#: P L L L L L L L L L L L L L L L L L M@&                                                   ",
-"                                                  y at A L L L L L L L L L L L L L L L L L L L L Y b &.F F G P L L L L L L ` %.%. at .M L L L L L @.A at E@E@$#$#$#F at J@4 $#b E E D r.L L L L L U r at D D E Q L L L L L s t C C F M L L L L R  #K at P@P at P@M at M@K at q &#N at H@s at B B W L L L L N 3#,#H *.B S L L L L D Q at R@T at T@U at U@U at j 9 K K K k r at r@%.L L L L ` V at 4#a s at s@Z L L L L | ##*#9 t at -.U M M N Y K -#-#;#;#q.q.<#s at -#>#(#(#G at y y  .R R R ..*#!#|#u at x -.T R R R -.1#~#{#{#{#]#~#r  #^#]#]#^#^#&#A ..N N M M u {#/#/#i H O L L L L $#_#_#]#a @.L L L L P Y@:#:#:#:#[#H at s ^#[#[#[#[#[#5#H L L L L L p /#[#6#*#Y L L L L L u@[#[#[#[#_#3 E@[#[#[#[#[#[#[#,#L L L L L T W at _#_#7#B L L L L L B >#/#/#M at P L L L L L z@|#]#]#{#O at g (#~#~#2#2#2#|#|#5#p L L L L L L L L L L L L L L L L L T a+.                                                 ",
-"                                                8#D at L L L L L L L L L L L L L L L L L L L L N l o $.F F X L L L L L L T F %.F U L L L L L M 6 E at E@E@$#$#$#H@} [ E at z E E F O L L L L L &.B D D @.L L L L L R c H C C Z L L L L L *.S at K@P at P@M at M@M at F@5 M at N@D@&.B C R L L L L ` x@[ B *.D N L L L L n R at T@T at T@U at U@U at 6 j K K Y at c r at r@@.L L L L E K 4#5 s at s@r.L L L L k 9#.#l t at s@T N N N Z Y at -#;#;#q.q.5#3#t@;#(#(#7#K at y y ..R R R ..'#|#|#: x t at V S R R H (#{#]#]#]#]#]#c 2 ]#^#^#/#/#K A F N N N N C )#a+a+x at s@T L L L L 4 a+_#_#F at E L L L L L F@[#[#[#[#[#9#C -#[#[#[#[#6#a+0 O L L L L Z -#6#6#/#q L L L L L *.2#6#6#6#6#U at A !#6#6#6#[#[#[#(#E L L L L L 8 /#:#:#0#L L L L L L G at a+a+!#s L L L L L T a#]#]#]#)#< M@~#~#~#~#~#2#2#2#Y@` L L L L L L L L L L L L L L L L L G B@                                                ",
-"                                              # ##L L L L L L L L L L L L L L L L L L L L L C c D $.F #.N L L L L L M +.F F +.M L L L L L F %#E at E@$#$#$#F at J@9 F@} D E E Z L L L L L Q v D D E U L L L L L B a D C D R L L L L L 2 K at P@P at P@M at M@L at 0 %#N at N@3 B B %.L L L L L -.b#5 *.*.G L L L L L i T at T@T at U@U at U@R at x : K K K 4 r at r@Y L L L L t at 4#+#n s at r@U L L L L 0#9#`@p t at s@T N N N $..#;#;#q.q.5#># #x q.7#7#7#N at y x @.T T T Y `@2#2#x at x A W T T T D q.]#]#]#^#^#^#u at t ]#/#/#/#/#C at w C N N N N Y C at _#_#4#t at X L L L L s@~#:#:#W at B P L L L L n a+[#[#[#[#{#s at b#6#6#6#6#6#6#M at V L L L L L S at c#c#c#I at M L L L L Q K c#c#c#c#{#v O at c#c#6#6#6#6#[#D at L L L L L W ##[#[#7#C L L L L L B 7#_#_#R at T L L L L L p !#^#^#]#4#c =#{#{#~#~#~#~#2#|#A at L L L L L L L L L L L L L L L L L L 4 ^                                               ",
-"                                          d#/ >#W L L L L L L L L L L L L L L L L L L L L S 2 t $.$.$.V L L L L L L V F F F T L L L L L O a E at E@$#$#$#$#H at h g F at r E E F Q L L L L L C z D D $.N L L L L L 0 u C C G L L L L L V $#K at P@P at M@M at M@K at p J at N@K at t B B ..L L L L L 2 N at v *.*.Y L L L L Q H at R@T at T@U at U@W at O@y O at K Y at T@q r at H V L L L L l X at K s s at H S L L M L K at 9#4#r t at r@R N N O %.*#;#q.q.5#>#>#%#v >#7#1#1#b#y x G T U U U Y@~#~#Q at x z X U U U @.}#^#^#/#/#/#/#J at t@2#a+a+a+a+)#n H O O N N N W at _#_#>#t @.L M L L X =#[#[#>#w U L L L L E !#6#6#6#6#6#k d [#c#c#c#c#c#;#D L L L L L n :#c#c#q. at .L L L L L 2 [#c#c#c#c#G at m a+c#c#c#c#c#c#}#` L L L L L < :#[#[#0#L L L L L L H at _#_#{#z at L L L L L R M@/#/#^#{#F at E@~#]#{#{#{#~#~#~#-#t at L L L L L L L L L L L L L L L L L L P@&                                             ",
-"                                          + e#X L L L L L L L L L L L L L L L L L L L L L s 2 %.$.$...M L L L L L N #.F F ..L L L L L L D u at E@E@$#$#$#F@&#5 $#k B E E  .L L L L L O n &.D D Y L L L L L ` [ *.C C W L L L L L t@&#K at P@P at M@M at M@. at z@L at N@G at r@B &.U L L L L P $#&#s at B B T L L L L +.N at T@T at U@U at U@W at J@x R at K Y at V@x r@*.S L L L L f X at R@x s@*.P L M M T Q at f#Z at t t at H P O O O C 9#q.5#5#>#>#(#3#c (#1#1#)#8 at y x G V V V U Y@~#{#K x x ` V V V Z *#/#/#/#/#/#a+U at w )#_#_#_#_#]#a -.S P O O N S@:#:#]#7 E L M M M L K [#[#/#8 ` L L L L P X at 6#6#c#c#c#T@*.|#c#c#c#c#c#_#6 N L L L L  .q.g#g#:#5 L L L L L F 1#g#g#g#g#(#s@'#g#c#c#c#c#c#:#a L L L L L G q.6#6#1#C L L L L L s@)#:#:#+#V L L L L L t at 1#/#/#/#-#c 4#]#]#]#]#{#{#~#~#O at T L L L L L L L L L L L L L L L L L T a+.                                           ",
-"                                          ! h L L L L L L L L L L L L L L L L L L L L L @.g y $.$.G R L L L L L L X F F $.R L L L L L P 1 E at E@$#$#$#F at H@[ f F at 9 %.E %.R L L L L L #.o E D %.Q L L L L L r 0 D C E P L L L L L e K at P@P at P@M at M@N at 2 [ N at N@< &.&.E N L L L L #.P at 3#B B D N L L L L z a#T at T@U at U@W at W@A at l K Y at Y@L at -.H &.N L L L L $#X at Q@A s@&.N M M M Y U at f#K x t@*.P O O P r@}#5#5#>#>#(#7#<#g 7#)#)#!#T at x w $.W W W U K {#]#X at w x ` W W W T +#/#a+a+a+_#_#9#z ;#_#_#_#_#_#< t at V P P O O i :#[#:#< H N M M M M F at 6#6#6#E@%.L L L L L 0#c#c#c#c#c#1#D X at c#c#g#g#g#g#x at T L L L L L M at h#h#h#O at P L L L L L N at h#h#h#h#c#} i c#g#g#g#g#g#g#X at U L L L L L $#6#c#[#F at L L L L L M &#[#:#/#a L L L L L M I at a+/#/#/#N at i |#^#]#]#]#]#{#{#|#c L M L L L L L L L L L L L L L L L L G i#J                                         ",
-"                                        # W at L L L L L L L L L L L L L L L L L L L L L Q 3 0 F $.$.Z L L L L L L P G F F ` L L L L L L B  #E at E@$#$#$#F@&#9 E@ #r at E E +.L L L L L L l t at D D ..L L L L L Q [ v D C @.L L L L L ` ,#K at P@P at M@M at M@L at o I at N@L at 5 &.&.G L L L L L s Q at c B B G L L L L L 2 T at T@U at U@U at W@W at a f Y at Y@Y at G@H H E L L L L O K at .#M at s@s at E M M M M $.4#C at U@y t at B O P P P t@=#5#>#>#(#(#7#u at g 7#)#!#!#Y at w w $.W W X U R@]#]#}#s w +.X X W T R at _#_#_#_#_#_#5#t@*#:#:#:#:#[#H at z Y P P P O n _#[#[#K at r@R M M M M z@:#6#6#W at B N L L L L l [#c#c#c#c#:#o F at g#g#g#g#g#g#-#F L L L L L m 6#h#h#|#D L L L L L n [#h#h#h#h#`@t@)#h#h#h#h#h#g#_#l L L L L L C !#c#c#7#E L L L L L s@|#[#[###` L L L L L C q.a+a+a+!#g @#/#^#^#]#]#]#]#{#f#%.L M L L L L L L L L L L L L L L L L 9 ^                                         ",
-"                                      d#p.r.L L L L L L L L L L L L L L L L L L L L L s@[ -.$.$.G P L L L L L L ` F F G Q L L L L L Q c E at E@$#$#$#F at H@h } . at b %.E %.T L L L L L ` 0 E E E T L L L L L C k &.D D U L L L L L x x at P@P at P@M at M@M@: o M at N@x at y &.&.X L L L L L [ Q at l B B Y L L L L N $#T at T@U at U@U at W@R at v ,#Y at Y@+#u at H H G L L L L X @#.#H at r@s at F L M M M B *#C at V@A t at D P P Q Q u ;#>#>#(#7#7#1#%#g 1#!#|#|#+#w w F X X Y T O@^#^#q.p v @.Y Y Y r.N at _#_#_#:#:#:#|#t R@[#[#[#[#[#a#z +.Q Q P P s@]#6#6#4#-.r.M M M M -.^#c#c#(#x T L L L L E 2#g#g#g#g#g#J at r _#h#h#h#h#h#:#9 N L L L L ..(#h#h#g#f L L L L L Y =#h#h#h#h#:#q S at h#h#h#h#h#h#h#R at P L L L L L x at c#c#c#E at L L L L L M &#[#[#_#g L L L L L L <#a+_#a+a+K d >#/#/#^#^#]#]#]#]#J at P L M L L L L L L L L L L L L L L L L K at j#                                      ",
-"                                      k#F L L L L L L L L L L L L L L L L M L L L L W | 4 $.$.$.W L L L L L L S $.F F Z L L L L L L s at 3#E at E@$#$#$#F@&#9 E at E@x %.E #.M L L L L L q r E E G M L L L L L 2 7 D D F N L L L L N h P at P@P at M@M at M@L@| h N at N@F at B &.C R L L L L U G at M@y B &.T L L L L ` M at T@T at U@U at W@W at 8@t at M@Y at Y@+#f H H  .L L L L %.K *#E at s@s@@.M M M N t@##}#Q at t@A E P Q Q R t q.>#(#7#7#1#1#%#h )#|#|#2#`@v v F Y Y Y U O@/#/#)#9 v $.Z Z Z Y G@:#:#[#[#[#[#^#4 &#[#[#[#6#6#C at x E Q R Q Q @.>#c#c#7#t  .N M M M Z ;#c#c#a+7 W L L L L P .#g#g#g#h#h#C at D 5#h#h#h#h#h#h#H at S L L L L L N at l#l#l#+#R L L L L L . at l#l#l#l#l#N at u a+l#l#l#h#h#h#^#x L L L L L A ]#g#g#7#E L L L L L s at 2#6#6#-#@.L L L L L F ;#_#_#_#]# #H@^#/#/#/#^#^#^#]#)#9 L M M L L L L L L L L L L L L L L L R ]#.                                     ",
-"                                    m#d L L L L L L L L L L L L L L L L L L L L L N l h *.$.$. at .N L L L L L M ..F F G P L L L L L S f E at E@$#$#$#$#I at h } . at g E %.%.V L L L L L U e *.E E W L L L L L `  #y D D  .L L L L L @.G at K@P at P@M at M@M at M@p : N at N@g C B %.M L L L L %.N@: *.B D O L L L L C @#T at U@U at U@W at W@&#z a#Y at +#Y at 8 H H W L L L L s at 4#*#j s at s@Z N N N O r f#}#L at t@A F S T U U 7 >#(#7#7#1#1#)#D at j !#|#2#~###s v &.#.G $.#.O@/#a+|#7 u &.E D D D F@[#[#[#[#[#6#:#d A at 6#6#c#c#c#)#p B #.%.E %.C '#c#c#/#7 %.Z #. at .@.+.W at g#g#c#j #.U Y Y X X H at h#h#h#h#h#^#r at 8@h#h#h#l#l#l#=##.L P O O N 9 c#l#n#/#s at L L L L L A :#n#n#n#n#2#-.+#l#l#l#l#l#l#l#K at L L L L L Q R at h#h#c#$#L L L L L M K at c#6#[#<#L L L L L L D at _#:#_#_#}#2 ##a+/#/#/#/#^#^#^#`@ .L N L L L L L L L L L L L L L L L L #.i#J                                   ",
-"                                  o#O at L L L L L L L L L L L L L L L L L M L L L L D < n G $.$.Y L L L L L L U $.F F +.L L L L L L A <#E at E@$#$#$#F at x@9 E at F@q %.%.F R L L L L L A 3 %.E E T L L L L L r A at C D D W L L L L L p K at P@P at P@M at M@M at H@p M at b#N at z@&.&.$.L L L L L n Q@< C &.E M L L L L m R at T@U at U@U at W@K  #v W at +#+#K m H H V L L L L m X@*#e s at s@Y N N P R b }#}#&#t at A F S S T T c (#7#7#1#)#)#)#i D@|#2#~#~#}#q u H $.F F F O at a+_#]#2 t -.r at s@s at -.F@6#6#6#6#c#c#6#k | c#c#c#c#c#/#8 s at t@[ $#z at y *#c#g#c#[ B E H &.4 b W at g#g#g#O at D Y #. at .+. .,#h#h#h#h#h#g#} | h#l#l#l#l#l#[#l N Q Q P O v c#n#n#l# #L M L L L &./#n#n#n#n#l#A at b g#n#n#n#n#l#l#2#C L L L L L L at h#h#h#1#E L L L L L F at c#c#c#(#E L L L L L 4 _#:#:#:#_#&#D@{#a+a+/#/#/#/#^#]# #L M N L L L L L L L L L L L L L L L L z@/                                   ",
-"                                d#I V L L L L L L L L L L L L L L L L M L L L L S 2 f C $.$.$.+.L L L L L N @.$.F F G M L L L L T g E at E@$#$#$#$#I at i | . at D@B %.%.%.T L L L L Q | z E E E V L L L L Q i 7 E D D ` L L L L O k K at P@P at M@M at L@N@} } b#b#K at x &.&.F L L L L L i @#8 &.&.D O L L L L i T at T@U at U@W at W@W at d e +#+#+#R at u H H r.L L L L e *#.#3 s at s@Y L L L L < }#=#J at t@A G L L L L } 7#7#1#)#)#!#!#[  #~#~#{#]#=#q t %.L L L L N at _#:#a+} t E L L L L 3#c#c#c#c#c#c#c#: 4 [#g#g#g#h#c#g A R 5 h G L ##g#g#g#M at r@R L M t at G Y at h#h#h#;#-.R L L L L x at l#h#l#l#l#l#U@*.{#l#n#n#n#n#n#,#R L L L L 4 l#n#n#n#C at X L L L L x c#n#n#n#n#n#f#H >#n#n#n#n#n#n#l#F at L L L L L `@l#h#h#g#F at L L L L L R at g#c#c#c#: L L L L L F@[#[#[#:#:#1#} U at _#_#a+a+/#/#/#/#>#x L N N L L L L L L L L L L L L L L L L J at j#                                ",
-"                                p#F L L L L L L L L L L L L L L L L M L L L L L v k 7 s at H C %.G O L L M L B A s at B D F R N L M L u <#E at E@$#$#$#F at x@5 E at .@e y t at H C X N L M M &.k t y s at B  .N L L M B 0#6 v z r at G Q N L R F I at P@P at M@M at L@L at N@p 0#b#b#I at l t z B S P L Q ` I at 8@d p x H r.S L T ` S at T@U at U@W at W@K U at u E at +#+#Z at R@b n w @.W L S r.<#*#.#k 5 r F W L R W $#=#=#N at a l *.X M R W  #7#1#)#)#!#|#|#[ <#{#{#]#]#>#u at a -...S Q  .V@:#[#:#M at c y ..T N ..H at g#c#g#g#h#h#h#8 at o a+h#h#h#h#h#R at 0 C 4 a D E ;#h#h#h#=#c C +.M t@%.f#h#h#h#_# #H $.N ` F U at l#l#l#l#n#n#)#F .#n#n#n#n#n#n#5#r D S V D E at n#n#q#q#c#e C V U C e n#q#q#q#q#q#c#9 ,#n#q#q#q#q#n#n#(#x +.P C z 7#l#l#l#l#)#t G L E B C at g#g#g#g#|#o %.L %.&.S@[#[#[#[#[#[#U@| )#_#_#_#a+a+a+/#/#T at V L O L L L L L L L L L L L L L L L L R ]#.                               ",
-"                              ] 0 L L L L L L L L L L L L L L L L M M L L L L ..g D at k k j [ g | 1 e +.a e k %#A at k i h } f #.0 } %#E at E@E@$#$#$#H at k e . at .@. at F@E at 3#%#i i &.4 i u at G@: : . at E@%#A at t@n A at E@&#S at J@H@,#E at 3#o A 3#. at P@M at M@M at M@L at L@I at p M at b#b#b#b#L at K@J at 0#d G F at H@Q at V@@#Q at b#K at J@k ` ,#&#R at U@U at W@W at K K @#A P at +#+#Z at 4#Z at Y@R at 8@x@@.F@@#+#'###'#*#4#U at b#@. #U@*#-#-#;#-#f#`@W@&.h X at C@)#)#!#!#|#2#|#h E@{#]#^#^#/#/#~#5#q.c u q.]#[#6#6#6#_#)#7#<#r at q.]#h#h#h#h#h#h#h#+#w ~#l#l#l#l#l#h#:#2#f#| .#|#c#l#l#l#l#6#~#f#G @#|#[#l#l#l#l#g#]#>#B I@{#[#n#n#n#n#n#n#c#p ,#n#n#n#n#q#q#q#:#^#d 6 ]#[#I q#q#q#q#c#/#F at v 2#[#I I I I I I I a#t@^#q#q#q#q#q#q#n#_#4#E f#a+l#n#n#n#n#l#a+}#C R@/#c#h#h#h#g#g#/#(#v K@{#_#c#6#6#[#[#[#]#j &#_#_#_#_#_#a+a+/#]#| L M O L L L L L L L L L L L L L L L L @.r#J                             ",
-"                            % M at L L L L L L L L L L L L L L L L L N L L L L P 7 D at D@A at A@A at A@%#%#E@,#z at u@u@ # # # #3#3#E at J@p 3#E at E@E at E@$#$#$#F at K@z at E@. at .@.@,#,#,#0#0#P at n <#: G at H@H at I@I at I@J at P@m u at S@S@&#&#&#&#x at x@M at 8 < P at P@P at M@M at M@L at L@N at h d N at b#b#O at O@O at 8@8 at 8@A at p Q@@#@#V at V@V at a#a#R at F@-.V at T@U at U@U at W@W at K K K at t@V at +#+#Z at 4#4#4#`@X@@#B V@*#*#'#####9#9#f#+#@.N@=#=#-#;#;#q.5#>#}#B 0#7#1#)#!#!#|#2#2#|#h $#]#^#^#/#a+a+_#_#:#g r _#6#6#c#c#c#g#g#h#M@*./#h#h#l#l#l#l#l#l#}#z 7#n#n#n#n#n#n#n#n#{#| X at l#l#l#l#l#l#l#l#:#q S at l#l#l#l#l#l#n#n#h#3 f l#n#n#n#n#n#n#n#n#. at t 6#q#q#q#q#q#q#q#q#K C ]#I I I I I I I I 5#C -#I I I I I I I I /#-.V at I I I q#q#q#q#q#c#5 ,#n#n#n#n#n#n#n#n#h#u at d [#l#h#h#h#h#h#g#g#O at 3 {#c#c#c#6#6#6#[#[#'#2 -#:#:#_#_#_#a+a+a+=#E L O N L L L L L L L L L L L L L L L L 9 /                             ",
-"                          . c#T L L L L L L L L L L L L L L L L N M L L L L H j D at D@A at A@A at A@%#%#K at 8 j u at u@ # # #3#3#3#J at c h <#E at E@E at E@$#$#$#H at k c . at .@.@,#,#,#,#0#H at E@6 G at H@H at H@H at I@I at I@J at J@n I at S@S@&#&#&#x at x@x at P@q H at P@P at P@M at M@M at L@L at N@o ,#b#b#b#O at O@O at 8@8 at 8@7 i @#@#@#V at V@V at a#a#R@} 4 T at T@U at U@U at W@K K K F at z@K +#Z at Z@4#4#`@`@X at P@z Y@*#'#'#####9#f#f#T at C R@=#-#-#;#q.q.5#>#C at s@K at 1#)#)#!#|#2#2#~#2#h F@^#/#/#a+a+_#:#:#[#D at n _#c#c#c#g#g#h#h#h#U at H {#l#n#n#n#n#n#n#n#)#q 9#n#n#n#n#n#n#n#n#:#9 K at n#n#n#n#n#n#n#n#h#f g l#n#n#n#n#n#n#n#n#K at t@:#n#n#n#n#n#n#n#q#C at E (#q#q#q#q#q#q#q#I {#&.U at I I I I I I I I h#9 F at I I I I I I I I q#F at z@g#I I I I I I I q#+#x 2#q#q#q#n#n#n#n#n#(#q X at l#l#l#h#h#h#h#h#/#c L at c#c#c#c#c#6#6#6#_#: E@/#:#:#:#_#_#_#a+/#x at R L P M L L L L L L L L L L L L L L L L J at j#                          ",
-"                          B@#.L L L L L L L L L L L L L L L L M N L L L L W e D at D@A at A@A at A@%#%#,#u at a u at u@u@ # # #3#3#$#J at 5 3#<#E at E@E@$#$#$#F at P@5 <#. at .@.@,#,#,#0#: P at 7 u at G@H at H@H at H@I at I@J at x@} g S at S@S@&#&#&#x at x@K@<#6 K at P@P at P@M at M@M at L@L@&#s P at b#b#b#O at O@O at 8@8 at b#r S@@#@#@#V at V@V at a#a#V at 9 <#T at T@U at U@W at W@K K K f | +#+#Z at Z@4#4#`@X at X@,#7 X@*#'#####9#9#f#C at O@o 4#-#-#;#q.q.5#>#>###l V@)#)#!#|#2#2#~#{#|#g ,#/#/#a+_#_#:#:#[#6#J@} _#c#g#g#h#h#h#l#l#f#z@)#n#n#n#n#n#n#q#q#/#4 K q#q#q#q#q#q#q#q#h#[ A at n#n#n#n#n#n#n#n#n#L at l [#n#n#n#n#n#n#n#n#-#*.(#n#n#n#q#q#q#q#q#a+H Q at q#q#q#q#I I I I n#d f n#I I I I I I I I 8 at -._#I I I I I I I I >#*.}#I I I I I I I I [#m x at q#q#q#q#q#n#n#n#h#F at e [#l#l#l#l#h#h#h#h#Z at 7 )#g#g#c#c#c#6#6#6#7#c `@[#:#:#:#_#_#_#a+~#5 L N Q L L L L L L L L L L L L L L L L R ]#9@                        ",
-"                        / 9 L L L L L L L L L L L L L L L L L O L L L L L p k D at D@A at A@A at A@%#u at x@z at D@u at u@ # # #3#3#3#&#2 i <#E at E@E at E@$#$#$#H at A@c . at .@.@,#,#0#: : H at H@9 : G at H@H at H@I at I@I at J@K at n 0#S at S@&#&#&#&#x at x@M at 7 u at P@P at P@M at M@M at M@L at N@i a N at b#b#b#O at O@O at 8@8 at I@n O@@#@#V at V@V at a#a#R at O@r P at T@U at U@U at W@W at K K W at 4 $#+#+#Z at 4#4#4#`@X at X@i } *#*#'#####9#f#f#C@&#4 ##-#-#;#q.5#>#>#(#*#z at Y@)#!#|#|#2#~#{#{#|#} H@/#a+_#_#:#[#[#6#c#M@} _#g#h#h#h#l#l#n#n#;#9 (#q#q#q#q#I I I I 6#c L at I I I I I I q#q#q#,#b h#q#q#q#q#q#q#q#q#*#z !#n#n#n#n#n#n#n#n#a+v R at q#q#q#q#q#q#q#q#n#| c n#I I I I I I I I K H /#I I I I s#s#s#s#{#H `@s#s#s#s#s#s#s#s#n#0 D at q#I I I I I I I I 8 at r /#I q#q#q#q#q#q#n#7#r X at n#n#l#l#l#l#h#h#:#g I at c#g#g#c#c#c#c#6#[#8 at h ~#[#[#:#:#:#_#_#_#*#+.L P P L L L L L L L L L L L L L L L L +.t#J                       ",
-"                      j#H at L L L L L L L L L L L L L L L L L O M L L L L F [ D at D@D at A@A at A@%#%#I@[ e u at u@u@ # # #3#3#.@,#4 <#<#E at E@E at E@$#$#F at P@z@<#.@,#,#0#0#0#: : K at a k G at H@H at H@H at I@I at I@&#<#7 S at S@S@&#&#&#x at x@x at x@q S at P@P at P@M at M@M at L@L at N@m E at N@b#b#O at O@O at O@8 at Q@g c Q@@#@#V at V@V at a#a#R at J@q @#T at U@U at U@W at W@K K V at q x at +#Z at Z@4#4#`@`@X@`@2  #*#'#'###9#9#f#C@}#. at 0 f#-#;#q.q.5#>#(#7#4#m Z@!#!#|#2#~#{#{#]#2#| &#a+_#_#:#[#[#6#c#c#b#f :#h#l#l#n#n#n#n#q#)#9 =#I I I I I I I I l#[ $#I I I I I I I I I V at l [#I I q#q#q#q#q#q#2#w *#q#q#q#q#q#q#q#q#h#e D at n#q#q#q#q#q#q#q#I 8@&.^#I I I I I I I I {#&.+#s#s#s#s#s#s#s#s#q#e | q#s#s#s#s#s#s#s#s#+#H ~#s#s#s#s#I I I I ^#v V at I I I q#q#q#q#q#l#3#e 6#n#n#n#l#l#l#l#h#*#5 q.g#g#g#g#c#c#c#6#]#[ N@[#[#[#:#:#:#_#_#a+E at L L R N L L L L L L L L L L L L L L L L l u#                      ",
-"                    . ~#Q L L L L L L L L L L L L L L L L N O L L L L R a D at D@D at A@A at A@A@%#3#J at 9 %#u at u@ # # # #3#3#K at 4 k <#<#E at E@E@$#$#$#H at A@1 ,#,#,#0#0#0#: : G@&#n 0#G at H@H at H@H at I@I at I@M at 5 3#S at S@S@&#&#&#x at x@P at j 3 K at P@P at P@M at M@M at L@L at S@t K at N@b#b#O at O@O at 8@8 at O@n F@@#@#@#V at V@V at a#a#R at D@0 R at T@U at U@U at W@K K K N at q @#+#Z at Z@4#4#`@X at X@4#5 J@*#'#####9#f#f#C@}#A at e }#-#;#q.5#>#>#(#7#+#z@##!#|#2#~#~#{#]#^#2#e P at _#_#:#[#[#6#c#c#g#O@} :#l#n#n#n#q#q#q#I ~#4 *#I I s#s#s#s#s#s#I E@< I s#s#s#s#s#I I I '#v |#I I I I I I I I [#4 S at q#q#q#q#q#q#q#q#q#I at a c#q#q#q#q#I I I I !#H '#I I I I I I I I q#d g I s#s#s#s#s#s#s#s#Z at B ~#s#s#s#s#s#s#s#s#[#y K at s#s#s#s#s#s#s#I I I at z@[#I I I I q#q#q#q#>#s .#n#n#n#n#l#l#l#l#6#%# #6#h#g#g#g#c#c#c#c#X at 1 (#[#[#[#:#:#:#_#_#)#u L N S L L L L L L L L L L L L L L L L L H at j#                    ",
-"                    v#@.L L L L L L L L L L L L L L L L M P L L L L L y k D at D@D at A@A at A@A@%#&#2 [ u at u@u@ # # #3#3#,#E at 3 <#<#E at E@E at E@$#$#F at M@z at E@,#,#,#0#0#0#: : &#} f G at G@H at H@H at I@I at I@J at I@n I at S@S at S@&#&#&#x at x@L at l $#K at P@P at P@M at M@M at L@N at A@0 N at N@b#b#O at O@O at 8@8 at P@s P at Q@@#@#V at V@V at a#a#a#7 u at T@T at U@U at W@W at K K K ,#l W at +#Z at 4#4#4#`@X at X@W at o b#'#'#####9#f#f#C at C@g j -#;#q.q.5#>#(#7#7#a#9 f#|#2#2#~#{#]#^#^#2#e L@:#:#[#6#6#c#g#g#h#8 at e _#n#n#q#q#I I I I a+a +#s#w#w#w#w#w#w#w#w#S at e n#w#w#w#s#s#s#s#s#1#v f#I I I I I I I I n#k [ n#I I I I I I q#I *#n )#I I I I I I I I g#b K at I I I I I s#s#s#s#R at t@_#s#s#s#s#s#s#s#s#:#s at b#w#w#w#w#w#w#s#s#s#H at u c#s#s#s#s#s#s#s#s#~#x Z at I I I I I I q#q#l#3#e c#n#n#n#n#n#l#l#l#;#5 C at h#h#g#g#g#g#c#c#_#3#,#_#[#[#[#[#:#:#_#_#W at V L Q R L L L L L L L L L L L L L L L L R 2#9@                  ",
-"                  x#o L L L L L L L L L L L L L L L L L P M L L L L ` f D at D@D at A@A at A@A at A@F at F@7 u at u@u at u@ # # #3#3#K at 4 A@<#<#E at E@E@$#F at F@J at A@b ,#,#,#,#0#0#0#: : K at m ,#G at G@H at H@H at I@I at I@K at d h S at S@S@&#&#&#&#x at K@J at q &#K at P@P at M@M at M@M at L@O at m <#N at N@b#b#O at O@O at 8@Q at .@m 8 at Q@@#@#V at V@V at a#a#T at q &#T at T@U at U@W at W@K K +#k d +#+#Z at 4#4#`@`@X at X@R at p U@'#####9#f#f#C@}#C at d E@;#;#q.5#>#>#(#7#1#R at 7 ;#|#2#~#{#]#]#^#/#~#} L@[#[#6#6#c#g#g#h#l#@#c a+q#q#I I I I s#s#[#c V at w#w#w#w#w#w#w#w#y#Q at 3 c#w#w#w#w#w#w#w#w#_#9 R at s#s#s#s#I I I I I &#5 c#I I I I I I I I ]#9 +#I I I I I I I I I x@%#h#I I s#s#s#s#s#s#^#4 ;#s#s#s#s#s#s#w#w#s#$#k I w#w#w#w#w#w#w#w#|#z (#s#s#s#s#s#s#s#s#I 3#i q#I I I I I I q#q#>#r 7#q#n#n#n#n#n#l#l#g#$#A at h#h#h#g#g#g#c#c#c#;#b >#6#[#[#[#[#:#:#_#/#g L L T O L L L L L L L L L L L L L L L L +.t#J                 ",
-"                > F at L L L L L L L L L L L L L L L L L O P L L L L L 7 <#E at E@E at E@$#$#F at F@c#9 <#,#,#0#0#0#: : : *#8 at c H at H@&#@#V at V@V at a#a#c#4 8 at R@R at R@T at T@T at U@U at 5#M at k Y at +#+#+#+#+#Z at Z@4#h#z at Y@.#*#*#*#*#'#'#'#|#K at 3#9#9#f#f#f#C at C@}#}#g#z@'#-#-#-#;#;#q.q.5#/#G@: >#(#7#7#7#1#1#)#)#6#l (#{#]#]#]#/#/#/#a+n#0#&#[#[#[#6#c#c#g#h#l#^#0 [#q#I s#w#w#p.p.H+z#A at U@]@A#B#C#w at 0+D#E#F#>#2 A#G#H#v#I#J#t#r#G+I#k f#K#L#p#M#{@k#N#O#v@{#g M#P#P#P#P#Q#Q#_ _ R#E@~#S#u#/ / / / / =.=.e#e P#=.=.=.=.=.=.=.=.x#3#-#=./ / / / / u#u#u#T#p {@x#x#/ / u#u#u#x#_  #*#x#S#S#S#_ _ Q#P#R#y#[ G+v at p@O#U#V#W#N#N#X#K@;#{@M#M#X#p#p#p#L#L#I F at Y#K#K#K#Z#`#`#`#B at r#0#2#G+G+G+r#t#t#t#J#J#_#0#F#v#v#v#H#G#G#G#G# $G at I  $.$.$F#F#+$E#E#E#_#N at F#0+w at C#C#B#B#A#A#e#&#0+A#T#T#@$z#z#H+H+p.7#Y L N V M L L L L L L L L L L L L L L L M l u#                ",
-"              + )#L L L L L L L L L L L L L L L L L N R L L L L L L [ O at O@8 at 8@Q at Q@Q@@#V at e#t 8 at R@R at T@T at U@U at W@W at 1#&#u at +#+#f#y#p.p.H+z#H+D#6 n#z#z#z#z#z#@$T#T#+$P at W@#$#$e#e#e#e#e#]@]@D#4 p.B#C#C#C#w at w@0+0+H#K at K E#E#+$+$F#F#.$.$ $0+3 B#G#G#H#v#v#I#q at q@i#K at X@r#r#G+G+i#$$$$B@`#0+e v#L#p#p#X#M#M#{@k#k#J@=#W#V#U#O#O#p at v@%$y at C#g &$Q#_ S#x#u#/ =.^ S#F@^#m#*$=$~ ! ' 8#, - e#[ ( & o## @ 9 at d#J   & E@@$                  q@<#d#                  &#q@                  {@E@                    K at G#                  &$g                     : e#                  i#j >           J d#. j#&#p.o#% & j#= > - ; , w at O@S#~ ~ *$*$( ( ] ] _ a#@$/ u#x#S#_ Q#P#R#R#p.*#k#p at O#U#V#W#N#N#k#K#R at F#X#p#L#K#Z#`#`#$$$$g#|#`#t#t#q at q@I#v#H#G#F#Y at K# $F#+$E#E#D#0+w at C#}#L L L R T L L L L L L L L L L L L L L L L M ,#>               ",
-"            J F# .L L L L L L L L L L L L L L L L L R N L L L L L M z at O@O at 8@Q at Q@Q@@#@#V@[#2 S at R@R at T@U at U@U at W@K ##;#d +#+#X at I H+H+z#z#z#C#} ]#z#@$@$@$@$T#T#T#B#q.I@#$#$e#e#e#e#]@]@A#w@[ c#B#C#C#C#w at w@0+0++$##K at E#E#+$+$F#F#.$.$ $0+| H+G#G#H#v#v#I#q at q@t#W at b#r#r#G+G+i#$$$$B@`#C#a E#L#p#p#X#M#M#{@k#M#&#K W#V#V#O#O#p at v@%$y at C#c M#Q#_ S#x#u#/ =.^ _ 3#~#m#*$*$~ ! ) 8#, ; T#[ ( & o#$ # + . J   * <#@$                  I#E at .                   H at q@                  i#0#                    . at G+                  r#E@                  J [ G+                  z#3##           J . 9@! } .$o#% & j#j#> - ; , ~#&#{ ! ~ =$*$m#( ] ] U#[ +$/ u#x#S#_ _ P#R#R#-#'#U#p at O#U#V#W#N#&$k#v#$#q at X#p#L#K#Z#`#`#$$$$K h#$$t#t#q at q@I#v#H#G#z#b#B at F#F#+$E#D#0+0+w at C#: L L L M V Q L L L L L L L L L L L L L L L L R 2#9@            ",
-"            S#u L L L L L L L L L L L L L L L L L Q P L L L L L L V z u at 3#3#<#E at E@E@$#$#8 at 6 | F at .@,#. at F@F at F@.@,#,#t ,#0#: +###########.#p P at .#*#*#*#*#'#'#'###0#a *#######9#9#9#9#f###m Q at f#C@}#}#}#}#}#=#-#,#d f#f#f#C at C@}#}#}#=#.#q T at -#;#;#;#q.q.q.5#5#[ h >#(#7#7#1#1#)#)#)#X at r 9#|#2#~#~#~#|#!#!#!#g u@~#~#~#{#]#]#^#^#/#4#l 1#_#:#[#[#6#c#c#g#[#c N at q#q#I h#h#h#l#n#q#+#2 c#y#p.H+z#z#w#y#p.q#g U@#$e#]@B#C#w at 0+E#+$##g C#G#v#v#I#I#q at q@q at F#g -#t#t#t#t#t#t#t#r#r#;#[ q at r#r#v#v#v#H#H#H#E#2 !#G#G#G#G#Y#Y# $q@ $Z at h +$F#F#F#F#+$E#G#G+I m C at e##$T#z#H+p.y#`#D#0#0 ^#_#a+/#/#]#]#6#V#1#v V@|#)#)#1#7#7#(#E#M#k 2 ;#q.;#-#-#-#=#7#M#A#x 8 at f#9#9#####'#'#^#k#K at 3 V at V@V at V@Q at Q@Q at 8@:#]@t H at b#b#N at N@N at L@L at M@h#H at 2 P at K@x at x@&#&#&#: J at 1#q 0#,#,#,#. at F@F at F@$#u@%.L L L L O W N L L L L L L L L L L L L L L L L E r#J           ",
-"          > F at M L L L L L L L L L L L L L L L L O T L L L L L L O $.C C C C C C C C C C C C C C C C C C C C C C &.&.&.C &.&.C C C C &.B r at t@A z z z z z z z z z y z z z z z z z z z z z y z z z z z z z z z z y y z z z z z z z z y x x y y y y y y y y y x x x x x x x x x x x x x w x x x x x x v v v v v v v v u u u u u t t t t s s s s r r r q q q p p p o o n n n m m l l l z at z@9 9 9 5 5 5 4 4 4 6 6 6 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 6 6 6 4 4 4 5 5 5 9 9 z at z@l l l m m n n n o o p p q . at p r r r s s t t t t 3 Z at v v v v v v w w w w @#W at x x x x x y y y y s ]@H at z z z z z z z z z . at i#[ A A A A A A A A z g#v#6 t at t@t at t@t at t@t at t@z at F#^#t at -.-.-.-.-.-.-.-.1 .$ #s at s@s at s@s at s@s at s@s at A@g#u r at r@r at r@r at r@r at r@H J at M@*.H H H H H H H H C P L L L L L T V L L L L L L L L L L L L L L L L Y g =.          ",
-"        9 at 2#Q L L L L L L L L L L L L L L L L N V N L L L L L L ` D E D D D D D D C C C C C C C C C C C C C C C C C C C C &.&.B B s at t@z z z z z z z z z z z z z z z z z z z y z z z z z z z z z z z y z z z z z z z z z z z y z z z z y y y y y y x y y y y y y y y y y y x y y x x x x x x x x w v x w w w w w w v v v t u v u t t t t s s r r p q q q p p p o o n n l z at m l l l z at z@9 9 9 5 7 7 4 6 7 7 7 7 7 8 3 3 2 3 3 3 3 3 3 3 3 3 3 2 c 3 3 3 3 8 8 7 7 7 7 d 0 4 4 4 4 5 9 9 9 9 7 d 5 m l l l m m n n n P at f o p p p q q r r r m 2#3 s t t t t t t t t 3#6#o v v t t t t t t u ~#{#r r r r r r r r s 3 G#C at r s s t t t t t t P at p#R at t t t t t t t t v f#t#g u u u u u u u u v {#g#r v s s s s s s t o h#b#t t t t t t t t t 9 _#1 u u u v v v v v v D L L L L L M Z W L L L L L L L L L L L L L L L R r K at j#        ",
-"        v#+.L L L L L L L L L L L L L L L L N G X L L L L L L E g [ [ < < < < j j i i i i k k k k k k %#A at D@D at A@A at A@A at A@%# #E@: 0#,#,#0#0#0#0#: G at H@J at S@I at J@J at J@J at J@J at S@S at S@M@&#&#&#&#&#&#K at K@K at K@P at O@M at P@P at M@M at M@M at M@L at L@O@@#b#N at N@O at Q@Q at Q@Q@@#V at U@T at V@V at a#a#R at R@R at R@R at U@`@K U at W@W at W@K K K Y at +#`@##Z at Z@Z at 4#4#`@`@X at X@X@=#}#*#'#}#-#;#;#q.q.5#(#2#7#7#7#1#)#)#|#|#2#~#a+[#]#]#^#/#a+_#_#:#[#[#s#I n#q#I I s#w#w#y#y#z#B#z#z#z#z#@$@$T#T#T##$w at +$e#e#e#e#e#e#e#]@]@]@Y#D#e#e#e#e#e#e#e#e#e#B#v#0+e#A#B#B#A#A#A#A#A#.$I#C#A#A#A#A#A#A#A#A#A#t#G#A#A#A#A#A#A#A#A#A#0+Z#+$A#B#w at 0+0+0+0+0+0+I#L#+$F#F#F#F#F#F#F#F#F#`#Z#F#F#F#F#F#F#F#F#F# $M#G+F#F#F#F#F#F#F#F#E#v#M#H#E#E#E#E#E#E#E#E#D#q at Z#E#D#+$+$E#E#E#E#E#E#J#J#0+0+0+0+0+w at w@C#C#w at J#E#B#B#A#A#A#]@]@e#e#)#Z L L L L L T C ..O L L L L M M N N N P P P O M  .r./#.       ",
-"      ' 9 L L L L L L L L L L L L L L L L L ..H P L L L L L S i K at K@K at P@P at P@M at M@M at L@L at L@N at N@N at b#b#O at O@O at O@8 at 8@Q at Q@Q at V@T at Y@+#Z at 4#4#4#4#`@`@`@X at X@X at X@.#.#.#*#*#*#'#'#'#########9#9#f#f#f#f#C at C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.5#5#>#>#>#(#(#(#7#7#1#1#)#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#]#^#/#/#/#a+_#_#:#:#[#[#6#c#c#c#g#h#h#l#n#n#q#I I s#w#y#p.p.H+z#z#@$T##$e#]@A#A#B#C#w at 0+D#E#+$F#F#.$ $Y#G#H#v#I#I#q at J#t#r#r#G+i#$$$$B@`#`#Z#Z#K#K#L#L#p#p#p#X#X#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B at B@B@$$$$$$i#i#G+G+G+r#r#r#t#t#v#J at L L L L L L ..z x W T R S T U V V V U T T R N L L t '       ",
-"      ~ t at U N L L L L L L L L L L L L L L S w E L L L L L L q &#K at K@K at P@P at M@M at M@M at L@L at N@N at N@N at b#b#O at O@O at 8@8 at Q@V at T@K +#Z at Z@Z at 4#4#4#4#`@`@`@`@X at X@X at .#.#.#*#*#*#*#'#'#'#######9#9#9#f#f#f#C at C@C@}#}#}#=#=#-#-#-#-#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#^#^#/#/#/#a+_#_#:#:#[#[#6#c#c#g#g#h#h#l#n#n#q#I s#w#w#y#p.p.H+z#@$T#T##$e#]@A#B#C#C#0+0+D#E#+$F#.$ $Y#G#G#v#v#I#q at J#t#t#r#G+i#$$$$B@`#`#Z#K#K#L#L#p#p#p#X#X#M#M#M#M#{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B at B@B@$$$$$$i#i#G+G+G+r#r#r#t#t#]@r L L L L L r.&.[ 4 F ..Z Z Y X r.U R P N M L L L 3 &       ",
-"      # j t at t@@.U Q N M L L L L L L L L L r at 0 V L L L L L ..,#K at K@K at P@P at P@M at M@M at L@L at L@N at N@N at b#b#b#O at O@8@@#R at K +#+#+#Z at Z@Z at Z@4#4#4#4#`@`@`@X at X@X at X@.#.#.#*#*#*#*#'#'#########9#9#9#f#f#f#C at C@C@}#}#}#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#:#[#[#6#c#c#g#h#h#l#n#n#q#I I s#w#w#y#p.H+z#z#@$T##$e#e#A#A#B#C#w at 0+D#E#+$F#F# $ $Y#G#H#v#I#q at J#t#t#r#G+i#$$$$B@`#`#Z#K#K#L#L#p#p#X#X#M#M#M#M#{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B at B@B@$$$$$$i#i#G+G+G+r#r#t#t#t#>#W L L L L U H n A at s@+.V S P N M L L L L L L L L 4#J       ",
-"      J _#U @.Y V U T S Q P O M M L L L  .%#3 N L L L L N c K at K@K at K@P at P@P at M@M at M@L at L@L at N@N at N@b#b#O at Q@R at W@Y at +#+#+#+#Z at Z@Z at Z@4#4#4#4#`@`@`@`@X at X@X at .#.#.#*#*#*#*#'#'#'#########9#9#f#f#f#f#C at C@}#}#}#}#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#[#6#c#c#g#h#h#l#n#n#q#I I s#w#w#y#p.H+z#z#T#T##$e#]@A#A#C#C#w at 0+D#E#+$F#.$ $Y#G#H#v#v#q at q@J#t#r#G+G+i#$$B@`#`#Z#K#K#L#L#p#p#X#X#M#M#{@{@{@k#k#k#k#k#k#k#k#&$&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#L#L#L#L#K#K#K#Z#Z#Z#Z#`#`#`#B at B@B@$$$$i#i#i#G+G+G+r#r#t#t#G#k L L L L N x D at u P L L L L L L L L L L L L L Q J#        ",
-"        O#` P O M L L L L L M M M L L L ..G at t O L L L L t at I@K at K@K at P@P at P@M at M@M at M@L at L@N at N@N at b#8 at a#U at Y@Y at Y@+#+#+#+#Z at Z@Z at Z@4#4#4#4#4#`@`@`@X at X@X at X@.#.#.#*#*#*#*#'#'#'#######9#9#9#f#f#f#f#C at C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#|#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#l#n#n#q#I I s#w#y#p.p.H+z#@$T#T#e#e#]@A#B#C#w at 0+D#E#E#F#F# $ $Y#G#H#v#I#q at J#t#r#G+G+i#$$B@`#`#Z#K#K#L#p#p#X#X#M#M#M#{@{@k#k#k#k#k#&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B at B@B@$$$$$$i#i#i#G+G+G+r#r#t#t#s#C L L L N B S at H L L L L L L L L L L L L L L y ~         ",
-"        > z at N N L L L L L L L L L L L L M s at H T L L L U u at K@K at K@K at P@P at P@M at M@M at L@L at L@N at O@V at U@K Y at Y@Y at Y@+#+#+#+#+#Z at Z@Z at Z@4#4#4#4#`@`@`@`@X at X@X at .#.#.#.#*#*#*#'#'#'#########9#9#9#f#f#f#C at C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.q.5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#2#2#~#~#~#{#{#]#]#^#^#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#l#n#n#q#I s#w#w#y#p.p.z#z#@$T##$e#e#A#A#B#C#w at 0+D#E#+$F#.$ $Y#G#H#v#v#q at q@J#t#r#G+i#$$$$B@`#Z#K#K#L#p#p#X#X#M#M#{@{@k#k#k#k#&$&$&$&$N#N#N#N#N#N#N#N#N#N#N#N#N#&$&$&$&$&$&$&$k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#M#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@M#M#M#M#M#M#X#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#B at B@B@$$$$$$i#i#G+G+G+r#r#r#t#q at 4#S L L P &.n P L L L L L L L L L L L L L L 3#+         ",
-"        d#+#L M L L L L L L L L L L L L L ..t at W L L L l &#x at K@K at K@P at P@P at M@M at M@L at b#@#U at K K Y at Y@Y at Y@+#+#+#+#+#+#Z at Z@Z at 4#4#4#4#4#`@`@`@X at X@X at X@X at .#.#.#*#*#*#*#'#'#'#######9#9#9#9#f#f#f#C at C@C@}#}#}#=#=#=#-#-#-#;#;#q.q.q.5#5#5#>#>#>#(#(#7#7#7#1#1#)#)#)#!#!#|#|#2#2#~#~#~#{#]#]#]#^#^#/#/#a+_#_#:#:#[#[#6#c#c#g#g#h#l#l#n#q#I I s#w#y#p.p.H+z#@$T#T#e#e#A#A#B#C#w at 0+D#E#+$F#.$ $Y#G#H#v#I#q at J#t#r#G+i#$$$$`#`#Z#K#K#p#p#X#M#M#M#{@k#k#&$&$&$N#N#N#W#W#W#W#W#W#W#V#V#V#V#V#V#W#W#W#W#W#N#N#N#N#N#N#N#N#N#&$k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@M#M#M#M#M#M#M#X#X#X#X#p#p#p#p#p#L#L#L#K#K#K#K#Z#Z#Z#`#`#`#`#B at B@$$$$$$i#i#i#G+G+G+r#r#t#t#F#a L L T z A L L L L L L L L L L L L L L L l#          ",
-"          v#O L L L L L L L L L L L L L L U t at ..M L $.,#&#x at x@K at K@K at K@K at P@N at Q@T at Y@+#+#+#+#+#+#+#+#+#+#Z at Z@4#4#4#4#4#4#4#`@`@`@X at X@X at X@X at X@.#.#.#*#*#*#*#'#'#'#########9#9#9#f#f#f#f#C at C@C@}#}#}#=#=#=#-#-#-#;#;#;#q.q.q.5#5#>#>#>#(#(#(#7#7#7#1#1#)#)#!#!#|#|#|#2#2#~#~#~#{#]#]#]#^#/#/#a+a+_#_#:#[#[#6#6#c#g#g#h#l#n#n#q#I s#s#w#y#p.H+z#z#T#T#e#e#A#A#C#C#0+D#E#+$F#.$ $Y#G#v#v#q at J#t#r#G+i#$$B@`#Z#K#L#p#X#M#{@k#k#&$N#N#W#V#V#U#O#O#O#O#p at v@v at v@v at v@v at v@v at v@v at v@v at v@v at v@v at p@p at p@O#O#O#O#U#U#U#V#V#V#V#W#W#N#N#N#N#N#N#N#&$k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#k#{@{@{@{@{@{@M#M#M#M#M#M#M#M#M#M#X#X#X#p#p#p#p#p#p#p#L#K#K#K#K#K#K#Z#Z#`#`#`#`#`#B@$$$$$$$$$$i#G+G+G+G+r#t#t#t#t#t#/#..N r.s G L L L L L L L L L L L L L L @.R#          ",
-"          ( s at L L L L L L L L L L L L L L N *.C C +.2 J at J@J at J@J at S@S@&#M at U@Z at 4#4#4#4#4#4#4#4#4#4#4#4#4#4#4#`@`@`@X at X@X at X@X at X@X at X@.#.#.#.#.#.#*#*#*#*#*#'#'#'#############9#9#f#f#f#f#f#f#f#}#}#}#}#}#}#=#-#-#-#-#-#-#;#q.q.q.q.5#5#5#>#>#>#(#(#7#7#7#1#1#1#)#)#!#!#|#|#|#2#2#~#~#{#{#]#]#^#^#/#a+a+_#_#:#[#[#6#c#c#g#h#h#n#n#q#I s#w#y#p.p.H+z#T#T#e#e#A#A#C#w at 0+D#E#+$F# $Y#G#H#v#I#q at t#t#G+i#$$B@`#Z#K#L#p#p#X#M#{@k#k#&$N#N#W#V#V#U#U#U#O#O#O#O#p at p@p at p@p at p@p at p@p at O#O#O#O#O#O#O#O#U#U#U#V#V#V#V#V#W#W#W#N#N#N#N#N#N#N#N#N#N#&$&$&$&$N#&$&$&$&$&$N#N#N#N#N#N#N#N#N#N#N#N#N#W#W#W#W#W#W#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#V#W#W#W#W#W#W#N#N#N#N#N#N#&$&$&$k#k#k#k#{@{@{@M#M#M#M#X#p#p#p#p#L#L#K#K#K#K#Z#`#`#`#B at B@B@$$$$$$i#G+G+G+G+G+r#t#t#t#J#J#q at q@q at I#I#v#v#v#H#H#G#F#F at F @.r V L L L L L L L L L L L L L L 7 *           ",
-"          + ,#L L L L L L L L L L L L L L L &.a [ s@ #. at .@.@,#H at J@J at S@N@*#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#f#C at C@C at C@C at C@C@}#}#}#}#}#}#=#-#-#-#-#-#-#;#;#;#q.q.q.q.5#>#>#>#>#>#(#(#(#(#7#7#7#7#1#)#)#)#)#)#!#!#|#|#|#2#2#2#~#~#~#{#{#]#]#^#]#/#/#/#/#a+a+_#:#[#[#6#6#c#c#g#g#h#h#l#l#n#n#q#I I I w#w#w#y#p.p.H+z#z#@$T#T##$e#]@]@A#B#w at 0+0+D#E#+$F#F#.$ $Y#G#H#v#v#I#q at J#t#t#r#G+i#$$$$`#`#Z#K#L#p#M#{@k#k#&$N#N#W#V#U#U#O#O#v at v@%$y at P#Q#Q#_ _ S#x#x#u#/ / =.^ ^ -$] ] { ( m#m#*$=$~ ~ ~ ~ ! ! ) ) ) ) ) ' 8#8#, , ; ; ; - - > > > > = j#j#j#j#* * & & & & % % o#o#o#o#o#$ $ $ $ # # # # # # # # # # # # # # # $ $ o#o#o#o#% % & & & * * j#j#j#= > > > - ; ; ; ; ; , 8#8#8#' ) ! ~ *$m#( ( { ] -$^ =./ u#x#S#_ Q#P#R#y at y@%$v at p@O#O#U#V#W#W#N#&$&$k#{@M#M#X#X#p#A#i 8 p O L L L L L L L L L L L L L L 4#J           ",
-"            q#L L L L L L L L L L L L L L L T z +.s@%#u at u@u@ #E at .@I at M@8 at K 9#7#^#:#6#c#c#c#c#c#c#c#c#c#c#c#c#c#c#c#c#g#g#g#h#h#h#h#h#h#h#l#l#n#n#n#n#n#q#I I I I I s#w#w#w#w#y#p.p.p.p.H+H+z#z#z#@$T#T#T##$#$e#e#]@]@A#A#B#B#C#C#w at w@0+0+D#D#E#E#+$F#F#.$.$ $Y#Y#G#G#H#v#v#I#q at q@J#t#t#r#G+G+i#$$$$B@`#Z#Z#K#L#p#p#X#M#M#k#k#&$N#N#V#V#U#O#O#v at v@%$y at R#P#P#_ _ S#x#u#/ =.^ ^ ] ] ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9 at . . d#d#J J                                                                                                                                                                                                                                                               J J d#. + + # o#% & j#= > - ; 8#' ) ! ~ =$*$m#( { ] ] ^ ^ / N#u at u ..L L L L L L L L L L L L L L Q J#            ",
-"            %$+.L L L L L L L L L L L L L L L L L $.z at a } [ < < i i i j A at 3#0#P at U@##1#_#l#s#w#y#y#y#y#y#y#y#y#y#p.p.p.p.p.p.p.H+H+H+H+z#z#z#z#@$@$@$T#T#T##$#$#$e#e#e#]@]@A#A#A#B#B#C#C#C#w at 0+0+0+D#D#E#E#+$+$F#F#.$.$ $Y#Y#G#G#H#H#v#v#I#q at q@J#t#t#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#k#k#&$N#N#W#V#U#O#O#p at v@%$y at y@R#P#Q#_ _ x#x#u#/ =.^ -$] { ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9 at . . d#J J                                                                                                                                                                                                                                                                                                           J . 9 at + # $ o#& & j#= > - ; 8#8#) ) ~ ~ =$m#y at F#)#o L L L L L L L L L L L L L L L L y ~             ",
-"            & d L L L L L L L L L L L L L L L L L L L O W @.D A s n 4 3 2 c e | } g k <#&#R@=#]#h#H+T#e#e#e#e#e#e#e#]@]@]@]@]@A#A#A#A#B#B#B#B#C#B#B#C#C#C#C#w at w@0+0+0+D#D#E#E#E#+$+$F#F#.$.$ $ $Y#Y#G#G#H#H#v#v#I#q at q@J#J#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#{@{@k#&$N#N#W#V#U#O#O#p at v@v at y@y at R#P#Q#_ _ x#x#u#/ =.^ ^ ] ] ( ( m#*$=$~ ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9 at . d#J J                                                                                                                                                                                                                                                                                                                                 J . 9 at + @ # $ o#& & j#= > - 8#! =$*$m#( ] v at e#+#| G L L L L L L L L L L L L L L L L L 3#+             ",
-"            J -#L L L L L L L L L L L L L L L L L L L L L L L L L L L R V Z +.D z p 4 b } [ D at E@H at Q@.#|#I C#G#t#G+G+G+G+G+G+r#t#J#q at I#H#G# $F#D#w at C#C#C#C#w at w@0+0+0+0+D#E#E#E#E#+$F#F#F#.$ $ $ $Y#G#G#G#H#v#v#v#I#q at q@J#J#t#t#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#{@k#&$N#N#W#V#V#U#O#p at v@v@%$y at R#P#P#_ _ S#x#u#/ / =.^ -$] { ( m#*$=$~ ! ! ) ' 8#, ; - > = j#* & % o#$ # @ + 9 at . J J J                                                                                                                                                                                                                                                                                                                                 J . 9 at + # $ o#% & * j#> ; *$/ y at W#M#v#^#0#x R L L L L L L L L L L L L L L L L L L L l#              ",
-"              i#Q L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M U Z G C y z at 2 i 3#S at R@C at _#T# $G+Z#L#K#B at G+t#I#H# $F#D#C#A#]@]@A#A#A#A#B#B#C#C#C#C#w at w@0+0+D#D#D#E#E#+$+$F#F#.$.$ $ $Y#Y#G#G#H#H#v#v#I#q at q@J#t#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#X#X#M#{@{@k#&$N#N#W#V#U#O#O#p at v@%$y at y@R#P#Q#_ _ S#x#u#/ / ^ ^ ] ] { ( m#*$*$~ ~ ) ) 8#8#; ; - > = j#* & % o#$ # + + . d#J J                                                                                                                                                                                                                                                                                                                       J J . + @ # o#% & * j#> ; *$u#v at r#)#} @.L L L L L L L L L L L L L L L L L L L L L @.R#              ",
-"              ) t L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L N V ..%.r at v 7 [ G at T@-#_#H+w at +$F#+$0+C#]@T#T#T#T#T##$#$#$e#e#e#]@]@]@A#A#B#B#B#C#C#w at w@0+0+0+D#D#E#E#+$+$F#F#.$.$ $ $Y#G#G#H#H#v#v#I#q at q@J#J#t#r#r#G+G+i#$$$$B@`#`#Z#K#K#L#p#p#X#M#M#k#k#&$N#N#W#V#V#O#O#p at v@v at y@y at R#P#P#_ _ S#x#u#/ / ^ ^ -$] { ( m#*$=$~ ! ) ) ' 8#, ; - > = j#* & o#o## # + 9 at . d#J J                                                                                                                                                                                                                                                                                                         J . 9@@ # o#% & j#= > - 8#^ `#}#l T L L L L L L L L L L L L L L L L L L L L L L L 7 *               ",
-"              . P at L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L P V ` E x 7 i G at V@##5#q.=#=#=#=#-#-#-#-#-#-#;#q.q.q.q.q.5#5#5#>#>#>#>#(#7#7#7#7#1#1#)#)#)#)#!#|#1#7#1#1#)#)#)#!#|#|#|#2#2#~#~#~#{#]#]#]#^#^#/#/#a+_#_#_#:#:#_#/#/#a+a+_#_#:#[#[#6#6#c#c#g#h#h#h#[#6#6#c#c#g#h#h#l#n#n#q#I I I w#w#y#y#p.p.H+z#@$@$T##$e#e#]@A#A#B#C#C#A#e#e#]@A#A#B#C#w at 0+0+D#E#+$F#F#.$ $Y#G#H#v#I#q at q@t#t#G+G+i#i#$$$$$$B at B@`#`#`#Z#Z#K#$$$$$$$$$$B at B@`#`#`#Z#Z#K#K#K#K#L#L#p#p#p#p#X#X#M#M#M#{@{@k#k#k#M#K#K#K#L#L#L#p#p#p#p#p#p#p#`#i#i#i#i#i#i#i#i#G+G+G+G+G+G+G+r#r#r#t#t#t#t#J#J#q at q@q at I#I#v#v#v#H#H#G#G#Y#Y# $ $ $.$F#w at A#e##$T#z#H+p.y#w#I q#n#l#h#g#6#[#:#_#a+/#/#]#]#{#~#2#|#|#!#)#)#7#7#7#-#j H L L L L L L L L L L L L L L L L L L L L L L L L L L 4#J               ",
-"                z#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M N N N N O P P Q R R R S T V W X Z  ...+.#.G $.F %.E C C &.B *.H H r at s@s at -.t@A A A t at t@t at t@-.s at s@r at H *.B &.C D E %.F $.G @.+... .` Z Y X W r.U T R Q Q P O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L Q J#                ",
-"                _ %.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O P P Q R S T U r.W X Y Y ` ` .... at .@.G G F F E E D C &.B B *.H H H r at r@r at s@s at s@r at r@r at H H *.*.B &.C C E E %.F G G @. at .....` ` Y Y X r.V T S R Q P P O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L y ~                 ",
-"                o#} L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P Q R R T T V r.W X Y Z ` ` .... at .@.#.G $.F F %.E D C C C &.&.B B B B B B B B B &.&.C C D E E %.F $.G #. at .@.....` ` Y Y X W r.U T S R Q P O O N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 3#+                 ",
-"                J >#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R S T U V W X Y Y Z ` ` ....+. at .@.G G $.F F F %.E E E E D D D D D D E E E E %.%.F F $.G G @. at .+.....` ` Y Y X W r.V T S R Q P P O O N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L I                   ",
-"                  p#V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O P P Q R R S T V r.W X Y Y Y ` `  .....+. at .@.#.G G G $.F F F F F F F F F F F F $.G G G #. at .@.+..... .` ` Y Y X W r.V U T R R Q P P O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L +.R#                  ",
-"                  ; p L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N O O P P Q R R T T V r.W W X Y Y Z ` `  .......+. at .@. at .@.#.G G G G G G G G #. at .@. at .@.+....... .` ` Z Y Y X W r.V U T S R Q P P O O N N N M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 7 *                   ",
-"                  . 8 at L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N O O P P Q R R T T U V r.W X Y Y Y Z ` ` `  .............+.+. at .@.+.+............. .` ` ` Z Y Y X X W r.V U T S R Q P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L `@J                   ",
-"                    E#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N N O P P P Q R R S T U V r.W W X Y Y Y Y Y ` ` ` ` ` ` ` `  . .` ` ` ` ` ` ` ` Y Y Y Y X W W r.V V T T S R R Q P P O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L P G+                    ",
-"                    ] H L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M N N N N O P P P Q R R S T T U V r.r.W W X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y X X W W r.V V U T T R R Q P P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L y ~                     ",
-"                    # j L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N O O P P Q Q R R S T T U V V V r.W W W W W W X X X X X X W W W W W W r.V V U T T T R R R Q P P P O O N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L E at +                     ",
-"                    J _#L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N O O P P P P R R R R S T T T U U V V V V V V V V V V V V V U U T T T S S R R R Q P P P O O N N N N M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L I                       ",
-"                      O#Z L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M M M M M N N N N N N N N N O O O O O O O O O O O O O O N N N N N N N N M M M M M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L +.P#                      ",
-"                      j#a L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L h %                       ",
-"                      J {#O L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S R Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y X ..+.+.+.+.+.+.+.+.+.G F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F E C C C C C C C C C C C C C C C C C C C C C C C C C C C C C B s at s@s at s@s at s@s at s@s at s@s at s@s at s@s at s@s at s@s at -.z z z z z z z z z v t t t t t t t t t t t t t t t q 3 w#                        ",
-"                        ; &$t#q at q@q at q@q at q@q at q@q at B#Y at B#q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@q at q@G+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$M#&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$&$N#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#O#v at R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#R#S#x#x#x#x#x#x#x#x#x#=.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( =$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$=$~ ) ) ) ) ) ) ) ) ) 8#, , , , , , , , , , , , , , , - % .                         ",
-"                                            5#2#r U@[ R#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ",
-"                                            k s at p $#s A@)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ",
-"                                          X#i v A at -#X#A at c#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ",
-"                                          X#. at z G#    $#v R#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ",
-"                                          X#0#K       n#u at G#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      X#X#^#^#                                                                                                                                                  ",
-"                                          X#3#-#      G#i                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ) X#^#X#X#X#X#                                                                                                                                                  ",
-"                                          G#| G#      n#l                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               X#T#T#X#      X#X#                                                                                                                                                  ",
-"                        ) ) ) ) ) ) ) ) ) G#5 #$) ) ) c {#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#G#5#G#R#) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )                         ",
-"                        T#T#T#T#T#T#T#T#T#T#s $#T#T#u 9 T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#;$>$,$,$y#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#c#a#a#-#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
-"                                          ) d !#  n n )                                                                       T#)                                                                                                                                           '$)$              T#)     !$~$,$,${$                ]$,$>$^$/           !$/$,$,$($;$=           B at _$,$,$:$<$[$}$|$1$.                 !$/$,$,$($;$=             ) T#                %$/$,$,$:$2$3$4$5$%               = ,$6$                                                                                                          X#X#                    ) T#T#)                     X#X#                                                                                                  T#)                                             ",
-"                                            a#n $.b -#                                                                        T#)                                                                                                                                         7$8$9$              T#)       . ,$,$0$              ] a$,$b$                9@,$,$=.                9@,$a$+     c$d$,$^$9@                9@,$,$=.                ) T#                  . ,$a$+     e$,$f$              g$,$h$                                                                                                          X#X#                ) T#T#)                         ^#                                                                                                    T#)                                             ",
-"                        ) ) ) ) ) ) ) ) R#C at G A 5 G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ~ i$,$j$! ) ) ) ) ) ) c#R#) ) ) S#k$,$,$S#) ) ) ) ) ) l$m$,$u#) ) ) ) ) ) ) ) n$,$m$! ) ) ) ) ) ) ) ) n$,$o$) ) ) ) ) p$,$q$) ) ) ) ) ) ) ) n$,$m$! ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) ) Q#,$o$) ) ) ( ,$a$! ) ) ) ) ) ) r$,$s$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) G#c#R#) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
-"                        T#T#T#T#T#T#T#`@r T S G T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#t$u$,$,$l#T#T#T#T#T#T#a#c#T#T#T#v$0$j$,$w$T#T#T#T#T#x$2$8$y$T#T#T#T#T#T#T#T#T#f$,$z$T#T#T#T#T#T#T#T#T#A$,$B$T#T#T#T#T#d$,$C$T#T#T#T#T#T#T#T#f$,$z$T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#D$,$B$T#T#T#H+,$,$@$T#T#T#T#T#T#E$,$[#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#-#S at -#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S at T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
-"                                    `@8 Q W b '#X#                                                                            T#)                                                                                                                                     > F$+ 4$,$K#            T#)       G$]$d$,$H$        o#x$S#,$I$                  J$,$q$                  s$,$G$          @ ,$a$J               J$,$q$                  ) T#                  K$,$G#      -$,$o$            9 at k$a$L$            M$,$,$v$  . N$,$E$              J O$_$P$y$,$,$,$Q$+                                           X#X#      ) T#X#                                X#X#                                                                                                      T#)                                             ",
-"                                  T#5 l +.G#R#-#K )                                                                           T#)                                                                                                                                     h$R$  x$,$S$            T#)       T$U$V$,$<$        H$W$X$,$Y$                  Z$,$b$                  `$,$v@          d#,$,$9@              Z$,$b$                  ) T#                  d$,$%$       %,$J$            / ,$_$              d#a$,$K$    o#,$w$              .%8$!$  +%8$J#P#@%                                            X#X#    X#T#)                                   ^#                                                ) X#X#X#                                                T#)                                             ",
-"                        ) ) ) ) ) 5#6 ` #$) c#X at 5 $#g#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) #%l$) ) $%,$%%) ) ) ) ) ) c#R#) ) ) &%*%=%,$-%*$) ) v@{$) ;%,$U$) ) ) ) ) ) ) ) ) [$,$R$) ) ) ) ) ) ) ) ) >%,$/ ) ) ) ) ) u#,$,%) ) ) ) ) ) ) ) [$,$R$) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) ) '%,$=.) ) =%k$z$( ) ) ) ) ) ) Y$,$d$) ) ) ) ) ) ) x#,$,$)%) ) {@,$]$) ) ) ) ) ) !%,$f$) ) -$,$Q$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#5#c#G#I@#$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
-"                        T#T#T#T#T#. at F 9 c#P at 2 p y u at s $#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#z#~%5$T#T#D$,$a$z#T#T#T#T#T#a#c#T#T#@$a$H+@$a$,$6#T#T#3$s#T#{%,$]%T#T#T#T#T#T#T#T#H+8$8$z#T#T#T#T#T#T#T#T#s#,$^%T#T#T#T#T#T#:#,$>%T#T#T#T#T#T#T#H+8$8$z#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#z#8$y$T#H+!#k$4$5$T#T#T#T#T#T#T#/%,$(%T#T#T#T#T#T#T#:#,$,$y#T#T#7#,$A$T#T#T#T#T#T#Q$,$/#T#T#q#,$-%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#a#T#T#c#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
-"                                  -#..X@) | {#X#'#X#-#i                                                                       T#)                                                                                                                                 _%s$      = ,$,$7$          T#)     { 6$    ^$,$:%  <%G#  d#[%}%                  @%,$u$                  U#,$x$            G$,$$%              @%,$u$                    ) T#                ^ ,$}$^$P$|%{@d#                1%,$]               2%,$[$      .%,$3%            4$,$4%    g$,$5%                                                X#X#                                        ^#                                          X#^#X#  X#T#T#                                                    T#)                                             ",
-"                                  G#+.R#  I@{#) c#T#  n R#                                                                    T#)                                                                                                                               ) o$@         6%,$1$          T#)     #%Z$    7%,$8%# 5%.   m#,$x$                  U$,$d$                  9%,$0%            2$,$=.              U$,$d$              + 9$;$:$a%l$@             b%,$S$                        & ,$^%d#              0%,${$      B$}$              c%,$%     ;$a$S#                                                X#X#                                      X#X#                                      X#^#X#  X#^#X#)                                                       T#)                                             ",
-"                        ) ) ) ) ) ) v }#) |#x K M at c#R#8 R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ;$d%_$_$_$_$_$}$,${$) ) ) ) ) c#R#) ) ]%e%) ) U$,$E$'$K#) ) :%,$'$) ) ) ) ) ) ) ) ) .%,$q$) ) ) ) ) ) ) ) ) f%,$g%) ) ) ) ) %$8$|$) ) ) ) ) ) ) ) .%,$q$) ) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) ) ) ) 5$,$J$) ) ) ) ) ) ) ) ) ) ) ) `#,$/$) ) ) ) ) ) ) ) h%,$q$) ) { 8$P$) ) ) ) ) ) ) i%>%r#!  %a$G$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R#c#G#) R#c#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
-"                        T#T#T#T#T#T#9 } -#T#`@x l a#T#v !#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#A$j%T#T#T#T#T#T#(%,$m$T#T#T#T#T#a#c#T#T#[$]#T#T#w#,$,$&%T#T#T#k%,$A$T#T#T#T#T#T#T#T#T#0$,$D$T#T#T#T#T#T#T#T#T#>$,$l%T#T#T#T#T#3$a$l#T#T#T#T#T#T#T#T#0$,$D$T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#6%,${$T#T#T#T#T#T#T#T#T#T#T#T#m%,$F$T#T#T#T#T#T#T#T#>%,$a+T#T#:#,$k%T#T#T#T#T#T#T#T#c#~%Q$B$n%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S at T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#a#!#-#a#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
-"                                    G#i '#X#    ) S@) 2 )                                                                     T#)                                                                                                                           o#(%#             c$,$8$o#        T#)     E$!       6$^%,       o%,$!                 J }$,$3%                * ,$-%d#        G$8$K#                J }$,$3%                    ) T#                4$,$,                         `$,$<%                >$,$4%    p%,$q%              r%m$3%                                                          X#X#                                    ^#                                X#5#n#T#T#X#)                                                                   T#)                                             ",
-"                                      *#| X#    G#`@a#a#                                                                      T#)                                                                                                                           Z$x#              9@,$,$K#        T#)   3%,$9@      l%9%      + ^%,$9@                @%,$,$.                 #%,$4$.     3%s%>$<%                  @%,$,$.                     ) T#              t%,$,$.                       d#}$,$=                 ,%,$N#v at p%P$,$t%              E$,$N#=$; J                                                     X#X#                                  X#X#                          ) n#S at K T#X#) ) X#X#T#^#^#^#^#^#^#^#K ^#                                              T#)                                             ",
-"                        ) ) ) ) ) ) ) ) G#m b b A@$.S@) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) R$6$,$u%) ) ) ) ) ) `#o$,$,$^%J#) ) ) c#X#:$>%,$i$2%) ) ) ) ) ) v%'%,$,$j%F#) ) ) ) ) S#:$}$,$,$i$b$) ) ) ) ) &$w%^%,$,$E$x%u$N$$%/ ) ) ) ) ) ) ) ) S#:$}$,$,$i$b$) ) ) ) ) ) ) ) ) R#c#) ) ) ) ) x#:$m$,$,$N$F#) ) ) ) ) ) ) ) ) 9%o$,$,$y%s$) ) ) ) ) ) ) ]$^%>%z%{ '%,$z$u#) ) ) ) ) ) [$,$,$,$,$j$s$) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) G#G#) ) ) ) ) ) ) ) R#G#G#c#5#. at 3#*#5#5#5#5#c#G#G#R#) ) ) ) G#c#5#G#) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) c#R#) ) ) ) ) ) ) ) ) )                         ",
-"                        T#T#T#T#T#T#T#T#T#c#$#A at d 4 T#T#T#T#z#g#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#c#a#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#s#[$u$@$T#@$A$,$-%T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#-#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#S at a#S at S@S at S@S at S@a#-#-#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#-#S at -#c#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#a#c#T#T#T#T#T#T#T#T#T#T#                        ",
-"                                                ) P@)     X#J at A#                                                                                                                                                                                                                                                                                                                                                                                                                                                                              u%,$;       { ,$^$                                                                                              )                                               T#X#                                                                                                          ",
-"                                                  } n#X#h < N@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                4$,$U#    ~ N$B$3%                                                                                                                                          X#K )   ) X#X#X#X#X#X#X#X#                                                                                        ",
-"                                            u at n#&#8 A at i G at G#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  7$`$}$/$9$9$1$9@                                                                                                                                            X#K ^#^#T#X#X#X#X#X#X#-#X#X#X#X#X#X#X#X#X#X#X#X#                                                                  ",
-"                                          S at 5 `@-#c#|#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        X#G#^#X#X#X#X#X#X#X#X#X#X#X#T#)                                                               ",
-"                                      X#K k   )   c#P@)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ) T#^#X#X#                                                        ",
-"                                      n#U@`@      R#8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           X#X#T#                                                      ",
-"                                      X#N at v `@R#) 8 `@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              )                                                       ",
-"                                        n#I at x g G at 6 X#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ",
-"                                              6#s#                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ",
-"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "};
diff --git a/src/amidi-plug/amidi-plug.midiicon.xpm b/src/amidi-plug/amidi-plug.midiicon.xpm
index 24b28ec03da4..bff0e97139b3 100644
--- a/src/amidi-plug/amidi-plug.midiicon.xpm
+++ b/src/amidi-plug/amidi-plug.midiicon.xpm
@@ -1,5 +1,5 @@
 /* XPM */
-static char * amidiplug_xpm_midiicon[] = {
+static const char * amidiplug_xpm_midiicon[] = {
 "48 52 257 2",
 "  	c None",
 ". 	c #000000",
diff --git a/src/amidi-plug/backend-fluidsynth/Makefile b/src/amidi-plug/backend-fluidsynth/Makefile
deleted file mode 100644
index f2f4dafc41ea..000000000000
--- a/src/amidi-plug/backend-fluidsynth/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-PLUGIN = ap-fluidsynth${PLUGIN_SUFFIX}
-
-SRCS = b-fluidsynth.c
-
-include ../../../buildsys.mk
-include ../../../extra.mk
-
-plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}/${AMIDIPLUG_BACKEND_DIR}
-
-CFLAGS += ${PLUGIN_CFLAGS} ${FLUIDSYNTH_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${FLUIDSYNTH_CFLAGS} ${GLIB_CFLAGS} -I../../..
-LIBS += ${FLUIDSYNTH_LIBS} ${GLIB_LIBS}
diff --git a/src/amidi-plug/backend-fluidsynth/b-fluidsynth.c b/src/amidi-plug/backend-fluidsynth/b-fluidsynth.c
deleted file mode 100644
index 12d2115985ec..000000000000
--- a/src/amidi-plug/backend-fluidsynth/b-fluidsynth.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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
-*
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <fluidsynth.h>
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-
-#include "../i_backend.h"
-#include "../i_configure.h"
-#include "../i_midievent.h"
-
-/* #define DEBUGMSG(...) fprintf (stderr, __VA_ARGS__) */
-#define DEBUGMSG(...)
-
-typedef struct
-{
-    fluid_settings_t * settings;
-    fluid_synth_t * synth;
-
-    GArray * soundfont_ids;
-}
-sequencer_client_t;
-
-/* sequencer instance */
-static sequencer_client_t sc;
-/* options */
-
-static void i_soundfont_load (void);
-
-void backend_init (void)
-{
-    sc.soundfont_ids = g_array_new (FALSE, FALSE, sizeof (int));
-    sc.settings = new_fluid_settings();
-
-    fluid_settings_setnum (sc.settings, "synth.sample-rate",
-     aud_get_int ("amidiplug", "fsyn_synth_samplerate"));
-
-    int gain = aud_get_int ("amidiplug", "fsyn_synth_gain");
-    int polyphony = aud_get_int ("amidiplug", "fsyn_synth_polyphony");
-    int reverb = aud_get_int ("amidiplug", "fsyn_synth_reverb");
-    int chorus = aud_get_int ("amidiplug", "fsyn_synth_chorus");
-
-    if (gain != -1)
-        fluid_settings_setnum (sc.settings, "synth.gain", gain / 10.0);
-
-    if (polyphony != -1)
-        fluid_settings_setint (sc.settings, "synth.polyphony", polyphony);
-
-    if (reverb == 1)
-        fluid_settings_setstr (sc.settings, "synth.reverb.active", "yes");
-    else if (reverb == 0)
-        fluid_settings_setstr (sc.settings, "synth.reverb.active", "no");
-
-    if (chorus == 1)
-        fluid_settings_setstr (sc.settings, "synth.chorus.active", "yes");
-    else if (chorus == 0)
-        fluid_settings_setstr (sc.settings, "synth.chorus.active", "no");
-
-    sc.synth = new_fluid_synth (sc.settings);
-}
-
-
-void backend_cleanup (void)
-{
-    if (sc.soundfont_ids->len > 0)
-    {
-        /* unload soundfonts */
-        int i = 0;
-
-        for (i = 0 ; i < sc.soundfont_ids->len ; i++)
-            fluid_synth_sfunload (sc.synth, g_array_index (sc.soundfont_ids, int, i), 0);
-    }
-
-    g_array_free (sc.soundfont_ids, TRUE);
-    delete_fluid_synth (sc.synth);
-    delete_fluid_settings (sc.settings);
-}
-
-
-void backend_prepare (void)
-{
-    /* soundfont loader, check if we should load soundfont on first midifile play */
-    if (! sc.soundfont_ids->len)
-        i_soundfont_load();
-}
-
-void backend_reset (void)
-{
-    fluid_synth_system_reset (sc.synth);  /* all notes off and channels reset */
-}
-
-
-void seq_event_noteon (midievent_t * event)
-{
-    fluid_synth_noteon (sc.synth,
-                        event->data.d[0],
-                        event->data.d[1],
-                        event->data.d[2]);
-}
-
-
-void seq_event_noteoff (midievent_t * event)
-{
-    fluid_synth_noteoff (sc.synth,
-                         event->data.d[0],
-                         event->data.d[1]);
-}
-
-
-void seq_event_keypress (midievent_t * event)
-{
-    /* KEY PRESSURE events are not handled by FluidSynth sequencer? */
-    DEBUGMSG ("KEYPRESS EVENT with FluidSynth backend (unhandled)\n");
-}
-
-
-void seq_event_controller (midievent_t * event)
-{
-    fluid_synth_cc (sc.synth,
-                    event->data.d[0],
-                    event->data.d[1],
-                    event->data.d[2]);
-}
-
-
-void seq_event_pgmchange (midievent_t * event)
-{
-    fluid_synth_program_change (sc.synth,
-                                event->data.d[0],
-                                event->data.d[1]);
-}
-
-
-void seq_event_chanpress (midievent_t * event)
-{
-    /* CHANNEL PRESSURE events are not handled by FluidSynth sequencer? */
-    DEBUGMSG ("CHANPRESS EVENT with FluidSynth backend (unhandled)\n");
-}
-
-
-void seq_event_pitchbend (midievent_t * event)
-{
-    int pb_value = (( (event->data.d[2]) & 0x7f) << 7) | ((event->data.d[1]) & 0x7f);
-    fluid_synth_pitch_bend (sc.synth,
-                            event->data.d[0],
-                            pb_value);
-}
-
-
-void seq_event_sysex (midievent_t * event)
-{
-    DEBUGMSG ("SYSEX EVENT with FluidSynth backend (unhandled)\n");
-}
-
-
-void seq_event_tempo (midievent_t * event)
-{
-    /* unhandled */
-}
-
-
-void seq_event_other (midievent_t * event)
-{
-    /* unhandled */
-}
-
-
-void seq_event_allnoteoff (int unused)
-{
-    int c = 0;
-
-    for (c = 0 ; c < 16 ; c++)
-    {
-        fluid_synth_cc (sc.synth, c, 123 /* all notes off */, 0);
-    }
-}
-
-
-void backend_generate_audio (void * buf, int bufsize)
-{
-    fluid_synth_write_s16 (sc.synth, bufsize / 4, buf, 0, 2, buf, 1, 2);
-}
-
-
-void backend_audio_info (int * channels, int * bitdepth, int * samplerate)
-{
-    *channels = 2;
-    *bitdepth = 16; /* always 16 bit, we use fluid_synth_write_s16() */
-    *samplerate = aud_get_int ("amidiplug", "fsyn_synth_samplerate");
-}
-
-
-/* ******************************************************************
-   *** INTERNALS ****************************************************
-   ****************************************************************** */
-
-static void i_soundfont_load (void)
-{
-    char * soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file");
-
-    if (soundfont_file[0])
-    {
-        char ** sffiles = g_strsplit (soundfont_file, ";", 0);
-        int i = 0;
-
-        while (sffiles[i] != NULL)
-        {
-            int sf_id = 0;
-            DEBUGMSG ("loading soundfont %s\n", sffiles[i]);
-            sf_id = fluid_synth_sfload (sc.synth, sffiles[i], 0);
-
-            if (sf_id == -1)
-            {
-                g_warning ("unable to load SoundFont file %s\n", sffiles[i]);
-            }
-            else
-            {
-                DEBUGMSG ("soundfont %s successfully loaded\n", sffiles[i]);
-                g_array_append_val (sc.soundfont_ids, sf_id);
-            }
-
-            i++;
-        }
-
-        g_strfreev (sffiles);
-
-        fluid_synth_system_reset (sc.synth);
-    }
-    else
-    {
-        g_warning ("FluidSynth backend was selected, but no SoundFont has been specified\n");
-    }
-
-    str_unref (soundfont_file);
-}
diff --git a/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc b/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc
new file mode 100644
index 000000000000..098b13e05930
--- /dev/null
+++ b/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc
@@ -0,0 +1,233 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
+*
+* 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
+*
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <fluidsynth.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/index.h>
+#include <libaudcore/runtime.h>
+
+#include "../i_backend.h"
+#include "../i_configure.h"
+#include "../i_midievent.h"
+
+typedef struct
+{
+    fluid_settings_t * settings;
+    fluid_synth_t * synth;
+
+    Index<int> soundfont_ids;
+}
+sequencer_client_t;
+
+/* sequencer instance */
+static sequencer_client_t sc;
+/* options */
+
+static void i_soundfont_load (void);
+
+void backend_init (void)
+{
+    sc.settings = new_fluid_settings();
+
+    fluid_settings_setnum (sc.settings, "synth.sample-rate",
+     aud_get_int ("amidiplug", "fsyn_synth_samplerate"));
+
+    int gain = aud_get_int ("amidiplug", "fsyn_synth_gain");
+    int polyphony = aud_get_int ("amidiplug", "fsyn_synth_polyphony");
+    int reverb = aud_get_int ("amidiplug", "fsyn_synth_reverb");
+    int chorus = aud_get_int ("amidiplug", "fsyn_synth_chorus");
+
+    if (gain != -1)
+        fluid_settings_setnum (sc.settings, "synth.gain", gain / 10.0);
+
+    if (polyphony != -1)
+        fluid_settings_setint (sc.settings, "synth.polyphony", polyphony);
+
+    if (reverb == 1)
+        fluid_settings_setstr (sc.settings, "synth.reverb.active", "yes");
+    else if (reverb == 0)
+        fluid_settings_setstr (sc.settings, "synth.reverb.active", "no");
+
+    if (chorus == 1)
+        fluid_settings_setstr (sc.settings, "synth.chorus.active", "yes");
+    else if (chorus == 0)
+        fluid_settings_setstr (sc.settings, "synth.chorus.active", "no");
+
+    sc.synth = new_fluid_synth (sc.settings);
+
+    /* load soundfonts */
+    i_soundfont_load();
+}
+
+
+void backend_cleanup (void)
+{
+    /* unload soundfonts */
+    for (int id : sc.soundfont_ids)
+        fluid_synth_sfunload (sc.synth, id, 0);
+
+    sc.soundfont_ids.clear ();
+    delete_fluid_synth (sc.synth);
+    delete_fluid_settings (sc.settings);
+}
+
+
+void backend_reset (void)
+{
+    fluid_synth_system_reset (sc.synth);  /* all notes off and channels reset */
+}
+
+
+void seq_event_noteon (midievent_t * event)
+{
+    fluid_synth_noteon (sc.synth,
+                        event->d[0],
+                        event->d[1],
+                        event->d[2]);
+}
+
+
+void seq_event_noteoff (midievent_t * event)
+{
+    fluid_synth_noteoff (sc.synth,
+                         event->d[0],
+                         event->d[1]);
+}
+
+
+void seq_event_keypress (midievent_t * event)
+{
+    /* KEY PRESSURE events are not handled by FluidSynth sequencer? */
+    AUDDBG ("KEYPRESS EVENT with FluidSynth backend (unhandled)\n");
+}
+
+
+void seq_event_controller (midievent_t * event)
+{
+    fluid_synth_cc (sc.synth,
+                    event->d[0],
+                    event->d[1],
+                    event->d[2]);
+}
+
+
+void seq_event_pgmchange (midievent_t * event)
+{
+    fluid_synth_program_change (sc.synth,
+                                event->d[0],
+                                event->d[1]);
+}
+
+
+void seq_event_chanpress (midievent_t * event)
+{
+    /* CHANNEL PRESSURE events are not handled by FluidSynth sequencer? */
+    AUDDBG ("CHANPRESS EVENT with FluidSynth backend (unhandled)\n");
+}
+
+
+void seq_event_pitchbend (midievent_t * event)
+{
+    int pb_value = (( (event->d[2]) & 0x7f) << 7) | ((event->d[1]) & 0x7f);
+    fluid_synth_pitch_bend (sc.synth,
+                            event->d[0],
+                            pb_value);
+}
+
+
+void seq_event_sysex (midievent_t * event)
+{
+    AUDDBG ("SYSEX EVENT with FluidSynth backend (unhandled)\n");
+}
+
+
+void seq_event_tempo (midievent_t * event)
+{
+    /* unhandled */
+}
+
+
+void seq_event_other (midievent_t * event)
+{
+    /* unhandled */
+}
+
+
+void seq_event_allnoteoff (int unused)
+{
+    int c = 0;
+
+    for (c = 0 ; c < 16 ; c++)
+    {
+        fluid_synth_cc (sc.synth, c, 123 /* all notes off */, 0);
+    }
+}
+
+
+void backend_generate_audio (void * buf, int bufsize)
+{
+    fluid_synth_write_s16 (sc.synth, bufsize / 4, buf, 0, 2, buf, 1, 2);
+}
+
+
+void backend_audio_info (int * channels, int * bitdepth, int * samplerate)
+{
+    *channels = 2;
+    *bitdepth = 16; /* always 16 bit, we use fluid_synth_write_s16() */
+    *samplerate = aud_get_int ("amidiplug", "fsyn_synth_samplerate");
+}
+
+
+/* ******************************************************************
+   *** INTERNALS ****************************************************
+   ****************************************************************** */
+
+static void i_soundfont_load (void)
+{
+    String soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file");
+
+    if (soundfont_file[0])
+    {
+        Index<String> sffiles = str_list_to_index (soundfont_file, ";");
+
+        for (const char * sffile : sffiles)
+        {
+            AUDDBG ("loading soundfont %s\n", sffile);
+            int sf_id = fluid_synth_sfload (sc.synth, sffile, 0);
+
+            if (sf_id == -1)
+                AUDWARN ("unable to load SoundFont file %s\n", sffile);
+            else
+            {
+                AUDDBG ("soundfont %s successfully loaded\n", sffile);
+                sc.soundfont_ids.append (sf_id);
+            }
+        }
+
+        fluid_synth_system_reset (sc.synth);
+    }
+    else
+        AUDWARN ("FluidSynth backend was selected, but no SoundFont has been specified\n");
+}
diff --git a/src/amidi-plug/i_backend.h b/src/amidi-plug/i_backend.h
index cabc315adb4c..54aecfbd05de 100644
--- a/src/amidi-plug/i_backend.h
+++ b/src/amidi-plug/i_backend.h
@@ -21,26 +21,25 @@
 #ifndef _I_BACKEND_H
 #define _I_BACKEND_H 1
 
-struct midievent_s;
+struct midievent_t;
 
 void backend_init (void);
 void backend_cleanup (void);
-void backend_prepare (void);
 void backend_reset (void);
 
 void backend_audio_info (int *, int *, int *);
 void backend_generate_audio (void * buf, int bufsize);
 
-void seq_event_noteon (struct midievent_s *);
-void seq_event_noteoff (struct midievent_s *);
+void seq_event_noteon (midievent_t *);
+void seq_event_noteoff (midievent_t *);
 void seq_event_allnoteoff (int);
-void seq_event_keypress (struct midievent_s *);
-void seq_event_controller (struct midievent_s *);
-void seq_event_pgmchange (struct midievent_s *);
-void seq_event_chanpress (struct midievent_s *);
-void seq_event_pitchbend (struct midievent_s *);
-void seq_event_sysex (struct midievent_s *);
-void seq_event_tempo (struct midievent_s *);
-void seq_event_other (struct midievent_s *);
+void seq_event_keypress (midievent_t *);
+void seq_event_controller (midievent_t *);
+void seq_event_pgmchange (midievent_t *);
+void seq_event_chanpress (midievent_t *);
+void seq_event_pitchbend (midievent_t *);
+void seq_event_sysex (midievent_t *);
+void seq_event_tempo (midievent_t *);
+void seq_event_other (midievent_t *);
 
 #endif /* !_I_BACKEND_H */
diff --git a/src/amidi-plug/i_configure-fluidsynth.c b/src/amidi-plug/i_configure-fluidsynth.c
deleted file mode 100644
index d4cfe5d93350..000000000000
--- a/src/amidi-plug/i_configure-fluidsynth.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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
-*
-*/
-
-#include "i_configure-fluidsynth.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-
-#include "i_configure.h"
-
-enum
-{
-    LISTSFONT_FILENAME_COLUMN = 0,
-    LISTSFONT_FILESIZE_COLUMN,
-    LISTSFONT_N_COLUMNS
-};
-
-static void i_configure_ev_sflist_commit (void * sfont_lv);
-
-void i_configure_ev_sflist_add (void * sfont_lv)
-{
-    GtkWidget * parent_window = gtk_widget_get_toplevel (sfont_lv);
-
-    if (gtk_widget_is_toplevel (parent_window))
-    {
-        GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
-        GtkTreeIter itersel, iterapp;
-        GtkWidget * browse_dialog = gtk_file_chooser_dialog_new (_("AMIDI-Plug - select SoundFont file"),
-                                    GTK_WINDOW (parent_window),
-                                    GTK_FILE_CHOOSER_ACTION_OPEN,
-                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
-                                    _("_Open"), GTK_RESPONSE_ACCEPT, NULL);
-
-        if (gtk_tree_selection_get_selected (listsel, NULL, &itersel))
-        {
-            char * selfilename = NULL, *selfiledir = NULL;
-            GtkTreeModel * store = gtk_tree_view_get_model (GTK_TREE_VIEW (sfont_lv));
-            gtk_tree_model_get (GTK_TREE_MODEL (store), &itersel, LISTSFONT_FILENAME_COLUMN, &selfilename, -1);
-            selfiledir = g_path_get_dirname (selfilename);
-            gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (browse_dialog), selfiledir);
-            g_free (selfiledir);
-            g_free (selfilename);
-        }
-
-        if (gtk_dialog_run (GTK_DIALOG (browse_dialog)) == GTK_RESPONSE_ACCEPT)
-        {
-            GStatBuf finfo;
-            GtkTreeModel * store = gtk_tree_view_get_model (GTK_TREE_VIEW (sfont_lv));
-            char * filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (browse_dialog));
-            int filesize = -1;
-
-            if (g_stat (filename, &finfo) == 0)
-                filesize = finfo.st_size;
-
-            gtk_list_store_append (GTK_LIST_STORE (store), &iterapp);
-            gtk_list_store_set (GTK_LIST_STORE (store), &iterapp,
-                                LISTSFONT_FILENAME_COLUMN, filename,
-                                LISTSFONT_FILESIZE_COLUMN, filesize, -1);
-
-            g_free (filename);
-        }
-
-        gtk_widget_destroy (browse_dialog);
-    }
-
-    i_configure_ev_sflist_commit (sfont_lv);
-}
-
-
-void i_configure_ev_sflist_rem (void * sfont_lv)
-{
-    GtkTreeModel * store;
-    GtkTreeIter iter;
-    GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
-
-    if (gtk_tree_selection_get_selected (listsel, &store, &iter))
-        gtk_list_store_remove (GTK_LIST_STORE (store), &iter);
-
-    i_configure_ev_sflist_commit (sfont_lv);
-}
-
-
-void i_configure_ev_sflist_swap (GtkWidget * button, void * sfont_lv)
-{
-    GtkTreeModel * store;
-    GtkTreeIter iter;
-    GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
-
-    if (gtk_tree_selection_get_selected (listsel, &store, &iter))
-    {
-        unsigned swapdire = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "swapdire"));
-
-        if (swapdire == 0)   /* move up */
-        {
-            GtkTreePath * treepath = gtk_tree_model_get_path (store, &iter);
-
-            if (gtk_tree_path_prev (treepath))
-            {
-                GtkTreeIter iter_prev;
-
-                if (gtk_tree_model_get_iter (store, &iter_prev, treepath))
-                    gtk_list_store_swap (GTK_LIST_STORE (store), &iter, &iter_prev);
-            }
-
-            gtk_tree_path_free (treepath);
-        }
-        else /* move down */
-        {
-            GtkTreeIter iter_prev = iter;
-
-            if (gtk_tree_model_iter_next (store, &iter))
-                gtk_list_store_swap (GTK_LIST_STORE (store), &iter, &iter_prev);
-        }
-    }
-
-    i_configure_ev_sflist_commit (sfont_lv);
-}
-
-
-void i_configure_ev_sflist_commit (void * sfont_lv)
-{
-    GtkTreeIter iter;
-    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)
-    {
-        bool_t iter_is_valid = FALSE;
-
-        do
-        {
-            char * fname;
-            gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
-                                LISTSFONT_FILENAME_COLUMN, &fname, -1);
-            g_string_prepend_c (sflist_string, ';');
-            g_string_prepend (sflist_string, fname);
-            g_free (fname);
-            iter_is_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
-        }
-        while (iter_is_valid == TRUE);
-    }
-
-    if (sflist_string->len > 0)
-        g_string_truncate (sflist_string, sflist_string->len - 1);
-
-    aud_set_str ("amidiplug", "fsyn_soundfont_file", sflist_string->str);
-
-    g_string_free (sflist_string, TRUE);
-
-    /* reset backend at beginning of next song to apply changes */
-    g_atomic_int_set (& backend_settings_changed, TRUE);
-}
-
-
-void * create_soundfont_list (void)
-{
-        GtkListStore * soundfont_file_store;
-        GtkCellRenderer * soundfont_file_lv_text_rndr;
-        GtkTreeViewColumn * soundfont_file_lv_fname_col, *soundfont_file_lv_fsize_col;
-        GtkWidget * soundfont_file_hbox, *soundfont_file_lv, *soundfont_file_lv_sw;
-        GtkTreeSelection * soundfont_file_lv_sel;
-        GtkWidget * soundfont_file_bbox_vbox, *soundfont_file_bbox_addbt, *soundfont_file_bbox_rembt;
-        GtkWidget * soundfont_file_bbox_mvupbt, *soundfont_file_bbox_mvdownbt;
-
-        /* soundfont settings - soundfont files - listview */
-        soundfont_file_store = gtk_list_store_new (LISTSFONT_N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
-
-        char * soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file");
-
-        if (soundfont_file[0])
-        {
-            /* fill soundfont list with fsyn_soundfont_file information */
-            char ** sffiles = g_strsplit (soundfont_file, ";", 0);
-            GtkTreeIter iter;
-            int i = 0;
-
-            while (sffiles[i] != NULL)
-            {
-                int filesize = -1;
-                GStatBuf finfo;
-
-                if (g_stat (sffiles[i], &finfo) == 0)
-                    filesize = finfo.st_size;
-
-                gtk_list_store_prepend (GTK_LIST_STORE (soundfont_file_store), &iter);
-                gtk_list_store_set (GTK_LIST_STORE (soundfont_file_store), &iter,
-                                    LISTSFONT_FILENAME_COLUMN, sffiles[i],
-                                    LISTSFONT_FILESIZE_COLUMN, filesize, -1);
-                i++;
-            }
-
-            g_strfreev (sffiles);
-        }
-
-        str_unref (soundfont_file);
-
-        soundfont_file_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 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);
-        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 (
-                                          _("Filename"), soundfont_file_lv_text_rndr, "text",
-                                          LISTSFONT_FILENAME_COLUMN, NULL);
-        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, NULL);
-        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));
-        gtk_tree_selection_set_mode (GTK_TREE_SELECTION (soundfont_file_lv_sel), GTK_SELECTION_SINGLE);
-
-        soundfont_file_lv_sw = gtk_scrolled_window_new (NULL, NULL);
-        gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) soundfont_file_lv_sw, GTK_SHADOW_IN);
-        gtk_scrolled_window_set_policy ((GtkScrolledWindow *) soundfont_file_lv_sw,
-                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-        gtk_container_add (GTK_CONTAINER (soundfont_file_lv_sw), soundfont_file_lv);
-
-        /* soundfont settings - soundfont files - buttonbox */
-        soundfont_file_bbox_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 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);
-        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);
-        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);
-        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);
-
-        return soundfont_file_hbox;
-}
diff --git a/src/amidi-plug/i_configure-fluidsynth.cc b/src/amidi-plug/i_configure-fluidsynth.cc
new file mode 100644
index 000000000000..75067015a9bf
--- /dev/null
+++ b/src/amidi-plug/i_configure-fluidsynth.cc
@@ -0,0 +1,275 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
+*
+* 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
+*
+*/
+
+#include "i_configure-fluidsynth.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+
+#include "i_configure.h"
+
+enum
+{
+    LISTSFONT_FILENAME_COLUMN = 0,
+    LISTSFONT_FILESIZE_COLUMN,
+    LISTSFONT_N_COLUMNS
+};
+
+static void i_configure_ev_sflist_commit (void * sfont_lv);
+
+void i_configure_ev_sflist_add (void * sfont_lv)
+{
+    GtkWidget * parent_window = gtk_widget_get_toplevel ((GtkWidget *) sfont_lv);
+
+    if (gtk_widget_is_toplevel (parent_window))
+    {
+        GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
+        GtkTreeIter itersel, iterapp;
+        GtkWidget * browse_dialog = gtk_file_chooser_dialog_new (_("AMIDI-Plug - select SoundFont file"),
+                                    GTK_WINDOW (parent_window),
+                                    GTK_FILE_CHOOSER_ACTION_OPEN,
+                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                    _("_Open"), GTK_RESPONSE_ACCEPT, nullptr);
+
+        if (gtk_tree_selection_get_selected (listsel, nullptr, &itersel))
+        {
+            char * selfilename = nullptr, *selfiledir = nullptr;
+            GtkTreeModel * store = gtk_tree_view_get_model (GTK_TREE_VIEW (sfont_lv));
+            gtk_tree_model_get (GTK_TREE_MODEL (store), &itersel, LISTSFONT_FILENAME_COLUMN, &selfilename, -1);
+            selfiledir = g_path_get_dirname (selfilename);
+            gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (browse_dialog), selfiledir);
+            g_free (selfiledir);
+            g_free (selfilename);
+        }
+
+        if (gtk_dialog_run (GTK_DIALOG (browse_dialog)) == GTK_RESPONSE_ACCEPT)
+        {
+            GStatBuf finfo;
+            GtkTreeModel * store = gtk_tree_view_get_model (GTK_TREE_VIEW (sfont_lv));
+            char * filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (browse_dialog));
+            int filesize = -1;
+
+            if (g_stat (filename, &finfo) == 0)
+                filesize = finfo.st_size;
+
+            gtk_list_store_append (GTK_LIST_STORE (store), &iterapp);
+            gtk_list_store_set (GTK_LIST_STORE (store), &iterapp,
+                                LISTSFONT_FILENAME_COLUMN, filename,
+                                LISTSFONT_FILESIZE_COLUMN, filesize, -1);
+
+            g_free (filename);
+        }
+
+        gtk_widget_destroy (browse_dialog);
+    }
+
+    i_configure_ev_sflist_commit (sfont_lv);
+}
+
+
+void i_configure_ev_sflist_rem (void * sfont_lv)
+{
+    GtkTreeModel * store;
+    GtkTreeIter iter;
+    GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
+
+    if (gtk_tree_selection_get_selected (listsel, &store, &iter))
+        gtk_list_store_remove (GTK_LIST_STORE (store), &iter);
+
+    i_configure_ev_sflist_commit (sfont_lv);
+}
+
+
+void i_configure_ev_sflist_swap (GtkWidget * button, void * sfont_lv)
+{
+    GtkTreeModel * store;
+    GtkTreeIter iter;
+    GtkTreeSelection * listsel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sfont_lv));
+
+    if (gtk_tree_selection_get_selected (listsel, &store, &iter))
+    {
+        unsigned swapdire = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "swapdire"));
+
+        if (swapdire == 0)   /* move up */
+        {
+            GtkTreePath * treepath = gtk_tree_model_get_path (store, &iter);
+
+            if (gtk_tree_path_prev (treepath))
+            {
+                GtkTreeIter iter_prev;
+
+                if (gtk_tree_model_get_iter (store, &iter_prev, treepath))
+                    gtk_list_store_swap (GTK_LIST_STORE (store), &iter, &iter_prev);
+            }
+
+            gtk_tree_path_free (treepath);
+        }
+        else /* move down */
+        {
+            GtkTreeIter iter_prev = iter;
+
+            if (gtk_tree_model_iter_next (store, &iter))
+                gtk_list_store_swap (GTK_LIST_STORE (store), &iter, &iter_prev);
+        }
+    }
+
+    i_configure_ev_sflist_commit (sfont_lv);
+}
+
+
+void i_configure_ev_sflist_commit (void * sfont_lv)
+{
+    GtkTreeIter iter;
+    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)
+    {
+        gboolean iter_is_valid = FALSE;
+
+        do
+        {
+            char * fname;
+            gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+                                LISTSFONT_FILENAME_COLUMN, &fname, -1);
+            g_string_prepend_c (sflist_string, ';');
+            g_string_prepend (sflist_string, fname);
+            g_free (fname);
+            iter_is_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+        }
+        while (iter_is_valid == TRUE);
+    }
+
+    if (sflist_string->len > 0)
+        g_string_truncate (sflist_string, sflist_string->len - 1);
+
+    aud_set_str ("amidiplug", "fsyn_soundfont_file", sflist_string->str);
+
+    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)
+{
+        GtkListStore * soundfont_file_store;
+        GtkCellRenderer * soundfont_file_lv_text_rndr;
+        GtkTreeViewColumn * soundfont_file_lv_fname_col, *soundfont_file_lv_fsize_col;
+        GtkWidget * soundfont_file_hbox, *soundfont_file_lv, *soundfont_file_lv_sw;
+        GtkTreeSelection * soundfont_file_lv_sel;
+        GtkWidget * soundfont_file_bbox_vbox, *soundfont_file_bbox_addbt, *soundfont_file_bbox_rembt;
+        GtkWidget * soundfont_file_bbox_mvupbt, *soundfont_file_bbox_mvdownbt;
+
+        /* soundfont settings - soundfont files - listview */
+        soundfont_file_store = gtk_list_store_new (LISTSFONT_N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
+
+        String soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file");
+
+        if (soundfont_file[0])
+        {
+            /* fill soundfont list with fsyn_soundfont_file information */
+            char ** sffiles = g_strsplit (soundfont_file, ";", 0);
+            GtkTreeIter iter;
+            int i = 0;
+
+            while (sffiles[i] != nullptr)
+            {
+                int filesize = -1;
+                GStatBuf finfo;
+
+                if (g_stat (sffiles[i], &finfo) == 0)
+                    filesize = finfo.st_size;
+
+                gtk_list_store_prepend (GTK_LIST_STORE (soundfont_file_store), &iter);
+                gtk_list_store_set (GTK_LIST_STORE (soundfont_file_store), &iter,
+                                    LISTSFONT_FILENAME_COLUMN, sffiles[i],
+                                    LISTSFONT_FILESIZE_COLUMN, filesize, -1);
+                i++;
+            }
+
+            g_strfreev (sffiles);
+        }
+
+        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);
+        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);
+        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_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));
+        gtk_tree_selection_set_mode (GTK_TREE_SELECTION (soundfont_file_lv_sel), GTK_SELECTION_SINGLE);
+
+        soundfont_file_lv_sw = gtk_scrolled_window_new (nullptr, nullptr);
+        gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) soundfont_file_lv_sw, GTK_SHADOW_IN);
+        gtk_scrolled_window_set_policy ((GtkScrolledWindow *) soundfont_file_lv_sw,
+                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+        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_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);
+        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);
+        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);
+        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);
+
+        return soundfont_file_hbox;
+}
diff --git a/src/amidi-plug/i_configure.c b/src/amidi-plug/i_configure.c
deleted file mode 100644
index a11f426dc9b6..000000000000
--- a/src/amidi-plug/i_configure.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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
-*
-*/
-
-#include "i_configure.h"
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/preferences.h>
-
-#include "i_configure-fluidsynth.h"
-
-int backend_settings_changed = FALSE;  /* atomic */
-
-static bool_t override_gain = FALSE;
-static float gain_setting = 0.2;
-static bool_t override_polyphony = FALSE;
-static int polyphony_setting = 256;
-static bool_t override_reverb = FALSE;
-static bool_t reverb_setting = TRUE;
-static bool_t override_chorus = FALSE;
-static bool_t chorus_setting = TRUE;
-
-static void get_values (void)
-{
-    int gain = aud_get_int ("amidiplug", "fsyn_synth_gain");
-    int polyphony = aud_get_int ("amidiplug", "fsyn_synth_polyphony");
-    int reverb = aud_get_int ("amidiplug", "fsyn_synth_reverb");
-    int chorus = aud_get_int ("amidiplug", "fsyn_synth_chorus");
-
-    if (gain != -1)
-    {
-        override_gain = TRUE;
-        gain_setting = gain / 10.0;
-    }
-
-    if (polyphony != -1)
-    {
-        override_polyphony = TRUE;
-        polyphony_setting = polyphony;
-    }
-
-    if (reverb != -1)
-    {
-        override_reverb = TRUE;
-        reverb_setting = reverb;
-    }
-
-    if (chorus != -1)
-    {
-        override_chorus = TRUE;
-        chorus_setting = chorus;
-    }
-}
-
-static void set_values (void)
-{
-    int gain = override_gain ? (int) (gain_setting * 10 + 0.5) : -1;
-    int polyphony = override_polyphony ? polyphony_setting : -1;
-    int reverb = override_reverb ? reverb_setting : -1;
-    int chorus = override_chorus ? chorus_setting : -1;
-
-    aud_set_int ("amidiplug", "fsyn_synth_gain", gain);
-    aud_set_int ("amidiplug", "fsyn_synth_polyphony", polyphony);
-    aud_set_int ("amidiplug", "fsyn_synth_reverb", reverb);
-    aud_set_int ("amidiplug", "fsyn_synth_chorus", chorus);
-}
-
-static void backend_change (void)
-{
-    set_values ();
-
-    /* reset backend at beginning of next song to apply changes */
-    g_atomic_int_set (& backend_settings_changed, TRUE);
-}
-
-static const PreferencesWidget gain_widgets[] = {
- {WIDGET_CHK_BTN, N_("Override default gain:"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & override_gain, .callback = backend_change},
- {WIDGET_SPIN_BTN, .child = TRUE, .data = {.spin_btn = {0, 10, 0.1}},
-  .cfg_type = VALUE_FLOAT, .cfg = & gain_setting, .callback = backend_change}};
-
-static const PreferencesWidget polyphony_widgets[] = {
- {WIDGET_CHK_BTN, N_("Override default polyphony:"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & override_polyphony, .callback = backend_change},
- {WIDGET_SPIN_BTN, .child = TRUE, .data = {.spin_btn = {16, 4096, 1}},
-  .cfg_type = VALUE_INT, .cfg = & polyphony_setting, .callback = backend_change}};
-
-static const PreferencesWidget reverb_widgets[] = {
- {WIDGET_CHK_BTN, N_("Override default reverb:"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & override_reverb, .callback = backend_change},
- {WIDGET_CHK_BTN, N_("On"), .child = TRUE,
-  .cfg_type = VALUE_BOOLEAN, .cfg = & reverb_setting, .callback = backend_change}};
-
-static const PreferencesWidget chorus_widgets[] = {
- {WIDGET_CHK_BTN, N_("Override default chorus:"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & override_chorus, .callback = backend_change},
- {WIDGET_CHK_BTN, N_("On"), .child = TRUE,
-  .cfg_type = VALUE_BOOLEAN, .cfg = & chorus_setting, .callback = backend_change}};
-
-static const PreferencesWidget amidiplug_widgets[] = {
-
- /* global settings */
- {WIDGET_LABEL, N_("<b>Playback</b>")},
- {WIDGET_SPIN_BTN, N_("Transpose:"), .data = {.spin_btn = {-20, 20, 1}},
-  .cfg_type = VALUE_INT, .csect = "amidiplug", .cname = "ap_opts_transpose_value"},
- {WIDGET_SPIN_BTN, N_("Drum shift:"), .data = {.spin_btn = {0, 127, 1}},
-  .cfg_type = VALUE_INT, .csect = "amidiplug", .cname = "ap_opts_drumshift_value"},
- {WIDGET_LABEL, N_("<b>Advanced</b>")},
- {WIDGET_CHK_BTN, N_("Extract comments from MIDI file"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "amidiplug", .cname = "ap_opts_comments_extract"},
- {WIDGET_CHK_BTN, N_("Extract lyrics from MIDI file"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "amidiplug", .cname = "ap_opts_lyrics_extract"},
-
- /* backend settings */
- {WIDGET_LABEL, N_("<b>SoundFont</b>")},
- {WIDGET_CUSTOM, .data = {.populate = create_soundfont_list}},
- {WIDGET_LABEL, N_("<b>Synthesizer</b>")},
- {WIDGET_BOX, .data = {.box = {gain_widgets, ARRAY_LEN (gain_widgets), TRUE}}},
- {WIDGET_BOX, .data = {.box = {polyphony_widgets, ARRAY_LEN (polyphony_widgets), TRUE}}},
- {WIDGET_BOX, .data = {.box = {reverb_widgets, ARRAY_LEN (reverb_widgets), TRUE}}},
- {WIDGET_BOX, .data = {.box = {chorus_widgets, ARRAY_LEN (chorus_widgets), TRUE}}},
- {WIDGET_SPIN_BTN, N_("Sampling rate:"), .data = {.spin_btn = {22050, 96000, 1}},
-  .cfg_type = VALUE_INT, .csect = "amidiplug", .cname = "fsyn_synth_samplerate",
-  .callback = backend_change}};
-
-const PluginPreferences amidiplug_prefs = {
- .init = get_values,
- .widgets = amidiplug_widgets,
- .n_widgets = ARRAY_LEN (amidiplug_widgets)};
diff --git a/src/amidi-plug/i_configure.cc b/src/amidi-plug/i_configure.cc
new file mode 100644
index 000000000000..f192d2b66383
--- /dev/null
+++ b/src/amidi-plug/i_configure.cc
@@ -0,0 +1,156 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
+*
+* 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
+*
+*/
+
+#include "i_configure.h"
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/preferences.h>
+
+#include "i_configure-fluidsynth.h"
+
+bool backend_settings_changed = false;  /* atomic */
+
+static bool override_gain = false;
+static double gain_setting = 0.2;
+static bool override_polyphony = false;
+static int polyphony_setting = 256;
+static bool override_reverb = false;
+static bool reverb_setting = true;
+static bool override_chorus = false;
+static bool chorus_setting = true;
+
+static void get_values (void)
+{
+    int gain = aud_get_int ("amidiplug", "fsyn_synth_gain");
+    int polyphony = aud_get_int ("amidiplug", "fsyn_synth_polyphony");
+    int reverb = aud_get_int ("amidiplug", "fsyn_synth_reverb");
+    int chorus = aud_get_int ("amidiplug", "fsyn_synth_chorus");
+
+    if (gain != -1)
+    {
+        override_gain = true;
+        gain_setting = gain / 10.0;
+    }
+
+    if (polyphony != -1)
+    {
+        override_polyphony = true;
+        polyphony_setting = polyphony;
+    }
+
+    if (reverb != -1)
+    {
+        override_reverb = true;
+        reverb_setting = reverb;
+    }
+
+    if (chorus != -1)
+    {
+        override_chorus = true;
+        chorus_setting = chorus;
+    }
+}
+
+static void set_values (void)
+{
+    int gain = override_gain ? (int) (gain_setting * 10 + 0.5) : -1;
+    int polyphony = override_polyphony ? polyphony_setting : -1;
+    int reverb = override_reverb ? reverb_setting : -1;
+    int chorus = override_chorus ? chorus_setting : -1;
+
+    aud_set_int ("amidiplug", "fsyn_synth_gain", gain);
+    aud_set_int ("amidiplug", "fsyn_synth_polyphony", polyphony);
+    aud_set_int ("amidiplug", "fsyn_synth_reverb", reverb);
+    aud_set_int ("amidiplug", "fsyn_synth_chorus", chorus);
+}
+
+static void backend_change (void)
+{
+    set_values ();
+
+    /* reset backend at beginning of next song to apply changes */
+    __sync_bool_compare_and_swap (& backend_settings_changed, false, true);
+}
+
+static const PreferencesWidget gain_widgets[] = {
+    WidgetCheck (N_("Override default gain:"),
+        WidgetBool (override_gain, backend_change)),
+    WidgetSpin (0, WidgetFloat (gain_setting, backend_change),
+        {0, 10, 0.1},
+        WIDGET_CHILD)
+};
+
+static const PreferencesWidget polyphony_widgets[] = {
+    WidgetCheck (N_("Override default polyphony:"),
+        WidgetBool (override_polyphony, backend_change)),
+    WidgetSpin (0, WidgetInt (polyphony_setting, backend_change),
+        {16, 4096, 1},
+        WIDGET_CHILD)
+};
+
+static const PreferencesWidget reverb_widgets[] = {
+    WidgetCheck (N_("Override default reverb:"),
+        WidgetBool (override_reverb, backend_change)),
+    WidgetCheck (N_("On"),
+        WidgetBool (reverb_setting, backend_change),
+        WIDGET_CHILD)
+};
+
+static const PreferencesWidget chorus_widgets[] = {
+    WidgetCheck (N_("Override default chorus:"),
+        WidgetBool (override_chorus, backend_change)),
+    WidgetCheck (N_("On"),
+        WidgetBool (chorus_setting, backend_change),
+        WIDGET_CHILD)
+};
+
+static const PreferencesWidget amidiplug_widgets[] = {
+
+    /* global settings */
+    WidgetLabel (N_("<b>Playback</b>")),
+    WidgetSpin (N_("Transpose:"),
+        WidgetInt ("amidiplug", "ap_opts_transpose_value"),
+        {-20, 20, 1, N_("semitones")}),
+    WidgetSpin (N_("Drum shift:"),
+        WidgetInt ("amidiplug", "ap_opts_drumshift_value"),
+        {0, 127, 1, N_("note numbers")}),
+    WidgetCheck (N_("Skip leading silence"),
+        WidgetBool ("amidiplug", "skip_leading")),
+    WidgetCheck (N_("Skip trailing silence"),
+        WidgetBool ("amidiplug", "skip_trailing")),
+
+    /* backend settings */
+    WidgetLabel (N_("<b>SoundFont</b>")),
+    WidgetCustomGTK (create_soundfont_list),
+    WidgetLabel (N_("<b>Synthesizer</b>")),
+    WidgetBox ({{gain_widgets}, true}),
+    WidgetBox ({{polyphony_widgets}, true}),
+    WidgetBox ({{reverb_widgets}, true}),
+    WidgetBox ({{chorus_widgets}, true}),
+    WidgetSpin (N_("Sample rate:"),
+        WidgetInt ("amidiplug", "fsyn_synth_samplerate", backend_change),
+        {22050, 96000, 1, N_("Hz")})
+};
+
+const PluginPreferences amidiplug_prefs = {
+    {amidiplug_widgets},
+    get_values
+};
diff --git a/src/amidi-plug/i_configure.h b/src/amidi-plug/i_configure.h
index 6359525aab16..4648b1c053a9 100644
--- a/src/amidi-plug/i_configure.h
+++ b/src/amidi-plug/i_configure.h
@@ -21,9 +21,9 @@
 #ifndef _I_CONFIGURE_H
 #define _I_CONFIGURE_H 1
 
-#include <audacious/preferences.h>
+struct PluginPreferences;
 
-extern int backend_settings_changed;  /* atomic */
+extern bool backend_settings_changed;  /* atomic */
 
 extern const PluginPreferences amidiplug_prefs;
 
diff --git a/src/amidi-plug/i_fileinfo.c b/src/amidi-plug/i_fileinfo.c
deleted file mode 100644
index e8f6eb06322c..000000000000
--- a/src/amidi-plug/i_fileinfo.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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
-*
-*/
-
-#include "i_fileinfo.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-
-#include "i_configure.h"
-/* this is needed to retrieve information */
-#include "i_midi.h"
-/* icon from gnome-mime-audio-midi.png of the GNOME ICON SET */
-#include "amidi-plug.midiicon.xpm"
-
-
-void i_fileinfo_ev_destroy (GtkWidget * win, void * mf)
-{
-    i_midi_free ((midifile_t *) mf);
-    g_free (mf);
-}
-
-
-void i_fileinfo_ev_close (GtkWidget * button, void * fileinfowin)
-{
-    gtk_widget_destroy (GTK_WIDGET (fileinfowin));
-}
-
-
-void i_fileinfo_grid_add_entry (char * field_text, char * value_text,
-                                GtkWidget * grid, unsigned line, PangoAttrList * attrlist)
-{
-    GtkWidget * field, *value;
-    field = gtk_label_new (field_text);
-    gtk_label_set_attributes (GTK_LABEL (field), attrlist);
-    gtk_misc_set_alignment (GTK_MISC (field), 0, 0);
-    gtk_label_set_justify (GTK_LABEL (field), GTK_JUSTIFY_LEFT);
-    gtk_grid_attach (GTK_GRID (grid), field, 0, line, 1, 1);
-    value = gtk_label_new (value_text);
-    gtk_misc_set_alignment (GTK_MISC (value), 0, 0);
-    gtk_label_set_justify (GTK_LABEL (value), GTK_JUSTIFY_LEFT);
-    gtk_grid_attach (GTK_GRID (grid), value, 1, line, 1, 1);
-    return;
-}
-
-
-/* COMMENT: this will also reset current position in each track! */
-void i_fileinfo_text_fill (midifile_t * mf, GtkTextBuffer * text_tb, GtkTextBuffer * lyrics_tb)
-{
-    int l = 0;
-
-    /* initialize current position in each track */
-    for (l = 0; l < mf->num_tracks; ++l)
-        mf->tracks[l].current_event = mf->tracks[l].first_event;
-
-    for (;;)
-    {
-        midievent_t * event = NULL;
-        midifile_track_t * event_track = NULL;
-        int i, min_tick = mf->max_tick + 1;
-
-        /* search next event */
-        for (i = 0 ; i < mf->num_tracks ; ++i)
-        {
-            midifile_track_t * track = &mf->tracks[i];
-            midievent_t * e2 = track->current_event;
-
-            if ((e2) && (e2->tick < min_tick))
-            {
-                min_tick = e2->tick;
-                event = e2;
-                event_track = track;
-            }
-        }
-
-        if (!event)
-            break; /* end of song reached */
-
-        /* advance pointer to next event */
-        event_track->current_event = event->next;
-
-        switch (event->type)
-        {
-        case SND_SEQ_EVENT_META_TEXT:
-            gtk_text_buffer_insert_at_cursor (text_tb, event->data.metat, strlen (event->data.metat));
-            break;
-
-        case SND_SEQ_EVENT_META_LYRIC:
-            gtk_text_buffer_insert_at_cursor (lyrics_tb, event->data.metat, strlen (event->data.metat));
-            break;
-        }
-    }
-}
-
-
-void i_fileinfo_gui (const char * filename_uri)
-{
-    static GtkWidget * fileinfowin = NULL;
-    GtkWidget * fileinfowin_vbox, *fileinfowin_columns_hbox;
-    GtkWidget * midiinfoboxes_vbox, *miditextboxes_vbox, *miditextboxes_paned;
-    GtkWidget * title_hbox, *title_icon_image, *title_name_f_label, *title_name_v_entry;
-    GtkWidget * info_frame, *info_frame_tl, *info_grid;
-    GtkWidget * text_frame, *text_frame_tl, *text_tv, *text_tv_sw;
-    GtkWidget * lyrics_frame, *lyrics_tv, *lyrics_tv_sw;
-    GtkTextBuffer * text_tb, *lyrics_tb;
-    GtkWidget * footer_hbbox, *footer_bclose;
-    GdkPixbuf * title_icon_pixbuf;
-    PangoAttrList * pangoattrlist;
-    PangoAttribute * pangoattr;
-    GString * value_gstring;
-    char * title, *filename, *filename_utf8;
-    int bpm = 0, wavg_bpm = 0;
-    midifile_t * mf;
-
-    if (fileinfowin)
-        return;
-
-    mf = g_new (midifile_t, 1);
-
-    /****************** midifile parser ******************/
-    if (!i_midi_parse_from_filename (filename_uri, mf))
-        return;
-
-    /* midifile is filled with information at this point,
-       bpm information is needed too */
-    i_midi_get_bpm (mf, &bpm, &wavg_bpm);
-    /*****************************************************/
-
-    fileinfowin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_type_hint (GTK_WINDOW (fileinfowin), GDK_WINDOW_TYPE_HINT_DIALOG);
-    g_signal_connect (G_OBJECT (fileinfowin), "destroy", G_CALLBACK (i_fileinfo_ev_destroy), mf);
-    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_box_new (GTK_ORIENTATION_VERTICAL, 10);
-    gtk_container_add (GTK_CONTAINER (fileinfowin), fileinfowin_vbox);
-
-    /* pango attributes */
-    pangoattrlist = pango_attr_list_new();
-    pangoattr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
-    pangoattr->start_index = 0;
-    pangoattr->end_index = G_MAXINT;
-    pango_attr_list_insert (pangoattrlist, pangoattr);
-
-    /******************
-     *** TITLE LINE ***/
-    title_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 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);
-
-    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);
-
-    title_name_v_entry = gtk_entry_new();
-    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);
-
-    fileinfowin_columns_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
-    gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), fileinfowin_columns_hbox, TRUE, TRUE, 0);
-
-    /*********************
-     *** MIDI INFO BOX ***/
-    midiinfoboxes_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
-
-    int comments_extract = aud_get_int ("amidiplug", "ap_opts_comments_extract");
-    int lyrics_extract = aud_get_int ("amidiplug", "ap_opts_lyrics_extract");
-
-    /* pick the entire space if both comments and lyrics boxes are not displayed,
-       pick only required space if at least one of them is displayed */
-    if (! comments_extract && ! lyrics_extract)
-        gtk_box_pack_start (GTK_BOX (fileinfowin_columns_hbox), midiinfoboxes_vbox, TRUE, TRUE, 0);
-    else
-        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);
-
-    info_frame = gtk_frame_new (NULL);
-    gtk_box_pack_start (GTK_BOX (midiinfoboxes_vbox), info_frame, TRUE, TRUE, 0);
-    info_grid = gtk_grid_new();
-    gtk_grid_set_row_spacing (GTK_GRID (info_grid), 4);
-    gtk_grid_set_column_spacing (GTK_GRID (info_grid), 10);
-    gtk_container_set_border_width (GTK_CONTAINER (info_grid), 3);
-    gtk_container_add (GTK_CONTAINER (info_frame), info_grid);
-    value_gstring = g_string_new ("");
-
-    /* midi format */
-    g_string_printf (value_gstring, "type %i", mf->format);
-    i_fileinfo_grid_add_entry (_("Format:"), value_gstring->str, info_grid, 0, pangoattrlist);
-    /* midi length */
-    g_string_printf (value_gstring, "%i", (int) (mf->length / 1000));
-    i_fileinfo_grid_add_entry (_("Length (msec):"), value_gstring->str, info_grid, 1, pangoattrlist);
-    /* midi num of tracks */
-    g_string_printf (value_gstring, "%i", mf->num_tracks);
-    i_fileinfo_grid_add_entry (_("No. of Tracks:"), value_gstring->str, info_grid, 2, pangoattrlist);
-
-    /* midi bpm */
-    if (bpm > 0)
-        g_string_printf (value_gstring, "%i", bpm);  /* fixed bpm */
-    else
-        g_string_printf (value_gstring, _("variable")); /* variable bpm */
-
-    i_fileinfo_grid_add_entry (_("BPM:"), value_gstring->str, info_grid, 3, pangoattrlist);
-
-    /* midi weighted average bpm */
-    if (bpm > 0)
-        g_string_printf (value_gstring, "/");  /* fixed bpm, don't care about wavg_bpm */
-    else
-        g_string_printf (value_gstring, "%i", wavg_bpm);  /* variable bpm, display wavg_bpm */
-
-    i_fileinfo_grid_add_entry (_("BPM (wavg):"), value_gstring->str, info_grid, 4, pangoattrlist);
-    /* midi time division */
-    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);
-
-    /**********************************
-     *** MIDI COMMENTS/LYRICS BOXES ***/
-    miditextboxes_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 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);
-
-    miditextboxes_paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
-    gtk_box_pack_start (GTK_BOX (miditextboxes_vbox), miditextboxes_paned, TRUE, TRUE, 0);
-
-    text_frame = gtk_frame_new (NULL);
-    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_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);
-    gtk_widget_set_size_request (text_tv, 300, 113);
-    text_tv_sw = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (text_tv_sw),
-                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-    gtk_container_add (GTK_CONTAINER (text_frame), text_tv_sw);
-    gtk_container_add (GTK_CONTAINER (text_tv_sw), text_tv);
-
-    lyrics_frame = gtk_frame_new (NULL);
-    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_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);
-    gtk_widget_set_size_request (lyrics_tv, 300, 113);
-    lyrics_tv_sw = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (lyrics_tv_sw),
-                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-    gtk_container_add (GTK_CONTAINER (lyrics_frame), lyrics_tv_sw);
-    gtk_container_add (GTK_CONTAINER (lyrics_tv_sw), lyrics_tv);
-
-    text_tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_tv));
-    lyrics_tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (lyrics_tv));
-
-    /* call the buffer fill routine if at least one between comments and lyrics is enabled */
-    if (comments_extract || lyrics_extract)
-        i_fileinfo_text_fill (mf, text_tb, lyrics_tb);
-
-    if (comments_extract && ! gtk_text_buffer_get_char_count (text_tb))
-    {
-        GtkTextIter start, end;
-        GtkTextTag * tag = gtk_text_buffer_create_tag (text_tb, "italicstyle",
-                           "style", PANGO_STYLE_ITALIC, NULL);
-        /*gtk_text_view_set_justification( GTK_TEXT_VIEW(text_tv), GTK_JUSTIFY_CENTER );*/
-        gtk_text_buffer_set_text (text_tb, _("* no comments available in this MIDI file *"), -1);
-        gtk_text_buffer_get_iter_at_offset (text_tb, &start, 0);
-        gtk_text_buffer_get_iter_at_offset (text_tb, &end, -1);
-        gtk_text_buffer_apply_tag (text_tb, tag, &start, &end);
-    }
-
-    if (lyrics_extract && ! gtk_text_buffer_get_char_count (lyrics_tb))
-    {
-        GtkTextIter start, end;
-        GtkTextTag * tag = gtk_text_buffer_create_tag (lyrics_tb, "italicstyle",
-                           "style", PANGO_STYLE_ITALIC, NULL);
-        /*gtk_text_view_set_justification( GTK_TEXT_VIEW(lyrics_tv), GTK_JUSTIFY_CENTER );*/
-        gtk_text_buffer_set_text (lyrics_tb, _("* no lyrics available in this MIDI file *"), -1);
-        gtk_text_buffer_get_iter_at_offset (lyrics_tb, &start, 0);
-        gtk_text_buffer_get_iter_at_offset (lyrics_tb, &end, -1);
-        gtk_text_buffer_apply_tag (lyrics_tb, tag, &start, &end);
-    }
-
-    /* hide boxes for disabled options (comments and/or lyrics) */
-    if (! comments_extract && ! lyrics_extract)
-    {
-        gtk_widget_set_no_show_all (miditextboxes_vbox, TRUE);
-        gtk_widget_hide (miditextboxes_vbox);
-    }
-    else if (! comments_extract)
-    {
-        gtk_widget_set_no_show_all (text_frame, TRUE);
-        gtk_widget_hide (text_frame);
-    }
-    else if (! lyrics_extract)
-    {
-        gtk_widget_set_no_show_all (lyrics_frame, TRUE);
-        gtk_widget_hide (lyrics_frame);
-    }
-
-    /**************
-     *** FOOTER ***/
-    footer_hbbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
-    gtk_button_box_set_layout (GTK_BUTTON_BOX (footer_hbbox), GTK_BUTTONBOX_END);
-    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);
-
-
-    /* utf8-ize filename and set window title */
-    filename = g_filename_from_uri (filename_uri, NULL, NULL);
-
-    if (!filename)
-        filename = g_strdup (filename_uri);
-
-    filename_utf8 = g_strdup (g_filename_to_utf8 (filename, -1, NULL, NULL, NULL));
-
-    if (!filename_utf8)
-    {
-        /* utf8 fallback */
-        char * chr, *convert_str = g_strdup (filename);
-
-        for (chr = convert_str ; *chr ; chr++)
-        {
-            if (*chr & 0x80)
-                *chr = '?';
-        }
-
-        filename_utf8 = g_strconcat (convert_str, _("  (invalid UTF-8)"), NULL);
-        g_free (convert_str);
-    }
-
-    title = g_path_get_basename (filename_utf8);
-    gtk_window_set_title (GTK_WINDOW (fileinfowin), title);
-    g_free (title);
-    /* set the text for the filename header too */
-    gtk_entry_set_text (GTK_ENTRY (title_name_v_entry), filename_utf8);
-    gtk_editable_set_position (GTK_EDITABLE (title_name_v_entry), -1);
-    g_free (filename_utf8);
-    g_free (filename);
-
-    gtk_widget_grab_focus (GTK_WIDGET (footer_bclose));
-    gtk_widget_show_all (fileinfowin);
-}
diff --git a/src/amidi-plug/i_fileinfo.cc b/src/amidi-plug/i_fileinfo.cc
new file mode 100644
index 000000000000..fc04c4c446a7
--- /dev/null
+++ b/src/amidi-plug/i_fileinfo.cc
@@ -0,0 +1,340 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
+*
+* 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
+*
+*/
+
+#include "i_fileinfo.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+
+#include "i_configure.h"
+/* this is needed to retrieve information */
+#include "i_midi.h"
+/* icon from gnome-mime-audio-midi.png of the GNOME ICON SET */
+#include "amidi-plug.midiicon.xpm"
+
+
+void i_fileinfo_ev_close (GtkWidget * button, void * fileinfowin)
+{
+    gtk_widget_destroy (GTK_WIDGET (fileinfowin));
+}
+
+
+void i_fileinfo_grid_add_entry (char * field_text, char * value_text,
+                                GtkWidget * grid, unsigned line, PangoAttrList * attrlist)
+{
+    GtkWidget * field, *value;
+    field = gtk_label_new (field_text);
+    gtk_label_set_attributes (GTK_LABEL (field), attrlist);
+    gtk_misc_set_alignment (GTK_MISC (field), 0, 0);
+    gtk_table_attach (GTK_TABLE (grid), field, 0, 1, line, line + 1, GTK_FILL, GTK_FILL, 0, 0);
+    value = gtk_label_new (value_text);
+    gtk_misc_set_alignment (GTK_MISC (value), 0, 0);
+    gtk_table_attach (GTK_TABLE (grid), value, 1, 2, line, line + 1, GTK_FILL, GTK_FILL, 0, 0);
+}
+
+
+/* COMMENT: this will also reset current position in each track! */
+void i_fileinfo_text_fill (midifile_t * mf, GtkTextBuffer * text_tb, GtkTextBuffer * lyrics_tb)
+{
+    /* initialize current position in each track */
+    for (midifile_track_t & track : mf->tracks)
+        track.current_event = track.events.head ();
+
+    for (;;)
+    {
+        midievent_t * event = nullptr;
+        midifile_track_t * event_track = nullptr;
+        int min_tick = INT_MAX;  /* meta-events may go past max_tick */
+
+        /* search next event */
+        for (midifile_track_t & track : mf->tracks)
+        {
+            midievent_t * e2 = track.current_event;
+
+            if (e2 && e2->tick < min_tick)
+            {
+                min_tick = e2->tick;
+                event = e2;
+                event_track = & track;
+            }
+        }
+
+        if (!event)
+            break; /* end of song reached */
+
+        /* advance pointer to next event */
+        event_track->current_event = event_track->events.next (event);
+
+        switch (event->type)
+        {
+        case SND_SEQ_EVENT_META_TEXT:
+            gtk_text_buffer_insert_at_cursor (text_tb, event->metat, -1);
+            break;
+
+        case SND_SEQ_EVENT_META_LYRIC:
+            gtk_text_buffer_insert_at_cursor (lyrics_tb, event->metat, -1);
+            break;
+        }
+    }
+}
+
+
+void i_fileinfo_gui (const char * filename_uri, VFSFile & file)
+{
+    static GtkWidget * fileinfowin = nullptr;
+    GtkWidget * fileinfowin_vbox, *fileinfowin_columns_hbox;
+    GtkWidget * midiinfoboxes_vbox, *miditextboxes_vbox, *miditextboxes_paned;
+    GtkWidget * title_hbox, *title_icon_image, *title_name_f_label, *title_name_v_entry;
+    GtkWidget * info_frame, *info_frame_tl, *info_grid;
+    GtkWidget * text_frame, *text_frame_tl, *text_tv, *text_tv_sw;
+    GtkWidget * lyrics_frame, *lyrics_tv, *lyrics_tv_sw;
+    GtkTextBuffer * text_tb, *lyrics_tb;
+    GtkWidget * footer_hbbox, *footer_bclose;
+    GdkPixbuf * title_icon_pixbuf;
+    PangoAttrList * pangoattrlist;
+    PangoAttribute * pangoattr;
+    GString * value_gstring;
+    char * title, *filename, *filename_utf8;
+    int bpm = 0, wavg_bpm = 0;
+
+    if (fileinfowin)
+        return;
+
+    midifile_t mf;
+
+    /****************** midifile parser ******************/
+    if (! mf.parse_from_file (filename_uri, file))
+        return;
+
+    /* midifile is filled with information at this point,
+       bpm information is needed too */
+    mf.get_bpm (& bpm, & wavg_bpm);
+    /*****************************************************/
+
+    fileinfowin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_default_size (GTK_WINDOW (fileinfowin), 500, 400);
+    gtk_window_set_type_hint (GTK_WINDOW (fileinfowin), GDK_WINDOW_TYPE_HINT_DIALOG);
+    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);
+    gtk_container_add (GTK_CONTAINER (fileinfowin), fileinfowin_vbox);
+
+    /* pango attributes */
+    pangoattrlist = pango_attr_list_new();
+    pangoattr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+    pangoattr->start_index = 0;
+    pangoattr->end_index = G_MAXINT;
+    pango_attr_list_insert (pangoattrlist, pangoattr);
+
+    /******************
+     *** TITLE LINE ***/
+    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);
+
+    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);
+
+    title_name_v_entry = gtk_entry_new();
+    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);
+
+    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);
+
+    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);
+
+    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_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);
+    gtk_container_add (GTK_CONTAINER (info_frame), info_grid);
+    value_gstring = g_string_new ("");
+
+    /* midi format */
+    g_string_printf (value_gstring, "type %i", mf.format);
+    i_fileinfo_grid_add_entry (_("Format:"), value_gstring->str, info_grid, 0, pangoattrlist);
+    /* midi length */
+    g_string_printf (value_gstring, "%i", (int) (mf.length / 1000));
+    i_fileinfo_grid_add_entry (_("Length (msec):"), value_gstring->str, info_grid, 1, pangoattrlist);
+    /* midi num of tracks */
+    g_string_printf (value_gstring, "%i", mf.tracks.len ());
+    i_fileinfo_grid_add_entry (_("No. of Tracks:"), value_gstring->str, info_grid, 2, pangoattrlist);
+
+    /* midi bpm */
+    if (bpm > 0)
+        g_string_printf (value_gstring, "%i", bpm);  /* fixed bpm */
+    else
+        g_string_printf (value_gstring, _("variable")); /* variable bpm */
+
+    i_fileinfo_grid_add_entry (_("BPM:"), value_gstring->str, info_grid, 3, pangoattrlist);
+
+    /* midi weighted average bpm */
+    if (bpm > 0)
+        g_string_printf (value_gstring, "/");  /* fixed bpm, don't care about wavg_bpm */
+    else
+        g_string_printf (value_gstring, "%i", wavg_bpm);  /* variable bpm, display wavg_bpm */
+
+    i_fileinfo_grid_add_entry (_("BPM (wavg):"), value_gstring->str, info_grid, 4, pangoattrlist);
+    /* midi time division */
+    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);
+
+    /**********************************
+     *** 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);
+
+    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);
+
+    miditextboxes_paned = gtk_vpaned_new ();
+    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);
+    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_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);
+    gtk_widget_set_size_request (text_tv, 300, 113);
+    text_tv_sw = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (text_tv_sw),
+                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_container_add (GTK_CONTAINER (text_frame), text_tv_sw);
+    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);
+    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_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);
+    gtk_widget_set_size_request (lyrics_tv, 300, 113);
+    lyrics_tv_sw = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (lyrics_tv_sw),
+                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_container_add (GTK_CONTAINER (lyrics_frame), lyrics_tv_sw);
+    gtk_container_add (GTK_CONTAINER (lyrics_tv_sw), lyrics_tv);
+
+    text_tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_tv));
+    lyrics_tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (lyrics_tv));
+
+    i_fileinfo_text_fill (& mf, text_tb, lyrics_tb);
+
+    if (! gtk_text_buffer_get_char_count (text_tb))
+    {
+        GtkTextIter start, end;
+        GtkTextTag * tag = gtk_text_buffer_create_tag (text_tb, "italicstyle",
+                           "style", PANGO_STYLE_ITALIC, nullptr);
+        /*gtk_text_view_set_justification( GTK_TEXT_VIEW(text_tv), GTK_JUSTIFY_CENTER );*/
+        gtk_text_buffer_set_text (text_tb, _("* no comments available in this MIDI file *"), -1);
+        gtk_text_buffer_get_iter_at_offset (text_tb, &start, 0);
+        gtk_text_buffer_get_iter_at_offset (text_tb, &end, -1);
+        gtk_text_buffer_apply_tag (text_tb, tag, &start, &end);
+    }
+
+    if (! gtk_text_buffer_get_char_count (lyrics_tb))
+    {
+        GtkTextIter start, end;
+        GtkTextTag * tag = gtk_text_buffer_create_tag (lyrics_tb, "italicstyle",
+                           "style", PANGO_STYLE_ITALIC, nullptr);
+        /*gtk_text_view_set_justification( GTK_TEXT_VIEW(lyrics_tv), GTK_JUSTIFY_CENTER );*/
+        gtk_text_buffer_set_text (lyrics_tb, _("* no lyrics available in this MIDI file *"), -1);
+        gtk_text_buffer_get_iter_at_offset (lyrics_tb, &start, 0);
+        gtk_text_buffer_get_iter_at_offset (lyrics_tb, &end, -1);
+        gtk_text_buffer_apply_tag (lyrics_tb, tag, &start, &end);
+    }
+
+    /**************
+     *** FOOTER ***/
+    footer_hbbox = gtk_hbutton_box_new ();
+    gtk_button_box_set_layout (GTK_BUTTON_BOX (footer_hbbox), GTK_BUTTONBOX_END);
+    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);
+
+
+    /* utf8-ize filename and set window title */
+    filename = g_filename_from_uri (filename_uri, nullptr, nullptr);
+
+    if (!filename)
+        filename = g_strdup (filename_uri);
+
+    filename_utf8 = g_strdup (g_filename_to_utf8 (filename, -1, nullptr, nullptr, nullptr));
+
+    if (!filename_utf8)
+    {
+        /* utf8 fallback */
+        char * chr, *convert_str = g_strdup (filename);
+
+        for (chr = convert_str ; *chr ; chr++)
+        {
+            if (*chr & 0x80)
+                *chr = '?';
+        }
+
+        filename_utf8 = g_strconcat (convert_str, _("  (invalid UTF-8)"), nullptr);
+        g_free (convert_str);
+    }
+
+    title = g_path_get_basename (filename_utf8);
+    gtk_window_set_title (GTK_WINDOW (fileinfowin), title);
+    g_free (title);
+    /* set the text for the filename header too */
+    gtk_entry_set_text (GTK_ENTRY (title_name_v_entry), filename_utf8);
+    gtk_editable_set_position (GTK_EDITABLE (title_name_v_entry), -1);
+    g_free (filename_utf8);
+    g_free (filename);
+
+    gtk_widget_grab_focus (GTK_WIDGET (footer_bclose));
+    gtk_widget_show_all (fileinfowin);
+}
diff --git a/src/amidi-plug/i_fileinfo.h b/src/amidi-plug/i_fileinfo.h
index 518e2190d17c..15749e515896 100644
--- a/src/amidi-plug/i_fileinfo.h
+++ b/src/amidi-plug/i_fileinfo.h
@@ -21,6 +21,8 @@
 #ifndef _I_FILEINFO_H
 #define _I_FILEINFO_H 1
 
-void i_fileinfo_gui (const char *);
+class VFSFile;
+
+void i_fileinfo_gui (const char * filename_uri, VFSFile & file);
 
 #endif /* !_I_FILEINFO_H */
diff --git a/src/amidi-plug/i_midi.c b/src/amidi-plug/i_midi.c
deleted file mode 100644
index e15358dbc070..000000000000
--- a/src/amidi-plug/i_midi.c
+++ /dev/null
@@ -1,897 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* MIDI (SMF) parser based on aplaymidi.c from ALSA-utils
-* aplaymidi.c is Copyright (c) 2004 Clemens Ladisch <clemens at ladisch.de>
-*
-* 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
-*
-*/
-
-#include "i_midi.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/misc.h>
-
-#include "i_configure.h"
-
-/* #define DEBUGMSG(...) fprintf (stderr, __VA_ARGS__) */
-#define DEBUGMSG(...)
-
-#define WARNANDBREAK(...) { fprintf (stderr, __VA_ARGS__); break; }
-
-#define ERRMSG_MIDITRACK() { fprintf(stderr, "%s: invalid MIDI data (offset %#x)", mf->file_name, mf->file_offset ); return 0; }
-
-
-/* skip a certain number of bytes */
-void i_midi_file_skip_bytes (midifile_t * mf, int bytes)
-{
-    while (bytes > 0)
-    {
-        i_midi_file_read_byte (mf);
-        --bytes;
-    }
-}
-
-
-/* reads a single byte */
-int i_midi_file_read_byte (midifile_t * mf)
-{
-    ++mf->file_offset;
-    return vfs_getc (mf->file_pointer);
-}
-
-
-/* reads a little-endian 32-bit integer */
-int i_midi_file_read_32_le (midifile_t * mf)
-{
-    int value;
-    value = i_midi_file_read_byte (mf);
-    value |= i_midi_file_read_byte (mf) << 8;
-    value |= i_midi_file_read_byte (mf) << 16;
-    value |= i_midi_file_read_byte (mf) << 24;
-    return !vfs_feof (mf->file_pointer) ? value : -1;
-}
-
-
-/* reads a 4-character identifier */
-int i_midi_file_read_id (midifile_t * mf)
-{
-    return i_midi_file_read_32_le (mf);
-}
-
-
-/* reads a fixed-size big-endian number */
-int i_midi_file_read_int (midifile_t * mf, int bytes)
-{
-    int c, value = 0;
-
-    do
-    {
-        c = i_midi_file_read_byte (mf);
-
-        if (c == EOF) return -1;
-
-        value = (value << 8) | c;
-    }
-    while (--bytes);
-
-    return value;
-}
-
-
-/* reads a variable-length number */
-int i_midi_file_read_var (midifile_t * mf)
-{
-    int value, c;
-
-    c = i_midi_file_read_byte (mf);
-    value = c & 0x7f;
-
-    if (c & 0x80)
-    {
-        c = i_midi_file_read_byte (mf);
-        value = (value << 7) | (c & 0x7f);
-
-        if (c & 0x80)
-        {
-            c = i_midi_file_read_byte (mf);
-            value = (value << 7) | (c & 0x7f);
-
-            if (c & 0x80)
-            {
-                c = i_midi_file_read_byte (mf);
-                value = (value << 7) | c;
-
-                if (c & 0x80)
-                    return -1;
-            }
-        }
-    }
-
-    return value;
-}
-
-
-/* allocates a new event */
-midievent_t * i_midi_file_new_event (midifile_track_t * track, int sysex_length)
-{
-    midievent_t * event;
-
-    event = g_new (midievent_t, 1);
-    event->sysex = sysex_length ? g_malloc (sysex_length) : NULL;
-    event->next = NULL;
-
-    /* append at the end of the track's linked list */
-    if (track->current_event)
-        track->current_event->next = event;
-    else
-        track->first_event = event;
-
-    track->current_event = event;
-
-    return event;
-}
-
-
-/* reads one complete track from the file */
-int i_midi_file_read_track (midifile_t * mf, midifile_track_t * track,
-                            int track_end, int port_count)
-{
-    int tick = 0;
-    unsigned char last_cmd = 0;
-    unsigned char port = 0;
-
-    /* the current file position is after the track ID and length */
-    while (mf->file_offset < track_end)
-    {
-        unsigned char cmd;
-        midievent_t * event;
-        int delta_ticks, len, c;
-
-        delta_ticks = i_midi_file_read_var (mf);
-
-        if (delta_ticks < 0)
-            break;
-
-        tick += delta_ticks;
-
-        c = i_midi_file_read_byte (mf);
-
-        if (c < 0)
-            break;
-
-        if (c & 0x80)
-        {
-            /* have command */
-            cmd = c;
-
-            if (cmd < 0xf0)
-                last_cmd = cmd;
-        }
-        else
-        {
-            /* running status */
-            if (vfs_ungetc (c, mf->file_pointer) < 0)
-                break;
-
-            mf->file_offset--;
-            cmd = last_cmd;
-
-            if (!cmd)
-                ERRMSG_MIDITRACK();
-        }
-
-        switch (cmd >> 4)
-        {
-            /* maps SMF events to ALSA sequencer events */
-            static unsigned char cmd_type[] =
-            {
-                [0x8] = SND_SEQ_EVENT_NOTEOFF,
-                [0x9] = SND_SEQ_EVENT_NOTEON,
-                [0xa] = SND_SEQ_EVENT_KEYPRESS,
-                [0xb] = SND_SEQ_EVENT_CONTROLLER,
-                [0xc] = SND_SEQ_EVENT_PGMCHANGE,
-                [0xd] = SND_SEQ_EVENT_CHANPRESS,
-                [0xe] = SND_SEQ_EVENT_PITCHBEND
-            };
-
-        case 0x8: /* channel msg with 2 parameter bytes */
-        case 0x9:
-        case 0xa:
-        {
-            event = i_midi_file_new_event (track, 0);
-            event->type = cmd_type[cmd >> 4];
-            event->port = port;
-            event->tick = tick;
-            event->data.d[0] = cmd & 0x0f;
-
-            /* if this note is not in standard drum channel (10), apply transpose */
-            if (event->data.d[0] != 9)
-            {
-                int transpose = aud_get_int ("amidiplug", "ap_opts_transpose_value");
-                int data_tr = (i_midi_file_read_byte (mf) & 0x7f) + transpose;
-
-                if (data_tr > 127) data_tr = 127;
-                else if (data_tr < 0) data_tr = 0;
-
-                event->data.d[1] = (unsigned char) data_tr;
-            }
-            else /* this note is in standard drum channel (10), apply drum shift */
-            {
-                int drumshift = aud_get_int ("amidiplug", "ap_opts_drumshift_value");
-                int data_ds = (i_midi_file_read_byte (mf) & 0x7f) + drumshift; /* always > 0 */
-
-                if (data_ds > 127) data_ds -= 127;
-
-                event->data.d[1] = (unsigned char) data_ds;
-            }
-
-            event->data.d[2] = i_midi_file_read_byte (mf) & 0x7f;
-        }
-        break;
-
-        case 0xb: /* channel msg with 2 parameter bytes */
-        case 0xe:
-        {
-            event = i_midi_file_new_event (track, 0);
-            event->type = cmd_type[cmd >> 4];
-            event->port = port;
-            event->tick = tick;
-            event->data.d[0] = cmd & 0x0f;
-            event->data.d[1] = i_midi_file_read_byte (mf) & 0x7f;
-            event->data.d[2] = i_midi_file_read_byte (mf) & 0x7f;
-        }
-        break;
-
-        case 0xc: /* channel msg with 1 parameter byte */
-        case 0xd:
-        {
-            event = i_midi_file_new_event (track, 0);
-            event->type = cmd_type[cmd >> 4];
-            event->port = port;
-            event->tick = tick;
-            event->data.d[0] = cmd & 0x0f;
-            event->data.d[1] = i_midi_file_read_byte (mf) & 0x7f;
-        }
-        break;
-
-        case 0xf:
-        {
-            switch (cmd)
-            {
-            case 0xf0: /* sysex */
-            case 0xf7: /* continued sysex, or escaped commands */
-            {
-                len = i_midi_file_read_var (mf);
-
-                if (len < 0)
-                    ERRMSG_MIDITRACK();
-
-                if (cmd == 0xf0)
-                    ++len;
-
-                event = i_midi_file_new_event (track, len);
-                event->type = SND_SEQ_EVENT_SYSEX;
-                event->port = port;
-                event->tick = tick;
-                event->data.length = len;
-
-                if (cmd == 0xf0)
-                {
-                    event->sysex[0] = 0xf0;
-                    c = 1;
-                }
-                else
-                {
-                    c = 0;
-                }
-
-                for (; c < len; ++c)
-                    event->sysex[c] = i_midi_file_read_byte (mf);
-            }
-            break;
-
-            case 0xff: /* meta event */
-            {
-                c = i_midi_file_read_byte (mf);
-                len = i_midi_file_read_var (mf);
-
-                if (len < 0)
-                    ERRMSG_MIDITRACK();
-
-                switch (c)
-                {
-                case 0x21: /* port number */
-                {
-                    if (len < 1)
-                        ERRMSG_MIDITRACK();
-
-                    port = i_midi_file_read_byte (mf) % port_count;
-                    i_midi_file_skip_bytes (mf, (len - 1));
-                }
-                break;
-
-                case 0x2f: /* end of track */
-                {
-                    track->end_tick = tick;
-                    i_midi_file_skip_bytes (mf, (track_end - mf->file_offset));
-                    return 1;
-                }
-
-                case 0x51: /* tempo */
-                {
-                    if (len < 3)
-                        ERRMSG_MIDITRACK();
-
-                    if (mf->smpte_timing)
-                    {
-                        /* SMPTE timing doesn't change */
-                        i_midi_file_skip_bytes (mf,len);
-                    }
-                    else
-                    {
-                        event = i_midi_file_new_event (track, 0);
-                        event->type = SND_SEQ_EVENT_TEMPO;
-                        event->port = port;
-                        event->tick = tick;
-                        event->data.tempo = i_midi_file_read_byte (mf) << 16;
-                        event->data.tempo |= i_midi_file_read_byte (mf) << 8;
-                        event->data.tempo |= i_midi_file_read_byte (mf);
-                        i_midi_file_skip_bytes (mf, (len - 3));
-                    }
-                }
-                break;
-
-                case 0x01: /* text comments */
-                {
-                    if (aud_get_int ("amidiplug", "ap_opts_comments_extract") > 0)
-                    {
-                        int ic = 0;
-
-                        if (len < 1)
-                            ERRMSG_MIDITRACK();
-
-                        event = i_midi_file_new_event (track, 0);
-                        event->type = SND_SEQ_EVENT_META_TEXT;
-                        event->tick = tick;
-                        event->data.metat = g_malloc (len + 1);
-
-                        for (ic = 0 ; ic < len ; ic++)
-                            event->data.metat[ic] = i_midi_file_read_byte (mf);
-
-                        event->data.metat[len] = '\0';
-                    }
-                    else
-                        i_midi_file_skip_bytes (mf,len);
-                }
-                break;
-
-                case 0x05: /* lyrics */
-                {
-                    if (aud_get_int ("amidiplug", "ap_opts_lyrics_extract"))
-                    {
-                        int ic = 0;
-
-                        if (len < 1)
-                            ERRMSG_MIDITRACK();
-
-                        event = i_midi_file_new_event (track, 0);
-                        event->type = SND_SEQ_EVENT_META_LYRIC;
-                        event->tick = tick;
-                        event->data.metat = g_malloc (len + 1);
-
-                        for (ic = 0 ; ic < len ; ic++)
-                            event->data.metat[ic] = i_midi_file_read_byte (mf);
-
-                        event->data.metat[len] = '\0';
-                    }
-                    else
-                        i_midi_file_skip_bytes (mf,len);
-                }
-                break;
-
-                default: /* ignore all other meta events */
-                {
-                    i_midi_file_skip_bytes (mf,len);
-                }
-                break;
-                }
-            }
-            break;
-
-            default: /* invalid Fx command */
-                ERRMSG_MIDITRACK();
-            }
-        }
-        break;
-
-        default: /* cannot happen */
-            ERRMSG_MIDITRACK();
-        }
-    }
-
-    ERRMSG_MIDITRACK();
-}
-
-
-/* read a MIDI file in Standard MIDI Format */
-/* return values: 0 = error, 1 = ok */
-int i_midi_file_parse_smf (midifile_t * mf, int port_count)
-{
-    int header_len, i;
-
-    /* the curren position is immediately after the "MThd" id */
-    header_len = i_midi_file_read_int (mf,4);
-
-    if (header_len < 6)
-    {
-        fprintf (stderr, "%s: invalid file format\n", mf->file_name);
-        return 0;
-    }
-
-    mf->format = i_midi_file_read_int (mf,2);
-
-    if ((mf->format != 0) && (mf->format != 1))
-    {
-        fprintf (stderr, "%s: type %d format is not supported\n", mf->file_name, mf->format);
-        return 0;
-    }
-
-    mf->num_tracks = i_midi_file_read_int (mf,2);
-
-    if ((mf->num_tracks < 1) || (mf->num_tracks > 1000))
-    {
-        fprintf (stderr, "%s: invalid number of tracks (%d)\n", mf->file_name, mf->num_tracks);
-        mf->num_tracks = 0;
-        return 0;
-    }
-
-    mf->tracks = g_new0 (midifile_track_t, mf->num_tracks);
-
-    mf->time_division = i_midi_file_read_int (mf,2);
-
-    if (mf->time_division < 0)
-    {
-        fprintf (stderr, "%s: invalid file format\n", mf->file_name);
-        return 0;
-    }
-
-    mf->smpte_timing = !! (mf->time_division & 0x8000);
-
-    /* read tracks */
-    for (i = 0 ; i < mf->num_tracks ; ++i)
-    {
-        int len;
-
-        /* search for MTrk chunk */
-        for (;;)
-        {
-            int id = i_midi_file_read_id (mf);
-            len = i_midi_file_read_int (mf,4);
-
-            if (vfs_feof (mf->file_pointer))
-            {
-                fprintf (stderr, "%s: unexpected end of file\n", mf->file_name);
-                return 0;
-            }
-
-            if ((len < 0) || (len >= 0x10000000))
-            {
-                fprintf (stderr, "%s: invalid chunk length %d\n", mf->file_name, len);
-                return 0;
-            }
-
-            if (id == MAKE_ID ('M', 'T', 'r', 'k'))
-                break;
-
-            i_midi_file_skip_bytes (mf,len);
-        }
-
-        if (!i_midi_file_read_track (mf, &mf->tracks[i], mf->file_offset + len, port_count))
-            return 0;
-    }
-
-    /* calculate the max_tick for the entire file */
-    mf->max_tick = 0;
-
-    for (i = 0 ; i < mf->num_tracks ; ++i)
-    {
-        if (mf->tracks[i].end_tick > mf->max_tick)
-            mf->max_tick = mf->tracks[i].end_tick;
-    }
-
-    /* ok, success */
-    return 1;
-}
-
-
-/* read a MIDI file enclosed in RIFF format */
-/* return values: 0 = error, 1 = ok */
-int i_midi_file_parse_riff (midifile_t * mf)
-{
-    /* skip file length (4 bytes) */
-    i_midi_file_skip_bytes (mf,4);
-
-    /* check file type ("RMID" = RIFF MIDI) */
-    if (i_midi_file_read_id (mf) != MAKE_ID ('R', 'M', 'I', 'D'))
-        return 0;
-
-    /* search for "data" chunk */
-    for (;;)
-    {
-        int id = i_midi_file_read_id (mf);
-        int len = i_midi_file_read_32_le (mf);
-
-        if (vfs_feof (mf->file_pointer))
-            return 0;
-
-        if (id == MAKE_ID ('d', 'a', 't', 'a'))
-            break;
-
-        if (len < 0)
-            return 0;
-
-        i_midi_file_skip_bytes (mf, ((len + 1) & ~1));
-    }
-
-    /* the "data" chunk must contain data in SMF format */
-    if (i_midi_file_read_id (mf) != MAKE_ID ('M', 'T', 'h', 'd'))
-        return 0;
-
-    /* ok, success */
-    return 1;
-}
-
-
-/* midifile init */
-void i_midi_init (midifile_t * mf)
-{
-    mf->file_pointer = NULL;
-    mf->file_name = NULL;
-    mf->file_offset = 0;
-    mf->num_tracks = 0;
-    mf->tracks = NULL;
-    mf->max_tick = 0;
-    mf->smpte_timing = 0;
-    mf->format = 0;
-    mf->time_division = 0;
-    mf->ppq = 0;
-    mf->current_tempo = 0;
-    mf->playing_tick = 0;
-    mf->avg_microsec_per_tick = 0;
-    mf->length = 0;
-    return;
-}
-
-
-void i_midi_free (midifile_t * mf)
-{
-    g_free (mf->file_name);
-    mf->file_name = NULL;
-
-    if (mf->tracks)
-    {
-        int i;
-
-        /* free event list for each track */
-        for (i = 0 ; i < mf->num_tracks ; ++i)
-        {
-            midievent_t * event = mf->tracks[i].first_event;
-            midievent_t * event_tmp = NULL;
-
-            while (event)
-            {
-                event_tmp = event;
-                event = event->next;
-
-                if ((event_tmp->type == SND_SEQ_EVENT_META_TEXT) ||
-                        (event_tmp->type == SND_SEQ_EVENT_META_LYRIC))
-                    g_free (event_tmp->data.metat);
-
-                g_free (event_tmp->sysex);
-                g_free (event_tmp);
-            }
-        }
-
-        /* free track array */
-        g_free (mf->tracks);
-        mf->tracks = NULL;
-    }
-}
-
-
-/* queue set tempo */
-int i_midi_setget_tempo (midifile_t * mf)
-{
-    int smpte_timing, i = 0;
-    int time_division = mf->time_division;
-
-    /* interpret and set tempo */
-    smpte_timing = !! (time_division & 0x8000);
-
-    if (!smpte_timing)
-    {
-        /* time_division is ticks per quarter */
-        mf->current_tempo = 500000;
-        mf->ppq = time_division;
-    }
-    else
-    {
-        /* upper byte is negative frames per second */
-        i = 0x80 - ((time_division >> 8) & 0x7f);
-        /* lower byte is ticks per frame */
-        time_division &= 0xff;
-
-        /* now pretend that we have quarter-note based timing */
-        switch (i)
-        {
-        case 24:
-            mf->current_tempo = 500000;
-            mf->ppq = 12 * time_division;
-            break;
-
-        case 25:
-            mf->current_tempo = 400000;
-            mf->ppq = 10 * time_division;
-            break;
-
-        case 29: /* 30 drop-frame */
-            mf->current_tempo = 100000000;
-            mf->ppq = 2997 * time_division;
-            break;
-
-        case 30:
-            mf->current_tempo = 500000;
-            mf->ppq = 15 * time_division;
-            break;
-
-        default:
-            fprintf (stderr, "Invalid number of SMPTE frames per second (%d)\n", i);
-            return 0;
-        }
-    }
-
-    DEBUGMSG ("MIDI tempo set -> time division: %i\n", midifile.time_division);
-    DEBUGMSG ("MIDI tempo set -> tempo: %i\n", midifile.current_tempo);
-    DEBUGMSG ("MIDI tempo set -> ppq: %i\n", midifile.ppq);
-    return 1;
-}
-
-
-/* this will set the midi length in microseconds
-   COMMENT: this will also reset current position in each track! */
-void i_midi_setget_length (midifile_t * mf)
-{
-    int64_t length_microsec = 0;
-    int last_tick = 0, i = 0;
-    /* get the first microsec_per_tick ratio */
-    int microsec_per_tick = (int) (mf->current_tempo / mf->ppq);
-
-    /* initialize current position in each track */
-    for (i = 0; i < mf->num_tracks; ++i)
-        mf->tracks[i].current_event = mf->tracks[i].first_event;
-
-    /* search for tempo events in each track; in fact, since the program
-       currently supports type 0 and type 1 MIDI files, we should find
-       tempo events only in one track */
-    DEBUGMSG ("LENGTH calc: starting calc loop\n");
-
-    for (;;)
-    {
-        midievent_t * event = NULL;
-        midifile_track_t * event_track = NULL;
-        int i, min_tick = mf->max_tick + 1;
-
-        /* search next event */
-        for (i = 0 ; i < mf->num_tracks ; ++i)
-        {
-            midifile_track_t * track = &mf->tracks[i];
-            midievent_t * e2 = track->current_event;
-
-            if (e2 && e2->tick < min_tick)
-            {
-                min_tick = e2->tick;
-                event = e2;
-                event_track = track;
-            }
-        }
-
-        if (!event)
-        {
-            /* calculate the remaining length */
-            length_microsec += (microsec_per_tick * (mf->max_tick - last_tick));
-            break; /* end of song reached */
-        }
-
-        /* advance pointer to next event */
-        event_track->current_event = event->next;
-
-        /* check if this is a tempo event */
-        if (event->type == SND_SEQ_EVENT_TEMPO)
-        {
-            DEBUGMSG ("LENGTH calc: tempo event (%i) encountered during calc on tick %i\n",
-                      event->data.tempo, event->tick);
-            /* increment length_microsec with the amount of microsec before tempo change */
-            length_microsec += (microsec_per_tick * (event->tick - last_tick));
-            /* now update last_tick and the microsec_per_tick ratio */
-            last_tick = event->tick;
-            microsec_per_tick = (int) (event->data.tempo / mf->ppq);
-        }
-    }
-
-    /* IMPORTANT
-       this couple of important values is set by i_midi_set_length */
-    mf->length = length_microsec;
-
-    if (mf->max_tick)
-        mf->avg_microsec_per_tick = (int) (length_microsec / mf->max_tick);
-    else
-        mf->avg_microsec_per_tick = 1;  /* dummy - protect against div-by-zero */
-
-    return;
-}
-
-
-/* this will get the weighted average bpm of the midi file;
-   if the file has a variable bpm, 'bpm' is set to -1;
-   COMMENT: this will also reset current position in each track! */
-void i_midi_get_bpm (midifile_t * mf, int * bpm, int * wavg_bpm)
-{
-    int i = 0, last_tick = 0;
-    unsigned weighted_avg_tempo = 0;
-    bool_t is_monotempo = TRUE;
-    int last_tempo = mf->current_tempo;
-
-    /* initialize current position in each track */
-    for (i = 0 ; i < mf->num_tracks ; ++i)
-        mf->tracks[i].current_event = mf->tracks[i].first_event;
-
-    /* search for tempo events in each track; in fact, since the program
-       currently supports type 0 and type 1 MIDI files, we should find
-       tempo events only in one track */
-    DEBUGMSG ("BPM calc: starting calc loop\n");
-
-    for (;;)
-    {
-        midievent_t * event = NULL;
-        midifile_track_t * event_track = NULL;
-        int i, min_tick = mf->max_tick + 1;
-
-        /* search next event */
-        for (i = 0 ; i < mf->num_tracks ; ++i)
-        {
-            midifile_track_t * track = &mf->tracks[i];
-            midievent_t * e2 = track->current_event;
-
-            if (e2 && e2->tick < min_tick)
-            {
-                min_tick = e2->tick;
-                event = e2;
-                event_track = track;
-            }
-        }
-
-        if (!event)
-        {
-            /* calculate the remaining length */
-            weighted_avg_tempo += (unsigned) (last_tempo * ((float) (mf->max_tick - last_tick) / (float) mf->max_tick));
-            break; /* end of song reached */
-        }
-
-        /* advance pointer to next event */
-        event_track->current_event = event->next;
-
-        /* check if this is a tempo event */
-        if (event->type == SND_SEQ_EVENT_TEMPO)
-        {
-            /* check if this is a tempo change (real change, tempo should be
-               different) in the midi file (and it shouldn't be at tick 0); */
-            if ((is_monotempo) && (event->tick > 0) && (event->data.tempo != last_tempo))
-                is_monotempo = FALSE;
-
-            DEBUGMSG ("BPM calc: tempo event (%i) encountered during calc on tick %i\n",
-                      event->data.tempo, event->tick);
-            /* add the previous tempo change multiplied for its weight (the tick interval for the tempo )  */
-            weighted_avg_tempo += (unsigned) (last_tempo * ((float) (event->tick - last_tick) / (float) mf->max_tick));
-            /* now update last_tick and the microsec_per_tick ratio */
-            last_tick = event->tick;
-            last_tempo = event->data.tempo;
-        }
-    }
-
-    DEBUGMSG ("BPM calc: weighted average tempo: %i\n", weighted_avg_tempo);
-
-    *wavg_bpm = (int) (60000000 / weighted_avg_tempo);
-
-    DEBUGMSG ("BPM calc: weighted average bpm: %i\n", *wavg_bpm);
-
-    if (is_monotempo)
-        *bpm = *wavg_bpm; /* the song has fixed bpm */
-    else
-        *bpm = -1; /* the song has variable bpm */
-
-    return;
-}
-
-
-/* helper function that parses a midi file; returns 1 on success, 0 otherwise */
-int i_midi_parse_from_filename (const char * filename, midifile_t * mf)
-{
-    i_midi_init (mf);
-    DEBUGMSG ("PARSE_FROM_FILENAME requested, opening file: %s\n", filename);
-    mf->file_pointer = vfs_fopen (filename, "rb");
-
-    if (!mf->file_pointer)
-    {
-        fprintf (stderr, "Cannot open %s\n", filename);
-        return 0;
-    }
-
-    mf->file_name = g_strdup (filename);
-
-    switch (i_midi_file_read_id (mf))
-    {
-    case MAKE_ID ('R', 'I', 'F', 'F') :
-    {
-        DEBUGMSG ("PARSE_FROM_FILENAME requested, RIFF chunk found, processing...\n");
-
-        /* read riff chunk */
-        if (!i_midi_file_parse_riff (mf))
-            WARNANDBREAK ("%s: invalid file format (riff parser)\n", filename);
-
-        /* if that was read correctly, go ahead and read smf data */
-    }
-
-    case MAKE_ID ('M', 'T', 'h', 'd') :
-    {
-        DEBUGMSG ("PARSE_FROM_FILENAME requested, MThd chunk found, processing...\n");
-
-        /* we don't care about port count here, pass 1 */
-        if (!i_midi_file_parse_smf (mf, 1))
-            WARNANDBREAK ("%s: invalid file format (smf parser)\n", filename);
-
-        if (mf->time_division < 1)
-            WARNANDBREAK ("%s: invalid time division (%i)\n", filename, mf->time_division);
-
-        /* fill mf->ppq and mf->tempo using time_division */
-        if (!i_midi_setget_tempo (mf))
-            WARNANDBREAK ("%s: invalid values while setting ppq and tempo\n", filename);
-
-        /* fill mf->length, keeping in count tempo-changes */
-        i_midi_setget_length (mf);
-
-        /* ok, mf has been filled with information; successfully return */
-        vfs_fclose (mf->file_pointer);
-        return 1;
-    }
-
-    default:
-    {
-        fprintf (stderr, "%s is not a Standard MIDI File\n", filename);
-        break;
-    }
-    }
-
-    /* something failed */
-    vfs_fclose (mf->file_pointer);
-    return 0;
-}
diff --git a/src/amidi-plug/i_midi.cc b/src/amidi-plug/i_midi.cc
new file mode 100644
index 000000000000..73087128614c
--- /dev/null
+++ b/src/amidi-plug/i_midi.cc
@@ -0,0 +1,803 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
+*
+* MIDI (SMF) parser based on aplaymidi.c from ALSA-utils
+* aplaymidi.c is Copyright (c) 2004 Clemens Ladisch <clemens at ladisch.de>
+*
+* 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
+*
+*/
+
+#include "i_midi.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/vfs.h>
+
+#include "i_configure.h"
+
+#define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
+
+#define WARNANDBREAK(...) { AUDERR (__VA_ARGS__); break; }
+
+#define ERRMSG_MIDITRACK() { AUDERR ("%s: invalid MIDI data (offset %#x)", \
+    (const char *) file_name, file_offset); return false; }
+
+
+/* skip a certain number of bytes */
+void midifile_t::skip_bytes (int bytes)
+{
+    while (bytes > 0)
+    {
+        read_byte ();
+        --bytes;
+    }
+}
+
+
+/* reads a single byte */
+int midifile_t::read_byte ()
+{
+    if (file_offset >= file_data.len ())
+    {
+        file_eof = true;
+        return -1;
+    }
+
+    return (unsigned char) file_data[file_offset ++];
+}
+
+
+/* reads a little-endian 32-bit integer */
+int midifile_t::read_32_le ()
+{
+    int value;
+    value = read_byte ();
+    value |= read_byte () << 8;
+    value |= read_byte () << 16;
+    value |= read_byte () << 24;
+    return !file_eof ? value : -1;
+}
+
+
+/* reads a 4-character identifier */
+int midifile_t::read_id ()
+{
+    return read_32_le ();
+}
+
+
+/* reads a fixed-size big-endian number */
+int midifile_t::read_int (int bytes)
+{
+    int c, value = 0;
+
+    do
+    {
+        c = read_byte ();
+
+        if (c < 0) return -1;
+
+        value = (value << 8) | c;
+    }
+    while (--bytes);
+
+    return value;
+}
+
+
+/* reads a variable-length number */
+int midifile_t::read_var ()
+{
+    int value, c;
+
+    c = read_byte ();
+    value = c & 0x7f;
+
+    if (c & 0x80)
+    {
+        c = read_byte ();
+        value = (value << 7) | (c & 0x7f);
+
+        if (c & 0x80)
+        {
+            c = read_byte ();
+            value = (value << 7) | (c & 0x7f);
+
+            if (c & 0x80)
+            {
+                c = read_byte ();
+                value = (value << 7) | c;
+
+                if (c & 0x80)
+                    return -1;
+            }
+        }
+    }
+
+    return value;
+}
+
+
+/* reads one complete track from the file */
+bool midifile_t::read_track (midifile_track_t & track, int track_end, int port_count)
+{
+    int tick = 0;
+    unsigned char last_cmd = 0;
+    unsigned char port = 0;
+
+    track.start_tick = -1;
+    track.end_tick = -1;
+
+    /* the current file position is after the track ID and length */
+    while (file_offset < track_end)
+    {
+        unsigned char cmd;
+        midievent_t * event;
+        int delta_ticks, len, c;
+
+        delta_ticks = read_var ();
+
+        if (delta_ticks < 0)
+            break;
+
+        tick += delta_ticks;
+
+        c = read_byte ();
+
+        if (c < 0)
+            break;
+
+        if (c & 0x80)
+        {
+            /* have command */
+            cmd = c;
+
+            if (cmd < 0xf0)
+                last_cmd = cmd;
+        }
+        else
+        {
+            /* running status */
+            file_offset--;
+            cmd = last_cmd;
+
+            if (!cmd)
+                ERRMSG_MIDITRACK();
+        }
+
+        switch (cmd >> 4)
+        {
+            /* maps SMF events to ALSA sequencer events */
+            static unsigned char cmd_type[16] =
+            {
+                0, 0, 0, 0, 0, 0, 0, 0,
+                SND_SEQ_EVENT_NOTEOFF,     // 08h
+                SND_SEQ_EVENT_NOTEON,      // 09h
+                SND_SEQ_EVENT_KEYPRESS,    // 0ah
+                SND_SEQ_EVENT_CONTROLLER,  // 0bh
+                SND_SEQ_EVENT_PGMCHANGE,   // 0ch
+                SND_SEQ_EVENT_CHANPRESS,   // 0dh
+                SND_SEQ_EVENT_PITCHBEND    // 0eh
+            };
+
+        case 0x8: /* channel msg with 2 parameter bytes */
+        case 0x9:
+        case 0xa:
+        {
+            event = track.add_event ();
+            event->type = cmd_type[cmd >> 4];
+            event->port = port;
+            event->tick = tick;
+            event->d[0] = cmd & 0x0f;
+
+            /* if this note is not in standard drum channel (10), apply transpose */
+            if (event->d[0] != 9)
+            {
+                int transpose = aud_get_int ("amidiplug", "ap_opts_transpose_value");
+                int data_tr = (read_byte () & 0x7f) + transpose;
+
+                if (data_tr > 127) data_tr = 127;
+                else if (data_tr < 0) data_tr = 0;
+
+                event->d[1] = (unsigned char) data_tr;
+            }
+            else /* this note is in standard drum channel (10), apply drum shift */
+            {
+                int drumshift = aud_get_int ("amidiplug", "ap_opts_drumshift_value");
+                int data_ds = (read_byte () & 0x7f) + drumshift; /* always > 0 */
+
+                if (data_ds > 127) data_ds -= 127;
+
+                event->d[1] = (unsigned char) data_ds;
+            }
+
+            event->d[2] = read_byte () & 0x7f;
+
+            if (event->type == SND_SEQ_EVENT_NOTEON && track.start_tick < 0)
+                track.start_tick = tick;
+            if (track.start_tick >= 0 && tick >= track.start_tick)
+                track.end_tick = tick;
+        }
+        break;
+
+        case 0xb: /* channel msg with 2 parameter bytes */
+        case 0xe:
+        {
+            event = track.add_event ();
+            event->type = cmd_type[cmd >> 4];
+            event->port = port;
+            event->tick = tick;
+            event->d[0] = cmd & 0x0f;
+            event->d[1] = read_byte () & 0x7f;
+            event->d[2] = read_byte () & 0x7f;
+
+            if (track.start_tick >= 0 && tick >= track.start_tick)
+                track.end_tick = tick;
+        }
+        break;
+
+        case 0xc: /* channel msg with 1 parameter byte */
+        case 0xd:
+        {
+            event = track.add_event ();
+            event->type = cmd_type[cmd >> 4];
+            event->port = port;
+            event->tick = tick;
+            event->d[0] = cmd & 0x0f;
+            event->d[1] = read_byte () & 0x7f;
+
+            if (track.start_tick >= 0 && tick >= track.start_tick)
+                track.end_tick = tick;
+        }
+        break;
+
+        case 0xf:
+        {
+            switch (cmd)
+            {
+            case 0xf0: /* sysex */
+            case 0xf7: /* continued sysex, or escaped commands */
+            {
+                len = read_var ();
+
+                if (len < 0)
+                    ERRMSG_MIDITRACK();
+
+                /* skip sysex */
+                skip_bytes (len);
+            }
+            break;
+
+            case 0xff: /* meta event */
+            {
+                c = read_byte ();
+                len = read_var ();
+
+                if (len < 0)
+                    ERRMSG_MIDITRACK();
+
+                switch (c)
+                {
+                case 0x21: /* port number */
+                {
+                    if (len < 1)
+                        ERRMSG_MIDITRACK();
+
+                    port = read_byte () % port_count;
+                    skip_bytes (len - 1);
+                }
+                break;
+
+                case 0x2f: /* end of track */
+                {
+                    if (! aud_get_bool ("amidiplug", "skip_leading"))
+                        track.start_tick = 0;
+                    if (! aud_get_bool ("amidiplug", "skip_trailing"))
+                        track.end_tick = tick;
+
+                    skip_bytes (track_end - file_offset);
+                    return true;
+                }
+
+                case 0x51: /* tempo */
+                {
+                    if (len < 3)
+                        ERRMSG_MIDITRACK();
+
+                    if (smpte_timing)
+                    {
+                        /* SMPTE timing doesn't change */
+                        skip_bytes (len);
+                    }
+                    else
+                    {
+                        event = track.add_event ();
+                        event->type = SND_SEQ_EVENT_TEMPO;
+                        event->port = port;
+                        event->tick = tick;
+                        event->tempo = read_byte () << 16;
+                        event->tempo |= read_byte () << 8;
+                        event->tempo |= read_byte ();
+                        skip_bytes (len - 3);
+                    }
+                }
+                break;
+
+                case 0x01: /* text comments */
+                {
+                    if (len < 0)
+                        ERRMSG_MIDITRACK();
+
+                    event = track.add_event ();
+                    event->type = SND_SEQ_EVENT_META_TEXT;
+                    event->tick = tick;
+
+                    StringBuf buf (len);
+                    for (int i = 0; i < len; i ++)
+                        buf[i] = read_byte ();
+
+                    event->metat = String (str_to_utf8 (std::move (buf)));
+                }
+                break;
+
+                case 0x05: /* lyrics */
+                {
+                    if (len < 0)
+                        ERRMSG_MIDITRACK();
+
+                    event = track.add_event ();
+                    event->type = SND_SEQ_EVENT_META_LYRIC;
+                    event->tick = tick;
+
+                    StringBuf buf (len);
+                    for (int i = 0; i < len; i ++)
+                        buf[i] = read_byte ();
+
+                    event->metat = String (str_to_utf8 (std::move (buf)));
+                }
+                break;
+
+                default: /* ignore all other meta events */
+                {
+                    skip_bytes (len);
+                }
+                break;
+                }
+            }
+            break;
+
+            default: /* invalid Fx command */
+                ERRMSG_MIDITRACK();
+            }
+        }
+        break;
+
+        default: /* cannot happen */
+            ERRMSG_MIDITRACK();
+        }
+    }
+
+    ERRMSG_MIDITRACK();
+}
+
+
+/* read a MIDI file in Standard MIDI Format */
+/* return values: 0 = error, 1 = ok */
+bool midifile_t::parse_smf (int port_count)
+{
+    int header_len;
+
+    /* the curren position is immediately after the "MThd" id */
+    header_len = read_int (4);
+
+    if (header_len < 6)
+    {
+        AUDERR ("%s: invalid file format\n", (const char *) file_name);
+        return false;
+    }
+
+    format = read_int (2);
+
+    if (format != 0 && format != 1)
+    {
+        AUDERR ("%s: type %d format is not supported\n", (const char *) file_name, format);
+        return false;
+    }
+
+    int num_tracks = read_int (2);
+
+    if (num_tracks < 1 || num_tracks > 1000)
+    {
+        AUDERR ("%s: invalid number of tracks (%d)\n", (const char *) file_name, num_tracks);
+        num_tracks = 0;
+        return false;
+    }
+
+    tracks.insert (0, num_tracks);
+
+    time_division = read_int (2);
+
+    if (time_division < 0)
+    {
+        AUDERR ("%s: invalid file format\n", (const char *) file_name);
+        return false;
+    }
+
+    smpte_timing = !! (time_division & 0x8000);
+
+    /* read tracks */
+    for (midifile_track_t & track : tracks)
+    {
+        int len;
+
+        /* search for MTrk chunk */
+        for (;;)
+        {
+            int id = read_id ();
+            len = read_int (4);
+
+            if (file_eof)
+            {
+                AUDERR ("%s: unexpected end of file\n", (const char *) file_name);
+                return false;
+            }
+
+            if (len < 0 || len >= 0x10000000)
+            {
+                AUDERR ("%s: invalid chunk length %d\n", (const char *) file_name, len);
+                return false;
+            }
+
+            if (id == MAKE_ID ('M', 'T', 'r', 'k'))
+                break;
+
+            skip_bytes (len);
+        }
+
+        if (! read_track (track, file_offset + len, port_count))
+            return false;
+    }
+
+    /* calculate the max_tick for the entire file */
+    start_tick = -1;
+    max_tick = 0;
+
+    for (midifile_track_t & track : tracks)
+    {
+        if (track.start_tick >= 0 && (start_tick < 0 || track.start_tick < start_tick))
+            start_tick = track.start_tick;
+        if (track.end_tick > max_tick)
+            max_tick = track.end_tick;
+    }
+
+    if (start_tick < 0)
+        start_tick = 0;
+
+    /* ok, success */
+    return true;
+}
+
+
+/* read a MIDI file enclosed in RIFF format */
+/* return values: 0 = error, 1 = ok */
+bool midifile_t::parse_riff ()
+{
+    /* skip file length (4 bytes) */
+    skip_bytes (4);
+
+    /* check file type ("RMID" = RIFF MIDI) */
+    if (read_id () != MAKE_ID ('R', 'M', 'I', 'D'))
+        return false;
+
+    /* search for "data" chunk */
+    for (;;)
+    {
+        int id = read_id ();
+        int len = read_32_le ();
+
+        if (file_eof)
+            return false;
+
+        if (id == MAKE_ID ('d', 'a', 't', 'a'))
+            break;
+
+        if (len < 0)
+            return false;
+
+        skip_bytes ((len + 1) & ~1);
+    }
+
+    /* the "data" chunk must contain data in SMF format */
+    if (read_id () != MAKE_ID ('M', 'T', 'h', 'd'))
+        return false;
+
+    /* ok, success */
+    return true;
+}
+
+
+/* queue set tempo */
+bool midifile_t::setget_tempo ()
+{
+    /* interpret and set tempo */
+    bool smpte_timing = !! (time_division & 0x8000);
+
+    if (!smpte_timing)
+    {
+        /* time_division is ticks per quarter */
+        current_tempo = 500000;
+        ppq = time_division;
+    }
+    else
+    {
+        /* upper byte is negative frames per second */
+        int fps = 0x80 - ((time_division >> 8) & 0x7f);
+        /* lower byte is ticks per frame */
+        int tpf = time_division & 0xff;
+
+        /* now pretend that we have quarter-note based timing */
+        switch (fps)
+        {
+        case 24:
+            current_tempo = 500000;
+            ppq = 12 * tpf;
+            break;
+
+        case 25:
+            current_tempo = 400000;
+            ppq = 10 * tpf;
+            break;
+
+        case 29: /* 30 drop-frame */
+            current_tempo = 100000000;
+            ppq = 2997 * tpf;
+            break;
+
+        case 30:
+            current_tempo = 500000;
+            ppq = 15 * tpf;
+            break;
+
+        default:
+            AUDERR ("Invalid number of SMPTE frames per second (%d)\n", fps);
+            return false;
+        }
+    }
+
+    AUDDBG ("MIDI tempo set -> time division: %i\n", time_division);
+    AUDDBG ("MIDI tempo set -> tempo: %i\n", current_tempo);
+    AUDDBG ("MIDI tempo set -> ppq: %i\n", ppq);
+    return true;
+}
+
+
+/* this will set the midi length in microseconds
+   COMMENT: this will also reset current position in each track! */
+void midifile_t::setget_length ()
+{
+    int64_t length_microsec = 0;
+    int last_tick = start_tick;
+    /* get the first microsec_per_tick ratio */
+    int microsec_per_tick = (int) (current_tempo / ppq);
+
+    /* initialize current position in each track */
+    for (midifile_track_t & track : tracks)
+        track.current_event = track.events.head ();
+
+    /* search for tempo events in each track; in fact, since the program
+       currently supports type 0 and type 1 MIDI files, we should find
+       tempo events only in one track */
+    AUDDBG ("LENGTH calc: starting calc loop\n");
+
+    for (;;)
+    {
+        midievent_t * event = nullptr;
+        midifile_track_t * event_track = nullptr;
+        int min_tick = max_tick + 1;
+
+        /* search next event */
+        for (midifile_track_t & track : tracks)
+        {
+            midievent_t * e2 = track.current_event;
+
+            if (e2 && e2->tick < min_tick)
+            {
+                min_tick = e2->tick;
+                event = e2;
+                event_track = & track;
+            }
+        }
+
+        if (!event)
+        {
+            /* calculate the remaining length */
+            length_microsec += (microsec_per_tick * (max_tick - last_tick));
+            break; /* end of song reached */
+        }
+
+        /* advance pointer to next event */
+        event_track->current_event = event_track->events.next (event);
+
+        /* check if this is a tempo event */
+        if (event->type == SND_SEQ_EVENT_TEMPO)
+        {
+            int tick = aud::max (event->tick, start_tick);
+            AUDDBG ("LENGTH calc: tempo event (%i) on tick %i\n", event->tempo, tick);
+
+            /* increment length_microsec with the amount of microsec before tempo change */
+            length_microsec += (microsec_per_tick * (tick - last_tick));
+            /* now update last_tick and the microsec_per_tick ratio */
+            last_tick = tick;
+            microsec_per_tick = (int) (event->tempo / ppq);
+        }
+    }
+
+    /* IMPORTANT
+       this couple of important values is set by midifile_t::set_length */
+    length = length_microsec;
+
+    if (max_tick > start_tick)
+        avg_microsec_per_tick = (int) (length_microsec / (max_tick - start_tick));
+    else
+        avg_microsec_per_tick = 0;
+
+    return;
+}
+
+
+/* this will get the weighted average bpm of the midi file;
+   if the file has a variable bpm, 'bpm' is set to -1;
+   COMMENT: this will also reset current position in each track! */
+void midifile_t::get_bpm (int * bpm, int * wavg_bpm)
+{
+    int last_tick = start_tick;
+    unsigned weighted_avg_tempo = 0;
+    bool is_monotempo = true;
+    int last_tempo = current_tempo;
+
+    /* initialize current position in each track */
+    for (midifile_track_t & track : tracks)
+        track.current_event = track.events.head ();
+
+    /* search for tempo events in each track; in fact, since the program
+       currently supports type 0 and type 1 MIDI files, we should find
+       tempo events only in one track */
+    AUDDBG ("BPM calc: starting calc loop\n");
+
+    for (;;)
+    {
+        midievent_t * event = nullptr;
+        midifile_track_t * event_track = nullptr;
+        int min_tick = max_tick + 1;
+
+        /* search next event */
+        for (midifile_track_t & track : tracks)
+        {
+            midievent_t * e2 = track.current_event;
+
+            if (e2 && e2->tick < min_tick)
+            {
+                min_tick = e2->tick;
+                event = e2;
+                event_track = & track;
+            }
+        }
+
+        if (!event)
+        {
+            /* calculate the remaining length */
+            if (max_tick > start_tick)
+                weighted_avg_tempo += (unsigned) (last_tempo *
+                 ((float) (max_tick - last_tick) / (float) (max_tick - start_tick)));
+
+            break; /* end of song reached */
+        }
+
+        /* advance pointer to next event */
+        event_track->current_event = event_track->events.next (event);
+
+        /* check if this is a tempo event */
+        if (event->type == SND_SEQ_EVENT_TEMPO)
+        {
+            int tick = aud::max (event->tick, start_tick);
+            AUDDBG ("BPM calc: tempo event (%i) on tick %i\n", event->tempo, tick);
+
+            /* check if this is a tempo change (real change, tempo should be
+               different) in the midi file (and it shouldn't be at tick 0); */
+            if (is_monotempo && tick > start_tick && event->tempo != last_tempo)
+                is_monotempo = false;
+
+            /* add the previous tempo change multiplied for its weight (the tick interval for the tempo )  */
+            if (max_tick > start_tick)
+                weighted_avg_tempo += (unsigned) (last_tempo *
+                 ((float) (tick - last_tick) / (float) (max_tick - start_tick)));
+
+            /* now update last_tick and the microsec_per_tick ratio */
+            last_tick = tick;
+            last_tempo = event->tempo;
+        }
+    }
+
+    AUDDBG ("BPM calc: weighted average tempo: %i\n", weighted_avg_tempo);
+
+    if (weighted_avg_tempo > 0)
+        *wavg_bpm = (int) (60000000 / weighted_avg_tempo);
+    else
+        *wavg_bpm = 0;
+
+    AUDDBG ("BPM calc: weighted average bpm: %i\n", *wavg_bpm);
+
+    if (is_monotempo)
+        *bpm = *wavg_bpm; /* the song has fixed bpm */
+    else
+        *bpm = -1; /* the song has variable bpm */
+}
+
+
+/* helper function that parses a midi file; returns 1 on success, 0 otherwise */
+bool midifile_t::parse_from_file (const char * filename, VFSFile & file)
+{
+    bool success = false;
+
+    file_name = String (filename);
+    file_data = file.read_all ();
+
+    switch (read_id ())
+    {
+    case MAKE_ID ('R', 'I', 'F', 'F') :
+        AUDDBG ("PARSE_FROM_FILENAME requested, RIFF chunk found, processing...\n");
+
+        /* read riff chunk */
+        if (!parse_riff ())
+            WARNANDBREAK ("%s: invalid file format (riff parser)\n", filename);
+
+        /* if that was read correctly, go ahead and read smf data */
+
+    case MAKE_ID ('M', 'T', 'h', 'd') :
+        AUDDBG ("PARSE_FROM_FILENAME requested, MThd chunk found, processing...\n");
+
+        /* we don't care about port count here, pass 1 */
+        if (!parse_smf (1))
+            WARNANDBREAK ("%s: invalid file format (smf parser)\n", filename);
+
+        if (time_division < 1)
+            WARNANDBREAK ("%s: invalid time division (%i)\n", filename, time_division);
+
+        /* fill ppq and tempo using time_division */
+        if (!setget_tempo ())
+            WARNANDBREAK ("%s: invalid values while setting ppq and tempo\n", filename);
+
+        /* fill length, keeping in count tempo-changes */
+        setget_length ();
+
+        /* ok, mf has been filled with information; successfully return */
+        success = true;
+        break;
+
+    default:
+        AUDERR ("%s is not a Standard MIDI File\n", filename);
+        break;
+    }
+
+    file_name = String ();
+    file_data.clear ();
+
+    return success;
+}
diff --git a/src/amidi-plug/i_midi.h b/src/amidi-plug/i_midi.h
index 7c86e79bd8b6..6863be68cb4e 100644
--- a/src/amidi-plug/i_midi.h
+++ b/src/amidi-plug/i_midi.h
@@ -22,11 +22,11 @@
 #define _I_MIDI_H 1
 
 #include <stdint.h>
-#include <libaudcore/vfs.h>
+#include <libaudcore/index.h>
 
 #include "i_midievent.h"
 
-#define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
+class VFSFile;
 
 
 /* sequencer event type, got from ALSA header alsa/seq_event.h */
@@ -227,53 +227,61 @@ enum snd_seq_event_type
 };
 
 
-typedef struct
+struct midifile_track_t
 {
-    midievent_t * first_event;	/* list of all events in this track */
+    List<midievent_t> events;           /* list of all events in this track */
+    int start_tick;                     /* start of this track */
     int end_tick;			/* length of this track */
     midievent_t * current_event;	/* used while loading and playing */
-}
-midifile_track_t;
 
-typedef struct
+    midievent_t * add_event ()
+    {
+        midievent_t * event = new midievent_t ();
+        events.append (event);
+        return event;
+    }
+
+    ~midifile_track_t ()
+        { events.clear (); }
+};
+
+
+struct midifile_t
 {
-    VFSFile * file_pointer;
-    char * file_name;
-    int file_offset;
-
-    int num_tracks;
-    midifile_track_t * tracks;
-
-    unsigned short format;
-    unsigned max_tick;
-    int smpte_timing;
-
-    int time_division;
-    int ppq;
-    int current_tempo;
-
-    int playing_tick;
-    int avg_microsec_per_tick;
-    int64_t length;
-}
-midifile_t;
-
-midievent_t * i_midi_file_new_event (midifile_track_t *, int);
-void i_midi_file_skip_bytes (midifile_t *, int);
-int i_midi_file_read_byte (midifile_t *);
-int i_midi_file_read_32_le (midifile_t *);
-int i_midi_file_read_id (midifile_t *);
-int i_midi_file_read_int (midifile_t *, int);
-int i_midi_file_read_var (midifile_t *);
-int i_midi_file_read_track (midifile_t *, midifile_track_t *, int, int);
-int i_midi_file_parse_riff (midifile_t *);
-int i_midi_file_parse_smf (midifile_t *, int);
-void i_midi_init (midifile_t *);
-void i_midi_free (midifile_t *);
-int i_midi_setget_tempo (midifile_t *);
-void i_midi_setget_length (midifile_t *);
-void i_midi_get_bpm (midifile_t *, int *, int *);
-/* helper function */
-int i_midi_parse_from_filename (const char *, midifile_t *);
+    Index<midifile_track_t> tracks;
+
+    unsigned short format = 0;
+    int start_tick = 0;
+    int max_tick = 0;
+    int smpte_timing = 0;
+
+    int time_division = 0;
+    int ppq = 0;
+    int current_tempo = 0;
+
+    int avg_microsec_per_tick = 0;
+    int64_t length = 0;
+
+    void get_bpm (int *, int *);
+    bool parse_from_file (const char *, VFSFile & file);
+
+private:
+    String file_name;
+    Index<char> file_data;
+    int file_offset = 0;
+    bool file_eof = false;
+
+    void skip_bytes (int);
+    int read_byte ();
+    int read_32_le ();
+    int read_id ();
+    int read_int (int);
+    int read_var ();
+    bool read_track (midifile_track_t &, int, int);
+    bool parse_smf (int);
+    bool parse_riff ();
+    bool setget_tempo ();
+    void setget_length ();
+};
 
 #endif /* !_I_MIDI_H */
diff --git a/src/amidi-plug/i_midievent.h b/src/amidi-plug/i_midievent.h
index 05a379686b3c..b939e5dec360 100644
--- a/src/amidi-plug/i_midievent.h
+++ b/src/amidi-plug/i_midievent.h
@@ -21,22 +21,18 @@
 #ifndef _I_MIDIEVENT_H
 #define _I_MIDIEVENT_H 1
 
-struct midievent_s
+#include <libaudcore/list.h>
+#include <libaudcore/objects.h>
+
+struct midievent_t : public ListNode
 {
-    struct midievent_s * next;		/* linked list */
     unsigned char type;				/* SND_SEQ_EVENT_xxx */
     unsigned char port;				/* port index */
-    unsigned tick;
-    union
-    {
-        unsigned char d[3];			/* channel and data bytes */
-        int tempo;
-        unsigned length;			/* length of sysex data */
-        char * metat;			/* meta-event text */
-    } data;
-    unsigned char * sysex;
-};
+    int tick;
 
-typedef struct midievent_s midievent_t;
+    unsigned char d[3];			/* channel and data bytes */
+    int tempo;
+    String metat;			/* meta-event text */
+};
 
 #endif /* !_I_MIDIEVENT_H */
diff --git a/src/amidi-plug/i_utils.c b/src/amidi-plug/i_utils.c
deleted file mode 100644
index d5d8cc419b6c..000000000000
--- a/src/amidi-plug/i_utils.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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
-*
-*/
-
-#include "i_utils.h"
-
-#include <stdlib.h>
-#include <gtk/gtk.h>
-#include <audacious/i18n.h>
-
-#include "amidi-plug.logo.xpm"
-
-
-void i_about_gui (void)
-{
-    static GtkWidget * aboutwin = NULL;
-    GtkWidget * logo_image;
-    GdkPixbuf * logo_pixbuf;
-
-    if (aboutwin != NULL)
-        return;
-
-    aboutwin = gtk_dialog_new_with_buttons (_("About AMIDI-Plug"), NULL, 0,
-                                            _("_Close"), GTK_RESPONSE_CLOSE, NULL);
-    gtk_window_set_resizable (GTK_WINDOW (aboutwin), FALSE);
-
-    g_signal_connect (aboutwin, "response", (GCallback) gtk_widget_destroy, NULL);
-    g_signal_connect (G_OBJECT (aboutwin), "destroy", G_CALLBACK (gtk_widget_destroyed), &aboutwin);
-
-    GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) aboutwin);
-
-    logo_pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) amidiplug_xpm_logo);
-    logo_image = gtk_image_new_from_pixbuf (logo_pixbuf);
-    gtk_box_pack_start ((GtkBox *) vbox, logo_image, FALSE, FALSE, 0);
-    g_object_unref (logo_pixbuf);
-
-    char * text = g_strjoin (NULL, _("AMIDI-Plug"),
-                             _("\nmodular MIDI music player\n"
-                                "http://www.develia.org/projects.php?p=amidiplug\n\n"
-                                "written by Giacomo Lozito\n"
-                                "<james at develia.org>\n\n"
-                                "special thanks to...\n\n"
-                                "Clemens Ladisch and Jaroslav Kysela\n"
-                                "for their cool programs aplaymidi and amixer; those\n"
-                                "were really useful, along with alsa-lib docs, in order\n"
-                                "to learn more about the ALSA API\n\n"
-                                "Alfredo Spadafina\n"
-                                "for the nice midi keyboard logo\n\n"
-                                "Tony Vroon\n"
-                                "for the good help with alpha testing"), NULL);
-
-    GtkWidget * label = gtk_label_new (text);
-    gtk_box_pack_start ((GtkBox *) vbox, label, FALSE, FALSE, 0);
-    g_free (text);
-
-    gtk_widget_show_all (aboutwin);
-}
diff --git a/src/amidi-plug/i_utils.h b/src/amidi-plug/i_utils.h
deleted file mode 100644
index 2f206bf0886c..000000000000
--- a/src/amidi-plug/i_utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2006
-*
-* 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 _I_UTILS_H
-#define _I_UTILS_H 1
-
-void i_about_gui (void);
-
-#endif /* !_I_UTILS_H */
diff --git a/src/aosd/Makefile b/src/aosd/Makefile
index 136784634f2d..3a02e6565327 100644
--- a/src/aosd/Makefile
+++ b/src/aosd/Makefile
@@ -1,11 +1,11 @@
 PLUGIN = aosd${PLUGIN_SUFFIX}
 
-SRCS = aosd.c		\
-       aosd_osd.c	\
-       aosd_style.c	\
-       aosd_trigger.c	\
-       aosd_ui.c	\
-       aosd_cfg.c	\
+SRCS = aosd.cc		\
+       aosd_osd.cc	\
+       aosd_style.cc	\
+       aosd_trigger.cc	\
+       aosd_ui.cc	\
+       aosd_cfg.cc	\
        ghosd.c		\
        ghosd-main.c
 
@@ -14,6 +14,8 @@ include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS}  ${GTK_CFLAGS} ${GLIB_CFLAGS} ${XRENDER_CFLAGS} ${XCOMPOSITE_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${XRENDER_LIBS} ${XCOMPOSITE_LIBS} -lm
diff --git a/src/aosd/aosd.c b/src/aosd/aosd.c
deleted file mode 100644
index 03044670b2fe..000000000000
--- a/src/aosd/aosd.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include <audacious/i18n.h>
-
-#include "aosd.h"
-#include "aosd_ui.h"
-#include "aosd_osd.h"
-#include "aosd_cfg.h"
-#include "aosd_trigger.h"
-
-static const char aosd_about[] =
- N_("Audacious OSD\n"
-    "http://www.develia.org/projects.php?p=audacious#aosd\n\n"
-    "Written by Giacomo Lozito <james at develia.org>\n\n"
-    "Based in part on Evan Martin's Ghosd library:\n"
-    "http://neugierig.org/software/ghosd/");
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("AOSD (On-Screen Display)"),
-    .domain = PACKAGE,
-    .about_text = aosd_about,
-    .init = aosd_init,
-    .configure = aosd_configure,
-    .cleanup = aosd_cleanup
-)
-
-aosd_cfg_t * global_config = NULL;
-gboolean plugin_is_active = FALSE;
-
-
-/* ***************** */
-/* plug-in functions */
-
-gboolean aosd_init (void)
-{
-  plugin_is_active = TRUE;
-  g_log_set_handler( NULL , G_LOG_LEVEL_WARNING , g_log_default_handler , NULL );
-
-  global_config = aosd_cfg_new();
-  aosd_cfg_load( global_config );
-
-  aosd_osd_init( global_config->osd->misc.transparency_mode );
-
-  aosd_trigger_start( &global_config->osd->trigger );
-
-  return TRUE;
-}
-
-
-void
-aosd_cleanup ( void )
-{
-  if ( plugin_is_active == TRUE )
-  {
-    aosd_trigger_stop( &global_config->osd->trigger );
-
-    aosd_osd_shutdown();
-    aosd_osd_cleanup();
-
-    if ( global_config != NULL )
-    {
-      aosd_cfg_delete( global_config );
-      global_config = NULL;
-    }
-
-    plugin_is_active = FALSE;
-  }
-}
-
-
-void
-aosd_configure ( void )
-{
-  /* create a new configuration object */
-  aosd_cfg_t *cfg = aosd_cfg_new();
-  /* fill it with information from config file */
-  aosd_cfg_load( cfg );
-  /* call the configuration UI */
-  aosd_ui_configure( cfg );
-  /* delete configuration object */
-  aosd_cfg_delete( cfg );
-}
diff --git a/src/aosd/aosd.cc b/src/aosd/aosd.cc
new file mode 100644
index 000000000000..db49b1fc333e
--- /dev/null
+++ b/src/aosd/aosd.cc
@@ -0,0 +1,59 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#include "aosd.h"
+#include "aosd_osd.h"
+#include "aosd_cfg.h"
+#include "aosd_trigger.h"
+
+EXPORT AOSD aud_plugin_instance;
+
+const char AOSD::about[] =
+ N_("Audacious OSD\n"
+    "http://www.develia.org/projects.php?p=audacious#aosd\n\n"
+    "Written by Giacomo Lozito <james at develia.org>\n\n"
+    "Based in part on Evan Martin's Ghosd library:\n"
+    "http://neugierig.org/software/ghosd/");
+
+aosd_cfg_t global_config = aosd_cfg_t ();
+
+
+/* ***************** */
+/* plug-in functions */
+
+bool AOSD::init ()
+{
+  aosd_cfg_load (global_config);
+  aosd_osd_init (global_config.misc.transparency_mode);
+  aosd_trigger_start (global_config.trigger);
+  return true;
+}
+
+
+void AOSD::cleanup ()
+{
+  aosd_trigger_stop (global_config.trigger);
+  aosd_osd_shutdown ();
+  aosd_osd_cleanup ();
+  global_config = aosd_cfg_t ();
+}
diff --git a/src/aosd/aosd.h b/src/aosd/aosd.h
index 5a60597f845e..f7de153f1a3b 100644
--- a/src/aosd/aosd.h
+++ b/src/aosd/aosd.h
@@ -21,15 +21,29 @@
 #ifndef _I_AOSD_H
 #define _I_AOSD_H 1
 
-#undef PACKAGE
-#define PACKAGE "audacious-plugins"
+#include <libaudcore/plugin.h>
 
-#include "aosd_common.h"
-#include <glib.h>
-#include <audacious/plugin.h>
+struct PreferencesWidget;
 
-gboolean aosd_init (void);
-void aosd_cleanup ( void );
-void aosd_configure ( void );
+class AOSD : public GeneralPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("AOSD (On-Screen Display)"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr AOSD () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
 
 #endif /* !_I_AOSD_H */
diff --git a/src/aosd/aosd_cfg.c b/src/aosd/aosd_cfg.c
deleted file mode 100644
index 0d93f35a8890..000000000000
--- a/src/aosd/aosd_cfg.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include "aosd_cfg.h"
-#include "aosd_style.h"
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-
-static gint
-aosd_cfg_util_str_to_color ( gchar * str , aosd_color_t * color )
-{
-  /* color strings are in format "x,x,x,x", where x are numbers
-     that represent respectively red, green, blue and alpha values (0-65535) */
-  gchar **str_values = g_strsplit( str , "," , 4 );
-  gint col_values[4] = { 0 , 0 , 0, 65535 };
-  gint i = 0;
-  while ( str_values[i] != NULL )
-  {
-    col_values[i] = (gint)strtol( str_values[i] , NULL , 10 );
-    i++;
-  }
-  g_strfreev( str_values );
-  color->red = col_values[0];
-  color->green = col_values[1];
-  color->blue = col_values[2];
-  color->alpha = col_values[3];
-  if ( i < 4 )
-    return -1;
-  else
-    return 0;
-}
-
-
-static gint
-aosd_cfg_util_color_to_str ( aosd_color_t color , gchar ** str )
-{
-  /* color strings are in format "x,x,x,x", where x are numbers
-     that represent respectively red, green, blue and alpha values (0-65535) */
-  *str = g_strdup_printf( "%i,%i,%i,%i" , color.red , color.green , color.blue , color.alpha );
-  if ( *str != NULL )
-    return 0;
-  else
-    return -1;
-}
-
-
-aosd_cfg_t *
-aosd_cfg_new ( void )
-{
-  aosd_cfg_t *cfg = g_malloc0(sizeof(aosd_cfg_t));
-  aosd_cfg_osd_t *cfg_osd = aosd_cfg_osd_new();
-  cfg->set = FALSE;
-  cfg->osd = cfg_osd;
-  return cfg;
-}
-
-
-void
-aosd_cfg_delete ( aosd_cfg_t * cfg )
-{
-  if ( cfg != NULL )
-  {
-    if ( cfg->osd != NULL )
-      aosd_cfg_osd_delete( cfg->osd );
-    g_free( cfg );
-  }
-  return;
-}
-
-
-aosd_cfg_osd_t *
-aosd_cfg_osd_new( void )
-{
-  aosd_cfg_osd_t *cfg_osd = g_malloc0(sizeof(aosd_cfg_osd_t));
-  cfg_osd->decoration.colors = g_array_sized_new( FALSE , TRUE , sizeof(aosd_color_t) ,
-                                                  aosd_deco_style_get_max_numcol() );
-  cfg_osd->trigger.active = g_array_new( FALSE , TRUE , sizeof(gint) );
-  return cfg_osd;
-}
-
-
-void
-aosd_cfg_osd_delete ( aosd_cfg_osd_t * cfg_osd )
-{
-  if ( cfg_osd != NULL )
-  {
-    gint i = 0;
-    /* free configuration fields */
-    for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-      str_unref (cfg_osd->text.fonts_name[i]);
-    if ( cfg_osd->decoration.colors != NULL )
-      g_array_free( cfg_osd->decoration.colors , TRUE );
-    if ( cfg_osd->trigger.active != NULL )
-      g_array_free( cfg_osd->trigger.active , TRUE );
-  }
-  g_free( cfg_osd );
-  return;
-}
-
-
-/* makes a copy of a aosd_cfg_osd_t object (mostly used by aosd_display) */
-aosd_cfg_osd_t *
-aosd_cfg_osd_copy ( aosd_cfg_osd_t * cfg_osd )
-{
-  aosd_cfg_osd_t *cfg_osd_copy = aosd_cfg_osd_new();
-  gint i = 0;
-  /* copy information */
-  cfg_osd_copy->position.placement = cfg_osd->position.placement;
-  cfg_osd_copy->position.offset_x = cfg_osd->position.offset_x;
-  cfg_osd_copy->position.offset_y = cfg_osd->position.offset_y;
-  cfg_osd_copy->position.maxsize_width = cfg_osd->position.maxsize_width;
-  cfg_osd_copy->position.multimon_id = cfg_osd->position.multimon_id;
-  cfg_osd_copy->animation.timing_display = cfg_osd->animation.timing_display;
-  cfg_osd_copy->animation.timing_fadein = cfg_osd->animation.timing_fadein;
-  cfg_osd_copy->animation.timing_fadeout = cfg_osd->animation.timing_fadeout;
-  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-  {
-    cfg_osd_copy->text.fonts_name[i] = str_ref (cfg_osd->text.fonts_name[i]);
-    cfg_osd_copy->text.fonts_color[i] = cfg_osd->text.fonts_color[i];
-    cfg_osd_copy->text.fonts_draw_shadow[i] = cfg_osd->text.fonts_draw_shadow[i];
-    cfg_osd_copy->text.fonts_shadow_color[i] = cfg_osd->text.fonts_shadow_color[i];
-  }
-  cfg_osd_copy->text.utf8conv_disable = cfg_osd->text.utf8conv_disable;
-  cfg_osd_copy->decoration.code = cfg_osd->decoration.code;
-  for ( i = 0 ; i < cfg_osd->decoration.colors->len ; i++ )
-  {
-    aosd_color_t color = g_array_index( cfg_osd->decoration.colors , aosd_color_t , i );
-    g_array_insert_val( cfg_osd_copy->decoration.colors , i , color );
-  }
-  for ( i = 0 ; i < cfg_osd->trigger.active->len ; i++ )
-  {
-    gint trigger_id = g_array_index( cfg_osd->trigger.active , gint , i );
-    g_array_insert_val( cfg_osd_copy->trigger.active , i , trigger_id );
-  }
-  cfg_osd_copy->misc.transparency_mode = cfg_osd->misc.transparency_mode;
-  return cfg_osd_copy;
-}
-
-
-#ifdef DEBUG
-void
-aosd_cfg_debug ( aosd_cfg_t * cfg )
-{
-  gint i = 0;
-  GString *string = g_string_new( "" );
-  g_print("\n***** debug configuration *****\n\n");
-  g_print("POSITION\n");
-  g_print("  placement: %i\n", cfg->osd->position.placement);
-  g_print("  offset x: %i\n", cfg->osd->position.offset_x);
-  g_print("  offset y: %i\n", cfg->osd->position.offset_y);
-  g_print("  max OSD width: %i\n", cfg->osd->position.maxsize_width);
-  g_print("  multi-monitor id: %i\n", cfg->osd->position.multimon_id);
-  g_print("\nANIMATION\n");
-  g_print("  timing display: %i\n", cfg->osd->animation.timing_display);
-  g_print("  timing fade in: %i\n", cfg->osd->animation.timing_fadein);
-  g_print("  timing fade out: %i\n", cfg->osd->animation.timing_fadeout);
-  g_print("\nTEXT\n");
-  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-  {
-    g_print("  font %i: %s\n", i, cfg->osd->text.fonts_name[i]);
-    g_print("  font color %i: %i,%i,%i (alpha %i)\n", i,
-      cfg->osd->text.fonts_color[i].red, cfg->osd->text.fonts_color[i].green,
-      cfg->osd->text.fonts_color[i].blue, cfg->osd->text.fonts_color[i].alpha);
-    g_print("  font %i use shadow: %i\n", i, cfg->osd->text.fonts_draw_shadow[i]);
-    g_print("  font %i shadow color: %i,%i,%i (alpha %i)\n", i,
-      cfg->osd->text.fonts_shadow_color[i].red, cfg->osd->text.fonts_shadow_color[i].green,
-      cfg->osd->text.fonts_shadow_color[i].blue, cfg->osd->text.fonts_shadow_color[i].alpha);
-  }
-  g_print("  disable utf8 conversion: %i\n", cfg->osd->text.utf8conv_disable);
-  g_print("\nDECORATION\n");
-  g_print("  code: %i\n", cfg->osd->decoration.code);
-  for ( i = 0 ; i < cfg->osd->decoration.colors->len ; i++ )
-  {
-    aosd_color_t color = g_array_index( cfg->osd->decoration.colors , aosd_color_t , i );
-    g_print("  color %i: %i,%i,%i (alpha %i)\n", i, color.red, color.green, color.blue, color.alpha);
-  }
-  g_print("\nTRIGGER\n");
-  for ( i = 0 ; i < cfg->osd->trigger.active->len ; i++ )
-    g_string_append_printf( string , "%i," , g_array_index( cfg->osd->trigger.active , gint , i ) );
-  if ( string->len > 1 )
-    g_string_truncate( string , string->len - 1 );
-  g_print("  active: %s\n", string->str);
-  g_string_free( string , TRUE );
-  g_print("\nEXTRA\n");
-  g_print("  set: %i\n", cfg->set);
-  g_print("\n*******************************\n\n");
-  return;
-}
-#endif
-
-static const gchar * const aosd_defaults[] = {
- "position_placement", "1", /* AOSD_POSITION_PLACEMENT_TOPLEFT */
- "position_offset_x", "0",
- "position_offset_y", "0",
- "position_maxsize_width", "0",
- "position_multimon_id", "-1",
- "animation_timing_display", "3000",
- "animation_timing_fadein", "300",
- "animation_timing_fadeout", "300",
- "text_fonts_name_0", "Sans 26",
- "text_fonts_color_0", "65535,65535,65535,65535",
- "text_fonts_draw_shadow_0", "TRUE",
- "text_fonts_shadow_color_0", "0,0,0,32767",
- "text_utf8conv_disable", "FALSE",
- "decoration_code", "0",
- "decoration_color_0", "0,0,65535,32767",
- "decoration_color_1", "65535,65535,65535,65535",
- "trigger_active", "0",
- "transparency_mode", "0",
- NULL};
-
-gint
-aosd_cfg_load ( aosd_cfg_t * cfg )
-{
-  aud_config_set_defaults ("aosd", aosd_defaults);
-
-  gint i = 0;
-  gint max_numcol;
-  gchar *trig_active_str;
-
-  /* position */
-  cfg->osd->position.placement = aud_get_int ("aosd", "position_placement");
-  cfg->osd->position.offset_x = aud_get_int ("aosd", "position_offset_x");
-  cfg->osd->position.offset_y = aud_get_int ("aosd", "position_offset_y");
-  cfg->osd->position.maxsize_width = aud_get_int ("aosd", "position_maxsize_width");
-  cfg->osd->position.multimon_id = aud_get_int ("aosd", "position_multimon_id");
-
-  /* animation */
-  cfg->osd->animation.timing_display = aud_get_int ("aosd", "animation_timing_display");
-  cfg->osd->animation.timing_fadein = aud_get_int ("aosd", "animation_timing_fadein");
-  cfg->osd->animation.timing_fadeout = aud_get_int ("aosd", "animation_timing_fadeout");
-
-  /* text */
-  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-  {
-    gchar *color_str = NULL;
-    gchar key_str[32];
-
-    snprintf (key_str, sizeof key_str, "text_fonts_name_%i" , i );
-    cfg->osd->text.fonts_name[i] = aud_get_str ("aosd", key_str);
-
-    snprintf (key_str, sizeof key_str, "text_fonts_color_%i", i);
-    color_str = aud_get_str ("aosd", key_str);
-    aosd_cfg_util_str_to_color( color_str , &(cfg->osd->text.fonts_color[i]) );
-    str_unref (color_str);
-
-    snprintf (key_str, sizeof key_str, "text_fonts_draw_shadow_%i", i);
-    cfg->osd->text.fonts_draw_shadow[i] = aud_get_bool ("aosd", key_str);
-
-    snprintf (key_str, sizeof key_str, "text_fonts_shadow_color_%i", i);
-    color_str = aud_get_str ("aosd", key_str);
-    aosd_cfg_util_str_to_color( color_str , &(cfg->osd->text.fonts_shadow_color[i]) );
-    str_unref (color_str);
-  }
-
-  cfg->osd->text.utf8conv_disable = aud_get_bool ("aosd", "text_utf8conv_disable");
-
-  /* decoration */
-  cfg->osd->decoration.code = aud_get_int ("aosd", "decoration_code");
-
-  /* decoration - colors */
-  max_numcol = aosd_deco_style_get_max_numcol();
-  for ( i = 0 ; i < max_numcol ; i++ )
-  {
-    gchar key_str[32];
-    gchar *color_str = NULL;
-    aosd_color_t color;
-    snprintf (key_str, sizeof key_str, "decoration_color_%i", i);
-    color_str = aud_get_str ("aosd", key_str);
-    aosd_cfg_util_str_to_color( color_str , &color );
-    str_unref (color_str);
-    g_array_insert_val( cfg->osd->decoration.colors , i , color );
-  }
-
-  /* trigger */
-  trig_active_str = aud_get_str ("aosd", "trigger_active");
-
-  if (strcmp (trig_active_str, "x"))
-  {
-    gchar **trig_active_strv = g_strsplit( trig_active_str , "," , 0 );
-    gint j = 0;
-    while ( trig_active_strv[j] != NULL )
-    {
-      gint trig_active_val = strtol( trig_active_strv[j] , NULL , 10 );
-      g_array_append_val( cfg->osd->trigger.active , trig_active_val );
-      j++;
-    }
-    g_strfreev( trig_active_strv );
-  }
-
-  str_unref (trig_active_str);
-
-  /* miscellanous */
-  cfg->osd->misc.transparency_mode = aud_get_int ("aosd", "transparency_mode");
-
-  /* the config object has been filled with information */
-  cfg->set = TRUE;
-
-  return 0;
-}
-
-
-gint
-aosd_cfg_save ( aosd_cfg_t * cfg )
-{
-  gint i = 0;
-  gint max_numcol;
-  GString *string = g_string_new( "" );
-
-  if ( cfg->set == FALSE )
-    return -1;
-
-  /* position */
-  aud_set_int ("aosd", "position_placement", cfg->osd->position.placement);
-  aud_set_int ("aosd", "position_offset_x", cfg->osd->position.offset_x);
-  aud_set_int ("aosd", "position_offset_y", cfg->osd->position.offset_y);
-  aud_set_int ("aosd", "position_maxsize_width", cfg->osd->position.maxsize_width);
-  aud_set_int ("aosd", "position_multimon_id", cfg->osd->position.multimon_id);
-
-  /* animation */
-  aud_set_int ("aosd", "animation_timing_display", cfg->osd->animation.timing_display);
-  aud_set_int ("aosd", "animation_timing_fadein", cfg->osd->animation.timing_fadein);
-  aud_set_int ("aosd", "animation_timing_fadeout", cfg->osd->animation.timing_fadeout);
-
-  /* text */
-  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-  {
-    gchar *color_str = NULL;
-    gchar key_str[32];
-
-    snprintf (key_str, sizeof key_str, "text_fonts_name_%i", i);
-    aud_set_str ("aosd", key_str, cfg->osd->text.fonts_name[i]);
-
-    snprintf (key_str, sizeof key_str, "text_fonts_color_%i", i);
-    aosd_cfg_util_color_to_str( cfg->osd->text.fonts_color[i] , &color_str );
-    aud_set_str ("aosd", key_str, color_str);
-    g_free( color_str );
-
-    snprintf (key_str, sizeof key_str, "text_fonts_draw_shadow_%i", i);
-    aud_set_bool ("aosd", key_str, cfg->osd->text.fonts_draw_shadow[i]);
-
-    snprintf (key_str, sizeof key_str, "text_fonts_shadow_color_%i", i);
-    aosd_cfg_util_color_to_str( cfg->osd->text.fonts_shadow_color[i] , &color_str );
-    aud_set_str ("aosd", key_str, color_str);
-    g_free( color_str );
-  }
-
-  aud_set_bool ("aosd", "text_utf8conv_disable", cfg->osd->text.utf8conv_disable);
-
-  /* decoration */
-  aud_set_int ("aosd" ,
-    "decoration_code" , cfg->osd->decoration.code );
-
-  /* decoration - colors */
-  max_numcol = aosd_deco_style_get_max_numcol();
-  for ( i = 0 ; i < max_numcol ; i++ )
-  {
-    gchar key_str[32];
-    gchar *color_str = NULL;
-    aosd_color_t color = g_array_index( cfg->osd->decoration.colors , aosd_color_t , i );
-    snprintf (key_str, sizeof key_str, "decoration_color_%i", i);
-    aosd_cfg_util_color_to_str( color , &color_str );
-    aud_set_str ("aosd", key_str, color_str);
-    g_free( color_str );
-  }
-
-  /* trigger */
-  for ( i = 0 ; i < cfg->osd->trigger.active->len ; i++ )
-    g_string_append_printf( string , "%i," , g_array_index( cfg->osd->trigger.active , gint , i ) );
-  if ( string->len > 1 )
-    g_string_truncate( string , string->len - 1 );
-  else
-    g_string_assign( string , "x" );
-  aud_set_str ("aosd", "trigger_active", string->str);
-  g_string_free( string , TRUE );
-
-  /* miscellaneous */
-  aud_set_int ("aosd", "transparency_mode", cfg->osd->misc.transparency_mode);
-
-  return 0;
-}
diff --git a/src/aosd/aosd_cfg.cc b/src/aosd/aosd_cfg.cc
new file mode 100644
index 000000000000..c0e242b1e59d
--- /dev/null
+++ b/src/aosd/aosd_cfg.cc
@@ -0,0 +1,174 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include "aosd_cfg.h"
+#include "aosd_style.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+
+static aosd_color_t str_to_color (const char * str)
+{
+  /* color strings are in format "x,x,x,x", where x are numbers
+     that represent respectively red, green, blue and alpha values (0-65535) */
+  aosd_color_t color = {0, 0, 0, 65535};
+  sscanf (str, "%d,%d,%d,%d", & color.red, & color.green, & color.blue, & color.alpha);
+  return color;
+}
+
+static StringBuf color_to_str (const aosd_color_t & color)
+{
+  /* color strings are in format "x,x,x,x", where x are numbers
+     that represent respectively red, green, blue and alpha values (0-65535) */
+  return str_printf ("%d,%d,%d,%d", color.red, color.green, color.blue, color.alpha);
+}
+
+static const char * const aosd_defaults[] = {
+ "position_placement", "1", /* AOSD_POSITION_PLACEMENT_TOPLEFT */
+ "position_offset_x", "0",
+ "position_offset_y", "0",
+ "position_maxsize_width", "0",
+ "position_multimon_id", "-1",
+ "animation_timing_display", "3000",
+ "animation_timing_fadein", "300",
+ "animation_timing_fadeout", "300",
+ "text_fonts_name_0", "Sans 26",
+ "text_fonts_color_0", "65535,65535,65535,65535",
+ "text_fonts_draw_shadow_0", "TRUE",
+ "text_fonts_shadow_color_0", "0,0,0,32767",
+ "decoration_code", "0",
+ "decoration_color_0", "0,0,65535,32767",
+ "decoration_color_1", "65535,65535,65535,65535",
+ "trigger_enabled", "1,0,0,0",
+ "transparency_mode", "0",
+ nullptr};
+
+void aosd_cfg_load (aosd_cfg_t & cfg)
+{
+  aud_config_set_defaults ("aosd", aosd_defaults);
+
+  /* position */
+  cfg.position.placement = aud_get_int ("aosd", "position_placement");
+  cfg.position.offset_x = aud_get_int ("aosd", "position_offset_x");
+  cfg.position.offset_y = aud_get_int ("aosd", "position_offset_y");
+  cfg.position.maxsize_width = aud_get_int ("aosd", "position_maxsize_width");
+  cfg.position.multimon_id = aud_get_int ("aosd", "position_multimon_id");
+
+  /* animation */
+  cfg.animation.timing_display = aud_get_int ("aosd", "animation_timing_display");
+  cfg.animation.timing_fadein = aud_get_int ("aosd", "animation_timing_fadein");
+  cfg.animation.timing_fadeout = aud_get_int ("aosd", "animation_timing_fadeout");
+
+  /* text */
+  for (int i = 0; i < AOSD_TEXT_FONTS_NUM; i ++)
+  {
+    char key_str[32];
+
+    snprintf (key_str, sizeof key_str, "text_fonts_name_%i" , i );
+    cfg.text.fonts_name[i] = aud_get_str ("aosd", key_str);
+
+    snprintf (key_str, sizeof key_str, "text_fonts_color_%i", i);
+    cfg.text.fonts_color[i] = str_to_color (aud_get_str ("aosd", key_str));
+
+    snprintf (key_str, sizeof key_str, "text_fonts_draw_shadow_%i", i);
+    cfg.text.fonts_draw_shadow[i] = aud_get_bool ("aosd", key_str);
+
+    snprintf (key_str, sizeof key_str, "text_fonts_shadow_color_%i", i);
+    cfg.text.fonts_shadow_color[i] = str_to_color (aud_get_str ("aosd", key_str));
+  }
+
+  /* decoration */
+  cfg.decoration.code = aud_get_int ("aosd", "decoration_code");
+
+  /* decoration - colors */
+  for (int i = 0; i < AOSD_DECO_STYLE_MAX_COLORS; i ++)
+  {
+    char key_str[32];
+    snprintf (key_str, sizeof key_str, "decoration_color_%i", i);
+    cfg.decoration.colors[i] = str_to_color (aud_get_str ("aosd", key_str));
+  }
+
+  /* trigger */
+  String trig_enabled_str = aud_get_str ("aosd", "trigger_enabled");
+  str_to_int_array (trig_enabled_str, cfg.trigger.enabled,
+   aud::n_elems (cfg.trigger.enabled));
+
+  /* miscellanous */
+  cfg.misc.transparency_mode = aud_get_int ("aosd", "transparency_mode");
+}
+
+
+void aosd_cfg_save (const aosd_cfg_t & cfg)
+{
+  /* position */
+  aud_set_int ("aosd", "position_placement", cfg.position.placement);
+  aud_set_int ("aosd", "position_offset_x", cfg.position.offset_x);
+  aud_set_int ("aosd", "position_offset_y", cfg.position.offset_y);
+  aud_set_int ("aosd", "position_maxsize_width", cfg.position.maxsize_width);
+  aud_set_int ("aosd", "position_multimon_id", cfg.position.multimon_id);
+
+  /* animation */
+  aud_set_int ("aosd", "animation_timing_display", cfg.animation.timing_display);
+  aud_set_int ("aosd", "animation_timing_fadein", cfg.animation.timing_fadein);
+  aud_set_int ("aosd", "animation_timing_fadeout", cfg.animation.timing_fadeout);
+
+  /* text */
+  for (int i = 0; i < AOSD_TEXT_FONTS_NUM; i ++)
+  {
+    char key_str[32];
+
+    snprintf (key_str, sizeof key_str, "text_fonts_name_%i", i);
+    aud_set_str ("aosd", key_str, cfg.text.fonts_name[i]);
+
+    snprintf (key_str, sizeof key_str, "text_fonts_color_%i", i);
+    aud_set_str ("aosd", key_str, color_to_str (cfg.text.fonts_color[i]));
+
+    snprintf (key_str, sizeof key_str, "text_fonts_draw_shadow_%i", i);
+    aud_set_bool ("aosd", key_str, cfg.text.fonts_draw_shadow[i]);
+
+    snprintf (key_str, sizeof key_str, "text_fonts_shadow_color_%i", i);
+    aud_set_str ("aosd", key_str, color_to_str (cfg.text.fonts_shadow_color[i]));
+  }
+
+  /* decoration */
+  aud_set_int ("aosd" ,
+    "decoration_code" , cfg.decoration.code );
+
+  /* decoration - colors */
+  for (int i = 0; i < AOSD_DECO_STYLE_MAX_COLORS; i ++)
+  {
+    char key_str[32];
+    snprintf (key_str, sizeof key_str, "decoration_color_%i", i);
+    aud_set_str ("aosd", key_str, color_to_str (cfg.decoration.colors[i]));
+  }
+
+  /* trigger */
+  StringBuf trig_enabled_str = int_array_to_str (cfg.trigger.enabled,
+   aud::n_elems (cfg.trigger.enabled));
+  aud_set_str ("aosd", "trigger_enabled", trig_enabled_str);
+
+  /* miscellaneous */
+  aud_set_int ("aosd", "transparency_mode", cfg.misc.transparency_mode);
+}
diff --git a/src/aosd/aosd_cfg.h b/src/aosd/aosd_cfg.h
index 20b0c97a3360..a1c6623bd73a 100644
--- a/src/aosd/aosd_cfg.h
+++ b/src/aosd/aosd_cfg.h
@@ -21,8 +21,7 @@
 #ifndef _I_AOSD_CFG_H
 #define _I_AOSD_CFG_H 1
 
-#include "aosd_common.h"
-#include <glib.h>
+#include <libaudcore/objects.h>
 
 /* in this release only one user font is supported */
 #define AOSD_TEXT_FONTS_NUM 1
@@ -31,6 +30,16 @@
 #define AOSD_MISC_TRANSPARENCY_FAKE 0
 #define AOSD_MISC_TRANSPARENCY_REAL 1
 
+#define AOSD_DECO_STYLE_MAX_COLORS 2
+
+enum
+{
+  AOSD_DECO_STYLE_RECT,
+  AOSD_DECO_STYLE_ROUNDRECT,
+  AOSD_DECO_STYLE_CONCAVERECT,
+  AOSD_DECO_STYLE_NONE,
+  AOSD_NUM_DECO_STYLES
+};
 
 enum
 {
@@ -45,13 +54,21 @@ enum
   AOSD_POSITION_PLACEMENT_BOTTOMRIGHT
 };
 
+enum
+{
+  AOSD_TRIGGER_PB_START = 0,
+  AOSD_TRIGGER_PB_TITLECHANGE,
+  AOSD_TRIGGER_PB_PAUSEON,
+  AOSD_TRIGGER_PB_PAUSEOFF,
+  AOSD_NUM_TRIGGERS
+};
 
 typedef struct
 {
-  guint16 red;
-  guint16 green;
-  guint16 blue;
-  guint16 alpha;
+  int red;
+  int green;
+  int blue;
+  int alpha;
 }
 aosd_color_t;
 
@@ -59,8 +76,8 @@ aosd_color_t;
 /* config portion containing osd decoration information */
 typedef struct
 {
-  gint code;
-  GArray *colors;
+  int code;
+  aosd_color_t colors[AOSD_DECO_STYLE_MAX_COLORS];
 }
 aosd_cfg_osd_decoration_t;
 
@@ -68,11 +85,10 @@ aosd_cfg_osd_decoration_t;
 /* config portion containing osd text information */
 typedef struct
 {
-  gchar *fonts_name[AOSD_TEXT_FONTS_NUM]; /* pooled */
+  String fonts_name[AOSD_TEXT_FONTS_NUM];
   aosd_color_t fonts_color[AOSD_TEXT_FONTS_NUM];
-  gboolean fonts_draw_shadow[AOSD_TEXT_FONTS_NUM];
+  bool fonts_draw_shadow[AOSD_TEXT_FONTS_NUM];
   aosd_color_t fonts_shadow_color[AOSD_TEXT_FONTS_NUM];
-  gboolean utf8conv_disable;
 }
 aosd_cfg_osd_text_t;
 
@@ -80,9 +96,9 @@ aosd_cfg_osd_text_t;
 /* config portion containing osd animation information */
 typedef struct
 {
-  gint timing_display;
-  gint timing_fadein;
-  gint timing_fadeout;
+  int timing_display;
+  int timing_fadein;
+  int timing_fadeout;
 }
 aosd_cfg_osd_animation_t;
 
@@ -90,11 +106,11 @@ aosd_cfg_osd_animation_t;
 /* config portion containing osd position information */
 typedef struct
 {
-  gint placement;
-  gint offset_x;
-  gint offset_y;
-  gint maxsize_width;
-  gint multimon_id;
+  int placement;
+  int offset_x;
+  int offset_y;
+  int maxsize_width;
+  int multimon_id;
 }
 aosd_cfg_osd_position_t;
 
@@ -102,7 +118,7 @@ aosd_cfg_osd_position_t;
 /* config portion containing osd trigger information */
 typedef struct
 {
-  GArray *active;
+  int enabled[AOSD_NUM_TRIGGERS];
 }
 aosd_cfg_osd_trigger_t;
 
@@ -110,7 +126,7 @@ aosd_cfg_osd_trigger_t;
 /* config portion containing osd miscellaneous information */
 typedef struct
 {
-  gint transparency_mode;
+  int transparency_mode;
 }
 aosd_cfg_osd_misc_t;
 
@@ -125,26 +141,13 @@ typedef struct
   aosd_cfg_osd_trigger_t trigger;
   aosd_cfg_osd_misc_t misc;
 }
-aosd_cfg_osd_t;
-
-
-/* config portion containing all config information */
-typedef struct
-{
-  gboolean set;
-
-  aosd_cfg_osd_t * osd;
-}
 aosd_cfg_t;
 
 
 /* API */
-aosd_cfg_t * aosd_cfg_new ( void );
-void aosd_cfg_delete ( aosd_cfg_t * cfg );
-aosd_cfg_osd_t * aosd_cfg_osd_new( void );
-void aosd_cfg_osd_delete ( aosd_cfg_osd_t * cfg_osd );
-aosd_cfg_osd_t * aosd_cfg_osd_copy ( aosd_cfg_osd_t * cfg_osd );
-gint aosd_cfg_load ( aosd_cfg_t * cfg );
-gint aosd_cfg_save ( aosd_cfg_t * cfg );
+void aosd_cfg_load (aosd_cfg_t & cfg);
+void aosd_cfg_save (const aosd_cfg_t & cfg);
+
+extern aosd_cfg_t global_config;
 
 #endif /* !_I_AOSD_CFG_H */
diff --git a/src/aosd/aosd_common.h b/src/aosd/aosd_common.h
deleted file mode 100644
index 4147068c1f67..000000000000
--- a/src/aosd/aosd_common.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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 _I_AOSD_COMMON_H
-#define _I_AOSD_COMMON_H 1
-
-#ifdef DEBUG
-#include <stdio.h>
-#define DEBUGMSG(...) { fprintf(stderr, "statusicon(%s:%s:%d): ", __FILE__, __FUNCTION__, (int) __LINE__); fprintf(stderr, __VA_ARGS__); }
-#else
-#define DEBUGMSG(...)
-#endif /* DEBUG */
-
-#define AOSD_VERSION_PLUGIN "0.1beta5"
-
-#endif /* !_I_AOSD_COMMON_H */
diff --git a/src/aosd/aosd_osd.c b/src/aosd/aosd_osd.c
deleted file mode 100644
index 173bf658b59d..000000000000
--- a/src/aosd/aosd_osd.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include "aosd_osd.h"
-#include "aosd_style.h"
-#include "aosd_style_private.h"
-#include "aosd_cfg.h"
-#include <glib.h>
-#include <X11/Xlib.h>
-#include <cairo/cairo.h>
-#include <pango/pangocairo.h>
-#include <gdk/gdk.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include "ghosd.h"
-
-
-#define AOSD_STATUS_HIDDEN       0
-#define AOSD_STATUS_FADEIN       1
-#define AOSD_STATUS_SHOW         2
-#define AOSD_STATUS_FADEOUT      3
-#define AOSD_STATUS_DESTROY      4
-/* updating OSD every 50 msec */
-#define AOSD_TIMING              50
-
-
-typedef struct
-{
-  cairo_surface_t * surface;
-  gfloat alpha;
-  gpointer user_data;
-  gint width;
-  gint height;
-  gint deco_code;
-}
-GhosdFadeData;
-
-
-typedef struct
-{
-  gchar * markup_message;
-  gboolean cfg_is_copied;
-  gfloat dalpha_in, dalpha_out, ddisplay_stay;
-
-  PangoContext *pango_context;
-  PangoLayout *pango_layout;
-
-  aosd_cfg_osd_t * cfg_osd;
-
-  GhosdFadeData fade_data;
-}
-GhosdData;
-
-
-static gint osd_source_id = 0;
-static gint osd_status = AOSD_STATUS_HIDDEN;
-static Ghosd *osd;
-static GhosdData *osd_data;
-
-
-static void
-aosd_osd_data_alloc ( gchar * markup_string , aosd_cfg_osd_t * cfg_osd , gboolean copy_cfg )
-{
-  osd_data = g_malloc0(sizeof(GhosdData));
-  osd_data->markup_message = g_strdup( markup_string );
-  if ( copy_cfg == TRUE )
-  {
-    osd_data->cfg_osd = aosd_cfg_osd_copy( cfg_osd );
-    osd_data->cfg_is_copied = TRUE;
-  }
-  else
-  {
-    osd_data->cfg_osd = cfg_osd;
-    osd_data->cfg_is_copied = FALSE;
-  }
-  return;
-}
-
-
-static void
-aosd_osd_data_free ( void )
-{
-  if ( osd_data->fade_data.surface != NULL )
-  {
-    cairo_surface_destroy( osd_data->fade_data.surface );
-    osd_data->fade_data.surface = NULL;
-  }
-
-  if ( osd_data->markup_message != NULL )
-  {
-    g_free( osd_data->markup_message );
-    osd_data->markup_message = NULL;
-  }
-
-  if ( osd_data->cfg_is_copied == TRUE )
-  {
-    aosd_cfg_osd_delete( osd_data->cfg_osd );
-    osd_data->cfg_osd = NULL;
-  }
-
-  if ( osd_data->pango_layout != NULL )
-  {
-    g_object_unref( osd_data->pango_layout );
-    osd_data->pango_layout = NULL;
-  }
-
-  if ( osd_data->pango_context != NULL )
-  {
-    g_object_unref( osd_data->pango_context );
-    osd_data->pango_context = NULL;
-  }
-
-  g_free( osd_data );
-}
-
-
-static void
-aosd_osd_hide ( void )
-{
-  if ( osd != NULL )
-  {
-    ghosd_hide( osd );
-    ghosd_main_iterations( osd );
-  }
-  return;
-}
-
-
-static void
-aosd_fade_func ( Ghosd * gosd , cairo_t * cr , void * user_data )
-{
-  GhosdFadeData *fade_data = user_data;
-
-  if ( fade_data->surface == NULL )
-  {
-    cairo_t *rendered_cr;
-    fade_data->surface = cairo_surface_create_similar( cairo_get_target( cr ) ,
-                           CAIRO_CONTENT_COLOR_ALPHA , fade_data->width , fade_data->height );
-    rendered_cr = cairo_create( fade_data->surface );
-    aosd_deco_style_render( fade_data->deco_code , gosd , rendered_cr , fade_data->user_data );
-    cairo_destroy( rendered_cr );
-  }
-
-  cairo_set_source_surface( cr , fade_data->surface , 0 , 0 );
-  cairo_paint_with_alpha( cr , fade_data->alpha );
-}
-
-
-static void
-aosd_button_func ( Ghosd * gosd , GhosdEventButton * ev , void * user_data )
-{
-  if ( ev->button == 1 )
-  {
-    osd_status = AOSD_STATUS_DESTROY; /* move to status destroy */
-  }
-  return;
-}
-
-
-static void
-aosd_osd_create ( void )
-{
-  gint max_width, layout_width, layout_height;
-  PangoRectangle ink, log;
-  GdkScreen *screen = gdk_screen_get_default();
-  gint pos_x = 0, pos_y = 0;
-  gint pad_left = 0 , pad_right = 0 , pad_top = 0 , pad_bottom = 0;
-  gint screen_width, screen_height;
-  aosd_deco_style_data_t style_data;
-
-  /* calculate screen_width and screen_height */
-  if ( osd_data->cfg_osd->position.multimon_id > -1 )
-  {
-    /* adjust coordinates and size according to selected monitor */
-    GdkRectangle rect;
-    gdk_screen_get_monitor_geometry( screen , osd_data->cfg_osd->position.multimon_id , &rect );
-    pos_x = rect.x;
-    pos_y = rect.y;
-    screen_width = rect.width;
-    screen_height = rect.height;
-  }
-  else
-  {
-    /* use total space available, even when composed by multiple monitor */
-    screen_width = gdk_screen_get_width( screen );
-    screen_height = gdk_screen_get_height( screen );
-    pos_x = 0;
-    pos_y = 0;
-  }
-
-  /* pick padding from selected decoration style */
-  aosd_deco_style_get_padding( osd_data->cfg_osd->decoration.code ,
-    &pad_top , &pad_bottom , &pad_left , &pad_right );
-
-  if ( osd_data->cfg_osd->position.maxsize_width > 0 )
-  {
-    gint max_width_default = screen_width - pad_left - pad_right - abs(osd_data->cfg_osd->position.offset_x);
-    max_width = osd_data->cfg_osd->position.maxsize_width - pad_left - pad_right;
-    /* ignore user-defined max_width if it is too small or too large */
-    if (( max_width < 1 ) || ( max_width > max_width_default ))
-      max_width = max_width_default;
-  }
-  else
-  {
-    max_width = screen_width - pad_left - pad_right - abs(osd_data->cfg_osd->position.offset_x);
-  }
-
-  osd_data->pango_context = pango_font_map_create_context
-   (pango_cairo_font_map_get_default ());
-  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_width( osd_data->pango_layout , PANGO_SCALE * max_width );
-  pango_layout_get_pixel_extents( osd_data->pango_layout , &ink , &log );
-  layout_width = ink.width;
-  layout_height = log.height;
-
-  /* osd position */
-  switch ( osd_data->cfg_osd->position.placement )
-  {
-    case AOSD_POSITION_PLACEMENT_TOP:
-      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
-      pos_y += 0;
-      break;
-    case AOSD_POSITION_PLACEMENT_TOPRIGHT:
-      pos_x += screen_width - (layout_width + pad_left + pad_right);
-      pos_y += 0;
-      break;
-    case AOSD_POSITION_PLACEMENT_MIDDLELEFT:
-      pos_x += 0;
-      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
-      break;
-    case AOSD_POSITION_PLACEMENT_MIDDLE:
-      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
-      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
-      break;
-    case AOSD_POSITION_PLACEMENT_MIDDLERIGHT:
-      pos_x += screen_width - (layout_width + pad_left + pad_right);
-      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
-      break;
-    case AOSD_POSITION_PLACEMENT_BOTTOMLEFT:
-      pos_x += 0;
-      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
-      break;
-    case AOSD_POSITION_PLACEMENT_BOTTOM:
-      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
-      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
-      break;
-    case AOSD_POSITION_PLACEMENT_BOTTOMRIGHT:
-      pos_x += screen_width - (layout_width + pad_left + pad_right);
-      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
-      break;
-    case AOSD_POSITION_PLACEMENT_TOPLEFT:
-    default:
-      pos_x += 0;
-      pos_y += 0;
-      break;
-  }
-
-  /* add offset to position */
-  pos_x += osd_data->cfg_osd->position.offset_x;
-  pos_y += osd_data->cfg_osd->position.offset_y;
-
-  ghosd_set_position( osd , pos_x , pos_y ,
-    layout_width + pad_left + pad_right ,
-    layout_height + pad_top + pad_bottom );
-
-  ghosd_set_event_button_cb( osd , aosd_button_func , NULL );
-
-  style_data.layout = osd_data->pango_layout;
-  style_data.text = &(osd_data->cfg_osd->text);
-  style_data.decoration = &(osd_data->cfg_osd->decoration);
-  osd_data->fade_data.surface = NULL;
-  osd_data->fade_data.user_data = &style_data;
-  osd_data->fade_data.width = layout_width + pad_left + pad_right;
-  osd_data->fade_data.height = layout_height + pad_top + pad_bottom;
-  osd_data->fade_data.alpha = 0;
-  osd_data->fade_data.deco_code = osd_data->cfg_osd->decoration.code;
-  osd_data->dalpha_in = 1.0 / ( osd_data->cfg_osd->animation.timing_fadein / (gfloat)AOSD_TIMING );
-  osd_data->dalpha_out = 1.0 / ( osd_data->cfg_osd->animation.timing_fadeout / (gfloat)AOSD_TIMING );
-  osd_data->ddisplay_stay = 1.0 / ( osd_data->cfg_osd->animation.timing_display / (gfloat)AOSD_TIMING );
-  ghosd_set_render( osd , (GhosdRenderFunc)aosd_fade_func , &(osd_data->fade_data) , NULL );
-
-  /* show the osd (with alpha 0, invisible) */
-  ghosd_show( osd );
-  return;
-}
-
-
-static gboolean
-aosd_timer_func ( gpointer none )
-{
-  static gfloat display_time = 0;
-
-  switch ( osd_status )
-  {
-    case AOSD_STATUS_FADEIN:
-    {
-      /* fade in */
-      osd_data->fade_data.alpha += osd_data->dalpha_in;
-      if ( osd_data->fade_data.alpha < 1.0 )
-      {
-        ghosd_render( osd );
-        ghosd_main_iterations( osd );
-      }
-      else
-      {
-        osd_data->fade_data.alpha = 1.0;
-        display_time = 0;
-        osd_status = AOSD_STATUS_SHOW; /* move to next phase */
-        ghosd_render( osd );
-        ghosd_main_iterations( osd );
-      }
-      return TRUE;
-    }
-
-    case AOSD_STATUS_SHOW:
-    {
-      display_time += osd_data->ddisplay_stay;
-      if ( display_time >= 1.0 )
-      {
-        osd_status = AOSD_STATUS_FADEOUT; /* move to next phase */
-        ghosd_main_iterations( osd );
-      }
-      else
-      {
-        ghosd_main_iterations( osd );
-      }
-      return TRUE;
-    }
-
-    case AOSD_STATUS_FADEOUT:
-    {
-      /* fade out */
-      osd_data->fade_data.alpha -= osd_data->dalpha_out;
-      if ( osd_data->fade_data.alpha > 0.0 )
-      {
-        ghosd_render( osd );
-        ghosd_main_iterations( osd );
-      }
-      else
-      {
-        osd_data->fade_data.alpha = 0.0;
-        osd_status = AOSD_STATUS_DESTROY; /* move to next phase */
-        ghosd_render( osd );
-        ghosd_main_iterations( osd );
-      }
-      return TRUE;
-    }
-
-    case AOSD_STATUS_DESTROY:
-    {
-      aosd_osd_hide();
-      aosd_osd_data_free();
-
-      osd_status = AOSD_STATUS_HIDDEN; /* reset status */
-      osd_source_id = 0;
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-
-gint
-aosd_osd_display ( gchar * markup_string , aosd_cfg_osd_t * cfg_osd , gboolean copy_cfg )
-{
-  if ( osd != NULL )
-  {
-    if ( osd_status == AOSD_STATUS_HIDDEN )
-    {
-      aosd_osd_data_alloc( markup_string , cfg_osd , copy_cfg );
-      aosd_osd_create();
-      osd_status = AOSD_STATUS_FADEIN;
-      osd_source_id = g_timeout_add_full( G_PRIORITY_DEFAULT_IDLE , AOSD_TIMING ,
-                                          aosd_timer_func , NULL , NULL );
-    }
-    else
-    {
-      g_source_remove( osd_source_id ); /* remove timer */
-      osd_source_id = 0;
-      aosd_osd_hide();
-      aosd_osd_data_free();
-      osd_status = AOSD_STATUS_HIDDEN;
-      /* now display new OSD */
-      aosd_osd_data_alloc( markup_string , cfg_osd , copy_cfg );
-      aosd_osd_create();
-      osd_status = AOSD_STATUS_FADEIN;
-      osd_source_id = g_timeout_add_full( G_PRIORITY_DEFAULT_IDLE , AOSD_TIMING ,
-                                          aosd_timer_func , NULL , NULL );
-    }
-    return 0;
-  }
-  else
-  {
-    g_warning( "OSD display requested, but no osd object is loaded!\n" );
-  }
-  return 1;
-}
-
-
-void
-aosd_osd_shutdown ( void )
-{
-  if ( osd != NULL )
-  {
-    if ( osd_status != AOSD_STATUS_HIDDEN ) /* osd is being displayed */
-    {
-      g_source_remove( osd_source_id ); /* remove timer */
-      osd_source_id = 0;
-      aosd_osd_hide();
-      aosd_osd_data_free();
-      osd_status = AOSD_STATUS_HIDDEN;
-    }
-  }
-  else
-  {
-    g_warning( "OSD shutdown requested, but no osd object is loaded!\n" );
-  }
-  return;
-}
-
-
-void
-aosd_osd_init ( gint transparency_mode )
-{
-  if ( osd == NULL )
-  {
-    /* create Ghosd object */
-    if ( transparency_mode == AOSD_MISC_TRANSPARENCY_FAKE )
-      osd = ghosd_new();
-    else
-#ifdef HAVE_XCOMPOSITE
-    {
-      /* check if the composite module is actually loaded */
-      if ( aosd_osd_check_composite_ext() )
-        osd = ghosd_new_with_argbvisual(); /* ok */
-      else
-      {
-        g_warning( "X Composite module not loaded; falling back to fake transparency.\n");
-        osd = ghosd_new(); /* fall back to fake transparency */
-      }
-    }
-#else
-      osd = ghosd_new();
-#endif
-
-    if ( osd == NULL )
-      g_warning( "Unable to load osd object; OSD will not work properly!\n" );
-  }
-  return;
-}
-
-
-void
-aosd_osd_cleanup ( void )
-{
-  if ( osd != NULL )
-  {
-    /* destroy Ghosd object */
-    ghosd_destroy( osd );
-    osd = NULL;
-  }
-  return;
-}
-
-#ifdef HAVE_XCOMPOSITE
-int
-aosd_osd_check_composite_ext ( void )
-{
-  return ghosd_check_composite_ext();
-}
-
-int
-aosd_osd_check_composite_mgr ( void )
-{
-  /* ghosd_check_composite_mgr() only checks for composite managers that
-     adhere to the Extended Window Manager hint specification ver.1.4 from
-     freedesktop ( where composite manager are identified with the hint
-     _NET_WM_CM_Sn ); unfortunately, non-standard comp.managers and older
-     ones (xcompmgr) do not use this hint; so let's also check if xcompmgr
-     is running before reporting a likely absence of running comp.managers */
-  int have_comp_mgr = ghosd_check_composite_mgr();
-
-  if ( have_comp_mgr != 0 )
-  {
-    DEBUGMSG("running composite manager found\n");
-    return have_comp_mgr;
-  }
-  else
-  {
-    /* check if xcompmgr is running; assumes there's a working 'ps'
-       utility in the system; not the most elegant of the checking
-       systems, but this is more than enough for its purpose */
-    gchar *soutput = NULL, *serror = NULL;
-    gint exit_status;
-
-    if ( g_spawn_command_line_sync( "ps -eo comm" ,
-           &soutput , &serror , &exit_status , NULL ) == TRUE )
-    {
-      if (( soutput != NULL ) && ( strstr( soutput , "\nxcompmgr\n" ) != NULL ))
-      {
-        DEBUGMSG("running xcompmgr found\n");
-        have_comp_mgr = 1;
-      }
-      else
-      {
-        DEBUGMSG("running xcompmgr not found\n");
-        have_comp_mgr = 0;
-      }
-    }
-    else
-    {
-      g_warning("command 'ps -eo comm' failed, unable to check if xcompgr is running\n");
-      have_comp_mgr = 0;
-    }
-
-    g_free( soutput );
-    g_free( serror );
-    return have_comp_mgr;
-  }
-}
-#endif
diff --git a/src/aosd/aosd_osd.cc b/src/aosd/aosd_osd.cc
new file mode 100644
index 000000000000..88eea0695d42
--- /dev/null
+++ b/src/aosd/aosd_osd.cc
@@ -0,0 +1,509 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include "aosd_osd.h"
+#include "aosd_style.h"
+#include "aosd_style_private.h"
+#include "aosd_cfg.h"
+
+#include <X11/Xlib.h>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <libaudcore/runtime.h>
+
+#include "ghosd.h"
+
+
+#define AOSD_STATUS_HIDDEN       0
+#define AOSD_STATUS_FADEIN       1
+#define AOSD_STATUS_SHOW         2
+#define AOSD_STATUS_FADEOUT      3
+#define AOSD_STATUS_DESTROY      4
+/* updating OSD every 50 msec */
+#define AOSD_TIMING              50
+
+
+struct GhosdFadeData
+{
+  cairo_surface_t * surface = nullptr;
+  float alpha = 0.0;
+  void * user_data = nullptr;
+  int width = 0;
+  int height = 0;
+  int deco_code = 0;
+
+  ~GhosdFadeData ()
+  {
+    if (surface)
+      cairo_surface_destroy (surface);
+  }
+};
+
+
+struct GhosdData
+{
+  String markup_message;
+  bool cfg_is_copied = false;
+  float dalpha_in = 0.0, dalpha_out = 0.0, ddisplay_stay = 0.0;
+
+  PangoContext *pango_context = nullptr;
+  PangoLayout *pango_layout = nullptr;
+
+  aosd_cfg_t *cfg_osd = nullptr;
+
+  GhosdFadeData fade_data;
+
+  GhosdData (const char * markup_string, aosd_cfg_t * cfg_osd, bool copy_cfg) :
+    markup_message (markup_string),
+    cfg_is_copied (copy_cfg),
+    cfg_osd (copy_cfg ? new aosd_cfg_t (* cfg_osd) : cfg_osd) {}
+
+  ~GhosdData ()
+  {
+    if (pango_layout)
+      g_object_unref (pango_layout);
+    if (pango_context)
+      g_object_unref (pango_context);
+    if (cfg_is_copied)
+      delete cfg_osd;
+  }
+};
+
+
+static int osd_source_id = 0;
+static int osd_status = AOSD_STATUS_HIDDEN;
+static Ghosd *osd;
+static SmartPtr<GhosdData> osd_data;
+
+
+static void
+aosd_osd_hide ( void )
+{
+  if ( osd != nullptr )
+  {
+    ghosd_hide( osd );
+    ghosd_main_iterations( osd );
+  }
+  return;
+}
+
+
+static void
+aosd_fade_func ( Ghosd * gosd , cairo_t * cr , void * user_data )
+{
+  GhosdFadeData *fade_data = (GhosdFadeData *) user_data;
+
+  if ( fade_data->surface == nullptr )
+  {
+    cairo_t *rendered_cr;
+    fade_data->surface = cairo_surface_create_similar( cairo_get_target( cr ) ,
+                           CAIRO_CONTENT_COLOR_ALPHA , fade_data->width , fade_data->height );
+    rendered_cr = cairo_create( fade_data->surface );
+    aosd_deco_style_render( fade_data->deco_code , gosd , rendered_cr , fade_data->user_data );
+    cairo_destroy( rendered_cr );
+  }
+
+  cairo_set_source_surface( cr , fade_data->surface , 0 , 0 );
+  cairo_paint_with_alpha( cr , fade_data->alpha );
+}
+
+
+static void
+aosd_button_func ( Ghosd * gosd , GhosdEventButton * ev , void * user_data )
+{
+  if ( ev->button == 1 )
+  {
+    osd_status = AOSD_STATUS_DESTROY; /* move to status destroy */
+  }
+  return;
+}
+
+
+static void
+aosd_osd_create ( void )
+{
+  int max_width, layout_width, layout_height;
+  PangoRectangle ink, log;
+  GdkScreen *screen = gdk_screen_get_default();
+  int pos_x = 0, pos_y = 0;
+  int pad_left = 0 , pad_right = 0 , pad_top = 0 , pad_bottom = 0;
+  int screen_width, screen_height;
+  aosd_deco_style_data_t style_data;
+
+  /* calculate screen_width and screen_height */
+  if ( osd_data->cfg_osd->position.multimon_id > -1 )
+  {
+    /* adjust coordinates and size according to selected monitor */
+    GdkRectangle rect;
+    gdk_screen_get_monitor_geometry( screen , osd_data->cfg_osd->position.multimon_id , &rect );
+    pos_x = rect.x;
+    pos_y = rect.y;
+    screen_width = rect.width;
+    screen_height = rect.height;
+  }
+  else
+  {
+    /* use total space available, even when composed by multiple monitor */
+    screen_width = gdk_screen_get_width( screen );
+    screen_height = gdk_screen_get_height( screen );
+    pos_x = 0;
+    pos_y = 0;
+  }
+
+  /* pick padding from selected decoration style */
+  aosd_deco_style_get_padding( osd_data->cfg_osd->decoration.code ,
+    &pad_top , &pad_bottom , &pad_left , &pad_right );
+
+  if ( osd_data->cfg_osd->position.maxsize_width > 0 )
+  {
+    int max_width_default = screen_width - pad_left - pad_right - abs(osd_data->cfg_osd->position.offset_x);
+    max_width = osd_data->cfg_osd->position.maxsize_width - pad_left - pad_right;
+    /* ignore user-defined max_width if it is too small or too large */
+    if (( max_width < 1 ) || ( max_width > max_width_default ))
+      max_width = max_width_default;
+  }
+  else
+  {
+    max_width = screen_width - pad_left - pad_right - abs(osd_data->cfg_osd->position.offset_x);
+  }
+
+  osd_data->pango_context = pango_font_map_create_context
+   (pango_cairo_font_map_get_default ());
+  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_width( osd_data->pango_layout , PANGO_SCALE * max_width );
+  pango_layout_get_pixel_extents( osd_data->pango_layout , &ink , &log );
+  layout_width = ink.width;
+  layout_height = log.height;
+
+  /* osd position */
+  switch ( osd_data->cfg_osd->position.placement )
+  {
+    case AOSD_POSITION_PLACEMENT_TOP:
+      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
+      pos_y += 0;
+      break;
+    case AOSD_POSITION_PLACEMENT_TOPRIGHT:
+      pos_x += screen_width - (layout_width + pad_left + pad_right);
+      pos_y += 0;
+      break;
+    case AOSD_POSITION_PLACEMENT_MIDDLELEFT:
+      pos_x += 0;
+      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
+      break;
+    case AOSD_POSITION_PLACEMENT_MIDDLE:
+      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
+      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
+      break;
+    case AOSD_POSITION_PLACEMENT_MIDDLERIGHT:
+      pos_x += screen_width - (layout_width + pad_left + pad_right);
+      pos_y += (screen_height - (layout_height + pad_top + pad_bottom)) / 2;
+      break;
+    case AOSD_POSITION_PLACEMENT_BOTTOMLEFT:
+      pos_x += 0;
+      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
+      break;
+    case AOSD_POSITION_PLACEMENT_BOTTOM:
+      pos_x += (screen_width - (layout_width + pad_left + pad_right)) / 2;
+      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
+      break;
+    case AOSD_POSITION_PLACEMENT_BOTTOMRIGHT:
+      pos_x += screen_width - (layout_width + pad_left + pad_right);
+      pos_y += screen_height - (layout_height + pad_top + pad_bottom);
+      break;
+    case AOSD_POSITION_PLACEMENT_TOPLEFT:
+    default:
+      pos_x += 0;
+      pos_y += 0;
+      break;
+  }
+
+  /* add offset to position */
+  pos_x += osd_data->cfg_osd->position.offset_x;
+  pos_y += osd_data->cfg_osd->position.offset_y;
+
+  ghosd_set_position( osd , pos_x , pos_y ,
+    layout_width + pad_left + pad_right ,
+    layout_height + pad_top + pad_bottom );
+
+  ghosd_set_event_button_cb( osd , aosd_button_func , nullptr );
+
+  style_data.layout = osd_data->pango_layout;
+  style_data.text = &(osd_data->cfg_osd->text);
+  style_data.decoration = &(osd_data->cfg_osd->decoration);
+  osd_data->fade_data.surface = nullptr;
+  osd_data->fade_data.user_data = &style_data;
+  osd_data->fade_data.width = layout_width + pad_left + pad_right;
+  osd_data->fade_data.height = layout_height + pad_top + pad_bottom;
+  osd_data->fade_data.alpha = 0;
+  osd_data->fade_data.deco_code = osd_data->cfg_osd->decoration.code;
+  osd_data->dalpha_in = 1.0 / ( osd_data->cfg_osd->animation.timing_fadein / (float)AOSD_TIMING );
+  osd_data->dalpha_out = 1.0 / ( osd_data->cfg_osd->animation.timing_fadeout / (float)AOSD_TIMING );
+  osd_data->ddisplay_stay = 1.0 / ( osd_data->cfg_osd->animation.timing_display / (float)AOSD_TIMING );
+  ghosd_set_render( osd , (GhosdRenderFunc)aosd_fade_func , &(osd_data->fade_data) , nullptr );
+
+  /* show the osd (with alpha 0, invisible) */
+  ghosd_show( osd );
+  return;
+}
+
+
+static gboolean
+aosd_timer_func ( void * none )
+{
+  static float display_time = 0;
+
+  switch ( osd_status )
+  {
+    case AOSD_STATUS_FADEIN:
+    {
+      /* fade in */
+      osd_data->fade_data.alpha += osd_data->dalpha_in;
+      if ( osd_data->fade_data.alpha < 1.0 )
+      {
+        ghosd_render( osd );
+        ghosd_main_iterations( osd );
+      }
+      else
+      {
+        osd_data->fade_data.alpha = 1.0;
+        display_time = 0;
+        osd_status = AOSD_STATUS_SHOW; /* move to next phase */
+        ghosd_render( osd );
+        ghosd_main_iterations( osd );
+      }
+      return TRUE;
+    }
+
+    case AOSD_STATUS_SHOW:
+    {
+      display_time += osd_data->ddisplay_stay;
+      if ( display_time >= 1.0 )
+      {
+        osd_status = AOSD_STATUS_FADEOUT; /* move to next phase */
+        ghosd_main_iterations( osd );
+      }
+      else
+      {
+        ghosd_main_iterations( osd );
+      }
+      return TRUE;
+    }
+
+    case AOSD_STATUS_FADEOUT:
+    {
+      /* fade out */
+      osd_data->fade_data.alpha -= osd_data->dalpha_out;
+      if ( osd_data->fade_data.alpha > 0.0 )
+      {
+        ghosd_render( osd );
+        ghosd_main_iterations( osd );
+      }
+      else
+      {
+        osd_data->fade_data.alpha = 0.0;
+        osd_status = AOSD_STATUS_DESTROY; /* move to next phase */
+        ghosd_render( osd );
+        ghosd_main_iterations( osd );
+      }
+      return TRUE;
+    }
+
+    case AOSD_STATUS_DESTROY:
+    {
+      aosd_osd_hide();
+      osd_data.clear();
+
+      osd_status = AOSD_STATUS_HIDDEN; /* reset status */
+      osd_source_id = 0;
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+
+int
+aosd_osd_display ( char * markup_string , aosd_cfg_t * cfg_osd , bool copy_cfg )
+{
+  if ( osd != nullptr )
+  {
+    if ( osd_status == AOSD_STATUS_HIDDEN )
+    {
+      osd_data.capture( new GhosdData( markup_string , cfg_osd , copy_cfg ) );
+      aosd_osd_create();
+      osd_status = AOSD_STATUS_FADEIN;
+      osd_source_id = g_timeout_add_full( G_PRIORITY_DEFAULT_IDLE , AOSD_TIMING ,
+                                          aosd_timer_func , nullptr , nullptr );
+    }
+    else
+    {
+      g_source_remove( osd_source_id ); /* remove timer */
+      osd_source_id = 0;
+      aosd_osd_hide();
+      osd_data.clear();
+      osd_status = AOSD_STATUS_HIDDEN;
+      /* now display new OSD */
+      osd_data.capture( new GhosdData( markup_string , cfg_osd , copy_cfg ) );
+      aosd_osd_create();
+      osd_status = AOSD_STATUS_FADEIN;
+      osd_source_id = g_timeout_add_full( G_PRIORITY_DEFAULT_IDLE , AOSD_TIMING ,
+                                          aosd_timer_func , nullptr , nullptr );
+    }
+    return 0;
+  }
+  else
+  {
+    g_warning( "OSD display requested, but no osd object is loaded!\n" );
+  }
+  return 1;
+}
+
+
+void
+aosd_osd_shutdown ( void )
+{
+  if ( osd != nullptr )
+  {
+    if ( osd_status != AOSD_STATUS_HIDDEN ) /* osd is being displayed */
+    {
+      g_source_remove( osd_source_id ); /* remove timer */
+      osd_source_id = 0;
+      aosd_osd_hide();
+      osd_data.clear();
+      osd_status = AOSD_STATUS_HIDDEN;
+    }
+  }
+  else
+  {
+    g_warning( "OSD shutdown requested, but no osd object is loaded!\n" );
+  }
+  return;
+}
+
+
+void
+aosd_osd_init ( int transparency_mode )
+{
+  if ( osd == nullptr )
+  {
+    /* create Ghosd object */
+    if ( transparency_mode == AOSD_MISC_TRANSPARENCY_FAKE )
+      osd = ghosd_new();
+    else
+#ifdef HAVE_XCOMPOSITE
+    {
+      /* check if the composite module is actually loaded */
+      if ( aosd_osd_check_composite_ext() )
+        osd = ghosd_new_with_argbvisual(); /* ok */
+      else
+      {
+        g_warning( "X Composite module not loaded; falling back to fake transparency.\n");
+        osd = ghosd_new(); /* fall back to fake transparency */
+      }
+    }
+#else
+      osd = ghosd_new();
+#endif
+
+    if ( osd == nullptr )
+      g_warning( "Unable to load osd object; OSD will not work properly!\n" );
+  }
+  return;
+}
+
+
+void
+aosd_osd_cleanup ( void )
+{
+  if ( osd != nullptr )
+  {
+    /* destroy Ghosd object */
+    ghosd_destroy( osd );
+    osd = nullptr;
+  }
+  return;
+}
+
+#ifdef HAVE_XCOMPOSITE
+int
+aosd_osd_check_composite_ext ( void )
+{
+  return ghosd_check_composite_ext();
+}
+
+int
+aosd_osd_check_composite_mgr ( void )
+{
+  /* ghosd_check_composite_mgr() only checks for composite managers that
+     adhere to the Extended Window Manager hint specification ver.1.4 from
+     freedesktop ( where composite manager are identified with the hint
+     _NET_WM_CM_Sn ); unfortunately, non-standard comp.managers and older
+     ones (xcompmgr) do not use this hint; so let's also check if xcompmgr
+     is running before reporting a likely absence of running comp.managers */
+  int have_comp_mgr = ghosd_check_composite_mgr();
+
+  if ( have_comp_mgr != 0 )
+  {
+    AUDDBG("running composite manager found\n");
+    return have_comp_mgr;
+  }
+  else
+  {
+    /* check if xcompmgr is running; assumes there's a working 'ps'
+       utility in the system; not the most elegant of the checking
+       systems, but this is more than enough for its purpose */
+    char *soutput = nullptr, *serror = nullptr;
+    int exit_status;
+
+    if ( g_spawn_command_line_sync( "ps -eo comm" ,
+           &soutput , &serror , &exit_status , nullptr ) == TRUE )
+    {
+      if (( soutput != nullptr ) && ( strstr( soutput , "\nxcompmgr\n" ) != nullptr ))
+      {
+        AUDDBG("running xcompmgr found\n");
+        have_comp_mgr = 1;
+      }
+      else
+      {
+        AUDDBG("running xcompmgr not found\n");
+        have_comp_mgr = 0;
+      }
+    }
+    else
+    {
+      g_warning("command 'ps -eo comm' failed, unable to check if xcompgr is running\n");
+      have_comp_mgr = 0;
+    }
+
+    g_free( soutput );
+    g_free( serror );
+    return have_comp_mgr;
+  }
+}
+#endif
diff --git a/src/aosd/aosd_osd.h b/src/aosd/aosd_osd.h
index 25bc63a79c26..bd0cfdf1760a 100644
--- a/src/aosd/aosd_osd.h
+++ b/src/aosd/aosd_osd.h
@@ -21,14 +21,11 @@
 #ifndef _I_AOSD_OSD_H
 #define _I_AOSD_OSD_H 1
 
-#include "aosd_common.h"
 #include "aosd_cfg.h"
-#include <glib.h>
 
-
-gint aosd_osd_display ( gchar * markup_string , aosd_cfg_osd_t * cfg_osd , gboolean copy_cfg );
+int aosd_osd_display ( char * markup_string , aosd_cfg_t * cfg_osd , bool copy_cfg );
 void aosd_osd_shutdown ( void );
-void aosd_osd_init ( gint transparency_mode ); /* to be called before any OSD usage */
+void aosd_osd_init ( int transparency_mode ); /* to be called before any OSD usage */
 void aosd_osd_cleanup ( void ); /* to be called when done with OSD usage */
 
 #ifdef HAVE_XCOMPOSITE
diff --git a/src/aosd/aosd_style.c b/src/aosd/aosd_style.c
deleted file mode 100644
index 326ca1db31f5..000000000000
--- a/src/aosd/aosd_style.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include "aosd_style.h"
-#include "aosd_style_private.h"
-#include "aosd_cfg.h"
-#include <glib.h>
-#include <audacious/i18n.h>
-#include <X11/Xlib.h>
-#include <cairo/cairo.h>
-#include <pango/pangocairo.h>
-#include "ghosd.h"
-
-
-/* HOW TO ADD A NEW DECORATION STYLE
-   --------------------------------------------------------------------------
-   First, add a new decoration style code; then, provide the decoration style
-   information by adding a new entry in the aosd_deco_styles[] array (name,
-   render function, etc.); add the new decoration style code in the array
-   of decoration style codes, and update the define containing the array size.
-   The render function uses three parameters; the Ghosd instance, the cairo
-   object you use to draw, and a aosd_deco_style_data_t object that contains
-   user-defined options (look into aosd_style.h and aosd_cfg.h for details).
-   Have fun! :)
-*/
-
-
-/* decoration style codes ( the code values do not need to be sequential ) */
-enum
-{
-  AOSD_DECO_STYLE_RECT = 0,
-  AOSD_DECO_STYLE_ROUNDRECT = 1,
-  AOSD_DECO_STYLE_CONCAVERECT = 2,
-  AOSD_DECO_STYLE_NONE
-};
-
-/* decoration style codes array size */
-#define AOSD_DECO_STYLE_CODES_ARRAY_SIZE 4
-
-/* decoration style codes array */
-gint aosd_deco_style_codes[] =
-{
-  AOSD_DECO_STYLE_RECT,
-  AOSD_DECO_STYLE_ROUNDRECT,
-  AOSD_DECO_STYLE_CONCAVERECT,
-  AOSD_DECO_STYLE_NONE
-};
-
-/* prototypes of render functions */
-static void aosd_deco_rfunc_rect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
-static void aosd_deco_rfunc_roundrect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
-static void aosd_deco_rfunc_concaverect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
-static void aosd_deco_rfunc_none ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
-
-/* map decoration style codes to decoration objects */
-aosd_deco_style_t aosd_deco_styles[] =
-{
-  [AOSD_DECO_STYLE_RECT] = { N_("Rectangle") ,
-                             aosd_deco_rfunc_rect ,
-                             2 , { 10 , 10 , 10 , 10 } },
-
-  [AOSD_DECO_STYLE_ROUNDRECT] = { N_("Rounded Rectangle") ,
-                                  aosd_deco_rfunc_roundrect ,
-                                  2 , { 10 , 10 , 10 , 10 } },
-
-  [AOSD_DECO_STYLE_CONCAVERECT] = { N_("Concave Rectangle") ,
-                                    aosd_deco_rfunc_concaverect ,
-                                    2 , { 10 , 10 , 10 , 10 } },
-
-  [AOSD_DECO_STYLE_NONE] = { N_("None") ,
-                             aosd_deco_rfunc_none ,
-                             0 , { 2 , 2 , 2 , 2 } }
-};
-
-
-
-/* DECORATION STYLE API */
-
-
-void
-aosd_deco_style_get_codes_array ( gint ** array , gint * array_size )
-{
-  *array = aosd_deco_style_codes;
-  *array_size = AOSD_DECO_STYLE_CODES_ARRAY_SIZE;
-  return;
-}
-
-
-void
-aosd_deco_style_get_padding ( gint deco_code ,
-                              gint * ptop , gint * pbottom ,
-                              gint * pleft , gint * pright )
-{
-  if ( ptop != NULL ) *ptop = aosd_deco_styles[deco_code].padding.top;
-  if ( pbottom != NULL ) *pbottom = aosd_deco_styles[deco_code].padding.bottom;
-  if ( pleft != NULL ) *pleft = aosd_deco_styles[deco_code].padding.left;
-  if ( pright != NULL ) *pright = aosd_deco_styles[deco_code].padding.right;
-  return;
-}
-
-
-const gchar *
-aosd_deco_style_get_desc ( gint deco_code )
-{
-  return aosd_deco_styles[deco_code].desc;
-}
-
-
-gint
-aosd_deco_style_get_numcol ( gint deco_code )
-{
-  return aosd_deco_styles[deco_code].colors_num;
-}
-
-
-void
-aosd_deco_style_render ( gint deco_code , gpointer ghosd , gpointer cr , gpointer user_data )
-{
-  aosd_deco_styles[deco_code].render_func( (Ghosd*)ghosd , (cairo_t*)cr , user_data );
-}
-
-
-gint
-aosd_deco_style_get_first_code ( void )
-{
-  return AOSD_DECO_STYLE_RECT;
-}
-
-
-gint
-aosd_deco_style_get_max_numcol ( void )
-{
-  gint i = 0;
-  gint max_numcol = 0;
-
-  for ( i = 0 ; i < AOSD_DECO_STYLE_CODES_ARRAY_SIZE ; i++ )
-  {
-    gint numcol = aosd_deco_style_get_numcol( aosd_deco_style_codes[i] );
-    if ( numcol > max_numcol )
-      max_numcol = numcol;
-  }
-
-  return max_numcol;
-}
-
-
-// sizing helper
-static void
-aosd_layout_size( PangoLayout * layout , gint * width , gint * height , gint * bearing )
-{
-  PangoRectangle ink, log;
-
-  pango_layout_get_pixel_extents( layout , &ink , &log );
-
-  if ( width != NULL )
-    *width = ink.width;
-  if ( height != NULL )
-    *height = log.height;
-  if ( bearing != NULL )
-    *bearing = -ink.x;
-}
-
-
-/* RENDER FUNCTIONS */
-
-static void
-aosd_deco_rfunc_rect( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
-{
-  /* decoration information
-     ----------------------
-     draws a simple rectangular decoration; uses 2 colors
-     (user color 1 and 2) and 1 font (user font 1), with optional shadow
-  */
-  PangoLayout *osd_layout = data->layout;
-  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
-  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
-  aosd_color_t textcolor0 = data->text->fonts_color[0];
-  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
-  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0, bearing = 0;
-
-  aosd_layout_size( osd_layout , &width , &height , &bearing );
-
-  /* draw rectangle container */
-  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
-    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
-  cairo_rectangle( cr , 0 , 0 ,
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + width +
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.right,
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + height +
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.bottom );
-  cairo_fill_preserve( cr );
-  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
-    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
-  cairo_stroke( cr );
-
-  if ( draw_shadow == TRUE )
-  {
-    /* draw text shadow */
-    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
-      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
-    cairo_move_to( cr,
-      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing + 2 ,
-      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + 2 );
-    pango_cairo_show_layout( cr , osd_layout );
-  }
-
-  /* draw text */
-  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
-    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
-  cairo_move_to( cr,
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing ,
-    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top );
-  pango_cairo_show_layout( cr , osd_layout );
-}
-
-
-static void
-aosd_deco_rfunc_roundrect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
-{
-  /* decoration information
-     ----------------------
-     draws a rectangular decoration with rounded angles; uses 2 colors
-     (user color 1 and 2) and 1 font (user font 1), with optional shadow
-  */
-  PangoLayout *osd_layout = data->layout;
-  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
-  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
-  aosd_color_t textcolor0 = data->text->fonts_color[0];
-  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
-  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0, bearing = 0;
-
-  aosd_layout_size( osd_layout , &width , &height , &bearing );
-
-  /* draw rounded-rectangle container */
-  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
-    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
-  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left , 0 );
-  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
-    10. , -G_PI_2 , 0. );
-  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
-    10. , -4. * G_PI_2 , -3. * G_PI_2 );
-  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
-    10. , -3. * G_PI_2 , -2. * G_PI_2 );
-  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
-    10. , -2. * G_PI_2 , -G_PI_2 );
-  cairo_close_path( cr );
-  cairo_fill_preserve( cr );
-  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
-    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
-  cairo_stroke( cr );
-
-  if ( draw_shadow == TRUE )
-  {
-    /* draw text shadow */
-    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
-      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
-    cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing + 2 ,
-      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + 2 );
-    pango_cairo_show_layout( cr , osd_layout );
-  }
-
-  /* draw text */
-  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
-    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
-  cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing ,
-    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top );
-  pango_cairo_show_layout( cr , osd_layout );
-}
-
-
-static void
-aosd_deco_rfunc_concaverect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
-{
-  /* decoration information
-     ----------------------
-     draws a rectangle with concave angles; uses 2 colors
-     (user color 1 and 2) and 1 font (user font 1), with optional shadow
-  */
-  PangoLayout *osd_layout = data->layout;
-  aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
-  aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
-  aosd_color_t textcolor0 = data->text->fonts_color[0];
-  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
-  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0, bearing = 0;
-
-  aosd_layout_size( osd_layout , &width , &height , &bearing );
-
-  /* draw jigsaw-piece-like container */
-  cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
-    (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
-  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left , 0 );
-  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
-    8. , -G_PI_2 , 0. );
-  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
-    8. , -4. * G_PI_2 , -3. * G_PI_2 );
-  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
-    8. , -3. * G_PI_2 , -2. * G_PI_2 );
-  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
-    8. , -2. * G_PI_2 , -G_PI_2 );
-  cairo_close_path( cr );
-  cairo_fill_preserve( cr );
-  cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
-    (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
-  cairo_stroke( cr );
-
-  if ( draw_shadow == TRUE )
-  {
-    /* draw text shadow */
-    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
-      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
-    cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing + 2 ,
-      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + 2 );
-    pango_cairo_show_layout( cr , osd_layout );
-  }
-
-  /* draw text */
-  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
-    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
-  cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing ,
-    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top );
-  pango_cairo_show_layout( cr , osd_layout );
-}
-
-
-static void
-aosd_deco_rfunc_none ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
-{
-  /* decoration information
-     ----------------------
-     does not draw any decoration around text; uses 0 colors
-     and 1 font (user font 1), with optional shadow
-  */
-  PangoLayout *osd_layout = data->layout;
-  aosd_color_t textcolor0 = data->text->fonts_color[0];
-  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
-  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
-  gint width = 0, height = 0, bearing = 0;
-
-  aosd_layout_size( osd_layout , &width , &height , &bearing );
-
-  if ( draw_shadow == TRUE )
-  {
-    /* draw text shadow */
-    cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
-      (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
-    cairo_move_to( cr ,
-      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing + 2 ,
-      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top + 2 );
-    pango_cairo_show_layout( cr , osd_layout );
-  }
-
-  /* draw text */
-  cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
-    (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
-  cairo_move_to( cr ,
-    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing ,
-    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top );
-  pango_cairo_show_layout( cr , osd_layout );
-}
diff --git a/src/aosd/aosd_style.cc b/src/aosd/aosd_style.cc
new file mode 100644
index 000000000000..9cd855b4273b
--- /dev/null
+++ b/src/aosd/aosd_style.cc
@@ -0,0 +1,341 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include "aosd_style.h"
+#include "aosd_style_private.h"
+#include "aosd_cfg.h"
+
+#include <libaudcore/i18n.h>
+#include <X11/Xlib.h>
+#include <cairo/cairo.h>
+#include <pango/pangocairo.h>
+#include "ghosd.h"
+
+
+/* HOW TO ADD A NEW DECORATION STYLE
+   --------------------------------------------------------------------------
+   First, add a new decoration style code; then, provide the decoration style
+   information by adding a new entry in the aosd_deco_styles[] array (name,
+   render function, etc.); add the new decoration style code in the array
+   of decoration style codes, and update the define containing the array size.
+   The render function uses three parameters; the Ghosd instance, the cairo
+   object you use to draw, and a aosd_deco_style_data_t object that contains
+   user-defined options (look into aosd_style.h and aosd_cfg.h for details).
+   Have fun! :)
+*/
+
+/* prototypes of render functions */
+static void aosd_deco_rfunc_rect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+static void aosd_deco_rfunc_roundrect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+static void aosd_deco_rfunc_concaverect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+static void aosd_deco_rfunc_none ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
+
+/* map decoration style codes to decoration objects */
+aosd_deco_style_t aosd_deco_styles[] =
+{
+  // AOSD_DECO_STYLE_RECT
+  { N_("Rectangle") ,
+    aosd_deco_rfunc_rect ,
+    2 , { 10 , 10 , 10 , 10 } },
+
+  // AOSD_DECO_STYLE_ROUNDRECT
+  { N_("Rounded Rectangle") ,
+    aosd_deco_rfunc_roundrect ,
+    2 , { 10 , 10 , 10 , 10 } },
+
+  // AOSD_DECO_STYLE_CONCAVERECT
+  { N_("Concave Rectangle") ,
+    aosd_deco_rfunc_concaverect ,
+    2 , { 10 , 10 , 10 , 10 } },
+
+  // AOSD_DECO_STYLE_NONE
+  { N_("None") ,
+    aosd_deco_rfunc_none ,
+    0 , { 2 , 2 , 2 , 2 } }
+};
+
+static_assert (aud::n_elems (aosd_deco_styles) == AOSD_NUM_DECO_STYLES, "update aosd_deco_styles");
+
+
+/* DECORATION STYLE API */
+
+void
+aosd_deco_style_get_padding ( int deco_code ,
+                              int * ptop , int * pbottom ,
+                              int * pleft , int * pright )
+{
+  if ( ptop != nullptr ) *ptop = aosd_deco_styles[deco_code].padding.top;
+  if ( pbottom != nullptr ) *pbottom = aosd_deco_styles[deco_code].padding.bottom;
+  if ( pleft != nullptr ) *pleft = aosd_deco_styles[deco_code].padding.left;
+  if ( pright != nullptr ) *pright = aosd_deco_styles[deco_code].padding.right;
+  return;
+}
+
+
+const char *
+aosd_deco_style_get_desc ( int deco_code )
+{
+  return aosd_deco_styles[deco_code].desc;
+}
+
+
+int
+aosd_deco_style_get_numcol ( int deco_code )
+{
+  return aosd_deco_styles[deco_code].colors_num;
+}
+
+
+void
+aosd_deco_style_render ( int deco_code , void * ghosd , void * cr , void * user_data )
+{
+  aosd_deco_styles[deco_code].render_func ((Ghosd *) ghosd, (cairo_t *) cr,
+   (aosd_deco_style_data_t *) user_data);
+}
+
+
+// sizing helper
+static void
+aosd_layout_size( PangoLayout * layout , int * width , int * height , int * bearing )
+{
+  PangoRectangle ink, log;
+
+  pango_layout_get_pixel_extents( layout , &ink , &log );
+
+  if ( width != nullptr )
+    *width = ink.width;
+  if ( height != nullptr )
+    *height = log.height;
+  if ( bearing != nullptr )
+    *bearing = -ink.x;
+}
+
+
+/* RENDER FUNCTIONS */
+
+static void
+aosd_deco_rfunc_rect( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a simple rectangular decoration; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = data->decoration->colors[0];
+  aosd_color_t color1 = data->decoration->colors[1];
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  int width = 0, height = 0, bearing = 0;
+
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
+
+  /* draw rectangle container */
+  cairo_set_source_rgba( cr , (double)color0.red / 65535 , (double)color0.green / 65535 ,
+    (double)color0.blue / 65535 , (double)color0.alpha / 65535 );
+  cairo_rectangle( cr , 0 , 0 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + width +
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.right,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + height +
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.bottom );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (double)color1.red / 65535 , (double)color1.green / 65535 ,
+    (double)color1.blue / 65535 , (double)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 ,
+      (double)shadowcolor0.blue / 65535 , (double)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr,
+      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (double)textcolor0.red / 65535 , (double)textcolor0.green / 65535 ,
+    (double)textcolor0.blue / 65535 , (double)textcolor0.alpha / 65535 );
+  cairo_move_to( cr,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + bearing ,
+    aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
+
+
+static void
+aosd_deco_rfunc_roundrect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a rectangular decoration with rounded angles; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = data->decoration->colors[0];
+  aosd_color_t color1 = data->decoration->colors[1];
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  int width = 0, height = 0, bearing = 0;
+
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
+
+  /* draw rounded-rectangle container */
+  cairo_set_source_rgba( cr , (double)color0.red / 65535 , (double)color0.green / 65535 ,
+    (double)color0.blue / 65535 , (double)color0.alpha / 65535 );
+  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left , 0 );
+  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
+    10. , -G_PI_2 , 0. );
+  cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
+    10. , -4. * G_PI_2 , -3. * G_PI_2 );
+  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
+    10. , -3. * G_PI_2 , -2. * G_PI_2 );
+  cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
+    10. , -2. * G_PI_2 , -G_PI_2 );
+  cairo_close_path( cr );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (double)color1.red / 65535 , (double)color1.green / 65535 ,
+    (double)color1.blue / 65535 , (double)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 ,
+      (double)shadowcolor0.blue / 65535 , (double)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr ,
+      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (double)textcolor0.red / 65535 , (double)textcolor0.green / 65535 ,
+    (double)textcolor0.blue / 65535 , (double)textcolor0.alpha / 65535 );
+  cairo_move_to( cr ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + bearing ,
+    aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
+
+
+static void
+aosd_deco_rfunc_concaverect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     draws a rectangle with concave angles; uses 2 colors
+     (user color 1 and 2) and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t color0 = data->decoration->colors[0];
+  aosd_color_t color1 = data->decoration->colors[1];
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  int width = 0, height = 0, bearing = 0;
+
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
+
+  /* draw jigsaw-piece-like container */
+  cairo_set_source_rgba( cr , (double)color0.red / 65535 , (double)color0.green / 65535 ,
+    (double)color0.blue / 65535 , (double)color0.alpha / 65535 );
+  cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left , 0 );
+  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
+    8. , -G_PI_2 , 0. );
+  cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
+    8. , -4. * G_PI_2 , -3. * G_PI_2 );
+  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
+    8. , -3. * G_PI_2 , -2. * G_PI_2 );
+  cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
+    8. , -2. * G_PI_2 , -G_PI_2 );
+  cairo_close_path( cr );
+  cairo_fill_preserve( cr );
+  cairo_set_source_rgba( cr , (double)color1.red / 65535 , (double)color1.green / 65535 ,
+    (double)color1.blue / 65535 , (double)color1.alpha / 65535 );
+  cairo_stroke( cr );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 ,
+      (double)shadowcolor0.blue / 65535 , (double)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr ,
+      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (double)textcolor0.red / 65535 , (double)textcolor0.green / 65535 ,
+    (double)textcolor0.blue / 65535 , (double)textcolor0.alpha / 65535 );
+  cairo_move_to( cr ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + bearing ,
+    aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
+
+
+static void
+aosd_deco_rfunc_none ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
+{
+  /* decoration information
+     ----------------------
+     does not draw any decoration around text; uses 0 colors
+     and 1 font (user font 1), with optional shadow
+  */
+  PangoLayout *osd_layout = data->layout;
+  aosd_color_t textcolor0 = data->text->fonts_color[0];
+  aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
+  gboolean draw_shadow = data->text->fonts_draw_shadow[0];
+  int width = 0, height = 0, bearing = 0;
+
+  aosd_layout_size( osd_layout , &width , &height , &bearing );
+
+  if ( draw_shadow == TRUE )
+  {
+    /* draw text shadow */
+    cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 ,
+      (double)shadowcolor0.blue / 65535 , (double)shadowcolor0.alpha / 65535 );
+    cairo_move_to( cr ,
+      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing + 2 ,
+      aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top + 2 );
+    pango_cairo_show_layout( cr , osd_layout );
+  }
+
+  /* draw text */
+  cairo_set_source_rgba( cr , (double)textcolor0.red / 65535 , (double)textcolor0.green / 65535 ,
+    (double)textcolor0.blue / 65535 , (double)textcolor0.alpha / 65535 );
+  cairo_move_to( cr ,
+    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.left + bearing ,
+    aosd_deco_styles[AOSD_DECO_STYLE_NONE].padding.top );
+  pango_cairo_show_layout( cr , osd_layout );
+}
diff --git a/src/aosd/aosd_style.h b/src/aosd/aosd_style.h
index 2ba603a5d70e..7ac2db7ea9d0 100644
--- a/src/aosd/aosd_style.h
+++ b/src/aosd/aosd_style.h
@@ -21,22 +21,10 @@
 #ifndef _I_AOSD_STYLE_H
 #define _I_AOSD_STYLE_H 1
 
-#undef PACKAGE
-#define PACKAGE "audacious-plugins"
-
-#include "aosd_common.h"
-#include <glib.h>
-
-
 /* decoration style public API */
-void aosd_deco_style_get_codes_array ( gint ** , gint * );
-void aosd_deco_style_get_padding ( gint , gint * , gint * , gint * , gint * );
-const gchar * aosd_deco_style_get_desc ( gint );
-gint aosd_deco_style_get_numcol ( gint );
-void aosd_deco_style_render ( gint , gpointer , gpointer , gpointer ); /* opaque */
-
-gint aosd_deco_style_get_first_code ( void );
-gint aosd_deco_style_get_max_numcol ( void );
-
+void aosd_deco_style_get_padding ( int , int * , int * , int * , int * );
+const char * aosd_deco_style_get_desc ( int );
+int aosd_deco_style_get_numcol ( int );
+void aosd_deco_style_render ( int , void * , void * , void * ); /* opaque */
 
 #endif /* !_I_AOSD_STYLE_H */
diff --git a/src/aosd/aosd_style_private.h b/src/aosd/aosd_style_private.h
index 94d73ec576f9..935e7c40a32d 100644
--- a/src/aosd/aosd_style_private.h
+++ b/src/aosd/aosd_style_private.h
@@ -21,9 +21,7 @@
 #ifndef _I_AOSD_STYLE_PRIVATE_H
 #define _I_AOSD_STYLE_PRIVATE_H 1
 
-#include "aosd_common.h"
 #include "aosd_cfg.h"
-#include <glib.h>
 #include <cairo/cairo.h>
 #include <pango/pangocairo.h>
 #include "ghosd.h"
@@ -48,24 +46,23 @@ aosd_deco_style_data_t;
    ----------------------------------------------------------
    desc           description
    render_func    render function used to draw the decoration
-   colors_num     number of user-definable colors
+   colors_num     number of user-definable colors (no more than AOSD_DECO_STYLE_MAX_COLORS)
    padding        drawable space available around the text
 */
 typedef struct
 {
-  const gchar * desc;
+  const char * desc;
   void (*render_func)( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
-  gint colors_num;
+  int colors_num;
   struct
   {
-    gint top;
-    gint bottom;
-    gint left;
-    gint right;
+    int top;
+    int bottom;
+    int left;
+    int right;
   }
   padding;
 }
 aosd_deco_style_t;
 
-
 #endif /* !_I_AOSD_STYLE_PRIVATE_H */
diff --git a/src/aosd/aosd_trigger.c b/src/aosd/aosd_trigger.c
deleted file mode 100644
index 8d3a28e3ec4b..000000000000
--- a/src/aosd/aosd_trigger.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include <glib.h>
-#include <string.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-
-#include "aosd_trigger.h"
-#include "aosd_trigger_private.h"
-#include "aosd_cfg.h"
-#include "aosd_osd.h"
-
-extern aosd_cfg_t * global_config;
-
-
-/* trigger codes ( the code values do not need to be sequential ) */
-enum
-{
-  AOSD_TRIGGER_PB_START = 0,
-  AOSD_TRIGGER_PB_TITLECHANGE = 1,
-  AOSD_TRIGGER_PB_PAUSEON = 2,
-  AOSD_TRIGGER_PB_PAUSEOFF = 3
-};
-
-/* trigger codes array size */
-#define AOSD_TRIGGER_CODES_ARRAY_SIZE 4
-
-/* trigger codes array */
-gint aosd_trigger_codes[] =
-{
-  AOSD_TRIGGER_PB_START,
-  AOSD_TRIGGER_PB_TITLECHANGE,
-  AOSD_TRIGGER_PB_PAUSEON,
-  AOSD_TRIGGER_PB_PAUSEOFF
-};
-
-/* prototypes of trigger functions */
-static void aosd_trigger_func_pb_start_onoff ( gboolean );
-static void aosd_trigger_func_pb_start_cb ( gpointer , gpointer );
-static void aosd_trigger_func_pb_titlechange_onoff ( gboolean );
-static void aosd_trigger_func_pb_titlechange_cb ( gpointer , gpointer );
-static void aosd_trigger_func_pb_pauseon_onoff ( gboolean );
-static void aosd_trigger_func_pb_pauseon_cb ( gpointer , gpointer );
-static void aosd_trigger_func_pb_pauseoff_onoff ( gboolean );
-static void aosd_trigger_func_pb_pauseoff_cb ( gpointer , gpointer );
-static void aosd_trigger_func_hook_cb ( gpointer markup_text , gpointer unused );
-
-/* map trigger codes to trigger objects */
-aosd_trigger_t aosd_triggers[] =
-{
-  [AOSD_TRIGGER_PB_START] = { N_("Playback Start") ,
-                              N_("Triggers OSD when a playlist entry is played.") ,
-                              aosd_trigger_func_pb_start_onoff ,
-                              aosd_trigger_func_pb_start_cb },
-
-  [AOSD_TRIGGER_PB_TITLECHANGE] = { N_("Title Change") ,
-                                    N_("Triggers OSD when, during playback, the song title changes "
-                                       "but the filename is the same. This is mostly useful to display "
-                                       "title changes in internet streams.") ,
-                                    aosd_trigger_func_pb_titlechange_onoff ,
-                                    aosd_trigger_func_pb_titlechange_cb },
-
-  [AOSD_TRIGGER_PB_PAUSEON] = { N_("Pause On") ,
-                                N_("Triggers OSD when playback is paused.") ,
-                                aosd_trigger_func_pb_pauseon_onoff ,
-                                aosd_trigger_func_pb_pauseon_cb },
-
-  [AOSD_TRIGGER_PB_PAUSEOFF] = { N_("Pause Off") ,
-                                 N_("Triggers OSD when playback is unpaused.") ,
-                                 aosd_trigger_func_pb_pauseoff_onoff ,
-                                 aosd_trigger_func_pb_pauseoff_cb }
-};
-
-
-
-/* TRIGGER API */
-
-void
-aosd_trigger_get_codes_array ( gint ** array , gint * array_size )
-{
-  *array = aosd_trigger_codes;
-  *array_size = AOSD_TRIGGER_CODES_ARRAY_SIZE;
-}
-
-
-const gchar *
-aosd_trigger_get_name ( gint trig_code )
-{
-  if (trig_code >= 0 && trig_code < ARRAY_LEN (aosd_triggers))
-    return aosd_triggers[trig_code].name;
-  return NULL;
-}
-
-
-const gchar *
-aosd_trigger_get_desc ( gint trig_code )
-{
-  if (trig_code >= 0 && trig_code < ARRAY_LEN (aosd_triggers))
-    return aosd_triggers[trig_code].desc;
-  return NULL;
-}
-
-
-void
-aosd_trigger_start ( aosd_cfg_osd_trigger_t * cfg_trigger )
-{
-  gint i = 0;
-  for ( i = 0 ; i < cfg_trigger->active->len ; i++ )
-  {
-    gint trig_code = g_array_index( cfg_trigger->active , gint , i );
-    if (trig_code >= 0 && trig_code < ARRAY_LEN (aosd_triggers))
-      aosd_triggers[trig_code].onoff_func (TRUE);
-  }
-  /* When called, this hook will display the text of the user pointer
-     or the current playing song, if NULL */
-  hook_associate( "aosd toggle" , aosd_trigger_func_hook_cb , NULL );
-}
-
-
-void
-aosd_trigger_stop ( aosd_cfg_osd_trigger_t * cfg_trigger )
-{
-  gint i = 0;
-  hook_dissociate( "aosd toggle" , aosd_trigger_func_hook_cb );
-  for ( i = 0 ; i < cfg_trigger->active->len ; i++ )
-  {
-    gint trig_code = g_array_index( cfg_trigger->active , gint , i );
-    if (trig_code >= 0 && trig_code < ARRAY_LEN (aosd_triggers))
-      aosd_triggers[trig_code].onoff_func (FALSE);
-  }
-}
-
-
-/* TRIGGER FUNCTIONS */
-
-static void
-aosd_trigger_func_pb_start_onoff(gboolean turn_on)
-{
-  if (turn_on == TRUE)
-    hook_associate("playback begin", aosd_trigger_func_pb_start_cb, NULL);
-  else
-    hook_dissociate("playback begin", aosd_trigger_func_pb_start_cb);
-}
-
-static void
-aosd_trigger_func_pb_start_cb(gpointer hook_data, gpointer user_data)
-{
-  char * title = aud_drct_get_title ();
-  char * markup = g_markup_printf_escaped ("<span font_desc='%s'>%s</span>",
-   global_config->osd->text.fonts_name[0], title);
-
-  aosd_osd_display (markup, global_config->osd, FALSE);
-  g_free (markup);
-  str_unref (title);
-}
-
-typedef struct
-{
-  gchar *title;
-  gchar *filename;
-}
-aosd_pb_titlechange_prevs_t;
-
-static void
-aosd_trigger_func_pb_titlechange_onoff ( gboolean turn_on )
-{
-  static aosd_pb_titlechange_prevs_t *prevs = NULL;
-
-  if ( turn_on == TRUE )
-  {
-    prevs = g_malloc0(sizeof(aosd_pb_titlechange_prevs_t));
-    prevs->title = NULL;
-    prevs->filename = NULL;
-    hook_associate( "title change" , aosd_trigger_func_pb_titlechange_cb , prevs );
-  }
-  else
-  {
-    hook_dissociate( "title change" , aosd_trigger_func_pb_titlechange_cb );
-    if ( prevs != NULL )
-    {
-      if ( prevs->title != NULL ) g_free( prevs->title );
-      if ( prevs->filename != NULL ) g_free( prevs->filename );
-      g_free( prevs );
-      prevs = NULL;
-    }
-  }
-}
-
-static void
-aosd_trigger_func_pb_titlechange_cb ( gpointer plentry_gp , gpointer prevs_gp )
-{
-  if (aud_drct_get_playing ())
-  {
-    aosd_pb_titlechange_prevs_t *prevs = prevs_gp;
-    gint playlist = aud_playlist_get_playing();
-    gint pl_entry = aud_playlist_get_position(playlist);
-    gchar * pl_entry_filename = aud_playlist_entry_get_filename (playlist, pl_entry);
-    gchar * pl_entry_title = aud_playlist_entry_get_title (playlist, pl_entry, FALSE);
-
-    /* same filename but title changed, useful to detect http stream song changes */
-
-    if ( ( prevs->title != NULL ) && ( prevs->filename != NULL ) )
-    {
-      if ( ( pl_entry_filename != NULL ) && ( !strcmp(pl_entry_filename,prevs->filename) ) )
-      {
-        if ( ( pl_entry_title != NULL ) && ( strcmp(pl_entry_title,prevs->title) ) )
-        {
-          /* string formatting is done here a.t.m. - TODO - improve this area */
-          char * markup = g_markup_printf_escaped
-           ("<span font_desc='%s'>%s</span>",
-           global_config->osd->text.fonts_name[0], pl_entry_title);
-
-          aosd_osd_display (markup, global_config->osd, FALSE);
-          g_free (markup);
-
-          g_free( prevs->title );
-          prevs->title = g_strdup(pl_entry_title);
-        }
-      }
-      else
-      {
-        g_free(prevs->filename);
-        prevs->filename = g_strdup(pl_entry_filename);
-        /* if filename changes, reset title as well */
-        if ( prevs->title != NULL )
-          g_free(prevs->title);
-        prevs->title = g_strdup(pl_entry_title);
-      }
-    }
-    else
-    {
-      if ( prevs->title != NULL )
-        g_free(prevs->title);
-      prevs->title = g_strdup(pl_entry_title);
-      if ( prevs->filename != NULL )
-        g_free(prevs->filename);
-      prevs->filename = g_strdup(pl_entry_filename);
-    }
-
-    str_unref (pl_entry_filename);
-    str_unref (pl_entry_title);
-  }
-}
-
-static void
-aosd_trigger_func_pb_pauseon_onoff ( gboolean turn_on )
-{
-  if ( turn_on == TRUE )
-    hook_associate( "playback pause" , aosd_trigger_func_pb_pauseon_cb , NULL );
-  else
-    hook_dissociate( "playback pause" , aosd_trigger_func_pb_pauseon_cb );
-}
-
-static void
-aosd_trigger_func_pb_pauseon_cb ( gpointer unused1 , gpointer unused2 )
-{
-  char * markup = g_markup_printf_escaped ("<span font_desc='%s'>Paused</span>",
-   global_config->osd->text.fonts_name[0]);
-  aosd_osd_display (markup, global_config->osd, FALSE);
-  g_free (markup);
-}
-
-
-static void
-aosd_trigger_func_pb_pauseoff_onoff ( gboolean turn_on )
-{
-  if ( turn_on == TRUE )
-    hook_associate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb , NULL );
-  else
-    hook_dissociate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb );
-}
-
-static void
-aosd_trigger_func_pb_pauseoff_cb ( gpointer unused1 , gpointer unused2 )
-{
-  gint active = aud_playlist_get_active();
-  gint pos = aud_playlist_get_position(active);
-  gint time_cur, time_tot;
-  gint time_cur_m, time_cur_s, time_tot_m, time_tot_s;
-
-  time_tot = aud_playlist_entry_get_length (active, pos, FALSE) / 1000;
-  time_cur = aud_drct_get_time() / 1000;
-  time_cur_s = time_cur % 60;
-  time_cur_m = (time_cur - time_cur_s) / 60;
-  time_tot_s = time_tot % 60;
-  time_tot_m = (time_tot - time_tot_s) / 60;
-
-  char * title = aud_playlist_entry_get_title (active, pos, FALSE);
-  char * markup = g_markup_printf_escaped
-   ("<span font_desc='%s'>%s (%i:%02i/%i:%02i)</span>",
-   global_config->osd->text.fonts_name[0], title, time_cur_m, time_cur_s,
-   time_tot_m, time_tot_s);
-
-  aosd_osd_display (markup, global_config->osd, FALSE);
-  g_free (markup);
-  str_unref (title);
-}
-
-
-/* Call with hook_call("aosd toggle", param);
-   If param != NULL, display the supplied text in the OSD
-   If param == NULL, display the current playing song */
-static void
-aosd_trigger_func_hook_cb ( gpointer markup_text , gpointer unused )
-{
-  if ( markup_text != NULL )
-  {
-    /* Display text from caller */
-    aosd_osd_display( markup_text , global_config->osd , FALSE );
-  } else {
-    /* Display currently playing song */
-    aosd_trigger_func_pb_start_cb (NULL, NULL);
-  }
-}
diff --git a/src/aosd/aosd_trigger.cc b/src/aosd/aosd_trigger.cc
new file mode 100644
index 000000000000..e9f3ee7f8074
--- /dev/null
+++ b/src/aosd/aosd_trigger.cc
@@ -0,0 +1,284 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include <glib.h>
+#include <string.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+
+#include "aosd_trigger.h"
+#include "aosd_trigger_private.h"
+#include "aosd_cfg.h"
+#include "aosd_osd.h"
+
+/* prototypes of trigger functions */
+static void aosd_trigger_func_pb_start_onoff ( bool );
+static void aosd_trigger_func_pb_start_cb ( void * , void * );
+static void aosd_trigger_func_pb_titlechange_onoff ( bool );
+static void aosd_trigger_func_pb_titlechange_cb ( void * , void * );
+static void aosd_trigger_func_pb_pauseon_onoff ( bool );
+static void aosd_trigger_func_pb_pauseon_cb ( void * , void * );
+static void aosd_trigger_func_pb_pauseoff_onoff ( bool );
+static void aosd_trigger_func_pb_pauseoff_cb ( void * , void * );
+static void aosd_trigger_func_hook_cb ( void * markup_text , void * unused );
+
+/* map trigger codes to trigger objects */
+aosd_trigger_t aosd_triggers[] =
+{
+  // AOSD_TRIGGER_PB_START
+  { N_("Playback Start") ,
+    N_("Triggers OSD when a playlist entry is played.") ,
+    aosd_trigger_func_pb_start_onoff ,
+    aosd_trigger_func_pb_start_cb },
+
+  // AOSD_TRIGGER_PB_TITLECHANGE
+  { N_("Title Change") ,
+    N_("Triggers OSD when the song title changes (for internet streams).") ,
+    aosd_trigger_func_pb_titlechange_onoff ,
+    aosd_trigger_func_pb_titlechange_cb },
+
+  // AOSD_TRIGGER_PB_PAUSEON
+  { N_("Pause On") ,
+    N_("Triggers OSD when playback is paused.") ,
+    aosd_trigger_func_pb_pauseon_onoff ,
+    aosd_trigger_func_pb_pauseon_cb },
+
+  // AOSD_TRIGGER_PB_PAUSEOFF
+  { N_("Pause Off") ,
+    N_("Triggers OSD when playback is unpaused.") ,
+    aosd_trigger_func_pb_pauseoff_onoff ,
+    aosd_trigger_func_pb_pauseoff_cb }
+};
+
+static_assert (aud::n_elems (aosd_triggers) == AOSD_NUM_TRIGGERS, "update aosd_triggers");
+
+/* TRIGGER API */
+
+const char *
+aosd_trigger_get_name ( int trig_code )
+{
+  if (trig_code >= 0 && trig_code < aud::n_elems (aosd_triggers))
+    return aosd_triggers[trig_code].name;
+  return nullptr;
+}
+
+
+const char *
+aosd_trigger_get_desc ( int trig_code )
+{
+  if (trig_code >= 0 && trig_code < aud::n_elems (aosd_triggers))
+    return aosd_triggers[trig_code].desc;
+  return nullptr;
+}
+
+
+void aosd_trigger_start (const aosd_cfg_osd_trigger_t & cfg_trigger)
+{
+  for (int i = 0; i < AOSD_NUM_TRIGGERS; i ++)
+  {
+    if (cfg_trigger.enabled[i])
+      aosd_triggers[i].onoff_func (true);
+  }
+
+  /* When called, this hook will display the text of the user pointer
+     or the current playing song, if nullptr */
+  hook_associate( "aosd toggle" , aosd_trigger_func_hook_cb , nullptr );
+}
+
+
+void aosd_trigger_stop (const aosd_cfg_osd_trigger_t & cfg_trigger)
+{
+  hook_dissociate( "aosd toggle" , aosd_trigger_func_hook_cb );
+
+  for (int i = 0; i < AOSD_NUM_TRIGGERS; i ++)
+  {
+    if (cfg_trigger.enabled[i])
+      aosd_triggers[i].onoff_func (false);
+  }
+}
+
+
+/* TRIGGER FUNCTIONS */
+
+static void
+aosd_trigger_func_pb_start_onoff ( bool turn_on )
+{
+  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);
+}
+
+static void
+aosd_trigger_func_pb_start_cb(void * hook_data, void * user_data)
+{
+  String title = aud_drct_get_title ();
+  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);
+  g_free (markup);
+}
+
+typedef struct
+{
+  String title;
+  String filename;
+}
+aosd_pb_titlechange_prevs_t;
+
+static void
+aosd_trigger_func_pb_titlechange_onoff ( bool turn_on )
+{
+  static aosd_pb_titlechange_prevs_t *prevs = nullptr;
+
+  if ( turn_on == TRUE )
+  {
+    prevs = new aosd_pb_titlechange_prevs_t;
+    hook_associate( "title change" , aosd_trigger_func_pb_titlechange_cb , prevs );
+  }
+  else
+  {
+    hook_dissociate( "title change" , aosd_trigger_func_pb_titlechange_cb );
+    if ( prevs != nullptr )
+    {
+      delete prevs;
+      prevs = nullptr;
+    }
+  }
+}
+
+static void
+aosd_trigger_func_pb_titlechange_cb ( void * plentry_gp , void * prevs_gp )
+{
+  if (aud_drct_get_playing ())
+  {
+    aosd_pb_titlechange_prevs_t *prevs = (aosd_pb_titlechange_prevs_t *) prevs_gp;
+    String pl_entry_filename = aud_drct_get_filename ();
+    Tuple pl_entry_tuple = aud_drct_get_tuple ();
+    String pl_entry_title = pl_entry_tuple.get_str (Tuple::FormattedTitle);
+
+    /* same filename but title changed, useful to detect http stream song changes */
+
+    if ( ( prevs->title != nullptr ) && ( prevs->filename != nullptr ) )
+    {
+      if ( ( pl_entry_filename != nullptr ) && ( !strcmp(pl_entry_filename,prevs->filename) ) )
+      {
+        if ( ( pl_entry_title != nullptr ) && ( strcmp(pl_entry_title,prevs->title) ) )
+        {
+          /* string formatting is done here a.t.m. - TODO - improve this area */
+          char * markup = g_markup_printf_escaped
+           ("<span font_desc='%s'>%s</span>",
+           (const char *) global_config.text.fonts_name[0],
+           (const char *) pl_entry_title);
+
+          aosd_osd_display (markup, & global_config, FALSE);
+          g_free (markup);
+
+          prevs->title = pl_entry_title;
+        }
+      }
+      else
+      {
+        prevs->filename = pl_entry_filename;
+        /* if filename changes, reset title as well */
+        prevs->title = pl_entry_title;
+      }
+    }
+    else
+    {
+      prevs->title = pl_entry_title;
+      prevs->filename = pl_entry_filename;
+    }
+  }
+}
+
+static void
+aosd_trigger_func_pb_pauseon_onoff ( bool turn_on )
+{
+  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 );
+}
+
+static void
+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);
+  g_free (markup);
+}
+
+
+static void
+aosd_trigger_func_pb_pauseoff_onoff ( bool turn_on )
+{
+  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 );
+}
+
+static void
+aosd_trigger_func_pb_pauseoff_cb ( void * unused1 , void * unused2 )
+{
+  Tuple tuple = aud_drct_get_tuple ();
+  int time_cur, time_tot;
+  int time_cur_m, time_cur_s, time_tot_m, time_tot_s;
+
+  time_tot = tuple.get_int (Tuple::Length) / 1000;
+  time_cur = aud_drct_get_time() / 1000;
+  time_cur_s = time_cur % 60;
+  time_cur_m = (time_cur - time_cur_s) / 60;
+  time_tot_s = time_tot % 60;
+  time_tot_m = (time_tot - time_tot_s) / 60;
+
+  String title = tuple.get_str (Tuple::FormattedTitle);
+  char * markup = g_markup_printf_escaped
+   ("<span font_desc='%s'>%s (%i:%02i/%i:%02i)</span>",
+   (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);
+  g_free (markup);
+}
+
+
+/* Call with hook_call("aosd toggle", param);
+   If param != nullptr, display the supplied text in the OSD
+   If param == nullptr, display the current playing song */
+static void
+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);
+  } else {
+    /* Display currently playing song */
+    aosd_trigger_func_pb_start_cb (nullptr, nullptr);
+  }
+}
diff --git a/src/aosd/aosd_trigger.h b/src/aosd/aosd_trigger.h
index d317da9e8b1a..cd45562004f3 100644
--- a/src/aosd/aosd_trigger.h
+++ b/src/aosd/aosd_trigger.h
@@ -21,20 +21,12 @@
 #ifndef _I_AOSD_TRIGGER_H
 #define _I_AOSD_TRIGGER_H 1
 
-#undef PACKAGE
-#define PACKAGE "audacious-plugins"
-
-#include "aosd_common.h"
 #include "aosd_cfg.h"
-#include <glib.h>
-
 
 /* trigger public API */
-void aosd_trigger_get_codes_array ( gint ** , gint * );
-const gchar * aosd_trigger_get_name ( gint );
-const gchar * aosd_trigger_get_desc ( gint );
-void aosd_trigger_start ( aosd_cfg_osd_trigger_t * cfg_trigger );
-void aosd_trigger_stop ( aosd_cfg_osd_trigger_t * cfg_trigger );
-
+const char * aosd_trigger_get_name ( int );
+const char * aosd_trigger_get_desc ( int );
+void aosd_trigger_start (const aosd_cfg_osd_trigger_t & cfg_trigger);
+void aosd_trigger_stop (const aosd_cfg_osd_trigger_t & cfg_trigger);
 
 #endif /* !_I_AOSD_TRIGGER_H */
diff --git a/src/aosd/aosd_trigger_private.h b/src/aosd/aosd_trigger_private.h
index 411e6bd814f7..0632598fd6c6 100644
--- a/src/aosd/aosd_trigger_private.h
+++ b/src/aosd/aosd_trigger_private.h
@@ -21,10 +21,6 @@
 #ifndef _I_AOSD_TRIGGER_PRIVATE_H
 #define _I_AOSD_TRIGGER_PRIVATE_H 1
 
-#include "aosd_common.h"
-#include <glib.h>
-
-
 /* trigger object
    ----------------------------------------------------------
    name           name
@@ -34,12 +30,11 @@
 */
 typedef struct
 {
-  const gchar * name;
-  const gchar * desc;
-  void (*onoff_func)( gboolean );
-  void (*callback_func)( gpointer , gpointer );
+  const char * name;
+  const char * desc;
+  void (*onoff_func)( bool );
+  void (*callback_func)( void * , void * );
 }
 aosd_trigger_t;
 
-
 #endif /* !_I_AOSD_TRIGGER_PRIVATE_H */
diff --git a/src/aosd/aosd_ui.c b/src/aosd/aosd_ui.c
deleted file mode 100644
index 9bf290ca0419..000000000000
--- a/src/aosd/aosd_ui.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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
-*
-*/
-
-#include <math.h>
-
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "aosd_ui.h"
-#include "aosd_style.h"
-#include "aosd_trigger.h"
-#include "aosd_cfg.h"
-#include "aosd_osd.h"
-#include "aosd_common.h"
-
-extern aosd_cfg_t * global_config;
-extern gboolean plugin_is_active;
-
-
-static void chooser_get_aosd_color (GtkColorChooser * chooser, aosd_color_t * color)
-{
-  GdkRGBA rgba;
-  gtk_color_chooser_get_rgba (chooser, & rgba);
-
-  color->red = rint (rgba.red * 65535.0);
-  color->green = rint (rgba.green * 65535.0);
-  color->blue = rint (rgba.blue * 65535.0);
-  color->alpha = rint (rgba.alpha * 65535.0);
-}
-
-
-static void chooser_set_aosd_color (GtkColorChooser * chooser, const aosd_color_t * color)
-{
-  GdkRGBA rgba =
-  {
-    .red = color->red / 65535.0,
-    .green = color->green / 65535.0,
-    .blue = color->blue / 65535.0,
-    .alpha = color->alpha / 65535.0
-  };
-
-  gtk_color_chooser_set_use_alpha (chooser, TRUE);
-  gtk_color_chooser_set_rgba (chooser, & rgba);
-}
-
-
-/*************************************************************/
-/* small callback system used by the configuration interface */
-typedef void (*aosd_ui_cb_func_t)( GtkWidget * , aosd_cfg_t * );
-
-typedef struct
-{
-  aosd_ui_cb_func_t func;
-  GtkWidget * widget;
-}
-aosd_ui_cb_t;
-
-static void
-aosd_callback_list_add ( GList ** list , GtkWidget * widget , aosd_ui_cb_func_t func )
-{
-  aosd_ui_cb_t *cb = g_malloc(sizeof(aosd_ui_cb_t));
-  cb->widget = widget;
-  cb->func = func;
-  *list = g_list_append( *list , cb );
-}
-
-static void
-aosd_callback_list_run ( GList * list , aosd_cfg_t * cfg )
-{
-  while ( list != NULL )
-  {
-    aosd_ui_cb_t *cb = (aosd_ui_cb_t*)list->data;
-    cb->func( cb->widget , cfg );
-    list = g_list_next( list );
-  }
-}
-
-static void
-aosd_callback_list_free ( GList * list )
-{
-  GList *list_top = list;
-  while ( list != NULL )
-  {
-    g_free( (aosd_ui_cb_t*)list->data );
-    list = g_list_next( list );
-  }
-  g_list_free( list_top );
-}
-/*************************************************************/
-
-
-
-static gboolean
-aosd_cb_configure_position_expose ( GtkWidget * darea ,
-                                    cairo_t * cr ,
-                                    gpointer coord_gp )
-{
-  gint coord = GPOINTER_TO_INT(coord_gp);
-
-  cairo_set_source_rgb ( cr , 0 , 0 , 0 );
-  cairo_rectangle ( cr , (coord % 3) * 10 , (coord / 3) * 16 , 20 , 8 );
-  cairo_fill ( cr );
-
-  return FALSE;
-}
-
-
-static void
-aosd_cb_configure_position_placement_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
-{
-  GList *placbt_list = gtk_container_get_children( GTK_CONTAINER(grid) );
-  GList *list_iter = placbt_list;
-
-  while ( list_iter != NULL )
-  {
-    GtkWidget *placbt = list_iter->data;
-    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(placbt) ) == TRUE )
-    {
-      cfg->osd->position.placement = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(placbt),"value"));
-      break;
-    }
-    list_iter = g_list_next( list_iter );
-  }
-
-  g_list_free( placbt_list );
-}
-
-
-static void
-aosd_cb_configure_position_offset_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
-{
-  cfg->osd->position.offset_x = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"offx")) );
-  cfg->osd->position.offset_y = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"offy")) );
-}
-
-
-static void
-aosd_cb_configure_position_maxsize_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
-{
-  cfg->osd->position.maxsize_width = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"maxsize_width")) );
-}
-
-
-static void
-aosd_cb_configure_position_multimon_commit ( GtkWidget * combo , aosd_cfg_t * cfg )
-{
-  gint active = gtk_combo_box_get_active( GTK_COMBO_BOX(combo) );
-  cfg->osd->position.multimon_id = ( active > -1 ) ? (active - 1) : -1;
-}
-
-
-static GtkWidget *
-aosd_ui_configure_position ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *pos_vbox;
-  GtkWidget *pos_placement_frame, *pos_placement_hbox, *pos_placement_grid;
-  GtkWidget *pos_placement_bt[9], *pos_placement_bt_darea[9];
-  GtkWidget *pos_offset_grid, *pos_offset_x_label, *pos_offset_x_spinbt;
-  GtkWidget *pos_offset_y_label, *pos_offset_y_spinbt;
-  GtkWidget *pos_maxsize_width_label, *pos_maxsize_width_spinbt;
-  GtkWidget *pos_multimon_frame, *pos_multimon_hbox;
-  GtkWidget *pos_multimon_label;
-  GtkWidget *pos_multimon_combobox;
-  gint monitors_num = gdk_screen_get_n_monitors( gdk_screen_get_default() );
-  gint i = 0;
-
-  pos_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 4 );
-  gtk_container_set_border_width( GTK_CONTAINER(pos_vbox) , 6 );
-
-  pos_placement_frame = gtk_frame_new( _("Placement") );
-  pos_placement_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 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 );
-
-  pos_placement_grid = gtk_grid_new();
-  for ( i = 0 ; i < 9 ; i++ )
-  {
-    if ( i == 0 )
-      pos_placement_bt[i] = gtk_radio_button_new( NULL );
-    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 );
-    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] );
-    g_signal_connect( G_OBJECT(pos_placement_bt_darea[i]) , "draw" ,
-                      G_CALLBACK(aosd_cb_configure_position_expose) , GINT_TO_POINTER(i) );
-    gtk_grid_attach( GTK_GRID(pos_placement_grid) , pos_placement_bt[i] , (i % 3) , (i / 3) , 1 , 1 );
-    g_object_set_data( G_OBJECT(pos_placement_bt[i]) , "value" , GINT_TO_POINTER(i+1) );
-    if ( cfg->osd->position.placement == (i+1) )
-      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 );
-  aosd_callback_list_add( cb_list , pos_placement_grid , aosd_cb_configure_position_placement_commit );
-
-  gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , gtk_separator_new(GTK_ORIENTATION_VERTICAL) , FALSE , FALSE , 6 );
-
-  pos_offset_grid = gtk_grid_new();
-  gtk_grid_set_row_spacing( GTK_GRID(pos_offset_grid) , 4 );
-  gtk_grid_set_column_spacing( GTK_GRID(pos_offset_grid) , 4 );
-  pos_offset_x_label = gtk_label_new( _( "Relative X offset:" ) );
-  gtk_misc_set_alignment( GTK_MISC(pos_offset_x_label) , 0 , 0.5 );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_offset_x_label , 0 , 0 , 1 , 1 );
-  pos_offset_x_spinbt = gtk_spin_button_new_with_range( -9999 , 9999 , 1 );
-  gtk_spin_button_set_value( GTK_SPIN_BUTTON(pos_offset_x_spinbt) , cfg->osd->position.offset_x );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_offset_x_spinbt , 1 , 0 , 1 , 1 );
-  g_object_set_data( G_OBJECT(pos_offset_grid) , "offx" , pos_offset_x_spinbt );
-  pos_offset_y_label = gtk_label_new( _( "Relative Y offset:" ) );
-  gtk_misc_set_alignment( GTK_MISC(pos_offset_y_label) , 0 , 0.5 );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_offset_y_label , 0 , 1 , 1 , 1 );
-  pos_offset_y_spinbt = gtk_spin_button_new_with_range( -9999 , 9999 , 1 );
-  gtk_spin_button_set_value( GTK_SPIN_BUTTON(pos_offset_y_spinbt) , cfg->osd->position.offset_y );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_offset_y_spinbt , 1 , 1 , 1 , 1 );
-  g_object_set_data( G_OBJECT(pos_offset_grid) , "offy" , pos_offset_y_spinbt );
-  pos_maxsize_width_label = gtk_label_new( _("Max OSD width:") );
-  gtk_misc_set_alignment( GTK_MISC(pos_maxsize_width_label) , 0 , 0.5 );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_maxsize_width_label , 0 , 2 , 1 , 1 );
-  pos_maxsize_width_spinbt = gtk_spin_button_new_with_range( 0 , 99999 , 1 );
-  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->osd->position.maxsize_width );
-  gtk_grid_attach( GTK_GRID(pos_offset_grid) , pos_maxsize_width_spinbt , 1 , 2 , 1 , 1 );
-  gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , pos_offset_grid , FALSE , FALSE , 0 );
-  aosd_callback_list_add( cb_list , pos_offset_grid , aosd_cb_configure_position_offset_commit );
-  aosd_callback_list_add( cb_list , pos_offset_grid , aosd_cb_configure_position_maxsize_commit );
-
-  pos_multimon_frame = gtk_frame_new( _("Multi-Monitor options") );
-  pos_multimon_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 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:") );
-  pos_multimon_combobox = gtk_combo_box_text_new ();
-  gtk_combo_box_text_append_text ((GtkComboBoxText *) pos_multimon_combobox, _("all monitors"));
-  for ( i = 0 ; i < monitors_num ; i++ )
-  {
-    gchar *mon_str = g_strdup_printf( _("monitor %i") , i + 1 );
-    gtk_combo_box_text_append_text ((GtkComboBoxText *) pos_multimon_combobox, mon_str);
-    g_free( mon_str );
-  }
-  gtk_combo_box_set_active( GTK_COMBO_BOX(pos_multimon_combobox) , (cfg->osd->position.multimon_id + 1) );
-  aosd_callback_list_add( cb_list , 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 );
-
-  return pos_vbox;
-}
-
-
-static GtkWidget *
-aosd_ui_configure_animation_timing ( gchar * label_string )
-{
-  GtkWidget *hbox, *desc_label, *spinbt;
-  hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 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 );
-  g_object_set_data( G_OBJECT(hbox) , "spinbt" , spinbt );
-  return hbox;
-}
-
-
-static void
-aosd_cb_configure_animation_timing_commit ( GtkWidget * timing_hbox , aosd_cfg_t * cfg )
-{
-  cfg->osd->animation.timing_display = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"display")) );
-  cfg->osd->animation.timing_fadein = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"fadein")) );
-  cfg->osd->animation.timing_fadeout = gtk_spin_button_get_value_as_int(
-    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"fadeout")) );
-}
-
-
-static GtkWidget *
-aosd_ui_configure_animation ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *ani_vbox;
-  GtkWidget *ani_timing_frame, *ani_timing_hbox;
-  GtkWidget *ani_timing_fadein_widget, *ani_timing_fadeout_widget, *ani_timing_stay_widget;
-  GtkSizeGroup *sizegroup;
-
-  ani_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 0 );
-  gtk_container_set_border_width( GTK_CONTAINER(ani_vbox) , 6 );
-
-  ani_timing_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 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 );
-
-  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->osd->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_separator_new(GTK_ORIENTATION_VERTICAL) , 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->osd->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_separator_new(GTK_ORIENTATION_VERTICAL) , 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->osd->animation.timing_fadeout );
-  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" ,
-    g_object_get_data(G_OBJECT(ani_timing_fadein_widget),"spinbt") );
-  g_object_set_data( G_OBJECT(ani_timing_hbox) , "fadeout" ,
-    g_object_get_data(G_OBJECT(ani_timing_fadeout_widget),"spinbt") );
-  sizegroup = gtk_size_group_new( GTK_SIZE_GROUP_HORIZONTAL );
-  gtk_size_group_add_widget( sizegroup , ani_timing_stay_widget );
-  gtk_size_group_add_widget( sizegroup , ani_timing_fadein_widget );
-  gtk_size_group_add_widget( sizegroup , ani_timing_fadeout_widget );
-  aosd_callback_list_add( cb_list , ani_timing_hbox , aosd_cb_configure_animation_timing_commit );
-
-  return ani_vbox;
-}
-
-
-static void
-aosd_cb_configure_text_font_shadow_toggle ( GtkToggleButton * shadow_togglebt ,
-                                            gpointer shadow_colorbt )
-{
-  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 );
-}
-
-
-static void
-aosd_cb_configure_text_font_commit ( GtkWidget * fontbt , aosd_cfg_t * cfg )
-{
-  gint fontnum = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(fontbt) , "fontnum" ));
-  GtkColorChooser * chooser;
-
-  str_unref (cfg->osd->text.fonts_name[fontnum]);
-  cfg->osd->text.fonts_name[fontnum] =
-   str_get (gtk_font_button_get_font_name (GTK_FONT_BUTTON (fontbt)));
-
-  cfg->osd->text.fonts_draw_shadow[fontnum] = gtk_toggle_button_get_active(
-    GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(fontbt),"use_shadow")) );
-
-  chooser = g_object_get_data ((GObject *) fontbt, "color");
-  chooser_get_aosd_color (chooser, & cfg->osd->text.fonts_color[fontnum]);
-
-  chooser = g_object_get_data ((GObject *) fontbt, "shadow_color");
-  chooser_get_aosd_color (chooser, & cfg->osd->text.fonts_shadow_color[fontnum]);
-}
-
-
-static GtkWidget *
-aosd_ui_configure_text ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *tex_vbox;
-  GtkWidget *tex_font_grid, *tex_font_frame;
-  GtkWidget *tex_font_label[3], *tex_font_fontbt[3];
-  GtkWidget *tex_font_colorbt[3], *tex_font_shadow_togglebt[3];
-  GtkWidget *tex_font_shadow_colorbt[3];
-  gint i = 0;
-
-  tex_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 4 );
-  gtk_container_set_border_width( GTK_CONTAINER(tex_vbox) , 6 );
-
-  tex_font_frame = gtk_frame_new( _("Fonts") );
-  tex_font_grid = gtk_grid_new();
-  gtk_container_set_border_width( GTK_CONTAINER(tex_font_grid) , 6 );
-  gtk_grid_set_row_spacing ( GTK_GRID(tex_font_grid) , 4 );
-  gtk_grid_set_column_spacing ( GTK_GRID(tex_font_grid) , 4 );
-  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
-  {
-    gchar *label_str = g_strdup_printf( _("Font %i:") , i+1 );
-    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_font_name( GTK_FONT_BUTTON(tex_font_fontbt[i]) , cfg->osd->text.fonts_name[i] );
-    gtk_widget_set_hexpand( tex_font_fontbt[i] , TRUE );
-
-    tex_font_colorbt[i] = gtk_color_button_new ();
-    chooser_set_aosd_color ((GtkColorChooser *) tex_font_colorbt[i],
-     & cfg->osd->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 );
-
-    tex_font_shadow_colorbt[i] = gtk_color_button_new ();
-    chooser_set_aosd_color ((GtkColorChooser *) tex_font_shadow_colorbt[i],
-     & cfg->osd->text.fonts_shadow_color[i]);
-
-    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] );
-    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tex_font_shadow_togglebt[i]) ,
-      cfg->osd->text.fonts_draw_shadow[i] );
-    gtk_grid_attach( GTK_GRID(tex_font_grid) , tex_font_label[i] , 0 , 0 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(tex_font_grid) , tex_font_fontbt[i] , 1 , 0 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(tex_font_grid) , tex_font_colorbt[i] , 2 , 0 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(tex_font_grid) , tex_font_shadow_togglebt[i] , 3 , 0 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(tex_font_grid) , tex_font_shadow_colorbt[i] , 4 , 0 , 1 , 1 );
-    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "fontnum" , GINT_TO_POINTER(i) );
-    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "color" , tex_font_colorbt[i] );
-    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "use_shadow" , tex_font_shadow_togglebt[i] );
-    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "shadow_color" , tex_font_shadow_colorbt[i] );
-    aosd_callback_list_add( cb_list , 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 );
-
-  return tex_vbox;
-}
-
-
-static void
-aosd_cb_configure_decoration_style_commit ( GtkWidget * lv , aosd_cfg_t * cfg )
-{
-  GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(lv) );
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-
-  if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE )
-  {
-    gint deco_code = 0;
-    gtk_tree_model_get( model , &iter , 1 , &deco_code , -1 );
-    cfg->osd->decoration.code = deco_code;
-  }
-}
-
-
-static void
-aosd_cb_configure_decoration_color_commit ( GtkWidget * colorbt , aosd_cfg_t * cfg )
-{
-  aosd_color_t color;
-  chooser_get_aosd_color ((GtkColorChooser *) colorbt, & color);
-
-  gint colnum = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(colorbt) , "colnum" ) );
-  g_array_insert_val( cfg->osd->decoration.colors , colnum , color );
-}
-
-
-static GtkWidget *
-aosd_ui_configure_decoration ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *dec_hbox;
-  GtkWidget *dec_rstyle_lv, *dec_rstyle_lv_frame, *dec_rstyle_lv_sw;
-  GtkListStore *dec_rstyle_store;
-  GtkCellRenderer *dec_rstyle_lv_rndr_text;
-  GtkTreeViewColumn *dec_rstyle_lv_col_desc;
-  GtkTreeSelection *dec_rstyle_lv_sel;
-  GtkTreeIter iter, iter_sel;
-  GtkWidget *dec_rstyle_hbox;
-  GtkWidget *dec_rstyleopts_frame, *dec_rstyleopts_grid;
-  gint *deco_code_array, deco_code_array_size;
-  gint colors_max_num = 0, i = 0;
-
-  dec_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 4 );
-  gtk_container_set_border_width( GTK_CONTAINER(dec_hbox) , 6 );
-
-  /* decoration style model
-     ---------------------------------------------
-     G_TYPE_STRING -> decoration description
-     G_TYPE_INT -> decoration code
-     G_TYPE_INT -> number of user-definable colors
-     ---------------------------------------------
-  */
-  dec_rstyle_store = gtk_list_store_new( 3 , G_TYPE_STRING , G_TYPE_INT , G_TYPE_INT );
-  aosd_deco_style_get_codes_array ( &deco_code_array , &deco_code_array_size );
-  for ( i = 0 ; i < deco_code_array_size ; i++ )
-  {
-    gint colors_num = aosd_deco_style_get_numcol( deco_code_array[i] );
-    if ( colors_num > colors_max_num )
-      colors_max_num = colors_num;
-    gtk_list_store_append( dec_rstyle_store , &iter );
-    gtk_list_store_set( dec_rstyle_store , &iter ,
-      0 , _(aosd_deco_style_get_desc( deco_code_array[i] )) ,
-      1 , deco_code_array[i] , 2 , colors_num , -1 );
-    if ( deco_code_array[i] == cfg->osd->decoration.code )
-      iter_sel = iter;
-  }
-
-  dec_rstyle_lv_frame = gtk_frame_new( NULL );
-  dec_rstyle_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(dec_rstyle_store) );
-  g_object_unref( dec_rstyle_store );
-  dec_rstyle_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(dec_rstyle_lv) );
-  gtk_tree_selection_set_mode( dec_rstyle_lv_sel , GTK_SELECTION_BROWSE );
-
-  dec_rstyle_lv_rndr_text = gtk_cell_renderer_text_new();
-  dec_rstyle_lv_col_desc = gtk_tree_view_column_new_with_attributes(
-    _("Render Style") , dec_rstyle_lv_rndr_text , "text" , 0 , NULL );
-  gtk_tree_view_append_column( GTK_TREE_VIEW(dec_rstyle_lv), dec_rstyle_lv_col_desc );
-  dec_rstyle_lv_sw = gtk_scrolled_window_new( NULL , NULL );
-  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(dec_rstyle_lv_sw) ,
-                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
-  gtk_container_add( GTK_CONTAINER(dec_rstyle_lv_sw) , dec_rstyle_lv );
-  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 );
-  aosd_callback_list_add( cb_list , dec_rstyle_lv , aosd_cb_configure_decoration_style_commit );
-
-  dec_rstyle_hbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 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_grid_new();
-  gtk_container_set_border_width( GTK_CONTAINER(dec_rstyleopts_grid) , 6 );
-  gtk_grid_set_row_spacing( GTK_GRID(dec_rstyleopts_grid) , 4 );
-  gtk_grid_set_column_spacing( GTK_GRID(dec_rstyleopts_grid) , 8 );
-  gtk_container_add( GTK_CONTAINER(dec_rstyleopts_frame) , dec_rstyleopts_grid );
-  for ( i = 0 ; i < colors_max_num ; i++ )
-  {
-    GtkWidget *hbox, *label;
-    gchar *label_str = NULL;
-    hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 4 );
-    label_str = g_strdup_printf( _("Color %i:") , i+1 );
-    label = gtk_label_new( label_str );
-    g_free( label_str );
-
-    GtkWidget * colorbt = gtk_color_button_new ();
-    chooser_set_aosd_color ((GtkColorChooser *) colorbt,
-     & g_array_index (cfg->osd->decoration.colors, aosd_color_t, i));
-
-    gtk_box_pack_start( GTK_BOX(hbox) , label , FALSE , FALSE , 0 );
-    gtk_box_pack_start( GTK_BOX(hbox) , colorbt , FALSE , FALSE , 0 );
-    gtk_grid_attach( GTK_GRID(dec_rstyleopts_grid) , hbox , (i % 3) , (i / 3) , 1 , 1 );
-    g_object_set_data( G_OBJECT(colorbt) , "colnum" , GINT_TO_POINTER(i) );
-    aosd_callback_list_add( cb_list , colorbt , aosd_cb_configure_decoration_color_commit );
-  }
-  gtk_box_pack_start( GTK_BOX(dec_rstyle_hbox) , dec_rstyleopts_frame , FALSE , FALSE , 0 );
-
-  return dec_hbox;
-}
-
-
-static void
-aosd_cb_configure_trigger_lvchanged ( GtkTreeSelection *sel , gpointer nb )
-{
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-
-  if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE )
-  {
-    gint page_num = 0;
-    gtk_tree_model_get( model , &iter , 2 , &page_num , -1 );
-    gtk_notebook_set_current_page( GTK_NOTEBOOK(nb) , page_num );
-  }
-}
-
-
-static gboolean
-aosd_cb_configure_trigger_findinarr ( GArray * array , gint value )
-{
-  gint i = 0;
-  for ( i = 0 ; i < array->len ; i++ )
-  {
-    if ( g_array_index( array , gint , i ) == value )
-      return TRUE;
-  }
-  return FALSE;
-}
-
-
-static void
-aosd_cb_configure_trigger_commit ( GtkWidget * cbt , aosd_cfg_t * cfg )
-{
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) ) == TRUE )
-  {
-    gint value = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbt),"code"));
-    g_array_append_val( cfg->osd->trigger.active , value );
-  }
-}
-
-
-static GtkWidget *
-aosd_ui_configure_trigger ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *tri_hbox;
-  GtkWidget *tri_event_lv, *tri_event_lv_frame, *tri_event_lv_sw;
-  GtkListStore *tri_event_store;
-  GtkCellRenderer *tri_event_lv_rndr_text;
-  GtkTreeViewColumn *tri_event_lv_col_desc;
-  GtkTreeSelection *tri_event_lv_sel;
-  GtkTreeIter iter;
-  gint *trigger_code_array, trigger_code_array_size;
-  GtkWidget *tri_event_nb;
-  gint i = 0;
-
-  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 );
-
-  tri_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 4 );
-  gtk_container_set_border_width( GTK_CONTAINER(tri_hbox) , 6 );
-
-  /* trigger model
-     ---------------------------------------------
-     G_TYPE_STRING -> trigger description
-     G_TYPE_INT -> trigger code
-     G_TYPE_INT -> gtk notebook page number
-     ---------------------------------------------
-  */
-  tri_event_store = gtk_list_store_new( 3 , G_TYPE_STRING , G_TYPE_INT , G_TYPE_INT );
-  aosd_trigger_get_codes_array ( &trigger_code_array , &trigger_code_array_size );
-  for ( i = 0 ; i < trigger_code_array_size ; i ++ )
-  {
-    GtkWidget *frame, *vbox, *label, *checkbt;
-    gtk_list_store_append( tri_event_store , &iter );
-    gtk_list_store_set( tri_event_store , &iter ,
-      0 , _(aosd_trigger_get_name( trigger_code_array[i] )) ,
-      1 , trigger_code_array[i] , 2 , i , -1 );
-    vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 0 );
-    gtk_container_set_border_width( GTK_CONTAINER(vbox) , 6 );
-    label = gtk_label_new( _(aosd_trigger_get_desc( trigger_code_array[i] )) );
-    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 ( aosd_cb_configure_trigger_findinarr( cfg->osd->trigger.active , trigger_code_array[i] ) )
-      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_separator_new(GTK_ORIENTATION_HORIZONTAL) , FALSE , FALSE , 4 );
-    gtk_box_pack_start( GTK_BOX(vbox) , label , FALSE , FALSE , 0 );
-    frame = gtk_frame_new( NULL );
-    gtk_container_add( GTK_CONTAINER(frame) , vbox );
-    gtk_notebook_append_page( GTK_NOTEBOOK(tri_event_nb) , frame , NULL );
-    g_object_set_data( G_OBJECT(checkbt) , "code" , GINT_TO_POINTER(trigger_code_array[i]) );
-    aosd_callback_list_add( cb_list , checkbt , aosd_cb_configure_trigger_commit );
-  }
-
-  tri_event_lv_frame = gtk_frame_new( NULL );
-  tri_event_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(tri_event_store) );
-  g_object_unref( tri_event_store );
-  tri_event_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(tri_event_lv) );
-  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 )
-    gtk_tree_selection_select_iter( tri_event_lv_sel , &iter );
-
-  tri_event_lv_rndr_text = gtk_cell_renderer_text_new();
-  tri_event_lv_col_desc = gtk_tree_view_column_new_with_attributes(
-    _("Event") , tri_event_lv_rndr_text , "text" , 0 , NULL );
-  gtk_tree_view_append_column( GTK_TREE_VIEW(tri_event_lv), tri_event_lv_col_desc );
-  tri_event_lv_sw = gtk_scrolled_window_new( NULL , NULL );
-  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tri_event_lv_sw) ,
-                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
-  gtk_container_add( GTK_CONTAINER(tri_event_lv_sw) , tri_event_lv );
-  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_nb , TRUE , TRUE , 0 );
-
-  return tri_hbox;
-}
-
-
-#ifdef HAVE_XCOMPOSITE
-static void
-aosd_cb_configure_misc_transp_real_clicked ( GtkToggleButton * real_rbt , gpointer status_hbox )
-{
-  GtkWidget *img = g_object_get_data( G_OBJECT(status_hbox) , "img" );
-  GtkWidget *label = g_object_get_data( G_OBJECT(status_hbox) , "label" );
-  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(real_rbt) ) )
-  {
-    if ( aosd_osd_check_composite_mgr() )
-    {
-      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 );
-    }
-    else
-    {
-      gtk_image_set_from_icon_name( GTK_IMAGE(img) , "dialog-warning" , GTK_ICON_SIZE_MENU );
-      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 );
-    }
-  }
-  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 );
-  }
-}
-#endif
-
-
-static void
-aosd_cb_configure_misc_transp_commit ( GtkWidget * mis_transp_vbox , aosd_cfg_t * cfg )
-{
-  GList *child_list = gtk_container_get_children( GTK_CONTAINER(mis_transp_vbox) );
-  while (child_list != NULL)
-  {
-    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(child_list->data) ) )
-    {
-      cfg->osd->misc.transparency_mode = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(child_list->data),"val"));
-      break;
-    }
-    child_list = g_list_next(child_list);
-  }
-}
-
-
-static GtkWidget *
-aosd_ui_configure_misc ( aosd_cfg_t * cfg , GList ** cb_list )
-{
-  GtkWidget *mis_vbox;
-  GtkWidget *mis_transp_frame, *mis_transp_vbox;
-  GtkWidget *mis_transp_fake_rbt, *mis_transp_real_rbt;
-  GtkWidget *mis_transp_status_frame, *mis_transp_status_hbox;
-  GtkWidget *mis_transp_status_img, *mis_transp_status_label;
-
-  mis_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 0 );
-  gtk_container_set_border_width( GTK_CONTAINER(mis_vbox) , 6 );
-
-  mis_transp_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , 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 );
-
-  mis_transp_fake_rbt = gtk_radio_button_new_with_label( NULL ,
-                          _("Fake transparency") );
-  mis_transp_real_rbt = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(mis_transp_fake_rbt) ,
-                          _("Real transparency (requires X Composite Ext.)") );
-  g_object_set_data( G_OBJECT(mis_transp_fake_rbt) , "val" ,
-                     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 );
-
-  mis_transp_status_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 4 );
-  mis_transp_status_frame = gtk_frame_new( NULL );
-  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 );
-
-  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 );
-  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 );
-
-#ifdef HAVE_XCOMPOSITE
-  g_signal_connect( G_OBJECT(mis_transp_real_rbt) , "toggled" ,
-    G_CALLBACK(aosd_cb_configure_misc_transp_real_clicked) , mis_transp_status_hbox );
-
-  /* check if the composite extension is loaded */
-  if ( aosd_osd_check_composite_ext() )
-  {
-    if ( cfg->osd->misc.transparency_mode == AOSD_MISC_TRANSPARENCY_FAKE )
-      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 );
-  }
-  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_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 );
-  }
-#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_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 );
-#endif
-
-  aosd_callback_list_add( cb_list , mis_transp_vbox , aosd_cb_configure_misc_transp_commit );
-
-  return mis_vbox;
-}
-
-
-static void
-aosd_cb_configure_test ( gpointer cfg_win )
-{
-  gchar *markup_message = NULL;
-  aosd_cfg_t *cfg = aosd_cfg_new();
-  GList *cb_list = g_object_get_data( G_OBJECT(cfg_win) , "cblist" );
-  aosd_callback_list_run( cb_list , cfg );
-  cfg->set = TRUE;
-  markup_message = g_markup_printf_escaped(
-    _("<span font_desc='%s'>Audacious OSD</span>") , cfg->osd->text.fonts_name[0] );
-  aosd_osd_shutdown(); /* stop any displayed osd */
-  aosd_osd_cleanup(); /* just in case it's active */
-  aosd_osd_init( cfg->osd->misc.transparency_mode );
-  aosd_osd_display( markup_message , cfg->osd , TRUE );
-  g_free( markup_message );
-  aosd_cfg_delete( cfg );
-}
-
-
-static void
-aosd_cb_configure_cancel ( gpointer cfg_win )
-{
-  GList *cb_list = g_object_get_data( G_OBJECT(cfg_win) , "cblist" );
-  aosd_callback_list_free( cb_list );
-  aosd_osd_shutdown(); /* stop any displayed osd */
-  aosd_osd_cleanup(); /* just in case it's active */
-  if ( plugin_is_active == TRUE )
-    aosd_osd_init( global_config->osd->misc.transparency_mode );
-  gtk_widget_destroy( GTK_WIDGET(cfg_win) );
-}
-
-
-static void
-aosd_cb_configure_ok ( gpointer cfg_win )
-{
-  //gchar *markup_message = NULL;
-  aosd_cfg_t *cfg = aosd_cfg_new();
-  GList *cb_list = g_object_get_data( G_OBJECT(cfg_win) , "cblist" );
-  aosd_callback_list_run( cb_list , cfg );
-  cfg->set = TRUE;
-  aosd_osd_shutdown(); /* stop any displayed osd */
-  aosd_osd_cleanup(); /* just in case it's active */
-
-  if ( global_config != NULL )
-  {
-    /* plugin is active */
-    aosd_trigger_stop( &global_config->osd->trigger ); /* stop triggers */
-    aosd_cfg_delete( global_config ); /* delete old global_config */
-    global_config = cfg; /* put the new one */
-    aosd_cfg_save( cfg ); /* save the new configuration on config file */
-    aosd_osd_init( cfg->osd->misc.transparency_mode ); /* restart osd */
-    aosd_trigger_start( &cfg->osd->trigger ); /* restart triggers */
-  }
-  else
-  {
-    /* plugin is not active */
-    aosd_cfg_save( cfg ); /* save the new configuration on config file */
-  }
-  aosd_callback_list_free( cb_list );
-  gtk_widget_destroy( GTK_WIDGET(cfg_win) );
-}
-
-
-void
-aosd_ui_configure ( aosd_cfg_t * cfg )
-{
-  static GtkWidget *cfg_win = NULL;
-  GtkWidget *cfg_vbox;
-  GtkWidget *cfg_nb;
-  GtkWidget *cfg_bbar_hbbox;
-  GtkWidget *cfg_bbar_bt_ok, *cfg_bbar_bt_test, *cfg_bbar_bt_cancel;
-  GtkWidget *cfg_position_widget;
-  GtkWidget *cfg_animation_widget;
-  GtkWidget *cfg_text_widget;
-  GtkWidget *cfg_decoration_widget;
-  GtkWidget *cfg_trigger_widget;
-  GdkGeometry cfg_win_hints;
-  GList *cb_list = NULL; /* list of custom callbacks */
-
-  if ( cfg_win != NULL )
-    gtk_window_present( GTK_WINDOW(cfg_win) );
-
-  cfg_win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
-  gtk_window_set_type_hint( GTK_WINDOW(cfg_win), GDK_WINDOW_TYPE_HINT_DIALOG );
-  gtk_window_set_title( GTK_WINDOW(cfg_win) , _("Audacious OSD - configuration") );
-  gtk_container_set_border_width( GTK_CONTAINER(cfg_win), 10 );
-  g_signal_connect( G_OBJECT(cfg_win) , "destroy" ,
-                    G_CALLBACK(gtk_widget_destroyed) , &cfg_win );
-  cfg_win_hints.min_width = -1;
-  cfg_win_hints.min_height = 350;
-  gtk_window_set_geometry_hints( GTK_WINDOW(cfg_win) , GTK_WIDGET(cfg_win) ,
-                                 &cfg_win_hints , GDK_HINT_MIN_SIZE );
-
-  cfg_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL , FALSE );
-  gtk_container_add( GTK_CONTAINER(cfg_win) , cfg_vbox );
-
-  cfg_nb = gtk_notebook_new();
-  gtk_notebook_set_tab_pos( GTK_NOTEBOOK(cfg_nb) , GTK_POS_TOP );
-  gtk_box_pack_start( GTK_BOX(cfg_vbox) , cfg_nb , TRUE , TRUE , 0 );
-
-  gtk_box_pack_start( GTK_BOX(cfg_vbox) , gtk_separator_new(GTK_ORIENTATION_HORIZONTAL) , FALSE , FALSE , 4 );
-
-  cfg_bbar_hbbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
-  gtk_button_box_set_layout( GTK_BUTTON_BOX(cfg_bbar_hbbox) , GTK_BUTTONBOX_START );
-  gtk_box_pack_start( GTK_BOX(cfg_vbox) , cfg_bbar_hbbox , FALSE , FALSE , 0 );
-  cfg_bbar_bt_test = audgui_button_new (_("_Test"), "media-playback-start", NULL, NULL);
-  gtk_container_add( GTK_CONTAINER(cfg_bbar_hbbox) , cfg_bbar_bt_test );
-  gtk_button_box_set_child_secondary( GTK_BUTTON_BOX(cfg_bbar_hbbox) , cfg_bbar_bt_test , FALSE );
-  cfg_bbar_bt_cancel = audgui_button_new (_("_Cancel"), "process-stop", NULL, NULL);
-  gtk_container_add( GTK_CONTAINER(cfg_bbar_hbbox) , cfg_bbar_bt_cancel );
-  gtk_button_box_set_child_secondary( GTK_BUTTON_BOX(cfg_bbar_hbbox) , cfg_bbar_bt_cancel , TRUE );
-  cfg_bbar_bt_ok = audgui_button_new (_("_Set"), "system-run", NULL, NULL);
-  gtk_container_add( GTK_CONTAINER(cfg_bbar_hbbox) , cfg_bbar_bt_ok );
-  gtk_button_box_set_child_secondary( GTK_BUTTON_BOX(cfg_bbar_hbbox) , cfg_bbar_bt_ok , TRUE );
-
-  /* add POSITION page */
-  cfg_position_widget = aosd_ui_configure_position( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_position_widget , gtk_label_new( _("Position") ) );
-
-  /* add ANIMATION page */
-  cfg_animation_widget = aosd_ui_configure_animation( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_animation_widget , gtk_label_new( _("Animation") ) );
-
-  /* add TEXT page */
-  cfg_text_widget = aosd_ui_configure_text( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_text_widget , gtk_label_new( _("Text") ) );
-
-  /* add DECORATION page */
-  cfg_decoration_widget = aosd_ui_configure_decoration( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_decoration_widget , gtk_label_new( _("Decoration") ) );
-
-  /* add TRIGGER page */
-  cfg_trigger_widget = aosd_ui_configure_trigger( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_trigger_widget , gtk_label_new( _("Trigger") ) );
-
-  /* add MISC page */
-  cfg_trigger_widget = aosd_ui_configure_misc( cfg , &cb_list );
-  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
-    cfg_trigger_widget , gtk_label_new( _("Misc") ) );
-
-  g_object_set_data( G_OBJECT(cfg_win) , "cblist" , cb_list );
-
-  g_signal_connect_swapped( G_OBJECT(cfg_bbar_bt_test) , "clicked" ,
-                            G_CALLBACK(aosd_cb_configure_test) , cfg_win );
-  g_signal_connect_swapped( G_OBJECT(cfg_bbar_bt_cancel) , "clicked" ,
-                            G_CALLBACK(aosd_cb_configure_cancel) , cfg_win );
-  g_signal_connect_swapped( G_OBJECT(cfg_bbar_bt_ok) , "clicked" ,
-                            G_CALLBACK(aosd_cb_configure_ok) , cfg_win );
-
-  gtk_widget_show_all( cfg_win );
-}
diff --git a/src/aosd/aosd_ui.cc b/src/aosd/aosd_ui.cc
new file mode 100644
index 000000000000..306d5228ac51
--- /dev/null
+++ b/src/aosd/aosd_ui.cc
@@ -0,0 +1,886 @@
+/*
+*
+* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
+*
+* 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
+*
+*/
+
+#include <math.h>
+
+#include <gtk/gtk.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/index.h>
+#include <libaudcore/preferences.h>
+
+#include "aosd.h"
+#include "aosd_style.h"
+#include "aosd_trigger.h"
+#include "aosd_cfg.h"
+#include "aosd_osd.h"
+
+
+static void chooser_get_aosd_color (GtkColorButton * chooser, aosd_color_t * color)
+{
+  GdkColor gdk_color;
+  gtk_color_button_get_color (chooser, & gdk_color);
+
+  color->red = gdk_color.red;
+  color->green = gdk_color.green;
+  color->blue = gdk_color.blue;
+  color->alpha = gtk_color_button_get_alpha (chooser);
+}
+
+
+static void chooser_set_aosd_color (GtkColorButton * chooser, const aosd_color_t * color)
+{
+  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_alpha (chooser, color->alpha);
+}
+
+
+/*************************************************************/
+/* small callback system used by the configuration interface */
+typedef void (*aosd_ui_cb_func_t)( GtkWidget * , aosd_cfg_t * );
+
+typedef struct
+{
+  GtkWidget * widget;
+  aosd_ui_cb_func_t func;
+}
+aosd_ui_cb_t;
+
+static Index<aosd_ui_cb_t> aosd_cb_list;
+
+static void
+aosd_callback_list_run ( aosd_cfg_t * cfg )
+{
+  for (const aosd_ui_cb_t & cb : aosd_cb_list)
+    cb.func (cb.widget, cfg);
+}
+/*************************************************************/
+
+
+
+static gboolean
+aosd_cb_configure_position_expose ( GtkWidget * darea ,
+                                    GdkEventExpose * event ,
+                                    void * coord_gp )
+{
+  int coord = GPOINTER_TO_INT(coord_gp);
+
+  cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (darea));
+  cairo_set_source_rgb ( cr , 0 , 0 , 0 );
+  cairo_rectangle ( cr , (coord % 3) * 10 , (coord / 3) * 16 , 20 , 8 );
+  cairo_fill ( cr );
+  cairo_destroy (cr);
+
+  return FALSE;
+}
+
+
+static void
+aosd_cb_configure_position_placement_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
+{
+  GList *placbt_list = gtk_container_get_children( GTK_CONTAINER(grid) );
+  GList *list_iter = placbt_list;
+
+  while ( list_iter != nullptr )
+  {
+    GtkWidget *placbt = (GtkWidget *) list_iter->data;
+    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;
+    }
+    list_iter = g_list_next( list_iter );
+  }
+
+  g_list_free( placbt_list );
+}
+
+
+static void
+aosd_cb_configure_position_offset_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
+{
+  cfg->position.offset_x = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"offx")) );
+  cfg->position.offset_y = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"offy")) );
+}
+
+
+static void
+aosd_cb_configure_position_maxsize_commit ( GtkWidget * grid , aosd_cfg_t * cfg )
+{
+  cfg->position.maxsize_width = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(grid),"maxsize_width")) );
+}
+
+
+static void
+aosd_cb_configure_position_multimon_commit ( GtkWidget * combo , aosd_cfg_t * cfg )
+{
+  int active = gtk_combo_box_get_active( GTK_COMBO_BOX(combo) );
+  cfg->position.multimon_id = ( active > -1 ) ? (active - 1) : -1;
+}
+
+
+static GtkWidget *
+aosd_ui_configure_position ( aosd_cfg_t * cfg )
+{
+  GtkWidget *pos_vbox;
+  GtkWidget *pos_placement_frame, *pos_placement_hbox, *pos_placement_grid;
+  GtkWidget *pos_placement_bt[9], *pos_placement_bt_darea[9];
+  GtkWidget *pos_offset_grid, *pos_offset_x_label, *pos_offset_x_spinbt;
+  GtkWidget *pos_offset_y_label, *pos_offset_y_spinbt;
+  GtkWidget *pos_maxsize_width_label, *pos_maxsize_width_spinbt;
+  GtkWidget *pos_multimon_frame, *pos_multimon_hbox;
+  GtkWidget *pos_multimon_label;
+  GtkWidget *pos_multimon_combobox;
+  int monitors_num = gdk_screen_get_n_monitors( gdk_screen_get_default() );
+  int i = 0;
+
+  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 );
+  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 );
+
+  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 );
+    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] );
+    g_signal_connect( G_OBJECT(pos_placement_bt_darea[i]) , "expose-event" ,
+                      G_CALLBACK(aosd_cb_configure_position_expose) , GINT_TO_POINTER(i) );
+    gtk_table_attach_defaults( GTK_TABLE(pos_placement_grid) , pos_placement_bt[i] ,
+                               (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_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 );
+
+  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:" ) );
+  gtk_misc_set_alignment( GTK_MISC(pos_offset_x_label) , 0 , 0.5 );
+  gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_offset_x_label , 0 , 1 , 0 , 1 );
+  pos_offset_x_spinbt = gtk_spin_button_new_with_range( -9999 , 9999 , 1 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(pos_offset_x_spinbt) , cfg->position.offset_x );
+  gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_offset_x_spinbt , 1 , 2 , 0 , 1 );
+  g_object_set_data( G_OBJECT(pos_offset_grid) , "offx" , pos_offset_x_spinbt );
+  pos_offset_y_label = gtk_label_new( _( "Relative Y offset:" ) );
+  gtk_misc_set_alignment( GTK_MISC(pos_offset_y_label) , 0 , 0.5 );
+  gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_offset_y_label , 0 , 1 , 1 , 2 );
+  pos_offset_y_spinbt = gtk_spin_button_new_with_range( -9999 , 9999 , 1 );
+  gtk_spin_button_set_value( GTK_SPIN_BUTTON(pos_offset_y_spinbt) , cfg->position.offset_y );
+  gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_offset_y_spinbt , 1 , 2 , 1 , 2 );
+  g_object_set_data( G_OBJECT(pos_offset_grid) , "offy" , pos_offset_y_spinbt );
+  pos_maxsize_width_label = gtk_label_new( _("Max OSD width:") );
+  gtk_misc_set_alignment( GTK_MISC(pos_maxsize_width_label) , 0 , 0.5 );
+  gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_maxsize_width_label , 0 , 1 , 2 , 3 );
+  pos_maxsize_width_spinbt = gtk_spin_button_new_with_range( 0 , 99999 , 1 );
+  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 );
+  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 );
+  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:") );
+  pos_multimon_combobox = gtk_combo_box_text_new ();
+  gtk_combo_box_text_append_text ((GtkComboBoxText *) pos_multimon_combobox, _("all monitors"));
+  for ( i = 0 ; i < monitors_num ; i++ )
+  {
+    char *mon_str = g_strdup_printf( _("monitor %i") , i + 1 );
+    gtk_combo_box_text_append_text ((GtkComboBoxText *) pos_multimon_combobox, mon_str);
+    g_free( mon_str );
+  }
+  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 );
+
+  return pos_vbox;
+}
+
+
+static GtkWidget *
+aosd_ui_configure_animation_timing ( char * label_string )
+{
+  GtkWidget *hbox, *desc_label, *spinbt;
+  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 );
+  g_object_set_data( G_OBJECT(hbox) , "spinbt" , spinbt );
+  return hbox;
+}
+
+
+static void
+aosd_cb_configure_animation_timing_commit ( GtkWidget * timing_hbox , aosd_cfg_t * cfg )
+{
+  cfg->animation.timing_display = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"display")) );
+  cfg->animation.timing_fadein = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"fadein")) );
+  cfg->animation.timing_fadeout = gtk_spin_button_get_value_as_int(
+    GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(timing_hbox),"fadeout")) );
+}
+
+
+static GtkWidget *
+aosd_ui_configure_animation ( aosd_cfg_t * cfg )
+{
+  GtkWidget *ani_vbox;
+  GtkWidget *ani_timing_frame, *ani_timing_hbox;
+  GtkWidget *ani_timing_fadein_widget, *ani_timing_fadeout_widget, *ani_timing_stay_widget;
+  GtkSizeGroup *sizegroup;
+
+  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_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 );
+
+  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 );
+  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 );
+  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 );
+  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" ,
+    g_object_get_data(G_OBJECT(ani_timing_fadein_widget),"spinbt") );
+  g_object_set_data( G_OBJECT(ani_timing_hbox) , "fadeout" ,
+    g_object_get_data(G_OBJECT(ani_timing_fadeout_widget),"spinbt") );
+  sizegroup = gtk_size_group_new( GTK_SIZE_GROUP_HORIZONTAL );
+  gtk_size_group_add_widget( sizegroup , ani_timing_stay_widget );
+  gtk_size_group_add_widget( sizegroup , ani_timing_fadein_widget );
+  gtk_size_group_add_widget( sizegroup , ani_timing_fadeout_widget );
+  aosd_cb_list.append( ani_timing_hbox , aosd_cb_configure_animation_timing_commit );
+
+  return ani_vbox;
+}
+
+
+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 );
+  else
+    gtk_widget_set_sensitive( GTK_WIDGET(shadow_colorbt) , FALSE );
+}
+
+
+static void
+aosd_cb_configure_text_font_commit ( GtkWidget * fontbt , aosd_cfg_t * cfg )
+{
+  int fontnum = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(fontbt) , "fontnum" ));
+  GtkColorButton * chooser;
+
+  cfg->text.fonts_name[fontnum] =
+   String (gtk_font_button_get_font_name (GTK_FONT_BUTTON (fontbt)));
+
+  cfg->text.fonts_draw_shadow[fontnum] = gtk_toggle_button_get_active(
+    GTK_TOGGLE_BUTTON(g_object_get_data(G_OBJECT(fontbt),"use_shadow")) );
+
+  chooser = (GtkColorButton *) g_object_get_data ((GObject *) fontbt, "color");
+  chooser_get_aosd_color (chooser, & cfg->text.fonts_color[fontnum]);
+
+  chooser = (GtkColorButton *) g_object_get_data ((GObject *) fontbt, "shadow_color");
+  chooser_get_aosd_color (chooser, & cfg->text.fonts_shadow_color[fontnum]);
+}
+
+
+static GtkWidget *
+aosd_ui_configure_text ( aosd_cfg_t * cfg )
+{
+  GtkWidget *tex_vbox;
+  GtkWidget *tex_font_grid, *tex_font_frame;
+  GtkWidget *tex_font_label[3], *tex_font_fontbt[3];
+  GtkWidget *tex_font_colorbt[3], *tex_font_shadow_togglebt[3];
+  GtkWidget *tex_font_shadow_colorbt[3];
+  int i = 0;
+
+  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);
+  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 );
+  for ( i = 0 ; i < AOSD_TEXT_FONTS_NUM ; i++ )
+  {
+    char *label_str = g_strdup_printf( _("Font %i:") , i+1 );
+    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_font_name( GTK_FONT_BUTTON(tex_font_fontbt[i]) , cfg->text.fonts_name[i] );
+
+    tex_font_colorbt[i] = gtk_color_button_new ();
+    chooser_set_aosd_color ((GtkColorButton *) tex_font_colorbt[i],
+     & 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 );
+
+    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 );
+    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] );
+    gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(tex_font_shadow_togglebt[i]) ,
+      cfg->text.fonts_draw_shadow[i] );
+    gtk_table_attach_defaults( GTK_TABLE(tex_font_grid) , tex_font_label[i] , 0 , 1 , i , i + 1 );
+    gtk_table_attach_defaults( GTK_TABLE(tex_font_grid) , tex_font_fontbt[i] , 1 , 2 , i , i + 1 );
+    gtk_table_attach_defaults( GTK_TABLE(tex_font_grid) , tex_font_colorbt[i] , 2 , 3 , i , i + 1 );
+    gtk_table_attach_defaults( GTK_TABLE(tex_font_grid) , tex_font_shadow_togglebt[i] , 3 , 4 , i , i + 1 );
+    gtk_table_attach_defaults( GTK_TABLE(tex_font_grid) , tex_font_shadow_colorbt[i] , 4 , 5 , i , i + 1 );
+    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "fontnum" , GINT_TO_POINTER(i) );
+    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "color" , tex_font_colorbt[i] );
+    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "use_shadow" , tex_font_shadow_togglebt[i] );
+    g_object_set_data( G_OBJECT(tex_font_fontbt[i]) , "shadow_color" , tex_font_shadow_colorbt[i] );
+    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 );
+
+  return tex_vbox;
+}
+
+
+static void
+aosd_cb_configure_decoration_style_commit ( GtkWidget * lv , aosd_cfg_t * cfg )
+{
+  GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(lv) );
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE )
+  {
+    int deco_code = 0;
+    gtk_tree_model_get( model , &iter , 1 , &deco_code , -1 );
+    cfg->decoration.code = deco_code;
+  }
+}
+
+
+static void
+aosd_cb_configure_decoration_color_commit ( GtkWidget * colorbt , aosd_cfg_t * cfg )
+{
+  aosd_color_t color;
+  chooser_get_aosd_color ((GtkColorButton *) colorbt, & color);
+
+  int colnum = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(colorbt) , "colnum" ) );
+  cfg->decoration.colors[colnum] = color;
+}
+
+
+static GtkWidget *
+aosd_ui_configure_decoration ( aosd_cfg_t * cfg )
+{
+  GtkWidget *dec_hbox;
+  GtkWidget *dec_rstyle_lv, *dec_rstyle_lv_frame, *dec_rstyle_lv_sw;
+  GtkListStore *dec_rstyle_store;
+  GtkCellRenderer *dec_rstyle_lv_rndr_text;
+  GtkTreeViewColumn *dec_rstyle_lv_col_desc;
+  GtkTreeSelection *dec_rstyle_lv_sel;
+  GtkTreeIter iter, iter_sel;
+  GtkWidget *dec_rstyle_hbox;
+  GtkWidget *dec_rstyleopts_frame, *dec_rstyleopts_grid;
+  int colors_max_num = 0, i = 0;
+
+  dec_hbox = gtk_hbox_new( FALSE , 4 );
+  gtk_container_set_border_width( GTK_CONTAINER(dec_hbox) , 6 );
+
+  /* decoration style model
+     ---------------------------------------------
+     G_TYPE_STRING -> decoration description
+     G_TYPE_INT -> decoration code
+     G_TYPE_INT -> number of user-definable colors
+     ---------------------------------------------
+  */
+  dec_rstyle_store = gtk_list_store_new( 3 , G_TYPE_STRING , G_TYPE_INT , G_TYPE_INT );
+  for ( i = 0 ; i < AOSD_NUM_DECO_STYLES ; i++ )
+  {
+    int colors_num = aosd_deco_style_get_numcol( i );
+    if ( colors_num > colors_max_num )
+      colors_max_num = colors_num;
+    gtk_list_store_append( dec_rstyle_store , &iter );
+    gtk_list_store_set( dec_rstyle_store , &iter ,
+      0 , _(aosd_deco_style_get_desc( i )) ,
+      1 , i , 2 , colors_num , -1 );
+    if ( i == cfg->decoration.code )
+      iter_sel = iter;
+  }
+
+  dec_rstyle_lv_frame = gtk_frame_new( nullptr );
+  dec_rstyle_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(dec_rstyle_store) );
+  g_object_unref( dec_rstyle_store );
+  dec_rstyle_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(dec_rstyle_lv) );
+  gtk_tree_selection_set_mode( dec_rstyle_lv_sel , GTK_SELECTION_BROWSE );
+
+  dec_rstyle_lv_rndr_text = gtk_cell_renderer_text_new();
+  dec_rstyle_lv_col_desc = gtk_tree_view_column_new_with_attributes(
+    _("Render Style") , dec_rstyle_lv_rndr_text , "text" , 0 , nullptr );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(dec_rstyle_lv), dec_rstyle_lv_col_desc );
+  dec_rstyle_lv_sw = gtk_scrolled_window_new( nullptr , nullptr );
+  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(dec_rstyle_lv_sw) ,
+                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
+  gtk_container_add( GTK_CONTAINER(dec_rstyle_lv_sw) , dec_rstyle_lv );
+  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 );
+  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 );
+
+  /* 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);
+  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 );
+  gtk_container_add( GTK_CONTAINER(dec_rstyleopts_frame) , dec_rstyleopts_grid );
+  for ( i = 0 ; i < colors_max_num ; i++ )
+  {
+    GtkWidget *hbox, *label;
+    char *label_str = nullptr;
+    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 );
+
+    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_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 );
+
+  return dec_hbox;
+}
+
+
+static void
+aosd_cb_configure_trigger_lvchanged ( GtkTreeSelection *sel , void * nb )
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE )
+  {
+    int page_num = 0;
+    gtk_tree_model_get( model , &iter , 2 , &page_num , -1 );
+    gtk_notebook_set_current_page( GTK_NOTEBOOK(nb) , page_num );
+  }
+}
+
+
+static void
+aosd_cb_configure_trigger_commit ( GtkWidget * cbt , aosd_cfg_t * cfg )
+{
+  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;
+  }
+}
+
+
+static GtkWidget *
+aosd_ui_configure_trigger ( aosd_cfg_t * cfg )
+{
+  GtkWidget *tri_hbox;
+  GtkWidget *tri_event_lv, *tri_event_lv_frame, *tri_event_lv_sw;
+  GtkListStore *tri_event_store;
+  GtkCellRenderer *tri_event_lv_rndr_text;
+  GtkTreeViewColumn *tri_event_lv_col_desc;
+  GtkTreeSelection *tri_event_lv_sel;
+  GtkTreeIter iter;
+  GtkWidget *tri_event_nb;
+  int i = 0;
+
+  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 );
+
+  tri_hbox = gtk_hbox_new( FALSE , 4 );
+  gtk_container_set_border_width( GTK_CONTAINER(tri_hbox) , 6 );
+
+  /* trigger model
+     ---------------------------------------------
+     G_TYPE_STRING -> trigger description
+     G_TYPE_INT -> trigger code
+     G_TYPE_INT -> gtk notebook page number
+     ---------------------------------------------
+  */
+  tri_event_store = gtk_list_store_new( 3 , G_TYPE_STRING , G_TYPE_INT , G_TYPE_INT );
+  for ( i = 0 ; i < AOSD_NUM_TRIGGERS ; i ++ )
+  {
+    GtkWidget *frame, *vbox, *label, *checkbt;
+    gtk_list_store_append( tri_event_store , &iter );
+    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 );
+    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_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 );
+    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 );
+    frame = gtk_frame_new( nullptr );
+    gtk_container_add( GTK_CONTAINER(frame) , vbox );
+    gtk_notebook_append_page( GTK_NOTEBOOK(tri_event_nb) , frame , nullptr );
+    g_object_set_data( G_OBJECT(checkbt) , "code" , GINT_TO_POINTER(i) );
+    aosd_cb_list.append( checkbt , aosd_cb_configure_trigger_commit );
+  }
+
+  tri_event_lv_frame = gtk_frame_new( nullptr );
+  tri_event_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(tri_event_store) );
+  g_object_unref( tri_event_store );
+  tri_event_lv_sel = gtk_tree_view_get_selection( GTK_TREE_VIEW(tri_event_lv) );
+  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 )
+    gtk_tree_selection_select_iter( tri_event_lv_sel , &iter );
+
+  tri_event_lv_rndr_text = gtk_cell_renderer_text_new();
+  tri_event_lv_col_desc = gtk_tree_view_column_new_with_attributes(
+    _("Event") , tri_event_lv_rndr_text , "text" , 0 , nullptr );
+  gtk_tree_view_append_column( GTK_TREE_VIEW(tri_event_lv), tri_event_lv_col_desc );
+  tri_event_lv_sw = gtk_scrolled_window_new( nullptr , nullptr );
+  gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tri_event_lv_sw) ,
+                                  GTK_POLICY_NEVER , GTK_POLICY_ALWAYS );
+  gtk_container_add( GTK_CONTAINER(tri_event_lv_sw) , tri_event_lv );
+  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_nb , TRUE , TRUE , 0 );
+
+  return tri_hbox;
+}
+
+
+#ifdef HAVE_XCOMPOSITE
+static void
+aosd_cb_configure_misc_transp_real_clicked ( GtkToggleButton * real_rbt , void * status_hbox )
+{
+  GtkWidget *img = (GtkWidget *) g_object_get_data( G_OBJECT(status_hbox) , "img" );
+  GtkWidget *label = (GtkWidget *) g_object_get_data( G_OBJECT(status_hbox) , "label" );
+  if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(real_rbt) ) )
+  {
+    if ( aosd_osd_check_composite_mgr() )
+    {
+      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 );
+    }
+    else
+    {
+      gtk_image_set_from_icon_name( GTK_IMAGE(img) , "dialog-warning" , GTK_ICON_SIZE_MENU );
+      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 );
+    }
+  }
+  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 );
+  }
+}
+#endif
+
+
+static void
+aosd_cb_configure_misc_transp_commit ( GtkWidget * mis_transp_vbox , aosd_cfg_t * cfg )
+{
+  GList *child_list = gtk_container_get_children( GTK_CONTAINER(mis_transp_vbox) );
+  while (child_list != nullptr)
+  {
+    if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(child_list->data) ) )
+    {
+      cfg->misc.transparency_mode = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(child_list->data),"val"));
+      break;
+    }
+    child_list = g_list_next(child_list);
+  }
+}
+
+
+static GtkWidget *
+aosd_ui_configure_misc ( aosd_cfg_t * cfg )
+{
+  GtkWidget *mis_vbox;
+  GtkWidget *mis_transp_frame, *mis_transp_vbox;
+  GtkWidget *mis_transp_fake_rbt, *mis_transp_real_rbt;
+  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 );
+  gtk_container_set_border_width( GTK_CONTAINER(mis_vbox) , 6 );
+
+  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 );
+
+  mis_transp_fake_rbt = gtk_radio_button_new_with_label( nullptr ,
+                          _("Fake transparency") );
+  mis_transp_real_rbt = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(mis_transp_fake_rbt) ,
+                          _("Real transparency (requires X Composite Ext.)") );
+  g_object_set_data( G_OBJECT(mis_transp_fake_rbt) , "val" ,
+                     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 );
+
+  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 );
+
+  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 );
+  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 );
+
+#ifdef HAVE_XCOMPOSITE
+  g_signal_connect( G_OBJECT(mis_transp_real_rbt) , "toggled" ,
+    G_CALLBACK(aosd_cb_configure_misc_transp_real_clicked) , mis_transp_status_hbox );
+
+  /* check if the composite extension is loaded */
+  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 );
+    else
+      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_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 );
+  }
+#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_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 );
+#endif
+
+  aosd_cb_list.append( mis_transp_vbox , aosd_cb_configure_misc_transp_commit );
+
+  return mis_vbox;
+}
+
+
+static void
+aosd_cb_configure_test ( void )
+{
+  aosd_cfg_t cfg = aosd_cfg_t ();
+  aosd_callback_list_run (& cfg);
+
+  char * markup_message = g_markup_printf_escaped
+   (_("<span font_desc='%s'>Audacious OSD</span>"),
+   (const char *) cfg.text.fonts_name[0]);
+
+  aosd_osd_shutdown (); /* stop any displayed osd */
+  aosd_osd_cleanup (); /* just in case it's active */
+  aosd_osd_init (cfg.misc.transparency_mode);
+  aosd_osd_display (markup_message, & cfg, true);
+
+  g_free (markup_message);
+}
+
+
+static void
+aosd_cb_configure_cancel ( void )
+{
+  aosd_cb_list.clear ();
+
+  aosd_osd_shutdown (); /* stop any displayed osd */
+  aosd_osd_cleanup (); /* just in case it's active */
+  aosd_osd_init (global_config.misc.transparency_mode);
+}
+
+
+static void
+aosd_cb_configure_ok ( void )
+{
+  aosd_cfg_t cfg = aosd_cfg_t ();
+
+  aosd_callback_list_run (& cfg);
+  aosd_cb_list.clear ();
+
+  aosd_osd_shutdown (); /* stop any displayed osd */
+  aosd_osd_cleanup (); /* just in case it's active */
+
+  aosd_trigger_stop (global_config.trigger); /* stop triggers */
+  global_config = cfg; /* put the new config */
+  aosd_cfg_save (cfg); /* save the new configuration on config file */
+  aosd_osd_init (cfg.misc.transparency_mode); /* restart osd */
+  aosd_trigger_start (cfg.trigger); /* restart triggers */
+}
+
+
+static void *
+aosd_ui_configure ( void )
+{
+  GtkWidget *cfg_nb;
+  GtkWidget *cfg_position_widget;
+  GtkWidget *cfg_animation_widget;
+  GtkWidget *cfg_text_widget;
+  GtkWidget *cfg_decoration_widget;
+  GtkWidget *cfg_trigger_widget;
+
+  /* create a new configuration object */
+  aosd_cfg_t cfg = aosd_cfg_t();
+  /* fill it with information from config file */
+  aosd_cfg_load( cfg );
+
+  cfg_nb = gtk_notebook_new();
+  gtk_notebook_set_tab_pos( GTK_NOTEBOOK(cfg_nb) , GTK_POS_TOP );
+
+  /* add POSITION page */
+  cfg_position_widget = aosd_ui_configure_position( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_position_widget , gtk_label_new( _("Position") ) );
+
+  /* add ANIMATION page */
+  cfg_animation_widget = aosd_ui_configure_animation( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_animation_widget , gtk_label_new( _("Animation") ) );
+
+  /* add TEXT page */
+  cfg_text_widget = aosd_ui_configure_text( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_text_widget , gtk_label_new( _("Text") ) );
+
+  /* add DECORATION page */
+  cfg_decoration_widget = aosd_ui_configure_decoration( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_decoration_widget , gtk_label_new( _("Decoration") ) );
+
+  /* add TRIGGER page */
+  cfg_trigger_widget = aosd_ui_configure_trigger( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_trigger_widget , gtk_label_new( _("Trigger") ) );
+
+  /* add MISC page */
+  cfg_trigger_widget = aosd_ui_configure_misc( &cfg );
+  gtk_notebook_append_page( GTK_NOTEBOOK(cfg_nb) ,
+    cfg_trigger_widget , gtk_label_new( _("Misc") ) );
+
+  return cfg_nb;
+}
+
+
+const PreferencesWidget AOSD::widgets[] = {
+    WidgetCustomGTK (aosd_ui_configure),
+    WidgetSeparator ({true}),
+    WidgetButton (N_("Test"), {aosd_cb_configure_test, "media-playback-start"})
+};
+
+const PluginPreferences AOSD::prefs = {
+    {widgets},
+    nullptr,  // init
+    aosd_cb_configure_ok,
+    aosd_cb_configure_cancel
+};
diff --git a/src/aosd/aosd_ui.h b/src/aosd/aosd_ui.h
deleted file mode 100644
index 16810c0fc1af..000000000000
--- a/src/aosd/aosd_ui.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-*
-* Author: Giacomo Lozito <james at develia.org>, (C) 2005-2007
-*
-* 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 _I_AOSD_UI_H
-#define _I_AOSD_UI_H 1
-
-#undef PACKAGE
-#define PACKAGE "audacious-plugins"
-
-#include "aosd_common.h"
-#include "aosd_cfg.h"
-#include <glib.h>
-
-void aosd_ui_configure ( aosd_cfg_t * );
-
-#endif /* !_I_AOSD_UI_H */
diff --git a/src/aosd/ghosd.c b/src/aosd/ghosd.c
index f3e36ced844e..cfe388658caf 100644
--- a/src/aosd/ghosd.c
+++ b/src/aosd/ghosd.c
@@ -8,8 +8,6 @@
  * - added/changed some other stuff
  */
 
-#include "aosd_common.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <cairo/cairo-xlib-xrender.h>
diff --git a/src/aosd/ghosd.h b/src/aosd/ghosd.h
index 4f82efa1da96..70c36a7d184e 100644
--- a/src/aosd/ghosd.h
+++ b/src/aosd/ghosd.h
@@ -16,8 +16,6 @@
 #include <limits.h>  /* INT_MAX */
 #include <sys/time.h>  /* timeval */
 
-#include "aosd_common.h"
-
 typedef struct _Ghosd Ghosd;
 
 /* minimal struct to handle button events */
@@ -34,6 +32,10 @@ GhosdEventButton;
 typedef void (*GhosdRenderFunc)(Ghosd *ghosd, cairo_t *cr, void *user_data);
 typedef void (*GhosdEventButtonCb)(Ghosd *ghosd, GhosdEventButton *event, void *user_data);
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 Ghosd *ghosd_new(void);
 void   ghosd_destroy(Ghosd* ghosd);
 #ifdef HAVE_XCOMPOSITE
@@ -60,6 +62,10 @@ void ghosd_flash(Ghosd *ghosd, int fade_ms, int total_display_ms);
 
 int ghosd_get_socket(Ghosd *ghosd);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __GHOSD_H__ */
 
 /* vim: set ts=2 sw=2 et cino=(0 : */
diff --git a/src/asx/Makefile b/src/asx/Makefile
index d867744a8991..3efffb77b93f 100644
--- a/src/asx/Makefile
+++ b/src/asx/Makefile
@@ -1,11 +1,13 @@
 PLUGIN = asx${PLUGIN_SUFFIX}
-SRCS = asx.c
+SRCS = asx.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+
diff --git a/src/asx/asx.c b/src/asx/asx.c
deleted file mode 100644
index 28d96f40fbbb..000000000000
--- a/src/asx/asx.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * asx.c
- * Copyright 2010-2013 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:
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/inifile.h>
-
-typedef struct {
-    const char * filename;
-    bool_t valid_heading;
-    Index * filenames;
-} ASXLoadState;
-
-void asx_handle_heading (const char * heading, void * data)
-{
-    ASXLoadState * state = data;
-
-    state->valid_heading = ! g_ascii_strcasecmp (heading, "reference");
-}
-
-void asx_handle_entry (const char * key, const char * value, void * data)
-{
-    ASXLoadState * state = data;
-
-    if (! state->valid_heading || g_ascii_strncasecmp (key, "ref", 3))
-        return;
-
-    char * uri = aud_construct_uri (value, state->filename);
-    if (! uri)
-        return;
-
-    if (! strncmp ("http://", uri, 7))
-    {
-        index_insert (state->filenames, -1, str_printf ("mms://%s", uri + 7));
-        str_unref (uri);
-    }
-    else
-        index_insert (state->filenames, -1, uri);
-}
-
-static bool_t playlist_load_asx (const char * filename, VFSFile * file,
- char * * title, Index * filenames, Index * tuples)
-{
-    ASXLoadState state = {
-        .filename = filename,
-        .valid_heading = FALSE,
-        .filenames = filenames
-    };
-
-    inifile_parse (file, asx_handle_heading, asx_handle_entry, & state);
-
-    return (index_count (filenames) != 0);
-}
-
-static const char * const asx_exts[] = {"asx", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
-    .name = N_("ASXv1/ASXv2 Playlists"),
-    .domain = PACKAGE,
-    .extensions = asx_exts,
-    .load = playlist_load_asx
-)
diff --git a/src/asx/asx.cc b/src/asx/asx.cc
new file mode 100644
index 000000000000..9b066a215e61
--- /dev/null
+++ b/src/asx/asx.cc
@@ -0,0 +1,80 @@
+/*
+ * asx.c
+ * Copyright 2010-2013 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:
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/inifile.h>
+
+static const char * const asx_exts[] = {"asx"};
+
+class ASXLoader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("ASXv1/ASXv2 Playlists"), PACKAGE};
+
+    constexpr ASXLoader () : PlaylistPlugin (info, asx_exts, false) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+};
+
+EXPORT ASXLoader aud_plugin_instance;
+
+class ASXParser : public IniParser
+{
+public:
+    ASXParser (const char * filename, Index<PlaylistAddItem> & items) :
+        filename (filename),
+        items (items),
+        valid_heading (false) {}
+
+private:
+    const char * filename;
+    Index<PlaylistAddItem> & items;
+    bool valid_heading;
+
+    void handle_heading (const char * heading)
+        { valid_heading = ! strcmp_nocase (heading, "reference"); }
+
+    void handle_entry (const char * key, const char * value)
+    {
+        if (! valid_heading || ! str_has_prefix_nocase (key, "ref"))
+            return;
+
+        StringBuf uri = uri_construct (value, filename);
+        if (! uri)
+            return;
+
+        if (! strncmp ("http://", uri, 7))
+            items.append (String (str_printf ("mms://%s", uri + 7)));
+        else
+            items.append (String (uri));
+    }
+};
+
+bool ASXLoader::load (const char * filename, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    ASXParser (filename, items).parse (file);
+    return (items.len () > 0);
+}
diff --git a/src/asx3/Makefile b/src/asx3/Makefile
index 56a7132a7346..e5abfb0c2948 100644
--- a/src/asx3/Makefile
+++ b/src/asx3/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = asx3${PLUGIN_SUFFIX}
 
-SRCS = asx3.c
+SRCS = asx3.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${XML_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${XML_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${XML_CFLAGS} -I../..
+LIBS += ${XML_LIBS}
diff --git a/src/asx3/asx3.c b/src/asx3/asx3.c
deleted file mode 100644
index 82ec0580c111..000000000000
--- a/src/asx3/asx3.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * asx3.c
- * Copyright 2013 Martin Steiger and 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 <stdio.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlsave.h>
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-static int read_cb (void * file, char * buf, int len)
-{
-    return vfs_fread (buf, 1, len, file);
-}
-
-static int write_cb (void * file, const char * buf, int len)
-{
-    return vfs_fwrite (buf, 1, len, file);
-}
-
-static int close_cb (void * file)
-{
-    return 0;
-}
-
-static const char * get_content (const xmlNode * node)
-{
-    const xmlNode * child = node->xmlChildrenNode;
-    if (child && child->type == XML_TEXT_NODE && child->content)
-        return (const char *) child->content;
-
-    return NULL;
-}
-
-static const char * get_prop_nocase (const xmlNode * node, const char * name)
-{
-    for (const xmlAttr * prop = node->properties; prop; prop = prop->next)
-    {
-        if (! xmlStrcasecmp (prop->name, (const xmlChar *) name))
-        {
-            const xmlNode * child = prop->children;
-            if (child && child->type == XML_TEXT_NODE && child->content)
-                return (const char *) child->content;
-        }
-    }
-
-    return NULL;
-}
-
-static bool_t check_root (const xmlNode * root)
-{
-    if (xmlStrcasecmp (root->name, (const xmlChar *) "asx"))
-    {
-        fprintf(stderr, "asx3: Not an ASX file\n");
-        return FALSE;
-    }
-
-    const char * version = get_prop_nocase (root, "version");
-
-    if (! version)
-    {
-        fprintf (stderr, "asx3: Unknown ASX version\n");
-        return FALSE;
-    }
-
-    if (strcmp (version, "3.0"))
-    {
-        fprintf(stderr, "asx3: Unsupported ASX version (%s)\n", version);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static void parse_entry (const xmlNode * entry, Index * filenames)
-{
-    for (const xmlNode * node = entry->xmlChildrenNode; node; node = node->next)
-    {
-        if (! xmlStrcasecmp (node->name, (const xmlChar *) "ref"))
-        {
-            const char * uri = get_prop_nocase (node, "href");
-            if (uri)
-                index_insert (filenames, -1, str_get (uri));
-        }
-    }
-}
-
-static bool_t playlist_load_asx3 (const char * filename, VFSFile * file,
- char * * title, Index * filenames, Index * tuples)
-{
-    xmlDoc * doc = xmlReadIO (read_cb, close_cb, file, filename, NULL, XML_PARSE_RECOVER);
-    if (! doc)
-        return FALSE;
-
-    xmlNode * root = xmlDocGetRootElement (doc);
-
-    if (! root || ! check_root (root))
-    {
-        xmlFreeDoc(doc);
-        return FALSE;
-    }
-
-    for (xmlNode * node = root->xmlChildrenNode; node; node = node->next)
-    {
-        if (! xmlStrcasecmp (node->name, (const xmlChar *) "entry"))
-            parse_entry (node, filenames);
-        else if (! xmlStrcasecmp (node->name, (const xmlChar *) "title"))
-        {
-            if (! (* title))
-                * title = str_get (get_content (node));
-        }
-    }
-
-    xmlFreeDoc(doc);
-    return TRUE;
-}
-
-static bool_t playlist_save_asx3 (const char * filename, VFSFile * file,
- const char * title, Index * filenames, Index * tuples)
-{
-    xmlDoc * doc = xmlNewDoc ((const xmlChar *) "1.0");
-    doc->charset = XML_CHAR_ENCODING_UTF8;
-    doc->encoding = xmlStrdup ((const xmlChar *) "UTF-8");
-
-    xmlNode * root = xmlNewNode (NULL, (const xmlChar *) "asx");
-    xmlSetProp (root, (const xmlChar *) "version", (const xmlChar *) "3.0");
-    xmlDocSetRootElement (doc, root);
-
-    if (title)
-        xmlNewTextChild (root, NULL, (const xmlChar *) "title", (const xmlChar *) title);
-
-    int entries = index_count (filenames);
-    for (int i = 0; i < entries; i ++)
-    {
-        xmlNode * entry = xmlNewNode (NULL, (const xmlChar *) "entry");
-        xmlNode * ref = xmlNewNode (NULL, (const xmlChar *) "ref");
-        xmlSetProp (ref, (const xmlChar *) "href", (const xmlChar *) index_get (filenames, i));
-        xmlAddChild (entry, ref);
-        xmlAddChild (root, entry);
-    }
-
-    xmlSaveCtxt * save = xmlSaveToIO (write_cb, close_cb, file, NULL, XML_SAVE_FORMAT);
-
-    if (! save || xmlSaveDoc (save, doc) < 0 || xmlSaveClose (save) < 0)
-    {
-        xmlFreeDoc(doc);
-        return FALSE;
-    }
-
-    xmlFreeDoc (doc);
-    return TRUE;
-}
-
-static const char * const asx3_exts[] = {"asx", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
-    .name = N_("ASXv3 Playlists"),
-    .domain = PACKAGE,
-    .extensions = asx3_exts,
-    .load = playlist_load_asx3,
-    .save = playlist_save_asx3
-)
diff --git a/src/asx3/asx3.cc b/src/asx3/asx3.cc
new file mode 100644
index 000000000000..3ab2dd943407
--- /dev/null
+++ b/src/asx3/asx3.cc
@@ -0,0 +1,187 @@
+/*
+ * asx3.c
+ * Copyright 2013 Martin Steiger and 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 <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlsave.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+static const char * const asx3_exts[] = {"asx"};
+
+class ASX3Loader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("ASXv3 Playlists"), PACKAGE};
+
+    constexpr ASX3Loader () : PlaylistPlugin (info, asx3_exts, true) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+    bool save (const char * filename, VFSFile & file, const char * title,
+     const Index<PlaylistAddItem> & items);
+};
+
+EXPORT ASX3Loader aud_plugin_instance;
+
+static int read_cb (void * file, char * buf, int len)
+{
+    return ((VFSFile *) file)->fread (buf, 1, len);
+}
+
+static int write_cb (void * file, const char * buf, int len)
+{
+    return ((VFSFile *) file)->fwrite (buf, 1, len);
+}
+
+static int close_cb (void * file)
+{
+    return 0;
+}
+
+static const char * get_content (const xmlNode * node)
+{
+    const xmlNode * child = node->xmlChildrenNode;
+    if (child && child->type == XML_TEXT_NODE && child->content)
+        return (const char *) child->content;
+
+    return nullptr;
+}
+
+static const char * get_prop_nocase (const xmlNode * node, const char * name)
+{
+    for (const xmlAttr * prop = node->properties; prop; prop = prop->next)
+    {
+        if (! xmlStrcasecmp (prop->name, (const xmlChar *) name))
+        {
+            const xmlNode * child = prop->children;
+            if (child && child->type == XML_TEXT_NODE && child->content)
+                return (const char *) child->content;
+        }
+    }
+
+    return nullptr;
+}
+
+static bool check_root (const xmlNode * root)
+{
+    if (xmlStrcasecmp (root->name, (const xmlChar *) "asx"))
+    {
+        AUDERR ("Not an ASX file\n");
+        return false;
+    }
+
+    const char * version = get_prop_nocase (root, "version");
+
+    if (! version)
+    {
+        AUDERR ("Unknown ASX version\n");
+        return false;
+    }
+
+    if (strcmp (version, "3.0"))
+    {
+        AUDERR ("Unsupported ASX version (%s)\n", version);
+        return false;
+    }
+
+    return true;
+}
+
+static void parse_entry (const xmlNode * entry, Index<PlaylistAddItem> & items)
+{
+    for (const xmlNode * node = entry->xmlChildrenNode; node; node = node->next)
+    {
+        if (! xmlStrcasecmp (node->name, (const xmlChar *) "ref"))
+        {
+            const char * uri = get_prop_nocase (node, "href");
+            if (uri)
+                items.append (String (uri));
+        }
+    }
+}
+
+bool ASX3Loader::load (const char * filename, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    xmlDoc * doc = xmlReadIO (read_cb, close_cb, & file, filename, nullptr, XML_PARSE_RECOVER);
+    if (! doc)
+        return false;
+
+    xmlNode * root = xmlDocGetRootElement (doc);
+
+    if (! root || ! check_root (root))
+    {
+        xmlFreeDoc(doc);
+        return false;
+    }
+
+    for (xmlNode * node = root->xmlChildrenNode; node; node = node->next)
+    {
+        if (! xmlStrcasecmp (node->name, (const xmlChar *) "entry"))
+            parse_entry (node, items);
+        else if (! xmlStrcasecmp (node->name, (const xmlChar *) "title"))
+        {
+            if (! title)
+                title = String (get_content (node));
+        }
+    }
+
+    xmlFreeDoc(doc);
+    return true;
+}
+
+bool ASX3Loader::save (const char * filename, VFSFile & file,
+ const char * title, const Index<PlaylistAddItem> & items)
+{
+    xmlDoc * doc = xmlNewDoc ((const xmlChar *) "1.0");
+    doc->charset = XML_CHAR_ENCODING_UTF8;
+    doc->encoding = xmlStrdup ((const xmlChar *) "UTF-8");
+
+    xmlNode * root = xmlNewNode (nullptr, (const xmlChar *) "asx");
+    xmlSetProp (root, (const xmlChar *) "version", (const xmlChar *) "3.0");
+    xmlDocSetRootElement (doc, root);
+
+    if (title)
+        xmlNewTextChild (root, nullptr, (const xmlChar *) "title", (const xmlChar *) title);
+
+    for (auto & item : items)
+    {
+        xmlNode * entry = xmlNewNode (nullptr, (const xmlChar *) "entry");
+        xmlNode * ref = xmlNewNode (nullptr, (const xmlChar *) "ref");
+        xmlSetProp (ref, (const xmlChar *) "href", (const xmlChar *) (const char *) item.filename);
+        xmlAddChild (entry, ref);
+        xmlAddChild (root, entry);
+    }
+
+    xmlSaveCtxt * save = xmlSaveToIO (write_cb, close_cb, & file, nullptr, XML_SAVE_FORMAT);
+
+    if (! save || xmlSaveDoc (save, doc) < 0 || xmlSaveClose (save) < 0)
+    {
+        xmlFreeDoc(doc);
+        return false;
+    }
+
+    xmlFreeDoc (doc);
+    return true;
+}
diff --git a/src/audpl/Makefile b/src/audpl/Makefile
index 243a09408cd5..3a86ec9632f7 100644
--- a/src/audpl/Makefile
+++ b/src/audpl/Makefile
@@ -1,11 +1,13 @@
 PLUGIN = audpl${PLUGIN_SUFFIX}
 
-SRCS = audpl.c
+SRCS = audpl.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../..
 CFLAGS += ${PLUGIN_CFLAGS}
diff --git a/src/audpl/audpl.c b/src/audpl/audpl.c
deleted file mode 100644
index 25aa621ecde2..000000000000
--- a/src/audpl/audpl.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Audacious playlist format plugin
- * Copyright 2011 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 <stdlib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/inifile.h>
-
-typedef struct {
-    char * * title;
-    Index * filenames;
-    Index * tuples;
-    char * uri;
-    Tuple * tuple;
-} LoadState;
-
-static void finish_item (LoadState * state)
-{
-    index_insert (state->filenames, -1, state->uri);
-    index_insert (state->tuples, -1, state->tuple);
-    state->uri = NULL;
-    state->tuple = NULL;
-}
-
-static void handle_heading (const char * heading, void * data)
-{
-    /* no headings */
-}
-
-static void handle_entry (const char * key, const char * value, void * data)
-{
-    LoadState * state = data;
-
-    if (! strcmp (key, "uri"))
-    {
-        /* finish previous item */
-        if (state->uri)
-            finish_item (state);
-
-        /* start new item */
-        state->uri = str_get (value);
-    }
-    else if (state->uri)
-    {
-        /* item field */
-        if (! state->tuple)
-            state->tuple = tuple_new_from_filename (state->uri);
-
-        if (strcmp (key, "empty"))
-        {
-            int field = tuple_field_by_name (key);
-            if (field < 0)
-                return;
-
-            TupleValueType type = tuple_field_get_type (field);
-
-            if (type == TUPLE_STRING)
-            {
-                char buf[strlen (value) + 1];
-                str_decode_percent (value, -1, buf);
-                tuple_set_str (state->tuple, field, buf);
-            }
-            else if (type == TUPLE_INT)
-                tuple_set_int (state->tuple, field, atoi (value));
-        }
-    }
-    else
-    {
-        /* top-level field */
-        if (! strcmp (key, "title") && ! * state->title)
-        {
-            char buf[strlen (value) + 1];
-            str_decode_percent (value, -1, buf);
-            * state->title = str_get (buf);
-        }
-    }
-}
-
-static bool_t audpl_load (const char * path, VFSFile * file, char * * title,
- Index * filenames, Index * tuples)
-{
-    LoadState state = {
-        .title = title,
-        .filenames = filenames,
-        .tuples = tuples
-    };
-
-    inifile_parse (file, handle_heading, handle_entry, & state);
-
-    /* finish last item */
-    if (state.uri)
-        finish_item (& state);
-
-    return TRUE;
-}
-
-static bool_t write_encoded_entry (VFSFile * file, const char * key, const char * val)
-{
-    char buf[3 * strlen (val) + 1];
-    str_encode_percent (val, -1, buf);
-    return inifile_write_entry (file, key, buf);
-}
-
-static bool_t audpl_save (const char * path, VFSFile * file,
- const char * title, Index * filenames, Index * tuples)
-{
-    if (! write_encoded_entry (file, "title", title))
-        return FALSE;
-
-    int count = index_count (filenames);
-
-    for (int i = 0; i < count; i ++)
-    {
-        if (! inifile_write_entry (file, "uri", index_get (filenames, i)))
-            return FALSE;
-
-        const Tuple * tuple = tuples ? index_get (tuples, i) : NULL;
-
-        if (tuple)
-        {
-            int keys = 0;
-
-            for (int f = 0; f < TUPLE_FIELDS; f ++)
-            {
-                if (f == FIELD_FILE_PATH || f == FIELD_FILE_NAME || f == FIELD_FILE_EXT)
-                    continue;
-
-                TupleValueType type = tuple_get_value_type (tuple, f);
-
-                if (type == TUPLE_STRING)
-                {
-                    char * str = tuple_get_str (tuple, f);
-
-                    if (! write_encoded_entry (file, tuple_field_get_name (f), str))
-                    {
-                        str_unref (str);
-                        return FALSE;
-                    }
-
-                    str_unref (str);
-                    keys ++;
-                }
-                else if (type == TUPLE_INT)
-                {
-                    char buf[32];
-                    str_itoa (tuple_get_int (tuple, f), buf, sizeof buf);
-
-                    if (! inifile_write_entry (file, tuple_field_get_name (f), buf))
-                        return FALSE;
-
-                    keys ++;
-                }
-            }
-
-            /* distinguish between an empty tuple and no tuple at all */
-            if (! keys && ! inifile_write_entry (file, "empty", "1"))
-                return FALSE;
-        }
-    }
-
-    return TRUE;
-}
-
-static const char * const audpl_exts[] = {"audpl", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
-    .name = N_("Audacious Playlists (audpl)"),
-    .domain = PACKAGE,
-    .extensions = audpl_exts,
-    .load = audpl_load,
-    .save = audpl_save
-)
diff --git a/src/audpl/audpl.cc b/src/audpl/audpl.cc
new file mode 100644
index 000000000000..0549a780cd31
--- /dev/null
+++ b/src/audpl/audpl.cc
@@ -0,0 +1,170 @@
+/*
+ * Audacious playlist format plugin
+ * Copyright 2011 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 <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/inifile.h>
+
+static const char * const audpl_exts[] = {"audpl"};
+
+class AudPlaylistLoader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("Audacious Playlists (audpl)"), PACKAGE};
+
+    constexpr AudPlaylistLoader () : PlaylistPlugin (info, audpl_exts, true) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+    bool save (const char * filename, VFSFile & file, const char * title,
+     const Index<PlaylistAddItem> & items);
+};
+
+EXPORT AudPlaylistLoader aud_plugin_instance;
+
+class AudPlaylistParser : private IniParser
+{
+public:
+    AudPlaylistParser (String & title, Index<PlaylistAddItem> & items) :
+        title (title),
+        items (items) {}
+
+    void parse (VFSFile & file)
+    {
+        IniParser::parse (file);
+
+        /* finish last item */
+        if (uri)
+            finish_item ();
+    }
+
+private:
+    String & title;
+    Index<PlaylistAddItem> & items;
+    String uri;
+    Tuple tuple;
+
+    void finish_item ()
+        { items.append (std::move (uri), std::move (tuple)); }
+
+    /* no headings */
+    void handle_heading (const char * heading) {}
+
+    void handle_entry (const char * key, const char * value)
+    {
+        if (! strcmp (key, "uri"))
+        {
+            /* finish previous item */
+            if (uri)
+                finish_item ();
+
+            /* start new item */
+            uri = String (value);
+        }
+        else if (uri)
+        {
+            /* item field */
+            if (! tuple)
+                tuple.set_filename (uri);
+
+            if (strcmp (key, "empty"))
+            {
+                auto field = Tuple::field_by_name (key);
+                if (field == Tuple::Invalid)
+                    return;
+
+                auto type = Tuple::field_get_type (field);
+                if (type == Tuple::String)
+                    tuple.set_str (field, str_decode_percent (value));
+                else if (type == Tuple::Int)
+                    tuple.set_int (field, atoi (value));
+            }
+        }
+        else
+        {
+            /* top-level field */
+            if (! strcmp (key, "title") && ! title)
+                title = String (str_decode_percent (value));
+        }
+    }
+};
+
+bool AudPlaylistLoader::load (const char * path, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    AudPlaylistParser (title, items).parse (file);
+    return true;
+}
+
+bool AudPlaylistLoader::save (const char * path, VFSFile & file,
+ const char * title, const Index<PlaylistAddItem> & items)
+{
+    if (! inifile_write_entry (file, "title", str_encode_percent (title)))
+        return false;
+
+    for (auto & item : items)
+    {
+        if (! inifile_write_entry (file, "uri", item.filename))
+            return false;
+
+        const Tuple & tuple = item.tuple;
+
+        if (tuple)
+        {
+            int keys = 0;
+
+            for (auto f : Tuple::all_fields ())
+            {
+                if (f == Tuple::Path || f == Tuple::Basename ||
+                 f == Tuple::Suffix || f == Tuple::FormattedTitle)
+                    continue;
+
+                const char * key = Tuple::field_get_name (f);
+                Tuple::ValueType type = tuple.get_value_type (f);
+
+                if (type == Tuple::String)
+                {
+                    String str = tuple.get_str (f);
+                    if (! inifile_write_entry (file, key, str_encode_percent (str)))
+                        return false;
+
+                    keys ++;
+                }
+                else if (type == Tuple::Int)
+                {
+                    int val = tuple.get_int (f);
+                    if (! inifile_write_entry (file, key, int_to_str (val)))
+                        return false;
+
+                    keys ++;
+                }
+            }
+
+            /* distinguish between an empty tuple and no tuple at all */
+            if (! keys && ! inifile_write_entry (file, "empty", "1"))
+                return false;
+        }
+    }
+
+    return true;
+}
diff --git a/src/blur_scope/Makefile b/src/blur_scope/Makefile
index 1398d3c42fab..8f191874d847 100644
--- a/src/blur_scope/Makefile
+++ b/src/blur_scope/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = blur_scope${PLUGIN_SUFFIX}
 
-SRCS = blur_scope.c
+SRCS = blur_scope.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${VISUALIZATION_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} -lm
diff --git a/src/blur_scope/blur_scope.c b/src/blur_scope/blur_scope.c
deleted file mode 100644
index fbfe1859f27c..000000000000
--- a/src/blur_scope/blur_scope.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *  Blur Scope plugin for Audacious
- *  Copyright (C) 2010-2012 John Lindgren
- *
- *  Based on 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; 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.
- */
-
-#include <math.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#define D_WIDTH 64
-#define D_HEIGHT 32
-
-static gboolean bscope_init (void);
-static void bscope_cleanup(void);
-static void bscope_clear (void);
-static void bscope_render (const gfloat * data);
-static void /* GtkWidget */ * bscope_get_widget (void);
-static void /* GtkWidget */ * bscope_get_color_chooser (void);
-
-static const PreferencesWidget bscope_widgets[] = {
- {WIDGET_LABEL, N_("<b>Color</b>")},
- {WIDGET_CUSTOM, .data = {.populate = bscope_get_color_chooser}}};
-
-static const PluginPreferences bscope_prefs = {
- .widgets = bscope_widgets,
- .n_widgets = ARRAY_LEN (bscope_widgets)};
-
-AUD_VIS_PLUGIN
-(
-    .name = N_("Blur Scope"),
-    .domain = PACKAGE,
-    .prefs = & bscope_prefs,
-    .init = bscope_init,                /* init */
-    .cleanup = bscope_cleanup,             /* cleanup */
-    .clear = bscope_clear,
-    .render_mono_pcm = bscope_render,
-    .get_widget = bscope_get_widget,
-)
-
-static GtkWidget * area = NULL;
-static gint width, height, stride, image_size;
-static guint32 * image = NULL, * corner = NULL;
-
-static const gchar * const bscope_defaults[] = {
- "color", "16727935", /* 0xFF3F7F */
- NULL};
-
-static gint color;
-
-static gboolean bscope_init (void)
-{
-    aud_config_set_defaults ("BlurScope", bscope_defaults);
-    color = aud_get_int ("BlurScope", "color");
-
-    return TRUE;
-}
-
-static void bscope_cleanup (void)
-{
-    aud_set_int ("BlurScope", "color", color);
-
-    g_free (image);
-    image = NULL;
-}
-
-static void bscope_resize (gint w, gint h)
-{
-    width = w;
-    height = h;
-    stride = width + 2;
-    image_size = (stride << 2) * (height + 2);
-    image = g_realloc (image, image_size);
-    memset (image, 0, image_size);
-    corner = image + stride + 1;
-}
-
-static void bscope_draw_to_cairo (cairo_t * cr)
-{
-    cairo_surface_t * surf = cairo_image_surface_create_for_data ((guchar *)
-     image, CAIRO_FORMAT_RGB24, width, height, stride << 2);
-    cairo_set_source_surface (cr, surf, 0, 0);
-    cairo_paint (cr);
-    cairo_surface_destroy (surf);
-}
-
-static void bscope_draw (void)
-{
-    if (! area || ! gtk_widget_get_window (area))
-        return;
-
-    cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (area));
-    bscope_draw_to_cairo (cr);
-    cairo_destroy (cr);
-}
-
-static gboolean configure_event (GtkWidget * widget, GdkEventConfigure * event)
-{
-    bscope_resize (event->width, event->height);
-    return TRUE;
-}
-
-static gboolean draw_cb (GtkWidget * widget, cairo_t * cr)
-{
-    bscope_draw_to_cairo (cr);
-    return TRUE;
-}
-
-static void /* GtkWidget */ * bscope_get_widget (void)
-{
-    area = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (area, D_WIDTH, D_HEIGHT);
-    bscope_resize (D_WIDTH, D_HEIGHT);
-
-    g_signal_connect (area, "draw", (GCallback) draw_cb, NULL);
-    g_signal_connect (area, "configure-event", (GCallback) configure_event, NULL);
-    g_signal_connect (area, "destroy", (GCallback) gtk_widget_destroyed, & area);
-
-    GtkWidget * frame = gtk_frame_new (NULL);
-    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
-    gtk_container_add ((GtkContainer *) frame, area);
-    return frame;
-}
-
-static void bscope_clear (void)
-{
-    g_return_if_fail (image != NULL);
-    memset (image, 0, image_size);
-    bscope_draw ();
-}
-
-static void bscope_blur (void)
-{
-    for (gint y = 0; y < height; y ++)
-    {
-        guint32 * p = corner + stride * y;
-        guint32 * end = p + width;
-        guint32 * plast = p - stride;
-        guint32 * pnext = p + stride;
-
-        /* We do a quick and dirty average of four color values, first masking
-         * off the lowest two bits.  Over a large area, this masking has the net
-         * effect of subtracting 1.5 from each value, which by a happy chance
-         * is just right for a gradual fade effect. */
-        for (; p < end; p ++)
-            * p = ((* plast ++ & 0xFCFCFC) + (p[-1] & 0xFCFCFC) + (p[1] &
-             0xFCFCFC) + (* pnext ++ & 0xFCFCFC)) >> 2;
-    }
-}
-
-static inline void draw_vert_line (gint x, guint y1, gint y2)
-{
-    gint y, h;
-
-    if (y1 < y2) {y = y1 + 1; h = y2 - y1;}
-    else if (y2 < y1) {y = y2; h = y1 - y2;}
-    else {y = y1; h = 1;}
-
-    guint32 * p = corner + y * stride + x;
-
-    for (; h --; p += stride)
-        * p = color;
-}
-
-static void bscope_render (const gfloat * data)
-{
-    bscope_blur ();
-
-    gint prev_y = (0.5 + data[0]) * height;
-    prev_y = CLAMP (prev_y, 0, height - 1);
-
-    for (gint i = 0; i < width; i ++)
-    {
-        gint y = (0.5 + data[i * 512 / width]) * height;
-        y = CLAMP (y, 0, height - 1);
-        draw_vert_line (i, prev_y, y);
-        prev_y = y;
-    }
-
-    bscope_draw ();
-}
-
-static void color_set_cb (GtkWidget * chooser)
-{
-    GdkRGBA rgba;
-    gtk_color_chooser_get_rgba ((GtkColorChooser *) chooser, & rgba);
-
-    int red = round (rgba.red * 255);
-    int green = round (rgba.green * 255);
-    int blue = round (rgba.blue * 255);
-    color = (red << 16) | (green << 8) | blue;
-}
-
-static void /* GtkWidget */ * bscope_get_color_chooser (void)
-{
-    GdkRGBA rgba = {
-     .red = ((color & 0xff0000) >> 16) / 255.0,
-     .green = ((color & 0xff00) >> 8) / 255.0,
-     .blue = (color & 0xff) / 255.0};
-
-    GtkWidget * chooser = gtk_color_button_new_with_rgba (& rgba);
-    gtk_color_chooser_set_use_alpha ((GtkColorChooser *) chooser, FALSE);
-
-    g_signal_connect (chooser, "color-set", (GCallback) color_set_cb, NULL);
-
-    return chooser;
-}
diff --git a/src/blur_scope/blur_scope.cc b/src/blur_scope/blur_scope.cc
new file mode 100644
index 000000000000..279009d5cd35
--- /dev/null
+++ b/src/blur_scope/blur_scope.cc
@@ -0,0 +1,234 @@
+/*
+ *  Blur Scope plugin for Audacious
+ *  Copyright (C) 2010-2012 John Lindgren
+ *
+ *  Based on 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; 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.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#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 const PreferencesWidget bscope_widgets[] = {
+    WidgetLabel (N_("<b>Color</b>")),
+    WidgetCustomGTK (bscope_get_color_chooser)
+};
+
+static const PluginPreferences bscope_prefs = {{bscope_widgets}};
+
+static const char * const bscope_defaults[] = {
+ "color", "16727935", /* 0xFF3F7F */
+ nullptr};
+
+static int bscope_color;
+
+class BlurScope : public VisPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Blur Scope"),
+        PACKAGE,
+        nullptr,
+        & bscope_prefs
+    };
+
+    constexpr BlurScope () : VisPlugin (info, Visualizer::MonoPCM) {}
+
+    bool init ();
+    void cleanup ();
+
+    void * get_gtk_widget ();
+
+    void clear ();
+    void render_mono_pcm (const float * pcm);
+
+private:
+    void resize (int w, int h);
+    void draw ();
+
+    void blur ();
+    void draw_vert_line (int x, int y1, int y2);
+
+    static gboolean configure_event (GtkWidget * widget, GdkEventConfigure * event, void * user);
+    static gboolean expose_event (GtkWidget * widget, GdkEventExpose * event, void * user);
+
+    GtkWidget * area = nullptr;
+    int width = 0, height = 0, stride = 0, image_size = 0;
+    uint32_t * image = nullptr, * corner = nullptr;
+};
+
+EXPORT BlurScope aud_plugin_instance;
+
+bool BlurScope::init ()
+{
+    aud_config_set_defaults ("BlurScope", bscope_defaults);
+    bscope_color = aud_get_int ("BlurScope", "color");
+
+    return TRUE;
+}
+
+void BlurScope::cleanup ()
+{
+    aud_set_int ("BlurScope", "color", bscope_color);
+
+    g_free (image);
+    image = nullptr;
+}
+
+void BlurScope::resize (int w, int h)
+{
+    width = w;
+    height = h;
+    stride = width + 2;
+    image_size = (stride << 2) * (height + 2);
+    image = (uint32_t *) g_realloc (image, image_size);
+    memset (image, 0, image_size);
+    corner = image + stride + 1;
+}
+
+void BlurScope::draw ()
+{
+    if (! area || ! gtk_widget_get_window (area))
+        return;
+
+    cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (area));
+    cairo_surface_t * surf = cairo_image_surface_create_for_data
+     ((unsigned char *) image, CAIRO_FORMAT_RGB24, width, height, stride << 2);
+    cairo_set_source_surface (cr, surf, 0, 0);
+    cairo_paint (cr);
+    cairo_surface_destroy (surf);
+    cairo_destroy (cr);
+}
+
+gboolean BlurScope::configure_event (GtkWidget * widget, GdkEventConfigure * event, void * user)
+{
+    ((BlurScope *) user)->resize (event->width, event->height);
+    return TRUE;
+}
+
+gboolean BlurScope::expose_event (GtkWidget * widget, GdkEventExpose * event, void * user)
+{
+    ((BlurScope *) user)->draw ();
+    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);
+    g_signal_connect (area, "destroy", (GCallback) gtk_widget_destroyed, & area);
+
+    GtkWidget * frame = gtk_frame_new (nullptr);
+    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
+    gtk_container_add ((GtkContainer *) frame, area);
+    return frame;
+}
+
+void BlurScope::clear ()
+{
+    memset (image, 0, image_size);
+    draw ();
+}
+
+void BlurScope::blur ()
+{
+    for (int y = 0; y < height; y ++)
+    {
+        uint32_t * p = corner + stride * y;
+        uint32_t * end = p + width;
+        uint32_t * plast = p - stride;
+        uint32_t * pnext = p + stride;
+
+        /* We do a quick and dirty average of four color values, first masking
+         * off the lowest two bits.  Over a large area, this masking has the net
+         * effect of subtracting 1.5 from each value, which by a happy chance
+         * is just right for a gradual fade effect. */
+        for (; p < end; p ++)
+            * p = ((* plast ++ & 0xFCFCFC) + (p[-1] & 0xFCFCFC) + (p[1] &
+             0xFCFCFC) + (* pnext ++ & 0xFCFCFC)) >> 2;
+    }
+}
+
+void BlurScope::draw_vert_line (int x, int y1, int y2)
+{
+    int y, h;
+
+    if (y1 < y2) {y = y1 + 1; h = y2 - y1;}
+    else if (y2 < y1) {y = y2; h = y1 - y2;}
+    else {y = y1; h = 1;}
+
+    uint32_t * p = corner + y * stride + x;
+
+    for (; h --; p += stride)
+        * p = bscope_color;
+}
+
+void BlurScope::render_mono_pcm (const float * pcm)
+{
+    blur ();
+
+    int prev_y = (0.5 + pcm[0]) * height;
+    prev_y = aud::clamp (prev_y, 0, height - 1);
+
+    for (int i = 0; i < width; i ++)
+    {
+        int y = (0.5 + pcm[i * 512 / width]) * height;
+        y = aud::clamp (y, 0, height - 1);
+        draw_vert_line (i, prev_y, y);
+        prev_y = y;
+    }
+
+    draw ();
+}
+
+static void color_set_cb (GtkWidget * chooser)
+{
+    GdkColor gdk_color;
+    gtk_color_button_get_color ((GtkColorButton *) chooser, & gdk_color);
+    bscope_color = ((gdk_color.red & 0xff00) << 8) | (gdk_color.green & 0xff00) | (gdk_color.blue >> 8);
+}
+
+static void /* GtkWidget */ * bscope_get_color_chooser (void)
+{
+    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);
+
+    g_signal_connect (chooser, "color-set", (GCallback) color_set_cb, nullptr);
+
+    return chooser;
+}
diff --git a/src/bs2b/Makefile b/src/bs2b/Makefile
index 49c4f9b574f1..fd6b5f307775 100644
--- a/src/bs2b/Makefile
+++ b/src/bs2b/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = bs2b${PLUGIN_SUFFIX}
 
-SRCS = plugin.c
+SRCS = plugin.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${BS2B_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${BS2B_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BS2B_CFLAGS} -I../..
+LIBS += ${BS2B_LIBS}
diff --git a/src/bs2b/plugin.c b/src/bs2b/plugin.c
deleted file mode 100644
index 9c0228ffbf58..000000000000
--- a/src/bs2b/plugin.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Audacious bs2b effect plugin
- * Copyright (C) 2009, Sebastian Pipping <sebastian at pipping.org>
- * Copyright (C) 2009, Tony Vroon <chainsaw at gentoo.org>
- * Copyright (C) 2010, John Lindgren <john.lindgren at tds.net>
- * Copyright (C) 2011, Michał Lipski <tallica at o2.pl>
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#include <bs2b.h>
-
-static t_bs2bdp bs2b = NULL;
-static int bs2b_channels;
-static GtkWidget * feed_slider, * fcut_slider;
-
-static const char * const bs2b_defaults[] = {
- "feed", "45",
- "fcut", "700",
- NULL};
-
-bool_t init (void)
-{
-    aud_config_set_defaults ("bs2b", bs2b_defaults);
-    bs2b = bs2b_open ();
-
-    if (! bs2b)
-        return FALSE;
-
-    bs2b_set_level_feed (bs2b, aud_get_int ("bs2b", "feed"));
-    bs2b_set_level_fcut (bs2b, aud_get_int ("bs2b", "fcut"));
-
-    return TRUE;
-}
-
-static void cleanup (void)
-{
-    if (! bs2b)
-        return;
-
-    bs2b_close (bs2b);
-    bs2b = NULL;
-}
-
-static void bs2b_start (int * channels, int * rate)
-{
-    if (! bs2b)
-        return;
-
-    bs2b_channels = * channels;
-
-    if (* channels != 2)
-        return;
-
-    bs2b_set_srate (bs2b, * rate);
-}
-
-static void bs2b_process (float * * data, int * samples)
-{
-    if (! bs2b || bs2b_channels != 2)
-        return;
-
-    bs2b_cross_feed_f (bs2b, * data, (* samples) / 2);
-}
-
-static void bs2b_finish (float * * data, int * samples)
-{
-    bs2b_process (data, samples);
-}
-
-static void feed_value_changed (GtkRange * range, gpointer data)
-{
-    int feed_level = gtk_range_get_value (range);
-    aud_set_int ("bs2b", "feed", feed_level);
-    bs2b_set_level_feed (bs2b, feed_level);
-}
-
-static char * feed_format_value (GtkScale * scale, double value)
-{
-    return g_strdup_printf ("%.1f dB", (float) value / 10);
-}
-
-static void fcut_value_changed (GtkRange * range, gpointer data)
-{
-    int fcut_level = gtk_range_get_value (range);
-    aud_set_int ("bs2b", "fcut", fcut_level);
-    bs2b_set_level_fcut (bs2b, fcut_level);
-}
-
-static char * fcut_format_value (GtkScale * scale, double value)
-{
-    return g_strdup_printf ("%d Hz, %d µs", (int) value, bs2b_level_delay ((int) value));
-}
-
-static void preset_button_clicked (GtkButton * button, gpointer data)
-{
-    int clevel = GPOINTER_TO_INT (data);
-    gtk_range_set_value ((GtkRange *) feed_slider, clevel >> 16);
-    gtk_range_set_value ((GtkRange *) fcut_slider, clevel & 0xffff);
-}
-
-static GtkWidget * preset_button (const char * label, int clevel)
-{
-    GtkWidget * button = gtk_button_new_with_label (label);
-    gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE);
-    g_signal_connect (button, "clicked", (GCallback)
-     preset_button_clicked, GINT_TO_POINTER (clevel));
-
-    return button;
-}
-
-static void * create_config_widget (void)
-{
-    int feed_level = aud_get_int ("bs2b", "feed");
-    int fcut_level = aud_get_int ("bs2b", "fcut");
-
-    GtkWidget * vbox, * hbox, * button;
-
-    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
-
-    gtk_box_pack_start ((GtkBox *) hbox, gtk_label_new (_("Feed level:")), TRUE, FALSE, 0);
-
-    feed_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, BS2B_MINFEED, BS2B_MAXFEED, 1.0);
-    gtk_range_set_value ((GtkRange *) feed_slider, feed_level);
-    gtk_widget_set_size_request (feed_slider, 200, -1);
-    gtk_box_pack_start ((GtkBox *) hbox, feed_slider, FALSE, FALSE, 0);
-    g_signal_connect (feed_slider, "value-changed", (GCallback) feed_value_changed, NULL);
-    g_signal_connect (feed_slider, "format-value", (GCallback) feed_format_value, NULL);
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
-
-    gtk_box_pack_start ((GtkBox *) hbox, gtk_label_new (_("Cut frequency:")), TRUE, FALSE, 0);
-
-    fcut_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, BS2B_MINFCUT, BS2B_MAXFCUT, 1.0);
-    gtk_range_set_value ((GtkRange *) fcut_slider, fcut_level);
-    gtk_widget_set_size_request (fcut_slider, 200, -1);
-    gtk_box_pack_start ((GtkBox *) hbox, fcut_slider, FALSE, FALSE, 0);
-    g_signal_connect (fcut_slider, "value-changed", (GCallback) fcut_value_changed, NULL);
-    g_signal_connect (fcut_slider, "format-value", (GCallback) fcut_format_value, NULL);
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
-
-    gtk_box_pack_start ((GtkBox *) hbox, gtk_label_new (_("Presets:")), TRUE, FALSE, 0);
-
-    button = preset_button (_("Default"), BS2B_DEFAULT_CLEVEL);
-    gtk_box_pack_start ((GtkBox *) hbox, button, TRUE, FALSE, 0);
-
-    button = preset_button ("C. Moy", BS2B_CMOY_CLEVEL);
-    gtk_box_pack_start ((GtkBox *) hbox, button, TRUE, FALSE, 0);
-
-    button = preset_button ("J. Meier", BS2B_JMEIER_CLEVEL);
-    gtk_box_pack_start ((GtkBox *) hbox, button, TRUE, FALSE, 0);
-
-    return vbox;
-}
-
-static const PreferencesWidget bs2b_widgets[] = {
- {WIDGET_CUSTOM, .data.populate = create_config_widget}};
-
-static const PluginPreferences bs2b_prefs = {
- .widgets = bs2b_widgets,
- .n_widgets = ARRAY_LEN (bs2b_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Bauer Stereophonic-to-Binaural (BS2B)"),
-    .domain = PACKAGE,
-    .init = init,
-    .cleanup = cleanup,
-    .prefs = & bs2b_prefs,
-    .start = bs2b_start,
-    .process = bs2b_process,
-    .finish = bs2b_finish,
-    .preserves_format = TRUE
-)
diff --git a/src/bs2b/plugin.cc b/src/bs2b/plugin.cc
new file mode 100644
index 000000000000..e208a76ad5ef
--- /dev/null
+++ b/src/bs2b/plugin.cc
@@ -0,0 +1,145 @@
+/*
+ * Audacious bs2b effect plugin
+ * Copyright (C) 2009, Sebastian Pipping <sebastian at pipping.org>
+ * Copyright (C) 2009, Tony Vroon <chainsaw at gentoo.org>
+ * Copyright (C) 2010, John Lindgren <john.lindgren at tds.net>
+ * Copyright (C) 2011, Michał Lipski <tallica at o2.pl>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+#include <bs2b.h>
+
+class BS2BPlugin : public EffectPlugin
+{
+public:
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Bauer Stereophonic-to-Binaural (BS2B)"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr BS2BPlugin () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+};
+
+EXPORT BS2BPlugin aud_plugin_instance;
+
+static t_bs2bdp bs2b = nullptr;
+static int bs2b_channels;
+
+const char * const BS2BPlugin::defaults[] = {
+ "feed", "45",
+ "fcut", "700",
+ nullptr};
+
+bool BS2BPlugin::init ()
+{
+    aud_config_set_defaults ("bs2b", defaults);
+    bs2b = bs2b_open ();
+
+    if (! bs2b)
+        return false;
+
+    bs2b_set_level_feed (bs2b, aud_get_int ("bs2b", "feed"));
+    bs2b_set_level_fcut (bs2b, aud_get_int ("bs2b", "fcut"));
+
+    return true;
+}
+
+void BS2BPlugin::cleanup ()
+{
+    bs2b_close (bs2b);
+    bs2b = nullptr;
+}
+
+void BS2BPlugin::start (int & channels, int & rate)
+{
+    bs2b_channels = channels;
+    bs2b_set_srate (bs2b, rate);
+}
+
+Index<float> & BS2BPlugin::process (Index<float> & data)
+{
+    if (bs2b_channels == 2)
+        bs2b_cross_feed_f (bs2b, data.begin (), data.len () / 2);
+
+    return data;
+}
+
+static void feed_value_changed ()
+{
+    bs2b_set_level_feed (bs2b, aud_get_int ("bs2b", "feed"));
+}
+
+static void fcut_value_changed ()
+{
+    bs2b_set_level_fcut (bs2b, aud_get_int ("bs2b", "fcut"));
+}
+
+static void set_preset (uint32_t preset)
+{
+    int feed = preset >> 16;
+    int fcut = preset & 0xffff;
+
+    aud_set_int ("bs2b", "feed", feed);
+    aud_set_int ("bs2b", "fcut", fcut);
+
+    bs2b_set_level_feed (bs2b, feed);
+    bs2b_set_level_fcut (bs2b, fcut);
+
+    hook_call ("bs2b preset loaded", nullptr);
+}
+
+static void set_default_preset ()
+    { set_preset (BS2B_DEFAULT_CLEVEL); }
+static void set_cmoy_preset ()
+    { set_preset (BS2B_CMOY_CLEVEL); }
+static void set_jmeier_preset ()
+    { set_preset (BS2B_JMEIER_CLEVEL); }
+
+static const PreferencesWidget preset_widgets[] = {
+    WidgetLabel (N_("Presets:")),
+    WidgetButton (N_("Default"), {set_default_preset}),
+    WidgetButton ("C. Moy", {set_cmoy_preset}),
+    WidgetButton ("J. Meier", {set_jmeier_preset})
+};
+
+const PreferencesWidget BS2BPlugin::widgets[] = {
+    WidgetSpin (N_("Feed level:"),
+        WidgetInt ("bs2b", "feed", feed_value_changed, "bs2b preset loaded"),
+        {BS2B_MINFEED, BS2B_MAXFEED, 1, N_("x1/10 dB")}),
+    WidgetSpin (N_("Cut frequency:"),
+        WidgetInt ("bs2b", "fcut", fcut_value_changed, "bs2b preset loaded"),
+        {BS2B_MINFCUT, BS2B_MAXFCUT, 1, N_("Hz")}),
+    WidgetBox ({{preset_widgets}, true})
+};
+
+const PluginPreferences BS2BPlugin::prefs = {{widgets}};
diff --git a/src/cairo-spectrum/Makefile b/src/cairo-spectrum/Makefile
index 42aa5912c6e7..429144c453d3 100644
--- a/src/cairo-spectrum/Makefile
+++ b/src/cairo-spectrum/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = cairo-spectrum${PLUGIN_SUFFIX}
 
-SRCS = cairo-spectrum.c
+SRCS = cairo-spectrum.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${VISUALIZATION_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GTK_CFLAGS}
 LIBS += -lm ${GTK_LIBS}
diff --git a/src/cairo-spectrum/cairo-spectrum.c b/src/cairo-spectrum/cairo-spectrum.c
deleted file mode 100644
index b396c1b3c337..000000000000
--- a/src/cairo-spectrum/cairo-spectrum.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2011 William Pitcock <nenolod at dereferenced.org>.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <math.h>
-#include <gtk/gtk.h>
-
-#include <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#define MAX_BANDS   (256)
-#define VIS_DELAY 2 /* delay before falloff in frames */
-#define VIS_FALLOFF 2 /* falloff in pixels per frame */
-
-static GtkWidget * spect_widget = NULL;
-static gfloat xscale[MAX_BANDS + 1];
-static gint width, height, bands;
-static gint bars[MAX_BANDS + 1];
-static gint delay[MAX_BANDS + 1];
-
-static void calculate_xscale (void)
-{
-    for (gint i = 0; i <= bands; i ++)
-        xscale[i] = powf (256, (gfloat) i / bands) - 0.5f;
-}
-
-static void render_cb (gfloat * freq)
-{
-    g_return_if_fail (spect_widget);
-
-    if (! bands)
-        return;
-
-    for (gint i = 0; i < bands; i ++)
-    {
-        gint a = ceilf (xscale[i]);
-        gint b = floorf (xscale[i + 1]);
-        gfloat n = 0;
-
-        if (b < a)
-            n += freq[b] * (xscale[i + 1] - xscale[i]);
-        else
-        {
-            if (a > 0)
-                n += freq[a - 1] * (a - xscale[i]);
-            for (; a < b; a ++)
-                n += freq[a];
-            if (b < 256)
-                n += 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 */
-        n *= (gfloat) bands / 12;
-
-        /* 40 dB range */
-        gint x = 40 + 20 * log10f (n);
-        x = CLAMP (x, 0, 40);
-
-        bars[i] -= MAX (0, VIS_FALLOFF - delay[i]);
-
-        if (delay[i])
-            delay[i]--;
-
-        if (x > bars[i])
-        {
-            bars[i] = x;
-            delay[i] = VIS_DELAY;
-        }
-    }
-
-    gtk_widget_queue_draw (spect_widget);
-}
-
-static void rgb_to_hsv (gfloat r, gfloat g, gfloat b, gfloat * h, gfloat * s, gfloat * v)
-{
-    gfloat max, min;
-
-    max = r;
-    if (g > max)
-        max = g;
-    if (b > max)
-        max = b;
-
-    min = r;
-    if (g < min)
-        min = g;
-    if (b < min)
-        min = b;
-
-    * v = max;
-
-    if (max == min)
-    {
-        * h = 0;
-        * s = 0;
-        return;
-    }
-
-    if (r == max)
-        * h = 1 + (g - b) / (max - min);
-    else if (g == max)
-        * h = 3 + (b - r) / (max - min);
-    else
-        * h = 5 + (r - g) / (max - min);
-
-    * s = (max - min) / max;
-}
-
-static void hsv_to_rgb (gfloat h, gfloat s, gfloat v, gfloat * r, gfloat * g, gfloat * b)
-{
-    for (; h >= 2; h -= 2)
-    {
-        gfloat * p = r;
-        r = g;
-        g = b;
-        b = p;
-    }
-
-    if (h < 1)
-    {
-        * r = 1;
-        * g = 0;
-        * b = 1 - h;
-    }
-    else
-    {
-        * r = 1;
-        * g = h - 1;
-        * b = 0;
-    }
-
-    * r = v * (1 - s * (1 - * r));
-    * g = v * (1 - s * (1 - * g));
-    * b = v * (1 - s * (1 - * b));
-}
-
-static void get_color (gint i, gfloat * r, gfloat * g, gfloat * b)
-{
-    static GdkRGBA c;
-    static bool_t valid = FALSE;
-    gfloat h, s, v, n;
-
-    if (! valid)
-    {
-        /* we want a color that matches the current theme
-         * selected color of a GtkEntry should be reasonable */
-        GtkStyleContext * style = gtk_style_context_new ();
-        GtkWidgetPath * path = gtk_widget_path_new ();
-        gtk_widget_path_append_type (path, GTK_TYPE_ENTRY);
-        gtk_style_context_set_path (style, path);
-        gtk_widget_path_free (path);
-        gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED, & c);
-        g_object_unref (style);
-        valid = TRUE;
-    }
-
-    rgb_to_hsv (c.red, c.green, c.blue, & h, & s, & v);
-
-    if (s < 0.1) /* monochrome theme? use blue instead */
-    {
-        h = 5;
-        s = 0.75;
-    }
-
-    n = i / (gfloat) (bands - 1);
-    s = 1 - 0.9 * n;
-    v = 0.75 + 0.25 * n;
-
-    hsv_to_rgb (h, s, v, r, g, b);
-}
-
-static void draw_background (GtkWidget * area, cairo_t * cr)
-{
-#if 0
-    GdkColor * c = (gtk_widget_get_style (area))->bg;
-#endif
-    GtkAllocation alloc;
-    gtk_widget_get_allocation (area, & alloc);
-
-#if 0
-    gdk_cairo_set_source_color(cr, c);
-#endif
-    cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
-    cairo_fill (cr);
-}
-
-#if 0
-static void draw_grid (GtkWidget * area, cairo_t * cr)
-{
-    GdkColor * c = (gtk_widget_get_style (area))->bg;
-    GtkAllocation alloc;
-    gtk_widget_get_allocation (area, & alloc);
-    gint i;
-    gfloat base_s = (height / 40);
-
-    for (i = 1; i < 41; i++)
-    {
-        gdk_cairo_set_source_color(cr, c);
-        cairo_move_to(cr, 0.0, i * base_s);
-        cairo_line_to(cr, alloc.width, i * base_s);
-        cairo_stroke(cr);
-    }
-}
-#endif
-
-static void draw_visualizer (GtkWidget *widget, cairo_t *cr)
-{
-    gfloat base_s = (height / 40);
-
-    for (gint i = 0; i <= bands; i++)
-    {
-        gint x = ((width / bands) * i) + 2;
-        gfloat r, g, b;
-
-        get_color (i, & r, & g, & b);
-        cairo_set_source_rgb (cr, r, g, b);
-        cairo_rectangle (cr, x + 1, height - (bars[i] * base_s), (width / bands) - 1, (bars[i] * base_s));
-        cairo_fill (cr);
-    }
-}
-
-static gboolean configure_event (GtkWidget * widget, GdkEventConfigure * event)
-{
-    width = event->width;
-    height = event->height;
-    gtk_widget_queue_draw(widget);
-
-    bands = width / 10;
-    bands = CLAMP(bands, 12, MAX_BANDS);
-    calculate_xscale ();
-
-    return TRUE;
-}
-
-static gboolean draw_event (GtkWidget * widget, cairo_t * cr, GtkWidget * area)
-{
-
-    draw_background (widget, cr);
-    draw_visualizer (widget, cr);
-#if 0
-    draw_grid (widget, cr);
-#endif
-
-    return TRUE;
-}
-
-static gboolean destroy_event (void)
-{
-    aud_vis_func_remove ((VisFunc) render_cb);
-    spect_widget = NULL;
-    return TRUE;
-}
-
-static /* GtkWidget * */ gpointer get_widget(void)
-{
-    GtkWidget *area = gtk_drawing_area_new();
-    spect_widget = area;
-
-    g_signal_connect(area, "draw", (GCallback) draw_event, NULL);
-    g_signal_connect(area, "configure-event", (GCallback) configure_event, NULL);
-    g_signal_connect(area, "destroy", (GCallback) destroy_event, NULL);
-
-    aud_vis_func_add (AUD_VIS_TYPE_FREQ, (VisFunc) render_cb);
-
-    GtkWidget * frame = gtk_frame_new (NULL);
-    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
-    gtk_container_add ((GtkContainer *) frame, area);
-    return frame;
-}
-
-AUD_VIS_PLUGIN
-(
-    .name = N_("Spectrum Analyzer"),
-    .domain = PACKAGE,
-    .get_widget = get_widget
-)
diff --git a/src/cairo-spectrum/cairo-spectrum.cc b/src/cairo-spectrum/cairo-spectrum.cc
new file mode 100644
index 000000000000..11f87ffe4452
--- /dev/null
+++ b/src/cairo-spectrum/cairo-spectrum.cc
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2011 William Pitcock <nenolod at dereferenced.org>.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+#define MAX_BANDS   (256)
+#define VIS_DELAY 2 /* delay before falloff in frames */
+#define VIS_FALLOFF 2 /* falloff in pixels per frame */
+
+class CairoSpectrum : public VisPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Spectrum Analyzer"),
+        PACKAGE
+    };
+
+    constexpr CairoSpectrum () : VisPlugin (info, Visualizer::Freq) {}
+
+    void * get_gtk_widget ();
+
+    void clear ();
+    void render_freq (const float * freq);
+};
+
+EXPORT CairoSpectrum aud_plugin_instance;
+
+static GtkWidget * spect_widget = nullptr;
+static float xscale[MAX_BANDS + 1];
+static int width, height, bands;
+static int bars[MAX_BANDS + 1];
+static int delay[MAX_BANDS + 1];
+
+static void calculate_xscale ()
+{
+    for (int i = 0; i <= bands; i ++)
+        xscale[i] = powf (256, (float) i / bands) - 0.5f;
+}
+
+void CairoSpectrum::render_freq (const float * freq)
+{
+    if (! bands)
+        return;
+
+    for (int i = 0; i < bands; i ++)
+    {
+        int a = ceilf (xscale[i]);
+        int b = floorf (xscale[i + 1]);
+        float n = 0;
+
+        if (b < a)
+            n += freq[b] * (xscale[i + 1] - xscale[i]);
+        else
+        {
+            if (a > 0)
+                n += freq[a - 1] * (a - xscale[i]);
+            for (; a < b; a ++)
+                n += freq[a];
+            if (b < 256)
+                n += 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 */
+        n *= (float) bands / 12;
+
+        /* 40 dB range */
+        int x = 40 + 20 * log10f (n);
+        x = aud::clamp (x, 0, 40);
+
+        bars[i] -= aud::max (0, VIS_FALLOFF - delay[i]);
+
+        if (delay[i])
+            delay[i]--;
+
+        if (x > bars[i])
+        {
+            bars[i] = x;
+            delay[i] = VIS_DELAY;
+        }
+    }
+
+    if (spect_widget)
+        gtk_widget_queue_draw (spect_widget);
+}
+
+void CairoSpectrum::clear ()
+{
+    memset (bars, 0, sizeof bars);
+    memset (delay, 0, sizeof delay);
+
+    if (spect_widget)
+        gtk_widget_queue_draw (spect_widget);
+}
+
+static void rgb_to_hsv (float r, float g, float b, float * h, float * s, float * v)
+{
+    float max, min;
+
+    max = r;
+    if (g > max)
+        max = g;
+    if (b > max)
+        max = b;
+
+    min = r;
+    if (g < min)
+        min = g;
+    if (b < min)
+        min = b;
+
+    * v = max;
+
+    if (max == min)
+    {
+        * h = 0;
+        * s = 0;
+        return;
+    }
+
+    if (r == max)
+        * h = 1 + (g - b) / (max - min);
+    else if (g == max)
+        * h = 3 + (b - r) / (max - min);
+    else
+        * h = 5 + (r - g) / (max - min);
+
+    * s = (max - min) / max;
+}
+
+static void hsv_to_rgb (float h, float s, float v, float * r, float * g, float * b)
+{
+    for (; h >= 2; h -= 2)
+    {
+        float * p = r;
+        r = g;
+        g = b;
+        b = p;
+    }
+
+    if (h < 1)
+    {
+        * r = 1;
+        * g = 0;
+        * b = 1 - h;
+    }
+    else
+    {
+        * r = 1;
+        * g = h - 1;
+        * b = 0;
+    }
+
+    * r = v * (1 - s * (1 - * r));
+    * g = v * (1 - s * (1 - * g));
+    * b = v * (1 - s * (1 - * b));
+}
+
+static void get_color (GtkWidget * widget, int i, float * r, float * g, float * b)
+{
+    GdkColor * c = (gtk_widget_get_style (widget))->base + GTK_STATE_SELECTED;
+    float h, s, v;
+
+    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 / (bands - 1);
+    v = 0.75 + 0.25 * i / (bands - 1);
+
+    hsv_to_rgb (h, s, v, r, g, b);
+}
+
+static void draw_background (GtkWidget * area, cairo_t * cr)
+{
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (area, & alloc);
+
+    cairo_rectangle(cr, 0, 0, alloc.width, alloc.height);
+    cairo_fill (cr);
+}
+
+static void draw_visualizer (GtkWidget *widget, cairo_t *cr)
+{
+    for (int i = 0; i < bands; i++)
+    {
+        int x = ((width / bands) * i) + 2;
+        float r, g, b;
+
+        get_color (widget, i, & r, & g, & b);
+        cairo_set_source_rgb (cr, r, g, b);
+        cairo_rectangle (cr, x + 1, height - (bars[i] * height / 40),
+         (width / bands) - 1, (bars[i] * height / 40));
+        cairo_fill (cr);
+    }
+}
+
+static gboolean configure_event (GtkWidget * widget, GdkEventConfigure * event)
+{
+    width = event->width;
+    height = event->height;
+    gtk_widget_queue_draw(widget);
+
+    bands = width / 10;
+    bands = aud::clamp(bands, 12, MAX_BANDS);
+    calculate_xscale ();
+
+    return TRUE;
+}
+
+static gboolean draw_event (GtkWidget * widget)
+{
+    cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+    draw_background (widget, cr);
+    draw_visualizer (widget, cr);
+
+    cairo_destroy (cr);
+    return TRUE;
+}
+
+void * CairoSpectrum::get_gtk_widget ()
+{
+    GtkWidget *area = gtk_drawing_area_new();
+    spect_widget = area;
+
+    g_signal_connect(area, "expose-event", (GCallback) draw_event, nullptr);
+    g_signal_connect(area, "configure-event", (GCallback) configure_event, nullptr);
+    g_signal_connect(area, "destroy", (GCallback) gtk_widget_destroyed, & spect_widget);
+
+    GtkWidget * frame = gtk_frame_new (nullptr);
+    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
+    gtk_container_add ((GtkContainer *) frame, area);
+    return frame;
+}
diff --git a/src/cd-menu-items/Makefile b/src/cd-menu-items/Makefile
index ce8dac136b4b..824a9d168686 100644
--- a/src/cd-menu-items/Makefile
+++ b/src/cd-menu-items/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = cd-menu-items${PLUGIN_SUFFIX}
 
-SRCS = cd-menu-items.c
+SRCS = cd-menu-items.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CPPFLAGS += -I../.. ${GTK_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
 LIBS += ${GTK_LIBS}
diff --git a/src/cd-menu-items/cd-menu-items.c b/src/cd-menu-items/cd-menu-items.c
deleted file mode 100644
index 4fd04f7b624a..000000000000
--- a/src/cd-menu-items/cd-menu-items.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * cd-menu-items.c
- * Copyright 2009-2011 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 <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#define N_ITEMS 2
-#define N_MENUS 3
-
-static const gchar * titles[N_ITEMS] = {N_("Play CD"), N_("Add CD")};
-static const gint menus[N_MENUS] = {AUD_MENU_MAIN, AUD_MENU_PLAYLIST_ADD, AUD_MENU_PLAYLIST};
-
-static void cd_play (void) {aud_drct_pl_open ("cdda://"); }
-static void cd_add (void) {aud_drct_pl_add ("cdda://", -1); }
-static MenuFunc funcs[N_ITEMS] = {cd_play, cd_add};
-
-static gboolean cd_init (void)
-{
-    for (gint m = 0; m < N_MENUS; m ++)
-        for (gint i = 0; i < N_ITEMS; i ++)
-            aud_plugin_menu_add (menus[m], funcs[i], _(titles[i]), "media-optical");
-
-    return TRUE;
-}
-
-void cd_cleanup (void)
-{
-    for (gint m = 0; m < N_MENUS; m ++)
-        for (gint i = 0; i < N_ITEMS; i ++)
-            aud_plugin_menu_remove (menus[m], funcs[i]);
-}
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Audio CD Menu Items"),
-    .domain = PACKAGE,
-    .enabled_by_default = TRUE,
-    .init = cd_init,
-    .cleanup = cd_cleanup,
-)
diff --git a/src/cd-menu-items/cd-menu-items.cc b/src/cd-menu-items/cd-menu-items.cc
new file mode 100644
index 000000000000..0719fc4712cc
--- /dev/null
+++ b/src/cd-menu-items/cd-menu-items.cc
@@ -0,0 +1,73 @@
+/*
+ * cd-menu-items.c
+ * Copyright 2009-2011 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 <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+
+#define N_ITEMS 2
+#define N_MENUS 3
+
+class CDMenuItems : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Audio CD Menu Items"),
+        PACKAGE
+    };
+
+    constexpr CDMenuItems () : GeneralPlugin (info, true) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT CDMenuItems aud_plugin_instance;
+
+static constexpr const char * titles[N_ITEMS] = {N_("Play CD"), N_("Add CD")};
+
+static constexpr AudMenuID menus[N_MENUS] = {
+    AudMenuID::Main,
+    AudMenuID::PlaylistAdd,
+    AudMenuID::Playlist
+};
+
+static void cd_play () {aud_drct_pl_open ("cdda://"); }
+static void cd_add () {aud_drct_pl_add ("cdda://", -1); }
+static void (* funcs[N_ITEMS]) () = {cd_play, cd_add};
+
+bool CDMenuItems::init ()
+{
+    for (int m = 0; m < N_MENUS; m ++)
+        for (int i = 0; i < N_ITEMS; i ++)
+            aud_plugin_menu_add (menus[m], funcs[i], _(titles[i]), "media-optical");
+
+    return TRUE;
+}
+
+void CDMenuItems::cleanup ()
+{
+    for (int m = 0; m < N_MENUS; m ++)
+        for (int i = 0; i < N_ITEMS; i ++)
+            aud_plugin_menu_remove (menus[m], funcs[i]);
+}
diff --git a/src/cdaudio-ng/Makefile b/src/cdaudio-ng/Makefile
index ffe42c23d1d1..59f125ad8078 100644
--- a/src/cdaudio-ng/Makefile
+++ b/src/cdaudio-ng/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = cdaudio-ng${PLUGIN_SUFFIX}
 
-SRCS = cdaudio-ng.c
+SRCS = cdaudio-ng.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS}  ${GTK_CFLAGS} ${GLIB_CFLAGS}  ${CDIO_CFLAGS} ${CDDB_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${GLIB_LIBS}  ${CDIO_LIBS} ${CDDB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${CDIO_CFLAGS} ${CDDB_CFLAGS} -I../..
+LIBS += ${CDIO_LIBS} ${CDDB_LIBS}
diff --git a/src/cdaudio-ng/cdaudio-ng.c b/src/cdaudio-ng/cdaudio-ng.c
deleted file mode 100644
index 7e70de244409..000000000000
--- a/src/cdaudio-ng/cdaudio-ng.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * Audacious CD Digital Audio plugin
- *
- * Copyright (c) 2007 Calin Crisan <ccrisan at gmail.com>
- * Copyright (c) 2009-2012 John Lindgren <john.lindgren at aol.com>
- * Copyright (c) 2009 Tomasz Moń <desowin at gmail.com>
- *
- * 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 <pthread.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-/* prevent libcdio from redefining PACKAGE, VERSION, etc. */
-#define EXTERNAL_LIBCDIO_CONFIG_H
-
-#include <cdio/cdio.h>
-#include <cdio/cdtext.h>
-#include <cdio/track.h>
-#include <cdio/audio.h>
-#include <cdio/sector.h>
-#include <cdio/cd_types.h>
-
-#if LIBCDIO_VERSION_NUM >= 90
-#include <cdio/paranoia/cdda.h>
-#else
-#include <cdio/cdda.h>
-#endif
-
-#include <cddb/cddb.h>
-
-#include <glib.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#define DEF_STRING_LEN 256
-
-#define MIN_DISC_SPEED 2
-#define MAX_DISC_SPEED 24
-
-#define MAX_RETRIES 10
-#define MAX_SKIPS 10
-
-#define warn(...) fprintf(stderr, "cdaudio-ng: " __VA_ARGS__)
-
-typedef struct
-{
-    char performer[DEF_STRING_LEN];
-    char name[DEF_STRING_LEN];
-    char genre[DEF_STRING_LEN];
-    int startlsn;
-    int endlsn;
-}
-trackinfo_t;
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static bool_t playing;
-
-/* lock mutex to read / set these variables */
-static int firsttrackno = -1;
-static int lasttrackno = -1;
-static int n_audio_tracks;
-static cdrom_drive_t *pcdrom_drive = NULL;
-static trackinfo_t *trackinfo = NULL;
-static int monitor_source = 0;
-
-static bool_t cdaudio_init (void);
-static int cdaudio_is_our_file (const char * filename, VFSFile * file);
-static bool_t cdaudio_play (const char * name, VFSFile * file);
-static void cdaudio_cleanup (void);
-static Tuple * make_tuple (const char * filename, VFSFile * file);
-static void scan_cd (void);
-static void refresh_trackinfo (bool_t warning);
-static void reset_trackinfo (void);
-static int calculate_track_length (int startlsn, int endlsn);
-static int find_trackno_from_filename (const char * filename);
-
-static const char cdaudio_about[] =
- N_("Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n\n"
-    "Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/>\n"
-    "and to libcddb developers <http://libcddb.sourceforge.net/>.\n\n"
-    "Also thank you to Tony Vroon for mentoring and guiding me.\n\n"
-    "This was a Google Summer of Code 2007 project.");
-
-static const char * const schemes[] = {"cdda", NULL};
-
-static const char * const cdaudio_defaults[] = {
- "disc_speed", "2",
- "use_cdtext", "TRUE",
- "use_cddb", "TRUE",
- "cddbhttp", "FALSE",
- "cddbserver", "freedb.org",
- "cddbport", "8880",
- NULL};
-
-static const PreferencesWidget cdaudio_widgets[] = {
- {WIDGET_LABEL, N_("<b>Device</b>")},
- {WIDGET_SPIN_BTN, N_("Read speed:"),
-  .cfg_type = VALUE_INT, .csect = "CDDA", .cname = "disc_speed",
-  .data = {.spin_btn = {MIN_DISC_SPEED, MAX_DISC_SPEED, 1}}},
- {WIDGET_ENTRY, N_("Override device:"),
-  .cfg_type = VALUE_STRING, .csect = "CDDA", .cname = "device"},
- {WIDGET_LABEL, N_("<b>Metadata</b>")},
- {WIDGET_CHK_BTN, N_("Use CD-Text"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "CDDA", .cname = "use_cdtext"},
- {WIDGET_CHK_BTN, N_("Use CDDB"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "CDDA", .cname = "use_cddb"},
- {WIDGET_CHK_BTN, N_("Use HTTP instead of CDDBP"), .child = TRUE,
-  .cfg_type = VALUE_BOOLEAN, .csect = "CDDA", .cname = "cddbhttp"},
- {WIDGET_ENTRY, N_("Server:"), .child = TRUE,
-  .cfg_type = VALUE_STRING, .csect = "CDDA", .cname = "cddbserver"},
- {WIDGET_ENTRY, N_("Path:"), .child = TRUE,
-  .cfg_type = VALUE_STRING, .csect = "CDDA", .cname = "cddbpath"},
- {WIDGET_SPIN_BTN, N_("Port:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "CDDA", .cname = "cddbport",
-  .data = {.spin_btn = {0, 65535, 1}}}};
-
-static const PluginPreferences cdaudio_prefs = {
- .widgets = cdaudio_widgets,
- .n_widgets = ARRAY_LEN (cdaudio_widgets)};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Audio CD Plugin"),
-    .domain = PACKAGE,
-    .about_text = cdaudio_about,
-    .prefs = & cdaudio_prefs,
-    .init = cdaudio_init,
-    .cleanup = cdaudio_cleanup,
-    .is_our_file_from_vfs = cdaudio_is_our_file,
-    .play = cdaudio_play,
-    .probe_for_tuple = make_tuple,
-    .schemes = schemes,
-    .have_subtune = TRUE,
-)
-
-static void cdaudio_error (const char * message_format, ...)
-{
-    va_list args;
-    char *msg = NULL;
-
-    va_start (args, message_format);
-    msg = g_markup_vprintf_escaped (message_format, args);
-    va_end (args);
-
-    aud_interface_show_error (msg);
-    g_free (msg);
-}
-
-/* main thread only */
-static void purge_playlist (int playlist)
-{
-    int length = aud_playlist_entry_count (playlist);
-
-    for (int count = 0; count < length; count ++)
-    {
-        char * filename = aud_playlist_entry_get_filename (playlist, count);
-
-        if (cdaudio_is_our_file (filename, NULL))
-        {
-            aud_playlist_entry_delete (playlist, count, 1);
-            count--;
-            length--;
-        }
-
-        str_unref (filename);
-    }
-}
-
-/* main thread only */
-static void purge_all_playlists (void)
-{
-    int playlists = aud_playlist_count ();
-    int count;
-
-    for (count = 0; count < playlists; count++)
-        purge_playlist (count);
-}
-
-/* main thread only */
-static bool_t monitor (gpointer unused)
-{
-    pthread_mutex_lock (& mutex);
-
-    /* make sure not to close drive handle while playing */
-    if (playing)
-    {
-        pthread_mutex_unlock (& mutex);
-        return true;
-    }
-
-    if (trackinfo != NULL)
-        refresh_trackinfo (FALSE);
-
-    if (trackinfo != NULL)
-    {
-        pthread_mutex_unlock (& mutex);
-        return TRUE;
-    }
-
-    monitor_source = 0;
-    pthread_mutex_unlock (& mutex);
-
-    purge_all_playlists ();
-    return FALSE;
-}
-
-/* mutex must be locked */
-static void trigger_monitor (void)
-{
-    if (! monitor_source)
-        monitor_source = g_timeout_add_seconds (1, monitor, NULL);
-}
-
-/* main thread only */
-static bool_t cdaudio_init (void)
-{
-    aud_config_set_defaults ("CDDA", cdaudio_defaults);
-
-    if (!cdio_init ())
-    {
-        cdaudio_error (_("Failed to initialize cdio subsystem."));
-        return FALSE;
-    }
-
-    libcddb_init ();
-
-    return TRUE;
-}
-
-/* thread safe (mutex may be locked) */
-static int cdaudio_is_our_file (const char * filename, VFSFile * file)
-{
-    return !strncmp (filename, "cdda://", 7);
-}
-
-/* thread safe (mutex may be locked) */
-static void cdaudio_set_strinfo (trackinfo_t * t,
-                                 const char * performer, const char * name,
-                                 const char * genre)
-{
-    g_strlcpy (t->performer, performer ? performer : "", DEF_STRING_LEN);
-    g_strlcpy (t->name, name ? name : "", DEF_STRING_LEN);
-    g_strlcpy (t->genre, genre ? genre : "", DEF_STRING_LEN);
-}
-
-/* thread safe (mutex may be locked) */
-static void cdaudio_set_fullinfo (trackinfo_t * t,
-                                  const lsn_t startlsn, const lsn_t endlsn,
-                                  const char * performer, const char * name,
-                                  const char * genre)
-{
-    t->startlsn = startlsn;
-    t->endlsn = endlsn;
-    cdaudio_set_strinfo (t, performer, name, genre);
-}
-
-/* play thread only */
-static bool_t cdaudio_play (const char * name, VFSFile * file)
-{
-    pthread_mutex_lock (& mutex);
-
-    if (trackinfo == NULL)
-    {
-        refresh_trackinfo (TRUE);
-
-        if (trackinfo == NULL)
-        {
-            pthread_mutex_unlock (& mutex);
-            return FALSE;
-        }
-    }
-
-    bool_t okay = FALSE;
-    int trackno = find_trackno_from_filename (name);
-
-    if (trackno < 0)
-        cdaudio_error (_("Invalid URI %s."), name);
-    else if (trackno < firsttrackno || trackno > lasttrackno)
-        cdaudio_error (_("Track %d not found."), trackno);
-    else if (! cdda_track_audiop (pcdrom_drive, trackno))
-        cdaudio_error (_("Track %d is a data track."), trackno);
-    else if (! aud_input_open_audio (FMT_S16_LE, 44100, 2))
-        cdaudio_error (_("Failed to open audio output."));
-    else
-        okay = TRUE;
-
-    if (! okay)
-    {
-        pthread_mutex_unlock (& mutex);
-        return FALSE;
-    }
-
-    int startlsn = trackinfo[trackno].startlsn;
-    int endlsn = trackinfo[trackno].endlsn;
-
-    playing = TRUE;
-
-    aud_input_set_bitrate (1411200);
-
-    int buffer_size = aud_get_int (NULL, "output_buffer_size");
-    int speed = aud_get_int ("CDDA", "disc_speed");
-    speed = CLAMP (speed, MIN_DISC_SPEED, MAX_DISC_SPEED);
-    int sectors = CLAMP (buffer_size / 2, 50, 250) * speed * 75 / 1000;
-    unsigned char buffer[2352 * sectors];
-    int currlsn = startlsn;
-    int retry_count = 0, skip_count = 0;
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_time = aud_input_check_seek ();
-        if (seek_time >= 0)
-            currlsn = startlsn + (seek_time * 75 / 1000);
-
-        sectors = MIN (sectors, endlsn + 1 - currlsn);
-        if (sectors < 1)
-            break;
-
-        /* unlock mutex here to avoid blocking
-         * other threads must be careful not to close drive handle */
-        pthread_mutex_unlock (& mutex);
-
-        int ret = cdio_read_audio_sectors (pcdrom_drive->p_cdio, buffer,
-         currlsn, sectors);
-
-        if (ret == DRIVER_OP_SUCCESS)
-            aud_input_write_audio (buffer, 2352 * sectors);
-
-        pthread_mutex_lock (& mutex);
-
-        if (ret == DRIVER_OP_SUCCESS)
-        {
-            currlsn += sectors;
-            retry_count = 0;
-            skip_count = 0;
-        }
-        else if (sectors > 16)
-        {
-            /* maybe a smaller read size will help */
-            sectors /= 2;
-        }
-        else if (retry_count < MAX_RETRIES)
-        {
-            /* still failed; retry a few times */
-            retry_count ++;
-        }
-        else if (skip_count < MAX_SKIPS)
-        {
-            /* maybe the disk is scratched; try skipping ahead */
-            currlsn = MIN (currlsn + 75, endlsn + 1);
-            skip_count ++;
-        }
-        else
-        {
-            /* still failed; give it up */
-            cdaudio_error (_("Error reading audio CD."));
-            break;
-        }
-    }
-
-    playing = FALSE;
-
-    pthread_mutex_unlock (& mutex);
-    return TRUE;
-}
-
-/* main thread only */
-static void cdaudio_cleanup (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    reset_trackinfo ();
-    libcddb_shutdown ();
-
-    pthread_mutex_unlock (& mutex);
-}
-
-/* thread safe */
-static Tuple * make_tuple (const char * filename, VFSFile * file)
-{
-    bool_t whole_disk = ! strcmp (filename, "cdda://");
-    Tuple * tuple = NULL;
-
-    pthread_mutex_lock (& mutex);
-
-    /* reset cached info when adding CD to the playlist */
-    if (whole_disk && ! playing)
-        reset_trackinfo ();
-
-    if (trackinfo == NULL)
-        refresh_trackinfo (TRUE);
-    if (trackinfo == NULL)
-        goto DONE;
-
-    if (whole_disk)
-    {
-        tuple = tuple_new_from_filename (filename);
-
-        int subtunes[n_audio_tracks];
-        int i = 0;
-
-        /* only add the audio tracks to the playlist */
-        for (int trackno = firsttrackno; trackno <= lasttrackno; trackno++)
-            if (cdda_track_audiop (pcdrom_drive, trackno))
-                subtunes[i ++] = trackno;
-
-        tuple_set_subtunes (tuple, n_audio_tracks, subtunes);
-
-        goto DONE;
-    }
-
-    int trackno = find_trackno_from_filename (filename);
-
-    if (trackno < firsttrackno || trackno > lasttrackno)
-    {
-        warn ("Track %d not found.\n", trackno);
-        goto DONE;
-    }
-
-    if (!cdda_track_audiop (pcdrom_drive, trackno))
-    {
-        warn ("Track %d is a data track.\n", trackno);
-        goto DONE;
-    }
-
-    tuple = tuple_new_from_filename (filename);
-    tuple_set_format (tuple, _("Audio CD"), 2, 44100, 1411);
-    tuple_set_int (tuple, FIELD_TRACK_NUMBER, trackno);
-    tuple_set_int (tuple, FIELD_LENGTH, calculate_track_length
-     (trackinfo[trackno].startlsn, trackinfo[trackno].endlsn));
-
-    if (trackinfo[trackno].name[0])
-        tuple_set_str (tuple, FIELD_TITLE, trackinfo[trackno].name);
-    else
-    {
-        SPRINTF (title, _("Track %d"), trackno);
-        tuple_set_str (tuple, FIELD_TITLE, title);
-    }
-
-    if (trackinfo[trackno].performer[0])
-        tuple_set_str (tuple, FIELD_ARTIST, trackinfo[trackno].performer);
-    if (trackinfo[0].name[0])
-        tuple_set_str (tuple, FIELD_ALBUM, trackinfo[0].name);
-    if (trackinfo[trackno].genre[0])
-        tuple_set_str (tuple, FIELD_GENRE, trackinfo[trackno].genre);
-
-  DONE:
-    pthread_mutex_unlock (& mutex);
-    return tuple;
-}
-
-/* mutex must be locked */
-static void open_cd (void)
-{
-    AUDDBG ("Opening CD drive.\n");
-    g_return_if_fail (pcdrom_drive == NULL);
-
-    char * device = aud_get_str ("CDDA", "device");
-
-    if (device[0])
-    {
-        if (! (pcdrom_drive = cdda_identify (device, 1, NULL)))
-            cdaudio_error (_("Failed to open CD device %s."), device);
-    }
-    else
-    {
-        char * * ppcd_drives = cdio_get_devices_with_cap (NULL, CDIO_FS_AUDIO, FALSE);
-
-        if (ppcd_drives && ppcd_drives[0])
-        {
-            if (! (pcdrom_drive = cdda_identify (ppcd_drives[0], 1, NULL)))
-                cdaudio_error (_("Failed to open CD device %s."), ppcd_drives[0]);
-        }
-        else
-            cdaudio_error (_("No audio capable CD drive found."));
-
-        if (ppcd_drives)
-            cdio_free_device_list (ppcd_drives);
-    }
-
-    str_unref (device);
-}
-
-/* mutex must be locked */
-static void scan_cd (void)
-{
-    AUDDBG ("Scanning CD drive.\n");
-    g_return_if_fail (pcdrom_drive != NULL);
-    g_return_if_fail (trackinfo == NULL);
-
-    int trackno;
-
-    /* general track initialization */
-
-    /* skip endianness detection (because it only affects cdda_read, and we use
-     * cdio_read_audio_sectors instead) */
-    pcdrom_drive->bigendianp = 0;
-
-    /* finish initialization of drive/disc (performs disc TOC sanitization) */
-    if (cdda_open (pcdrom_drive) != 0)
-    {
-        cdaudio_error (_("Failed to finish initializing opened CD drive."));
-        goto ERR;
-    }
-
-    int speed = aud_get_int ("CDDA", "disc_speed");
-    speed = CLAMP (speed, MIN_DISC_SPEED, MAX_DISC_SPEED);
-    if (cdda_speed_set (pcdrom_drive, speed) != DRIVER_OP_SUCCESS)
-        warn ("Cannot set drive speed.\n");
-
-    firsttrackno = cdio_get_first_track_num (pcdrom_drive->p_cdio);
-    lasttrackno = cdio_get_last_track_num (pcdrom_drive->p_cdio);
-    if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK)
-    {
-        cdaudio_error (_("Failed to retrieve first/last track number."));
-        goto ERR;
-    }
-    AUDDBG ("first track is %d and last track is %d\n", firsttrackno,
-           lasttrackno);
-
-    trackinfo = (trackinfo_t *) g_new (trackinfo_t, (lasttrackno + 1));
-
-    cdaudio_set_fullinfo (&trackinfo[0],
-                          cdda_track_firstsector (pcdrom_drive, 0),
-                          cdda_track_lastsector (pcdrom_drive, lasttrackno),
-                          "", "", "");
-
-    n_audio_tracks = 0;
-
-    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
-    {
-        cdaudio_set_fullinfo (&trackinfo[trackno],
-                              cdda_track_firstsector (pcdrom_drive, trackno),
-                              cdda_track_lastsector (pcdrom_drive, trackno),
-                              "", "", "");
-
-        if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN
-            || trackinfo[trackno].endlsn == CDIO_INVALID_LSN)
-        {
-            cdaudio_error (_("Cannot read start/end LSN for track %d."), trackno);
-            goto ERR;
-        }
-
-        /* count how many tracks are audio tracks */
-        if (cdda_track_audiop (pcdrom_drive, trackno))
-            n_audio_tracks++;
-    }
-
-    /* get trackinfo[0] cdtext information (the disc) */
-    cdtext_t *pcdtext = NULL;
-    if (aud_get_bool ("CDDA", "use_cdtext"))
-    {
-        AUDDBG ("getting cd-text information for disc\n");
-#if LIBCDIO_VERSION_NUM >= 90
-        pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio);
-        if (pcdtext == NULL)
-#else
-        pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, 0);
-        if (pcdtext == NULL || pcdtext->field[CDTEXT_TITLE] == NULL)
-#endif
-        {
-            AUDDBG ("no cd-text available for disc\n");
-        }
-        else
-        {
-            cdaudio_set_strinfo (&trackinfo[0],
-#if LIBCDIO_VERSION_NUM >= 90
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_PERFORMER, 0),
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_TITLE, 0),
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_GENRE, 0));
-#else
-                                 pcdtext->field[CDTEXT_PERFORMER],
-                                 pcdtext->field[CDTEXT_TITLE],
-                                 pcdtext->field[CDTEXT_GENRE]);
-#endif
-        }
-    }
-
-    /* get track information from cdtext */
-    bool_t cdtext_was_available = FALSE;
-    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
-    {
-#if LIBCDIO_VERSION_NUM < 90
-        if (aud_get_bool ("CDDA", "use_cdtext"))
-        {
-            AUDDBG ("getting cd-text information for track %d\n", trackno);
-            pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, trackno);
-            if (pcdtext == NULL || pcdtext->field[CDTEXT_PERFORMER] == NULL)
-            {
-                AUDDBG ("no cd-text available for track %d\n", trackno);
-                pcdtext = NULL;
-            }
-        }
-#endif
-
-        if (pcdtext != NULL)
-        {
-            cdaudio_set_strinfo (&trackinfo[trackno],
-#if LIBCDIO_VERSION_NUM >= 90
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_PERFORMER, trackno),
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_TITLE, trackno),
-                                 cdtext_get(pcdtext, CDTEXT_FIELD_GENRE, trackno));
-#else
-                                 pcdtext->field[CDTEXT_PERFORMER],
-                                 pcdtext->field[CDTEXT_TITLE],
-                                 pcdtext->field[CDTEXT_GENRE]);
-#endif
-            cdtext_was_available = TRUE;
-        }
-    }
-
-    if (!cdtext_was_available)
-    {
-        /* initialize de cddb subsystem */
-        cddb_conn_t *pcddb_conn = NULL;
-        cddb_disc_t *pcddb_disc = NULL;
-        cddb_track_t *pcddb_track = NULL;
-        lba_t lba;              /* Logical Block Address */
-
-        if (aud_get_bool ("CDDA", "use_cddb"))
-        {
-            pcddb_conn = cddb_new ();
-            if (pcddb_conn == NULL)
-                cdaudio_error (_("Failed to create the cddb connection."));
-            else
-            {
-                AUDDBG ("getting CDDB info\n");
-
-                cddb_cache_enable (pcddb_conn);
-                // cddb_cache_set_dir(pcddb_conn, "~/.cddbslave");
-
-                char * server = aud_get_str ("CDDA", "cddbserver");
-                char * path = aud_get_str ("CDDA", "cddbpath");
-                int port = aud_get_int ("CDDA", "cddbport");
-
-                if (aud_get_bool (NULL, "use_proxy"))
-                {
-                    char * prhost = aud_get_str (NULL, "proxy_host");
-                    int prport = aud_get_int (NULL, "proxy_port");
-                    char * pruser = aud_get_str (NULL, "proxy_user");
-                    char * prpass = aud_get_str (NULL, "proxy_pass");
-
-                    cddb_http_proxy_enable (pcddb_conn);
-                    cddb_set_http_proxy_server_name (pcddb_conn, prhost);
-                    cddb_set_http_proxy_server_port (pcddb_conn, prport);
-                    cddb_set_http_proxy_username (pcddb_conn, pruser);
-                    cddb_set_http_proxy_password (pcddb_conn, prpass);
-
-                    str_unref (prhost);
-                    str_unref (pruser);
-                    str_unref (prpass);
-
-                    cddb_set_server_name (pcddb_conn, server);
-                    cddb_set_server_port (pcddb_conn, port);
-                }
-                else if (aud_get_bool ("CDDA", "cddbhttp"))
-                {
-                    cddb_http_enable (pcddb_conn);
-                    cddb_set_server_name (pcddb_conn, server);
-                    cddb_set_server_port (pcddb_conn, port);
-                    cddb_set_http_path_query (pcddb_conn, path);
-                }
-                else
-                {
-                    cddb_set_server_name (pcddb_conn, server);
-                    cddb_set_server_port (pcddb_conn, port);
-                }
-
-                str_unref (server);
-                str_unref (path);
-
-                pcddb_disc = cddb_disc_new ();
-
-                lba = cdio_get_track_lba (pcdrom_drive->p_cdio,
-                                          CDIO_CDROM_LEADOUT_TRACK);
-                cddb_disc_set_length (pcddb_disc, FRAMES_TO_SECONDS (lba));
-
-                for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
-                {
-                    pcddb_track = cddb_track_new ();
-                    cddb_track_set_frame_offset (pcddb_track,
-                                                 cdio_get_track_lba (
-                                                     pcdrom_drive->p_cdio,
-                                                     trackno));
-                    cddb_disc_add_track (pcddb_disc, pcddb_track);
-                }
-
-                cddb_disc_calc_discid (pcddb_disc);
-
-#if DEBUG
-                guint discid = cddb_disc_get_discid (pcddb_disc);
-                AUDDBG ("CDDB disc id = %x\n", discid);
-#endif
-
-                int matches;
-                if ((matches = cddb_query (pcddb_conn, pcddb_disc)) == -1)
-                {
-                    if (cddb_errno (pcddb_conn) == CDDB_ERR_OK)
-                        cdaudio_error (_("Failed to query the CDDB server"));
-                    else
-                        cdaudio_error (_("Failed to query the CDDB server: %s"),
-                                       cddb_error_str (cddb_errno
-                                                       (pcddb_conn)));
-
-                    cddb_disc_destroy (pcddb_disc);
-                    pcddb_disc = NULL;
-                }
-                else
-                {
-                    if (matches == 0)
-                    {
-                        AUDDBG ("no cddb info available for this disc\n");
-
-                        cddb_disc_destroy (pcddb_disc);
-                        pcddb_disc = NULL;
-                    }
-                    else
-                    {
-                        AUDDBG ("CDDB disc category = \"%s\"\n",
-                               cddb_disc_get_category_str (pcddb_disc));
-
-                        cddb_read (pcddb_conn, pcddb_disc);
-                        if (cddb_errno (pcddb_conn) != CDDB_ERR_OK)
-                        {
-                            cdaudio_error (_("Failed to read the cddb info: %s"),
-                                           cddb_error_str (cddb_errno
-                                                           (pcddb_conn)));
-                            cddb_disc_destroy (pcddb_disc);
-                            pcddb_disc = NULL;
-                        }
-                        else
-                        {
-                            cdaudio_set_strinfo (&trackinfo[0],
-                                                 cddb_disc_get_artist
-                                                 (pcddb_disc),
-                                                 cddb_disc_get_title
-                                                 (pcddb_disc),
-                                                 cddb_disc_get_genre
-                                                 (pcddb_disc));
-
-                            int trackno;
-                            for (trackno = firsttrackno; trackno <= lasttrackno;
-                                 trackno++)
-                            {
-                                cddb_track_t *pcddb_track =
-                                    cddb_disc_get_track (pcddb_disc,
-                                                         trackno - 1);
-                                cdaudio_set_strinfo (&trackinfo[trackno],
-                                                     cddb_track_get_artist
-                                                     (pcddb_track),
-                                                     cddb_track_get_title
-                                                     (pcddb_track),
-                                                     cddb_disc_get_genre
-                                                     (pcddb_disc));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        if (pcddb_disc != NULL)
-            cddb_disc_destroy (pcddb_disc);
-
-        if (pcddb_conn != NULL)
-            cddb_destroy (pcddb_conn);
-    }
-
-    return;
-
-  ERR:
-    g_free (trackinfo);
-    trackinfo = NULL;
-}
-
-/* mutex must be locked */
-static void refresh_trackinfo (bool_t warning)
-{
-    if (pcdrom_drive == NULL)
-    {
-        open_cd ();
-        if (pcdrom_drive == NULL)
-            return;
-    }
-
-    int mode = cdio_get_discmode (pcdrom_drive->p_cdio);
-#ifdef _WIN32 /* cdio_get_discmode reports the wrong disk type sometimes */
-    if (mode == CDIO_DISC_MODE_NO_INFO || mode == CDIO_DISC_MODE_ERROR)
-#else
-    if (mode != CDIO_DISC_MODE_CD_DA && mode != CDIO_DISC_MODE_CD_MIXED)
-#endif
-    {
-        if (warning)
-        {
-            if (mode == CDIO_DISC_MODE_NO_INFO)
-                cdaudio_error (_("Drive is empty."));
-            else
-                cdaudio_error (_("Unsupported disk type."));
-        }
-
-        reset_trackinfo ();
-        return;
-    }
-
-    if (trackinfo == NULL || cdio_get_media_changed (pcdrom_drive->p_cdio))
-    {
-        g_free (trackinfo);
-        trackinfo = NULL;
-        scan_cd ();
-
-        if (trackinfo != NULL)
-            trigger_monitor ();
-    }
-}
-
-/* mutex must be locked */
-static void reset_trackinfo (void)
-{
-    if (monitor_source)
-    {
-        g_source_remove (monitor_source);
-        monitor_source = 0;
-    }
-
-    if (pcdrom_drive != NULL)
-    {
-        cdda_close (pcdrom_drive);
-        pcdrom_drive = NULL;
-    }
-
-    g_free (trackinfo);
-    trackinfo = NULL;
-}
-
-/* thread safe (mutex may be locked) */
-static int calculate_track_length (int startlsn, int endlsn)
-{
-    return ((endlsn - startlsn + 1) * 1000) / 75;
-}
-
-/* thread safe (mutex may be locked) */
-static int find_trackno_from_filename (const char * filename)
-{
-    int track;
-
-    if (strncmp (filename, "cdda://?", 8) || sscanf (filename + 8, "%d",
-                                                     &track) != 1)
-        return -1;
-
-    return track;
-}
diff --git a/src/cdaudio-ng/cdaudio-ng.cc b/src/cdaudio-ng/cdaudio-ng.cc
new file mode 100644
index 000000000000..6ac85edc865a
--- /dev/null
+++ b/src/cdaudio-ng/cdaudio-ng.cc
@@ -0,0 +1,815 @@
+/*
+ * Audacious CD Digital Audio plugin
+ *
+ * Copyright (c) 2007 Calin Crisan <ccrisan at gmail.com>
+ * Copyright (c) 2009-2012 John Lindgren <john.lindgren at aol.com>
+ * Copyright (c) 2009 Tomasz Moń <desowin at gmail.com>
+ *
+ * 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 <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* prevent libcdio from redefining PACKAGE, VERSION, etc. */
+#define EXTERNAL_LIBCDIO_CONFIG_H
+
+#include <cdio/cdio.h>
+#include <cdio/cdtext.h>
+#include <cdio/track.h>
+#include <cdio/audio.h>
+#include <cdio/sector.h>
+#include <cdio/cd_types.h>
+
+#if LIBCDIO_VERSION_NUM >= 90
+#include <cdio/paranoia/cdda.h>
+#else
+#include <cdio/cdda.h>
+#endif
+
+#include <cddb/cddb.h>
+
+#include <libaudcore/audstrings.h>
+#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>
+#include <libaudcore/runtime.h>
+
+#define MIN_DISC_SPEED 2
+#define MAX_DISC_SPEED 24
+
+#define MAX_RETRIES 10
+#define MAX_SKIPS 10
+
+static const char * const cdaudio_schemes[] = {"cdda", nullptr};
+
+class CDAudio : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Audio CD Plugin"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagSubtunes)
+        .with_schemes (cdaudio_schemes);
+
+    constexpr CDAudio () : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    void cleanup ();
+
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT CDAudio aud_plugin_instance;
+
+typedef struct
+{
+    String performer;
+    String name;
+    String genre;
+    int startlsn;
+    int endlsn;
+}
+trackinfo_t;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool playing;
+
+/* lock mutex to read / set these variables */
+static int firsttrackno = -1;
+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);
+static void reset_trackinfo ();
+static int calculate_track_length (int startlsn, int endlsn);
+static int find_trackno_from_filename (const char * filename);
+
+const char CDAudio::about[] =
+ N_("Copyright (C) 2007-2012 Calin Crisan <ccrisan at gmail.com> and others.\n\n"
+    "Many thanks to libcdio developers <http://www.gnu.org/software/libcdio/>\n"
+    "and to libcddb developers <http://libcddb.sourceforge.net/>.\n\n"
+    "Also thank you to Tony Vroon for mentoring and guiding me.\n\n"
+    "This was a Google Summer of Code 2007 project.");
+
+const char * const CDAudio::defaults[] = {
+ "disc_speed", "2",
+ "use_cdtext", "TRUE",
+ "use_cddb", "TRUE",
+ "cddbhttp", "FALSE",
+ "cddbserver", "freedb.org",
+ "cddbport", "8880",
+ nullptr};
+
+const PreferencesWidget CDAudio::widgets[] = {
+    WidgetLabel (N_("<b>Device</b>")),
+    WidgetSpin (N_("Read speed:"),
+        WidgetInt ("CDDA", "disc_speed"),
+        {MIN_DISC_SPEED, MAX_DISC_SPEED, 1}),
+    WidgetEntry (N_("Override device:"),
+        WidgetString ("CDDA", "device")),
+    WidgetLabel (N_("<b>Metadata</b>")),
+    WidgetCheck (N_("Use CD-Text"),
+        WidgetBool ("CDDA", "use_cdtext")),
+    WidgetCheck (N_("Use CDDB"),
+        WidgetBool ("CDDA", "use_cddb")),
+    WidgetCheck (N_("Use HTTP instead of CDDBP"),
+        WidgetBool ("CDDA", "cddbhttp"),
+        WIDGET_CHILD),
+    WidgetEntry (N_("Server:"),
+        WidgetString ("CDDA", "cddbserver"),
+        {false},
+        WIDGET_CHILD),
+    WidgetEntry (N_("Path:"),
+        WidgetString ("CDDA", "cddbpath"),
+        {false},
+        WIDGET_CHILD),
+    WidgetSpin (N_("Port:"),
+        WidgetInt ("CDDA", "cddbport"),
+        {0, 65535, 1},
+        WIDGET_CHILD)
+};
+
+const PluginPreferences CDAudio::prefs = {{widgets}};
+
+static void cdaudio_error (const char * message_format, ...)
+{
+    va_list args;
+    va_start (args, message_format);
+    StringBuf msg = str_vprintf (message_format, args);
+    va_end (args);
+
+    aud_ui_show_error (msg);
+}
+
+/* main thread only */
+static void purge_playlist (int playlist)
+{
+    int length = aud_playlist_entry_count (playlist);
+
+    for (int count = 0; count < length; count ++)
+    {
+        String filename = aud_playlist_entry_get_filename (playlist, count);
+
+        if (! strncmp (filename, "cdda://", 7))
+        {
+            aud_playlist_entry_delete (playlist, count, 1);
+            count--;
+            length--;
+        }
+    }
+}
+
+/* main thread only */
+static void purge_all_playlists ()
+{
+    int playlists = aud_playlist_count ();
+    int count;
+
+    for (count = 0; count < playlists; count++)
+        purge_playlist (count);
+}
+
+/* main thread only */
+static void monitor (void *)
+{
+    pthread_mutex_lock (& mutex);
+
+    /* make sure not to close drive handle while playing */
+    if (playing)
+    {
+        pthread_mutex_unlock (& mutex);
+        return;
+    }
+
+    if (trackinfo.len ())
+        refresh_trackinfo (false);
+
+    if (trackinfo.len ())
+    {
+        pthread_mutex_unlock (& mutex);
+        return;
+    }
+
+    monitor_source.stop ();
+    pthread_mutex_unlock (& mutex);
+
+    purge_all_playlists ();
+}
+
+/* mutex must be locked */
+static void trigger_monitor ()
+{
+    if (! monitor_source.running ())
+        monitor_source.start (1000, monitor, nullptr);
+}
+
+/* main thread only */
+bool CDAudio::init ()
+{
+    aud_config_set_defaults ("CDDA", defaults);
+
+    if (!cdio_init ())
+    {
+        cdaudio_error (_("Failed to initialize cdio subsystem."));
+        return false;
+    }
+
+    libcddb_init ();
+
+    return true;
+}
+
+/* thread safe (mutex may be locked) */
+bool CDAudio::is_our_file (const char * filename, VFSFile & file)
+{
+    return !strncmp (filename, "cdda://", 7);
+}
+
+/* play thread only */
+bool CDAudio::play (const char * name, VFSFile & file)
+{
+    pthread_mutex_lock (& mutex);
+
+    if (! trackinfo.len ())
+    {
+        refresh_trackinfo (true);
+
+        if (! trackinfo.len ())
+        {
+            pthread_mutex_unlock (& mutex);
+            return false;
+        }
+    }
+
+    bool okay = false;
+    int trackno = find_trackno_from_filename (name);
+
+    if (trackno < 0)
+        cdaudio_error (_("Invalid URI %s."), name);
+    else if (trackno < firsttrackno || trackno > lasttrackno)
+        cdaudio_error (_("Track %d not found."), trackno);
+    else if (! cdda_track_audiop (pcdrom_drive, trackno))
+        cdaudio_error (_("Track %d is a data track."), trackno);
+    else
+        okay = true;
+
+    if (! okay)
+    {
+        pthread_mutex_unlock (& mutex);
+        return false;
+    }
+
+    set_stream_bitrate (1411200);
+    open_audio (FMT_S16_LE, 44100, 2);
+
+    int startlsn = trackinfo[trackno].startlsn;
+    int endlsn = trackinfo[trackno].endlsn;
+
+    playing = true;
+
+    int buffer_size = aud_get_int (nullptr, "output_buffer_size");
+    int speed = aud_get_int ("CDDA", "disc_speed");
+    speed = aud::clamp (speed, MIN_DISC_SPEED, MAX_DISC_SPEED);
+    int sectors = aud::clamp (buffer_size / 2, 50, 250) * speed * 75 / 1000;
+    int currlsn = startlsn;
+    int retry_count = 0, skip_count = 0;
+
+    Index<unsigned char> buffer;
+    buffer.insert (0, 2352 * sectors);
+
+    while (! check_stop ())
+    {
+        int seek_time = check_seek ();
+        if (seek_time >= 0)
+            currlsn = startlsn + (seek_time * 75 / 1000);
+
+        sectors = aud::min (sectors, endlsn + 1 - currlsn);
+        if (sectors < 1)
+            break;
+
+        /* unlock mutex here to avoid blocking
+         * other threads must be careful not to close drive handle */
+        pthread_mutex_unlock (& mutex);
+
+        int ret = cdio_read_audio_sectors (pcdrom_drive->p_cdio,
+         buffer.begin (), currlsn, sectors);
+
+        if (ret == DRIVER_OP_SUCCESS)
+            write_audio (buffer.begin (), 2352 * sectors);
+
+        pthread_mutex_lock (& mutex);
+
+        if (ret == DRIVER_OP_SUCCESS)
+        {
+            currlsn += sectors;
+            retry_count = 0;
+            skip_count = 0;
+        }
+        else if (sectors > 16)
+        {
+            /* maybe a smaller read size will help */
+            sectors /= 2;
+        }
+        else if (retry_count < MAX_RETRIES)
+        {
+            /* still failed; retry a few times */
+            retry_count ++;
+        }
+        else if (skip_count < MAX_SKIPS)
+        {
+            /* maybe the disk is scratched; try skipping ahead */
+            currlsn = aud::min (currlsn + 75, endlsn + 1);
+            skip_count ++;
+        }
+        else
+        {
+            /* still failed; give it up */
+            cdaudio_error (_("Error reading audio CD."));
+            break;
+        }
+    }
+
+    playing = false;
+
+    pthread_mutex_unlock (& mutex);
+    return true;
+}
+
+/* main thread only */
+void CDAudio::cleanup ()
+{
+    pthread_mutex_lock (& mutex);
+
+    reset_trackinfo ();
+    libcddb_shutdown ();
+
+    pthread_mutex_unlock (& mutex);
+}
+
+/* thread safe */
+Tuple CDAudio::read_tuple (const char * filename, VFSFile & file)
+{
+    bool whole_disk = ! strcmp (filename, "cdda://");
+    Tuple tuple;
+
+    pthread_mutex_lock (& mutex);
+
+    /* reset cached info when adding CD to the playlist */
+    if (whole_disk && ! playing)
+        reset_trackinfo ();
+
+    if (! trackinfo.len ())
+        refresh_trackinfo (true);
+    if (! trackinfo.len ())
+        goto DONE;
+
+    if (whole_disk)
+    {
+        tuple.set_filename (filename);
+
+        Index<int> subtunes;
+
+        /* only add the audio tracks to the playlist */
+        for (int trackno = firsttrackno; trackno <= lasttrackno; trackno++)
+            if (cdda_track_audiop (pcdrom_drive, trackno))
+                subtunes.append (trackno);
+
+        tuple.set_subtunes (subtunes.len (), subtunes.begin ());
+    }
+    else
+    {
+        int trackno = find_trackno_from_filename (filename);
+
+        if (trackno < firsttrackno || trackno > lasttrackno)
+        {
+            AUDERR ("Track %d not found.\n", trackno);
+            goto DONE;
+        }
+
+        if (!cdda_track_audiop (pcdrom_drive, trackno))
+        {
+            AUDERR ("Track %d is a data track.\n", trackno);
+            goto DONE;
+        }
+
+        tuple.set_filename (filename);
+        tuple.set_format (_("Audio CD"), 2, 44100, 1411);
+        tuple.set_int (Tuple::Track, trackno);
+        tuple.set_int (Tuple::Length, calculate_track_length
+         (trackinfo[trackno].startlsn, trackinfo[trackno].endlsn));
+
+        if (trackinfo[trackno].name)
+            tuple.set_str (Tuple::Title, trackinfo[trackno].name);
+        if (trackinfo[trackno].performer)
+            tuple.set_str (Tuple::Artist, trackinfo[trackno].performer);
+        if (trackinfo[0].name)
+            tuple.set_str (Tuple::Album, trackinfo[0].name);
+        if (trackinfo[trackno].genre)
+            tuple.set_str (Tuple::Genre, trackinfo[trackno].genre);
+    }
+
+  DONE:
+    pthread_mutex_unlock (& mutex);
+    return tuple;
+}
+
+/* mutex must be locked */
+static void open_cd ()
+{
+    AUDDBG ("Opening CD drive.\n");
+    assert (pcdrom_drive == nullptr);
+
+    String device = aud_get_str ("CDDA", "device");
+
+    if (device[0])
+    {
+        if (! (pcdrom_drive = cdda_identify (device, 1, nullptr)))
+            cdaudio_error (_("Failed to open CD device %s."), (const char *) device);
+    }
+    else
+    {
+        char * * ppcd_drives = cdio_get_devices_with_cap (nullptr, CDIO_FS_AUDIO, false);
+
+        if (ppcd_drives && ppcd_drives[0])
+        {
+            if (! (pcdrom_drive = cdda_identify (ppcd_drives[0], 1, nullptr)))
+                cdaudio_error (_("Failed to open CD device %s."), ppcd_drives[0]);
+        }
+        else
+            cdaudio_error (_("No audio capable CD drive found."));
+
+        if (ppcd_drives)
+            cdio_free_device_list (ppcd_drives);
+    }
+}
+
+/* mutex must be locked */
+static bool scan_cd ()
+{
+    AUDDBG ("Scanning CD drive.\n");
+    assert (pcdrom_drive);
+    assert (! trackinfo.len ());
+
+    int trackno;
+
+    /* general track initialization */
+
+    /* skip endianness detection (because it only affects cdda_read, and we use
+     * cdio_read_audio_sectors instead) */
+    pcdrom_drive->bigendianp = 0;
+
+    /* finish initialization of drive/disc (performs disc TOC sanitization) */
+    if (cdda_open (pcdrom_drive) != 0)
+    {
+        cdaudio_error (_("Failed to finish initializing opened CD drive."));
+        return false;
+    }
+
+    int speed = aud_get_int ("CDDA", "disc_speed");
+    speed = aud::clamp (speed, MIN_DISC_SPEED, MAX_DISC_SPEED);
+    if (cdda_speed_set (pcdrom_drive, speed) != DRIVER_OP_SUCCESS)
+        AUDERR ("Cannot set drive speed.\n");
+
+    firsttrackno = cdio_get_first_track_num (pcdrom_drive->p_cdio);
+    lasttrackno = cdio_get_last_track_num (pcdrom_drive->p_cdio);
+    if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK)
+    {
+        cdaudio_error (_("Failed to retrieve first/last track number."));
+        return false;
+    }
+    AUDDBG ("first track is %d and last track is %d\n", firsttrackno,
+           lasttrackno);
+
+    trackinfo.insert (0, lasttrackno + 1);
+
+    trackinfo[0].startlsn = cdda_track_firstsector (pcdrom_drive, 0);
+    trackinfo[0].endlsn = cdda_track_lastsector (pcdrom_drive, lasttrackno);
+
+    n_audio_tracks = 0;
+
+    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
+    {
+        trackinfo[trackno].startlsn = cdda_track_firstsector (pcdrom_drive, trackno);
+        trackinfo[trackno].endlsn = cdda_track_lastsector (pcdrom_drive, trackno);
+
+        if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN
+            || trackinfo[trackno].endlsn == CDIO_INVALID_LSN)
+        {
+            cdaudio_error (_("Cannot read start/end LSN for track %d."), trackno);
+            return false;
+        }
+
+        /* count how many tracks are audio tracks */
+        if (cdda_track_audiop (pcdrom_drive, trackno))
+            n_audio_tracks++;
+    }
+
+    /* get trackinfo[0] cdtext information (the disc) */
+    cdtext_t *pcdtext = nullptr;
+    if (aud_get_bool ("CDDA", "use_cdtext"))
+    {
+        AUDDBG ("getting cd-text information for disc\n");
+#if LIBCDIO_VERSION_NUM >= 90
+        pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio);
+        if (pcdtext == nullptr)
+#else
+        pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, 0);
+        if (pcdtext == nullptr || pcdtext->field[CDTEXT_TITLE] == nullptr)
+#endif
+        {
+            AUDDBG ("no cd-text available for disc\n");
+        }
+        else
+        {
+#if LIBCDIO_VERSION_NUM >= 90
+            trackinfo[0].performer = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_PERFORMER, 0));
+            trackinfo[0].name = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_TITLE, 0));
+            trackinfo[0].genre = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_GENRE, 0));
+#else
+            trackinfo[0].performer = String (pcdtext->field[CDTEXT_PERFORMER]);
+            trackinfo[0].name = String (pcdtext->field[CDTEXT_TITLE]);
+            trackinfo[0].genre = String (pcdtext->field[CDTEXT_GENRE]);
+#endif
+        }
+    }
+
+    /* get track information from cdtext */
+    bool cdtext_was_available = false;
+    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
+    {
+#if LIBCDIO_VERSION_NUM < 90
+        if (aud_get_bool ("CDDA", "use_cdtext"))
+        {
+            AUDDBG ("getting cd-text information for track %d\n", trackno);
+            pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, trackno);
+            if (pcdtext == nullptr || pcdtext->field[CDTEXT_PERFORMER] == nullptr)
+            {
+                AUDDBG ("no cd-text available for track %d\n", trackno);
+                pcdtext = nullptr;
+            }
+        }
+#endif
+
+        if (pcdtext != nullptr)
+        {
+#if LIBCDIO_VERSION_NUM >= 90
+            trackinfo[trackno].performer = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_PERFORMER, trackno));
+            trackinfo[trackno].name = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_TITLE, trackno));
+            trackinfo[trackno].genre = String (cdtext_get_const (pcdtext, CDTEXT_FIELD_GENRE, trackno));
+#else
+            trackinfo[trackno].performer = String (pcdtext->field[CDTEXT_PERFORMER]);
+            trackinfo[trackno].name = String (pcdtext->field[CDTEXT_TITLE]);
+            trackinfo[trackno].genre = String (pcdtext->field[CDTEXT_GENRE]);
+#endif
+            cdtext_was_available = true;
+        }
+    }
+
+    if (!cdtext_was_available)
+    {
+        /* initialize de cddb subsystem */
+        cddb_conn_t *pcddb_conn = nullptr;
+        cddb_disc_t *pcddb_disc = nullptr;
+        cddb_track_t *pcddb_track = nullptr;
+        lba_t lba;              /* Logical Block Address */
+
+        if (aud_get_bool ("CDDA", "use_cddb"))
+        {
+            pcddb_conn = cddb_new ();
+            if (pcddb_conn == nullptr)
+                cdaudio_error (_("Failed to create the cddb connection."));
+            else
+            {
+                AUDDBG ("getting CDDB info\n");
+
+                cddb_cache_enable (pcddb_conn);
+                // cddb_cache_set_dir(pcddb_conn, "~/.cddbslave");
+
+                String server = aud_get_str ("CDDA", "cddbserver");
+                String path = aud_get_str ("CDDA", "cddbpath");
+                int port = aud_get_int ("CDDA", "cddbport");
+
+                if (aud_get_bool (nullptr, "use_proxy"))
+                {
+                    String prhost = aud_get_str (nullptr, "proxy_host");
+                    int prport = aud_get_int (nullptr, "proxy_port");
+                    String pruser = aud_get_str (nullptr, "proxy_user");
+                    String prpass = aud_get_str (nullptr, "proxy_pass");
+
+                    cddb_http_proxy_enable (pcddb_conn);
+                    cddb_set_http_proxy_server_name (pcddb_conn, prhost);
+                    cddb_set_http_proxy_server_port (pcddb_conn, prport);
+                    cddb_set_http_proxy_username (pcddb_conn, pruser);
+                    cddb_set_http_proxy_password (pcddb_conn, prpass);
+
+                    cddb_set_server_name (pcddb_conn, server);
+                    cddb_set_server_port (pcddb_conn, port);
+                }
+                else if (aud_get_bool ("CDDA", "cddbhttp"))
+                {
+                    cddb_http_enable (pcddb_conn);
+                    cddb_set_server_name (pcddb_conn, server);
+                    cddb_set_server_port (pcddb_conn, port);
+                    cddb_set_http_path_query (pcddb_conn, path);
+                }
+                else
+                {
+                    cddb_set_server_name (pcddb_conn, server);
+                    cddb_set_server_port (pcddb_conn, port);
+                }
+
+                pcddb_disc = cddb_disc_new ();
+
+                lba = cdio_get_track_lba (pcdrom_drive->p_cdio,
+                                          CDIO_CDROM_LEADOUT_TRACK);
+                cddb_disc_set_length (pcddb_disc, FRAMES_TO_SECONDS (lba));
+
+                for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
+                {
+                    pcddb_track = cddb_track_new ();
+                    cddb_track_set_frame_offset (pcddb_track,
+                                                 cdio_get_track_lba (
+                                                     pcdrom_drive->p_cdio,
+                                                     trackno));
+                    cddb_disc_add_track (pcddb_disc, pcddb_track);
+                }
+
+                cddb_disc_calc_discid (pcddb_disc);
+
+                unsigned discid = cddb_disc_get_discid (pcddb_disc);
+                AUDDBG ("CDDB disc id = %x\n", discid);
+
+                int matches;
+                if ((matches = cddb_query (pcddb_conn, pcddb_disc)) == -1)
+                {
+                    if (cddb_errno (pcddb_conn) == CDDB_ERR_OK)
+                        cdaudio_error (_("Failed to query the CDDB server"));
+                    else
+                        cdaudio_error (_("Failed to query the CDDB server: %s"),
+                                       cddb_error_str (cddb_errno
+                                                       (pcddb_conn)));
+
+                    cddb_disc_destroy (pcddb_disc);
+                    pcddb_disc = nullptr;
+                }
+                else
+                {
+                    if (matches == 0)
+                    {
+                        AUDDBG ("no cddb info available for this disc\n");
+
+                        cddb_disc_destroy (pcddb_disc);
+                        pcddb_disc = nullptr;
+                    }
+                    else
+                    {
+                        AUDDBG ("CDDB disc category = \"%s\"\n",
+                               cddb_disc_get_category_str (pcddb_disc));
+
+                        cddb_read (pcddb_conn, pcddb_disc);
+                        if (cddb_errno (pcddb_conn) != CDDB_ERR_OK)
+                        {
+                            cdaudio_error (_("Failed to read the cddb info: %s"),
+                                           cddb_error_str (cddb_errno
+                                                           (pcddb_conn)));
+                            cddb_disc_destroy (pcddb_disc);
+                            pcddb_disc = nullptr;
+                        }
+                        else
+                        {
+                            trackinfo[0].performer = String (cddb_disc_get_artist (pcddb_disc));
+                            trackinfo[0].name = String (cddb_disc_get_title (pcddb_disc));
+                            trackinfo[0].genre = String (cddb_disc_get_genre (pcddb_disc));
+
+                            int trackno;
+                            for (trackno = firsttrackno; trackno <= lasttrackno;
+                                 trackno++)
+                            {
+                                cddb_track_t *pcddb_track =
+                                    cddb_disc_get_track (pcddb_disc,
+                                                         trackno - 1);
+
+                                trackinfo[trackno].performer = String (cddb_track_get_artist (pcddb_track));
+                                trackinfo[trackno].name = String (cddb_track_get_title (pcddb_track));
+                                trackinfo[trackno].genre = String (cddb_disc_get_genre (pcddb_disc));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (pcddb_disc != nullptr)
+            cddb_disc_destroy (pcddb_disc);
+
+        if (pcddb_conn != nullptr)
+            cddb_destroy (pcddb_conn);
+    }
+
+    return true;
+}
+
+/* mutex must be locked */
+static void refresh_trackinfo (bool warning)
+{
+    if (pcdrom_drive == nullptr)
+    {
+        open_cd ();
+        if (pcdrom_drive == nullptr)
+            return;
+    }
+
+    int mode = cdio_get_discmode (pcdrom_drive->p_cdio);
+#ifdef _WIN32 /* cdio_get_discmode reports the wrong disk type sometimes */
+    if (mode == CDIO_DISC_MODE_NO_INFO || mode == CDIO_DISC_MODE_ERROR)
+#else
+    if (mode != CDIO_DISC_MODE_CD_DA && mode != CDIO_DISC_MODE_CD_MIXED)
+#endif
+    {
+        if (warning)
+        {
+            if (mode == CDIO_DISC_MODE_NO_INFO)
+                cdaudio_error (_("Drive is empty."));
+            else
+                cdaudio_error (_("Unsupported disk type."));
+        }
+
+        reset_trackinfo ();
+        return;
+    }
+
+    if (! trackinfo.len () || cdio_get_media_changed (pcdrom_drive->p_cdio))
+    {
+        trackinfo.clear ();
+
+        if (scan_cd ())
+            trigger_monitor ();
+        else
+            reset_trackinfo ();
+    }
+}
+
+/* mutex must be locked */
+static void reset_trackinfo ()
+{
+    monitor_source.stop ();
+
+    if (pcdrom_drive != nullptr)
+    {
+        cdda_close (pcdrom_drive);
+        pcdrom_drive = nullptr;
+    }
+
+    trackinfo.clear ();
+}
+
+/* thread safe (mutex may be locked) */
+static int calculate_track_length (int startlsn, int endlsn)
+{
+    return ((endlsn - startlsn + 1) * 1000) / 75;
+}
+
+/* thread safe (mutex may be locked) */
+static int find_trackno_from_filename (const char * filename)
+{
+    int track;
+
+    if (strncmp (filename, "cdda://?", 8) || sscanf (filename + 8, "%d",
+                                                     &track) != 1)
+        return -1;
+
+    return track;
+}
diff --git a/src/compressor/Makefile b/src/compressor/Makefile
index 06786087b345..43787e0ef518 100644
--- a/src/compressor/Makefile
+++ b/src/compressor/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = compressor${PLUGIN_SUFFIX}
 
-SRCS = compressor.c plugin.c
+SRCS = compressor.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += -lm ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -lm
diff --git a/src/compressor/compressor.c b/src/compressor/compressor.c
deleted file mode 100644
index e9ac74bf27f6..000000000000
--- a/src/compressor/compressor.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Dynamic Range Compression Plugin for Audacious
- * Copyright 2010-2012 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 <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/misc.h>
-
-#include "compressor.h"
-
-/* Response time adjustments.  Maybe this should be adjustable.  Or maybe that
- * would just be confusing.  I don't know. */
-#define CHUNK_TIME 0.2 /* seconds */
-#define CHUNKS 5
-#define DECAY 0.3
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-static float * buffer, * output, * peaks;
-static int output_size;
-static int chunk_size, buffer_size;
-static int ring_at, buffer_filled, peaks_filled;
-static float current_peak;
-static int output_filled;
-static int current_channels, current_rate;
-
-static void buffer_append (float * * data, int * length)
-{
-    int offset = (chunk_size * ring_at + buffer_filled) % buffer_size;
-    int writable = MIN (* length, buffer_size - buffer_filled);
-
-    if (writable <= buffer_size - offset)
-        memcpy (buffer + offset, * data, sizeof (float) * writable);
-    else
-    {
-        int part = buffer_size - offset;
-
-        memcpy (buffer + offset, * data, part);
-        memcpy (buffer, (* data) + part, writable - part);
-    }
-
-    buffer_filled += writable;
-    * data += writable;
-    * length -= writable;
-}
-
-/* I used to find the maximum sample and take that as the peak, but that doesn't
- * work well on badly clipped tracks.  Now, I use the highly sophisticated
- * method of averaging the absolute value of the samples and multiplying by 6, a
- * number proved by experiment (on exactly three files) to best approximate the
- * actual peak. */
-
-static float calc_peak (float * data, int length)
-{
-    if (! length)
-        return 0;
-
-    float sum = 0;
-
-    float * end = data + length;
-    while (data < end)
-        sum += fabsf (* data ++);
-
-    return sum / length * 6;
-}
-
-static void do_ramp (float * data, int length, float peak_a, float peak_b)
-{
-    float center = aud_get_double ("compressor", "center");
-    float range = aud_get_double ("compressor", "range");
-    float a = powf (peak_a / center, range - 1);
-    float b = powf (peak_b / center, range - 1);
-
-    for (int count = 0; count < length; count ++)
-    {
-        * data = (* data) * (a * (length - count) + b * count) / length;
-        data ++;
-    }
-}
-
-static void output_append (float * data, int length)
-{
-    if (output_size < output_filled + length)
-    {
-        output_size = output_filled + length;
-        output = g_renew (float, output, output_size);
-    }
-
-    memcpy (output + output_filled, data, sizeof (float) * length);
-    output_filled += length;
-}
-
-static void reset (void)
-{
-    ring_at = 0;
-    buffer_filled = 0;
-    peaks_filled = 0;
-    current_peak = 0.0;
-}
-
-#define IN_RING(i) ((ring_at + i) % CHUNKS)
-#define GET_PEAK(i) peaks[IN_RING (i)]
-
-static inline float FMAX (float a, float b)
-{
-    return a > b ? a : b;
-}
-
-static void do_compress (float * * data, int * samples, char finish)
-{
-    float new_peak;
-
-    output_filled = 0;
-
-    while (1)
-    {
-        buffer_append (data, samples);
-
-        if (buffer_filled < buffer_size)
-            break;
-
-        for (; peaks_filled < CHUNKS; peaks_filled ++)
-            GET_PEAK (peaks_filled) = calc_peak (buffer + chunk_size * IN_RING
-             (peaks_filled), chunk_size);
-
-        if (current_peak == 0.0)
-            current_peak = FMAX (0.01, calc_peak (peaks, CHUNKS));
-
-        new_peak = FMAX (0.01, GET_PEAK (0));
-        new_peak = FMAX (new_peak, current_peak * (1.0 - DECAY));
-
-        for (int count = 1; count < CHUNKS; count ++)
-            new_peak = FMAX (new_peak, current_peak + (GET_PEAK (count) -
-             current_peak) / count);
-
-        do_ramp (buffer + chunk_size * ring_at, chunk_size, current_peak,
-         new_peak);
-
-        output_append (buffer + chunk_size * ring_at, chunk_size);
-
-        ring_at = IN_RING (1);
-        buffer_filled -= chunk_size;
-        peaks_filled --;
-        current_peak = new_peak;
-    }
-
-    if (finish)
-    {
-        int offset = chunk_size * ring_at;
-        int first = MIN (buffer_filled, buffer_size - offset);
-        int second = buffer_filled - first;
-
-        if (current_peak == 0.0)
-        {
-            current_peak = FMAX (0.01, calc_peak (buffer + offset, first));
-            current_peak = FMAX (current_peak, calc_peak (buffer, second));
-        }
-
-        do_ramp (buffer + offset, first, current_peak, current_peak);
-        do_ramp (buffer, second, current_peak, current_peak);
-
-        output_append (buffer + offset, first);
-        output_append (buffer, second);
-
-        reset ();
-    }
-
-    * data = output;
-    * samples = output_filled;
-}
-
-int compressor_init (void)
-{
-    compressor_config_load ();
-
-    buffer = NULL;
-    output = NULL;
-    output_size = 0;
-    peaks = NULL;
-
-    return 1;
-}
-
-void compressor_cleanup (void)
-{
-    g_free (buffer);
-    g_free (output);
-    g_free (peaks);
-}
-
-void compressor_start (int * channels, int * rate)
-{
-    chunk_size = (* channels) * (int) ((* rate) * CHUNK_TIME);
-    buffer_size = chunk_size * CHUNKS;
-    buffer = g_renew (float, buffer, buffer_size);
-    peaks = g_renew (float, peaks, CHUNKS);
-
-    current_channels = * channels;
-    current_rate = * rate;
-
-    reset ();
-}
-
-void compressor_process (float * * data, int * samples)
-{
-    do_compress (data, samples, 0);
-}
-
-void compressor_flush (void)
-{
-    reset ();
-}
-
-void compressor_finish (float * * data, int * samples)
-{
-    do_compress (data, samples, 1);
-}
-
-int compressor_adjust_delay (int delay)
-{
-    return delay + (int64_t) (buffer_filled / current_channels) * 1000 / current_rate;
-}
diff --git a/src/compressor/compressor.cc b/src/compressor/compressor.cc
new file mode 100644
index 000000000000..04a02c1d214e
--- /dev/null
+++ b/src/compressor/compressor.cc
@@ -0,0 +1,232 @@
+/*
+ * Dynamic Range Compression Plugin for Audacious
+ * Copyright 2010-2014 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 <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+/* Response time adjustments.  Maybe this should be adjustable? */
+#define CHUNK_TIME 0.2f /* seconds */
+#define CHUNKS 5
+#define DECAY 0.3f
+
+/* What is a "normal" volume?  Replay Gain stuff claims to use 89 dB, but what
+ * does that translate to in our PCM range? */
+static const char * const compressor_defaults[] = {
+    "center", "0.5",
+    "range", "0.5",
+     nullptr
+};
+
+static const PreferencesWidget compressor_widgets[] = {
+    WidgetLabel (N_("<b>Compression</b>")),
+    WidgetSpin (N_("Center volume:"),
+        WidgetFloat ("compressor", "center"),
+        {0.1, 1, 0.1}),
+    WidgetSpin (N_("Dynamic range:"),
+        WidgetFloat ("compressor", "range"),
+        {0.0, 3.0, 0.1})
+};
+
+static const PluginPreferences compressor_prefs = {{compressor_widgets}};
+
+static const char compressor_about[] =
+ N_("Dynamic Range Compression Plugin for Audacious\n"
+    "Copyright 2010-2014 John Lindgren");
+
+class Compressor : public EffectPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Dynamic Range Compressor"),
+        PACKAGE,
+        compressor_about,
+        & compressor_prefs
+    };
+
+    constexpr Compressor () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+    Index<float> & finish (Index<float> & data, bool end_of_playlist);
+    int adjust_delay (int delay);
+};
+
+EXPORT Compressor aud_plugin_instance;
+
+/* The read pointer of the ring buffer is kept aligned to the chunk size at all
+ * times.  To preserve the alignment, each read from the buffer must either (a)
+ * read a multiple of the chunk size or (b) empty the buffer completely.  Writes
+ * to the buffer need not be aligned to the chunk size. */
+
+static RingBuf<float> buffer, peaks;
+static Index<float> output;
+static int chunk_size;
+static float current_peak;
+static int current_channels, current_rate;
+
+/* I used to find the maximum sample and take that as the peak, but that doesn't
+ * work well on badly clipped tracks.  Now, I use the highly sophisticated
+ * method of averaging the absolute value of the samples and multiplying by 6, a
+ * number proved by experiment (on exactly three files) to best approximate the
+ * actual peak. */
+
+static float calc_peak (float * data, int length)
+{
+    float sum = 0;
+
+    float * end = data + length;
+    while (data < end)
+        sum += fabsf (* data ++);
+
+    return aud::max (0.01f, sum / length * 6);
+}
+
+static void do_ramp (float * data, int length, float peak_a, float peak_b)
+{
+    float center = aud_get_double ("compressor", "center");
+    float range = aud_get_double ("compressor", "range");
+    float a = powf (peak_a / center, range - 1);
+    float b = powf (peak_b / center, range - 1);
+
+    for (int count = 0; count < length; count ++)
+    {
+        * data = (* data) * (a * (length - count) + b * count) / length;
+        data ++;
+    }
+}
+
+bool Compressor::init ()
+{
+    aud_config_set_defaults ("compressor", compressor_defaults);
+    return true;
+}
+
+void Compressor::cleanup ()
+{
+    buffer.destroy ();
+    peaks.destroy ();
+    output.clear ();
+}
+
+void Compressor::start (int & channels, int & rate)
+{
+    current_channels = channels;
+    current_rate = rate;
+
+    chunk_size = channels * (int) (rate * CHUNK_TIME);
+
+    buffer.alloc (chunk_size * CHUNKS);
+    peaks.alloc (CHUNKS);
+
+    flush (true);
+}
+
+Index<float> & Compressor::process (Index<float> & data)
+{
+    output.resize (0);
+
+    int offset = 0;
+    int remain = data.len ();
+
+    while (1)
+    {
+        int writable = aud::min (remain, buffer.space ());
+
+        buffer.copy_in (& data[offset], writable);
+
+        offset += writable;
+        remain -= writable;
+
+        if (buffer.space ())
+            break;
+
+        while (peaks.len () < CHUNKS)
+            peaks.push (calc_peak (& buffer[chunk_size * peaks.len ()], chunk_size));
+
+        if (current_peak == 0.0f)
+        {
+            for (int i = 0; i < CHUNKS; i ++)
+                current_peak = aud::max (current_peak, peaks[i]);
+        }
+
+        float new_peak = aud::max (peaks[0], current_peak * (1.0f - DECAY));
+
+        for (int count = 1; count < CHUNKS; count ++)
+            new_peak = aud::max (new_peak, current_peak + (peaks[count] - current_peak) / count);
+
+        do_ramp (& buffer[0], chunk_size, current_peak, new_peak);
+
+        buffer.move_out (output, -1, chunk_size);
+
+        current_peak = new_peak;
+        peaks.pop ();
+    }
+
+    return output;
+}
+
+bool Compressor::flush (bool force)
+{
+    buffer.discard ();
+    peaks.discard ();
+
+    current_peak = 0.0f;
+    return true;
+}
+
+Index<float> & Compressor::finish (Index<float> & data, bool end_of_playlist)
+{
+    output.resize (0);
+
+    peaks.discard ();
+
+    while (buffer.len ())
+    {
+        int writable = buffer.linear ();
+
+        if (current_peak != 0.0f)
+            do_ramp (& buffer[0], writable, current_peak, current_peak);
+
+        buffer.move_out (output, -1, writable);
+    }
+
+    if (current_peak != 0.0f)
+        do_ramp (data.begin (), data.len (), current_peak, current_peak);
+
+    output.insert (data.begin (), -1, data.len ());
+
+    return output;
+}
+
+int Compressor::adjust_delay (int delay)
+{
+    return delay + aud::rescale<int64_t> (buffer.len () / current_channels, current_rate, 1000);
+}
diff --git a/src/compressor/compressor.h b/src/compressor/compressor.h
deleted file mode 100644
index 2676ef261f46..000000000000
--- a/src/compressor/compressor.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Dynamic Range Compression Plugin for Audacious
- * Copyright 2010 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.
- */
-
-void compressor_config_load (void);
-
-int compressor_init (void);
-void compressor_cleanup (void);
-void compressor_start (int * channels, int * rate);
-void compressor_process (float * * data, int * samples);
-void compressor_flush (void);
-void compressor_finish (float * * data, int * samples);
-int compressor_adjust_delay (int delay);
diff --git a/src/compressor/plugin.c b/src/compressor/plugin.c
deleted file mode 100644
index eabc77aef9cd..000000000000
--- a/src/compressor/plugin.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Dynamic Range Compression Plugin for Audacious
- * Copyright 2010-2012 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 <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#include "compressor.h"
-
-/* What is a "normal" volume?  Replay Gain stuff claims to use 89 dB, but what
- * does that translate to in our PCM range?  Does anybody even know? */
-static const char * const compressor_defaults[] = {
- "center", "0.5",
- "range", "0.5",
- NULL};
-
-static const PreferencesWidget compressor_widgets[] = {
- {WIDGET_LABEL, N_("<b>Compression</b>")},
- {WIDGET_SPIN_BTN, N_("Center volume:"),
-  .cfg_type = VALUE_FLOAT, .csect = "compressor", .cname = "center",
-  .data = {.spin_btn = {0.1, 1, 0.1}}},
- {WIDGET_SPIN_BTN, N_("Dynamic range:"),
-  .cfg_type = VALUE_FLOAT, .csect = "compressor", .cname = "range",
-  .data = {.spin_btn = {0.0, 3.0, 0.1}}}};
-
-static const PluginPreferences compressor_prefs = {
- .widgets = compressor_widgets,
- .n_widgets = ARRAY_LEN (compressor_widgets)};
-
-void compressor_config_load (void)
-{
-    aud_config_set_defaults ("compressor", compressor_defaults);
-}
-
-static const char compressor_about[] =
- N_("Dynamic Range Compression Plugin for Audacious\n"
-    "Copyright 2010-2012 John Lindgren");
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Dynamic Range Compressor"),
-    .domain = PACKAGE,
-    .about_text = compressor_about,
-    .prefs = & compressor_prefs,
-    .init = compressor_init,
-    .cleanup = compressor_cleanup,
-    .start = compressor_start,
-    .process = compressor_process,
-    .flush = compressor_flush,
-    .finish = compressor_finish,
-    .adjust_delay = compressor_adjust_delay,
-    .preserves_format = TRUE
-)
diff --git a/src/console/Audacious_Driver.cc b/src/console/Audacious_Driver.cc
new file mode 100644
index 000000000000..4d90bc781dc4
--- /dev/null
+++ b/src/console/Audacious_Driver.cc
@@ -0,0 +1,292 @@
+/*
+ * Audacious: Cross platform multimedia player
+ * Copyright (c) 2005-2009 Audacious Team
+ *
+ * Driver for Game_Music_Emu library. See details at:
+ * http://www.slack.net/~ant/libs/
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+
+#include "configure.h"
+#include "plugin.h"
+#include "Music_Emu.h"
+#include "Gzip_Reader.h"
+
+static const int fade_threshold = 10 * 1000;
+static const int fade_length    = 8 * 1000;
+
+static bool log_err(blargg_err_t err)
+{
+    if (err)
+        AUDERR("%s\n", err);
+    return !!err;
+}
+
+static void log_warning(Music_Emu * emu)
+{
+    const char *str = emu->warning();
+    if (str)
+        AUDWARN("%s\n", str);
+}
+
+/* Handles URL parsing, file opening and identification, and file
+ * loading. Keeps file header around when loading rest of file to
+ * avoid seeking and re-reading.
+ */
+class ConsoleFileHandler {
+public:
+    String m_path;            // path without track number specification
+    int m_track;             // track number (0 = first track)
+    Music_Emu* m_emu;         // set to 0 to take ownership
+    gme_type_t m_type;
+
+    // Parses path and identifies file type
+    ConsoleFileHandler(const char* path, VFSFile &fd);
+
+    // Creates emulator and returns 0. If this wasn't a music file or
+    // emulator couldn't be created, returns 1.
+    int load(int sample_rate);
+
+    // Deletes owned emu and closes file
+    ~ConsoleFileHandler();
+
+private:
+    char m_header[4];
+    Vfs_File_Reader vfs_in;
+    Gzip_Reader gzip_in;
+};
+
+ConsoleFileHandler::ConsoleFileHandler(const char *path, VFSFile &fd)
+{
+    m_emu   = nullptr;
+    m_type  = 0;
+    m_track = -1;
+
+    const char * sub;
+    uri_parse (path, nullptr, nullptr, & sub, & m_track);
+    m_path = String (str_copy (path, sub - path));
+
+    m_track -= 1;
+
+    // open vfs
+    vfs_in.reset(fd);
+
+    // now open gzip_reader on top of vfs
+    if (log_err(gzip_in.open(&vfs_in)))
+        return;
+
+    // read and identify header
+    if (!log_err(gzip_in.read(m_header, sizeof(m_header))))
+    {
+        m_type = gme_identify_extension(gme_identify_header(m_header));
+        if (!m_type)
+        {
+            m_type = gme_identify_extension(m_path);
+            if (m_type != gme_gym_type) // only trust file extension for headerless .gym files
+                m_type = 0;
+        }
+    }
+}
+
+ConsoleFileHandler::~ConsoleFileHandler()
+{
+    gme_delete(m_emu);
+}
+
+int ConsoleFileHandler::load(int sample_rate)
+{
+    if (!m_type)
+        return 1;
+
+    m_emu = gme_new_emu(m_type, sample_rate);
+    if (m_emu == nullptr)
+    {
+        log_err("Out of memory allocating emulator engine. Fatal error.");
+        return 1;
+    }
+
+    // combine header with remaining file data
+    Remaining_Reader reader(m_header, sizeof(m_header), &gzip_in);
+    if (log_err(m_emu->load(reader)))
+        return 1;
+
+    // files can be closed now
+    gzip_in.close();
+    vfs_in.close();
+
+    log_warning(m_emu);
+
+#if 0
+    // load .m3u from same directory( replace/add extension with ".m3u")
+    char *m3u_path = g_strdup(m_path);
+    char *ext = strrchr(m3u_path, '.');
+    if (ext == nullptr)
+    {
+        ext = g_strdup_printf("%s.m3u", m3u_path);
+        g_free(m3u_path);
+        m3u_path = ext;
+    }
+
+    Vfs_File_Reader m3u;
+    if (!m3u.open(m3u_path))
+    {
+        if (log_err(m_emu->load_m3u(m3u))) // TODO: fail if m3u can't be loaded?
+            log_warning(m_emu); // this will log line number of first problem in m3u
+    }
+#endif
+
+    return 0;
+}
+
+static Tuple get_track_ti(const char *path, const track_info_t *info, const int track)
+{
+    Tuple tuple;
+    tuple.set_filename (path);
+
+    tuple.set_str (Tuple::Artist, info->author);
+    tuple.set_str (Tuple::Album, info->game);
+    tuple.set_str (Tuple::Title, info->song);
+    tuple.set_str (Tuple::Copyright, info->copyright);
+    tuple.set_str (Tuple::Codec, info->system);
+    tuple.set_str (Tuple::Comment, info->comment);
+
+    if (track >= 0)
+    {
+        tuple.set_int (Tuple::Track, track + 1);
+        tuple.set_int (Tuple::Subtune, track + 1);
+        tuple.set_int (Tuple::NumSubtunes, info->track_count);
+    }
+    else
+        tuple.set_subtunes (info->track_count, nullptr);
+
+    int length = info->length;
+    if (length <= 0)
+        length = info->intro_length + 2 * info->loop_length;
+    if (length <= 0)
+        length = audcfg.loop_length * 1000;
+    else if (length >= fade_threshold)
+        length += fade_length;
+    tuple.set_int (Tuple::Length, length);
+
+    return tuple;
+}
+
+Tuple ConsolePlugin::read_tuple(const char *filename, VFSFile &file)
+{
+    ConsoleFileHandler fh(filename, file);
+
+    if (!fh.m_type)
+        return Tuple ();
+
+    if (!fh.load(gme_info_only))
+    {
+        track_info_t info;
+        if (!log_err(fh.m_emu->track_info(&info, fh.m_track < 0 ? 0 : fh.m_track)))
+            return get_track_ti(fh.m_path, &info, fh.m_track);
+    }
+
+    return Tuple ();
+}
+
+bool ConsolePlugin::play(const char *filename, VFSFile &file)
+{
+    int length, sample_rate;
+    track_info_t info;
+
+    // identify file
+    ConsoleFileHandler fh(filename, file);
+    if (!fh.m_type)
+        return false;
+
+    if (fh.m_track < 0)
+        fh.m_track = 0;
+
+    // select sample rate
+    sample_rate = 0;
+    if (fh.m_type == gme_spc_type)
+        sample_rate = 32000;
+    if (audcfg.resample)
+        sample_rate = audcfg.resample_rate;
+    if (sample_rate == 0)
+        sample_rate = 44100;
+
+    // create emulator and load file
+    if (fh.load(sample_rate))
+        return false;
+
+    // stereo echo depth
+    gme_set_stereo_depth(fh.m_emu, 1.0 / 100 * audcfg.echo);
+
+    // set equalizer
+    if (audcfg.treble || audcfg.bass)
+    {
+        Music_Emu::equalizer_t eq;
+
+        // bass - logarithmic, 2 to 8194 Hz
+        double bass = 1.0 - (audcfg.bass / 200.0 + 0.5);
+        eq.bass = (long) (2.0 + pow( 2.0, bass * 13 ));
+
+        // treble - -50 to 0 to +5 dB
+        double treble = audcfg.treble / 100.0;
+        eq.treble = treble * (treble < 0 ? 50.0 : 5.0);
+
+        fh.m_emu->set_equalizer(eq);
+    }
+
+    // get info
+    length = -1;
+    if (!log_err(fh.m_emu->track_info(&info, fh.m_track)))
+    {
+        if (fh.m_type == gme_spc_type && audcfg.ignore_spc_length)
+            info.length = -1;
+
+        Tuple tuple = get_track_ti(fh.m_path, &info, fh.m_track);
+        if (tuple)
+        {
+            length = tuple.get_int (Tuple::Length);
+            set_stream_bitrate(fh.m_emu->voice_count() * 1000);
+        }
+    }
+
+    // start track
+    if (log_err(fh.m_emu->start_track(fh.m_track)))
+        return false;
+
+    log_warning(fh.m_emu);
+
+    open_audio(FMT_S16_NE, sample_rate, 2);
+
+    // set fade time
+    if (length <= 0)
+        length = audcfg.loop_length * 1000;
+    if (length >= fade_threshold + fade_length)
+        length -= fade_length / 2;
+    fh.m_emu->set_fade(length, fade_length);
+
+    while (!check_stop())
+    {
+        /* Perform seek, if requested */
+        int seek_value = check_seek();
+        if (seek_value >= 0)
+            fh.m_emu->seek(seek_value);
+
+        /* Fill and play buffer of audio */
+        int const buf_size = 1024;
+        Music_Emu::sample_t buf[buf_size];
+
+        fh.m_emu->play(buf_size, buf);
+
+        write_audio(buf, sizeof(buf));
+
+        if (fh.m_emu->track_ended())
+            break;
+    }
+
+    return true;
+}
diff --git a/src/console/Audacious_Driver.cxx b/src/console/Audacious_Driver.cxx
deleted file mode 100644
index b0c27b562697..000000000000
--- a/src/console/Audacious_Driver.cxx
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Audacious: Cross platform multimedia player
- * Copyright (c) 2005-2009 Audacious Team
- *
- * Driver for Game_Music_Emu library. See details at:
- * http://www.slack.net/~ant/libs/
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-
-extern "C" {
-#include <libaudcore/audstrings.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-}
-
-#include "configure.h"
-#include "Music_Emu.h"
-#include "Gzip_Reader.h"
-
-static const int fade_threshold = 10 * 1000;
-static const int fade_length    = 8 * 1000;
-
-static blargg_err_t log_err(blargg_err_t err)
-{
-    if (err)
-        fprintf (stderr, "console: %s\n", err);
-    return err;
-}
-
-static void log_warning(Music_Emu * emu)
-{
-    const char *str = emu->warning();
-    if (str != NULL)
-        fprintf (stderr, "console: %s\n", str);
-}
-
-/* Handles URL parsing, file opening and identification, and file
- * loading. Keeps file header around when loading rest of file to
- * avoid seeking and re-reading.
- */
-class ConsoleFileHandler {
-public:
-    char *m_path;            // path without track number specification
-    int m_track;             // track number (0 = first track)
-    Music_Emu* m_emu;         // set to 0 to take ownership
-    gme_type_t m_type;
-
-    // Parses path and identifies file type
-    ConsoleFileHandler(const char* path, VFSFile *fd = NULL);
-
-    // Creates emulator and returns 0. If this wasn't a music file or
-    // emulator couldn't be created, returns 1.
-    int load(int sample_rate);
-
-    // Deletes owned emu and closes file
-    ~ConsoleFileHandler();
-
-private:
-    char m_header[4];
-    Vfs_File_Reader vfs_in;
-    Gzip_Reader gzip_in;
-};
-
-ConsoleFileHandler::ConsoleFileHandler(const char *path, VFSFile *fd)
-{
-    m_emu   = NULL;
-    m_type  = 0;
-    m_track = -1;
-
-    const char * sub;
-    uri_parse (path, NULL, NULL, & sub, & m_track);
-    m_path = str_nget (path, sub - path);
-
-    m_track -= 1;
-
-    // open vfs
-    if (fd != NULL)
-        vfs_in.reset(fd);
-    else if (log_err(vfs_in.open(m_path)))
-        return;
-
-    // now open gzip_reader on top of vfs
-    if (log_err(gzip_in.open(&vfs_in)))
-        return;
-
-    // read and identify header
-    if (!log_err(gzip_in.read(m_header, sizeof(m_header))))
-    {
-        m_type = gme_identify_extension(gme_identify_header(m_header));
-        if (!m_type)
-        {
-            m_type = gme_identify_extension(m_path);
-            if (m_type != gme_gym_type) // only trust file extension for headerless .gym files
-                m_type = 0;
-        }
-    }
-}
-
-ConsoleFileHandler::~ConsoleFileHandler()
-{
-    gme_delete(m_emu);
-    str_unref (m_path);
-}
-
-int ConsoleFileHandler::load(int sample_rate)
-{
-    if (!m_type)
-        return 1;
-
-    m_emu = gme_new_emu(m_type, sample_rate);
-    if (m_emu == NULL)
-    {
-        log_err("Out of memory allocating emulator engine. Fatal error.");
-        return 1;
-    }
-
-    // combine header with remaining file data
-    Remaining_Reader reader(m_header, sizeof(m_header), &gzip_in);
-    if (log_err(m_emu->load(reader)))
-        return 1;
-
-    // files can be closed now
-    gzip_in.close();
-    vfs_in.close();
-
-    log_warning(m_emu);
-
-#if 0
-    // load .m3u from same directory( replace/add extension with ".m3u")
-    char *m3u_path = g_strdup(m_path);
-    char *ext = strrchr(m3u_path, '.');
-    if (ext == NULL)
-    {
-        ext = g_strdup_printf("%s.m3u", m3u_path);
-        g_free(m3u_path);
-        m3u_path = ext;
-    }
-
-    Vfs_File_Reader m3u;
-    if (!m3u.open(m3u_path))
-    {
-        if (log_err(m_emu->load_m3u(m3u))) // TODO: fail if m3u can't be loaded?
-            log_warning(m_emu); // this will log line number of first problem in m3u
-    }
-#endif
-
-    return 0;
-}
-
-static Tuple * get_track_ti(const char *path, const track_info_t *info, const int track)
-{
-    Tuple *ti = tuple_new_from_filename(path);
-
-    if (ti != NULL)
-    {
-        tuple_set_str (ti, FIELD_ARTIST, info->author);
-        tuple_set_str (ti, FIELD_ALBUM, info->game);
-        tuple_set_str (ti, FIELD_TITLE, info->song);
-        tuple_set_str (ti, FIELD_COPYRIGHT, info->copyright);
-        tuple_set_str (ti, FIELD_CODEC, info->system);
-        tuple_set_str (ti, FIELD_COMMENT, info->comment);
-
-        if (track >= 0)
-        {
-            tuple_set_int(ti, FIELD_TRACK_NUMBER, track + 1);
-            tuple_set_int(ti, FIELD_SUBSONG_ID, track + 1);
-            tuple_set_int(ti, FIELD_SUBSONG_NUM, info->track_count);
-        }
-        else
-            tuple_set_subtunes (ti, info->track_count, NULL);
-
-        int length = info->length;
-        if (length <= 0)
-            length = info->intro_length + 2 * info->loop_length;
-        if (length <= 0)
-            length = audcfg.loop_length * 1000;
-        else if (length >= fade_threshold)
-            length += fade_length;
-        tuple_set_int(ti, FIELD_LENGTH, length);
-    }
-
-    return ti;
-}
-
-extern "C" Tuple * console_probe_for_tuple(const char *filename, VFSFile *fd)
-{
-    ConsoleFileHandler fh(filename, fd);
-
-    if (!fh.m_type)
-        return NULL;
-
-    if (!fh.load(gme_info_only))
-    {
-        track_info_t info;
-        if (!log_err(fh.m_emu->track_info(&info, fh.m_track < 0 ? 0 : fh.m_track)))
-            return get_track_ti(fh.m_path, &info, fh.m_track);
-    }
-
-    return NULL;
-}
-
-extern "C" bool_t console_play(const char *filename, VFSFile *file)
-{
-    int length, sample_rate;
-    track_info_t info;
-
-    // identify file
-    ConsoleFileHandler fh(filename);
-    if (!fh.m_type)
-        return FALSE;
-
-    if (fh.m_track < 0)
-        fh.m_track = 0;
-
-    // select sample rate
-    sample_rate = 0;
-    if (fh.m_type == gme_spc_type)
-        sample_rate = 32000;
-    if (audcfg.resample)
-        sample_rate = audcfg.resample_rate;
-    if (sample_rate == 0)
-        sample_rate = 44100;
-
-    // create emulator and load file
-    if (fh.load(sample_rate))
-        return FALSE;
-
-    // stereo echo depth
-    gme_set_stereo_depth(fh.m_emu, 1.0 / 100 * audcfg.echo);
-
-    // set equalizer
-    if (audcfg.treble || audcfg.bass)
-    {
-        Music_Emu::equalizer_t eq;
-
-        // bass - logarithmic, 2 to 8194 Hz
-        double bass = 1.0 - (audcfg.bass / 200.0 + 0.5);
-        eq.bass = (long) (2.0 + pow( 2.0, bass * 13 ));
-
-        // treble - -50 to 0 to +5 dB
-        double treble = audcfg.treble / 100.0;
-        eq.treble = treble * (treble < 0 ? 50.0 : 5.0);
-
-        fh.m_emu->set_equalizer(eq);
-    }
-
-    // get info
-    length = -1;
-    if (!log_err(fh.m_emu->track_info(&info, fh.m_track)))
-    {
-        if (fh.m_type == gme_spc_type && audcfg.ignore_spc_length)
-            info.length = -1;
-
-        Tuple *ti = get_track_ti(fh.m_path, &info, fh.m_track);
-        if (ti != NULL)
-        {
-            length = tuple_get_int(ti, FIELD_LENGTH);
-            tuple_unref(ti);
-            aud_input_set_bitrate(fh.m_emu->voice_count() * 1000);
-        }
-    }
-
-    // start track
-    if (log_err(fh.m_emu->start_track(fh.m_track)))
-        return FALSE;
-
-    log_warning(fh.m_emu);
-
-    if (!aud_input_open_audio(FMT_S16_NE, sample_rate, 2))
-        return FALSE;
-
-    // set fade time
-    if (length <= 0)
-        length = audcfg.loop_length * 1000;
-    if (length >= fade_threshold + fade_length)
-        length -= fade_length / 2;
-    fh.m_emu->set_fade(length, fade_length);
-
-    while (!aud_input_check_stop())
-    {
-        /* Perform seek, if requested */
-        int seek_value = aud_input_check_seek();
-        if (seek_value >= 0)
-            fh.m_emu->seek(seek_value);
-
-        /* Fill and play buffer of audio */
-        int const buf_size = 1024;
-        Music_Emu::sample_t buf[buf_size];
-
-        fh.m_emu->play(buf_size, buf);
-
-        aud_input_write_audio(buf, sizeof(buf));
-
-        if (fh.m_emu->track_ended())
-            break;
-    }
-
-    return TRUE;
-}
diff --git a/src/console/Ay_Apu.cc b/src/console/Ay_Apu.cc
new file mode 100644
index 000000000000..107d058334bc
--- /dev/null
+++ b/src/console/Ay_Apu.cc
@@ -0,0 +1,395 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Ay_Apu.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Emulation inaccuracies:
+// * Noise isn't run when not in use
+// * Changes to envelope and noise periods are delayed until next reload
+// * Super-sonic tone should attenuate output to about 60%, not 50%
+
+// Tones above this frequency are treated as disabled tone at half volume.
+// Power of two is more efficient (avoids division).
+unsigned const inaudible_freq = 16384;
+
+int const period_factor = 16;
+
+static byte const amp_table [16] =
+{
+#define ENTRY( n ) byte (n * Ay_Apu::amp_range + 0.5)
+	// With channels tied together and 1K resistor to ground (as datasheet recommends),
+	// output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
+	ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
+	ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
+	ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
+	ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
+
+	/*
+	// Measured from an AY-3-8910A chip with date code 8611.
+
+	// Direct voltages without any load (very linear)
+	ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
+	ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
+	ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
+	ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
+	// With only some load
+	ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
+	ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
+	ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
+	ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
+	*/
+#undef ENTRY
+};
+
+static byte const modes [8] =
+{
+#define MODE( a0,a1, b0,b1, c0,c1 ) \
+		(a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
+	MODE( 1,0, 1,0, 1,0 ),
+	MODE( 1,0, 0,0, 0,0 ),
+	MODE( 1,0, 0,1, 1,0 ),
+	MODE( 1,0, 1,1, 1,1 ),
+	MODE( 0,1, 0,1, 0,1 ),
+	MODE( 0,1, 1,1, 1,1 ),
+	MODE( 0,1, 1,0, 0,1 ),
+	MODE( 0,1, 0,0, 0,0 ),
+};
+
+Ay_Apu::Ay_Apu()
+{
+	// build full table of the upper 8 envelope waveforms
+	for ( int m = 8; m--; )
+	{
+		byte* out = env.modes [m];
+		int flags = modes [m];
+		for ( int x = 3; --x >= 0; )
+		{
+			int amp = flags & 1;
+			int end = flags >> 1 & 1;
+			int step = end - amp;
+			amp *= 15;
+			for ( int y = 16; --y >= 0; )
+			{
+				*out++ = amp_table [amp];
+				amp += step;
+			}
+			flags >>= 2;
+		}
+	}
+
+	output( 0 );
+	volume( 1.0 );
+	reset();
+}
+
+void Ay_Apu::reset()
+{
+	last_time   = 0;
+	noise.delay = 0;
+	noise.lfsr  = 1;
+
+	osc_t* osc = &oscs [osc_count];
+	do
+	{
+		osc--;
+		osc->period   = period_factor;
+		osc->delay    = 0;
+		osc->last_amp = 0;
+		osc->phase    = 0;
+	}
+	while ( osc != oscs );
+
+	for ( int i = sizeof regs; --i >= 0; )
+		regs [i] = 0;
+	regs [7] = 0xFF;
+	write_data_( 13, 0 );
+}
+
+void Ay_Apu::write_data_( int addr, int data )
+{
+	assert( (unsigned) addr < reg_count );
+
+	if ( (unsigned) addr >= 14 )
+	{
+		#ifdef debug_printf
+			debug_printf( "Wrote to I/O port %02X\n", (int) addr );
+		#endif
+	}
+
+	// envelope mode
+	if ( addr == 13 )
+	{
+		if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
+			data = (data & 4) ? 15 : 9;
+		env.wave = env.modes [data - 7];
+		env.pos = -48;
+		env.delay = 0; // will get set to envelope period in run_until()
+	}
+	regs [addr] = data;
+
+	// handle period changes accurately
+	int i = addr >> 1;
+	if ( i < osc_count )
+	{
+		blip_time_t period = (regs [i * 2 + 1] & 0x0F) * (0x100L * period_factor) +
+				regs [i * 2] * period_factor;
+		if ( !period )
+			period = period_factor;
+
+		// adjust time of next timer expiration based on change in period
+		osc_t& osc = oscs [i];
+		if ( (osc.delay += period - osc.period) < 0 )
+			osc.delay = 0;
+		osc.period = period;
+	}
+
+	// TODO: same as above for envelope timer, and it also has a divide by two after it
+}
+
+int const noise_off = 0x08;
+int const tone_off  = 0x01;
+
+void Ay_Apu::run_until( blip_time_t final_end_time )
+{
+	require( final_end_time >= last_time );
+
+	// noise period and initial values
+	blip_time_t const noise_period_factor = period_factor * 2; // verified
+	blip_time_t noise_period = (regs [6] & 0x1F) * noise_period_factor;
+	if ( !noise_period )
+		noise_period = noise_period_factor;
+	blip_time_t const old_noise_delay = noise.delay;
+	blargg_ulong const old_noise_lfsr = noise.lfsr;
+
+	// envelope period
+	blip_time_t const env_period_factor = period_factor * 2; // verified
+	blip_time_t env_period = (regs [12] * 0x100L + regs [11]) * env_period_factor;
+	if ( !env_period )
+		env_period = env_period_factor; // same as period 1 on my AY chip
+	if ( !env.delay )
+		env.delay = env_period;
+
+	// run each osc separately
+	for ( int index = 0; index < osc_count; index++ )
+	{
+		osc_t* const osc = &oscs [index];
+		int osc_mode = regs [7] >> index;
+
+		// output
+		Blip_Buffer* const osc_output = osc->output;
+		if ( !osc_output )
+			continue;
+		osc_output->set_modified();
+
+		// period
+		int half_vol = 0;
+		blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() +
+				inaudible_freq) / (inaudible_freq * 2);
+		if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
+		{
+			half_vol = 1; // Actually around 60%, but 50% is close enough
+			osc_mode |= tone_off;
+		}
+
+		// envelope
+		blip_time_t start_time = last_time;
+		blip_time_t end_time   = final_end_time;
+		int const vol_mode = regs [0x08 + index];
+		int volume = amp_table [vol_mode & 0x0F] >> half_vol;
+		int osc_env_pos = env.pos;
+		if ( vol_mode & 0x10 )
+		{
+			volume = env.wave [osc_env_pos] >> half_vol;
+			// use envelope only if it's a repeating wave or a ramp that hasn't finished
+			if ( !(regs [13] & 1) || osc_env_pos < -32 )
+			{
+				end_time = start_time + env.delay;
+				if ( end_time >= final_end_time )
+					end_time = final_end_time;
+
+				//if ( !(regs [12] | regs [11]) )
+				//  debug_printf( "Used envelope period 0\n" );
+			}
+			else if ( !volume )
+			{
+				osc_mode = noise_off | tone_off;
+			}
+		}
+		else if ( !volume )
+		{
+			osc_mode = noise_off | tone_off;
+		}
+
+		// tone time
+		blip_time_t const period = osc->period;
+		blip_time_t time = start_time + osc->delay;
+		if ( osc_mode & tone_off ) // maintain tone's phase when off
+		{
+			blargg_long count = (final_end_time - time + period - 1) / period;
+			time += count * period;
+			osc->phase ^= count & 1;
+		}
+
+		// noise time
+		blip_time_t ntime = final_end_time;
+		blargg_ulong noise_lfsr = 1;
+		if ( !(osc_mode & noise_off) )
+		{
+			ntime = start_time + old_noise_delay;
+			noise_lfsr = old_noise_lfsr;
+			//if ( (regs [6] & 0x1F) == 0 )
+			//  debug_printf( "Used noise period 0\n" );
+		}
+
+		// The following efficiently handles several cases (least demanding first):
+		// * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
+		// * Just tone or just noise, envelope disabled
+		// * Envelope controlling tone and/or noise
+		// * Tone and noise disabled, envelope enabled with high frequency
+		// * Tone and noise together
+		// * Tone and noise together with envelope
+
+		// This loop only runs one iteration if envelope is disabled. If envelope
+		// is being used as a waveform (tone and noise disabled), this loop will
+		// still be reasonably efficient since the bulk of it will be skipped.
+		while ( 1 )
+		{
+			// current amplitude
+			int amp = 0;
+			if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
+				amp = volume;
+			{
+				int delta = amp - osc->last_amp;
+				if ( delta )
+				{
+					osc->last_amp = amp;
+					synth_.offset( start_time, delta, osc_output );
+				}
+			}
+
+			// Run wave and noise interleved with each catching up to the other.
+			// If one or both are disabled, their "current time" will be past end time,
+			// so there will be no significant performance hit.
+			if ( ntime < end_time || time < end_time )
+			{
+				// Since amplitude was updated above, delta will always be +/- volume,
+				// so we can avoid using last_amp every time to calculate the delta.
+				int delta = amp * 2 - volume;
+				int delta_non_zero = delta != 0;
+				int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
+				do
+				{
+					// run noise
+					blip_time_t end = end_time;
+					if ( end_time > time ) end = time;
+					if ( phase & delta_non_zero )
+					{
+						while ( ntime <= end ) // must advance *past* time to avoid hang
+						{
+							int changed = noise_lfsr + 1;
+							noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
+							if ( changed & 2 )
+							{
+								delta = -delta;
+								synth_.offset( ntime, delta, osc_output );
+							}
+							ntime += noise_period;
+						}
+					}
+					else
+					{
+						// 20 or more noise periods on average for some music
+						blargg_long remain = end - ntime;
+						blargg_long count = remain / noise_period;
+						if ( remain >= 0 )
+							ntime += noise_period + count * noise_period;
+					}
+
+					// run tone
+					end = end_time;
+					if ( end_time > ntime ) end = ntime;
+					if ( noise_lfsr & delta_non_zero )
+					{
+						while ( time < end )
+						{
+							delta = -delta;
+							synth_.offset( time, delta, osc_output );
+							time += period;
+							//phase ^= 1;
+						}
+						//assert( phase == (delta > 0) );
+						phase = unsigned (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
+						// (delta > 0)
+					}
+					else
+					{
+						// loop usually runs less than once
+						//SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
+
+						while ( time < end )
+						{
+							time += period;
+							phase ^= 1;
+						}
+					}
+				}
+				while ( time < end_time || ntime < end_time );
+
+				osc->last_amp = (delta + volume) >> 1;
+				if ( !(osc_mode & tone_off) )
+					osc->phase = phase;
+			}
+
+			if ( end_time >= final_end_time )
+				break; // breaks first time when envelope is disabled
+
+			// next envelope step
+			if ( ++osc_env_pos >= 0 )
+				osc_env_pos -= 32;
+			volume = env.wave [osc_env_pos] >> half_vol;
+
+			start_time = end_time;
+			end_time += env_period;
+			if ( end_time > final_end_time )
+				end_time = final_end_time;
+		}
+		osc->delay = time - final_end_time;
+
+		if ( !(osc_mode & noise_off) )
+		{
+			noise.delay = ntime - final_end_time;
+			noise.lfsr = noise_lfsr;
+		}
+	}
+
+	// TODO: optimized saw wave envelope?
+
+	// maintain envelope phase
+	blip_time_t remain = final_end_time - last_time - env.delay;
+	if ( remain >= 0 )
+	{
+		blargg_long count = (remain + env_period) / env_period;
+		env.pos += count;
+		if ( env.pos >= 0 )
+			env.pos = (env.pos & 31) - 32;
+		remain -= count * env_period;
+		assert( -remain <= env_period );
+	}
+	env.delay = -remain;
+	assert( env.delay > 0 );
+	assert( env.pos < 0 );
+
+	last_time = final_end_time;
+}
diff --git a/src/console/Ay_Apu.cxx b/src/console/Ay_Apu.cxx
deleted file mode 100644
index 107d058334bc..000000000000
--- a/src/console/Ay_Apu.cxx
+++ /dev/null
@@ -1,395 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Ay_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Emulation inaccuracies:
-// * Noise isn't run when not in use
-// * Changes to envelope and noise periods are delayed until next reload
-// * Super-sonic tone should attenuate output to about 60%, not 50%
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const period_factor = 16;
-
-static byte const amp_table [16] =
-{
-#define ENTRY( n ) byte (n * Ay_Apu::amp_range + 0.5)
-	// With channels tied together and 1K resistor to ground (as datasheet recommends),
-	// output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
-	ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
-	ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
-	ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
-	ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
-
-	/*
-	// Measured from an AY-3-8910A chip with date code 8611.
-
-	// Direct voltages without any load (very linear)
-	ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
-	ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
-	ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
-	ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
-	// With only some load
-	ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
-	ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
-	ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
-	ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
-	*/
-#undef ENTRY
-};
-
-static byte const modes [8] =
-{
-#define MODE( a0,a1, b0,b1, c0,c1 ) \
-		(a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
-	MODE( 1,0, 1,0, 1,0 ),
-	MODE( 1,0, 0,0, 0,0 ),
-	MODE( 1,0, 0,1, 1,0 ),
-	MODE( 1,0, 1,1, 1,1 ),
-	MODE( 0,1, 0,1, 0,1 ),
-	MODE( 0,1, 1,1, 1,1 ),
-	MODE( 0,1, 1,0, 0,1 ),
-	MODE( 0,1, 0,0, 0,0 ),
-};
-
-Ay_Apu::Ay_Apu()
-{
-	// build full table of the upper 8 envelope waveforms
-	for ( int m = 8; m--; )
-	{
-		byte* out = env.modes [m];
-		int flags = modes [m];
-		for ( int x = 3; --x >= 0; )
-		{
-			int amp = flags & 1;
-			int end = flags >> 1 & 1;
-			int step = end - amp;
-			amp *= 15;
-			for ( int y = 16; --y >= 0; )
-			{
-				*out++ = amp_table [amp];
-				amp += step;
-			}
-			flags >>= 2;
-		}
-	}
-
-	output( 0 );
-	volume( 1.0 );
-	reset();
-}
-
-void Ay_Apu::reset()
-{
-	last_time   = 0;
-	noise.delay = 0;
-	noise.lfsr  = 1;
-
-	osc_t* osc = &oscs [osc_count];
-	do
-	{
-		osc--;
-		osc->period   = period_factor;
-		osc->delay    = 0;
-		osc->last_amp = 0;
-		osc->phase    = 0;
-	}
-	while ( osc != oscs );
-
-	for ( int i = sizeof regs; --i >= 0; )
-		regs [i] = 0;
-	regs [7] = 0xFF;
-	write_data_( 13, 0 );
-}
-
-void Ay_Apu::write_data_( int addr, int data )
-{
-	assert( (unsigned) addr < reg_count );
-
-	if ( (unsigned) addr >= 14 )
-	{
-		#ifdef debug_printf
-			debug_printf( "Wrote to I/O port %02X\n", (int) addr );
-		#endif
-	}
-
-	// envelope mode
-	if ( addr == 13 )
-	{
-		if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
-			data = (data & 4) ? 15 : 9;
-		env.wave = env.modes [data - 7];
-		env.pos = -48;
-		env.delay = 0; // will get set to envelope period in run_until()
-	}
-	regs [addr] = data;
-
-	// handle period changes accurately
-	int i = addr >> 1;
-	if ( i < osc_count )
-	{
-		blip_time_t period = (regs [i * 2 + 1] & 0x0F) * (0x100L * period_factor) +
-				regs [i * 2] * period_factor;
-		if ( !period )
-			period = period_factor;
-
-		// adjust time of next timer expiration based on change in period
-		osc_t& osc = oscs [i];
-		if ( (osc.delay += period - osc.period) < 0 )
-			osc.delay = 0;
-		osc.period = period;
-	}
-
-	// TODO: same as above for envelope timer, and it also has a divide by two after it
-}
-
-int const noise_off = 0x08;
-int const tone_off  = 0x01;
-
-void Ay_Apu::run_until( blip_time_t final_end_time )
-{
-	require( final_end_time >= last_time );
-
-	// noise period and initial values
-	blip_time_t const noise_period_factor = period_factor * 2; // verified
-	blip_time_t noise_period = (regs [6] & 0x1F) * noise_period_factor;
-	if ( !noise_period )
-		noise_period = noise_period_factor;
-	blip_time_t const old_noise_delay = noise.delay;
-	blargg_ulong const old_noise_lfsr = noise.lfsr;
-
-	// envelope period
-	blip_time_t const env_period_factor = period_factor * 2; // verified
-	blip_time_t env_period = (regs [12] * 0x100L + regs [11]) * env_period_factor;
-	if ( !env_period )
-		env_period = env_period_factor; // same as period 1 on my AY chip
-	if ( !env.delay )
-		env.delay = env_period;
-
-	// run each osc separately
-	for ( int index = 0; index < osc_count; index++ )
-	{
-		osc_t* const osc = &oscs [index];
-		int osc_mode = regs [7] >> index;
-
-		// output
-		Blip_Buffer* const osc_output = osc->output;
-		if ( !osc_output )
-			continue;
-		osc_output->set_modified();
-
-		// period
-		int half_vol = 0;
-		blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() +
-				inaudible_freq) / (inaudible_freq * 2);
-		if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
-		{
-			half_vol = 1; // Actually around 60%, but 50% is close enough
-			osc_mode |= tone_off;
-		}
-
-		// envelope
-		blip_time_t start_time = last_time;
-		blip_time_t end_time   = final_end_time;
-		int const vol_mode = regs [0x08 + index];
-		int volume = amp_table [vol_mode & 0x0F] >> half_vol;
-		int osc_env_pos = env.pos;
-		if ( vol_mode & 0x10 )
-		{
-			volume = env.wave [osc_env_pos] >> half_vol;
-			// use envelope only if it's a repeating wave or a ramp that hasn't finished
-			if ( !(regs [13] & 1) || osc_env_pos < -32 )
-			{
-				end_time = start_time + env.delay;
-				if ( end_time >= final_end_time )
-					end_time = final_end_time;
-
-				//if ( !(regs [12] | regs [11]) )
-				//  debug_printf( "Used envelope period 0\n" );
-			}
-			else if ( !volume )
-			{
-				osc_mode = noise_off | tone_off;
-			}
-		}
-		else if ( !volume )
-		{
-			osc_mode = noise_off | tone_off;
-		}
-
-		// tone time
-		blip_time_t const period = osc->period;
-		blip_time_t time = start_time + osc->delay;
-		if ( osc_mode & tone_off ) // maintain tone's phase when off
-		{
-			blargg_long count = (final_end_time - time + period - 1) / period;
-			time += count * period;
-			osc->phase ^= count & 1;
-		}
-
-		// noise time
-		blip_time_t ntime = final_end_time;
-		blargg_ulong noise_lfsr = 1;
-		if ( !(osc_mode & noise_off) )
-		{
-			ntime = start_time + old_noise_delay;
-			noise_lfsr = old_noise_lfsr;
-			//if ( (regs [6] & 0x1F) == 0 )
-			//  debug_printf( "Used noise period 0\n" );
-		}
-
-		// The following efficiently handles several cases (least demanding first):
-		// * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
-		// * Just tone or just noise, envelope disabled
-		// * Envelope controlling tone and/or noise
-		// * Tone and noise disabled, envelope enabled with high frequency
-		// * Tone and noise together
-		// * Tone and noise together with envelope
-
-		// This loop only runs one iteration if envelope is disabled. If envelope
-		// is being used as a waveform (tone and noise disabled), this loop will
-		// still be reasonably efficient since the bulk of it will be skipped.
-		while ( 1 )
-		{
-			// current amplitude
-			int amp = 0;
-			if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
-				amp = volume;
-			{
-				int delta = amp - osc->last_amp;
-				if ( delta )
-				{
-					osc->last_amp = amp;
-					synth_.offset( start_time, delta, osc_output );
-				}
-			}
-
-			// Run wave and noise interleved with each catching up to the other.
-			// If one or both are disabled, their "current time" will be past end time,
-			// so there will be no significant performance hit.
-			if ( ntime < end_time || time < end_time )
-			{
-				// Since amplitude was updated above, delta will always be +/- volume,
-				// so we can avoid using last_amp every time to calculate the delta.
-				int delta = amp * 2 - volume;
-				int delta_non_zero = delta != 0;
-				int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
-				do
-				{
-					// run noise
-					blip_time_t end = end_time;
-					if ( end_time > time ) end = time;
-					if ( phase & delta_non_zero )
-					{
-						while ( ntime <= end ) // must advance *past* time to avoid hang
-						{
-							int changed = noise_lfsr + 1;
-							noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
-							if ( changed & 2 )
-							{
-								delta = -delta;
-								synth_.offset( ntime, delta, osc_output );
-							}
-							ntime += noise_period;
-						}
-					}
-					else
-					{
-						// 20 or more noise periods on average for some music
-						blargg_long remain = end - ntime;
-						blargg_long count = remain / noise_period;
-						if ( remain >= 0 )
-							ntime += noise_period + count * noise_period;
-					}
-
-					// run tone
-					end = end_time;
-					if ( end_time > ntime ) end = ntime;
-					if ( noise_lfsr & delta_non_zero )
-					{
-						while ( time < end )
-						{
-							delta = -delta;
-							synth_.offset( time, delta, osc_output );
-							time += period;
-							//phase ^= 1;
-						}
-						//assert( phase == (delta > 0) );
-						phase = unsigned (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
-						// (delta > 0)
-					}
-					else
-					{
-						// loop usually runs less than once
-						//SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
-
-						while ( time < end )
-						{
-							time += period;
-							phase ^= 1;
-						}
-					}
-				}
-				while ( time < end_time || ntime < end_time );
-
-				osc->last_amp = (delta + volume) >> 1;
-				if ( !(osc_mode & tone_off) )
-					osc->phase = phase;
-			}
-
-			if ( end_time >= final_end_time )
-				break; // breaks first time when envelope is disabled
-
-			// next envelope step
-			if ( ++osc_env_pos >= 0 )
-				osc_env_pos -= 32;
-			volume = env.wave [osc_env_pos] >> half_vol;
-
-			start_time = end_time;
-			end_time += env_period;
-			if ( end_time > final_end_time )
-				end_time = final_end_time;
-		}
-		osc->delay = time - final_end_time;
-
-		if ( !(osc_mode & noise_off) )
-		{
-			noise.delay = ntime - final_end_time;
-			noise.lfsr = noise_lfsr;
-		}
-	}
-
-	// TODO: optimized saw wave envelope?
-
-	// maintain envelope phase
-	blip_time_t remain = final_end_time - last_time - env.delay;
-	if ( remain >= 0 )
-	{
-		blargg_long count = (remain + env_period) / env_period;
-		env.pos += count;
-		if ( env.pos >= 0 )
-			env.pos = (env.pos & 31) - 32;
-		remain -= count * env_period;
-		assert( -remain <= env_period );
-	}
-	env.delay = -remain;
-	assert( env.delay > 0 );
-	assert( env.pos < 0 );
-
-	last_time = final_end_time;
-}
diff --git a/src/console/Ay_Apu.h b/src/console/Ay_Apu.h
index fe5d12518de0..b7f223898426 100644
--- a/src/console/Ay_Apu.h
+++ b/src/console/Ay_Apu.h
@@ -9,7 +9,7 @@
 
 class Ay_Apu {
 public:
-	// Set buffer to generate all sound into, or disable sound if NULL
+	// Set buffer to generate all sound into, or disable sound if nullptr
 	void output( Blip_Buffer* );
 
 	// Reset sound chip
@@ -27,7 +27,7 @@ public:
 // Additional features
 
 	// Set sound output of specific oscillator to buffer, where index is
-	// 0, 1, or 2. If buffer is NULL, the specified oscillator is muted.
+	// 0, 1, or 2. If buffer is nullptr, the specified oscillator is muted.
 	enum { osc_count = 3 };
 	void osc_output( int index, Blip_Buffer* );
 
@@ -50,7 +50,6 @@ private:
 		Blip_Buffer* output;
 	} oscs [osc_count];
 	blip_time_t last_time;
-	byte latch;
 	byte regs [reg_count];
 
 	struct {
diff --git a/src/console/Ay_Cpu.cc b/src/console/Ay_Cpu.cc
new file mode 100644
index 000000000000..bee9eedf7e56
--- /dev/null
+++ b/src/console/Ay_Cpu.cc
@@ -0,0 +1,1661 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+/*
+Last validated with zexall 2006.11.21 5:26 PM
+* Doesn't implement the R register or immediate interrupt after EI.
+* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
+*/
+
+#include "Ay_Cpu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+//#include "z80_cpu_log.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#define SYNC_TIME()     (void) (s.time = s_time)
+#define RELOAD_TIME()   (void) (s_time = s.time)
+
+// Callbacks to emulator
+
+#define CPU_OUT( cpu, addr, data, TIME )\
+	ay_cpu_out( cpu, TIME, addr, data )
+
+#define CPU_IN( cpu, addr, TIME )\
+	ay_cpu_in( cpu, addr )
+
+#include "blargg_source.h"
+
+// flags, named with hex value for clarity
+int const S80 = 0x80;
+int const Z40 = 0x40;
+int const F20 = 0x20;
+int const H10 = 0x10;
+int const F08 = 0x08;
+int const V04 = 0x04;
+int const P04 = 0x04;
+int const N02 = 0x02;
+int const C01 = 0x01;
+
+#define SZ28P( n )  szpc [n]
+#define SZ28PC( n ) szpc [n]
+#define SZ28C( n )  (szpc [n] & ~P04)
+#define SZ28( n )   SZ28C( n )
+
+#define SET_R( n )  (void) (r.r = n)
+#define GET_R()     (r.r)
+
+Ay_Cpu::Ay_Cpu()
+{
+	state = &state_;
+	for ( int i = 0x100; --i >= 0; )
+	{
+		int even = 1;
+		for ( int p = i; p; p >>= 1 )
+			even ^= p;
+		int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
+		szpc [i] = n;
+		szpc [i + 0x100] = n | C01;
+	}
+	szpc [0x000] |= Z40;
+	szpc [0x100] |= Z40;
+}
+
+void Ay_Cpu::reset( void* m )
+{
+	mem = (uint8_t*) m;
+
+	check( state == &state_ );
+	state = &state_;
+	state_.time = 0;
+	state_.base = 0;
+	end_time_   = 0;
+
+	memset( &r, 0, sizeof r );
+}
+
+#define TIME                        (s_time + s.base)
+#define READ_PROG( addr )           (mem [addr])
+#define INSTR( offset )             READ_PROG( pc + (offset) )
+#define GET_ADDR()                  GET_LE16( &READ_PROG( pc ) )
+#define READ( addr )                READ_PROG( addr )
+#define WRITE( addr, data )         (void) (READ_PROG( addr ) = data)
+#define READ_WORD( addr )           GET_LE16( &READ_PROG( addr ) )
+#define WRITE_WORD( addr, data )    SET_LE16( &READ_PROG( addr ), data )
+#define IN( addr )                  CPU_IN( this, addr, TIME )
+#define OUT( addr, data )           CPU_OUT( this, addr, data, TIME )
+
+#if BLARGG_BIG_ENDIAN
+	#define R8( n, offset ) ((r8_ - offset) [n])
+#elif BLARGG_LITTLE_ENDIAN
+	#define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
+#else
+	#error "Byte order of CPU must be known"
+#endif
+
+//#define R16( n, shift, offset )   (r16_ [((n) >> shift) - (offset >> shift)])
+
+// help compiler see that it can just adjust stack offset, saving an extra instruction
+#define R16( n, shift, offset )\
+	(*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
+
+#define CASE5( a, b, c, d, e          ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
+#define CASE6( a, b, c, d, e, f       ) CASE5( a, b, c, d, e       ): case 0x##f
+#define CASE7( a, b, c, d, e, f, g    ) CASE6( a, b, c, d, e, f    ): case 0x##g
+#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
+
+// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
+static byte const ed_dd_timing [0x100] = {
+//0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
+0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
+0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
+0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+// even on x86, using short and unsigned char was slower
+typedef int         fint16;
+typedef unsigned    fuint16;
+typedef unsigned    fuint8;
+
+bool Ay_Cpu::run( cpu_time_t end_time )
+{
+	set_end_time( end_time );
+	state_t s = this->state_;
+	this->state = &s;
+	bool warning = false;
+
+	union {
+		regs_t rg;
+		pairs_t rp;
+		uint8_t r8_ [8]; // indexed
+		uint16_t r16_ [4];
+	};
+	rg = this->r.b;
+
+	cpu_time_t s_time = s.time;
+	uint8_t* const mem = this->mem; // cache
+	fuint16 pc = r.pc;
+	fuint16 sp = r.sp;
+	fuint16 ix = r.ix; // TODO: keep in memory for direct access?
+	fuint16 iy = r.iy;
+	int flags = r.b.flags;
+
+	goto loop;
+jr_not_taken:
+	s_time -= 5;
+	goto loop;
+call_not_taken:
+	s_time -= 7;
+jp_not_taken:
+	pc += 2;
+loop:
+
+	check( (unsigned long) pc < 0x10000 );
+	check( (unsigned long) sp < 0x10000 );
+	check( (unsigned) flags < 0x100 );
+	check( (unsigned) ix < 0x10000 );
+	check( (unsigned) iy < 0x10000 );
+
+	fuint8 opcode;
+	opcode = READ_PROG( pc );
+	pc++;
+
+	static byte const base_timing [0x100] = {
+	//   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
+		 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
+		13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
+		12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
+		12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
+		 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
+		11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
+		11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
+		11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
+		11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
+	};
+
+	fuint16 data;
+	data = base_timing [opcode];
+	if ( (s_time += data) >= 0 )
+		goto possibly_out_of_time;
+almost_out_of_time:
+
+	data = READ_PROG( pc );
+
+	#ifdef Z80_CPU_LOG_H
+		//log_opcode( opcode, READ_PROG( pc ) );
+		z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
+		z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
+				READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
+	#endif
+
+	switch ( opcode )
+	{
+possibly_out_of_time:
+		if ( s_time < (int) data )
+			goto almost_out_of_time;
+		s_time -= data;
+		goto out_of_time;
+
+// Common
+
+	case 0x00: // NOP
+	CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
+		goto loop;
+
+	case 0x08:{// EX AF,AF'
+		int temp = r.alt.b.a;
+		r.alt.b.a = rg.a;
+		rg.a = temp;
+
+		temp = r.alt.b.flags;
+		r.alt.b.flags = flags;
+		flags = temp;
+		goto loop;
+	}
+
+	case 0xD3: // OUT (imm),A
+		pc++;
+		OUT( data + rg.a * 0x100, rg.a );
+		goto loop;
+
+	case 0x2E: // LD L,imm
+		pc++;
+		rg.l = data;
+		goto loop;
+
+	case 0x3E: // LD A,imm
+		pc++;
+		rg.a = data;
+		goto loop;
+
+	case 0x3A:{// LD A,(addr)
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		rg.a = READ( addr );
+		goto loop;
+	}
+
+// Conditional
+
+#define ZERO    (flags & Z40)
+#define CARRY   (flags & C01)
+#define EVEN    (flags & P04)
+#define MINUS   (flags & S80)
+
+// JR
+#define JR( cond ) {\
+	int disp = (int8_t) data;\
+	pc++;\
+	if ( !(cond) )\
+		goto jr_not_taken;\
+	pc += disp;\
+	goto loop;\
+}
+
+	case 0x20: JR( !ZERO  ) // JR NZ,disp
+	case 0x28: JR(  ZERO  ) // JR Z,disp
+	case 0x30: JR( !CARRY ) // JR NC,disp
+	case 0x38: JR(  CARRY ) // JR C,disp
+	case 0x18: JR(  true  ) // JR disp
+
+	case 0x10:{// DJNZ disp
+		int temp = rg.b - 1;
+		rg.b = temp;
+		JR( temp )
+	}
+
+// JP
+#define JP( cond )  if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
+
+	case 0xC2: JP( !ZERO  ) // JP NZ,addr
+	case 0xCA: JP(  ZERO  ) // JP Z,addr
+	case 0xD2: JP( !CARRY ) // JP NC,addr
+	case 0xDA: JP(  CARRY ) // JP C,addr
+	case 0xE2: JP( !EVEN  ) // JP PO,addr
+	case 0xEA: JP(  EVEN  ) // JP PE,addr
+	case 0xF2: JP( !MINUS ) // JP P,addr
+	case 0xFA: JP(  MINUS ) // JP M,addr
+
+	case 0xC3: // JP addr
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xE9: // JP HL
+		pc = rp.hl;
+		goto loop;
+
+// RET
+#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
+
+	case 0xC0: RET( !ZERO  ) // RET NZ
+	case 0xC8: RET(  ZERO  ) // RET Z
+	case 0xD0: RET( !CARRY ) // RET NC
+	case 0xD8: RET(  CARRY ) // RET C
+	case 0xE0: RET( !EVEN  ) // RET PO
+	case 0xE8: RET(  EVEN  ) // RET PE
+	case 0xF0: RET( !MINUS ) // RET P
+	case 0xF8: RET(  MINUS ) // RET M
+
+	case 0xC9: // RET
+	ret_taken:
+		pc = READ_WORD( sp );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+// CALL
+#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
+
+	case 0xC4: CALL( !ZERO  ) // CALL NZ,addr
+	case 0xCC: CALL(  ZERO  ) // CALL Z,addr
+	case 0xD4: CALL( !CARRY ) // CALL NC,addr
+	case 0xDC: CALL(  CARRY ) // CALL C,addr
+	case 0xE4: CALL( !EVEN  ) // CALL PO,addr
+	case 0xEC: CALL(  EVEN  ) // CALL PE,addr
+	case 0xF4: CALL( !MINUS ) // CALL P,addr
+	case 0xFC: CALL(  MINUS ) // CALL M,addr
+
+	case 0xCD:{// CALL addr
+	call_taken:
+		fuint16 addr = pc + 2;
+		pc = GET_ADDR();
+		sp = uint16_t (sp - 2);
+		WRITE_WORD( sp, addr );
+		goto loop;
+	}
+
+	case 0xFF: // RST
+		if ( (pc - 1) > 0xFFFF )
+		{
+			pc = uint16_t (pc - 1);
+			s_time -= 11;
+			goto loop;
+		}
+	CASE7( C7, CF, D7, DF, E7, EF, F7 ):
+		data = pc;
+		pc = opcode & 0x38;
+		goto push_data;
+
+// PUSH/POP
+	case 0xF5: // PUSH AF
+		data = rg.a * 0x100u + flags;
+		goto push_data;
+
+	case 0xC5: // PUSH BC
+	case 0xD5: // PUSH DE
+	case 0xE5: // PUSH HL
+		data = R16( opcode, 4, 0xC5 );
+	push_data:
+		sp = uint16_t (sp - 2);
+		WRITE_WORD( sp, data );
+		goto loop;
+
+	case 0xF1: // POP AF
+		flags = READ( sp );
+		rg.a = READ( sp + 1 );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+	case 0xC1: // POP BC
+	case 0xD1: // POP DE
+	case 0xE1: // POP HL
+		R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+// ADC/ADD/SBC/SUB
+	case 0x96: // SUB (HL)
+	case 0x86: // ADD (HL)
+		flags &= ~C01;
+	case 0x9E: // SBC (HL)
+	case 0x8E: // ADC (HL)
+		data = READ( rp.hl );
+		goto adc_data;
+
+	case 0xD6: // SUB A,imm
+	case 0xC6: // ADD imm
+		flags &= ~C01;
+	case 0xDE: // SBC A,imm
+	case 0xCE: // ADC imm
+		pc++;
+		goto adc_data;
+
+	CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
+	CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
+		flags &= ~C01;
+	CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
+	CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
+		data = R8( opcode & 7, 0 );
+	adc_data: {
+		int result = data + (flags & C01);
+		data ^= rg.a;
+		flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
+		if ( flags )
+			result = -result;
+		result += rg.a;
+		data ^= result;
+		flags |=(data & H10) |
+				((data - -0x80) >> 6 & V04) |
+				SZ28C( result & 0x1FF );
+		rg.a = result;
+		goto loop;
+	}
+
+// CP
+	case 0xBE: // CP (HL)
+		data = READ( rp.hl );
+		goto cp_data;
+
+	case 0xFE: // CP imm
+		pc++;
+		goto cp_data;
+
+	CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
+		data = R8( opcode, 0xB8 );
+	cp_data: {
+		int result = rg.a - data;
+		flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
+		data ^= rg.a;
+		flags |=(((result ^ rg.a) & data) >> 5 & V04) |
+				(((data & H10) ^ result) & (S80 | H10));
+		if ( (uint8_t) result )
+			goto loop;
+		flags |= Z40;
+		goto loop;
+	}
+
+// ADD HL,rp
+
+	case 0x39: // ADD HL,SP
+		data = sp;
+		goto add_hl_data;
+
+	case 0x09: // ADD HL,BC
+	case 0x19: // ADD HL,DE
+	case 0x29: // ADD HL,HL
+		data = R16( opcode, 4, 0x09 );
+	add_hl_data: {
+		blargg_ulong sum = rp.hl + data;
+		data ^= rp.hl;
+		rp.hl = sum;
+		flags = (flags & (S80 | Z40 | V04)) |
+				(sum >> 16) |
+				(sum >> 8 & (F20 | F08)) |
+				((data ^ sum) >> 8 & H10);
+		goto loop;
+	}
+
+	case 0x27:{// DAA
+		int a = rg.a;
+		if ( a > 0x99 )
+			flags |= C01;
+
+		int adjust = 0x60 & -(flags & C01);
+
+		if ( flags & H10 || (a & 0x0F) > 9 )
+			adjust |= 0x06;
+
+		if ( flags & N02 )
+			adjust = -adjust;
+		a += adjust;
+
+		flags = (flags & (C01 | N02)) |
+				((rg.a ^ a) & H10) |
+				SZ28P( (uint8_t) a );
+		rg.a = a;
+		goto loop;
+	}
+	/*
+	case 0x27:{// DAA
+		// more optimized, but probably not worth the obscurity
+		int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
+		int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
+
+		if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
+			adjust |= 0x06;
+
+		if ( f & N02 )
+			adjust = -adjust;
+		int a = rg.a + adjust;
+
+		flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
+		rg.a = a;
+		goto loop;
+	}
+	*/
+
+// INC/DEC
+	case 0x34: // INC (HL)
+		data = READ( rp.hl ) + 1;
+		WRITE( rp.hl, data );
+		goto inc_set_flags;
+
+	CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
+		data = ++R8( opcode >> 3, 0 );
+	inc_set_flags:
+		flags = (flags & C01) |
+				(((data & 0x0F) - 1) & H10) |
+				SZ28( (uint8_t) data );
+		if ( data != 0x80 )
+			goto loop;
+		flags |= V04;
+		goto loop;
+
+	case 0x35: // DEC (HL)
+		data = READ( rp.hl ) - 1;
+		WRITE( rp.hl, data );
+		goto dec_set_flags;
+
+	CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
+		data = --R8( opcode >> 3, 0 );
+	dec_set_flags:
+		flags = (flags & C01) | N02 |
+				(((data & 0x0F) + 1) & H10) |
+				SZ28( (uint8_t) data );
+		if ( data != 0x7F )
+			goto loop;
+		flags |= V04;
+		goto loop;
+
+	case 0x03: // INC BC
+	case 0x13: // INC DE
+	case 0x23: // INC HL
+		R16( opcode, 4, 0x03 )++;
+		goto loop;
+
+	case 0x33: // INC SP
+		sp = uint16_t (sp + 1);
+		goto loop;
+
+	case 0x0B: // DEC BC
+	case 0x1B: // DEC DE
+	case 0x2B: // DEC HL
+		R16( opcode, 4, 0x0B )--;
+		goto loop;
+
+	case 0x3B: // DEC SP
+		sp = uint16_t (sp - 1);
+		goto loop;
+
+// AND
+	case 0xA6: // AND (HL)
+		data = READ( rp.hl );
+		goto and_data;
+
+	case 0xE6: // AND imm
+		pc++;
+		goto and_data;
+
+	CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
+		data = R8( opcode, 0xA0 );
+	and_data:
+		rg.a &= data;
+		flags = SZ28P( rg.a ) | H10;
+		goto loop;
+
+// OR
+	case 0xB6: // OR (HL)
+		data = READ( rp.hl );
+		goto or_data;
+
+	case 0xF6: // OR imm
+		pc++;
+		goto or_data;
+
+	CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
+		data = R8( opcode, 0xB0 );
+	or_data:
+		rg.a |= data;
+		flags = SZ28P( rg.a );
+		goto loop;
+
+// XOR
+	case 0xAE: // XOR (HL)
+		data = READ( rp.hl );
+		goto xor_data;
+
+	case 0xEE: // XOR imm
+		pc++;
+		goto xor_data;
+
+	CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
+		data = R8( opcode, 0xA8 );
+	xor_data:
+		rg.a ^= data;
+		flags = SZ28P( rg.a );
+		goto loop;
+
+// LD
+	CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
+		WRITE( rp.hl, R8( opcode, 0x70 ) );
+		goto loop;
+
+	CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
+	CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
+	CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
+	CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
+	CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
+	CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
+	CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
+		R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
+		goto loop;
+
+	CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
+		R8( opcode >> 3, 0 ) = data;
+		pc++;
+		goto loop;
+
+	case 0x36: // LD (HL),imm
+		pc++;
+		WRITE( rp.hl, data );
+		goto loop;
+
+	CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
+		R8( opcode >> 3, 8 ) = READ( rp.hl );
+		goto loop;
+
+	case 0x01: // LD rp,imm
+	case 0x11:
+	case 0x21:
+		R16( opcode, 4, 0x01 ) = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x31: // LD sp,imm
+		sp = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x2A:{// LD HL,(addr)
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		rp.hl = READ_WORD( addr );
+		goto loop;
+	}
+
+	case 0x32:{// LD (addr),A
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		WRITE( addr, rg.a );
+		goto loop;
+	}
+
+	case 0x22:{// LD (addr),HL
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		WRITE_WORD( addr, rp.hl );
+		goto loop;
+	}
+
+	case 0x02: // LD (BC),A
+	case 0x12: // LD (DE),A
+		WRITE( R16( opcode, 4, 0x02 ), rg.a );
+		goto loop;
+
+	case 0x0A: // LD A,(BC)
+	case 0x1A: // LD A,(DE)
+		rg.a = READ( R16( opcode, 4, 0x0A ) );
+		goto loop;
+
+	case 0xF9: // LD SP,HL
+		sp = rp.hl;
+		goto loop;
+
+// Rotate
+
+	case 0x07:{// RLCA
+		fuint16 temp = rg.a;
+		temp = (temp << 1) | (temp >> 7);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08 | C01));
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x0F:{// RRCA
+		fuint16 temp = rg.a;
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & C01);
+		temp = (temp << 7) | (temp >> 1);
+		flags |= temp & (F20 | F08);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x17:{// RLA
+		blargg_ulong temp = (rg.a << 1) | (flags & C01);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08)) |
+				(temp >> 8);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x1F:{// RRA
+		fuint16 temp = (flags << 7) | (rg.a >> 1);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08)) |
+				(rg.a & C01);
+		rg.a = temp;
+		goto loop;
+	}
+
+// Misc
+	case 0x2F:{// CPL
+		fuint16 temp = ~rg.a;
+		flags = (flags & (S80 | Z40 | P04 | C01)) |
+				(temp & (F20 | F08)) |
+				(H10 | N02);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x3F:{// CCF
+		flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
+				(flags << 4 & H10) |
+				(rg.a & (F20 | F08));
+		goto loop;
+	}
+
+	case 0x37: // SCF
+		flags = (flags & (S80 | Z40 | P04)) | C01 |
+				(rg.a & (F20 | F08));
+		goto loop;
+
+	case 0xDB: // IN A,(imm)
+		pc++;
+		rg.a = IN( data + rg.a * 0x100 );
+		goto loop;
+
+	case 0xE3:{// EX (SP),HL
+		fuint16 temp = READ_WORD( sp );
+		WRITE_WORD( sp, rp.hl );
+		rp.hl = temp;
+		goto loop;
+	}
+
+	case 0xEB:{// EX DE,HL
+		fuint16 temp = rp.hl;
+		rp.hl = rp.de;
+		rp.de = temp;
+		goto loop;
+	}
+
+	case 0xD9:{// EXX DE,HL
+		fuint16 temp = r.alt.w.bc;
+		r.alt.w.bc = rp.bc;
+		rp.bc = temp;
+
+		temp = r.alt.w.de;
+		r.alt.w.de = rp.de;
+		rp.de = temp;
+
+		temp = r.alt.w.hl;
+		r.alt.w.hl = rp.hl;
+		rp.hl = temp;
+		goto loop;
+	}
+
+	case 0xF3: // DI
+		r.iff1 = 0;
+		r.iff2 = 0;
+		goto loop;
+
+	case 0xFB: // EI
+		r.iff1 = 1;
+		r.iff2 = 1;
+		// TODO: delayed effect
+		goto loop;
+
+	case 0x76: // HALT
+		goto halt;
+
+//////////////////////////////////////// CB prefix
+	{
+	case 0xCB:
+		pc++;
+		switch ( data )
+		{
+
+	// Rotate left
+
+	#define RLC( read, write ) {\
+		fuint8 result = read;\
+		result = uint8_t (result << 1) | (result >> 7);\
+		flags = SZ28P( result ) | (result & C01);\
+		write;\
+		goto loop;\
+	}
+
+		case 0x06: // RLC (HL)
+			s_time += 7;
+			data = rp.hl;
+		rlc_data_addr:
+			RLC( READ( data ), WRITE( data, result ) )
+
+		CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
+			uint8_t& reg = R8( data, 0 );
+			RLC( reg, reg = result )
+		}
+
+	#define RL( read, write ) {\
+		fuint16 result = (read << 1) | (flags & C01);\
+		flags = SZ28PC( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x16: // RL (HL)
+			s_time += 7;
+			data = rp.hl;
+		rl_data_addr:
+			RL( READ( data ), WRITE( data, result ) )
+
+		CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
+			uint8_t& reg = R8( data, 0x10 );
+			RL( reg, reg = result )
+		}
+
+	#define SLA( read, add, write ) {\
+		fuint16 result = (read << 1) | add;\
+		flags = SZ28PC( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x26: // SLA (HL)
+			s_time += 7;
+			data = rp.hl;
+		sla_data_addr:
+			SLA( READ( data ), 0, WRITE( data, result ) )
+
+		CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
+			uint8_t& reg = R8( data, 0x20 );
+			SLA( reg, 0, reg = result )
+		}
+
+		case 0x36: // SLL (HL)
+			s_time += 7;
+			data = rp.hl;
+		sll_data_addr:
+			SLA( READ( data ), 1, WRITE( data, result ) )
+
+		CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
+			uint8_t& reg = R8( data, 0x30 );
+			SLA( reg, 1, reg = result )
+		}
+
+	// Rotate right
+
+	#define RRC( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result = uint8_t (result << 7) | (result >> 1);\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x0E: // RRC (HL)
+			s_time += 7;
+			data = rp.hl;
+		rrc_data_addr:
+			RRC( READ( data ), WRITE( data, result ) )
+
+		CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
+			uint8_t& reg = R8( data, 0x08 );
+			RRC( reg, reg = result )
+		}
+
+	#define RR( read, write ) {\
+		fuint8 result = read;\
+		fuint8 temp = result & C01;\
+		result = uint8_t (flags << 7) | (result >> 1);\
+		flags = SZ28P( result ) | temp;\
+		write;\
+		goto loop;\
+	}
+
+		case 0x1E: // RR (HL)
+			s_time += 7;
+			data = rp.hl;
+		rr_data_addr:
+			RR( READ( data ), WRITE( data, result ) )
+
+		CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
+			uint8_t& reg = R8( data, 0x18 );
+			RR( reg, reg = result )
+		}
+
+	#define SRA( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result = (result & 0x80) | (result >> 1);\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x2E: // SRA (HL)
+			data = rp.hl;
+			s_time += 7;
+		sra_data_addr:
+			SRA( READ( data ), WRITE( data, result ) )
+
+		CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
+			uint8_t& reg = R8( data, 0x28 );
+			SRA( reg, reg = result )
+		}
+
+	#define SRL( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result >>= 1;\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x3E: // SRL (HL)
+			s_time += 7;
+			data = rp.hl;
+		srl_data_addr:
+			SRL( READ( data ), WRITE( data, result ) )
+
+		CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
+			uint8_t& reg = R8( data, 0x38 );
+			SRL( reg, reg = result )
+		}
+
+	// BIT
+		{
+			unsigned temp;
+		CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
+			s_time += 4;
+			temp = READ( rp.hl );
+			flags &= C01;
+			goto bit_temp;
+		CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
+		CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
+		CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
+		CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
+		CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
+		CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
+		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
+		CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
+			temp = R8( data & 7, 0 );
+			flags = (flags & C01) | (temp & (F20 | F08));
+		bit_temp:
+			int masked = temp & 1 << (data >> 3 & 7);
+			flags |=(masked & S80) | H10 |
+					((masked - 1) >> 8 & (Z40 | P04));
+			goto loop;
+		}
+
+	// SET/RES
+		CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
+		CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
+			s_time += 7;
+			int temp = READ( rp.hl );
+			int bit = 1 << (data >> 3 & 7);
+			temp |= bit; // SET
+			if ( !(data & 0x40) )
+				temp ^= bit; // RES
+			WRITE( rp.hl, temp );
+			goto loop;
+		}
+
+		CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
+		CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
+		CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
+		CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
+		CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
+		CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
+		CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
+		CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
+			R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
+			goto loop;
+
+		CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
+		CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
+		CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
+		CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
+		CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
+		CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
+		CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
+		CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
+			R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
+			goto loop;
+		}
+		assert( false );
+	}
+
+//////////////////////////////////////// ED prefix
+	{
+	case 0xED:
+		pc++;
+		s_time += ed_dd_timing [data] >> 4;
+		switch ( data )
+		{
+		{
+			blargg_ulong temp;
+		case 0x72: // SBC HL,SP
+		case 0x7A: // ADC HL,SP
+			temp = sp;
+			if ( 0 )
+		case 0x42: // SBC HL,BC
+		case 0x52: // SBC HL,DE
+		case 0x62: // SBC HL,HL
+		case 0x4A: // ADC HL,BC
+		case 0x5A: // ADC HL,DE
+		case 0x6A: // ADC HL,HL
+				temp = R16( data >> 3 & 6, 1, 0 );
+			blargg_ulong sum = temp + (flags & C01);
+			flags = ~data >> 2 & N02;
+			if ( flags )
+				sum = -sum;
+			sum += rp.hl;
+			temp ^= rp.hl;
+			temp ^= sum;
+			flags |=(sum >> 16 & C01) |
+					(temp >> 8 & H10) |
+					(sum >> 8 & (S80 | F20 | F08)) |
+					((temp - -0x8000) >> 14 & V04);
+			rp.hl = sum;
+			if ( (uint16_t) sum )
+				goto loop;
+			flags |= Z40;
+			goto loop;
+		}
+
+		CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
+			int temp = IN( rp.bc );
+			R8( data >> 3, 8 ) = temp;
+			flags = (flags & C01) | SZ28P( temp );
+			goto loop;
+		}
+
+		case 0x71: // OUT (C),0
+			rg.flags = 0;
+		CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
+			OUT( rp.bc, R8( data >> 3, 8 ) );
+			goto loop;
+
+		{
+			unsigned temp;
+		case 0x73: // LD (ADDR),SP
+			temp = sp;
+			if ( 0 )
+		case 0x43: // LD (ADDR),BC
+		case 0x53: // LD (ADDR),DE
+				temp = R16( data, 4, 0x43 );
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			WRITE_WORD( addr, temp );
+			goto loop;
+		}
+
+		case 0x4B: // LD BC,(ADDR)
+		case 0x5B:{// LD DE,(ADDR)
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			R16( data, 4, 0x4B ) = READ_WORD( addr );
+			goto loop;
+		}
+
+		case 0x7B:{// LD SP,(ADDR)
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			sp = READ_WORD( addr );
+			goto loop;
+		}
+
+		case 0x67:{// RRD
+			fuint8 temp = READ( rp.hl );
+			WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
+			temp = (rg.a & 0xF0) | (temp & 0x0F);
+			flags = (flags & C01) | SZ28P( temp );
+			rg.a = temp;
+			goto loop;
+		}
+
+		case 0x6F:{// RLD
+			fuint8 temp = READ( rp.hl );
+			WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
+			temp = (rg.a & 0xF0) | (temp >> 4);
+			flags = (flags & C01) | SZ28P( temp );
+			rg.a = temp;
+			goto loop;
+		}
+
+		CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
+			opcode = 0x10; // flag to do SBC instead of ADC
+			flags &= ~C01;
+			data = rg.a;
+			rg.a = 0;
+			goto adc_data;
+
+		{
+			int inc;
+		case 0xA9: // CPD
+		case 0xB9: // CPDR
+			inc = -1;
+			if ( 0 )
+		case 0xA1: // CPI
+		case 0xB1: // CPIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			int result = rg.a - temp;
+			flags = (flags & C01) | N02 |
+					((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
+
+			if ( !(uint8_t) result ) flags |= Z40;
+			result -= (flags & H10) >> 4;
+			flags |= result & F08;
+			flags |= result << 4 & F20;
+			if ( !--rp.bc )
+				goto loop;
+
+			flags |= V04;
+			if ( flags & Z40 || data < 0xB0 )
+				goto loop;
+
+			pc -= 2;
+			s_time += 5;
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xA8: // LDD
+		case 0xB8: // LDDR
+			inc = -1;
+			if ( 0 )
+		case 0xA0: // LDI
+		case 0xB0: // LDIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			addr = rp.de;
+			rp.de = addr + inc;
+			WRITE( addr, temp );
+
+			temp += rg.a;
+			flags = (flags & (S80 | Z40 | C01)) |
+					(temp & F08) | (temp << 4 & F20);
+			if ( !--rp.bc )
+				goto loop;
+
+			flags |= V04;
+			if ( data < 0xB0 )
+				goto loop;
+
+			pc -= 2;
+			s_time += 5;
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xAB: // OUTD
+		case 0xBB: // OTDR
+			inc = -1;
+			if ( 0 )
+		case 0xA3: // OUTI
+		case 0xB3: // OTIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			int b = --rg.b;
+			flags = (temp >> 6 & N02) | SZ28( b );
+			if ( b && data >= 0xB0 )
+			{
+				pc -= 2;
+				s_time += 5;
+			}
+
+			OUT( rp.bc, temp );
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xAA: // IND
+		case 0xBA: // INDR
+			inc = -1;
+			if ( 0 )
+		case 0xA2: // INI
+		case 0xB2: // INIR
+				inc = +1;
+
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+
+			int temp = IN( rp.bc );
+
+			int b = --rg.b;
+			flags = (temp >> 6 & N02) | SZ28( b );
+			if ( b && data >= 0xB0 )
+			{
+				pc -= 2;
+				s_time += 5;
+			}
+
+			WRITE( addr, temp );
+			goto loop;
+		}
+
+		case 0x47: // LD I,A
+			r.i = rg.a;
+			goto loop;
+
+		case 0x4F: // LD R,A
+			SET_R( rg.a );
+			debug_printf( "LD R,A not supported\n" );
+			warning = true;
+			goto loop;
+
+		case 0x57: // LD A,I
+			rg.a = r.i;
+			goto ld_ai_common;
+
+		case 0x5F: // LD A,R
+			rg.a = GET_R();
+			debug_printf( "LD A,R not supported\n" );
+			warning = true;
+		ld_ai_common:
+			flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
+			goto loop;
+
+		CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
+			r.iff1 = r.iff2;
+			goto ret_taken;
+
+		case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
+			r.im = 0;
+			goto loop;
+
+		case 0x56: case 0x76: // IM 1
+			r.im = 1;
+			goto loop;
+
+		case 0x5E: case 0x7E: // IM 2
+			r.im = 2;
+			goto loop;
+
+		default:
+			debug_printf( "Opcode $ED $%02X not supported\n", data );
+			warning = true;
+			goto loop;
+		}
+		assert( false );
+	}
+
+//////////////////////////////////////// DD/FD prefix
+	{
+	fuint16 ixy;
+	case 0xDD:
+		ixy = ix;
+		goto ix_prefix;
+	case 0xFD:
+		ixy = iy;
+	ix_prefix:
+		pc++;
+		unsigned data2 = READ_PROG( pc );
+		s_time += ed_dd_timing [data] & 0x0F;
+		switch ( data )
+		{
+	// TODO: more efficient way of avoid negative address
+	#define IXY_DISP( ixy, disp )   uint16_t ((ixy) + (disp))
+
+	#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
+
+	// ADD/ADC/SUB/SBC
+
+		case 0x96: // SUB (IXY+disp)
+		case 0x86: // ADD (IXY+disp)
+			flags &= ~C01;
+		case 0x9E: // SBC (IXY+disp)
+		case 0x8E: // ADC (IXY+disp)
+			pc++;
+			opcode = data;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto adc_data;
+
+		case 0x94: // SUB HXY
+		case 0x84: // ADD HXY
+			flags &= ~C01;
+		case 0x9C: // SBC HXY
+		case 0x8C: // ADC HXY
+			opcode = data;
+			data = ixy >> 8;
+			goto adc_data;
+
+		case 0x95: // SUB LXY
+		case 0x85: // ADD LXY
+			flags &= ~C01;
+		case 0x9D: // SBC LXY
+		case 0x8D: // ADC LXY
+			opcode = data;
+			data = (uint8_t) ixy;
+			goto adc_data;
+
+		{
+			unsigned temp;
+		case 0x39: // ADD IXY,SP
+			temp = sp;
+			goto add_ixy_data;
+
+		case 0x29: // ADD IXY,HL
+			temp = ixy;
+			goto add_ixy_data;
+
+		case 0x09: // ADD IXY,BC
+		case 0x19: // ADD IXY,DE
+			temp = R16( data, 4, 0x09 );
+		add_ixy_data: {
+			blargg_ulong sum = ixy + temp;
+			temp ^= ixy;
+			ixy = (uint16_t) sum;
+			flags = (flags & (S80 | Z40 | V04)) |
+					(sum >> 16) |
+					(sum >> 8 & (F20 | F08)) |
+					((temp ^ sum) >> 8 & H10);
+			goto set_ixy;
+		}
+		}
+
+	// AND
+		case 0xA6: // AND (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto and_data;
+
+		case 0xA4: // AND HXY
+			data = ixy >> 8;
+			goto and_data;
+
+		case 0xA5: // AND LXY
+			data = (uint8_t) ixy;
+			goto and_data;
+
+	// OR
+		case 0xB6: // OR (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto or_data;
+
+		case 0xB4: // OR HXY
+			data = ixy >> 8;
+			goto or_data;
+
+		case 0xB5: // OR LXY
+			data = (uint8_t) ixy;
+			goto or_data;
+
+	// XOR
+		case 0xAE: // XOR (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto xor_data;
+
+		case 0xAC: // XOR HXY
+			data = ixy >> 8;
+			goto xor_data;
+
+		case 0xAD: // XOR LXY
+			data = (uint8_t) ixy;
+			goto xor_data;
+
+	// CP
+		case 0xBE: // CP (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 )  );
+			goto cp_data;
+
+		case 0xBC: // CP HXY
+			data = ixy >> 8;
+			goto cp_data;
+
+		case 0xBD: // CP LXY
+			data = (uint8_t) ixy;
+			goto cp_data;
+
+	// LD
+		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
+			data = R8( data, 0x70 );
+			if ( 0 )
+		case 0x36: // LD (IXY+disp),imm
+				pc++, data = READ_PROG( pc );
+			pc++;
+			WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
+			goto loop;
+
+		CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
+			R8( data >> 3, 8 ) = ixy >> 8;
+			goto loop;
+
+		case 0x64: // LD HXY,HXY
+		case 0x6D: // LD LXY,LXY
+			goto loop;
+
+		CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
+			R8( data >> 3, 8 ) = ixy;
+			goto loop;
+
+		CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
+			pc++;
+			R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto loop;
+
+		case 0x26: // LD HXY,imm
+			pc++;
+			goto ld_hxy_data;
+
+		case 0x65: // LD HXY,LXY
+			data2 = (uint8_t) ixy;
+			goto ld_hxy_data;
+
+		CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
+			data2 = R8( data, 0x60 );
+		ld_hxy_data:
+			ixy = (uint8_t) ixy | (data2 << 8);
+			goto set_ixy;
+
+		case 0x2E: // LD LXY,imm
+			pc++;
+			goto ld_lxy_data;
+
+		case 0x6C: // LD LXY,HXY
+			data2 = ixy >> 8;
+			goto ld_lxy_data;
+
+		CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
+			data2 = R8( data, 0x68 );
+		ld_lxy_data:
+			ixy = (ixy & 0xFF00) | data2;
+		set_ixy:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto loop;
+			}
+			iy = ixy;
+			goto loop;
+
+		case 0xF9: // LD SP,IXY
+			sp = ixy;
+			goto loop;
+
+		case 0x22:{// LD (ADDR),IXY
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			WRITE_WORD( addr, ixy );
+			goto loop;
+		}
+
+		case 0x21: // LD IXY,imm
+			ixy = GET_ADDR();
+			pc += 2;
+			goto set_ixy;
+
+		case 0x2A:{// LD IXY,(addr)
+			fuint16 addr = GET_ADDR();
+			ixy = READ_WORD( addr );
+			pc += 2;
+			goto set_ixy;
+		}
+
+	// DD/FD CB prefix
+		case 0xCB: {
+			data = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data2 = READ_PROG( pc );
+			pc++;
+			switch ( data2 )
+			{
+			case 0x06: goto rlc_data_addr; // RLC (IXY)
+			case 0x16: goto rl_data_addr;  // RL (IXY)
+			case 0x26: goto sla_data_addr; // SLA (IXY)
+			case 0x36: goto sll_data_addr; // SLL (IXY)
+			case 0x0E: goto rrc_data_addr; // RRC (IXY)
+			case 0x1E: goto rr_data_addr;  // RR (IXY)
+			case 0x2E: goto sra_data_addr; // SRA (IXY)
+			case 0x3E: goto srl_data_addr; // SRL (IXY)
+
+			CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
+				fuint8 temp = READ( data );
+				int masked = temp & 1 << (data2 >> 3 & 7);
+				flags = (flags & C01) | H10 |
+						(masked & S80) |
+						((masked - 1) >> 8 & (Z40 | P04));
+				goto loop;
+			}
+
+			CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
+			CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
+				int temp = READ( data );
+				int bit = 1 << (data2 >> 3 & 7);
+				temp |= bit; // SET
+				if ( !(data2 & 0x40) )
+					temp ^= bit; // RES
+				WRITE( data, temp );
+				goto loop;
+			}
+
+			default:
+				debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
+				warning = true;
+				goto loop;
+			}
+			assert( false );
+		}
+
+	// INC/DEC
+		case 0x23: // INC IXY
+			ixy = uint16_t (ixy + 1);
+			goto set_ixy;
+
+		case 0x2B: // DEC IXY
+			ixy = uint16_t (ixy - 1);
+			goto set_ixy;
+
+		case 0x34: // INC (IXY+disp)
+			ixy = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data = READ( ixy ) + 1;
+			WRITE( ixy, data );
+			goto inc_set_flags;
+
+		case 0x35: // DEC (IXY+disp)
+			ixy = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data = READ( ixy ) - 1;
+			WRITE( ixy, data );
+			goto dec_set_flags;
+
+		case 0x24: // INC HXY
+			ixy = uint16_t (ixy + 0x100);
+			data = ixy >> 8;
+			goto inc_xy_common;
+
+		case 0x2C: // INC LXY
+			data = uint8_t (ixy + 1);
+			ixy = (ixy & 0xFF00) | data;
+		inc_xy_common:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto inc_set_flags;
+			}
+			iy = ixy;
+			goto inc_set_flags;
+
+		case 0x25: // DEC HXY
+			ixy = uint16_t (ixy - 0x100);
+			data = ixy >> 8;
+			goto dec_xy_common;
+
+		case 0x2D: // DEC LXY
+			data = uint8_t (ixy - 1);
+			ixy = (ixy & 0xFF00) | data;
+		dec_xy_common:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto dec_set_flags;
+			}
+			iy = ixy;
+			goto dec_set_flags;
+
+	// PUSH/POP
+		case 0xE5: // PUSH IXY
+			data = ixy;
+			goto push_data;
+
+		case 0xE1:{// POP IXY
+			ixy = READ_WORD( sp );
+			sp = uint16_t (sp + 2);
+			goto set_ixy;
+		}
+
+	// Misc
+
+		case 0xE9: // JP (IXY)
+			pc = ixy;
+			goto loop;
+
+		case 0xE3:{// EX (SP),IXY
+			fuint16 temp = READ_WORD( sp );
+			WRITE_WORD( sp, ixy );
+			ixy = temp;
+			goto set_ixy;
+		}
+
+		default:
+			debug_printf( "Unnecessary DD/FD prefix encountered\n" );
+			warning = true;
+			pc--;
+			goto loop;
+		}
+		assert( false );
+	}
+
+	}
+	debug_printf( "Unhandled main opcode: $%02X\n", opcode );
+	assert( false );
+
+halt:
+	s_time &= 3; // increment by multiple of 4
+out_of_time:
+	pc--;
+
+	s.time   = s_time;
+	rg.flags = flags;
+	r.ix     = ix;
+	r.iy     = iy;
+	r.sp     = sp;
+	r.pc     = pc;
+	this->r.b = rg;
+	this->state_ = s;
+	this->state = &this->state_;
+
+	return warning;
+}
diff --git a/src/console/Ay_Cpu.cxx b/src/console/Ay_Cpu.cxx
deleted file mode 100644
index bee9eedf7e56..000000000000
--- a/src/console/Ay_Cpu.cxx
+++ /dev/null
@@ -1,1661 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.21 5:26 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Ay_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME()     (void) (s.time = s_time)
-#define RELOAD_TIME()   (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, TIME )\
-	ay_cpu_out( cpu, TIME, addr, data )
-
-#define CPU_IN( cpu, addr, TIME )\
-	ay_cpu_in( cpu, addr )
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n )  szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n )  (szpc [n] & ~P04)
-#define SZ28( n )   SZ28C( n )
-
-#define SET_R( n )  (void) (r.r = n)
-#define GET_R()     (r.r)
-
-Ay_Cpu::Ay_Cpu()
-{
-	state = &state_;
-	for ( int i = 0x100; --i >= 0; )
-	{
-		int even = 1;
-		for ( int p = i; p; p >>= 1 )
-			even ^= p;
-		int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
-		szpc [i] = n;
-		szpc [i + 0x100] = n | C01;
-	}
-	szpc [0x000] |= Z40;
-	szpc [0x100] |= Z40;
-}
-
-void Ay_Cpu::reset( void* m )
-{
-	mem = (uint8_t*) m;
-
-	check( state == &state_ );
-	state = &state_;
-	state_.time = 0;
-	state_.base = 0;
-	end_time_   = 0;
-
-	memset( &r, 0, sizeof r );
-}
-
-#define TIME                        (s_time + s.base)
-#define READ_PROG( addr )           (mem [addr])
-#define INSTR( offset )             READ_PROG( pc + (offset) )
-#define GET_ADDR()                  GET_LE16( &READ_PROG( pc ) )
-#define READ( addr )                READ_PROG( addr )
-#define WRITE( addr, data )         (void) (READ_PROG( addr ) = data)
-#define READ_WORD( addr )           GET_LE16( &READ_PROG( addr ) )
-#define WRITE_WORD( addr, data )    SET_LE16( &READ_PROG( addr ), data )
-#define IN( addr )                  CPU_IN( this, addr, TIME )
-#define OUT( addr, data )           CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
-	#define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
-	#define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
-	#error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset )   (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
-	(*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e          ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f       ) CASE5( a, b, c, d, e       ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g    ) CASE6( a, b, c, d, e, f    ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int         fint16;
-typedef unsigned    fuint16;
-typedef unsigned    fuint8;
-
-bool Ay_Cpu::run( cpu_time_t end_time )
-{
-	set_end_time( end_time );
-	state_t s = this->state_;
-	this->state = &s;
-	bool warning = false;
-
-	union {
-		regs_t rg;
-		pairs_t rp;
-		uint8_t r8_ [8]; // indexed
-		uint16_t r16_ [4];
-	};
-	rg = this->r.b;
-
-	cpu_time_t s_time = s.time;
-	uint8_t* const mem = this->mem; // cache
-	fuint16 pc = r.pc;
-	fuint16 sp = r.sp;
-	fuint16 ix = r.ix; // TODO: keep in memory for direct access?
-	fuint16 iy = r.iy;
-	int flags = r.b.flags;
-
-	goto loop;
-jr_not_taken:
-	s_time -= 5;
-	goto loop;
-call_not_taken:
-	s_time -= 7;
-jp_not_taken:
-	pc += 2;
-loop:
-
-	check( (unsigned long) pc < 0x10000 );
-	check( (unsigned long) sp < 0x10000 );
-	check( (unsigned) flags < 0x100 );
-	check( (unsigned) ix < 0x10000 );
-	check( (unsigned) iy < 0x10000 );
-
-	fuint8 opcode;
-	opcode = READ_PROG( pc );
-	pc++;
-
-	static byte const base_timing [0x100] = {
-	//   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
-		 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
-		13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
-		12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
-		12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
-		 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
-		11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
-		11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
-		11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
-		11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
-	};
-
-	fuint16 data;
-	data = base_timing [opcode];
-	if ( (s_time += data) >= 0 )
-		goto possibly_out_of_time;
-almost_out_of_time:
-
-	data = READ_PROG( pc );
-
-	#ifdef Z80_CPU_LOG_H
-		//log_opcode( opcode, READ_PROG( pc ) );
-		z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
-		z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
-				READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
-	#endif
-
-	switch ( opcode )
-	{
-possibly_out_of_time:
-		if ( s_time < (int) data )
-			goto almost_out_of_time;
-		s_time -= data;
-		goto out_of_time;
-
-// Common
-
-	case 0x00: // NOP
-	CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
-		goto loop;
-
-	case 0x08:{// EX AF,AF'
-		int temp = r.alt.b.a;
-		r.alt.b.a = rg.a;
-		rg.a = temp;
-
-		temp = r.alt.b.flags;
-		r.alt.b.flags = flags;
-		flags = temp;
-		goto loop;
-	}
-
-	case 0xD3: // OUT (imm),A
-		pc++;
-		OUT( data + rg.a * 0x100, rg.a );
-		goto loop;
-
-	case 0x2E: // LD L,imm
-		pc++;
-		rg.l = data;
-		goto loop;
-
-	case 0x3E: // LD A,imm
-		pc++;
-		rg.a = data;
-		goto loop;
-
-	case 0x3A:{// LD A,(addr)
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		rg.a = READ( addr );
-		goto loop;
-	}
-
-// Conditional
-
-#define ZERO    (flags & Z40)
-#define CARRY   (flags & C01)
-#define EVEN    (flags & P04)
-#define MINUS   (flags & S80)
-
-// JR
-#define JR( cond ) {\
-	int disp = (int8_t) data;\
-	pc++;\
-	if ( !(cond) )\
-		goto jr_not_taken;\
-	pc += disp;\
-	goto loop;\
-}
-
-	case 0x20: JR( !ZERO  ) // JR NZ,disp
-	case 0x28: JR(  ZERO  ) // JR Z,disp
-	case 0x30: JR( !CARRY ) // JR NC,disp
-	case 0x38: JR(  CARRY ) // JR C,disp
-	case 0x18: JR(  true  ) // JR disp
-
-	case 0x10:{// DJNZ disp
-		int temp = rg.b - 1;
-		rg.b = temp;
-		JR( temp )
-	}
-
-// JP
-#define JP( cond )  if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
-	case 0xC2: JP( !ZERO  ) // JP NZ,addr
-	case 0xCA: JP(  ZERO  ) // JP Z,addr
-	case 0xD2: JP( !CARRY ) // JP NC,addr
-	case 0xDA: JP(  CARRY ) // JP C,addr
-	case 0xE2: JP( !EVEN  ) // JP PO,addr
-	case 0xEA: JP(  EVEN  ) // JP PE,addr
-	case 0xF2: JP( !MINUS ) // JP P,addr
-	case 0xFA: JP(  MINUS ) // JP M,addr
-
-	case 0xC3: // JP addr
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xE9: // JP HL
-		pc = rp.hl;
-		goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
-	case 0xC0: RET( !ZERO  ) // RET NZ
-	case 0xC8: RET(  ZERO  ) // RET Z
-	case 0xD0: RET( !CARRY ) // RET NC
-	case 0xD8: RET(  CARRY ) // RET C
-	case 0xE0: RET( !EVEN  ) // RET PO
-	case 0xE8: RET(  EVEN  ) // RET PE
-	case 0xF0: RET( !MINUS ) // RET P
-	case 0xF8: RET(  MINUS ) // RET M
-
-	case 0xC9: // RET
-	ret_taken:
-		pc = READ_WORD( sp );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
-	case 0xC4: CALL( !ZERO  ) // CALL NZ,addr
-	case 0xCC: CALL(  ZERO  ) // CALL Z,addr
-	case 0xD4: CALL( !CARRY ) // CALL NC,addr
-	case 0xDC: CALL(  CARRY ) // CALL C,addr
-	case 0xE4: CALL( !EVEN  ) // CALL PO,addr
-	case 0xEC: CALL(  EVEN  ) // CALL PE,addr
-	case 0xF4: CALL( !MINUS ) // CALL P,addr
-	case 0xFC: CALL(  MINUS ) // CALL M,addr
-
-	case 0xCD:{// CALL addr
-	call_taken:
-		fuint16 addr = pc + 2;
-		pc = GET_ADDR();
-		sp = uint16_t (sp - 2);
-		WRITE_WORD( sp, addr );
-		goto loop;
-	}
-
-	case 0xFF: // RST
-		if ( (pc - 1) > 0xFFFF )
-		{
-			pc = uint16_t (pc - 1);
-			s_time -= 11;
-			goto loop;
-		}
-	CASE7( C7, CF, D7, DF, E7, EF, F7 ):
-		data = pc;
-		pc = opcode & 0x38;
-		goto push_data;
-
-// PUSH/POP
-	case 0xF5: // PUSH AF
-		data = rg.a * 0x100u + flags;
-		goto push_data;
-
-	case 0xC5: // PUSH BC
-	case 0xD5: // PUSH DE
-	case 0xE5: // PUSH HL
-		data = R16( opcode, 4, 0xC5 );
-	push_data:
-		sp = uint16_t (sp - 2);
-		WRITE_WORD( sp, data );
-		goto loop;
-
-	case 0xF1: // POP AF
-		flags = READ( sp );
-		rg.a = READ( sp + 1 );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-	case 0xC1: // POP BC
-	case 0xD1: // POP DE
-	case 0xE1: // POP HL
-		R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-// ADC/ADD/SBC/SUB
-	case 0x96: // SUB (HL)
-	case 0x86: // ADD (HL)
-		flags &= ~C01;
-	case 0x9E: // SBC (HL)
-	case 0x8E: // ADC (HL)
-		data = READ( rp.hl );
-		goto adc_data;
-
-	case 0xD6: // SUB A,imm
-	case 0xC6: // ADD imm
-		flags &= ~C01;
-	case 0xDE: // SBC A,imm
-	case 0xCE: // ADC imm
-		pc++;
-		goto adc_data;
-
-	CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
-	CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
-		flags &= ~C01;
-	CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
-	CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
-		data = R8( opcode & 7, 0 );
-	adc_data: {
-		int result = data + (flags & C01);
-		data ^= rg.a;
-		flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
-		if ( flags )
-			result = -result;
-		result += rg.a;
-		data ^= result;
-		flags |=(data & H10) |
-				((data - -0x80) >> 6 & V04) |
-				SZ28C( result & 0x1FF );
-		rg.a = result;
-		goto loop;
-	}
-
-// CP
-	case 0xBE: // CP (HL)
-		data = READ( rp.hl );
-		goto cp_data;
-
-	case 0xFE: // CP imm
-		pc++;
-		goto cp_data;
-
-	CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
-		data = R8( opcode, 0xB8 );
-	cp_data: {
-		int result = rg.a - data;
-		flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
-		data ^= rg.a;
-		flags |=(((result ^ rg.a) & data) >> 5 & V04) |
-				(((data & H10) ^ result) & (S80 | H10));
-		if ( (uint8_t) result )
-			goto loop;
-		flags |= Z40;
-		goto loop;
-	}
-
-// ADD HL,rp
-
-	case 0x39: // ADD HL,SP
-		data = sp;
-		goto add_hl_data;
-
-	case 0x09: // ADD HL,BC
-	case 0x19: // ADD HL,DE
-	case 0x29: // ADD HL,HL
-		data = R16( opcode, 4, 0x09 );
-	add_hl_data: {
-		blargg_ulong sum = rp.hl + data;
-		data ^= rp.hl;
-		rp.hl = sum;
-		flags = (flags & (S80 | Z40 | V04)) |
-				(sum >> 16) |
-				(sum >> 8 & (F20 | F08)) |
-				((data ^ sum) >> 8 & H10);
-		goto loop;
-	}
-
-	case 0x27:{// DAA
-		int a = rg.a;
-		if ( a > 0x99 )
-			flags |= C01;
-
-		int adjust = 0x60 & -(flags & C01);
-
-		if ( flags & H10 || (a & 0x0F) > 9 )
-			adjust |= 0x06;
-
-		if ( flags & N02 )
-			adjust = -adjust;
-		a += adjust;
-
-		flags = (flags & (C01 | N02)) |
-				((rg.a ^ a) & H10) |
-				SZ28P( (uint8_t) a );
-		rg.a = a;
-		goto loop;
-	}
-	/*
-	case 0x27:{// DAA
-		// more optimized, but probably not worth the obscurity
-		int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
-		int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
-		if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
-			adjust |= 0x06;
-
-		if ( f & N02 )
-			adjust = -adjust;
-		int a = rg.a + adjust;
-
-		flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
-		rg.a = a;
-		goto loop;
-	}
-	*/
-
-// INC/DEC
-	case 0x34: // INC (HL)
-		data = READ( rp.hl ) + 1;
-		WRITE( rp.hl, data );
-		goto inc_set_flags;
-
-	CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
-		data = ++R8( opcode >> 3, 0 );
-	inc_set_flags:
-		flags = (flags & C01) |
-				(((data & 0x0F) - 1) & H10) |
-				SZ28( (uint8_t) data );
-		if ( data != 0x80 )
-			goto loop;
-		flags |= V04;
-		goto loop;
-
-	case 0x35: // DEC (HL)
-		data = READ( rp.hl ) - 1;
-		WRITE( rp.hl, data );
-		goto dec_set_flags;
-
-	CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
-		data = --R8( opcode >> 3, 0 );
-	dec_set_flags:
-		flags = (flags & C01) | N02 |
-				(((data & 0x0F) + 1) & H10) |
-				SZ28( (uint8_t) data );
-		if ( data != 0x7F )
-			goto loop;
-		flags |= V04;
-		goto loop;
-
-	case 0x03: // INC BC
-	case 0x13: // INC DE
-	case 0x23: // INC HL
-		R16( opcode, 4, 0x03 )++;
-		goto loop;
-
-	case 0x33: // INC SP
-		sp = uint16_t (sp + 1);
-		goto loop;
-
-	case 0x0B: // DEC BC
-	case 0x1B: // DEC DE
-	case 0x2B: // DEC HL
-		R16( opcode, 4, 0x0B )--;
-		goto loop;
-
-	case 0x3B: // DEC SP
-		sp = uint16_t (sp - 1);
-		goto loop;
-
-// AND
-	case 0xA6: // AND (HL)
-		data = READ( rp.hl );
-		goto and_data;
-
-	case 0xE6: // AND imm
-		pc++;
-		goto and_data;
-
-	CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
-		data = R8( opcode, 0xA0 );
-	and_data:
-		rg.a &= data;
-		flags = SZ28P( rg.a ) | H10;
-		goto loop;
-
-// OR
-	case 0xB6: // OR (HL)
-		data = READ( rp.hl );
-		goto or_data;
-
-	case 0xF6: // OR imm
-		pc++;
-		goto or_data;
-
-	CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
-		data = R8( opcode, 0xB0 );
-	or_data:
-		rg.a |= data;
-		flags = SZ28P( rg.a );
-		goto loop;
-
-// XOR
-	case 0xAE: // XOR (HL)
-		data = READ( rp.hl );
-		goto xor_data;
-
-	case 0xEE: // XOR imm
-		pc++;
-		goto xor_data;
-
-	CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
-		data = R8( opcode, 0xA8 );
-	xor_data:
-		rg.a ^= data;
-		flags = SZ28P( rg.a );
-		goto loop;
-
-// LD
-	CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
-		WRITE( rp.hl, R8( opcode, 0x70 ) );
-		goto loop;
-
-	CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
-	CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
-	CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
-	CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
-	CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
-	CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
-	CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
-		R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
-		goto loop;
-
-	CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
-		R8( opcode >> 3, 0 ) = data;
-		pc++;
-		goto loop;
-
-	case 0x36: // LD (HL),imm
-		pc++;
-		WRITE( rp.hl, data );
-		goto loop;
-
-	CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
-		R8( opcode >> 3, 8 ) = READ( rp.hl );
-		goto loop;
-
-	case 0x01: // LD rp,imm
-	case 0x11:
-	case 0x21:
-		R16( opcode, 4, 0x01 ) = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x31: // LD sp,imm
-		sp = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x2A:{// LD HL,(addr)
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		rp.hl = READ_WORD( addr );
-		goto loop;
-	}
-
-	case 0x32:{// LD (addr),A
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		WRITE( addr, rg.a );
-		goto loop;
-	}
-
-	case 0x22:{// LD (addr),HL
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		WRITE_WORD( addr, rp.hl );
-		goto loop;
-	}
-
-	case 0x02: // LD (BC),A
-	case 0x12: // LD (DE),A
-		WRITE( R16( opcode, 4, 0x02 ), rg.a );
-		goto loop;
-
-	case 0x0A: // LD A,(BC)
-	case 0x1A: // LD A,(DE)
-		rg.a = READ( R16( opcode, 4, 0x0A ) );
-		goto loop;
-
-	case 0xF9: // LD SP,HL
-		sp = rp.hl;
-		goto loop;
-
-// Rotate
-
-	case 0x07:{// RLCA
-		fuint16 temp = rg.a;
-		temp = (temp << 1) | (temp >> 7);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08 | C01));
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x0F:{// RRCA
-		fuint16 temp = rg.a;
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & C01);
-		temp = (temp << 7) | (temp >> 1);
-		flags |= temp & (F20 | F08);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x17:{// RLA
-		blargg_ulong temp = (rg.a << 1) | (flags & C01);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08)) |
-				(temp >> 8);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x1F:{// RRA
-		fuint16 temp = (flags << 7) | (rg.a >> 1);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08)) |
-				(rg.a & C01);
-		rg.a = temp;
-		goto loop;
-	}
-
-// Misc
-	case 0x2F:{// CPL
-		fuint16 temp = ~rg.a;
-		flags = (flags & (S80 | Z40 | P04 | C01)) |
-				(temp & (F20 | F08)) |
-				(H10 | N02);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x3F:{// CCF
-		flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
-				(flags << 4 & H10) |
-				(rg.a & (F20 | F08));
-		goto loop;
-	}
-
-	case 0x37: // SCF
-		flags = (flags & (S80 | Z40 | P04)) | C01 |
-				(rg.a & (F20 | F08));
-		goto loop;
-
-	case 0xDB: // IN A,(imm)
-		pc++;
-		rg.a = IN( data + rg.a * 0x100 );
-		goto loop;
-
-	case 0xE3:{// EX (SP),HL
-		fuint16 temp = READ_WORD( sp );
-		WRITE_WORD( sp, rp.hl );
-		rp.hl = temp;
-		goto loop;
-	}
-
-	case 0xEB:{// EX DE,HL
-		fuint16 temp = rp.hl;
-		rp.hl = rp.de;
-		rp.de = temp;
-		goto loop;
-	}
-
-	case 0xD9:{// EXX DE,HL
-		fuint16 temp = r.alt.w.bc;
-		r.alt.w.bc = rp.bc;
-		rp.bc = temp;
-
-		temp = r.alt.w.de;
-		r.alt.w.de = rp.de;
-		rp.de = temp;
-
-		temp = r.alt.w.hl;
-		r.alt.w.hl = rp.hl;
-		rp.hl = temp;
-		goto loop;
-	}
-
-	case 0xF3: // DI
-		r.iff1 = 0;
-		r.iff2 = 0;
-		goto loop;
-
-	case 0xFB: // EI
-		r.iff1 = 1;
-		r.iff2 = 1;
-		// TODO: delayed effect
-		goto loop;
-
-	case 0x76: // HALT
-		goto halt;
-
-//////////////////////////////////////// CB prefix
-	{
-	case 0xCB:
-		pc++;
-		switch ( data )
-		{
-
-	// Rotate left
-
-	#define RLC( read, write ) {\
-		fuint8 result = read;\
-		result = uint8_t (result << 1) | (result >> 7);\
-		flags = SZ28P( result ) | (result & C01);\
-		write;\
-		goto loop;\
-	}
-
-		case 0x06: // RLC (HL)
-			s_time += 7;
-			data = rp.hl;
-		rlc_data_addr:
-			RLC( READ( data ), WRITE( data, result ) )
-
-		CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
-			uint8_t& reg = R8( data, 0 );
-			RLC( reg, reg = result )
-		}
-
-	#define RL( read, write ) {\
-		fuint16 result = (read << 1) | (flags & C01);\
-		flags = SZ28PC( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x16: // RL (HL)
-			s_time += 7;
-			data = rp.hl;
-		rl_data_addr:
-			RL( READ( data ), WRITE( data, result ) )
-
-		CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
-			uint8_t& reg = R8( data, 0x10 );
-			RL( reg, reg = result )
-		}
-
-	#define SLA( read, add, write ) {\
-		fuint16 result = (read << 1) | add;\
-		flags = SZ28PC( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x26: // SLA (HL)
-			s_time += 7;
-			data = rp.hl;
-		sla_data_addr:
-			SLA( READ( data ), 0, WRITE( data, result ) )
-
-		CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
-			uint8_t& reg = R8( data, 0x20 );
-			SLA( reg, 0, reg = result )
-		}
-
-		case 0x36: // SLL (HL)
-			s_time += 7;
-			data = rp.hl;
-		sll_data_addr:
-			SLA( READ( data ), 1, WRITE( data, result ) )
-
-		CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
-			uint8_t& reg = R8( data, 0x30 );
-			SLA( reg, 1, reg = result )
-		}
-
-	// Rotate right
-
-	#define RRC( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result = uint8_t (result << 7) | (result >> 1);\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x0E: // RRC (HL)
-			s_time += 7;
-			data = rp.hl;
-		rrc_data_addr:
-			RRC( READ( data ), WRITE( data, result ) )
-
-		CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
-			uint8_t& reg = R8( data, 0x08 );
-			RRC( reg, reg = result )
-		}
-
-	#define RR( read, write ) {\
-		fuint8 result = read;\
-		fuint8 temp = result & C01;\
-		result = uint8_t (flags << 7) | (result >> 1);\
-		flags = SZ28P( result ) | temp;\
-		write;\
-		goto loop;\
-	}
-
-		case 0x1E: // RR (HL)
-			s_time += 7;
-			data = rp.hl;
-		rr_data_addr:
-			RR( READ( data ), WRITE( data, result ) )
-
-		CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
-			uint8_t& reg = R8( data, 0x18 );
-			RR( reg, reg = result )
-		}
-
-	#define SRA( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result = (result & 0x80) | (result >> 1);\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x2E: // SRA (HL)
-			data = rp.hl;
-			s_time += 7;
-		sra_data_addr:
-			SRA( READ( data ), WRITE( data, result ) )
-
-		CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
-			uint8_t& reg = R8( data, 0x28 );
-			SRA( reg, reg = result )
-		}
-
-	#define SRL( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result >>= 1;\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x3E: // SRL (HL)
-			s_time += 7;
-			data = rp.hl;
-		srl_data_addr:
-			SRL( READ( data ), WRITE( data, result ) )
-
-		CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
-			uint8_t& reg = R8( data, 0x38 );
-			SRL( reg, reg = result )
-		}
-
-	// BIT
-		{
-			unsigned temp;
-		CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
-			s_time += 4;
-			temp = READ( rp.hl );
-			flags &= C01;
-			goto bit_temp;
-		CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
-		CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
-		CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
-		CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
-		CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
-		CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
-		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
-		CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
-			temp = R8( data & 7, 0 );
-			flags = (flags & C01) | (temp & (F20 | F08));
-		bit_temp:
-			int masked = temp & 1 << (data >> 3 & 7);
-			flags |=(masked & S80) | H10 |
-					((masked - 1) >> 8 & (Z40 | P04));
-			goto loop;
-		}
-
-	// SET/RES
-		CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
-		CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
-			s_time += 7;
-			int temp = READ( rp.hl );
-			int bit = 1 << (data >> 3 & 7);
-			temp |= bit; // SET
-			if ( !(data & 0x40) )
-				temp ^= bit; // RES
-			WRITE( rp.hl, temp );
-			goto loop;
-		}
-
-		CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
-		CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
-		CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
-		CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
-		CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
-		CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
-		CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
-		CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
-			R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
-			goto loop;
-
-		CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
-		CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
-		CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
-		CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
-		CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
-		CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
-		CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
-		CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
-			R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
-			goto loop;
-		}
-		assert( false );
-	}
-
-//////////////////////////////////////// ED prefix
-	{
-	case 0xED:
-		pc++;
-		s_time += ed_dd_timing [data] >> 4;
-		switch ( data )
-		{
-		{
-			blargg_ulong temp;
-		case 0x72: // SBC HL,SP
-		case 0x7A: // ADC HL,SP
-			temp = sp;
-			if ( 0 )
-		case 0x42: // SBC HL,BC
-		case 0x52: // SBC HL,DE
-		case 0x62: // SBC HL,HL
-		case 0x4A: // ADC HL,BC
-		case 0x5A: // ADC HL,DE
-		case 0x6A: // ADC HL,HL
-				temp = R16( data >> 3 & 6, 1, 0 );
-			blargg_ulong sum = temp + (flags & C01);
-			flags = ~data >> 2 & N02;
-			if ( flags )
-				sum = -sum;
-			sum += rp.hl;
-			temp ^= rp.hl;
-			temp ^= sum;
-			flags |=(sum >> 16 & C01) |
-					(temp >> 8 & H10) |
-					(sum >> 8 & (S80 | F20 | F08)) |
-					((temp - -0x8000) >> 14 & V04);
-			rp.hl = sum;
-			if ( (uint16_t) sum )
-				goto loop;
-			flags |= Z40;
-			goto loop;
-		}
-
-		CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
-			int temp = IN( rp.bc );
-			R8( data >> 3, 8 ) = temp;
-			flags = (flags & C01) | SZ28P( temp );
-			goto loop;
-		}
-
-		case 0x71: // OUT (C),0
-			rg.flags = 0;
-		CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
-			OUT( rp.bc, R8( data >> 3, 8 ) );
-			goto loop;
-
-		{
-			unsigned temp;
-		case 0x73: // LD (ADDR),SP
-			temp = sp;
-			if ( 0 )
-		case 0x43: // LD (ADDR),BC
-		case 0x53: // LD (ADDR),DE
-				temp = R16( data, 4, 0x43 );
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			WRITE_WORD( addr, temp );
-			goto loop;
-		}
-
-		case 0x4B: // LD BC,(ADDR)
-		case 0x5B:{// LD DE,(ADDR)
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			R16( data, 4, 0x4B ) = READ_WORD( addr );
-			goto loop;
-		}
-
-		case 0x7B:{// LD SP,(ADDR)
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			sp = READ_WORD( addr );
-			goto loop;
-		}
-
-		case 0x67:{// RRD
-			fuint8 temp = READ( rp.hl );
-			WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
-			temp = (rg.a & 0xF0) | (temp & 0x0F);
-			flags = (flags & C01) | SZ28P( temp );
-			rg.a = temp;
-			goto loop;
-		}
-
-		case 0x6F:{// RLD
-			fuint8 temp = READ( rp.hl );
-			WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
-			temp = (rg.a & 0xF0) | (temp >> 4);
-			flags = (flags & C01) | SZ28P( temp );
-			rg.a = temp;
-			goto loop;
-		}
-
-		CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
-			opcode = 0x10; // flag to do SBC instead of ADC
-			flags &= ~C01;
-			data = rg.a;
-			rg.a = 0;
-			goto adc_data;
-
-		{
-			int inc;
-		case 0xA9: // CPD
-		case 0xB9: // CPDR
-			inc = -1;
-			if ( 0 )
-		case 0xA1: // CPI
-		case 0xB1: // CPIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			int result = rg.a - temp;
-			flags = (flags & C01) | N02 |
-					((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
-			if ( !(uint8_t) result ) flags |= Z40;
-			result -= (flags & H10) >> 4;
-			flags |= result & F08;
-			flags |= result << 4 & F20;
-			if ( !--rp.bc )
-				goto loop;
-
-			flags |= V04;
-			if ( flags & Z40 || data < 0xB0 )
-				goto loop;
-
-			pc -= 2;
-			s_time += 5;
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xA8: // LDD
-		case 0xB8: // LDDR
-			inc = -1;
-			if ( 0 )
-		case 0xA0: // LDI
-		case 0xB0: // LDIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			addr = rp.de;
-			rp.de = addr + inc;
-			WRITE( addr, temp );
-
-			temp += rg.a;
-			flags = (flags & (S80 | Z40 | C01)) |
-					(temp & F08) | (temp << 4 & F20);
-			if ( !--rp.bc )
-				goto loop;
-
-			flags |= V04;
-			if ( data < 0xB0 )
-				goto loop;
-
-			pc -= 2;
-			s_time += 5;
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xAB: // OUTD
-		case 0xBB: // OTDR
-			inc = -1;
-			if ( 0 )
-		case 0xA3: // OUTI
-		case 0xB3: // OTIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			int b = --rg.b;
-			flags = (temp >> 6 & N02) | SZ28( b );
-			if ( b && data >= 0xB0 )
-			{
-				pc -= 2;
-				s_time += 5;
-			}
-
-			OUT( rp.bc, temp );
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xAA: // IND
-		case 0xBA: // INDR
-			inc = -1;
-			if ( 0 )
-		case 0xA2: // INI
-		case 0xB2: // INIR
-				inc = +1;
-
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-
-			int temp = IN( rp.bc );
-
-			int b = --rg.b;
-			flags = (temp >> 6 & N02) | SZ28( b );
-			if ( b && data >= 0xB0 )
-			{
-				pc -= 2;
-				s_time += 5;
-			}
-
-			WRITE( addr, temp );
-			goto loop;
-		}
-
-		case 0x47: // LD I,A
-			r.i = rg.a;
-			goto loop;
-
-		case 0x4F: // LD R,A
-			SET_R( rg.a );
-			debug_printf( "LD R,A not supported\n" );
-			warning = true;
-			goto loop;
-
-		case 0x57: // LD A,I
-			rg.a = r.i;
-			goto ld_ai_common;
-
-		case 0x5F: // LD A,R
-			rg.a = GET_R();
-			debug_printf( "LD A,R not supported\n" );
-			warning = true;
-		ld_ai_common:
-			flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
-			goto loop;
-
-		CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
-			r.iff1 = r.iff2;
-			goto ret_taken;
-
-		case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
-			r.im = 0;
-			goto loop;
-
-		case 0x56: case 0x76: // IM 1
-			r.im = 1;
-			goto loop;
-
-		case 0x5E: case 0x7E: // IM 2
-			r.im = 2;
-			goto loop;
-
-		default:
-			debug_printf( "Opcode $ED $%02X not supported\n", data );
-			warning = true;
-			goto loop;
-		}
-		assert( false );
-	}
-
-//////////////////////////////////////// DD/FD prefix
-	{
-	fuint16 ixy;
-	case 0xDD:
-		ixy = ix;
-		goto ix_prefix;
-	case 0xFD:
-		ixy = iy;
-	ix_prefix:
-		pc++;
-		unsigned data2 = READ_PROG( pc );
-		s_time += ed_dd_timing [data] & 0x0F;
-		switch ( data )
-		{
-	// TODO: more efficient way of avoid negative address
-	#define IXY_DISP( ixy, disp )   uint16_t ((ixy) + (disp))
-
-	#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
-	// ADD/ADC/SUB/SBC
-
-		case 0x96: // SUB (IXY+disp)
-		case 0x86: // ADD (IXY+disp)
-			flags &= ~C01;
-		case 0x9E: // SBC (IXY+disp)
-		case 0x8E: // ADC (IXY+disp)
-			pc++;
-			opcode = data;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto adc_data;
-
-		case 0x94: // SUB HXY
-		case 0x84: // ADD HXY
-			flags &= ~C01;
-		case 0x9C: // SBC HXY
-		case 0x8C: // ADC HXY
-			opcode = data;
-			data = ixy >> 8;
-			goto adc_data;
-
-		case 0x95: // SUB LXY
-		case 0x85: // ADD LXY
-			flags &= ~C01;
-		case 0x9D: // SBC LXY
-		case 0x8D: // ADC LXY
-			opcode = data;
-			data = (uint8_t) ixy;
-			goto adc_data;
-
-		{
-			unsigned temp;
-		case 0x39: // ADD IXY,SP
-			temp = sp;
-			goto add_ixy_data;
-
-		case 0x29: // ADD IXY,HL
-			temp = ixy;
-			goto add_ixy_data;
-
-		case 0x09: // ADD IXY,BC
-		case 0x19: // ADD IXY,DE
-			temp = R16( data, 4, 0x09 );
-		add_ixy_data: {
-			blargg_ulong sum = ixy + temp;
-			temp ^= ixy;
-			ixy = (uint16_t) sum;
-			flags = (flags & (S80 | Z40 | V04)) |
-					(sum >> 16) |
-					(sum >> 8 & (F20 | F08)) |
-					((temp ^ sum) >> 8 & H10);
-			goto set_ixy;
-		}
-		}
-
-	// AND
-		case 0xA6: // AND (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto and_data;
-
-		case 0xA4: // AND HXY
-			data = ixy >> 8;
-			goto and_data;
-
-		case 0xA5: // AND LXY
-			data = (uint8_t) ixy;
-			goto and_data;
-
-	// OR
-		case 0xB6: // OR (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto or_data;
-
-		case 0xB4: // OR HXY
-			data = ixy >> 8;
-			goto or_data;
-
-		case 0xB5: // OR LXY
-			data = (uint8_t) ixy;
-			goto or_data;
-
-	// XOR
-		case 0xAE: // XOR (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto xor_data;
-
-		case 0xAC: // XOR HXY
-			data = ixy >> 8;
-			goto xor_data;
-
-		case 0xAD: // XOR LXY
-			data = (uint8_t) ixy;
-			goto xor_data;
-
-	// CP
-		case 0xBE: // CP (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 )  );
-			goto cp_data;
-
-		case 0xBC: // CP HXY
-			data = ixy >> 8;
-			goto cp_data;
-
-		case 0xBD: // CP LXY
-			data = (uint8_t) ixy;
-			goto cp_data;
-
-	// LD
-		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
-			data = R8( data, 0x70 );
-			if ( 0 )
-		case 0x36: // LD (IXY+disp),imm
-				pc++, data = READ_PROG( pc );
-			pc++;
-			WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
-			goto loop;
-
-		CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
-			R8( data >> 3, 8 ) = ixy >> 8;
-			goto loop;
-
-		case 0x64: // LD HXY,HXY
-		case 0x6D: // LD LXY,LXY
-			goto loop;
-
-		CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
-			R8( data >> 3, 8 ) = ixy;
-			goto loop;
-
-		CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
-			pc++;
-			R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto loop;
-
-		case 0x26: // LD HXY,imm
-			pc++;
-			goto ld_hxy_data;
-
-		case 0x65: // LD HXY,LXY
-			data2 = (uint8_t) ixy;
-			goto ld_hxy_data;
-
-		CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
-			data2 = R8( data, 0x60 );
-		ld_hxy_data:
-			ixy = (uint8_t) ixy | (data2 << 8);
-			goto set_ixy;
-
-		case 0x2E: // LD LXY,imm
-			pc++;
-			goto ld_lxy_data;
-
-		case 0x6C: // LD LXY,HXY
-			data2 = ixy >> 8;
-			goto ld_lxy_data;
-
-		CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
-			data2 = R8( data, 0x68 );
-		ld_lxy_data:
-			ixy = (ixy & 0xFF00) | data2;
-		set_ixy:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto loop;
-			}
-			iy = ixy;
-			goto loop;
-
-		case 0xF9: // LD SP,IXY
-			sp = ixy;
-			goto loop;
-
-		case 0x22:{// LD (ADDR),IXY
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			WRITE_WORD( addr, ixy );
-			goto loop;
-		}
-
-		case 0x21: // LD IXY,imm
-			ixy = GET_ADDR();
-			pc += 2;
-			goto set_ixy;
-
-		case 0x2A:{// LD IXY,(addr)
-			fuint16 addr = GET_ADDR();
-			ixy = READ_WORD( addr );
-			pc += 2;
-			goto set_ixy;
-		}
-
-	// DD/FD CB prefix
-		case 0xCB: {
-			data = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data2 = READ_PROG( pc );
-			pc++;
-			switch ( data2 )
-			{
-			case 0x06: goto rlc_data_addr; // RLC (IXY)
-			case 0x16: goto rl_data_addr;  // RL (IXY)
-			case 0x26: goto sla_data_addr; // SLA (IXY)
-			case 0x36: goto sll_data_addr; // SLL (IXY)
-			case 0x0E: goto rrc_data_addr; // RRC (IXY)
-			case 0x1E: goto rr_data_addr;  // RR (IXY)
-			case 0x2E: goto sra_data_addr; // SRA (IXY)
-			case 0x3E: goto srl_data_addr; // SRL (IXY)
-
-			CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
-				fuint8 temp = READ( data );
-				int masked = temp & 1 << (data2 >> 3 & 7);
-				flags = (flags & C01) | H10 |
-						(masked & S80) |
-						((masked - 1) >> 8 & (Z40 | P04));
-				goto loop;
-			}
-
-			CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
-			CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
-				int temp = READ( data );
-				int bit = 1 << (data2 >> 3 & 7);
-				temp |= bit; // SET
-				if ( !(data2 & 0x40) )
-					temp ^= bit; // RES
-				WRITE( data, temp );
-				goto loop;
-			}
-
-			default:
-				debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
-				warning = true;
-				goto loop;
-			}
-			assert( false );
-		}
-
-	// INC/DEC
-		case 0x23: // INC IXY
-			ixy = uint16_t (ixy + 1);
-			goto set_ixy;
-
-		case 0x2B: // DEC IXY
-			ixy = uint16_t (ixy - 1);
-			goto set_ixy;
-
-		case 0x34: // INC (IXY+disp)
-			ixy = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data = READ( ixy ) + 1;
-			WRITE( ixy, data );
-			goto inc_set_flags;
-
-		case 0x35: // DEC (IXY+disp)
-			ixy = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data = READ( ixy ) - 1;
-			WRITE( ixy, data );
-			goto dec_set_flags;
-
-		case 0x24: // INC HXY
-			ixy = uint16_t (ixy + 0x100);
-			data = ixy >> 8;
-			goto inc_xy_common;
-
-		case 0x2C: // INC LXY
-			data = uint8_t (ixy + 1);
-			ixy = (ixy & 0xFF00) | data;
-		inc_xy_common:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto inc_set_flags;
-			}
-			iy = ixy;
-			goto inc_set_flags;
-
-		case 0x25: // DEC HXY
-			ixy = uint16_t (ixy - 0x100);
-			data = ixy >> 8;
-			goto dec_xy_common;
-
-		case 0x2D: // DEC LXY
-			data = uint8_t (ixy - 1);
-			ixy = (ixy & 0xFF00) | data;
-		dec_xy_common:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto dec_set_flags;
-			}
-			iy = ixy;
-			goto dec_set_flags;
-
-	// PUSH/POP
-		case 0xE5: // PUSH IXY
-			data = ixy;
-			goto push_data;
-
-		case 0xE1:{// POP IXY
-			ixy = READ_WORD( sp );
-			sp = uint16_t (sp + 2);
-			goto set_ixy;
-		}
-
-	// Misc
-
-		case 0xE9: // JP (IXY)
-			pc = ixy;
-			goto loop;
-
-		case 0xE3:{// EX (SP),IXY
-			fuint16 temp = READ_WORD( sp );
-			WRITE_WORD( sp, ixy );
-			ixy = temp;
-			goto set_ixy;
-		}
-
-		default:
-			debug_printf( "Unnecessary DD/FD prefix encountered\n" );
-			warning = true;
-			pc--;
-			goto loop;
-		}
-		assert( false );
-	}
-
-	}
-	debug_printf( "Unhandled main opcode: $%02X\n", opcode );
-	assert( false );
-
-halt:
-	s_time &= 3; // increment by multiple of 4
-out_of_time:
-	pc--;
-
-	s.time   = s_time;
-	rg.flags = flags;
-	r.ix     = ix;
-	r.iy     = iy;
-	r.sp     = sp;
-	r.pc     = pc;
-	this->r.b = rg;
-	this->state_ = s;
-	this->state = &this->state_;
-
-	return warning;
-}
diff --git a/src/console/Ay_Emu.cc b/src/console/Ay_Emu.cc
new file mode 100644
index 000000000000..663842d09f07
--- /dev/null
+++ b/src/console/Ay_Emu.cc
@@ -0,0 +1,405 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Ay_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+long const spectrum_clock = 3546900;
+long const cpc_clock      = 2000000;
+
+unsigned const ram_start = 0x4000;
+int const osc_count = Ay_Apu::osc_count + 1;
+
+Ay_Emu::Ay_Emu()
+{
+	beeper_output = 0;
+	set_type( gme_ay_type );
+
+	static const char* const names [osc_count] = {
+		"Wave 1", "Wave 2", "Wave 3", "Beeper"
+	};
+	set_voice_names( names );
+
+	static int const types [osc_count] = {
+		wave_type | 0, wave_type | 1, wave_type | 2, mixed_type | 0
+	};
+	set_voice_types( types );
+	set_silence_lookahead( 6 );
+}
+
+Ay_Emu::~Ay_Emu() { }
+
+// Track info
+
+static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size )
+{
+	long pos = ptr - (byte const*) file.header;
+	long file_size = file.end - (byte const*) file.header;
+	assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
+	int offset = (int16_t) GET_BE16( ptr );
+	if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
+		return 0;
+	return ptr + offset;
+}
+
+static blargg_err_t parse_header( byte const* in, long size, Ay_Emu::file_t* out )
+{
+	typedef Ay_Emu::header_t header_t;
+	out->header = (header_t const*) in;
+	out->end    = in + size;
+
+	if ( size < Ay_Emu::header_size )
+		return gme_wrong_file_type;
+
+	header_t const& h = *(header_t const*) in;
+	if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
+		return gme_wrong_file_type;
+
+	out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
+	if ( !out->tracks )
+		return "Missing track data";
+
+	return 0;
+}
+
+static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
+{
+	Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
+	byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
+	if ( track_info )
+		out->length = GET_BE16( track_info + 4 ) * (1000L / 50); // frames to msec
+
+	Gme_File::copy_field_( out->author,  (char const*) get_data( file, file.header->author, 1 ) );
+	Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
+}
+
+blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
+{
+	copy_ay_fields( file, out, track );
+	return 0;
+}
+
+struct Ay_File : Gme_Info_
+{
+	Ay_Emu::file_t file;
+
+	Ay_File() { set_type( gme_ay_type ); }
+
+	blargg_err_t load_mem_( byte const* begin, long size )
+	{
+		RETURN_ERR( parse_header( begin, size, &file ) );
+		set_track_count( file.header->max_track + 1 );
+		return 0;
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int track ) const
+	{
+		copy_ay_fields( file, out, track );
+		return 0;
+	}
+};
+
+static Music_Emu* new_ay_emu () { return BLARGG_NEW Ay_Emu ; }
+static Music_Emu* new_ay_file() { return BLARGG_NEW Ay_File; }
+
+static gme_type_t_ const gme_ay_type_ = { "ZX Spectrum", 0, &new_ay_emu, &new_ay_file, "AY", 1 };
+gme_type_t const gme_ay_type = &gme_ay_type_;
+
+// Setup
+
+blargg_err_t Ay_Emu::load_mem_( byte const* in, long size )
+{
+	assert( offsetof (header_t,track_info [2]) == header_size );
+
+	RETURN_ERR( parse_header( in, size, &file ) );
+	set_track_count( file.header->max_track + 1 );
+
+	if ( file.header->vers > 2 )
+		set_warning( "Unknown file version" );
+
+	set_voice_count( osc_count );
+	apu.volume( gain() );
+
+	return setup_buffer( spectrum_clock );
+}
+
+void Ay_Emu::update_eq( blip_eq_t const& eq )
+{
+	apu.treble_eq( eq );
+}
+
+void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
+{
+	if ( i >= Ay_Apu::osc_count )
+		beeper_output = center;
+	else
+		apu.osc_output( i, center );
+}
+
+// Emulation
+
+void Ay_Emu::set_tempo_( double t )
+{
+	play_period = blip_time_t (clock_rate() / 50 / t);
+}
+
+blargg_err_t Ay_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( mem.ram + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
+	memset( mem.ram + 0x0100, 0xFF, 0x4000 - 0x100 );
+	memset( mem.ram + ram_start, 0x00, sizeof mem.ram - ram_start );
+	memset( mem.padding1, 0xFF, sizeof mem.padding1 );
+	memset( mem.ram + 0x10000, 0xFF, sizeof mem.ram - 0x10000 );
+
+	// locate data blocks
+	byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
+	if ( !data ) return "File data missing";
+
+	byte const* const more_data = get_data( file, data + 10, 6 );
+	if ( !more_data ) return "File data missing";
+
+	byte const* blocks = get_data( file, data + 12, 8 );
+	if ( !blocks ) return "File data missing";
+
+	// initial addresses
+	cpu::reset( mem.ram );
+	r.sp = GET_BE16( more_data );
+	r.b.a = r.b.b = r.b.d = r.b.h = data [8];
+	r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
+	r.alt.w = r.w;
+	r.ix = r.iy = r.w.hl;
+
+	unsigned addr = GET_BE16( blocks );
+	if ( !addr ) return "File data missing";
+
+	unsigned init = GET_BE16( more_data + 2 );
+	if ( !init )
+		init = addr;
+
+	// copy blocks into memory
+	do
+	{
+		blocks += 2;
+		unsigned len = GET_BE16( blocks ); blocks += 2;
+		if ( addr + len > 0x10000 )
+		{
+			set_warning( "Bad data block size" );
+			len = 0x10000 - addr;
+		}
+		check( len );
+		byte const* in = get_data( file, blocks, 0 ); blocks += 2;
+		if ( len > blargg_ulong (file.end - in) )
+		{
+			set_warning( "Missing file data" );
+			len = file.end - in;
+		}
+		//debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
+		if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
+			debug_printf( "Block addr in ROM\n" );
+		memcpy( mem.ram + addr, in, len );
+
+		if ( file.end - blocks < 8 )
+		{
+			set_warning( "Missing file data" );
+			break;
+		}
+	}
+	while ( (addr = GET_BE16( blocks )) != 0 );
+
+	// copy and configure driver
+	static byte const passive [] = {
+		0xF3,       // DI
+		0xCD, 0, 0, // CALL init
+		0xED, 0x5E, // LOOP: IM 2
+		0xFB,       // EI
+		0x76,       // HALT
+		0x18, 0xFA  // JR LOOP
+	};
+	static byte const active [] = {
+		0xF3,       // DI
+		0xCD, 0, 0, // CALL init
+		0xED, 0x56, // LOOP: IM 1
+		0xFB,       // EI
+		0x76,       // HALT
+		0xCD, 0, 0, // CALL play
+		0x18, 0xF7  // JR LOOP
+	};
+	memcpy( mem.ram, passive, sizeof passive );
+	unsigned play_addr = GET_BE16( more_data + 4 );
+	//debug_printf( "Play: $%04X\n", play_addr );
+	if ( play_addr )
+	{
+		memcpy( mem.ram, active, sizeof active );
+		mem.ram [ 9] = play_addr;
+		mem.ram [10] = play_addr >> 8;
+	}
+	mem.ram [2] = init;
+	mem.ram [3] = init >> 8;
+
+	mem.ram [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
+
+	memcpy( mem.ram + 0x10000, mem.ram, 0x80 ); // some code wraps around (ugh)
+
+	beeper_delta = int (apu.amp_range * 0.65);
+	last_beeper = 0;
+	apu.reset();
+	next_play = play_period;
+
+	// start at spectrum speed
+	change_clock_rate( spectrum_clock );
+	set_tempo( tempo() );
+
+	spectrum_mode = false;
+	cpc_mode      = false;
+	cpc_latch     = 0;
+
+	return 0;
+}
+
+// Emulation
+
+void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
+{
+	if ( !cpc_mode )
+	{
+		switch ( addr & 0xFEFF )
+		{
+		case 0xFEFD:
+			spectrum_mode = true;
+			apu_addr = data & 0x0F;
+			return;
+
+		case 0xBEFD:
+			spectrum_mode = true;
+			apu.write( time, apu_addr, data );
+			return;
+		}
+	}
+
+	if ( !spectrum_mode )
+	{
+		switch ( addr >> 8 )
+		{
+		case 0xF6:
+			switch ( data & 0xC0 )
+			{
+			case 0xC0:
+				apu_addr = cpc_latch & 0x0F;
+				goto enable_cpc;
+
+			case 0x80:
+				apu.write( time, apu_addr, cpc_latch );
+				goto enable_cpc;
+			}
+			break;
+
+		case 0xF4:
+			cpc_latch = data;
+			goto enable_cpc;
+		}
+	}
+
+	debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
+	return;
+
+enable_cpc:
+	if ( !cpc_mode )
+	{
+		cpc_mode = true;
+		change_clock_rate( cpc_clock );
+		set_tempo( tempo() );
+	}
+}
+
+void ay_cpu_out( Ay_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
+{
+	Ay_Emu& emu = STATIC_CAST(Ay_Emu&,*cpu);
+
+	if ( (addr & 0xFF) == 0xFE && !emu.cpc_mode )
+	{
+		int delta = emu.beeper_delta;
+		data &= 0x10;
+		if ( emu.last_beeper != data )
+		{
+			emu.last_beeper = data;
+			emu.beeper_delta = -delta;
+			emu.spectrum_mode = true;
+			if ( emu.beeper_output )
+				emu.apu.synth_.offset( time, delta, emu.beeper_output );
+		}
+	}
+	else
+	{
+		emu.cpu_out_misc( time, addr, data );
+	}
+}
+
+int ay_cpu_in( Ay_Cpu*, unsigned addr )
+{
+	// keyboard read and other things
+	if ( (addr & 0xFF) == 0xFE )
+		return 0xFF; // other values break some beeper tunes
+
+	debug_printf( "Unmapped IN : $%04X\n", addr );
+	return 0xFF;
+}
+
+blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
+{
+	set_time( 0 );
+	if ( !(spectrum_mode | cpc_mode) )
+		duration /= 2; // until mode is set, leave room for halved clock rate
+
+	while ( time() < duration )
+	{
+		cpu::run( min( duration, (blip_time_t) next_play ) );
+
+		if ( time() >= next_play )
+		{
+			next_play += play_period;
+
+			if ( r.iff1 )
+			{
+				if ( mem.ram [r.pc] == 0x76 )
+					r.pc++;
+
+				r.iff1 = r.iff2 = 0;
+
+				mem.ram [--r.sp] = uint8_t (r.pc >> 8);
+				mem.ram [--r.sp] = uint8_t (r.pc);
+				r.pc = 0x38;
+				cpu::adjust_time( 12 );
+				if ( r.im == 2 )
+				{
+					cpu::adjust_time( 6 );
+					unsigned addr = r.i * 0x100u + 0xFF;
+					r.pc = mem.ram [(addr + 1) & 0xFFFF] * 0x100u + mem.ram [addr];
+				}
+			}
+		}
+	}
+	duration = time();
+	next_play -= duration;
+	check( next_play >= 0 );
+	adjust_time( -duration );
+
+	apu.end_frame( duration );
+
+	return 0;
+}
diff --git a/src/console/Ay_Emu.cxx b/src/console/Ay_Emu.cxx
deleted file mode 100644
index 663842d09f07..000000000000
--- a/src/console/Ay_Emu.cxx
+++ /dev/null
@@ -1,405 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Ay_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const spectrum_clock = 3546900;
-long const cpc_clock      = 2000000;
-
-unsigned const ram_start = 0x4000;
-int const osc_count = Ay_Apu::osc_count + 1;
-
-Ay_Emu::Ay_Emu()
-{
-	beeper_output = 0;
-	set_type( gme_ay_type );
-
-	static const char* const names [osc_count] = {
-		"Wave 1", "Wave 2", "Wave 3", "Beeper"
-	};
-	set_voice_names( names );
-
-	static int const types [osc_count] = {
-		wave_type | 0, wave_type | 1, wave_type | 2, mixed_type | 0
-	};
-	set_voice_types( types );
-	set_silence_lookahead( 6 );
-}
-
-Ay_Emu::~Ay_Emu() { }
-
-// Track info
-
-static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size )
-{
-	long pos = ptr - (byte const*) file.header;
-	long file_size = file.end - (byte const*) file.header;
-	assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
-	int offset = (int16_t) GET_BE16( ptr );
-	if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
-		return 0;
-	return ptr + offset;
-}
-
-static blargg_err_t parse_header( byte const* in, long size, Ay_Emu::file_t* out )
-{
-	typedef Ay_Emu::header_t header_t;
-	out->header = (header_t const*) in;
-	out->end    = in + size;
-
-	if ( size < Ay_Emu::header_size )
-		return gme_wrong_file_type;
-
-	header_t const& h = *(header_t const*) in;
-	if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
-		return gme_wrong_file_type;
-
-	out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
-	if ( !out->tracks )
-		return "Missing track data";
-
-	return 0;
-}
-
-static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
-{
-	Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
-	byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
-	if ( track_info )
-		out->length = GET_BE16( track_info + 4 ) * (1000L / 50); // frames to msec
-
-	Gme_File::copy_field_( out->author,  (char const*) get_data( file, file.header->author, 1 ) );
-	Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
-}
-
-blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
-{
-	copy_ay_fields( file, out, track );
-	return 0;
-}
-
-struct Ay_File : Gme_Info_
-{
-	Ay_Emu::file_t file;
-
-	Ay_File() { set_type( gme_ay_type ); }
-
-	blargg_err_t load_mem_( byte const* begin, long size )
-	{
-		RETURN_ERR( parse_header( begin, size, &file ) );
-		set_track_count( file.header->max_track + 1 );
-		return 0;
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int track ) const
-	{
-		copy_ay_fields( file, out, track );
-		return 0;
-	}
-};
-
-static Music_Emu* new_ay_emu () { return BLARGG_NEW Ay_Emu ; }
-static Music_Emu* new_ay_file() { return BLARGG_NEW Ay_File; }
-
-static gme_type_t_ const gme_ay_type_ = { "ZX Spectrum", 0, &new_ay_emu, &new_ay_file, "AY", 1 };
-gme_type_t const gme_ay_type = &gme_ay_type_;
-
-// Setup
-
-blargg_err_t Ay_Emu::load_mem_( byte const* in, long size )
-{
-	assert( offsetof (header_t,track_info [2]) == header_size );
-
-	RETURN_ERR( parse_header( in, size, &file ) );
-	set_track_count( file.header->max_track + 1 );
-
-	if ( file.header->vers > 2 )
-		set_warning( "Unknown file version" );
-
-	set_voice_count( osc_count );
-	apu.volume( gain() );
-
-	return setup_buffer( spectrum_clock );
-}
-
-void Ay_Emu::update_eq( blip_eq_t const& eq )
-{
-	apu.treble_eq( eq );
-}
-
-void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
-{
-	if ( i >= Ay_Apu::osc_count )
-		beeper_output = center;
-	else
-		apu.osc_output( i, center );
-}
-
-// Emulation
-
-void Ay_Emu::set_tempo_( double t )
-{
-	play_period = blip_time_t (clock_rate() / 50 / t);
-}
-
-blargg_err_t Ay_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( mem.ram + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
-	memset( mem.ram + 0x0100, 0xFF, 0x4000 - 0x100 );
-	memset( mem.ram + ram_start, 0x00, sizeof mem.ram - ram_start );
-	memset( mem.padding1, 0xFF, sizeof mem.padding1 );
-	memset( mem.ram + 0x10000, 0xFF, sizeof mem.ram - 0x10000 );
-
-	// locate data blocks
-	byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
-	if ( !data ) return "File data missing";
-
-	byte const* const more_data = get_data( file, data + 10, 6 );
-	if ( !more_data ) return "File data missing";
-
-	byte const* blocks = get_data( file, data + 12, 8 );
-	if ( !blocks ) return "File data missing";
-
-	// initial addresses
-	cpu::reset( mem.ram );
-	r.sp = GET_BE16( more_data );
-	r.b.a = r.b.b = r.b.d = r.b.h = data [8];
-	r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
-	r.alt.w = r.w;
-	r.ix = r.iy = r.w.hl;
-
-	unsigned addr = GET_BE16( blocks );
-	if ( !addr ) return "File data missing";
-
-	unsigned init = GET_BE16( more_data + 2 );
-	if ( !init )
-		init = addr;
-
-	// copy blocks into memory
-	do
-	{
-		blocks += 2;
-		unsigned len = GET_BE16( blocks ); blocks += 2;
-		if ( addr + len > 0x10000 )
-		{
-			set_warning( "Bad data block size" );
-			len = 0x10000 - addr;
-		}
-		check( len );
-		byte const* in = get_data( file, blocks, 0 ); blocks += 2;
-		if ( len > blargg_ulong (file.end - in) )
-		{
-			set_warning( "Missing file data" );
-			len = file.end - in;
-		}
-		//debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
-		if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
-			debug_printf( "Block addr in ROM\n" );
-		memcpy( mem.ram + addr, in, len );
-
-		if ( file.end - blocks < 8 )
-		{
-			set_warning( "Missing file data" );
-			break;
-		}
-	}
-	while ( (addr = GET_BE16( blocks )) != 0 );
-
-	// copy and configure driver
-	static byte const passive [] = {
-		0xF3,       // DI
-		0xCD, 0, 0, // CALL init
-		0xED, 0x5E, // LOOP: IM 2
-		0xFB,       // EI
-		0x76,       // HALT
-		0x18, 0xFA  // JR LOOP
-	};
-	static byte const active [] = {
-		0xF3,       // DI
-		0xCD, 0, 0, // CALL init
-		0xED, 0x56, // LOOP: IM 1
-		0xFB,       // EI
-		0x76,       // HALT
-		0xCD, 0, 0, // CALL play
-		0x18, 0xF7  // JR LOOP
-	};
-	memcpy( mem.ram, passive, sizeof passive );
-	unsigned play_addr = GET_BE16( more_data + 4 );
-	//debug_printf( "Play: $%04X\n", play_addr );
-	if ( play_addr )
-	{
-		memcpy( mem.ram, active, sizeof active );
-		mem.ram [ 9] = play_addr;
-		mem.ram [10] = play_addr >> 8;
-	}
-	mem.ram [2] = init;
-	mem.ram [3] = init >> 8;
-
-	mem.ram [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
-
-	memcpy( mem.ram + 0x10000, mem.ram, 0x80 ); // some code wraps around (ugh)
-
-	beeper_delta = int (apu.amp_range * 0.65);
-	last_beeper = 0;
-	apu.reset();
-	next_play = play_period;
-
-	// start at spectrum speed
-	change_clock_rate( spectrum_clock );
-	set_tempo( tempo() );
-
-	spectrum_mode = false;
-	cpc_mode      = false;
-	cpc_latch     = 0;
-
-	return 0;
-}
-
-// Emulation
-
-void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
-{
-	if ( !cpc_mode )
-	{
-		switch ( addr & 0xFEFF )
-		{
-		case 0xFEFD:
-			spectrum_mode = true;
-			apu_addr = data & 0x0F;
-			return;
-
-		case 0xBEFD:
-			spectrum_mode = true;
-			apu.write( time, apu_addr, data );
-			return;
-		}
-	}
-
-	if ( !spectrum_mode )
-	{
-		switch ( addr >> 8 )
-		{
-		case 0xF6:
-			switch ( data & 0xC0 )
-			{
-			case 0xC0:
-				apu_addr = cpc_latch & 0x0F;
-				goto enable_cpc;
-
-			case 0x80:
-				apu.write( time, apu_addr, cpc_latch );
-				goto enable_cpc;
-			}
-			break;
-
-		case 0xF4:
-			cpc_latch = data;
-			goto enable_cpc;
-		}
-	}
-
-	debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
-	return;
-
-enable_cpc:
-	if ( !cpc_mode )
-	{
-		cpc_mode = true;
-		change_clock_rate( cpc_clock );
-		set_tempo( tempo() );
-	}
-}
-
-void ay_cpu_out( Ay_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
-	Ay_Emu& emu = STATIC_CAST(Ay_Emu&,*cpu);
-
-	if ( (addr & 0xFF) == 0xFE && !emu.cpc_mode )
-	{
-		int delta = emu.beeper_delta;
-		data &= 0x10;
-		if ( emu.last_beeper != data )
-		{
-			emu.last_beeper = data;
-			emu.beeper_delta = -delta;
-			emu.spectrum_mode = true;
-			if ( emu.beeper_output )
-				emu.apu.synth_.offset( time, delta, emu.beeper_output );
-		}
-	}
-	else
-	{
-		emu.cpu_out_misc( time, addr, data );
-	}
-}
-
-int ay_cpu_in( Ay_Cpu*, unsigned addr )
-{
-	// keyboard read and other things
-	if ( (addr & 0xFF) == 0xFE )
-		return 0xFF; // other values break some beeper tunes
-
-	debug_printf( "Unmapped IN : $%04X\n", addr );
-	return 0xFF;
-}
-
-blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
-{
-	set_time( 0 );
-	if ( !(spectrum_mode | cpc_mode) )
-		duration /= 2; // until mode is set, leave room for halved clock rate
-
-	while ( time() < duration )
-	{
-		cpu::run( min( duration, (blip_time_t) next_play ) );
-
-		if ( time() >= next_play )
-		{
-			next_play += play_period;
-
-			if ( r.iff1 )
-			{
-				if ( mem.ram [r.pc] == 0x76 )
-					r.pc++;
-
-				r.iff1 = r.iff2 = 0;
-
-				mem.ram [--r.sp] = uint8_t (r.pc >> 8);
-				mem.ram [--r.sp] = uint8_t (r.pc);
-				r.pc = 0x38;
-				cpu::adjust_time( 12 );
-				if ( r.im == 2 )
-				{
-					cpu::adjust_time( 6 );
-					unsigned addr = r.i * 0x100u + 0xFF;
-					r.pc = mem.ram [(addr + 1) & 0xFFFF] * 0x100u + mem.ram [addr];
-				}
-			}
-		}
-	}
-	duration = time();
-	next_play -= duration;
-	check( next_play >= 0 );
-	adjust_time( -duration );
-
-	apu.end_frame( duration );
-
-	return 0;
-}
diff --git a/src/console/Ay_Emu.h b/src/console/Ay_Emu.h
index 4865c0dc09a3..5015ac5ef052 100644
--- a/src/console/Ay_Emu.h
+++ b/src/console/Ay_Emu.h
@@ -46,7 +46,6 @@ protected:
 private:
 	file_t file;
 
-	unsigned play_addr;
 	cpu_time_t play_period;
 	cpu_time_t next_play;
 	Blip_Buffer* beeper_output;
diff --git a/src/console/Blip_Buffer.cc b/src/console/Blip_Buffer.cc
new file mode 100644
index 000000000000..a46b0e350d42
--- /dev/null
+++ b/src/console/Blip_Buffer.cc
@@ -0,0 +1,460 @@
+// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+
+#include "Blip_Buffer.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
+
+Blip_Buffer::Blip_Buffer()
+{
+	factor_       = (blip_ulong)-1 / 2;
+	offset_       = 0;
+	buffer_       = 0;
+	buffer_size_  = 0;
+	sample_rate_  = 0;
+	reader_accum_ = 0;
+	bass_shift_   = 0;
+	clock_rate_   = 0;
+	bass_freq_    = 16;
+	length_       = 0;
+
+	// assumptions code makes about implementation-defined features
+	#ifndef NDEBUG
+		// right shift of negative value preserves sign
+		buf_t_ i = -0x7FFFFFFE;
+		assert( (i >> 1) == -0x3FFFFFFF );
+
+		// casting to short truncates to 16 bits and sign-extends
+		i = 0x18000;
+		assert( (short) i == -0x8000 );
+	#endif
+}
+
+Blip_Buffer::~Blip_Buffer()
+{
+	if ( buffer_size_ != silent_buf_size )
+		free( buffer_ );
+}
+
+Silent_Blip_Buffer::Silent_Blip_Buffer()
+{
+	factor_      = 0;
+	buffer_      = buf;
+	buffer_size_ = silent_buf_size;
+	memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
+}
+
+void Blip_Buffer::clear( int entire_buffer )
+{
+	offset_      = 0;
+	reader_accum_ = 0;
+	modified_    = 0;
+	if ( buffer_ )
+	{
+		long count = (entire_buffer ? buffer_size_ : samples_avail());
+		memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
+	}
+}
+
+Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
+{
+	if ( buffer_size_ == silent_buf_size )
+	{
+		assert( 0 );
+		return "Internal (tried to resize Silent_Blip_Buffer)";
+	}
+
+	// start with maximum length that resampled time can represent
+	long new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
+	if ( msec != blip_max_length )
+	{
+		long s = (new_rate * (msec + 1) + 999) / 1000;
+		if ( s < new_size )
+			new_size = s;
+		else
+			assert( 0 ); // fails if requested buffer length exceeds limit
+	}
+
+	if ( buffer_size_ != new_size )
+	{
+		void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
+		if ( !p )
+			return "Out of memory";
+		buffer_ = (buf_t_*) p;
+	}
+
+	buffer_size_ = new_size;
+	assert( buffer_size_ != silent_buf_size );
+
+	// update things based on the sample rate
+	sample_rate_ = new_rate;
+	length_ = new_size * 1000 / new_rate - 1;
+	if ( msec )
+		assert( length_ == msec ); // ensure length is same as that passed in
+	if ( clock_rate_ )
+		clock_rate( clock_rate_ );
+	bass_freq( bass_freq_ );
+
+	clear();
+
+	return 0; // success
+}
+
+blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
+{
+	double ratio = (double) sample_rate_ / rate;
+	blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
+	assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
+	return (blip_resampled_time_t) factor;
+}
+
+void Blip_Buffer::bass_freq( int freq )
+{
+	bass_freq_ = freq;
+	int shift = 31;
+	if ( freq > 0 )
+	{
+		shift = 13;
+		long f = (freq << 16) / sample_rate_;
+		while ( (f >>= 1) && --shift ) { }
+	}
+	bass_shift_ = shift;
+}
+
+void Blip_Buffer::end_frame( blip_time_t t )
+{
+	offset_ += t * factor_;
+	assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
+}
+
+void Blip_Buffer::remove_silence( long count )
+{
+	assert( count <= samples_avail() ); // tried to remove more samples than available
+	offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+}
+
+long Blip_Buffer::count_samples( blip_time_t t ) const
+{
+	unsigned long last_sample  = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
+	unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
+	return (long) (last_sample - first_sample);
+}
+
+blip_time_t Blip_Buffer::count_clocks( long count ) const
+{
+	if ( !factor_ )
+	{
+		assert( 0 ); // sample rate and clock rates must be set first
+		return 0;
+	}
+
+	if ( count > buffer_size_ )
+		count = buffer_size_;
+	blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+	return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
+}
+
+void Blip_Buffer::remove_samples( long count )
+{
+	if ( count )
+	{
+		remove_silence( count );
+
+		// copy remaining samples to beginning and clear old samples
+		long remain = samples_avail() + blip_buffer_extra_;
+		memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
+		memset( buffer_ + remain, 0, count * sizeof *buffer_ );
+	}
+}
+
+// Blip_Synth_
+
+Blip_Synth_Fast_::Blip_Synth_Fast_()
+{
+	buf = 0;
+	last_amp = 0;
+	delta_factor = 0;
+}
+
+void Blip_Synth_Fast_::volume_unit( double new_unit )
+{
+	delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
+}
+
+#if !BLIP_BUFFER_FAST
+
+Blip_Synth_::Blip_Synth_( short* p, int w ) :
+	impulses( p ),
+	width( w )
+{
+	volume_unit_ = 0.0;
+	kernel_unit = 0;
+	buf = 0;
+	last_amp = 0;
+	delta_factor = 0;
+}
+
+#undef PI
+#define PI 3.1415926535897932384626433832795029
+
+static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
+{
+	if ( cutoff >= 0.999 )
+		cutoff = 0.999;
+
+	if ( treble < -300.0 )
+		treble = -300.0;
+	if ( treble > 5.0 )
+		treble = 5.0;
+
+	double const maxh = 4096.0;
+	double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
+	double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
+	double const to_angle = PI / 2 / maxh / oversample;
+	for ( int i = 0; i < count; i++ )
+	{
+		double angle          = ((i - count) * 2 + 1) * to_angle;
+		double angle_maxh     = angle * maxh;
+		double angle_maxh_mid = angle_maxh * cutoff;
+
+		double y = maxh;
+
+		// 0 to Fs/2*cutoff, flat
+		if ( angle_maxh_mid ) // unstable at t=0
+			y *= sin( angle_maxh_mid ) / angle_maxh_mid;
+
+		// Fs/2*cutoff to Fs/2, logarithmic rolloff
+		double cosa = cos( angle );
+		double den = 1 + rolloff * (rolloff - cosa - cosa);
+
+		// Becomes unstable when rolloff is near 1.0 and t is near 0,
+		// which is the only time den becomes small
+		if ( den > 1e-13 )
+		{
+			double num =
+				(cos( angle_maxh     - angle ) * rolloff - cos( angle_maxh     )) * pow_a_n -
+				 cos( angle_maxh_mid - angle ) * rolloff + cos( angle_maxh_mid );
+
+			y = y * cutoff + num / den;
+		}
+
+		out [i] = (float) y;
+	}
+}
+
+void blip_eq_t::generate( float* out, int count ) const
+{
+	// lower cutoff freq for narrow kernels with their wider transition band
+	// (8 points->1.49, 16 points->1.15)
+	double oversample = blip_res * 2.25 / count + 0.85;
+	double half_rate = sample_rate * 0.5;
+	if ( cutoff_freq )
+		oversample = half_rate / cutoff_freq;
+	double cutoff = rolloff_freq * oversample / half_rate;
+
+	gen_sinc( out, count, blip_res * oversample, treble, cutoff );
+
+	// apply (half of) hamming window
+	double to_fraction = PI / (count - 1);
+	for ( int i = count; i--; )
+		out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
+}
+
+void Blip_Synth_::adjust_impulse()
+{
+	// sum pairs for each phase and add error correction to end of first half
+	int const size = impulses_size();
+	for ( int p = blip_res; p-- >= blip_res / 2; )
+	{
+		int p2 = blip_res - 2 - p;
+		long error = kernel_unit;
+		for ( int i = 1; i < size; i += blip_res )
+		{
+			error -= impulses [i + p ];
+			error -= impulses [i + p2];
+		}
+		if ( p == p2 )
+			error /= 2; // phase = 0.5 impulse uses same half for both sides
+		impulses [size - blip_res + p] += (short) error;
+		//printf( "error: %ld\n", error );
+	}
+
+	//for ( int i = blip_res; i--; printf( "\n" ) )
+	//  for ( int j = 0; j < width / 2; j++ )
+	//      printf( "%5ld,", impulses [j * blip_res + i + 1] );
+}
+
+void Blip_Synth_::treble_eq( blip_eq_t const& eq )
+{
+	float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
+
+	int const half_size = blip_res / 2 * (width - 1);
+	eq.generate( &fimpulse [blip_res], half_size );
+
+	int i;
+
+	// need mirror slightly past center for calculation
+	for ( i = blip_res; i--; )
+		fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
+
+	// starts at 0
+	for ( i = 0; i < blip_res; i++ )
+		fimpulse [i] = 0.0f;
+
+	// find rescale factor
+	double total = 0.0;
+	for ( i = 0; i < half_size; i++ )
+		total += fimpulse [blip_res + i];
+
+	//double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
+	//double const base_unit = 37888.0; // allows treble to +5 dB
+	double const base_unit = 32768.0; // necessary for blip_unscaled to work
+	double rescale = base_unit / 2 / total;
+	kernel_unit = (long) base_unit;
+
+	// integrate, first difference, rescale, convert to int
+	double sum = 0.0;
+	double next = 0.0;
+	int const impulses_size = this->impulses_size();
+	for ( i = 0; i < impulses_size; i++ )
+	{
+		impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
+		sum += fimpulse [i];
+		next += fimpulse [i + blip_res];
+	}
+	adjust_impulse();
+
+	// volume might require rescaling
+	double vol = volume_unit_;
+	if ( vol )
+	{
+		volume_unit_ = 0.0;
+		volume_unit( vol );
+	}
+}
+
+void Blip_Synth_::volume_unit( double new_unit )
+{
+	if ( new_unit != volume_unit_ )
+	{
+		// use default eq if it hasn't been set yet
+		if ( !kernel_unit )
+			treble_eq( -8.0 );
+
+		volume_unit_ = new_unit;
+		double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
+
+		if ( factor > 0.0 )
+		{
+			int shift = 0;
+
+			// if unit is really small, might need to attenuate kernel
+			while ( factor < 2.0 )
+			{
+				shift++;
+				factor *= 2.0;
+			}
+
+			if ( shift )
+			{
+				kernel_unit >>= shift;
+				assert( kernel_unit > 0 ); // fails if volume unit is too low
+
+				// keep values positive to avoid round-towards-zero of sign-preserving
+				// right shift for negative values
+				long offset = 0x8000 + (1 << (shift - 1));
+				long offset2 = 0x8000 >> shift;
+				for ( int i = impulses_size(); i--; )
+					impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
+				adjust_impulse();
+			}
+		}
+		delta_factor = (int) floor( factor + 0.5 );
+		//printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
+	}
+}
+#endif
+
+long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
+{
+	long count = samples_avail();
+	if ( count > max_samples )
+		count = max_samples;
+
+	if ( count )
+	{
+		int const bass = BLIP_READER_BASS( *this );
+		BLIP_READER_BEGIN( reader, *this );
+
+		if ( !stereo )
+		{
+			for ( blip_long n = count; n; --n )
+			{
+				blip_long s = BLIP_READER_READ( reader );
+				if ( (blip_sample_t) s != s )
+					s = 0x7FFF - (s >> 24);
+				*out++ = (blip_sample_t) s;
+				BLIP_READER_NEXT( reader, bass );
+			}
+		}
+		else
+		{
+			for ( blip_long n = count; n; --n )
+			{
+				blip_long s = BLIP_READER_READ( reader );
+				if ( (blip_sample_t) s != s )
+					s = 0x7FFF - (s >> 24);
+				*out = (blip_sample_t) s;
+				out += 2;
+				BLIP_READER_NEXT( reader, bass );
+			}
+		}
+		BLIP_READER_END( reader, *this );
+
+		remove_samples( count );
+	}
+	return count;
+}
+
+void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
+{
+	if ( buffer_size_ == silent_buf_size )
+	{
+		assert( 0 );
+		return;
+	}
+
+	buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
+
+	int const sample_shift = blip_sample_bits - 16;
+	int prev = 0;
+	while ( count-- )
+	{
+		blip_long s = (blip_long) *in++ << sample_shift;
+		*out += s - prev;
+		prev = s;
+		++out;
+	}
+	*out -= prev;
+}
+
diff --git a/src/console/Blip_Buffer.cxx b/src/console/Blip_Buffer.cxx
deleted file mode 100644
index a46b0e350d42..000000000000
--- a/src/console/Blip_Buffer.cxx
+++ /dev/null
@@ -1,460 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Blip_Buffer.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
-	factor_       = (blip_ulong)-1 / 2;
-	offset_       = 0;
-	buffer_       = 0;
-	buffer_size_  = 0;
-	sample_rate_  = 0;
-	reader_accum_ = 0;
-	bass_shift_   = 0;
-	clock_rate_   = 0;
-	bass_freq_    = 16;
-	length_       = 0;
-
-	// assumptions code makes about implementation-defined features
-	#ifndef NDEBUG
-		// right shift of negative value preserves sign
-		buf_t_ i = -0x7FFFFFFE;
-		assert( (i >> 1) == -0x3FFFFFFF );
-
-		// casting to short truncates to 16 bits and sign-extends
-		i = 0x18000;
-		assert( (short) i == -0x8000 );
-	#endif
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
-	if ( buffer_size_ != silent_buf_size )
-		free( buffer_ );
-}
-
-Silent_Blip_Buffer::Silent_Blip_Buffer()
-{
-	factor_      = 0;
-	buffer_      = buf;
-	buffer_size_ = silent_buf_size;
-	memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
-}
-
-void Blip_Buffer::clear( int entire_buffer )
-{
-	offset_      = 0;
-	reader_accum_ = 0;
-	modified_    = 0;
-	if ( buffer_ )
-	{
-		long count = (entire_buffer ? buffer_size_ : samples_avail());
-		memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
-	}
-}
-
-Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
-{
-	if ( buffer_size_ == silent_buf_size )
-	{
-		assert( 0 );
-		return "Internal (tried to resize Silent_Blip_Buffer)";
-	}
-
-	// start with maximum length that resampled time can represent
-	long new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
-	if ( msec != blip_max_length )
-	{
-		long s = (new_rate * (msec + 1) + 999) / 1000;
-		if ( s < new_size )
-			new_size = s;
-		else
-			assert( 0 ); // fails if requested buffer length exceeds limit
-	}
-
-	if ( buffer_size_ != new_size )
-	{
-		void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
-		if ( !p )
-			return "Out of memory";
-		buffer_ = (buf_t_*) p;
-	}
-
-	buffer_size_ = new_size;
-	assert( buffer_size_ != silent_buf_size );
-
-	// update things based on the sample rate
-	sample_rate_ = new_rate;
-	length_ = new_size * 1000 / new_rate - 1;
-	if ( msec )
-		assert( length_ == msec ); // ensure length is same as that passed in
-	if ( clock_rate_ )
-		clock_rate( clock_rate_ );
-	bass_freq( bass_freq_ );
-
-	clear();
-
-	return 0; // success
-}
-
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
-{
-	double ratio = (double) sample_rate_ / rate;
-	blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
-	assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
-	return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
-	bass_freq_ = freq;
-	int shift = 31;
-	if ( freq > 0 )
-	{
-		shift = 13;
-		long f = (freq << 16) / sample_rate_;
-		while ( (f >>= 1) && --shift ) { }
-	}
-	bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
-	offset_ += t * factor_;
-	assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
-}
-
-void Blip_Buffer::remove_silence( long count )
-{
-	assert( count <= samples_avail() ); // tried to remove more samples than available
-	offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const
-{
-	unsigned long last_sample  = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
-	unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
-	return (long) (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( long count ) const
-{
-	if ( !factor_ )
-	{
-		assert( 0 ); // sample rate and clock rates must be set first
-		return 0;
-	}
-
-	if ( count > buffer_size_ )
-		count = buffer_size_;
-	blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-	return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
-	if ( count )
-	{
-		remove_silence( count );
-
-		// copy remaining samples to beginning and clear old samples
-		long remain = samples_avail() + blip_buffer_extra_;
-		memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
-		memset( buffer_ + remain, 0, count * sizeof *buffer_ );
-	}
-}
-
-// Blip_Synth_
-
-Blip_Synth_Fast_::Blip_Synth_Fast_()
-{
-	buf = 0;
-	last_amp = 0;
-	delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
-	delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
-}
-
-#if !BLIP_BUFFER_FAST
-
-Blip_Synth_::Blip_Synth_( short* p, int w ) :
-	impulses( p ),
-	width( w )
-{
-	volume_unit_ = 0.0;
-	kernel_unit = 0;
-	buf = 0;
-	last_amp = 0;
-	delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
-{
-	if ( cutoff >= 0.999 )
-		cutoff = 0.999;
-
-	if ( treble < -300.0 )
-		treble = -300.0;
-	if ( treble > 5.0 )
-		treble = 5.0;
-
-	double const maxh = 4096.0;
-	double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
-	double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
-	double const to_angle = PI / 2 / maxh / oversample;
-	for ( int i = 0; i < count; i++ )
-	{
-		double angle          = ((i - count) * 2 + 1) * to_angle;
-		double angle_maxh     = angle * maxh;
-		double angle_maxh_mid = angle_maxh * cutoff;
-
-		double y = maxh;
-
-		// 0 to Fs/2*cutoff, flat
-		if ( angle_maxh_mid ) // unstable at t=0
-			y *= sin( angle_maxh_mid ) / angle_maxh_mid;
-
-		// Fs/2*cutoff to Fs/2, logarithmic rolloff
-		double cosa = cos( angle );
-		double den = 1 + rolloff * (rolloff - cosa - cosa);
-
-		// Becomes unstable when rolloff is near 1.0 and t is near 0,
-		// which is the only time den becomes small
-		if ( den > 1e-13 )
-		{
-			double num =
-				(cos( angle_maxh     - angle ) * rolloff - cos( angle_maxh     )) * pow_a_n -
-				 cos( angle_maxh_mid - angle ) * rolloff + cos( angle_maxh_mid );
-
-			y = y * cutoff + num / den;
-		}
-
-		out [i] = (float) y;
-	}
-}
-
-void blip_eq_t::generate( float* out, int count ) const
-{
-	// lower cutoff freq for narrow kernels with their wider transition band
-	// (8 points->1.49, 16 points->1.15)
-	double oversample = blip_res * 2.25 / count + 0.85;
-	double half_rate = sample_rate * 0.5;
-	if ( cutoff_freq )
-		oversample = half_rate / cutoff_freq;
-	double cutoff = rolloff_freq * oversample / half_rate;
-
-	gen_sinc( out, count, blip_res * oversample, treble, cutoff );
-
-	// apply (half of) hamming window
-	double to_fraction = PI / (count - 1);
-	for ( int i = count; i--; )
-		out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
-}
-
-void Blip_Synth_::adjust_impulse()
-{
-	// sum pairs for each phase and add error correction to end of first half
-	int const size = impulses_size();
-	for ( int p = blip_res; p-- >= blip_res / 2; )
-	{
-		int p2 = blip_res - 2 - p;
-		long error = kernel_unit;
-		for ( int i = 1; i < size; i += blip_res )
-		{
-			error -= impulses [i + p ];
-			error -= impulses [i + p2];
-		}
-		if ( p == p2 )
-			error /= 2; // phase = 0.5 impulse uses same half for both sides
-		impulses [size - blip_res + p] += (short) error;
-		//printf( "error: %ld\n", error );
-	}
-
-	//for ( int i = blip_res; i--; printf( "\n" ) )
-	//  for ( int j = 0; j < width / 2; j++ )
-	//      printf( "%5ld,", impulses [j * blip_res + i + 1] );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
-	float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
-
-	int const half_size = blip_res / 2 * (width - 1);
-	eq.generate( &fimpulse [blip_res], half_size );
-
-	int i;
-
-	// need mirror slightly past center for calculation
-	for ( i = blip_res; i--; )
-		fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
-
-	// starts at 0
-	for ( i = 0; i < blip_res; i++ )
-		fimpulse [i] = 0.0f;
-
-	// find rescale factor
-	double total = 0.0;
-	for ( i = 0; i < half_size; i++ )
-		total += fimpulse [blip_res + i];
-
-	//double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
-	//double const base_unit = 37888.0; // allows treble to +5 dB
-	double const base_unit = 32768.0; // necessary for blip_unscaled to work
-	double rescale = base_unit / 2 / total;
-	kernel_unit = (long) base_unit;
-
-	// integrate, first difference, rescale, convert to int
-	double sum = 0.0;
-	double next = 0.0;
-	int const impulses_size = this->impulses_size();
-	for ( i = 0; i < impulses_size; i++ )
-	{
-		impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
-		sum += fimpulse [i];
-		next += fimpulse [i + blip_res];
-	}
-	adjust_impulse();
-
-	// volume might require rescaling
-	double vol = volume_unit_;
-	if ( vol )
-	{
-		volume_unit_ = 0.0;
-		volume_unit( vol );
-	}
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
-	if ( new_unit != volume_unit_ )
-	{
-		// use default eq if it hasn't been set yet
-		if ( !kernel_unit )
-			treble_eq( -8.0 );
-
-		volume_unit_ = new_unit;
-		double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
-
-		if ( factor > 0.0 )
-		{
-			int shift = 0;
-
-			// if unit is really small, might need to attenuate kernel
-			while ( factor < 2.0 )
-			{
-				shift++;
-				factor *= 2.0;
-			}
-
-			if ( shift )
-			{
-				kernel_unit >>= shift;
-				assert( kernel_unit > 0 ); // fails if volume unit is too low
-
-				// keep values positive to avoid round-towards-zero of sign-preserving
-				// right shift for negative values
-				long offset = 0x8000 + (1 << (shift - 1));
-				long offset2 = 0x8000 >> shift;
-				for ( int i = impulses_size(); i--; )
-					impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
-				adjust_impulse();
-			}
-		}
-		delta_factor = (int) floor( factor + 0.5 );
-		//printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
-	}
-}
-#endif
-
-long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
-{
-	long count = samples_avail();
-	if ( count > max_samples )
-		count = max_samples;
-
-	if ( count )
-	{
-		int const bass = BLIP_READER_BASS( *this );
-		BLIP_READER_BEGIN( reader, *this );
-
-		if ( !stereo )
-		{
-			for ( blip_long n = count; n; --n )
-			{
-				blip_long s = BLIP_READER_READ( reader );
-				if ( (blip_sample_t) s != s )
-					s = 0x7FFF - (s >> 24);
-				*out++ = (blip_sample_t) s;
-				BLIP_READER_NEXT( reader, bass );
-			}
-		}
-		else
-		{
-			for ( blip_long n = count; n; --n )
-			{
-				blip_long s = BLIP_READER_READ( reader );
-				if ( (blip_sample_t) s != s )
-					s = 0x7FFF - (s >> 24);
-				*out = (blip_sample_t) s;
-				out += 2;
-				BLIP_READER_NEXT( reader, bass );
-			}
-		}
-		BLIP_READER_END( reader, *this );
-
-		remove_samples( count );
-	}
-	return count;
-}
-
-void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
-{
-	if ( buffer_size_ == silent_buf_size )
-	{
-		assert( 0 );
-		return;
-	}
-
-	buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
-
-	int const sample_shift = blip_sample_bits - 16;
-	int prev = 0;
-	while ( count-- )
-	{
-		blip_long s = (blip_long) *in++ << sample_shift;
-		*out += s - prev;
-		prev = s;
-		++out;
-	}
-	*out -= prev;
-}
-
diff --git a/src/console/Blip_Buffer.h b/src/console/Blip_Buffer.h
index 667c3b0730d7..063ed4fe6c32 100644
--- a/src/console/Blip_Buffer.h
+++ b/src/console/Blip_Buffer.h
@@ -25,7 +25,7 @@ public:
 	typedef const char* blargg_err_t;
 
 	// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
-	// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
+	// to 1/4 second), then clear buffer. Returns nullptr on success, otherwise if there
 	// isn't enough memory, returns error without affecting current buffer setup.
 	blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
 
diff --git a/src/console/Classic_Emu.cc b/src/console/Classic_Emu.cc
new file mode 100644
index 000000000000..9c22311e9a41
--- /dev/null
+++ b/src/console/Classic_Emu.cc
@@ -0,0 +1,184 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Classic_Emu.h"
+
+#include "Multi_Buffer.h"
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Classic_Emu::Classic_Emu()
+{
+	buf           = 0;
+	stereo_buffer = 0;
+	voice_types   = 0;
+
+	// avoid inconsistency in our duplicated constants
+	assert( (int) wave_type  == (int) Multi_Buffer::wave_type );
+	assert( (int) noise_type == (int) Multi_Buffer::noise_type );
+	assert( (int) mixed_type == (int) Multi_Buffer::mixed_type );
+}
+
+Classic_Emu::~Classic_Emu()
+{
+	delete stereo_buffer;
+}
+
+void Classic_Emu::set_equalizer_( equalizer_t const& eq )
+{
+	Music_Emu::set_equalizer_( eq );
+	update_eq( eq.treble );
+	if ( buf )
+		buf->bass_freq( (int) equalizer().bass );
+}
+
+blargg_err_t Classic_Emu::set_sample_rate_( long rate )
+{
+	if ( !buf )
+	{
+		if ( !stereo_buffer )
+			CHECK_ALLOC( stereo_buffer = BLARGG_NEW Stereo_Buffer );
+		buf = stereo_buffer;
+	}
+	return buf->set_sample_rate( rate, 1000 / 20 );
+}
+
+void Classic_Emu::mute_voices_( int mask )
+{
+	Music_Emu::mute_voices_( mask );
+	for ( int i = voice_count(); i--; )
+	{
+		if ( mask & (1 << i) )
+		{
+			set_voice( i, 0, 0, 0 );
+		}
+		else
+		{
+			Multi_Buffer::channel_t ch = buf->channel( i, (voice_types ? voice_types [i] : 0) );
+			assert( (ch.center && ch.left && ch.right) ||
+					(!ch.center && !ch.left && !ch.right) ); // all or nothing
+			set_voice( i, ch.center, ch.left, ch.right );
+		}
+	}
+}
+
+void Classic_Emu::change_clock_rate( long rate )
+{
+	clock_rate_ = rate;
+	buf->clock_rate( rate );
+}
+
+blargg_err_t Classic_Emu::setup_buffer( long rate )
+{
+	change_clock_rate( rate );
+	RETURN_ERR( buf->set_channel_count( voice_count() ) );
+	set_equalizer( equalizer() );
+	buf_changed_count = buf->channels_changed_count();
+	return 0;
+}
+
+blargg_err_t Classic_Emu::start_track_( int track )
+{
+	RETURN_ERR( Music_Emu::start_track_( track ) );
+	buf->clear();
+	return 0;
+}
+
+blargg_err_t Classic_Emu::play_( long count, sample_t* out )
+{
+	long remain = count;
+	while ( remain )
+	{
+		remain -= buf->read_samples( &out [count - remain], remain );
+		if ( remain )
+		{
+			if ( buf_changed_count != buf->channels_changed_count() )
+			{
+				buf_changed_count = buf->channels_changed_count();
+				remute_voices();
+			}
+			int msec = buf->length();
+			blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000;
+			RETURN_ERR( run_clocks( clocks_emulated, msec ) );
+			assert( clocks_emulated );
+			buf->end_frame( clocks_emulated );
+		}
+	}
+	return 0;
+}
+
+// Rom_Data
+
+blargg_err_t Rom_Data_::load_rom_data_( Data_Reader& in,
+		int header_size, void* header_out, int fill, long pad_size )
+{
+	long file_offset = pad_size - header_size;
+
+	rom_addr = 0;
+	mask     = 0;
+	size_    = 0;
+	rom.clear();
+
+	file_size_ = in.remain();
+	if ( file_size_ <= header_size ) // <= because there must be data after header
+		return gme_wrong_file_type;
+	blargg_err_t err = rom.resize( file_offset + file_size_ + pad_size );
+	if ( !err )
+		err = in.read( rom.begin() + file_offset, file_size_ );
+	if ( err )
+	{
+		rom.clear();
+		return err;
+	}
+
+	file_size_ -= header_size;
+	memcpy( header_out, &rom [file_offset], header_size );
+
+	memset( rom.begin()         , fill, pad_size );
+	memset( rom.end() - pad_size, fill, pad_size );
+
+	return 0;
+}
+
+void Rom_Data_::set_addr_( long addr, int unit )
+{
+	rom_addr = addr - unit - pad_extra;
+
+	long rounded = (addr + file_size_ + unit - 1) / unit * unit;
+	if ( rounded <= 0 )
+	{
+		rounded = 0;
+	}
+	else
+	{
+		int shift = 0;
+		unsigned long max_addr = (unsigned long) (rounded - 1);
+		while ( max_addr >> shift )
+			shift++;
+		mask = (1L << shift) - 1;
+	}
+
+	if ( addr < 0 )
+		addr = 0;
+	size_ = rounded;
+	if ( rom.resize( rounded - rom_addr + pad_extra ) ) { } // OK if shrink fails
+
+	if ( 0 )
+	{
+		debug_printf( "addr: %X\n", addr );
+		debug_printf( "file_size: %d\n", file_size_ );
+		debug_printf( "rounded: %d\n", rounded );
+		debug_printf( "mask: $%X\n", mask );
+	}
+}
diff --git a/src/console/Classic_Emu.cxx b/src/console/Classic_Emu.cxx
deleted file mode 100644
index 9c22311e9a41..000000000000
--- a/src/console/Classic_Emu.cxx
+++ /dev/null
@@ -1,184 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Classic_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Classic_Emu::Classic_Emu()
-{
-	buf           = 0;
-	stereo_buffer = 0;
-	voice_types   = 0;
-
-	// avoid inconsistency in our duplicated constants
-	assert( (int) wave_type  == (int) Multi_Buffer::wave_type );
-	assert( (int) noise_type == (int) Multi_Buffer::noise_type );
-	assert( (int) mixed_type == (int) Multi_Buffer::mixed_type );
-}
-
-Classic_Emu::~Classic_Emu()
-{
-	delete stereo_buffer;
-}
-
-void Classic_Emu::set_equalizer_( equalizer_t const& eq )
-{
-	Music_Emu::set_equalizer_( eq );
-	update_eq( eq.treble );
-	if ( buf )
-		buf->bass_freq( (int) equalizer().bass );
-}
-
-blargg_err_t Classic_Emu::set_sample_rate_( long rate )
-{
-	if ( !buf )
-	{
-		if ( !stereo_buffer )
-			CHECK_ALLOC( stereo_buffer = BLARGG_NEW Stereo_Buffer );
-		buf = stereo_buffer;
-	}
-	return buf->set_sample_rate( rate, 1000 / 20 );
-}
-
-void Classic_Emu::mute_voices_( int mask )
-{
-	Music_Emu::mute_voices_( mask );
-	for ( int i = voice_count(); i--; )
-	{
-		if ( mask & (1 << i) )
-		{
-			set_voice( i, 0, 0, 0 );
-		}
-		else
-		{
-			Multi_Buffer::channel_t ch = buf->channel( i, (voice_types ? voice_types [i] : 0) );
-			assert( (ch.center && ch.left && ch.right) ||
-					(!ch.center && !ch.left && !ch.right) ); // all or nothing
-			set_voice( i, ch.center, ch.left, ch.right );
-		}
-	}
-}
-
-void Classic_Emu::change_clock_rate( long rate )
-{
-	clock_rate_ = rate;
-	buf->clock_rate( rate );
-}
-
-blargg_err_t Classic_Emu::setup_buffer( long rate )
-{
-	change_clock_rate( rate );
-	RETURN_ERR( buf->set_channel_count( voice_count() ) );
-	set_equalizer( equalizer() );
-	buf_changed_count = buf->channels_changed_count();
-	return 0;
-}
-
-blargg_err_t Classic_Emu::start_track_( int track )
-{
-	RETURN_ERR( Music_Emu::start_track_( track ) );
-	buf->clear();
-	return 0;
-}
-
-blargg_err_t Classic_Emu::play_( long count, sample_t* out )
-{
-	long remain = count;
-	while ( remain )
-	{
-		remain -= buf->read_samples( &out [count - remain], remain );
-		if ( remain )
-		{
-			if ( buf_changed_count != buf->channels_changed_count() )
-			{
-				buf_changed_count = buf->channels_changed_count();
-				remute_voices();
-			}
-			int msec = buf->length();
-			blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000;
-			RETURN_ERR( run_clocks( clocks_emulated, msec ) );
-			assert( clocks_emulated );
-			buf->end_frame( clocks_emulated );
-		}
-	}
-	return 0;
-}
-
-// Rom_Data
-
-blargg_err_t Rom_Data_::load_rom_data_( Data_Reader& in,
-		int header_size, void* header_out, int fill, long pad_size )
-{
-	long file_offset = pad_size - header_size;
-
-	rom_addr = 0;
-	mask     = 0;
-	size_    = 0;
-	rom.clear();
-
-	file_size_ = in.remain();
-	if ( file_size_ <= header_size ) // <= because there must be data after header
-		return gme_wrong_file_type;
-	blargg_err_t err = rom.resize( file_offset + file_size_ + pad_size );
-	if ( !err )
-		err = in.read( rom.begin() + file_offset, file_size_ );
-	if ( err )
-	{
-		rom.clear();
-		return err;
-	}
-
-	file_size_ -= header_size;
-	memcpy( header_out, &rom [file_offset], header_size );
-
-	memset( rom.begin()         , fill, pad_size );
-	memset( rom.end() - pad_size, fill, pad_size );
-
-	return 0;
-}
-
-void Rom_Data_::set_addr_( long addr, int unit )
-{
-	rom_addr = addr - unit - pad_extra;
-
-	long rounded = (addr + file_size_ + unit - 1) / unit * unit;
-	if ( rounded <= 0 )
-	{
-		rounded = 0;
-	}
-	else
-	{
-		int shift = 0;
-		unsigned long max_addr = (unsigned long) (rounded - 1);
-		while ( max_addr >> shift )
-			shift++;
-		mask = (1L << shift) - 1;
-	}
-
-	if ( addr < 0 )
-		addr = 0;
-	size_ = rounded;
-	if ( rom.resize( rounded - rom_addr + pad_extra ) ) { } // OK if shrink fails
-
-	if ( 0 )
-	{
-		debug_printf( "addr: %X\n", addr );
-		debug_printf( "file_size: %d\n", file_size_ );
-		debug_printf( "rounded: %d\n", rounded );
-		debug_printf( "mask: $%X\n", mask );
-	}
-}
diff --git a/src/console/Classic_Emu.h b/src/console/Classic_Emu.h
index b2ab769f7e20..94e19e26089b 100644
--- a/src/console/Classic_Emu.h
+++ b/src/console/Classic_Emu.h
@@ -34,7 +34,7 @@ protected:
 	blargg_err_t play_( long, sample_t* );
 private:
 	Multi_Buffer* buf;
-	Multi_Buffer* stereo_buffer; // NULL if using custom buffer
+	Multi_Buffer* stereo_buffer; // nullptr if using custom buffer
 	long clock_rate_;
 	unsigned buf_changed_count;
 	int const* voice_types;
@@ -70,7 +70,7 @@ template<int unit>
 class Rom_Data : public Rom_Data_ {
 	enum { pad_size = unit + pad_extra };
 public:
-	// Load file data, using already-loaded header 'h' if not NULL. Copy header
+	// Load file data, using already-loaded header 'h' if not nullptr. Copy header
 	// from loaded file data into *out and fill unmapped bytes with 'fill'.
 	blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill )
 	{
diff --git a/src/console/Data_Reader.cc b/src/console/Data_Reader.cc
new file mode 100644
index 000000000000..48e834728329
--- /dev/null
+++ b/src/console/Data_Reader.cc
@@ -0,0 +1,315 @@
+// File_Extractor 0.4.0. http://www.slack.net/~ant/
+
+#include "Data_Reader.h"
+
+#include "blargg_endian.h"
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+/* Copyright (C) 2005-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+const char Data_Reader::eof_error [] = "Unexpected end of file";
+
+blargg_err_t Data_Reader::read( void* p, long s )
+{
+	long result = read_avail( p, s );
+	if ( result != s )
+	{
+		if ( result >= 0 && result < s )
+			return eof_error;
+
+		return "Read error";
+	}
+
+	return 0;
+}
+
+blargg_err_t Data_Reader::skip( long count )
+{
+	char buf [512];
+	while ( count )
+	{
+		long n = sizeof buf;
+		if ( n > count )
+			n = count;
+		count -= n;
+		RETURN_ERR( read( buf, n ) );
+	}
+	return 0;
+}
+
+long File_Reader::remain() const { return size() - tell(); }
+
+blargg_err_t File_Reader::skip( long n )
+{
+	assert( n >= 0 );
+	if ( !n )
+		return 0;
+	return seek( tell() + n );
+}
+
+// Subset_Reader
+
+Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
+{
+	in = dr;
+	remain_ = dr->remain();
+	if ( remain_ > size )
+		remain_ = size;
+}
+
+long Subset_Reader::remain() const { return remain_; }
+
+long Subset_Reader::read_avail( void* p, long s )
+{
+	if ( s > remain_ )
+		s = remain_;
+	remain_ -= s;
+	return in->read_avail( p, s );
+}
+
+// Remaining_Reader
+
+Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
+{
+	header = (char const*) h;
+	header_end = header + size;
+	in = r;
+}
+
+long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
+
+long Remaining_Reader::read_first( void* out, long count )
+{
+	long first = header_end - header;
+	if ( first )
+	{
+		if ( first > count )
+			first = count;
+		void const* old = header;
+		header += first;
+		memcpy( out, old, first );
+	}
+	return first;
+}
+
+long Remaining_Reader::read_avail( void* out, long count )
+{
+	long first = read_first( out, count );
+	long second = count - first;
+	if ( second )
+	{
+		second = in->read_avail( (char*) out + first, second );
+		if ( second <= 0 )
+			return second;
+	}
+	return first + second;
+}
+
+blargg_err_t Remaining_Reader::read( void* out, long count )
+{
+	long first = read_first( out, count );
+	long second = count - first;
+	if ( !second )
+		return 0;
+	return in->read( (char*) out + first, second );
+}
+
+// Mem_File_Reader
+
+Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
+	begin( (const char*) p ),
+	size_( s )
+{
+	pos = 0;
+}
+
+long Mem_File_Reader::size() const { return size_; }
+
+long Mem_File_Reader::read_avail( void* p, long s )
+{
+	long r = remain();
+	if ( s > r )
+		s = r;
+	memcpy( p, begin + pos, s );
+	pos += s;
+	return s;
+}
+
+long Mem_File_Reader::tell() const { return pos; }
+
+blargg_err_t Mem_File_Reader::seek( long n )
+{
+	if ( n > size_ )
+		return eof_error;
+	pos = n;
+	return 0;
+}
+
+// Callback_Reader
+
+Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
+	callback( c ),
+	data( d )
+{
+	remain_ = size;
+}
+
+long Callback_Reader::remain() const { return remain_; }
+
+long Callback_Reader::read_avail( void* out, long count )
+{
+	if ( count > remain_ )
+		count = remain_;
+	if ( Callback_Reader::read( out, count ) )
+		count = -1;
+	return count;
+}
+
+blargg_err_t Callback_Reader::read( void* out, long count )
+{
+	if ( count > remain_ )
+		return eof_error;
+	return callback( data, out, count );
+}
+
+// Std_File_Reader
+
+Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
+
+Std_File_Reader::~Std_File_Reader() { close(); }
+
+blargg_err_t Std_File_Reader::open( const char* path )
+{
+	file_ = fopen( path, "rb" );
+	if ( !file_ )
+		return "Couldn't open file";
+	return 0;
+}
+
+long Std_File_Reader::size() const
+{
+	long pos = tell();
+	fseek( (FILE*) file_, 0, SEEK_END );
+	long result = tell();
+	fseek( (FILE*) file_, pos, SEEK_SET );
+	return result;
+}
+
+long Std_File_Reader::read_avail( void* p, long s )
+{
+	return fread( p, 1, s, (FILE*) file_ );
+}
+
+blargg_err_t Std_File_Reader::read( void* p, long s )
+{
+	if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
+		return 0;
+	if ( feof( (FILE*) file_ ) )
+		return eof_error;
+	return "Couldn't read from file";
+}
+
+long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
+
+blargg_err_t Std_File_Reader::seek( long n )
+{
+	if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
+		return 0;
+	if ( n > size() )
+		return eof_error;
+	return "Error seeking in file";
+}
+
+void Std_File_Reader::close()
+{
+	if ( file_ )
+	{
+		fclose( (FILE*) file_ );
+		file_ = 0;
+	}
+}
+
+// Gzip_File_Reader
+
+static const char* get_gzip_eof( const char* path, long* eof )
+{
+	FILE* file = fopen( path, "rb" );
+	if ( !file )
+		return "Couldn't open file";
+
+	unsigned char buf[4];
+	if (fread (buf, 2, 1, file) == 1 && buf[0] == 0x1F && buf[1] == 0x8B)
+	{
+		if (fseek (file, -4, SEEK_END) != 0 || fread (buf, 4, 1, file) != 1)
+			goto ERR_CLOSE;
+		*eof = GET_LE32 (buf);
+	}
+	else
+	{
+		long pos;
+		if (fseek (file, 0, SEEK_END) != 0 || (pos = ftell (file) < 0))
+			goto ERR_CLOSE;
+		*eof = pos;
+	}
+
+	fclose (file);
+	return 0;
+
+ERR_CLOSE:
+	fclose (file);
+	return "Couldn't get file size";
+}
+
+Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
+
+Gzip_File_Reader::~Gzip_File_Reader() { close(); }
+
+blargg_err_t Gzip_File_Reader::open( const char* path )
+{
+	close();
+
+	RETURN_ERR( get_gzip_eof( path, &size_ ) );
+
+	file_ = gzopen( path, "rb" );
+	if ( !file_ )
+		return "Couldn't open file";
+
+	return 0;
+}
+
+long Gzip_File_Reader::size() const { return size_; }
+
+long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
+
+long Gzip_File_Reader::tell() const { return gztell( file_ ); }
+
+blargg_err_t Gzip_File_Reader::seek( long n )
+{
+	if ( gzseek( file_, n, SEEK_SET ) >= 0 )
+		return 0;
+	if ( n > size_ )
+		return eof_error;
+	return "Error seeking in file";
+}
+
+void Gzip_File_Reader::close()
+{
+	if ( file_ )
+	{
+		gzclose( file_ );
+		file_ = 0;
+	}
+}
diff --git a/src/console/Data_Reader.cxx b/src/console/Data_Reader.cxx
deleted file mode 100644
index 48e834728329..000000000000
--- a/src/console/Data_Reader.cxx
+++ /dev/null
@@ -1,315 +0,0 @@
-// File_Extractor 0.4.0. http://www.slack.net/~ant/
-
-#include "Data_Reader.h"
-
-#include "blargg_endian.h"
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char Data_Reader::eof_error [] = "Unexpected end of file";
-
-blargg_err_t Data_Reader::read( void* p, long s )
-{
-	long result = read_avail( p, s );
-	if ( result != s )
-	{
-		if ( result >= 0 && result < s )
-			return eof_error;
-
-		return "Read error";
-	}
-
-	return 0;
-}
-
-blargg_err_t Data_Reader::skip( long count )
-{
-	char buf [512];
-	while ( count )
-	{
-		long n = sizeof buf;
-		if ( n > count )
-			n = count;
-		count -= n;
-		RETURN_ERR( read( buf, n ) );
-	}
-	return 0;
-}
-
-long File_Reader::remain() const { return size() - tell(); }
-
-blargg_err_t File_Reader::skip( long n )
-{
-	assert( n >= 0 );
-	if ( !n )
-		return 0;
-	return seek( tell() + n );
-}
-
-// Subset_Reader
-
-Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
-{
-	in = dr;
-	remain_ = dr->remain();
-	if ( remain_ > size )
-		remain_ = size;
-}
-
-long Subset_Reader::remain() const { return remain_; }
-
-long Subset_Reader::read_avail( void* p, long s )
-{
-	if ( s > remain_ )
-		s = remain_;
-	remain_ -= s;
-	return in->read_avail( p, s );
-}
-
-// Remaining_Reader
-
-Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
-{
-	header = (char const*) h;
-	header_end = header + size;
-	in = r;
-}
-
-long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
-
-long Remaining_Reader::read_first( void* out, long count )
-{
-	long first = header_end - header;
-	if ( first )
-	{
-		if ( first > count )
-			first = count;
-		void const* old = header;
-		header += first;
-		memcpy( out, old, first );
-	}
-	return first;
-}
-
-long Remaining_Reader::read_avail( void* out, long count )
-{
-	long first = read_first( out, count );
-	long second = count - first;
-	if ( second )
-	{
-		second = in->read_avail( (char*) out + first, second );
-		if ( second <= 0 )
-			return second;
-	}
-	return first + second;
-}
-
-blargg_err_t Remaining_Reader::read( void* out, long count )
-{
-	long first = read_first( out, count );
-	long second = count - first;
-	if ( !second )
-		return 0;
-	return in->read( (char*) out + first, second );
-}
-
-// Mem_File_Reader
-
-Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
-	begin( (const char*) p ),
-	size_( s )
-{
-	pos = 0;
-}
-
-long Mem_File_Reader::size() const { return size_; }
-
-long Mem_File_Reader::read_avail( void* p, long s )
-{
-	long r = remain();
-	if ( s > r )
-		s = r;
-	memcpy( p, begin + pos, s );
-	pos += s;
-	return s;
-}
-
-long Mem_File_Reader::tell() const { return pos; }
-
-blargg_err_t Mem_File_Reader::seek( long n )
-{
-	if ( n > size_ )
-		return eof_error;
-	pos = n;
-	return 0;
-}
-
-// Callback_Reader
-
-Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
-	callback( c ),
-	data( d )
-{
-	remain_ = size;
-}
-
-long Callback_Reader::remain() const { return remain_; }
-
-long Callback_Reader::read_avail( void* out, long count )
-{
-	if ( count > remain_ )
-		count = remain_;
-	if ( Callback_Reader::read( out, count ) )
-		count = -1;
-	return count;
-}
-
-blargg_err_t Callback_Reader::read( void* out, long count )
-{
-	if ( count > remain_ )
-		return eof_error;
-	return callback( data, out, count );
-}
-
-// Std_File_Reader
-
-Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
-
-Std_File_Reader::~Std_File_Reader() { close(); }
-
-blargg_err_t Std_File_Reader::open( const char* path )
-{
-	file_ = fopen( path, "rb" );
-	if ( !file_ )
-		return "Couldn't open file";
-	return 0;
-}
-
-long Std_File_Reader::size() const
-{
-	long pos = tell();
-	fseek( (FILE*) file_, 0, SEEK_END );
-	long result = tell();
-	fseek( (FILE*) file_, pos, SEEK_SET );
-	return result;
-}
-
-long Std_File_Reader::read_avail( void* p, long s )
-{
-	return fread( p, 1, s, (FILE*) file_ );
-}
-
-blargg_err_t Std_File_Reader::read( void* p, long s )
-{
-	if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
-		return 0;
-	if ( feof( (FILE*) file_ ) )
-		return eof_error;
-	return "Couldn't read from file";
-}
-
-long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
-
-blargg_err_t Std_File_Reader::seek( long n )
-{
-	if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
-		return 0;
-	if ( n > size() )
-		return eof_error;
-	return "Error seeking in file";
-}
-
-void Std_File_Reader::close()
-{
-	if ( file_ )
-	{
-		fclose( (FILE*) file_ );
-		file_ = 0;
-	}
-}
-
-// Gzip_File_Reader
-
-static const char* get_gzip_eof( const char* path, long* eof )
-{
-	FILE* file = fopen( path, "rb" );
-	if ( !file )
-		return "Couldn't open file";
-
-	unsigned char buf[4];
-	if (fread (buf, 2, 1, file) == 1 && buf[0] == 0x1F && buf[1] == 0x8B)
-	{
-		if (fseek (file, -4, SEEK_END) != 0 || fread (buf, 4, 1, file) != 1)
-			goto ERR_CLOSE;
-		*eof = GET_LE32 (buf);
-	}
-	else
-	{
-		long pos;
-		if (fseek (file, 0, SEEK_END) != 0 || (pos = ftell (file) < 0))
-			goto ERR_CLOSE;
-		*eof = pos;
-	}
-
-	fclose (file);
-	return 0;
-
-ERR_CLOSE:
-	fclose (file);
-	return "Couldn't get file size";
-}
-
-Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
-
-Gzip_File_Reader::~Gzip_File_Reader() { close(); }
-
-blargg_err_t Gzip_File_Reader::open( const char* path )
-{
-	close();
-
-	RETURN_ERR( get_gzip_eof( path, &size_ ) );
-
-	file_ = gzopen( path, "rb" );
-	if ( !file_ )
-		return "Couldn't open file";
-
-	return 0;
-}
-
-long Gzip_File_Reader::size() const { return size_; }
-
-long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
-
-long Gzip_File_Reader::tell() const { return gztell( file_ ); }
-
-blargg_err_t Gzip_File_Reader::seek( long n )
-{
-	if ( gzseek( file_, n, SEEK_SET ) >= 0 )
-		return 0;
-	if ( n > size_ )
-		return eof_error;
-	return "Error seeking in file";
-}
-
-void Gzip_File_Reader::close()
-{
-	if ( file_ )
-	{
-		gzclose( file_ );
-		file_ = 0;
-	}
-}
diff --git a/src/console/Dual_Resampler.cc b/src/console/Dual_Resampler.cc
new file mode 100644
index 000000000000..c6bba8cca4be
--- /dev/null
+++ b/src/console/Dual_Resampler.cc
@@ -0,0 +1,129 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Dual_Resampler.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Dual_Resampler::Dual_Resampler() { }
+
+Dual_Resampler::~Dual_Resampler() { }
+
+blargg_err_t Dual_Resampler::reset( int pairs )
+{
+	// expand allocations a bit
+	RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
+	resize( pairs );
+	resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
+	return resampler.buffer_size( resampler_size );
+}
+
+void Dual_Resampler::resize( int pairs )
+{
+	int new_sample_buf_size = pairs * 2;
+	if ( sample_buf_size != new_sample_buf_size )
+	{
+		if ( (unsigned) new_sample_buf_size > sample_buf.size() )
+		{
+			check( false );
+			return;
+		}
+		sample_buf_size = new_sample_buf_size;
+		oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2;
+		clear();
+	}
+}
+
+void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
+{
+	long pair_count = sample_buf_size >> 1;
+	blip_time_t blip_time = blip_buf.count_clocks( pair_count );
+	int sample_count = oversamples_per_frame - resampler.written();
+
+	int new_count = play_frame( blip_time, sample_count, resampler.buffer() );
+	assert( new_count < resampler_size );
+
+	blip_buf.end_frame( blip_time );
+	assert( blip_buf.samples_avail() == pair_count );
+
+	resampler.write( new_count );
+
+	long count = resampler.read( sample_buf.begin(), sample_buf_size );
+	assert( count == (long) sample_buf_size );
+
+	mix_samples( blip_buf, out );
+	blip_buf.remove_samples( pair_count );
+}
+
+void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf )
+{
+	// empty extra buffer
+	long remain = sample_buf_size - buf_pos;
+	if ( remain )
+	{
+		if ( remain > count )
+			remain = count;
+		count -= remain;
+		memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
+		out += remain;
+		buf_pos += remain;
+	}
+
+	// entire frames
+	while ( count >= (long) sample_buf_size )
+	{
+		play_frame_( blip_buf, out );
+		out += sample_buf_size;
+		count -= sample_buf_size;
+	}
+
+	// extra
+	if ( count )
+	{
+		play_frame_( blip_buf, sample_buf.begin() );
+		buf_pos = count;
+		memcpy( out, sample_buf.begin(), count * sizeof *out );
+		out += count;
+	}
+}
+
+void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
+{
+	Blip_Reader sn;
+	int bass = sn.begin( blip_buf );
+	const dsample_t* in = sample_buf.begin();
+
+	for ( int n = sample_buf_size >> 1; n--; )
+	{
+		int s = sn.read();
+		blargg_long l = (blargg_long) in [0] * 2 + s;
+		if ( (int16_t) l != l )
+			l = 0x7FFF - (l >> 24);
+
+		sn.next( bass );
+		blargg_long r = (blargg_long) in [1] * 2 + s;
+		if ( (int16_t) r != r )
+			r = 0x7FFF - (r >> 24);
+
+		in += 2;
+		out [0] = l;
+		out [1] = r;
+		out += 2;
+	}
+
+	sn.end( blip_buf );
+}
+
diff --git a/src/console/Dual_Resampler.cxx b/src/console/Dual_Resampler.cxx
deleted file mode 100644
index 7a2caa4db4e7..000000000000
--- a/src/console/Dual_Resampler.cxx
+++ /dev/null
@@ -1,131 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Dual_Resampler.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const resampler_extra = 256;
-
-Dual_Resampler::Dual_Resampler() { }
-
-Dual_Resampler::~Dual_Resampler() { }
-
-blargg_err_t Dual_Resampler::reset( int pairs )
-{
-	// expand allocations a bit
-	RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
-	resize( pairs );
-	resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
-	return resampler.buffer_size( resampler_size );
-}
-
-void Dual_Resampler::resize( int pairs )
-{
-	int new_sample_buf_size = pairs * 2;
-	if ( sample_buf_size != new_sample_buf_size )
-	{
-		if ( (unsigned) new_sample_buf_size > sample_buf.size() )
-		{
-			check( false );
-			return;
-		}
-		sample_buf_size = new_sample_buf_size;
-		oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2;
-		clear();
-	}
-}
-
-void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
-{
-	long pair_count = sample_buf_size >> 1;
-	blip_time_t blip_time = blip_buf.count_clocks( pair_count );
-	int sample_count = oversamples_per_frame - resampler.written();
-
-	int new_count = play_frame( blip_time, sample_count, resampler.buffer() );
-	assert( new_count < resampler_size );
-
-	blip_buf.end_frame( blip_time );
-	assert( blip_buf.samples_avail() == pair_count );
-
-	resampler.write( new_count );
-
-	long count = resampler.read( sample_buf.begin(), sample_buf_size );
-	assert( count == (long) sample_buf_size );
-
-	mix_samples( blip_buf, out );
-	blip_buf.remove_samples( pair_count );
-}
-
-void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf )
-{
-	// empty extra buffer
-	long remain = sample_buf_size - buf_pos;
-	if ( remain )
-	{
-		if ( remain > count )
-			remain = count;
-		count -= remain;
-		memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
-		out += remain;
-		buf_pos += remain;
-	}
-
-	// entire frames
-	while ( count >= (long) sample_buf_size )
-	{
-		play_frame_( blip_buf, out );
-		out += sample_buf_size;
-		count -= sample_buf_size;
-	}
-
-	// extra
-	if ( count )
-	{
-		play_frame_( blip_buf, sample_buf.begin() );
-		buf_pos = count;
-		memcpy( out, sample_buf.begin(), count * sizeof *out );
-		out += count;
-	}
-}
-
-void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
-{
-	Blip_Reader sn;
-	int bass = sn.begin( blip_buf );
-	const dsample_t* in = sample_buf.begin();
-
-	for ( int n = sample_buf_size >> 1; n--; )
-	{
-		int s = sn.read();
-		blargg_long l = (blargg_long) in [0] * 2 + s;
-		if ( (int16_t) l != l )
-			l = 0x7FFF - (l >> 24);
-
-		sn.next( bass );
-		blargg_long r = (blargg_long) in [1] * 2 + s;
-		if ( (int16_t) r != r )
-			r = 0x7FFF - (r >> 24);
-
-		in += 2;
-		out [0] = l;
-		out [1] = r;
-		out += 2;
-	}
-
-	sn.end( blip_buf );
-}
-
diff --git a/src/console/Effects_Buffer.cc b/src/console/Effects_Buffer.cc
new file mode 100644
index 000000000000..a4e0f93dc58f
--- /dev/null
+++ b/src/console/Effects_Buffer.cc
@@ -0,0 +1,529 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Effects_Buffer.h"
+
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+typedef blargg_long fixed_t;
+
+#define TO_FIXED( f )   fixed_t ((f) * (1L << 15) + 0.5)
+#define FMUL( x, y )    (((x) * (y)) >> 15)
+
+const unsigned echo_size = 4096;
+const unsigned echo_mask = echo_size - 1;
+BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2
+
+const unsigned reverb_size = 8192 * 2;
+const unsigned reverb_mask = reverb_size - 1;
+BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2
+
+Effects_Buffer::config_t::config_t()
+{
+	pan_1           = -0.15f;
+	pan_2           =  0.15f;
+	reverb_delay    = 88.0f;
+	reverb_level    = 0.12f;
+	echo_delay      = 61.0f;
+	echo_level      = 0.10f;
+	delay_variance  = 18.0f;
+	effects_enabled = false;
+}
+
+void Effects_Buffer::set_depth( double d )
+{
+	float f = (float) d;
+	config_t c;
+	c.pan_1             = -0.6f * f;
+	c.pan_2             =  0.6f * f;
+	c.reverb_delay      = 880 * 0.1f;
+	c.echo_delay        = 610 * 0.1f;
+	if ( f > 0.5 )
+		f = 0.5; // TODO: more linear reduction of extreme reverb/echo
+	c.reverb_level      = 0.5f * f;
+	c.echo_level        = 0.30f * f;
+	c.delay_variance    = 180 * 0.1f;
+	c.effects_enabled   = (d > 0.0f);
+	config( c );
+}
+
+Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 )
+{
+	buf_count = center_only ? max_buf_count - 4 : max_buf_count;
+
+	echo_pos = 0;
+	reverb_pos = 0;
+
+	stereo_remain = 0;
+	effect_remain = 0;
+	effects_enabled = false;
+	set_depth( 0 );
+}
+
+Effects_Buffer::~Effects_Buffer() { }
+
+blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
+{
+	if ( !echo_buf.size() )
+		RETURN_ERR( echo_buf.resize( echo_size ) );
+
+	if ( !reverb_buf.size() )
+		RETURN_ERR( reverb_buf.resize( reverb_size ) );
+
+	for ( int i = 0; i < buf_count; i++ )
+		RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
+
+	config( config_ );
+	clear();
+
+	return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
+}
+
+void Effects_Buffer::clock_rate( long rate )
+{
+	for ( int i = 0; i < buf_count; i++ )
+		bufs [i].clock_rate( rate );
+}
+
+void Effects_Buffer::bass_freq( int freq )
+{
+	for ( int i = 0; i < buf_count; i++ )
+		bufs [i].bass_freq( freq );
+}
+
+void Effects_Buffer::clear()
+{
+	stereo_remain = 0;
+	effect_remain = 0;
+	if ( echo_buf.size() )
+		memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
+
+	if ( reverb_buf.size() )
+		memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
+
+	for ( int i = 0; i < buf_count; i++ )
+		bufs [i].clear();
+}
+
+inline int pin_range( int n, int max, int min = 0 )
+{
+	if ( n < min )
+		return min;
+	if ( n > max )
+		return max;
+	return n;
+}
+
+void Effects_Buffer::config( const config_t& cfg )
+{
+	channels_changed();
+
+	// clear echo and reverb buffers
+	if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf.size() )
+	{
+		memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
+		memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
+	}
+
+	config_ = cfg;
+
+	if ( config_.effects_enabled )
+	{
+		// convert to internal format
+
+		chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 );
+		chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0];
+
+		chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 );
+		chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0];
+
+		chans.reverb_level = TO_FIXED( config_.reverb_level );
+		chans.echo_level = TO_FIXED( config_.echo_level );
+
+		int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate());
+
+		int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate());
+		chans.reverb_delay_l = pin_range( reverb_size -
+				(reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
+		chans.reverb_delay_r = pin_range( reverb_size + 1 -
+				(reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
+
+		int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate());
+		chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset),
+				echo_size - 1 );
+		chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset),
+				echo_size - 1 );
+
+		chan_types [0].center = &bufs [0];
+		chan_types [0].left   = &bufs [3];
+		chan_types [0].right  = &bufs [4];
+
+		chan_types [1].center = &bufs [1];
+		chan_types [1].left   = &bufs [3];
+		chan_types [1].right  = &bufs [4];
+
+		chan_types [2].center = &bufs [2];
+		chan_types [2].left   = &bufs [5];
+		chan_types [2].right  = &bufs [6];
+		assert( 2 < chan_types_count );
+	}
+	else
+	{
+		// set up outputs
+		for ( unsigned i = 0; i < chan_types_count; i++ )
+		{
+			channel_t& c = chan_types [i];
+			c.center = &bufs [0];
+			c.left   = &bufs [1];
+			c.right  = &bufs [2];
+		}
+	}
+
+	if ( buf_count < max_buf_count )
+	{
+		for ( int i = 0; i < chan_types_count; i++ )
+		{
+			channel_t& c = chan_types [i];
+			c.left   = c.center;
+			c.right  = c.center;
+		}
+	}
+}
+
+Effects_Buffer::channel_t Effects_Buffer::channel( int i, int type )
+{
+	int out = 2;
+	if ( !type )
+	{
+		out = i % 5;
+		if ( out > 2 )
+			out = 2;
+	}
+	else if ( !(type & noise_type) && (type & type_index_mask) % 3 != 0 )
+	{
+		out = type & 1;
+	}
+	return chan_types [out];
+}
+
+void Effects_Buffer::end_frame( blip_time_t clock_count )
+{
+	int bufs_used = 0;
+	for ( int i = 0; i < buf_count; i++ )
+	{
+		bufs_used |= bufs [i].clear_modified() << i;
+		bufs [i].end_frame( clock_count );
+	}
+
+	int stereo_mask = (config_.effects_enabled ? 0x78 : 0x06);
+	if ( (bufs_used & stereo_mask) && buf_count == max_buf_count )
+		stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency();
+
+	if ( effects_enabled || config_.effects_enabled )
+		effect_remain = bufs [0].samples_avail() + bufs [0].output_latency();
+
+	effects_enabled = config_.effects_enabled;
+}
+
+long Effects_Buffer::samples_avail() const
+{
+	return bufs [0].samples_avail() * 2;
+}
+
+long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
+{
+	require( total_samples % 2 == 0 ); // count must be even
+
+	long remain = bufs [0].samples_avail();
+	if ( remain > (total_samples >> 1) )
+		remain = (total_samples >> 1);
+	total_samples = remain;
+	while ( remain )
+	{
+		int active_bufs = buf_count;
+		long count = remain;
+
+		// optimizing mixing to skip any channels which had nothing added
+		if ( effect_remain )
+		{
+			if ( count > effect_remain )
+				count = effect_remain;
+
+			if ( stereo_remain )
+			{
+				mix_enhanced( out, count );
+			}
+			else
+			{
+				mix_mono_enhanced( out, count );
+				active_bufs = 3;
+			}
+		}
+		else if ( stereo_remain )
+		{
+			mix_stereo( out, count );
+			active_bufs = 3;
+		}
+		else
+		{
+			mix_mono( out, count );
+			active_bufs = 1;
+		}
+
+		out += count * 2;
+		remain -= count;
+
+		stereo_remain -= count;
+		if ( stereo_remain < 0 )
+			stereo_remain = 0;
+
+		effect_remain -= count;
+		if ( effect_remain < 0 )
+			effect_remain = 0;
+
+		for ( int i = 0; i < buf_count; i++ )
+		{
+			if ( i < active_bufs )
+				bufs [i].remove_samples( count );
+			else
+				bufs [i].remove_silence( count ); // keep time synchronized
+		}
+	}
+
+	return total_samples * 2;
+}
+
+void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [0] );
+	BLIP_READER_BEGIN( c, bufs [0] );
+
+	// unrolled loop
+	for ( blargg_long n = count >> 1; n; --n )
+	{
+		blargg_long cs0 = BLIP_READER_READ( c );
+		BLIP_READER_NEXT( c, bass );
+
+		blargg_long cs1 = BLIP_READER_READ( c );
+		BLIP_READER_NEXT( c, bass );
+
+		if ( (int16_t) cs0 != cs0 )
+			cs0 = 0x7FFF - (cs0 >> 24);
+		((uint32_t*) out) [0] = ((uint16_t) cs0) | (cs0 << 16);
+
+		if ( (int16_t) cs1 != cs1 )
+			cs1 = 0x7FFF - (cs1 >> 24);
+		((uint32_t*) out) [1] = ((uint16_t) cs1) | (cs1 << 16);
+		out += 4;
+	}
+
+	if ( count & 1 )
+	{
+		int s = BLIP_READER_READ( c );
+		BLIP_READER_NEXT( c, bass );
+		out [0] = s;
+		out [1] = s;
+		if ( (int16_t) s != s )
+		{
+			s = 0x7FFF - (s >> 24);
+			out [0] = s;
+			out [1] = s;
+		}
+	}
+
+	BLIP_READER_END( c, bufs [0] );
+}
+
+void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [0] );
+	BLIP_READER_BEGIN( c, bufs [0] );
+	BLIP_READER_BEGIN( l, bufs [1] );
+	BLIP_READER_BEGIN( r, bufs [2] );
+
+	while ( count-- )
+	{
+		int cs = BLIP_READER_READ( c );
+		BLIP_READER_NEXT( c, bass );
+		int left = cs + BLIP_READER_READ( l );
+		int right = cs + BLIP_READER_READ( r );
+		BLIP_READER_NEXT( l, bass );
+		BLIP_READER_NEXT( r, bass );
+
+		if ( (int16_t) left != left )
+			left = 0x7FFF - (left >> 24);
+
+		out [0] = left;
+		out [1] = right;
+
+		out += 2;
+
+		if ( (int16_t) right != right )
+			out [-1] = 0x7FFF - (right >> 24);
+	}
+
+	BLIP_READER_END( r, bufs [2] );
+	BLIP_READER_END( l, bufs [1] );
+	BLIP_READER_END( c, bufs [0] );
+}
+
+void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [2] );
+	BLIP_READER_BEGIN( center, bufs [2] );
+	BLIP_READER_BEGIN( sq1, bufs [0] );
+	BLIP_READER_BEGIN( sq2, bufs [1] );
+
+	blip_sample_t* const reverb_buf = this->reverb_buf.begin();
+	blip_sample_t* const echo_buf = this->echo_buf.begin();
+	int echo_pos = this->echo_pos;
+	int reverb_pos = this->reverb_pos;
+
+	while ( count-- )
+	{
+		int sum1_s = BLIP_READER_READ( sq1 );
+		int sum2_s = BLIP_READER_READ( sq2 );
+
+		BLIP_READER_NEXT( sq1, bass );
+		BLIP_READER_NEXT( sq2, bass );
+
+		int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
+				FMUL( sum2_s, chans.pan_2_levels [0] ) +
+				reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
+
+		int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
+				FMUL( sum2_s, chans.pan_2_levels [1] ) +
+				reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
+
+		fixed_t reverb_level = chans.reverb_level;
+		reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
+		reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
+		reverb_pos = (reverb_pos + 2) & reverb_mask;
+
+		int sum3_s = BLIP_READER_READ( center );
+		BLIP_READER_NEXT( center, bass );
+
+		int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
+				echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
+		int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
+				echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
+
+		echo_buf [echo_pos] = sum3_s;
+		echo_pos = (echo_pos + 1) & echo_mask;
+
+		if ( (int16_t) left != left )
+			left = 0x7FFF - (left >> 24);
+
+		out [0] = left;
+		out [1] = right;
+
+		out += 2;
+
+		if ( (int16_t) right != right )
+			out [-1] = 0x7FFF - (right >> 24);
+	}
+	this->reverb_pos = reverb_pos;
+	this->echo_pos = echo_pos;
+
+	BLIP_READER_END( sq1, bufs [0] );
+	BLIP_READER_END( sq2, bufs [1] );
+	BLIP_READER_END( center, bufs [2] );
+}
+
+void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [2] );
+	BLIP_READER_BEGIN( center, bufs [2] );
+	BLIP_READER_BEGIN( l1, bufs [3] );
+	BLIP_READER_BEGIN( r1, bufs [4] );
+	BLIP_READER_BEGIN( l2, bufs [5] );
+	BLIP_READER_BEGIN( r2, bufs [6] );
+	BLIP_READER_BEGIN( sq1, bufs [0] );
+	BLIP_READER_BEGIN( sq2, bufs [1] );
+
+	blip_sample_t* const reverb_buf = this->reverb_buf.begin();
+	blip_sample_t* const echo_buf = this->echo_buf.begin();
+	int echo_pos = this->echo_pos;
+	int reverb_pos = this->reverb_pos;
+
+	while ( count-- )
+	{
+		int sum1_s = BLIP_READER_READ( sq1 );
+		int sum2_s = BLIP_READER_READ( sq2 );
+
+		BLIP_READER_NEXT( sq1, bass );
+		BLIP_READER_NEXT( sq2, bass );
+
+		int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
+				FMUL( sum2_s, chans.pan_2_levels [0] ) + BLIP_READER_READ( l1 ) +
+				reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
+
+		int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
+				FMUL( sum2_s, chans.pan_2_levels [1] ) + BLIP_READER_READ( r1 ) +
+				reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
+
+		BLIP_READER_NEXT( l1, bass );
+		BLIP_READER_NEXT( r1, bass );
+
+		fixed_t reverb_level = chans.reverb_level;
+		reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
+		reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
+		reverb_pos = (reverb_pos + 2) & reverb_mask;
+
+		int sum3_s = BLIP_READER_READ( center );
+		BLIP_READER_NEXT( center, bass );
+
+		int left = new_reverb_l + sum3_s + BLIP_READER_READ( l2 ) + FMUL( chans.echo_level,
+				echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
+		int right = new_reverb_r + sum3_s + BLIP_READER_READ( r2 ) + FMUL( chans.echo_level,
+				echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
+
+		BLIP_READER_NEXT( l2, bass );
+		BLIP_READER_NEXT( r2, bass );
+
+		echo_buf [echo_pos] = sum3_s;
+		echo_pos = (echo_pos + 1) & echo_mask;
+
+		if ( (int16_t) left != left )
+			left = 0x7FFF - (left >> 24);
+
+		out [0] = left;
+		out [1] = right;
+
+		out += 2;
+
+		if ( (int16_t) right != right )
+			out [-1] = 0x7FFF - (right >> 24);
+	}
+	this->reverb_pos = reverb_pos;
+	this->echo_pos = echo_pos;
+
+	BLIP_READER_END( l1, bufs [3] );
+	BLIP_READER_END( r1, bufs [4] );
+	BLIP_READER_END( l2, bufs [5] );
+	BLIP_READER_END( r2, bufs [6] );
+	BLIP_READER_END( sq1, bufs [0] );
+	BLIP_READER_END( sq2, bufs [1] );
+	BLIP_READER_END( center, bufs [2] );
+}
+
diff --git a/src/console/Effects_Buffer.cxx b/src/console/Effects_Buffer.cxx
deleted file mode 100644
index a4e0f93dc58f..000000000000
--- a/src/console/Effects_Buffer.cxx
+++ /dev/null
@@ -1,529 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Effects_Buffer.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-typedef blargg_long fixed_t;
-
-#define TO_FIXED( f )   fixed_t ((f) * (1L << 15) + 0.5)
-#define FMUL( x, y )    (((x) * (y)) >> 15)
-
-const unsigned echo_size = 4096;
-const unsigned echo_mask = echo_size - 1;
-BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2
-
-const unsigned reverb_size = 8192 * 2;
-const unsigned reverb_mask = reverb_size - 1;
-BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2
-
-Effects_Buffer::config_t::config_t()
-{
-	pan_1           = -0.15f;
-	pan_2           =  0.15f;
-	reverb_delay    = 88.0f;
-	reverb_level    = 0.12f;
-	echo_delay      = 61.0f;
-	echo_level      = 0.10f;
-	delay_variance  = 18.0f;
-	effects_enabled = false;
-}
-
-void Effects_Buffer::set_depth( double d )
-{
-	float f = (float) d;
-	config_t c;
-	c.pan_1             = -0.6f * f;
-	c.pan_2             =  0.6f * f;
-	c.reverb_delay      = 880 * 0.1f;
-	c.echo_delay        = 610 * 0.1f;
-	if ( f > 0.5 )
-		f = 0.5; // TODO: more linear reduction of extreme reverb/echo
-	c.reverb_level      = 0.5f * f;
-	c.echo_level        = 0.30f * f;
-	c.delay_variance    = 180 * 0.1f;
-	c.effects_enabled   = (d > 0.0f);
-	config( c );
-}
-
-Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 )
-{
-	buf_count = center_only ? max_buf_count - 4 : max_buf_count;
-
-	echo_pos = 0;
-	reverb_pos = 0;
-
-	stereo_remain = 0;
-	effect_remain = 0;
-	effects_enabled = false;
-	set_depth( 0 );
-}
-
-Effects_Buffer::~Effects_Buffer() { }
-
-blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
-{
-	if ( !echo_buf.size() )
-		RETURN_ERR( echo_buf.resize( echo_size ) );
-
-	if ( !reverb_buf.size() )
-		RETURN_ERR( reverb_buf.resize( reverb_size ) );
-
-	for ( int i = 0; i < buf_count; i++ )
-		RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
-
-	config( config_ );
-	clear();
-
-	return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Effects_Buffer::clock_rate( long rate )
-{
-	for ( int i = 0; i < buf_count; i++ )
-		bufs [i].clock_rate( rate );
-}
-
-void Effects_Buffer::bass_freq( int freq )
-{
-	for ( int i = 0; i < buf_count; i++ )
-		bufs [i].bass_freq( freq );
-}
-
-void Effects_Buffer::clear()
-{
-	stereo_remain = 0;
-	effect_remain = 0;
-	if ( echo_buf.size() )
-		memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
-
-	if ( reverb_buf.size() )
-		memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
-
-	for ( int i = 0; i < buf_count; i++ )
-		bufs [i].clear();
-}
-
-inline int pin_range( int n, int max, int min = 0 )
-{
-	if ( n < min )
-		return min;
-	if ( n > max )
-		return max;
-	return n;
-}
-
-void Effects_Buffer::config( const config_t& cfg )
-{
-	channels_changed();
-
-	// clear echo and reverb buffers
-	if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf.size() )
-	{
-		memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
-		memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
-	}
-
-	config_ = cfg;
-
-	if ( config_.effects_enabled )
-	{
-		// convert to internal format
-
-		chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 );
-		chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0];
-
-		chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 );
-		chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0];
-
-		chans.reverb_level = TO_FIXED( config_.reverb_level );
-		chans.echo_level = TO_FIXED( config_.echo_level );
-
-		int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate());
-
-		int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate());
-		chans.reverb_delay_l = pin_range( reverb_size -
-				(reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
-		chans.reverb_delay_r = pin_range( reverb_size + 1 -
-				(reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
-
-		int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate());
-		chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset),
-				echo_size - 1 );
-		chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset),
-				echo_size - 1 );
-
-		chan_types [0].center = &bufs [0];
-		chan_types [0].left   = &bufs [3];
-		chan_types [0].right  = &bufs [4];
-
-		chan_types [1].center = &bufs [1];
-		chan_types [1].left   = &bufs [3];
-		chan_types [1].right  = &bufs [4];
-
-		chan_types [2].center = &bufs [2];
-		chan_types [2].left   = &bufs [5];
-		chan_types [2].right  = &bufs [6];
-		assert( 2 < chan_types_count );
-	}
-	else
-	{
-		// set up outputs
-		for ( unsigned i = 0; i < chan_types_count; i++ )
-		{
-			channel_t& c = chan_types [i];
-			c.center = &bufs [0];
-			c.left   = &bufs [1];
-			c.right  = &bufs [2];
-		}
-	}
-
-	if ( buf_count < max_buf_count )
-	{
-		for ( int i = 0; i < chan_types_count; i++ )
-		{
-			channel_t& c = chan_types [i];
-			c.left   = c.center;
-			c.right  = c.center;
-		}
-	}
-}
-
-Effects_Buffer::channel_t Effects_Buffer::channel( int i, int type )
-{
-	int out = 2;
-	if ( !type )
-	{
-		out = i % 5;
-		if ( out > 2 )
-			out = 2;
-	}
-	else if ( !(type & noise_type) && (type & type_index_mask) % 3 != 0 )
-	{
-		out = type & 1;
-	}
-	return chan_types [out];
-}
-
-void Effects_Buffer::end_frame( blip_time_t clock_count )
-{
-	int bufs_used = 0;
-	for ( int i = 0; i < buf_count; i++ )
-	{
-		bufs_used |= bufs [i].clear_modified() << i;
-		bufs [i].end_frame( clock_count );
-	}
-
-	int stereo_mask = (config_.effects_enabled ? 0x78 : 0x06);
-	if ( (bufs_used & stereo_mask) && buf_count == max_buf_count )
-		stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
-	if ( effects_enabled || config_.effects_enabled )
-		effect_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
-	effects_enabled = config_.effects_enabled;
-}
-
-long Effects_Buffer::samples_avail() const
-{
-	return bufs [0].samples_avail() * 2;
-}
-
-long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
-{
-	require( total_samples % 2 == 0 ); // count must be even
-
-	long remain = bufs [0].samples_avail();
-	if ( remain > (total_samples >> 1) )
-		remain = (total_samples >> 1);
-	total_samples = remain;
-	while ( remain )
-	{
-		int active_bufs = buf_count;
-		long count = remain;
-
-		// optimizing mixing to skip any channels which had nothing added
-		if ( effect_remain )
-		{
-			if ( count > effect_remain )
-				count = effect_remain;
-
-			if ( stereo_remain )
-			{
-				mix_enhanced( out, count );
-			}
-			else
-			{
-				mix_mono_enhanced( out, count );
-				active_bufs = 3;
-			}
-		}
-		else if ( stereo_remain )
-		{
-			mix_stereo( out, count );
-			active_bufs = 3;
-		}
-		else
-		{
-			mix_mono( out, count );
-			active_bufs = 1;
-		}
-
-		out += count * 2;
-		remain -= count;
-
-		stereo_remain -= count;
-		if ( stereo_remain < 0 )
-			stereo_remain = 0;
-
-		effect_remain -= count;
-		if ( effect_remain < 0 )
-			effect_remain = 0;
-
-		for ( int i = 0; i < buf_count; i++ )
-		{
-			if ( i < active_bufs )
-				bufs [i].remove_samples( count );
-			else
-				bufs [i].remove_silence( count ); // keep time synchronized
-		}
-	}
-
-	return total_samples * 2;
-}
-
-void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [0] );
-	BLIP_READER_BEGIN( c, bufs [0] );
-
-	// unrolled loop
-	for ( blargg_long n = count >> 1; n; --n )
-	{
-		blargg_long cs0 = BLIP_READER_READ( c );
-		BLIP_READER_NEXT( c, bass );
-
-		blargg_long cs1 = BLIP_READER_READ( c );
-		BLIP_READER_NEXT( c, bass );
-
-		if ( (int16_t) cs0 != cs0 )
-			cs0 = 0x7FFF - (cs0 >> 24);
-		((uint32_t*) out) [0] = ((uint16_t) cs0) | (cs0 << 16);
-
-		if ( (int16_t) cs1 != cs1 )
-			cs1 = 0x7FFF - (cs1 >> 24);
-		((uint32_t*) out) [1] = ((uint16_t) cs1) | (cs1 << 16);
-		out += 4;
-	}
-
-	if ( count & 1 )
-	{
-		int s = BLIP_READER_READ( c );
-		BLIP_READER_NEXT( c, bass );
-		out [0] = s;
-		out [1] = s;
-		if ( (int16_t) s != s )
-		{
-			s = 0x7FFF - (s >> 24);
-			out [0] = s;
-			out [1] = s;
-		}
-	}
-
-	BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [0] );
-	BLIP_READER_BEGIN( c, bufs [0] );
-	BLIP_READER_BEGIN( l, bufs [1] );
-	BLIP_READER_BEGIN( r, bufs [2] );
-
-	while ( count-- )
-	{
-		int cs = BLIP_READER_READ( c );
-		BLIP_READER_NEXT( c, bass );
-		int left = cs + BLIP_READER_READ( l );
-		int right = cs + BLIP_READER_READ( r );
-		BLIP_READER_NEXT( l, bass );
-		BLIP_READER_NEXT( r, bass );
-
-		if ( (int16_t) left != left )
-			left = 0x7FFF - (left >> 24);
-
-		out [0] = left;
-		out [1] = right;
-
-		out += 2;
-
-		if ( (int16_t) right != right )
-			out [-1] = 0x7FFF - (right >> 24);
-	}
-
-	BLIP_READER_END( r, bufs [2] );
-	BLIP_READER_END( l, bufs [1] );
-	BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [2] );
-	BLIP_READER_BEGIN( center, bufs [2] );
-	BLIP_READER_BEGIN( sq1, bufs [0] );
-	BLIP_READER_BEGIN( sq2, bufs [1] );
-
-	blip_sample_t* const reverb_buf = this->reverb_buf.begin();
-	blip_sample_t* const echo_buf = this->echo_buf.begin();
-	int echo_pos = this->echo_pos;
-	int reverb_pos = this->reverb_pos;
-
-	while ( count-- )
-	{
-		int sum1_s = BLIP_READER_READ( sq1 );
-		int sum2_s = BLIP_READER_READ( sq2 );
-
-		BLIP_READER_NEXT( sq1, bass );
-		BLIP_READER_NEXT( sq2, bass );
-
-		int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
-				FMUL( sum2_s, chans.pan_2_levels [0] ) +
-				reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
-		int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
-				FMUL( sum2_s, chans.pan_2_levels [1] ) +
-				reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
-		fixed_t reverb_level = chans.reverb_level;
-		reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
-		reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
-		reverb_pos = (reverb_pos + 2) & reverb_mask;
-
-		int sum3_s = BLIP_READER_READ( center );
-		BLIP_READER_NEXT( center, bass );
-
-		int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
-				echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
-		int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
-				echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
-		echo_buf [echo_pos] = sum3_s;
-		echo_pos = (echo_pos + 1) & echo_mask;
-
-		if ( (int16_t) left != left )
-			left = 0x7FFF - (left >> 24);
-
-		out [0] = left;
-		out [1] = right;
-
-		out += 2;
-
-		if ( (int16_t) right != right )
-			out [-1] = 0x7FFF - (right >> 24);
-	}
-	this->reverb_pos = reverb_pos;
-	this->echo_pos = echo_pos;
-
-	BLIP_READER_END( sq1, bufs [0] );
-	BLIP_READER_END( sq2, bufs [1] );
-	BLIP_READER_END( center, bufs [2] );
-}
-
-void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [2] );
-	BLIP_READER_BEGIN( center, bufs [2] );
-	BLIP_READER_BEGIN( l1, bufs [3] );
-	BLIP_READER_BEGIN( r1, bufs [4] );
-	BLIP_READER_BEGIN( l2, bufs [5] );
-	BLIP_READER_BEGIN( r2, bufs [6] );
-	BLIP_READER_BEGIN( sq1, bufs [0] );
-	BLIP_READER_BEGIN( sq2, bufs [1] );
-
-	blip_sample_t* const reverb_buf = this->reverb_buf.begin();
-	blip_sample_t* const echo_buf = this->echo_buf.begin();
-	int echo_pos = this->echo_pos;
-	int reverb_pos = this->reverb_pos;
-
-	while ( count-- )
-	{
-		int sum1_s = BLIP_READER_READ( sq1 );
-		int sum2_s = BLIP_READER_READ( sq2 );
-
-		BLIP_READER_NEXT( sq1, bass );
-		BLIP_READER_NEXT( sq2, bass );
-
-		int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
-				FMUL( sum2_s, chans.pan_2_levels [0] ) + BLIP_READER_READ( l1 ) +
-				reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
-		int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
-				FMUL( sum2_s, chans.pan_2_levels [1] ) + BLIP_READER_READ( r1 ) +
-				reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
-		BLIP_READER_NEXT( l1, bass );
-		BLIP_READER_NEXT( r1, bass );
-
-		fixed_t reverb_level = chans.reverb_level;
-		reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
-		reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
-		reverb_pos = (reverb_pos + 2) & reverb_mask;
-
-		int sum3_s = BLIP_READER_READ( center );
-		BLIP_READER_NEXT( center, bass );
-
-		int left = new_reverb_l + sum3_s + BLIP_READER_READ( l2 ) + FMUL( chans.echo_level,
-				echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
-		int right = new_reverb_r + sum3_s + BLIP_READER_READ( r2 ) + FMUL( chans.echo_level,
-				echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
-		BLIP_READER_NEXT( l2, bass );
-		BLIP_READER_NEXT( r2, bass );
-
-		echo_buf [echo_pos] = sum3_s;
-		echo_pos = (echo_pos + 1) & echo_mask;
-
-		if ( (int16_t) left != left )
-			left = 0x7FFF - (left >> 24);
-
-		out [0] = left;
-		out [1] = right;
-
-		out += 2;
-
-		if ( (int16_t) right != right )
-			out [-1] = 0x7FFF - (right >> 24);
-	}
-	this->reverb_pos = reverb_pos;
-	this->echo_pos = echo_pos;
-
-	BLIP_READER_END( l1, bufs [3] );
-	BLIP_READER_END( r1, bufs [4] );
-	BLIP_READER_END( l2, bufs [5] );
-	BLIP_READER_END( r2, bufs [6] );
-	BLIP_READER_END( sq1, bufs [0] );
-	BLIP_READER_END( sq2, bufs [1] );
-	BLIP_READER_END( center, bufs [2] );
-}
-
diff --git a/src/console/Fir_Resampler.cc b/src/console/Fir_Resampler.cc
new file mode 100644
index 000000000000..d8cbc3d246f3
--- /dev/null
+++ b/src/console/Fir_Resampler.cc
@@ -0,0 +1,199 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Fir_Resampler.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+/* Copyright (C) 2004-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#undef PI
+#define PI 3.1415926535897932384626433832795029
+
+static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
+		int count, short* out )
+{
+	double const maxh = 256;
+	double const step = PI / maxh * spacing;
+	double const to_w = maxh * 2 / width;
+	double const pow_a_n = pow( rolloff, maxh );
+	scale /= maxh * 2;
+
+	double angle = (count / 2 - 1 + offset) * -step;
+	while ( count-- )
+	{
+		*out++ = 0;
+		double w = angle * to_w;
+		if ( fabs( w ) < PI )
+		{
+			double rolloff_cos_a = rolloff * cos( angle );
+			double num = 1 - rolloff_cos_a -
+					pow_a_n * cos( maxh * angle ) +
+					pow_a_n * rolloff * cos( (maxh - 1) * angle );
+			double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
+			double sinc = scale * num / den - scale;
+
+			out [-1] = (short) (cos( w ) * sinc + sinc);
+		}
+		angle += step;
+	}
+}
+
+Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) :
+	width_( width ),
+	write_offset( width * stereo - stereo ),
+	impulses( impulses_ )
+{
+	write_pos = 0;
+	res       = 1;
+	imp_phase = 0;
+	skip_bits = 0;
+	step      = stereo;
+	ratio_    = 1.0;
+}
+
+Fir_Resampler_::~Fir_Resampler_() { }
+
+void Fir_Resampler_::clear()
+{
+	imp_phase = 0;
+	if ( buf.size() )
+	{
+		write_pos = &buf [write_offset];
+		memset( buf.begin(), 0, write_offset * sizeof buf [0] );
+	}
+}
+
+blargg_err_t Fir_Resampler_::buffer_size( int new_size )
+{
+	RETURN_ERR( buf.resize( new_size + write_offset ) );
+	clear();
+	return 0;
+}
+
+double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gain )
+{
+	ratio_ = new_factor;
+
+	double fstep = 0.0;
+	{
+		double least_error = 2;
+		double pos = 0;
+		res = -1;
+		for ( int r = 1; r <= max_res; r++ )
+		{
+			pos += ratio_;
+			double nearest = floor( pos + 0.5 );
+			double error = fabs( pos - nearest );
+			if ( error < least_error )
+			{
+				res = r;
+				fstep = nearest / res;
+				least_error = error;
+			}
+		}
+	}
+
+	skip_bits = 0;
+
+	step = stereo * (int) floor( fstep );
+
+	ratio_ = fstep;
+	fstep = fmod( fstep, 1.0 );
+
+	double filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
+	double pos = 0.0;
+	input_per_cycle = 0;
+	for ( int i = 0; i < res; i++ )
+	{
+		gen_sinc( rolloff, int (width_ * filter + 1) & ~1, pos, filter,
+				double (0x7FFF * gain * filter),
+				(int) width_, impulses + i * width_ );
+
+		pos += fstep;
+		input_per_cycle += step;
+		if ( pos >= 0.9999999 )
+		{
+			pos -= 1.0;
+			skip_bits |= 1 << i;
+			input_per_cycle++;
+		}
+	}
+
+	clear();
+
+	return ratio_;
+}
+
+int Fir_Resampler_::input_needed( blargg_long output_count ) const
+{
+	blargg_long input_count = 0;
+
+	unsigned long skip = skip_bits >> imp_phase;
+	int remain = res - imp_phase;
+	while ( (output_count -= 2) > 0 )
+	{
+		input_count += step + (skip & 1) * stereo;
+		skip >>= 1;
+		if ( !--remain )
+		{
+			skip = skip_bits;
+			remain = res;
+		}
+		output_count -= 2;
+	}
+
+	long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
+	if ( input_extra < 0 )
+		input_extra = 0;
+	return input_extra;
+}
+
+int Fir_Resampler_::avail_( blargg_long input_count ) const
+{
+	int cycle_count = input_count / input_per_cycle;
+	int output_count = cycle_count * res * stereo;
+	input_count -= cycle_count * input_per_cycle;
+
+	blargg_ulong skip = skip_bits >> imp_phase;
+	int remain = res - imp_phase;
+	while ( input_count >= 0 )
+	{
+		input_count -= step + (skip & 1) * stereo;
+		skip >>= 1;
+		if ( !--remain )
+		{
+			skip = skip_bits;
+			remain = res;
+		}
+		output_count += 2;
+	}
+	return output_count;
+}
+
+int Fir_Resampler_::skip_input( long count )
+{
+	int remain = write_pos - buf.begin();
+	int max_count = remain - width_ * stereo;
+	if ( count > max_count )
+		count = max_count;
+
+	remain -= count;
+	write_pos = &buf [remain];
+	memmove( buf.begin(), &buf [count], remain * sizeof buf [0] );
+
+	return count;
+}
diff --git a/src/console/Fir_Resampler.cxx b/src/console/Fir_Resampler.cxx
deleted file mode 100644
index d8cbc3d246f3..000000000000
--- a/src/console/Fir_Resampler.cxx
+++ /dev/null
@@ -1,199 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Fir_Resampler.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
-		int count, short* out )
-{
-	double const maxh = 256;
-	double const step = PI / maxh * spacing;
-	double const to_w = maxh * 2 / width;
-	double const pow_a_n = pow( rolloff, maxh );
-	scale /= maxh * 2;
-
-	double angle = (count / 2 - 1 + offset) * -step;
-	while ( count-- )
-	{
-		*out++ = 0;
-		double w = angle * to_w;
-		if ( fabs( w ) < PI )
-		{
-			double rolloff_cos_a = rolloff * cos( angle );
-			double num = 1 - rolloff_cos_a -
-					pow_a_n * cos( maxh * angle ) +
-					pow_a_n * rolloff * cos( (maxh - 1) * angle );
-			double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
-			double sinc = scale * num / den - scale;
-
-			out [-1] = (short) (cos( w ) * sinc + sinc);
-		}
-		angle += step;
-	}
-}
-
-Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) :
-	width_( width ),
-	write_offset( width * stereo - stereo ),
-	impulses( impulses_ )
-{
-	write_pos = 0;
-	res       = 1;
-	imp_phase = 0;
-	skip_bits = 0;
-	step      = stereo;
-	ratio_    = 1.0;
-}
-
-Fir_Resampler_::~Fir_Resampler_() { }
-
-void Fir_Resampler_::clear()
-{
-	imp_phase = 0;
-	if ( buf.size() )
-	{
-		write_pos = &buf [write_offset];
-		memset( buf.begin(), 0, write_offset * sizeof buf [0] );
-	}
-}
-
-blargg_err_t Fir_Resampler_::buffer_size( int new_size )
-{
-	RETURN_ERR( buf.resize( new_size + write_offset ) );
-	clear();
-	return 0;
-}
-
-double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gain )
-{
-	ratio_ = new_factor;
-
-	double fstep = 0.0;
-	{
-		double least_error = 2;
-		double pos = 0;
-		res = -1;
-		for ( int r = 1; r <= max_res; r++ )
-		{
-			pos += ratio_;
-			double nearest = floor( pos + 0.5 );
-			double error = fabs( pos - nearest );
-			if ( error < least_error )
-			{
-				res = r;
-				fstep = nearest / res;
-				least_error = error;
-			}
-		}
-	}
-
-	skip_bits = 0;
-
-	step = stereo * (int) floor( fstep );
-
-	ratio_ = fstep;
-	fstep = fmod( fstep, 1.0 );
-
-	double filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
-	double pos = 0.0;
-	input_per_cycle = 0;
-	for ( int i = 0; i < res; i++ )
-	{
-		gen_sinc( rolloff, int (width_ * filter + 1) & ~1, pos, filter,
-				double (0x7FFF * gain * filter),
-				(int) width_, impulses + i * width_ );
-
-		pos += fstep;
-		input_per_cycle += step;
-		if ( pos >= 0.9999999 )
-		{
-			pos -= 1.0;
-			skip_bits |= 1 << i;
-			input_per_cycle++;
-		}
-	}
-
-	clear();
-
-	return ratio_;
-}
-
-int Fir_Resampler_::input_needed( blargg_long output_count ) const
-{
-	blargg_long input_count = 0;
-
-	unsigned long skip = skip_bits >> imp_phase;
-	int remain = res - imp_phase;
-	while ( (output_count -= 2) > 0 )
-	{
-		input_count += step + (skip & 1) * stereo;
-		skip >>= 1;
-		if ( !--remain )
-		{
-			skip = skip_bits;
-			remain = res;
-		}
-		output_count -= 2;
-	}
-
-	long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
-	if ( input_extra < 0 )
-		input_extra = 0;
-	return input_extra;
-}
-
-int Fir_Resampler_::avail_( blargg_long input_count ) const
-{
-	int cycle_count = input_count / input_per_cycle;
-	int output_count = cycle_count * res * stereo;
-	input_count -= cycle_count * input_per_cycle;
-
-	blargg_ulong skip = skip_bits >> imp_phase;
-	int remain = res - imp_phase;
-	while ( input_count >= 0 )
-	{
-		input_count -= step + (skip & 1) * stereo;
-		skip >>= 1;
-		if ( !--remain )
-		{
-			skip = skip_bits;
-			remain = res;
-		}
-		output_count += 2;
-	}
-	return output_count;
-}
-
-int Fir_Resampler_::skip_input( long count )
-{
-	int remain = write_pos - buf.begin();
-	int max_count = remain - width_ * stereo;
-	if ( count > max_count )
-		count = max_count;
-
-	remain -= count;
-	write_pos = &buf [remain];
-	memmove( buf.begin(), &buf [count], remain * sizeof buf [0] );
-
-	return count;
-}
diff --git a/src/console/Gb_Apu.cc b/src/console/Gb_Apu.cc
new file mode 100644
index 000000000000..834977ea9eed
--- /dev/null
+++ b/src/console/Gb_Apu.cc
@@ -0,0 +1,306 @@
+// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
+
+#include "Gb_Apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+unsigned const vol_reg    = 0xFF24;
+unsigned const status_reg = 0xFF26;
+
+Gb_Apu::Gb_Apu()
+{
+	square1.synth = &square_synth;
+	square2.synth = &square_synth;
+	wave.synth  = &other_synth;
+	noise.synth = &other_synth;
+
+	oscs [0] = &square1;
+	oscs [1] = &square2;
+	oscs [2] = &wave;
+	oscs [3] = &noise;
+
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		Gb_Osc& osc = *oscs [i];
+		osc.regs = &regs [i * 5];
+		osc.output = 0;
+		osc.outputs [0] = 0;
+		osc.outputs [1] = 0;
+		osc.outputs [2] = 0;
+		osc.outputs [3] = 0;
+	}
+
+	set_tempo( 1.0 );
+	volume( 1.0 );
+	reset();
+}
+
+void Gb_Apu::treble_eq( const blip_eq_t& eq )
+{
+	square_synth.treble_eq( eq );
+	other_synth.treble_eq( eq );
+}
+
+void Gb_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	require( (unsigned) index < osc_count );
+	require( (center && left && right) || (!center && !left && !right) );
+	Gb_Osc& osc = *oscs [index];
+	osc.outputs [1] = right;
+	osc.outputs [2] = left;
+	osc.outputs [3] = center;
+	osc.output = osc.outputs [osc.output_select];
+}
+
+void Gb_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, center, left, right );
+}
+
+void Gb_Apu::update_volume()
+{
+	// TODO: doesn't handle differing left/right global volume (support would
+	// require modification to all oscillator code)
+	int data = regs [vol_reg - start_addr];
+	double vol = (max( data & 7, data >> 4 & 7 ) + 1) * volume_unit;
+	square_synth.volume( vol );
+	other_synth.volume( vol );
+}
+
+static unsigned char const powerup_regs [0x20] = {
+	0x80,0x3F,0x00,0xFF,0xBF, // square 1
+	0xFF,0x3F,0x00,0xFF,0xBF, // square 2
+	0x7F,0xFF,0x9F,0xFF,0xBF, // wave
+	0xFF,0xFF,0x00,0x00,0xBF, // noise
+	0x00, // left/right enables
+	0x77, // master volume
+	0x80, // power
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+};
+
+void Gb_Apu::set_tempo( double t )
+{
+	frame_period = 4194304 / 256; // 256 Hz
+	if ( t != 1.0 )
+		frame_period = blip_time_t (frame_period / t);
+}
+
+void Gb_Apu::reset()
+{
+	next_frame_time = 0;
+	last_time       = 0;
+	frame_count     = 0;
+
+	square1.reset();
+	square2.reset();
+	wave.reset();
+	noise.reset();
+	noise.bits = 1;
+	wave.wave_pos = 0;
+
+	// avoid click at beginning
+	regs [vol_reg - start_addr] = 0x77;
+	update_volume();
+
+	regs [status_reg - start_addr] = 0x01; // force power
+	write_register( 0, status_reg, 0x00 );
+
+	static unsigned char const initial_wave [] = {
+		0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
+		0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
+	};
+	memcpy( wave.wave, initial_wave, sizeof wave.wave );
+}
+
+void Gb_Apu::run_until( blip_time_t end_time )
+{
+	require( end_time >= last_time ); // end_time must not be before previous time
+	if ( end_time == last_time )
+		return;
+
+	while ( true )
+	{
+		blip_time_t time = next_frame_time;
+		if ( time > end_time )
+			time = end_time;
+
+		// run oscillators
+		for ( int i = 0; i < osc_count; ++i )
+		{
+			Gb_Osc& osc = *oscs [i];
+			if ( osc.output )
+			{
+				osc.output->set_modified(); // TODO: misses optimization opportunities?
+				int playing = false;
+				if ( osc.enabled && osc.volume &&
+						(!(osc.regs [4] & osc.len_enabled_mask) || osc.length) )
+					playing = -1;
+				switch ( i )
+				{
+				case 0: square1.run( last_time, time, playing ); break;
+				case 1: square2.run( last_time, time, playing ); break;
+				case 2: wave   .run( last_time, time, playing ); break;
+				case 3: noise  .run( last_time, time, playing ); break;
+				}
+			}
+		}
+		last_time = time;
+
+		if ( time == end_time )
+			break;
+
+		next_frame_time += frame_period;
+
+		// 256 Hz actions
+		square1.clock_length();
+		square2.clock_length();
+		wave.clock_length();
+		noise.clock_length();
+
+		frame_count = (frame_count + 1) & 3;
+		if ( frame_count == 0 )
+		{
+			// 64 Hz actions
+			square1.clock_envelope();
+			square2.clock_envelope();
+			noise.clock_envelope();
+		}
+
+		if ( frame_count & 1 )
+			square1.clock_sweep(); // 128 Hz action
+	}
+}
+
+void Gb_Apu::end_frame( blip_time_t end_time )
+{
+	if ( end_time > last_time )
+		run_until( end_time );
+
+	assert( next_frame_time >= end_time );
+	next_frame_time -= end_time;
+
+	assert( last_time >= end_time );
+	last_time -= end_time;
+}
+
+void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
+{
+	require( (unsigned) data < 0x100 );
+
+	int reg = addr - start_addr;
+	if ( (unsigned) reg >= register_count )
+		return;
+
+	run_until( time );
+
+	int old_reg = regs [reg];
+	regs [reg] = data;
+
+	if ( addr < vol_reg )
+	{
+		write_osc( reg / 5, reg, data );
+	}
+	else if ( addr == vol_reg && data != old_reg ) // global volume
+	{
+		// return all oscs to 0
+		for ( int i = 0; i < osc_count; i++ )
+		{
+			Gb_Osc& osc = *oscs [i];
+			int amp = osc.last_amp;
+			osc.last_amp = 0;
+			if ( amp && osc.enabled && osc.output )
+				other_synth.offset( time, -amp, osc.output );
+		}
+
+		if ( wave.outputs [3] )
+			other_synth.offset( time, 30, wave.outputs [3] );
+
+		update_volume();
+
+		if ( wave.outputs [3] )
+			other_synth.offset( time, -30, wave.outputs [3] );
+
+		// oscs will update with new amplitude when next run
+	}
+	else if ( addr == 0xFF25 || addr == status_reg )
+	{
+		int mask = (regs [status_reg - start_addr] & 0x80) ? ~0 : 0;
+		int flags = regs [0xFF25 - start_addr] & mask;
+
+		// left/right assignments
+		for ( int i = 0; i < osc_count; i++ )
+		{
+			Gb_Osc& osc = *oscs [i];
+			osc.enabled &= mask;
+			int bits = flags >> i;
+			Blip_Buffer* old_output = osc.output;
+			osc.output_select = (bits >> 3 & 2) | (bits & 1);
+			osc.output = osc.outputs [osc.output_select];
+			if ( osc.output != old_output )
+			{
+				int amp = osc.last_amp;
+				osc.last_amp = 0;
+				if ( amp && old_output )
+					other_synth.offset( time, -amp, old_output );
+			}
+		}
+
+		if ( addr == status_reg && data != old_reg )
+		{
+			if ( !(data & 0x80) )
+			{
+				for ( unsigned i = 0; i < sizeof powerup_regs; i++ )
+				{
+					if ( i != status_reg - start_addr )
+						write_register( time, i + start_addr, powerup_regs [i] );
+				}
+			}
+			else
+			{
+				//debug_printf( "APU powered on\n" );
+			}
+		}
+	}
+	else if ( addr >= 0xFF30 )
+	{
+		int index = (addr & 0x0F) * 2;
+		wave.wave [index] = data >> 4;
+		wave.wave [index + 1] = data & 0x0F;
+	}
+}
+
+int Gb_Apu::read_register( blip_time_t time, unsigned addr )
+{
+	run_until( time );
+
+	int index = addr - start_addr;
+	require( (unsigned) index < register_count );
+	int data = regs [index];
+
+	if ( addr == status_reg )
+	{
+		data = (data & 0x80) | 0x70;
+		for ( int i = 0; i < osc_count; i++ )
+		{
+			const Gb_Osc& osc = *oscs [i];
+			if ( osc.enabled && (osc.length || !(osc.regs [4] & osc.len_enabled_mask)) )
+				data |= 1 << i;
+		}
+	}
+
+	return data;
+}
diff --git a/src/console/Gb_Apu.cxx b/src/console/Gb_Apu.cxx
deleted file mode 100644
index 834977ea9eed..000000000000
--- a/src/console/Gb_Apu.cxx
+++ /dev/null
@@ -1,306 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const vol_reg    = 0xFF24;
-unsigned const status_reg = 0xFF26;
-
-Gb_Apu::Gb_Apu()
-{
-	square1.synth = &square_synth;
-	square2.synth = &square_synth;
-	wave.synth  = &other_synth;
-	noise.synth = &other_synth;
-
-	oscs [0] = &square1;
-	oscs [1] = &square2;
-	oscs [2] = &wave;
-	oscs [3] = &noise;
-
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		Gb_Osc& osc = *oscs [i];
-		osc.regs = &regs [i * 5];
-		osc.output = 0;
-		osc.outputs [0] = 0;
-		osc.outputs [1] = 0;
-		osc.outputs [2] = 0;
-		osc.outputs [3] = 0;
-	}
-
-	set_tempo( 1.0 );
-	volume( 1.0 );
-	reset();
-}
-
-void Gb_Apu::treble_eq( const blip_eq_t& eq )
-{
-	square_synth.treble_eq( eq );
-	other_synth.treble_eq( eq );
-}
-
-void Gb_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	require( (unsigned) index < osc_count );
-	require( (center && left && right) || (!center && !left && !right) );
-	Gb_Osc& osc = *oscs [index];
-	osc.outputs [1] = right;
-	osc.outputs [2] = left;
-	osc.outputs [3] = center;
-	osc.output = osc.outputs [osc.output_select];
-}
-
-void Gb_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, center, left, right );
-}
-
-void Gb_Apu::update_volume()
-{
-	// TODO: doesn't handle differing left/right global volume (support would
-	// require modification to all oscillator code)
-	int data = regs [vol_reg - start_addr];
-	double vol = (max( data & 7, data >> 4 & 7 ) + 1) * volume_unit;
-	square_synth.volume( vol );
-	other_synth.volume( vol );
-}
-
-static unsigned char const powerup_regs [0x20] = {
-	0x80,0x3F,0x00,0xFF,0xBF, // square 1
-	0xFF,0x3F,0x00,0xFF,0xBF, // square 2
-	0x7F,0xFF,0x9F,0xFF,0xBF, // wave
-	0xFF,0xFF,0x00,0x00,0xBF, // noise
-	0x00, // left/right enables
-	0x77, // master volume
-	0x80, // power
-	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-void Gb_Apu::set_tempo( double t )
-{
-	frame_period = 4194304 / 256; // 256 Hz
-	if ( t != 1.0 )
-		frame_period = blip_time_t (frame_period / t);
-}
-
-void Gb_Apu::reset()
-{
-	next_frame_time = 0;
-	last_time       = 0;
-	frame_count     = 0;
-
-	square1.reset();
-	square2.reset();
-	wave.reset();
-	noise.reset();
-	noise.bits = 1;
-	wave.wave_pos = 0;
-
-	// avoid click at beginning
-	regs [vol_reg - start_addr] = 0x77;
-	update_volume();
-
-	regs [status_reg - start_addr] = 0x01; // force power
-	write_register( 0, status_reg, 0x00 );
-
-	static unsigned char const initial_wave [] = {
-		0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
-		0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
-	};
-	memcpy( wave.wave, initial_wave, sizeof wave.wave );
-}
-
-void Gb_Apu::run_until( blip_time_t end_time )
-{
-	require( end_time >= last_time ); // end_time must not be before previous time
-	if ( end_time == last_time )
-		return;
-
-	while ( true )
-	{
-		blip_time_t time = next_frame_time;
-		if ( time > end_time )
-			time = end_time;
-
-		// run oscillators
-		for ( int i = 0; i < osc_count; ++i )
-		{
-			Gb_Osc& osc = *oscs [i];
-			if ( osc.output )
-			{
-				osc.output->set_modified(); // TODO: misses optimization opportunities?
-				int playing = false;
-				if ( osc.enabled && osc.volume &&
-						(!(osc.regs [4] & osc.len_enabled_mask) || osc.length) )
-					playing = -1;
-				switch ( i )
-				{
-				case 0: square1.run( last_time, time, playing ); break;
-				case 1: square2.run( last_time, time, playing ); break;
-				case 2: wave   .run( last_time, time, playing ); break;
-				case 3: noise  .run( last_time, time, playing ); break;
-				}
-			}
-		}
-		last_time = time;
-
-		if ( time == end_time )
-			break;
-
-		next_frame_time += frame_period;
-
-		// 256 Hz actions
-		square1.clock_length();
-		square2.clock_length();
-		wave.clock_length();
-		noise.clock_length();
-
-		frame_count = (frame_count + 1) & 3;
-		if ( frame_count == 0 )
-		{
-			// 64 Hz actions
-			square1.clock_envelope();
-			square2.clock_envelope();
-			noise.clock_envelope();
-		}
-
-		if ( frame_count & 1 )
-			square1.clock_sweep(); // 128 Hz action
-	}
-}
-
-void Gb_Apu::end_frame( blip_time_t end_time )
-{
-	if ( end_time > last_time )
-		run_until( end_time );
-
-	assert( next_frame_time >= end_time );
-	next_frame_time -= end_time;
-
-	assert( last_time >= end_time );
-	last_time -= end_time;
-}
-
-void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
-{
-	require( (unsigned) data < 0x100 );
-
-	int reg = addr - start_addr;
-	if ( (unsigned) reg >= register_count )
-		return;
-
-	run_until( time );
-
-	int old_reg = regs [reg];
-	regs [reg] = data;
-
-	if ( addr < vol_reg )
-	{
-		write_osc( reg / 5, reg, data );
-	}
-	else if ( addr == vol_reg && data != old_reg ) // global volume
-	{
-		// return all oscs to 0
-		for ( int i = 0; i < osc_count; i++ )
-		{
-			Gb_Osc& osc = *oscs [i];
-			int amp = osc.last_amp;
-			osc.last_amp = 0;
-			if ( amp && osc.enabled && osc.output )
-				other_synth.offset( time, -amp, osc.output );
-		}
-
-		if ( wave.outputs [3] )
-			other_synth.offset( time, 30, wave.outputs [3] );
-
-		update_volume();
-
-		if ( wave.outputs [3] )
-			other_synth.offset( time, -30, wave.outputs [3] );
-
-		// oscs will update with new amplitude when next run
-	}
-	else if ( addr == 0xFF25 || addr == status_reg )
-	{
-		int mask = (regs [status_reg - start_addr] & 0x80) ? ~0 : 0;
-		int flags = regs [0xFF25 - start_addr] & mask;
-
-		// left/right assignments
-		for ( int i = 0; i < osc_count; i++ )
-		{
-			Gb_Osc& osc = *oscs [i];
-			osc.enabled &= mask;
-			int bits = flags >> i;
-			Blip_Buffer* old_output = osc.output;
-			osc.output_select = (bits >> 3 & 2) | (bits & 1);
-			osc.output = osc.outputs [osc.output_select];
-			if ( osc.output != old_output )
-			{
-				int amp = osc.last_amp;
-				osc.last_amp = 0;
-				if ( amp && old_output )
-					other_synth.offset( time, -amp, old_output );
-			}
-		}
-
-		if ( addr == status_reg && data != old_reg )
-		{
-			if ( !(data & 0x80) )
-			{
-				for ( unsigned i = 0; i < sizeof powerup_regs; i++ )
-				{
-					if ( i != status_reg - start_addr )
-						write_register( time, i + start_addr, powerup_regs [i] );
-				}
-			}
-			else
-			{
-				//debug_printf( "APU powered on\n" );
-			}
-		}
-	}
-	else if ( addr >= 0xFF30 )
-	{
-		int index = (addr & 0x0F) * 2;
-		wave.wave [index] = data >> 4;
-		wave.wave [index + 1] = data & 0x0F;
-	}
-}
-
-int Gb_Apu::read_register( blip_time_t time, unsigned addr )
-{
-	run_until( time );
-
-	int index = addr - start_addr;
-	require( (unsigned) index < register_count );
-	int data = regs [index];
-
-	if ( addr == status_reg )
-	{
-		data = (data & 0x80) | 0x70;
-		for ( int i = 0; i < osc_count; i++ )
-		{
-			const Gb_Osc& osc = *oscs [i];
-			if ( osc.enabled && (osc.length || !(osc.regs [4] & osc.len_enabled_mask)) )
-				data |= 1 << i;
-		}
-	}
-
-	return data;
-}
diff --git a/src/console/Gb_Apu.h b/src/console/Gb_Apu.h
index 557ef8bd556c..b2695385e8c0 100644
--- a/src/console/Gb_Apu.h
+++ b/src/console/Gb_Apu.h
@@ -19,12 +19,12 @@ public:
 	// buffers for stereo output (using Stereo_Buffer to do the mixing).
 
 	// Assign all oscillator outputs to specified buffer(s). If buffer
-	// is NULL, silences all oscillators.
+	// is nullptr, silences all oscillators.
 	void output( Blip_Buffer* mono );
 	void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
 
 	// Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
-	// which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL,
+	// which refer to Square 1, Square 2, Wave, and Noise. If buffer is nullptr,
 	// silences oscillator.
 	enum { osc_count = 4 };
 	void osc_output( int index, Blip_Buffer* mono );
diff --git a/src/console/Gb_Cpu.cc b/src/console/Gb_Cpu.cc
new file mode 100644
index 000000000000..9954b5026a33
--- /dev/null
+++ b/src/console/Gb_Cpu.cc
@@ -0,0 +1,1052 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Gb_Cpu.h"
+
+#include <string.h>
+
+//#include "gb_cpu_log.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "gb_cpu_io.h"
+
+#include "blargg_source.h"
+
+// Common instructions:
+//
+// 365880   FA      LD  A,IND16
+// 355863   20      JR  NZ
+// 313655   21      LD  HL,IMM
+// 274580   28      JR  Z
+// 252878   FE      CMP IMM
+// 230541   7E      LD  A,(HL)
+// 226209   2A      LD A,(HL+)
+// 217467   CD      CALL
+// 212034   C9      RET
+// 208376   CB      CB prefix
+//
+//  27486   CB 7E   BIT 7,(HL)
+//  15925   CB 76   BIT 6,(HL)
+//  13035   CB 19   RR  C
+//  11557   CB 7F   BIT 7,A
+//  10898   CB 37   SWAP A
+//  10208   CB 66   BIT 4,(HL)
+
+#if BLARGG_NONPORTABLE
+	#define PAGE_OFFSET( addr ) (addr)
+#else
+	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
+#endif
+
+inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
+{
+	state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size );
+}
+
+void Gb_Cpu::reset( void* unmapped )
+{
+	check( state == &state_ );
+	state = &state_;
+
+	state_.remain = 0;
+
+	for ( int i = 0; i < page_count + 1; i++ )
+		set_code_page( i, (uint8_t*) unmapped );
+
+	memset( &r, 0, sizeof r );
+	//interrupts_enabled = false;
+}
+
+void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
+{
+	// address range must begin and end on page boundaries
+	require( start % page_size == 0 );
+	require( size % page_size == 0 );
+
+	unsigned first_page = start / page_size;
+	for ( unsigned i = size / page_size; i--; )
+		set_code_page( first_page + i, (uint8_t*) data + i * page_size );
+}
+
+#define READ( addr )            CPU_READ( this, (addr), s.remain )
+#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), s.remain );}
+#define READ_FAST( addr, out )  CPU_READ_FAST( this, (addr), s.remain, out )
+#define READ_PROG( addr )       (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
+
+unsigned const z_flag = 0x80;
+unsigned const n_flag = 0x40;
+unsigned const h_flag = 0x20;
+unsigned const c_flag = 0x10;
+
+bool Gb_Cpu::run( blargg_long cycle_count )
+{
+	state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
+	state_t s;
+	this->state = &s;
+	memcpy( &s, &this->state_, sizeof s );
+
+#if BLARGG_BIG_ENDIAN
+	#define R8( n ) (r8_ [n])
+#elif BLARGG_LITTLE_ENDIAN
+	#define R8( n ) (r8_ [(n) ^ 1])
+#else
+	#error "Byte order of CPU must be known"
+#endif
+
+	union {
+		core_regs_t rg; // individual registers
+
+		struct {
+			uint16_t bc, de, hl, unused; // pairs
+		} rp;
+
+		uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
+		uint16_t r16 [4]; // indexed pairs
+	};
+	BOOST_STATIC_ASSERT( sizeof rg == 8 && sizeof rp == 8 );
+
+	rg = r;
+	unsigned pc = r.pc;
+	unsigned sp = r.sp;
+	unsigned flags = r.flags;
+
+loop:
+
+	check( (unsigned long) pc < 0x10000 );
+	check( (unsigned long) sp < 0x10000 );
+	check( (flags & ~0xF0) == 0 );
+
+	uint8_t const* instr = s.code_map [pc >> page_shift];
+	unsigned op;
+
+	// TODO: eliminate this special case
+	#if BLARGG_NONPORTABLE
+		op = instr [pc];
+		pc++;
+		instr += pc;
+	#else
+		instr += PAGE_OFFSET( pc );
+		op = *instr++;
+		pc++;
+	#endif
+
+#define GET_ADDR()  GET_LE16( instr )
+
+	if ( !--s.remain )
+		goto stop;
+
+	unsigned data;
+	data = *instr;
+
+	#ifdef GB_CPU_LOG_H
+		gb_cpu_log( "new", pc - 1, op, data, instr [1] );
+	#endif
+
+	switch ( op )
+	{
+
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define BRANCH( cond )\
+{\
+	pc++;\
+	int offset = (int8_t) data;\
+	if ( !(cond) ) goto loop;\
+	pc = uint16_t (pc + offset);\
+	goto loop;\
+}
+
+// Most Common
+
+	case 0x20: // JR NZ
+		BRANCH( !(flags & z_flag) )
+
+	case 0x21: // LD HL,IMM (common)
+		rp.hl = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x28: // JR Z
+		BRANCH( flags & z_flag )
+
+	{
+		unsigned temp;
+	case 0xF0: // LD A,(0xFF00+imm)
+		temp = data | 0xFF00;
+		pc++;
+		goto ld_a_ind_comm;
+
+	case 0xF2: // LD A,(0xFF00+C)
+		temp = rg.c | 0xFF00;
+		goto ld_a_ind_comm;
+
+	case 0x0A: // LD A,(BC)
+		temp = rp.bc;
+		goto ld_a_ind_comm;
+
+	case 0x3A: // LD A,(HL-)
+		temp = rp.hl;
+		rp.hl = temp - 1;
+		goto ld_a_ind_comm;
+
+	case 0x1A: // LD A,(DE)
+		temp = rp.de;
+		goto ld_a_ind_comm;
+
+	case 0x2A: // LD A,(HL+) (common)
+		temp = rp.hl;
+		rp.hl = temp + 1;
+		goto ld_a_ind_comm;
+
+	case 0xFA: // LD A,IND16 (common)
+		temp = GET_ADDR();
+		pc += 2;
+	ld_a_ind_comm:
+		READ_FAST( temp, rg.a );
+		goto loop;
+	}
+
+	case 0xBE: // CMP (HL)
+		data = READ( rp.hl );
+		goto cmp_comm;
+
+	case 0xB8: // CMP B
+	case 0xB9: // CMP C
+	case 0xBA: // CMP D
+	case 0xBB: // CMP E
+	case 0xBC: // CMP H
+	case 0xBD: // CMP L
+		data = R8( op & 7 );
+		goto cmp_comm;
+
+	case 0xFE: // CMP IMM
+		pc++;
+	cmp_comm:
+		op = rg.a;
+		data = op - data;
+	sub_set_flags:
+		flags = ((op & 15) - (data & 15)) & h_flag;
+		flags |= (data >> 4) & c_flag;
+		flags |= n_flag;
+		if ( data & 0xFF )
+			goto loop;
+		flags |= z_flag;
+		goto loop;
+
+	case 0x46: // LD B,(HL)
+	case 0x4E: // LD C,(HL)
+	case 0x56: // LD D,(HL)
+	case 0x5E: // LD E,(HL)
+	case 0x66: // LD H,(HL)
+	case 0x6E: // LD L,(HL)
+	case 0x7E:{// LD A,(HL)
+		unsigned addr = rp.hl;
+		READ_FAST( addr, R8( (op >> 3) & 7 ) );
+		goto loop;
+	}
+
+	case 0xC4: // CNZ (next-most-common)
+		pc += 2;
+		if ( flags & z_flag )
+			goto loop;
+	call:
+		pc -= 2;
+	case 0xCD: // CALL (most-common)
+		data = pc + 2;
+		pc = GET_ADDR();
+	push:
+		sp = (sp - 1) & 0xFFFF;
+		WRITE( sp, data >> 8 );
+		sp = (sp - 1) & 0xFFFF;
+		WRITE( sp, data & 0xFF );
+		goto loop;
+
+	case 0xC8: // RNZ (next-most-common)
+		if ( !(flags & z_flag) )
+			goto loop;
+	case 0xC9: // RET (most common)
+	ret:
+		pc = READ( sp );
+		pc += 0x100 * READ( sp + 1 );
+		sp = (sp + 2) & 0xFFFF;
+		goto loop;
+
+	case 0x00: // NOP
+	case 0x40: // LD B,B
+	case 0x49: // LD C,C
+	case 0x52: // LD D,D
+	case 0x5B: // LD E,E
+	case 0x64: // LD H,H
+	case 0x6D: // LD L,L
+	case 0x7F: // LD A,A
+		goto loop;
+
+// CB Instructions
+
+	case 0xCB:
+		pc++;
+		// now data is the opcode
+		switch ( data ) {
+
+		{
+			int temp;
+		case 0x46: // BIT b,(HL)
+		case 0x4E:
+		case 0x56:
+		case 0x5E:
+		case 0x66:
+		case 0x6E:
+		case 0x76:
+		case 0x7E:
+			{
+				unsigned addr = rp.hl;
+				READ_FAST( addr, temp );
+				goto bit_comm;
+			}
+
+		case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
+		case 0x44: case 0x45: case 0x47: case 0x48:
+		case 0x49: case 0x4A: case 0x4B: case 0x4C:
+		case 0x4D: case 0x4F: case 0x50: case 0x51:
+		case 0x52: case 0x53: case 0x54: case 0x55:
+		case 0x57: case 0x58: case 0x59: case 0x5A:
+		case 0x5B: case 0x5C: case 0x5D: case 0x5F:
+		case 0x60: case 0x61: case 0x62: case 0x63:
+		case 0x64: case 0x65: case 0x67: case 0x68:
+		case 0x69: case 0x6A: case 0x6B: case 0x6C:
+		case 0x6D: case 0x6F: case 0x70: case 0x71:
+		case 0x72: case 0x73: case 0x74: case 0x75:
+		case 0x77: case 0x78: case 0x79: case 0x7A:
+		case 0x7B: case 0x7C: case 0x7D: case 0x7F:
+			temp = R8( data & 7 );
+		bit_comm:
+			int bit = (~data >> 3) & 7;
+			flags &= ~n_flag;
+			flags |= h_flag | z_flag;
+			flags ^= (temp << bit) & z_flag;
+			goto loop;
+		}
+
+		case 0x86: // RES b,(HL)
+		case 0x8E:
+		case 0x96:
+		case 0x9E:
+		case 0xA6:
+		case 0xAE:
+		case 0xB6:
+		case 0xBE:
+		case 0xC6: // SET b,(HL)
+		case 0xCE:
+		case 0xD6:
+		case 0xDE:
+		case 0xE6:
+		case 0xEE:
+		case 0xF6:
+		case 0xFE: {
+			int temp = READ( rp.hl );
+			int bit = 1 << ((data >> 3) & 7);
+			temp &= ~bit;
+			if ( !(data & 0x40) )
+				bit = 0;
+			WRITE( rp.hl, temp | bit );
+			goto loop;
+		}
+
+		case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
+		case 0xC4: case 0xC5: case 0xC7: case 0xC8:
+		case 0xC9: case 0xCA: case 0xCB: case 0xCC:
+		case 0xCD: case 0xCF: case 0xD0: case 0xD1:
+		case 0xD2: case 0xD3: case 0xD4: case 0xD5:
+		case 0xD7: case 0xD8: case 0xD9: case 0xDA:
+		case 0xDB: case 0xDC: case 0xDD: case 0xDF:
+		case 0xE0: case 0xE1: case 0xE2: case 0xE3:
+		case 0xE4: case 0xE5: case 0xE7: case 0xE8:
+		case 0xE9: case 0xEA: case 0xEB: case 0xEC:
+		case 0xED: case 0xEF: case 0xF0: case 0xF1:
+		case 0xF2: case 0xF3: case 0xF4: case 0xF5:
+		case 0xF7: case 0xF8: case 0xF9: case 0xFA:
+		case 0xFB: case 0xFC: case 0xFD: case 0xFF:
+			R8( data & 7 ) |= 1 << ((data >> 3) & 7);
+			goto loop;
+
+		case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
+		case 0x84: case 0x85: case 0x87: case 0x88:
+		case 0x89: case 0x8A: case 0x8B: case 0x8C:
+		case 0x8D: case 0x8F: case 0x90: case 0x91:
+		case 0x92: case 0x93: case 0x94: case 0x95:
+		case 0x97: case 0x98: case 0x99: case 0x9A:
+		case 0x9B: case 0x9C: case 0x9D: case 0x9F:
+		case 0xA0: case 0xA1: case 0xA2: case 0xA3:
+		case 0xA4: case 0xA5: case 0xA7: case 0xA8:
+		case 0xA9: case 0xAA: case 0xAB: case 0xAC:
+		case 0xAD: case 0xAF: case 0xB0: case 0xB1:
+		case 0xB2: case 0xB3: case 0xB4: case 0xB5:
+		case 0xB7: case 0xB8: case 0xB9: case 0xBA:
+		case 0xBB: case 0xBC: case 0xBD: case 0xBF:
+			R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
+			goto loop;
+
+		{
+			int temp;
+		case 0x36: // SWAP (HL)
+			temp = READ( rp.hl );
+			goto swap_comm;
+
+		case 0x30: // SWAP B
+		case 0x31: // SWAP C
+		case 0x32: // SWAP D
+		case 0x33: // SWAP E
+		case 0x34: // SWAP H
+		case 0x35: // SWAP L
+		case 0x37: // SWAP A
+			temp = R8( data & 7 );
+		swap_comm:
+			op = (temp >> 4) | (temp << 4);
+			flags = 0;
+			goto shift_comm;
+		}
+
+// Shift/Rotate
+
+		case 0x06: // RLC (HL)
+		case 0x16: // RL (HL)
+		case 0x26: // SLA (HL)
+			op = READ( rp.hl );
+			goto rl_comm;
+
+		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
+		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
+		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
+			op = R8( data & 7 );
+			goto rl_comm;
+
+		case 0x3E: // SRL (HL)
+			data += 0x10; // bump up to 0x4n to avoid preserving sign bit
+		case 0x1E: // RR (HL)
+		case 0x0E: // RRC (HL)
+		case 0x2E: // SRA (HL)
+			op = READ( rp.hl );
+			goto rr_comm;
+
+		case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
+			data += 0x10; // bump up to 0x4n
+		case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
+		case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
+		case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
+			op = R8( data & 7 );
+			goto rr_comm;
+
+	} // CB op
+	assert( false ); // unhandled CB op
+
+	case 0x07: // RLCA
+	case 0x17: // RLA
+		data = op;
+		op = rg.a;
+	rl_comm:
+		op <<= 1;
+		op |= ((data & flags) >> 4) & 1; // RL and carry is set
+		flags = (op >> 4) & c_flag; // C = bit shifted out
+		if ( data < 0x10 ) // RLC
+			op |= op >> 8;
+		// SLA doesn't fill lower bit
+		goto shift_comm;
+
+	case 0x0F: // RRCA
+	case 0x1F: // RRA
+		data = op;
+		op = rg.a;
+	rr_comm:
+		op |= (data & flags) << 4; // RR and carry is set
+		flags = (op << 4) & c_flag; // C = bit shifted out
+		if ( data < 0x10 ) // RRC
+			op |= op << 8;
+		op >>= 1;
+		if ( data & 0x20 ) // SRA propagates sign bit
+			op |= (op << 1) & 0x80;
+	shift_comm:
+		data &= 7;
+		if ( !(op & 0xFF) )
+			flags |= z_flag;
+		if ( data == 6 )
+			goto write_hl_op_ff;
+		R8( data ) = op;
+		goto loop;
+
+// Load
+
+	case 0x70: // LD (HL),B
+	case 0x71: // LD (HL),C
+	case 0x72: // LD (HL),D
+	case 0x73: // LD (HL),E
+	case 0x74: // LD (HL),H
+	case 0x75: // LD (HL),L
+	case 0x77: // LD (HL),A
+		op = R8( op & 7 );
+	write_hl_op_ff:
+		WRITE( rp.hl, op & 0xFF );
+		goto loop;
+
+	case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
+	case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
+	case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
+	case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
+	case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
+	case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
+	case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
+		R8( (op >> 3) & 7 ) = R8( op & 7 );
+		goto loop;
+
+	case 0x08: // LD IND16,SP
+		data = GET_ADDR();
+		pc += 2;
+		WRITE( data, sp&0xFF );
+		data++;
+		WRITE( data, sp >> 8 );
+		goto loop;
+
+	case 0xF9: // LD SP,HL
+		sp = rp.hl;
+		goto loop;
+
+	case 0x31: // LD SP,IMM
+		sp = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x01: // LD BC,IMM
+	case 0x11: // LD DE,IMM
+		r16 [op >> 4] = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	{
+		unsigned temp;
+	case 0xE0: // LD (0xFF00+imm),A
+		temp = data | 0xFF00;
+		pc++;
+		goto write_data_rg_a;
+
+	case 0xE2: // LD (0xFF00+C),A
+		temp = rg.c | 0xFF00;
+		goto write_data_rg_a;
+
+	case 0x32: // LD (HL-),A
+		temp = rp.hl;
+		rp.hl = temp - 1;
+		goto write_data_rg_a;
+
+	case 0x02: // LD (BC),A
+		temp = rp.bc;
+		goto write_data_rg_a;
+
+	case 0x12: // LD (DE),A
+		temp = rp.de;
+		goto write_data_rg_a;
+
+	case 0x22: // LD (HL+),A
+		temp = rp.hl;
+		rp.hl = temp + 1;
+		goto write_data_rg_a;
+
+	case 0xEA: // LD IND16,A (common)
+		temp = GET_ADDR();
+		pc += 2;
+	write_data_rg_a:
+		WRITE( temp, rg.a );
+		goto loop;
+	}
+
+	case 0x06: // LD B,IMM
+		rg.b = data;
+		pc++;
+		goto loop;
+
+	case 0x0E: // LD C,IMM
+		rg.c = data;
+		pc++;
+		goto loop;
+
+	case 0x16: // LD D,IMM
+		rg.d = data;
+		pc++;
+		goto loop;
+
+	case 0x1E: // LD E,IMM
+		rg.e = data;
+		pc++;
+		goto loop;
+
+	case 0x26: // LD H,IMM
+		rg.h = data;
+		pc++;
+		goto loop;
+
+	case 0x2E: // LD L,IMM
+		rg.l = data;
+		pc++;
+		goto loop;
+
+	case 0x36: // LD (HL),IMM
+		WRITE( rp.hl, data );
+		pc++;
+		goto loop;
+
+	case 0x3E: // LD A,IMM
+		rg.a = data;
+		pc++;
+		goto loop;
+
+// Increment/Decrement
+
+	case 0x03: // INC BC
+	case 0x13: // INC DE
+	case 0x23: // INC HL
+		r16 [op >> 4]++;
+		goto loop;
+
+	case 0x33: // INC SP
+		sp = (sp + 1) & 0xFFFF;
+		goto loop;
+
+	case 0x0B: // DEC BC
+	case 0x1B: // DEC DE
+	case 0x2B: // DEC HL
+		r16 [op >> 4]--;
+		goto loop;
+
+	case 0x3B: // DEC SP
+		sp = (sp - 1) & 0xFFFF;
+		goto loop;
+
+	case 0x34: // INC (HL)
+		op = rp.hl;
+		data = READ( op );
+		data++;
+		WRITE( op, data & 0xFF );
+		goto inc_comm;
+
+	case 0x04: // INC B
+	case 0x0C: // INC C (common)
+	case 0x14: // INC D
+	case 0x1C: // INC E
+	case 0x24: // INC H
+	case 0x2C: // INC L
+	case 0x3C: // INC A
+		op = (op >> 3) & 7;
+		R8( op ) = data = R8( op ) + 1;
+	inc_comm:
+		flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
+		goto loop;
+
+	case 0x35: // DEC (HL)
+		op = rp.hl;
+		data = READ( op );
+		data--;
+		WRITE( op, data & 0xFF );
+		goto dec_comm;
+
+	case 0x05: // DEC B
+	case 0x0D: // DEC C
+	case 0x15: // DEC D
+	case 0x1D: // DEC E
+	case 0x25: // DEC H
+	case 0x2D: // DEC L
+	case 0x3D: // DEC A
+		op = (op >> 3) & 7;
+		data = R8( op ) - 1;
+		R8( op ) = data;
+	dec_comm:
+		flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
+		if ( data & 0xFF )
+			goto loop;
+		flags |= z_flag;
+		goto loop;
+
+// Add 16-bit
+
+	{
+		blargg_ulong temp; // need more than 16 bits for carry
+		unsigned prev;
+
+	case 0xF8: // LD HL,SP+imm
+		temp = int8_t (data); // sign-extend to 16 bits
+		pc++;
+		flags = 0;
+		temp += sp;
+		prev = sp;
+		goto add_16_hl;
+
+	case 0xE8: // ADD SP,IMM
+		temp = int8_t (data); // sign-extend to 16 bits
+		pc++;
+		flags = 0;
+		temp += sp;
+		prev = sp;
+		sp = temp & 0xFFFF;
+		goto add_16_comm;
+
+	case 0x39: // ADD HL,SP
+		temp = sp;
+		goto add_hl_comm;
+
+	case 0x09: // ADD HL,BC
+	case 0x19: // ADD HL,DE
+	case 0x29: // ADD HL,HL
+		temp = r16 [op >> 4];
+	add_hl_comm:
+		prev = rp.hl;
+		temp += prev;
+		flags &= z_flag;
+	add_16_hl:
+		rp.hl = temp;
+	add_16_comm:
+		flags |= (temp >> 12) & c_flag;
+		flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;
+		goto loop;
+	}
+
+	case 0x86: // ADD (HL)
+		data = READ( rp.hl );
+		goto add_comm;
+
+	case 0x80: // ADD B
+	case 0x81: // ADD C
+	case 0x82: // ADD D
+	case 0x83: // ADD E
+	case 0x84: // ADD H
+	case 0x85: // ADD L
+	case 0x87: // ADD A
+		data = R8( op & 7 );
+		goto add_comm;
+
+	case 0xC6: // ADD IMM
+		pc++;
+	add_comm:
+		flags = rg.a;
+		data += flags;
+		flags = ((data & 15) - (flags & 15)) & h_flag;
+		flags |= (data >> 4) & c_flag;
+		rg.a = data;
+		if ( data & 0xFF )
+			goto loop;
+		flags |= z_flag;
+		goto loop;
+
+// Add/Subtract
+
+	case 0x8E: // ADC (HL)
+		data = READ( rp.hl );
+		goto adc_comm;
+
+	case 0x88: // ADC B
+	case 0x89: // ADC C
+	case 0x8A: // ADC D
+	case 0x8B: // ADC E
+	case 0x8C: // ADC H
+	case 0x8D: // ADC L
+	case 0x8F: // ADC A
+		data = R8( op & 7 );
+		goto adc_comm;
+
+	case 0xCE: // ADC IMM
+		pc++;
+	adc_comm:
+		data += (flags >> 4) & 1;
+		data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
+		goto add_comm;
+
+	case 0x96: // SUB (HL)
+		data = READ( rp.hl );
+		goto sub_comm;
+
+	case 0x90: // SUB B
+	case 0x91: // SUB C
+	case 0x92: // SUB D
+	case 0x93: // SUB E
+	case 0x94: // SUB H
+	case 0x95: // SUB L
+	case 0x97: // SUB A
+		data = R8( op & 7 );
+		goto sub_comm;
+
+	case 0xD6: // SUB IMM
+		pc++;
+	sub_comm:
+		op = rg.a;
+		data = op - data;
+		rg.a = data;
+		goto sub_set_flags;
+
+	case 0x9E: // SBC (HL)
+		data = READ( rp.hl );
+		goto sbc_comm;
+
+	case 0x98: // SBC B
+	case 0x99: // SBC C
+	case 0x9A: // SBC D
+	case 0x9B: // SBC E
+	case 0x9C: // SBC H
+	case 0x9D: // SBC L
+	case 0x9F: // SBC A
+		data = R8( op & 7 );
+		goto sbc_comm;
+
+	case 0xDE: // SBC IMM
+		pc++;
+	sbc_comm:
+		data += (flags >> 4) & 1;
+		data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
+		goto sub_comm;
+
+// Logical
+
+	case 0xA0: // AND B
+	case 0xA1: // AND C
+	case 0xA2: // AND D
+	case 0xA3: // AND E
+	case 0xA4: // AND H
+	case 0xA5: // AND L
+		data = R8( op & 7 );
+		goto and_comm;
+
+	case 0xA6: // AND (HL)
+		data = READ( rp.hl );
+		pc--;
+	case 0xE6: // AND IMM
+		pc++;
+	and_comm:
+		rg.a &= data;
+	case 0xA7: // AND A
+		flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
+		goto loop;
+
+	case 0xB0: // OR B
+	case 0xB1: // OR C
+	case 0xB2: // OR D
+	case 0xB3: // OR E
+	case 0xB4: // OR H
+	case 0xB5: // OR L
+		data = R8( op & 7 );
+		goto or_comm;
+
+	case 0xB6: // OR (HL)
+		data = READ( rp.hl );
+		pc--;
+	case 0xF6: // OR IMM
+		pc++;
+	or_comm:
+		rg.a |= data;
+	case 0xB7: // OR A
+		flags = ((rg.a - 1) >> 1) & z_flag;
+		goto loop;
+
+	case 0xA8: // XOR B
+	case 0xA9: // XOR C
+	case 0xAA: // XOR D
+	case 0xAB: // XOR E
+	case 0xAC: // XOR H
+	case 0xAD: // XOR L
+		data = R8( op & 7 );
+		goto xor_comm;
+
+	case 0xAE: // XOR (HL)
+		data = READ( rp.hl );
+		pc--;
+	case 0xEE: // XOR IMM
+		pc++;
+	xor_comm:
+		data ^= rg.a;
+		rg.a = data;
+		data--;
+		flags = (data >> 1) & z_flag;
+		goto loop;
+
+	case 0xAF: // XOR A
+		rg.a = 0;
+		flags = z_flag;
+		goto loop;
+
+// Stack
+
+	case 0xF1: // POP FA
+	case 0xC1: // POP BC
+	case 0xD1: // POP DE
+	case 0xE1: // POP HL (common)
+		data = READ( sp );
+		r16 [(op >> 4) & 3] = data + 0x100 * READ( sp + 1 );
+		sp = (sp + 2) & 0xFFFF;
+		if ( op != 0xF1 )
+			goto loop;
+		flags = rg.flags & 0xF0;
+		goto loop;
+
+	case 0xC5: // PUSH BC
+		data = rp.bc;
+		goto push;
+
+	case 0xD5: // PUSH DE
+		data = rp.de;
+		goto push;
+
+	case 0xE5: // PUSH HL
+		data = rp.hl;
+		goto push;
+
+	case 0xF5: // PUSH FA
+		data = (flags << 8) | rg.a;
+		goto push;
+
+// Flow control
+
+	case 0xFF:
+		if ( pc == idle_addr + 1 )
+			goto stop;
+	case 0xC7: case 0xCF: case 0xD7: case 0xDF:  // RST
+	case 0xE7: case 0xEF: case 0xF7:
+		data = pc;
+		pc = (op & 0x38) + rst_base;
+		goto push;
+
+	case 0xCC: // CZ
+		pc += 2;
+		if ( flags & z_flag )
+			goto call;
+		goto loop;
+
+	case 0xD4: // CNC
+		pc += 2;
+		if ( !(flags & c_flag) )
+			goto call;
+		goto loop;
+
+	case 0xDC: // CC
+		pc += 2;
+		if ( flags & c_flag )
+			goto call;
+		goto loop;
+
+	case 0xD9: // RETI
+		//interrupts_enabled = 1;
+		goto ret;
+
+	case 0xC0: // RZ
+		if ( !(flags & z_flag) )
+			goto ret;
+		goto loop;
+
+	case 0xD0: // RNC
+		if ( !(flags & c_flag) )
+			goto ret;
+		goto loop;
+
+	case 0xD8: // RC
+		if ( flags & c_flag )
+			goto ret;
+		goto loop;
+
+	case 0x18: // JR
+		BRANCH( true )
+
+	case 0x30: // JR NC
+		BRANCH( !(flags & c_flag) )
+
+	case 0x38: // JR C
+		BRANCH( flags & c_flag )
+
+	case 0xE9: // JP_HL
+		pc = rp.hl;
+		goto loop;
+
+	case 0xC3: // JP (next-most-common)
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xC2: // JP NZ
+		pc += 2;
+		if ( !(flags & z_flag) )
+			goto jp_taken;
+		goto loop;
+
+	case 0xCA: // JP Z (most common)
+		pc += 2;
+		if ( !(flags & z_flag) )
+			goto loop;
+	jp_taken:
+		pc -= 2;
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xD2: // JP NC
+		pc += 2;
+		if ( !(flags & c_flag) )
+			goto jp_taken;
+		goto loop;
+
+	case 0xDA: // JP C
+		pc += 2;
+		if ( flags & c_flag )
+			goto jp_taken;
+		goto loop;
+
+// Flags
+
+	case 0x2F: // CPL
+		rg.a = ~rg.a;
+		flags |= n_flag | h_flag;
+		goto loop;
+
+	case 0x3F: // CCF
+		flags = (flags ^ c_flag) & ~(n_flag | h_flag);
+		goto loop;
+
+	case 0x37: // SCF
+		flags = (flags | c_flag) & ~(n_flag | h_flag);
+		goto loop;
+
+	case 0xF3: // DI
+		//interrupts_enabled = 0;
+		goto loop;
+
+	case 0xFB: // EI
+		//interrupts_enabled = 1;
+		goto loop;
+
+// Special
+
+	case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
+	case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
+	case 0x10: // STOP
+	case 0x27: // DAA (I'll have to implement this eventually...)
+	case 0xBF:
+	case 0xED: // Z80 prefix
+	case 0x76: // HALT
+		s.remain++;
+		goto stop;
+	}
+
+	// If this fails then the case above is missing an opcode
+	assert( false );
+
+stop:
+	pc--;
+
+	// copy state back
+	STATIC_CAST(core_regs_t&,r) = rg;
+	r.pc = pc;
+	r.sp = sp;
+	r.flags = flags;
+
+	this->state = &state_;
+	memcpy( &this->state_, &s, sizeof this->state_ );
+
+	return s.remain > 0;
+}
diff --git a/src/console/Gb_Cpu.cxx b/src/console/Gb_Cpu.cxx
deleted file mode 100644
index 9954b5026a33..000000000000
--- a/src/console/Gb_Cpu.cxx
+++ /dev/null
@@ -1,1052 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gb_Cpu.h"
-
-#include <string.h>
-
-//#include "gb_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "gb_cpu_io.h"
-
-#include "blargg_source.h"
-
-// Common instructions:
-//
-// 365880   FA      LD  A,IND16
-// 355863   20      JR  NZ
-// 313655   21      LD  HL,IMM
-// 274580   28      JR  Z
-// 252878   FE      CMP IMM
-// 230541   7E      LD  A,(HL)
-// 226209   2A      LD A,(HL+)
-// 217467   CD      CALL
-// 212034   C9      RET
-// 208376   CB      CB prefix
-//
-//  27486   CB 7E   BIT 7,(HL)
-//  15925   CB 76   BIT 6,(HL)
-//  13035   CB 19   RR  C
-//  11557   CB 7F   BIT 7,A
-//  10898   CB 37   SWAP A
-//  10208   CB 66   BIT 4,(HL)
-
-#if BLARGG_NONPORTABLE
-	#define PAGE_OFFSET( addr ) (addr)
-#else
-	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
-{
-	state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size );
-}
-
-void Gb_Cpu::reset( void* unmapped )
-{
-	check( state == &state_ );
-	state = &state_;
-
-	state_.remain = 0;
-
-	for ( int i = 0; i < page_count + 1; i++ )
-		set_code_page( i, (uint8_t*) unmapped );
-
-	memset( &r, 0, sizeof r );
-	//interrupts_enabled = false;
-}
-
-void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
-{
-	// address range must begin and end on page boundaries
-	require( start % page_size == 0 );
-	require( size % page_size == 0 );
-
-	unsigned first_page = start / page_size;
-	for ( unsigned i = size / page_size; i--; )
-		set_code_page( first_page + i, (uint8_t*) data + i * page_size );
-}
-
-#define READ( addr )            CPU_READ( this, (addr), s.remain )
-#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), s.remain );}
-#define READ_FAST( addr, out )  CPU_READ_FAST( this, (addr), s.remain, out )
-#define READ_PROG( addr )       (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-unsigned const z_flag = 0x80;
-unsigned const n_flag = 0x40;
-unsigned const h_flag = 0x20;
-unsigned const c_flag = 0x10;
-
-bool Gb_Cpu::run( blargg_long cycle_count )
-{
-	state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
-	state_t s;
-	this->state = &s;
-	memcpy( &s, &this->state_, sizeof s );
-
-#if BLARGG_BIG_ENDIAN
-	#define R8( n ) (r8_ [n])
-#elif BLARGG_LITTLE_ENDIAN
-	#define R8( n ) (r8_ [(n) ^ 1])
-#else
-	#error "Byte order of CPU must be known"
-#endif
-
-	union {
-		core_regs_t rg; // individual registers
-
-		struct {
-			uint16_t bc, de, hl, unused; // pairs
-		} rp;
-
-		uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
-		uint16_t r16 [4]; // indexed pairs
-	};
-	BOOST_STATIC_ASSERT( sizeof rg == 8 && sizeof rp == 8 );
-
-	rg = r;
-	unsigned pc = r.pc;
-	unsigned sp = r.sp;
-	unsigned flags = r.flags;
-
-loop:
-
-	check( (unsigned long) pc < 0x10000 );
-	check( (unsigned long) sp < 0x10000 );
-	check( (flags & ~0xF0) == 0 );
-
-	uint8_t const* instr = s.code_map [pc >> page_shift];
-	unsigned op;
-
-	// TODO: eliminate this special case
-	#if BLARGG_NONPORTABLE
-		op = instr [pc];
-		pc++;
-		instr += pc;
-	#else
-		instr += PAGE_OFFSET( pc );
-		op = *instr++;
-		pc++;
-	#endif
-
-#define GET_ADDR()  GET_LE16( instr )
-
-	if ( !--s.remain )
-		goto stop;
-
-	unsigned data;
-	data = *instr;
-
-	#ifdef GB_CPU_LOG_H
-		gb_cpu_log( "new", pc - 1, op, data, instr [1] );
-	#endif
-
-	switch ( op )
-	{
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
-	pc++;\
-	int offset = (int8_t) data;\
-	if ( !(cond) ) goto loop;\
-	pc = uint16_t (pc + offset);\
-	goto loop;\
-}
-
-// Most Common
-
-	case 0x20: // JR NZ
-		BRANCH( !(flags & z_flag) )
-
-	case 0x21: // LD HL,IMM (common)
-		rp.hl = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x28: // JR Z
-		BRANCH( flags & z_flag )
-
-	{
-		unsigned temp;
-	case 0xF0: // LD A,(0xFF00+imm)
-		temp = data | 0xFF00;
-		pc++;
-		goto ld_a_ind_comm;
-
-	case 0xF2: // LD A,(0xFF00+C)
-		temp = rg.c | 0xFF00;
-		goto ld_a_ind_comm;
-
-	case 0x0A: // LD A,(BC)
-		temp = rp.bc;
-		goto ld_a_ind_comm;
-
-	case 0x3A: // LD A,(HL-)
-		temp = rp.hl;
-		rp.hl = temp - 1;
-		goto ld_a_ind_comm;
-
-	case 0x1A: // LD A,(DE)
-		temp = rp.de;
-		goto ld_a_ind_comm;
-
-	case 0x2A: // LD A,(HL+) (common)
-		temp = rp.hl;
-		rp.hl = temp + 1;
-		goto ld_a_ind_comm;
-
-	case 0xFA: // LD A,IND16 (common)
-		temp = GET_ADDR();
-		pc += 2;
-	ld_a_ind_comm:
-		READ_FAST( temp, rg.a );
-		goto loop;
-	}
-
-	case 0xBE: // CMP (HL)
-		data = READ( rp.hl );
-		goto cmp_comm;
-
-	case 0xB8: // CMP B
-	case 0xB9: // CMP C
-	case 0xBA: // CMP D
-	case 0xBB: // CMP E
-	case 0xBC: // CMP H
-	case 0xBD: // CMP L
-		data = R8( op & 7 );
-		goto cmp_comm;
-
-	case 0xFE: // CMP IMM
-		pc++;
-	cmp_comm:
-		op = rg.a;
-		data = op - data;
-	sub_set_flags:
-		flags = ((op & 15) - (data & 15)) & h_flag;
-		flags |= (data >> 4) & c_flag;
-		flags |= n_flag;
-		if ( data & 0xFF )
-			goto loop;
-		flags |= z_flag;
-		goto loop;
-
-	case 0x46: // LD B,(HL)
-	case 0x4E: // LD C,(HL)
-	case 0x56: // LD D,(HL)
-	case 0x5E: // LD E,(HL)
-	case 0x66: // LD H,(HL)
-	case 0x6E: // LD L,(HL)
-	case 0x7E:{// LD A,(HL)
-		unsigned addr = rp.hl;
-		READ_FAST( addr, R8( (op >> 3) & 7 ) );
-		goto loop;
-	}
-
-	case 0xC4: // CNZ (next-most-common)
-		pc += 2;
-		if ( flags & z_flag )
-			goto loop;
-	call:
-		pc -= 2;
-	case 0xCD: // CALL (most-common)
-		data = pc + 2;
-		pc = GET_ADDR();
-	push:
-		sp = (sp - 1) & 0xFFFF;
-		WRITE( sp, data >> 8 );
-		sp = (sp - 1) & 0xFFFF;
-		WRITE( sp, data & 0xFF );
-		goto loop;
-
-	case 0xC8: // RNZ (next-most-common)
-		if ( !(flags & z_flag) )
-			goto loop;
-	case 0xC9: // RET (most common)
-	ret:
-		pc = READ( sp );
-		pc += 0x100 * READ( sp + 1 );
-		sp = (sp + 2) & 0xFFFF;
-		goto loop;
-
-	case 0x00: // NOP
-	case 0x40: // LD B,B
-	case 0x49: // LD C,C
-	case 0x52: // LD D,D
-	case 0x5B: // LD E,E
-	case 0x64: // LD H,H
-	case 0x6D: // LD L,L
-	case 0x7F: // LD A,A
-		goto loop;
-
-// CB Instructions
-
-	case 0xCB:
-		pc++;
-		// now data is the opcode
-		switch ( data ) {
-
-		{
-			int temp;
-		case 0x46: // BIT b,(HL)
-		case 0x4E:
-		case 0x56:
-		case 0x5E:
-		case 0x66:
-		case 0x6E:
-		case 0x76:
-		case 0x7E:
-			{
-				unsigned addr = rp.hl;
-				READ_FAST( addr, temp );
-				goto bit_comm;
-			}
-
-		case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
-		case 0x44: case 0x45: case 0x47: case 0x48:
-		case 0x49: case 0x4A: case 0x4B: case 0x4C:
-		case 0x4D: case 0x4F: case 0x50: case 0x51:
-		case 0x52: case 0x53: case 0x54: case 0x55:
-		case 0x57: case 0x58: case 0x59: case 0x5A:
-		case 0x5B: case 0x5C: case 0x5D: case 0x5F:
-		case 0x60: case 0x61: case 0x62: case 0x63:
-		case 0x64: case 0x65: case 0x67: case 0x68:
-		case 0x69: case 0x6A: case 0x6B: case 0x6C:
-		case 0x6D: case 0x6F: case 0x70: case 0x71:
-		case 0x72: case 0x73: case 0x74: case 0x75:
-		case 0x77: case 0x78: case 0x79: case 0x7A:
-		case 0x7B: case 0x7C: case 0x7D: case 0x7F:
-			temp = R8( data & 7 );
-		bit_comm:
-			int bit = (~data >> 3) & 7;
-			flags &= ~n_flag;
-			flags |= h_flag | z_flag;
-			flags ^= (temp << bit) & z_flag;
-			goto loop;
-		}
-
-		case 0x86: // RES b,(HL)
-		case 0x8E:
-		case 0x96:
-		case 0x9E:
-		case 0xA6:
-		case 0xAE:
-		case 0xB6:
-		case 0xBE:
-		case 0xC6: // SET b,(HL)
-		case 0xCE:
-		case 0xD6:
-		case 0xDE:
-		case 0xE6:
-		case 0xEE:
-		case 0xF6:
-		case 0xFE: {
-			int temp = READ( rp.hl );
-			int bit = 1 << ((data >> 3) & 7);
-			temp &= ~bit;
-			if ( !(data & 0x40) )
-				bit = 0;
-			WRITE( rp.hl, temp | bit );
-			goto loop;
-		}
-
-		case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
-		case 0xC4: case 0xC5: case 0xC7: case 0xC8:
-		case 0xC9: case 0xCA: case 0xCB: case 0xCC:
-		case 0xCD: case 0xCF: case 0xD0: case 0xD1:
-		case 0xD2: case 0xD3: case 0xD4: case 0xD5:
-		case 0xD7: case 0xD8: case 0xD9: case 0xDA:
-		case 0xDB: case 0xDC: case 0xDD: case 0xDF:
-		case 0xE0: case 0xE1: case 0xE2: case 0xE3:
-		case 0xE4: case 0xE5: case 0xE7: case 0xE8:
-		case 0xE9: case 0xEA: case 0xEB: case 0xEC:
-		case 0xED: case 0xEF: case 0xF0: case 0xF1:
-		case 0xF2: case 0xF3: case 0xF4: case 0xF5:
-		case 0xF7: case 0xF8: case 0xF9: case 0xFA:
-		case 0xFB: case 0xFC: case 0xFD: case 0xFF:
-			R8( data & 7 ) |= 1 << ((data >> 3) & 7);
-			goto loop;
-
-		case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
-		case 0x84: case 0x85: case 0x87: case 0x88:
-		case 0x89: case 0x8A: case 0x8B: case 0x8C:
-		case 0x8D: case 0x8F: case 0x90: case 0x91:
-		case 0x92: case 0x93: case 0x94: case 0x95:
-		case 0x97: case 0x98: case 0x99: case 0x9A:
-		case 0x9B: case 0x9C: case 0x9D: case 0x9F:
-		case 0xA0: case 0xA1: case 0xA2: case 0xA3:
-		case 0xA4: case 0xA5: case 0xA7: case 0xA8:
-		case 0xA9: case 0xAA: case 0xAB: case 0xAC:
-		case 0xAD: case 0xAF: case 0xB0: case 0xB1:
-		case 0xB2: case 0xB3: case 0xB4: case 0xB5:
-		case 0xB7: case 0xB8: case 0xB9: case 0xBA:
-		case 0xBB: case 0xBC: case 0xBD: case 0xBF:
-			R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
-			goto loop;
-
-		{
-			int temp;
-		case 0x36: // SWAP (HL)
-			temp = READ( rp.hl );
-			goto swap_comm;
-
-		case 0x30: // SWAP B
-		case 0x31: // SWAP C
-		case 0x32: // SWAP D
-		case 0x33: // SWAP E
-		case 0x34: // SWAP H
-		case 0x35: // SWAP L
-		case 0x37: // SWAP A
-			temp = R8( data & 7 );
-		swap_comm:
-			op = (temp >> 4) | (temp << 4);
-			flags = 0;
-			goto shift_comm;
-		}
-
-// Shift/Rotate
-
-		case 0x06: // RLC (HL)
-		case 0x16: // RL (HL)
-		case 0x26: // SLA (HL)
-			op = READ( rp.hl );
-			goto rl_comm;
-
-		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
-		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
-		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
-			op = R8( data & 7 );
-			goto rl_comm;
-
-		case 0x3E: // SRL (HL)
-			data += 0x10; // bump up to 0x4n to avoid preserving sign bit
-		case 0x1E: // RR (HL)
-		case 0x0E: // RRC (HL)
-		case 0x2E: // SRA (HL)
-			op = READ( rp.hl );
-			goto rr_comm;
-
-		case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
-			data += 0x10; // bump up to 0x4n
-		case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
-		case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
-		case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
-			op = R8( data & 7 );
-			goto rr_comm;
-
-	} // CB op
-	assert( false ); // unhandled CB op
-
-	case 0x07: // RLCA
-	case 0x17: // RLA
-		data = op;
-		op = rg.a;
-	rl_comm:
-		op <<= 1;
-		op |= ((data & flags) >> 4) & 1; // RL and carry is set
-		flags = (op >> 4) & c_flag; // C = bit shifted out
-		if ( data < 0x10 ) // RLC
-			op |= op >> 8;
-		// SLA doesn't fill lower bit
-		goto shift_comm;
-
-	case 0x0F: // RRCA
-	case 0x1F: // RRA
-		data = op;
-		op = rg.a;
-	rr_comm:
-		op |= (data & flags) << 4; // RR and carry is set
-		flags = (op << 4) & c_flag; // C = bit shifted out
-		if ( data < 0x10 ) // RRC
-			op |= op << 8;
-		op >>= 1;
-		if ( data & 0x20 ) // SRA propagates sign bit
-			op |= (op << 1) & 0x80;
-	shift_comm:
-		data &= 7;
-		if ( !(op & 0xFF) )
-			flags |= z_flag;
-		if ( data == 6 )
-			goto write_hl_op_ff;
-		R8( data ) = op;
-		goto loop;
-
-// Load
-
-	case 0x70: // LD (HL),B
-	case 0x71: // LD (HL),C
-	case 0x72: // LD (HL),D
-	case 0x73: // LD (HL),E
-	case 0x74: // LD (HL),H
-	case 0x75: // LD (HL),L
-	case 0x77: // LD (HL),A
-		op = R8( op & 7 );
-	write_hl_op_ff:
-		WRITE( rp.hl, op & 0xFF );
-		goto loop;
-
-	case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
-	case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
-	case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
-	case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
-	case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
-	case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
-	case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
-		R8( (op >> 3) & 7 ) = R8( op & 7 );
-		goto loop;
-
-	case 0x08: // LD IND16,SP
-		data = GET_ADDR();
-		pc += 2;
-		WRITE( data, sp&0xFF );
-		data++;
-		WRITE( data, sp >> 8 );
-		goto loop;
-
-	case 0xF9: // LD SP,HL
-		sp = rp.hl;
-		goto loop;
-
-	case 0x31: // LD SP,IMM
-		sp = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x01: // LD BC,IMM
-	case 0x11: // LD DE,IMM
-		r16 [op >> 4] = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	{
-		unsigned temp;
-	case 0xE0: // LD (0xFF00+imm),A
-		temp = data | 0xFF00;
-		pc++;
-		goto write_data_rg_a;
-
-	case 0xE2: // LD (0xFF00+C),A
-		temp = rg.c | 0xFF00;
-		goto write_data_rg_a;
-
-	case 0x32: // LD (HL-),A
-		temp = rp.hl;
-		rp.hl = temp - 1;
-		goto write_data_rg_a;
-
-	case 0x02: // LD (BC),A
-		temp = rp.bc;
-		goto write_data_rg_a;
-
-	case 0x12: // LD (DE),A
-		temp = rp.de;
-		goto write_data_rg_a;
-
-	case 0x22: // LD (HL+),A
-		temp = rp.hl;
-		rp.hl = temp + 1;
-		goto write_data_rg_a;
-
-	case 0xEA: // LD IND16,A (common)
-		temp = GET_ADDR();
-		pc += 2;
-	write_data_rg_a:
-		WRITE( temp, rg.a );
-		goto loop;
-	}
-
-	case 0x06: // LD B,IMM
-		rg.b = data;
-		pc++;
-		goto loop;
-
-	case 0x0E: // LD C,IMM
-		rg.c = data;
-		pc++;
-		goto loop;
-
-	case 0x16: // LD D,IMM
-		rg.d = data;
-		pc++;
-		goto loop;
-
-	case 0x1E: // LD E,IMM
-		rg.e = data;
-		pc++;
-		goto loop;
-
-	case 0x26: // LD H,IMM
-		rg.h = data;
-		pc++;
-		goto loop;
-
-	case 0x2E: // LD L,IMM
-		rg.l = data;
-		pc++;
-		goto loop;
-
-	case 0x36: // LD (HL),IMM
-		WRITE( rp.hl, data );
-		pc++;
-		goto loop;
-
-	case 0x3E: // LD A,IMM
-		rg.a = data;
-		pc++;
-		goto loop;
-
-// Increment/Decrement
-
-	case 0x03: // INC BC
-	case 0x13: // INC DE
-	case 0x23: // INC HL
-		r16 [op >> 4]++;
-		goto loop;
-
-	case 0x33: // INC SP
-		sp = (sp + 1) & 0xFFFF;
-		goto loop;
-
-	case 0x0B: // DEC BC
-	case 0x1B: // DEC DE
-	case 0x2B: // DEC HL
-		r16 [op >> 4]--;
-		goto loop;
-
-	case 0x3B: // DEC SP
-		sp = (sp - 1) & 0xFFFF;
-		goto loop;
-
-	case 0x34: // INC (HL)
-		op = rp.hl;
-		data = READ( op );
-		data++;
-		WRITE( op, data & 0xFF );
-		goto inc_comm;
-
-	case 0x04: // INC B
-	case 0x0C: // INC C (common)
-	case 0x14: // INC D
-	case 0x1C: // INC E
-	case 0x24: // INC H
-	case 0x2C: // INC L
-	case 0x3C: // INC A
-		op = (op >> 3) & 7;
-		R8( op ) = data = R8( op ) + 1;
-	inc_comm:
-		flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
-		goto loop;
-
-	case 0x35: // DEC (HL)
-		op = rp.hl;
-		data = READ( op );
-		data--;
-		WRITE( op, data & 0xFF );
-		goto dec_comm;
-
-	case 0x05: // DEC B
-	case 0x0D: // DEC C
-	case 0x15: // DEC D
-	case 0x1D: // DEC E
-	case 0x25: // DEC H
-	case 0x2D: // DEC L
-	case 0x3D: // DEC A
-		op = (op >> 3) & 7;
-		data = R8( op ) - 1;
-		R8( op ) = data;
-	dec_comm:
-		flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
-		if ( data & 0xFF )
-			goto loop;
-		flags |= z_flag;
-		goto loop;
-
-// Add 16-bit
-
-	{
-		blargg_ulong temp; // need more than 16 bits for carry
-		unsigned prev;
-
-	case 0xF8: // LD HL,SP+imm
-		temp = int8_t (data); // sign-extend to 16 bits
-		pc++;
-		flags = 0;
-		temp += sp;
-		prev = sp;
-		goto add_16_hl;
-
-	case 0xE8: // ADD SP,IMM
-		temp = int8_t (data); // sign-extend to 16 bits
-		pc++;
-		flags = 0;
-		temp += sp;
-		prev = sp;
-		sp = temp & 0xFFFF;
-		goto add_16_comm;
-
-	case 0x39: // ADD HL,SP
-		temp = sp;
-		goto add_hl_comm;
-
-	case 0x09: // ADD HL,BC
-	case 0x19: // ADD HL,DE
-	case 0x29: // ADD HL,HL
-		temp = r16 [op >> 4];
-	add_hl_comm:
-		prev = rp.hl;
-		temp += prev;
-		flags &= z_flag;
-	add_16_hl:
-		rp.hl = temp;
-	add_16_comm:
-		flags |= (temp >> 12) & c_flag;
-		flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;
-		goto loop;
-	}
-
-	case 0x86: // ADD (HL)
-		data = READ( rp.hl );
-		goto add_comm;
-
-	case 0x80: // ADD B
-	case 0x81: // ADD C
-	case 0x82: // ADD D
-	case 0x83: // ADD E
-	case 0x84: // ADD H
-	case 0x85: // ADD L
-	case 0x87: // ADD A
-		data = R8( op & 7 );
-		goto add_comm;
-
-	case 0xC6: // ADD IMM
-		pc++;
-	add_comm:
-		flags = rg.a;
-		data += flags;
-		flags = ((data & 15) - (flags & 15)) & h_flag;
-		flags |= (data >> 4) & c_flag;
-		rg.a = data;
-		if ( data & 0xFF )
-			goto loop;
-		flags |= z_flag;
-		goto loop;
-
-// Add/Subtract
-
-	case 0x8E: // ADC (HL)
-		data = READ( rp.hl );
-		goto adc_comm;
-
-	case 0x88: // ADC B
-	case 0x89: // ADC C
-	case 0x8A: // ADC D
-	case 0x8B: // ADC E
-	case 0x8C: // ADC H
-	case 0x8D: // ADC L
-	case 0x8F: // ADC A
-		data = R8( op & 7 );
-		goto adc_comm;
-
-	case 0xCE: // ADC IMM
-		pc++;
-	adc_comm:
-		data += (flags >> 4) & 1;
-		data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
-		goto add_comm;
-
-	case 0x96: // SUB (HL)
-		data = READ( rp.hl );
-		goto sub_comm;
-
-	case 0x90: // SUB B
-	case 0x91: // SUB C
-	case 0x92: // SUB D
-	case 0x93: // SUB E
-	case 0x94: // SUB H
-	case 0x95: // SUB L
-	case 0x97: // SUB A
-		data = R8( op & 7 );
-		goto sub_comm;
-
-	case 0xD6: // SUB IMM
-		pc++;
-	sub_comm:
-		op = rg.a;
-		data = op - data;
-		rg.a = data;
-		goto sub_set_flags;
-
-	case 0x9E: // SBC (HL)
-		data = READ( rp.hl );
-		goto sbc_comm;
-
-	case 0x98: // SBC B
-	case 0x99: // SBC C
-	case 0x9A: // SBC D
-	case 0x9B: // SBC E
-	case 0x9C: // SBC H
-	case 0x9D: // SBC L
-	case 0x9F: // SBC A
-		data = R8( op & 7 );
-		goto sbc_comm;
-
-	case 0xDE: // SBC IMM
-		pc++;
-	sbc_comm:
-		data += (flags >> 4) & 1;
-		data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
-		goto sub_comm;
-
-// Logical
-
-	case 0xA0: // AND B
-	case 0xA1: // AND C
-	case 0xA2: // AND D
-	case 0xA3: // AND E
-	case 0xA4: // AND H
-	case 0xA5: // AND L
-		data = R8( op & 7 );
-		goto and_comm;
-
-	case 0xA6: // AND (HL)
-		data = READ( rp.hl );
-		pc--;
-	case 0xE6: // AND IMM
-		pc++;
-	and_comm:
-		rg.a &= data;
-	case 0xA7: // AND A
-		flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
-		goto loop;
-
-	case 0xB0: // OR B
-	case 0xB1: // OR C
-	case 0xB2: // OR D
-	case 0xB3: // OR E
-	case 0xB4: // OR H
-	case 0xB5: // OR L
-		data = R8( op & 7 );
-		goto or_comm;
-
-	case 0xB6: // OR (HL)
-		data = READ( rp.hl );
-		pc--;
-	case 0xF6: // OR IMM
-		pc++;
-	or_comm:
-		rg.a |= data;
-	case 0xB7: // OR A
-		flags = ((rg.a - 1) >> 1) & z_flag;
-		goto loop;
-
-	case 0xA8: // XOR B
-	case 0xA9: // XOR C
-	case 0xAA: // XOR D
-	case 0xAB: // XOR E
-	case 0xAC: // XOR H
-	case 0xAD: // XOR L
-		data = R8( op & 7 );
-		goto xor_comm;
-
-	case 0xAE: // XOR (HL)
-		data = READ( rp.hl );
-		pc--;
-	case 0xEE: // XOR IMM
-		pc++;
-	xor_comm:
-		data ^= rg.a;
-		rg.a = data;
-		data--;
-		flags = (data >> 1) & z_flag;
-		goto loop;
-
-	case 0xAF: // XOR A
-		rg.a = 0;
-		flags = z_flag;
-		goto loop;
-
-// Stack
-
-	case 0xF1: // POP FA
-	case 0xC1: // POP BC
-	case 0xD1: // POP DE
-	case 0xE1: // POP HL (common)
-		data = READ( sp );
-		r16 [(op >> 4) & 3] = data + 0x100 * READ( sp + 1 );
-		sp = (sp + 2) & 0xFFFF;
-		if ( op != 0xF1 )
-			goto loop;
-		flags = rg.flags & 0xF0;
-		goto loop;
-
-	case 0xC5: // PUSH BC
-		data = rp.bc;
-		goto push;
-
-	case 0xD5: // PUSH DE
-		data = rp.de;
-		goto push;
-
-	case 0xE5: // PUSH HL
-		data = rp.hl;
-		goto push;
-
-	case 0xF5: // PUSH FA
-		data = (flags << 8) | rg.a;
-		goto push;
-
-// Flow control
-
-	case 0xFF:
-		if ( pc == idle_addr + 1 )
-			goto stop;
-	case 0xC7: case 0xCF: case 0xD7: case 0xDF:  // RST
-	case 0xE7: case 0xEF: case 0xF7:
-		data = pc;
-		pc = (op & 0x38) + rst_base;
-		goto push;
-
-	case 0xCC: // CZ
-		pc += 2;
-		if ( flags & z_flag )
-			goto call;
-		goto loop;
-
-	case 0xD4: // CNC
-		pc += 2;
-		if ( !(flags & c_flag) )
-			goto call;
-		goto loop;
-
-	case 0xDC: // CC
-		pc += 2;
-		if ( flags & c_flag )
-			goto call;
-		goto loop;
-
-	case 0xD9: // RETI
-		//interrupts_enabled = 1;
-		goto ret;
-
-	case 0xC0: // RZ
-		if ( !(flags & z_flag) )
-			goto ret;
-		goto loop;
-
-	case 0xD0: // RNC
-		if ( !(flags & c_flag) )
-			goto ret;
-		goto loop;
-
-	case 0xD8: // RC
-		if ( flags & c_flag )
-			goto ret;
-		goto loop;
-
-	case 0x18: // JR
-		BRANCH( true )
-
-	case 0x30: // JR NC
-		BRANCH( !(flags & c_flag) )
-
-	case 0x38: // JR C
-		BRANCH( flags & c_flag )
-
-	case 0xE9: // JP_HL
-		pc = rp.hl;
-		goto loop;
-
-	case 0xC3: // JP (next-most-common)
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xC2: // JP NZ
-		pc += 2;
-		if ( !(flags & z_flag) )
-			goto jp_taken;
-		goto loop;
-
-	case 0xCA: // JP Z (most common)
-		pc += 2;
-		if ( !(flags & z_flag) )
-			goto loop;
-	jp_taken:
-		pc -= 2;
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xD2: // JP NC
-		pc += 2;
-		if ( !(flags & c_flag) )
-			goto jp_taken;
-		goto loop;
-
-	case 0xDA: // JP C
-		pc += 2;
-		if ( flags & c_flag )
-			goto jp_taken;
-		goto loop;
-
-// Flags
-
-	case 0x2F: // CPL
-		rg.a = ~rg.a;
-		flags |= n_flag | h_flag;
-		goto loop;
-
-	case 0x3F: // CCF
-		flags = (flags ^ c_flag) & ~(n_flag | h_flag);
-		goto loop;
-
-	case 0x37: // SCF
-		flags = (flags | c_flag) & ~(n_flag | h_flag);
-		goto loop;
-
-	case 0xF3: // DI
-		//interrupts_enabled = 0;
-		goto loop;
-
-	case 0xFB: // EI
-		//interrupts_enabled = 1;
-		goto loop;
-
-// Special
-
-	case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
-	case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
-	case 0x10: // STOP
-	case 0x27: // DAA (I'll have to implement this eventually...)
-	case 0xBF:
-	case 0xED: // Z80 prefix
-	case 0x76: // HALT
-		s.remain++;
-		goto stop;
-	}
-
-	// If this fails then the case above is missing an opcode
-	assert( false );
-
-stop:
-	pc--;
-
-	// copy state back
-	STATIC_CAST(core_regs_t&,r) = rg;
-	r.pc = pc;
-	r.sp = sp;
-	r.flags = flags;
-
-	this->state = &state_;
-	memcpy( &this->state_, &s, sizeof this->state_ );
-
-	return s.remain > 0;
-}
diff --git a/src/console/Gb_Oscs.cc b/src/console/Gb_Oscs.cc
new file mode 100644
index 000000000000..56dbff6cfdb9
--- /dev/null
+++ b/src/console/Gb_Oscs.cc
@@ -0,0 +1,336 @@
+// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
+
+#include "Gb_Apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Gb_Osc
+
+void Gb_Osc::reset()
+{
+	delay = 0;
+	last_amp = 0;
+	length = 0;
+	output_select = 3;
+	output = outputs [output_select];
+}
+
+void Gb_Osc::clock_length()
+{
+	if ( (regs [4] & len_enabled_mask) && length )
+		length--;
+}
+
+// Gb_Env
+
+void Gb_Env::clock_envelope()
+{
+	if ( env_delay && !--env_delay )
+	{
+		env_delay = regs [2] & 7;
+		int v = volume - 1 + (regs [2] >> 2 & 2);
+		if ( (unsigned) v < 15 )
+			volume = v;
+	}
+}
+
+bool Gb_Env::write_register( int reg, int data )
+{
+	switch ( reg )
+	{
+	case 1:
+		length = 64 - (regs [1] & 0x3F);
+		break;
+
+	case 2:
+		if ( !(data >> 4) )
+			enabled = false;
+		break;
+
+	case 4:
+		if ( data & trigger )
+		{
+			env_delay = regs [2] & 7;
+			volume = regs [2] >> 4;
+			enabled = true;
+			if ( length == 0 )
+				length = 64;
+			return true;
+		}
+	}
+	return false;
+}
+
+// Gb_Square
+
+void Gb_Square::reset()
+{
+	phase = 0;
+	sweep_freq = 0;
+	sweep_delay = 0;
+	Gb_Env::reset();
+}
+
+void Gb_Square::clock_sweep()
+{
+	int sweep_period = (regs [0] & period_mask) >> 4;
+	if ( sweep_period && sweep_delay && !--sweep_delay )
+	{
+		sweep_delay = sweep_period;
+		regs [3] = sweep_freq & 0xFF;
+		regs [4] = (regs [4] & ~0x07) | (sweep_freq >> 8 & 0x07);
+
+		int offset = sweep_freq >> (regs [0] & shift_mask);
+		if ( regs [0] & 0x08 )
+			offset = -offset;
+		sweep_freq += offset;
+
+		if ( sweep_freq < 0 )
+		{
+			sweep_freq = 0;
+		}
+		else if ( sweep_freq >= 2048 )
+		{
+			sweep_delay = 0; // don't modify channel frequency any further
+			sweep_freq = 2048; // silence sound immediately
+		}
+	}
+}
+
+void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
+{
+	if ( sweep_freq == 2048 )
+		playing = false;
+
+	static unsigned char const table [4] = { 1, 2, 4, 6 };
+	int const duty = table [regs [1] >> 6];
+	int amp = volume & playing;
+	if ( phase >= duty )
+		amp = -amp;
+
+	int frequency = this->frequency();
+	if ( unsigned (frequency - 1) > 2040 ) // frequency < 1 || frequency > 2041
+	{
+		// really high frequency results in DC at half volume
+		amp = volume >> 1;
+		playing = false;
+	}
+
+	{
+		int delta = amp - last_amp;
+		if ( delta )
+		{
+			last_amp = amp;
+			synth->offset( time, delta, output );
+		}
+	}
+
+	time += delay;
+	if ( !playing )
+		time = end_time;
+
+	if ( time < end_time )
+	{
+		int const period = (2048 - frequency) * 4;
+		Blip_Buffer* const output = this->output;
+		int phase = this->phase;
+		int delta = amp * 2;
+		do
+		{
+			phase = (phase + 1) & 7;
+			if ( phase == 0 || phase == duty )
+			{
+				delta = -delta;
+				synth->offset_inline( time, delta, output );
+			}
+			time += period;
+		}
+		while ( time < end_time );
+
+		this->phase = phase;
+		last_amp = delta >> 1;
+	}
+	delay = time - end_time;
+}
+
+// Gb_Noise
+
+void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
+{
+	int amp = volume & playing;
+	int tap = 13 - (regs [3] & 8);
+	if ( bits >> tap & 2 )
+		amp = -amp;
+
+	{
+		int delta = amp - last_amp;
+		if ( delta )
+		{
+			last_amp = amp;
+			synth->offset( time, delta, output );
+		}
+	}
+
+	time += delay;
+	if ( !playing )
+		time = end_time;
+
+	if ( time < end_time )
+	{
+		static unsigned char const table [8] = { 8, 16, 32, 48, 64, 80, 96, 112 };
+		int period = table [regs [3] & 7] << (regs [3] >> 4);
+
+		// keep parallel resampled time to eliminate time conversion in the loop
+		Blip_Buffer* const output = this->output;
+		const blip_resampled_time_t resampled_period =
+				output->resampled_duration( period );
+		blip_resampled_time_t resampled_time = output->resampled_time( time );
+		unsigned bits = this->bits;
+		int delta = amp * 2;
+
+		do
+		{
+			unsigned changed = (bits >> tap) + 1;
+			time += period;
+			bits <<= 1;
+			if ( changed & 2 )
+			{
+				delta = -delta;
+				bits |= 1;
+				synth->offset_resampled( resampled_time, delta, output );
+			}
+			resampled_time += resampled_period;
+		}
+		while ( time < end_time );
+
+		this->bits = bits;
+		last_amp = delta >> 1;
+	}
+	delay = time - end_time;
+}
+
+// Gb_Wave
+
+inline void Gb_Wave::write_register( int reg, int data )
+{
+	switch ( reg )
+	{
+	case 0:
+		if ( !(data & 0x80) )
+			enabled = false;
+		break;
+
+	case 1:
+		length = 256 - regs [1];
+		break;
+
+	case 2:
+		volume = data >> 5 & 3;
+		break;
+
+	case 4:
+		if ( data & trigger & regs [0] )
+		{
+			wave_pos = 0;
+			enabled = true;
+			if ( length == 0 )
+				length = 256;
+		}
+	}
+}
+
+void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
+{
+	int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
+	int frequency;
+	{
+		int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
+
+		frequency = this->frequency();
+		if ( unsigned (frequency - 1) > 2044 ) // frequency < 1 || frequency > 2045
+		{
+			amp = 30 >> volume_shift & playing;
+			playing = false;
+		}
+
+		int delta = amp - last_amp;
+		if ( delta )
+		{
+			last_amp = amp;
+			synth->offset( time, delta, output );
+		}
+	}
+
+	time += delay;
+	if ( !playing )
+		time = end_time;
+
+	if ( time < end_time )
+	{
+		Blip_Buffer* const output = this->output;
+		int const period = (2048 - frequency) * 2;
+	 	int wave_pos = (this->wave_pos + 1) & (wave_size - 1);
+
+		do
+		{
+			int amp = (wave [wave_pos] >> volume_shift) * 2;
+			wave_pos = (wave_pos + 1) & (wave_size - 1);
+			int delta = amp - last_amp;
+			if ( delta )
+			{
+				last_amp = amp;
+				synth->offset_inline( time, delta, output );
+			}
+			time += period;
+		}
+		while ( time < end_time );
+
+		this->wave_pos = (wave_pos - 1) & (wave_size - 1);
+	}
+	delay = time - end_time;
+}
+
+// Gb_Apu::write_osc
+
+void Gb_Apu::write_osc( int index, int reg, int data )
+{
+	reg -= index * 5;
+	Gb_Square* sq = &square2;
+	switch ( index )
+	{
+	case 0:
+		sq = &square1;
+	case 1:
+		if ( sq->write_register( reg, data ) && index == 0 )
+		{
+			square1.sweep_freq = square1.frequency();
+			if ( (regs [0] & sq->period_mask) && (regs [0] & sq->shift_mask) )
+			{
+				square1.sweep_delay = 1; // cause sweep to recalculate now
+				square1.clock_sweep();
+			}
+		}
+		break;
+
+	case 2:
+		wave.write_register( reg, data );
+		break;
+
+	case 3:
+		if ( noise.write_register( reg, data ) )
+			noise.bits = 0x7FFF;
+	}
+}
diff --git a/src/console/Gb_Oscs.cxx b/src/console/Gb_Oscs.cxx
deleted file mode 100644
index 56dbff6cfdb9..000000000000
--- a/src/console/Gb_Oscs.cxx
+++ /dev/null
@@ -1,336 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Gb_Osc
-
-void Gb_Osc::reset()
-{
-	delay = 0;
-	last_amp = 0;
-	length = 0;
-	output_select = 3;
-	output = outputs [output_select];
-}
-
-void Gb_Osc::clock_length()
-{
-	if ( (regs [4] & len_enabled_mask) && length )
-		length--;
-}
-
-// Gb_Env
-
-void Gb_Env::clock_envelope()
-{
-	if ( env_delay && !--env_delay )
-	{
-		env_delay = regs [2] & 7;
-		int v = volume - 1 + (regs [2] >> 2 & 2);
-		if ( (unsigned) v < 15 )
-			volume = v;
-	}
-}
-
-bool Gb_Env::write_register( int reg, int data )
-{
-	switch ( reg )
-	{
-	case 1:
-		length = 64 - (regs [1] & 0x3F);
-		break;
-
-	case 2:
-		if ( !(data >> 4) )
-			enabled = false;
-		break;
-
-	case 4:
-		if ( data & trigger )
-		{
-			env_delay = regs [2] & 7;
-			volume = regs [2] >> 4;
-			enabled = true;
-			if ( length == 0 )
-				length = 64;
-			return true;
-		}
-	}
-	return false;
-}
-
-// Gb_Square
-
-void Gb_Square::reset()
-{
-	phase = 0;
-	sweep_freq = 0;
-	sweep_delay = 0;
-	Gb_Env::reset();
-}
-
-void Gb_Square::clock_sweep()
-{
-	int sweep_period = (regs [0] & period_mask) >> 4;
-	if ( sweep_period && sweep_delay && !--sweep_delay )
-	{
-		sweep_delay = sweep_period;
-		regs [3] = sweep_freq & 0xFF;
-		regs [4] = (regs [4] & ~0x07) | (sweep_freq >> 8 & 0x07);
-
-		int offset = sweep_freq >> (regs [0] & shift_mask);
-		if ( regs [0] & 0x08 )
-			offset = -offset;
-		sweep_freq += offset;
-
-		if ( sweep_freq < 0 )
-		{
-			sweep_freq = 0;
-		}
-		else if ( sweep_freq >= 2048 )
-		{
-			sweep_delay = 0; // don't modify channel frequency any further
-			sweep_freq = 2048; // silence sound immediately
-		}
-	}
-}
-
-void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
-{
-	if ( sweep_freq == 2048 )
-		playing = false;
-
-	static unsigned char const table [4] = { 1, 2, 4, 6 };
-	int const duty = table [regs [1] >> 6];
-	int amp = volume & playing;
-	if ( phase >= duty )
-		amp = -amp;
-
-	int frequency = this->frequency();
-	if ( unsigned (frequency - 1) > 2040 ) // frequency < 1 || frequency > 2041
-	{
-		// really high frequency results in DC at half volume
-		amp = volume >> 1;
-		playing = false;
-	}
-
-	{
-		int delta = amp - last_amp;
-		if ( delta )
-		{
-			last_amp = amp;
-			synth->offset( time, delta, output );
-		}
-	}
-
-	time += delay;
-	if ( !playing )
-		time = end_time;
-
-	if ( time < end_time )
-	{
-		int const period = (2048 - frequency) * 4;
-		Blip_Buffer* const output = this->output;
-		int phase = this->phase;
-		int delta = amp * 2;
-		do
-		{
-			phase = (phase + 1) & 7;
-			if ( phase == 0 || phase == duty )
-			{
-				delta = -delta;
-				synth->offset_inline( time, delta, output );
-			}
-			time += period;
-		}
-		while ( time < end_time );
-
-		this->phase = phase;
-		last_amp = delta >> 1;
-	}
-	delay = time - end_time;
-}
-
-// Gb_Noise
-
-void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
-{
-	int amp = volume & playing;
-	int tap = 13 - (regs [3] & 8);
-	if ( bits >> tap & 2 )
-		amp = -amp;
-
-	{
-		int delta = amp - last_amp;
-		if ( delta )
-		{
-			last_amp = amp;
-			synth->offset( time, delta, output );
-		}
-	}
-
-	time += delay;
-	if ( !playing )
-		time = end_time;
-
-	if ( time < end_time )
-	{
-		static unsigned char const table [8] = { 8, 16, 32, 48, 64, 80, 96, 112 };
-		int period = table [regs [3] & 7] << (regs [3] >> 4);
-
-		// keep parallel resampled time to eliminate time conversion in the loop
-		Blip_Buffer* const output = this->output;
-		const blip_resampled_time_t resampled_period =
-				output->resampled_duration( period );
-		blip_resampled_time_t resampled_time = output->resampled_time( time );
-		unsigned bits = this->bits;
-		int delta = amp * 2;
-
-		do
-		{
-			unsigned changed = (bits >> tap) + 1;
-			time += period;
-			bits <<= 1;
-			if ( changed & 2 )
-			{
-				delta = -delta;
-				bits |= 1;
-				synth->offset_resampled( resampled_time, delta, output );
-			}
-			resampled_time += resampled_period;
-		}
-		while ( time < end_time );
-
-		this->bits = bits;
-		last_amp = delta >> 1;
-	}
-	delay = time - end_time;
-}
-
-// Gb_Wave
-
-inline void Gb_Wave::write_register( int reg, int data )
-{
-	switch ( reg )
-	{
-	case 0:
-		if ( !(data & 0x80) )
-			enabled = false;
-		break;
-
-	case 1:
-		length = 256 - regs [1];
-		break;
-
-	case 2:
-		volume = data >> 5 & 3;
-		break;
-
-	case 4:
-		if ( data & trigger & regs [0] )
-		{
-			wave_pos = 0;
-			enabled = true;
-			if ( length == 0 )
-				length = 256;
-		}
-	}
-}
-
-void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
-{
-	int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
-	int frequency;
-	{
-		int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
-
-		frequency = this->frequency();
-		if ( unsigned (frequency - 1) > 2044 ) // frequency < 1 || frequency > 2045
-		{
-			amp = 30 >> volume_shift & playing;
-			playing = false;
-		}
-
-		int delta = amp - last_amp;
-		if ( delta )
-		{
-			last_amp = amp;
-			synth->offset( time, delta, output );
-		}
-	}
-
-	time += delay;
-	if ( !playing )
-		time = end_time;
-
-	if ( time < end_time )
-	{
-		Blip_Buffer* const output = this->output;
-		int const period = (2048 - frequency) * 2;
-	 	int wave_pos = (this->wave_pos + 1) & (wave_size - 1);
-
-		do
-		{
-			int amp = (wave [wave_pos] >> volume_shift) * 2;
-			wave_pos = (wave_pos + 1) & (wave_size - 1);
-			int delta = amp - last_amp;
-			if ( delta )
-			{
-				last_amp = amp;
-				synth->offset_inline( time, delta, output );
-			}
-			time += period;
-		}
-		while ( time < end_time );
-
-		this->wave_pos = (wave_pos - 1) & (wave_size - 1);
-	}
-	delay = time - end_time;
-}
-
-// Gb_Apu::write_osc
-
-void Gb_Apu::write_osc( int index, int reg, int data )
-{
-	reg -= index * 5;
-	Gb_Square* sq = &square2;
-	switch ( index )
-	{
-	case 0:
-		sq = &square1;
-	case 1:
-		if ( sq->write_register( reg, data ) && index == 0 )
-		{
-			square1.sweep_freq = square1.frequency();
-			if ( (regs [0] & sq->period_mask) && (regs [0] & sq->shift_mask) )
-			{
-				square1.sweep_delay = 1; // cause sweep to recalculate now
-				square1.clock_sweep();
-			}
-		}
-		break;
-
-	case 2:
-		wave.write_register( reg, data );
-		break;
-
-	case 3:
-		if ( noise.write_register( reg, data ) )
-			noise.bits = 0x7FFF;
-	}
-}
diff --git a/src/console/Gb_Oscs.h b/src/console/Gb_Oscs.h
index cd5c1c3eedcd..5cad0a1e1733 100644
--- a/src/console/Gb_Oscs.h
+++ b/src/console/Gb_Oscs.h
@@ -12,7 +12,7 @@ struct Gb_Osc
 	enum { trigger = 0x80 };
 	enum { len_enabled_mask = 0x40 };
 
-	Blip_Buffer* outputs [4]; // NULL, right, left, center
+	Blip_Buffer* outputs [4]; // nullptr, right, left, center
 	Blip_Buffer* output;
 	int output_select;
 	uint8_t* regs; // osc's 5 registers
diff --git a/src/console/Gbs_Emu.cc b/src/console/Gbs_Emu.cc
new file mode 100644
index 000000000000..265d8036464c
--- /dev/null
+++ b/src/console/Gbs_Emu.cc
@@ -0,0 +1,289 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Gbs_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq   = { -47.0, 2000 };
+Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = {   0.0,  300 };
+
+Gbs_Emu::Gbs_Emu()
+{
+	set_type( gme_gbs_type );
+
+	static const char* const names [Gb_Apu::osc_count] = {
+		"Square 1", "Square 2", "Wave", "Noise"
+	};
+	set_voice_names( names );
+
+	static int const types [Gb_Apu::osc_count] = {
+		wave_type | 1, wave_type | 2, wave_type | 0, mixed_type | 0
+	};
+	set_voice_types( types );
+
+	set_silence_lookahead( 6 );
+	set_max_initial_silence( 21 );
+	set_gain( 1.2 );
+
+	static equalizer_t const eq = { -1.0, 120 };
+	set_equalizer( eq );
+}
+
+Gbs_Emu::~Gbs_Emu() { }
+
+void Gbs_Emu::unload()
+{
+	rom.clear();
+	Music_Emu::unload();
+}
+
+// Track info
+
+static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
+{
+	GME_COPY_FIELD( h, out, game );
+	GME_COPY_FIELD( h, out, author );
+	GME_COPY_FIELD( h, out, copyright );
+}
+
+blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
+{
+	copy_gbs_fields( header_, out );
+	return 0;
+}
+
+static blargg_err_t check_gbs_header( void const* header )
+{
+	if ( memcmp( header, "GBS", 3 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Gbs_File : Gme_Info_
+{
+	Gbs_Emu::header_t h;
+
+	Gbs_File() { set_type( gme_gbs_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		blargg_err_t err = in.read( &h, Gbs_Emu::header_size );
+		if ( err )
+			return (err == in.eof_error ? gme_wrong_file_type : err);
+
+		set_track_count( h.track_count );
+		return check_gbs_header( &h );
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		copy_gbs_fields( h, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
+static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
+
+static gme_type_t_ const gme_gbs_type_ = { "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 };
+gme_type_t const gme_gbs_type = &gme_gbs_type_;
+
+// Setup
+
+blargg_err_t Gbs_Emu::load_( Data_Reader& in )
+{
+	assert( offsetof (header_t,copyright [32]) == header_size );
+	RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
+
+	set_track_count( header_.track_count );
+	RETURN_ERR( check_gbs_header( &header_ ) );
+
+	if ( header_.vers != 1 )
+		set_warning( "Unknown file version" );
+
+	if ( header_.timer_mode & 0x78 )
+		set_warning( "Invalid timer mode" );
+
+	unsigned load_addr = GET_LE16( header_.load_addr );
+	if ( (header_.load_addr [1] | header_.init_addr [1] | header_.play_addr [1]) > 0x7F ||
+			load_addr < 0x400 )
+		set_warning( "Invalid load/init/play address" );
+
+	set_voice_count( Gb_Apu::osc_count );
+
+	apu.volume( gain() );
+
+	return setup_buffer( 4194304 );
+}
+
+void Gbs_Emu::update_eq( blip_eq_t const& eq )
+{
+	apu.treble_eq( eq );
+}
+
+void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+	apu.osc_output( i, c, l, r );
+}
+
+// Emulation
+
+// see gb_cpu_io.h for read/write functions
+
+void Gbs_Emu::set_bank( int n )
+{
+	blargg_long addr = rom.mask_addr( n * (blargg_long) bank_size );
+	if ( addr == 0 && rom.size() > bank_size )
+	{
+		// TODO: what is the correct behavior? Current Game & Watch Gallery
+		// rip requires that this have no effect or set to bank 1.
+		//debug_printf( "Selected ROM bank 0\n" );
+		return;
+		//n = 1;
+	}
+	cpu::map_code( bank_size, bank_size, rom.at_addr( addr ) );
+}
+
+void Gbs_Emu::update_timer()
+{
+	if ( header_.timer_mode & 0x04 )
+	{
+		static byte const rates [4] = { 10, 4, 6, 8 };
+		int shift = rates [ram [hi_page + 7] & 3] - (header_.timer_mode >> 7);
+		play_period = (256L - ram [hi_page + 6]) << shift;
+	}
+	else
+	{
+		play_period = 70224; // 59.73 Hz
+	}
+	if ( tempo() != 1.0 )
+		play_period = blip_time_t (play_period / tempo());
+}
+
+static uint8_t const sound_data [Gb_Apu::register_count] = {
+	0x80, 0xBF, 0x00, 0x00, 0xBF, // square 1
+	0x00, 0x3F, 0x00, 0x00, 0xBF, // square 2
+	0x7F, 0xFF, 0x9F, 0x00, 0xBF, // wave
+	0x00, 0xFF, 0x00, 0x00, 0xBF, // noise
+	0x77, 0xF3, 0xF1, // vin/volume, status, power mode
+	0, 0, 0, 0, 0, 0, 0, 0, 0, // unused
+	0xAC, 0xDD, 0xDA, 0x48, 0x36, 0x02, 0xCF, 0x16, // waveform data
+	0x2C, 0x04, 0xE5, 0x2C, 0xAC, 0xDD, 0xDA, 0x48
+};
+
+void Gbs_Emu::cpu_jsr( gb_addr_t addr )
+{
+	check( cpu::r.sp == GET_LE16( header_.stack_ptr ) );
+	cpu::r.pc = addr;
+	cpu_write( --cpu::r.sp, idle_addr >> 8 );
+	cpu_write( --cpu::r.sp, idle_addr&0xFF );
+}
+
+void Gbs_Emu::set_tempo_( double t )
+{
+	apu.set_tempo( t );
+	update_timer();
+}
+
+blargg_err_t Gbs_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( ram, 0, 0x4000 );
+	memset( ram + 0x4000, 0xFF, 0x1F80 );
+	memset( ram + 0x5F80, 0, sizeof ram - 0x5F80 );
+	ram [hi_page] = 0; // joypad reads back as 0
+
+	apu.reset();
+	for ( int i = 0; i < (int) sizeof sound_data; i++ )
+		apu.write_register( 0, i + apu.start_addr, sound_data [i] );
+
+	unsigned load_addr = GET_LE16( header_.load_addr );
+	rom.set_addr( load_addr );
+	cpu::rst_base = load_addr;
+
+	cpu::reset( rom.unmapped() );
+
+	cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
+	cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
+	set_bank( rom.size() > bank_size );
+
+	ram [hi_page + 6] = header_.timer_modulo;
+	ram [hi_page + 7] = header_.timer_mode;
+	update_timer();
+	next_play = play_period;
+
+	cpu::r.a  = track;
+	cpu::r.pc = idle_addr;
+	cpu::r.sp = GET_LE16( header_.stack_ptr );
+	cpu_time  = 0;
+	cpu_jsr( GET_LE16( header_.init_addr ) );
+
+	return 0;
+}
+
+blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
+{
+	cpu_time = 0;
+	while ( cpu_time < duration )
+	{
+		long count = duration - cpu_time;
+		cpu_time = duration;
+		bool result = cpu::run( count );
+		cpu_time -= cpu::remain();
+
+		if ( result )
+		{
+			if ( cpu::r.pc == idle_addr )
+			{
+				if ( next_play > duration )
+				{
+					cpu_time = duration;
+					break;
+				}
+
+				if ( cpu_time < next_play )
+					cpu_time = next_play;
+				next_play += play_period;
+				cpu_jsr( GET_LE16( header_.play_addr ) );
+				GME_FRAME_HOOK( this );
+				// TODO: handle timer rates different than 60 Hz
+			}
+			else if ( cpu::r.pc > 0xFFFF )
+			{
+				debug_printf( "PC wrapped around\n" );
+				cpu::r.pc &= 0xFFFF;
+			}
+			else
+			{
+				set_warning( "Emulation error (illegal/unsupported instruction)" );
+				debug_printf( "Bad opcode $%.2x at $%.4x\n",
+						(int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
+				cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
+				cpu_time += 6;
+			}
+		}
+	}
+
+	duration = cpu_time;
+	next_play -= cpu_time;
+	if ( next_play < 0 ) // could go negative if routine is taking too long to return
+		next_play = 0;
+	apu.end_frame( cpu_time );
+
+	return 0;
+}
diff --git a/src/console/Gbs_Emu.cxx b/src/console/Gbs_Emu.cxx
deleted file mode 100644
index 265d8036464c..000000000000
--- a/src/console/Gbs_Emu.cxx
+++ /dev/null
@@ -1,289 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gbs_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq   = { -47.0, 2000 };
-Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = {   0.0,  300 };
-
-Gbs_Emu::Gbs_Emu()
-{
-	set_type( gme_gbs_type );
-
-	static const char* const names [Gb_Apu::osc_count] = {
-		"Square 1", "Square 2", "Wave", "Noise"
-	};
-	set_voice_names( names );
-
-	static int const types [Gb_Apu::osc_count] = {
-		wave_type | 1, wave_type | 2, wave_type | 0, mixed_type | 0
-	};
-	set_voice_types( types );
-
-	set_silence_lookahead( 6 );
-	set_max_initial_silence( 21 );
-	set_gain( 1.2 );
-
-	static equalizer_t const eq = { -1.0, 120 };
-	set_equalizer( eq );
-}
-
-Gbs_Emu::~Gbs_Emu() { }
-
-void Gbs_Emu::unload()
-{
-	rom.clear();
-	Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
-{
-	GME_COPY_FIELD( h, out, game );
-	GME_COPY_FIELD( h, out, author );
-	GME_COPY_FIELD( h, out, copyright );
-}
-
-blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
-{
-	copy_gbs_fields( header_, out );
-	return 0;
-}
-
-static blargg_err_t check_gbs_header( void const* header )
-{
-	if ( memcmp( header, "GBS", 3 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Gbs_File : Gme_Info_
-{
-	Gbs_Emu::header_t h;
-
-	Gbs_File() { set_type( gme_gbs_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		blargg_err_t err = in.read( &h, Gbs_Emu::header_size );
-		if ( err )
-			return (err == in.eof_error ? gme_wrong_file_type : err);
-
-		set_track_count( h.track_count );
-		return check_gbs_header( &h );
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		copy_gbs_fields( h, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
-static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
-
-static gme_type_t_ const gme_gbs_type_ = { "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 };
-gme_type_t const gme_gbs_type = &gme_gbs_type_;
-
-// Setup
-
-blargg_err_t Gbs_Emu::load_( Data_Reader& in )
-{
-	assert( offsetof (header_t,copyright [32]) == header_size );
-	RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
-	set_track_count( header_.track_count );
-	RETURN_ERR( check_gbs_header( &header_ ) );
-
-	if ( header_.vers != 1 )
-		set_warning( "Unknown file version" );
-
-	if ( header_.timer_mode & 0x78 )
-		set_warning( "Invalid timer mode" );
-
-	unsigned load_addr = GET_LE16( header_.load_addr );
-	if ( (header_.load_addr [1] | header_.init_addr [1] | header_.play_addr [1]) > 0x7F ||
-			load_addr < 0x400 )
-		set_warning( "Invalid load/init/play address" );
-
-	set_voice_count( Gb_Apu::osc_count );
-
-	apu.volume( gain() );
-
-	return setup_buffer( 4194304 );
-}
-
-void Gbs_Emu::update_eq( blip_eq_t const& eq )
-{
-	apu.treble_eq( eq );
-}
-
-void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
-	apu.osc_output( i, c, l, r );
-}
-
-// Emulation
-
-// see gb_cpu_io.h for read/write functions
-
-void Gbs_Emu::set_bank( int n )
-{
-	blargg_long addr = rom.mask_addr( n * (blargg_long) bank_size );
-	if ( addr == 0 && rom.size() > bank_size )
-	{
-		// TODO: what is the correct behavior? Current Game & Watch Gallery
-		// rip requires that this have no effect or set to bank 1.
-		//debug_printf( "Selected ROM bank 0\n" );
-		return;
-		//n = 1;
-	}
-	cpu::map_code( bank_size, bank_size, rom.at_addr( addr ) );
-}
-
-void Gbs_Emu::update_timer()
-{
-	if ( header_.timer_mode & 0x04 )
-	{
-		static byte const rates [4] = { 10, 4, 6, 8 };
-		int shift = rates [ram [hi_page + 7] & 3] - (header_.timer_mode >> 7);
-		play_period = (256L - ram [hi_page + 6]) << shift;
-	}
-	else
-	{
-		play_period = 70224; // 59.73 Hz
-	}
-	if ( tempo() != 1.0 )
-		play_period = blip_time_t (play_period / tempo());
-}
-
-static uint8_t const sound_data [Gb_Apu::register_count] = {
-	0x80, 0xBF, 0x00, 0x00, 0xBF, // square 1
-	0x00, 0x3F, 0x00, 0x00, 0xBF, // square 2
-	0x7F, 0xFF, 0x9F, 0x00, 0xBF, // wave
-	0x00, 0xFF, 0x00, 0x00, 0xBF, // noise
-	0x77, 0xF3, 0xF1, // vin/volume, status, power mode
-	0, 0, 0, 0, 0, 0, 0, 0, 0, // unused
-	0xAC, 0xDD, 0xDA, 0x48, 0x36, 0x02, 0xCF, 0x16, // waveform data
-	0x2C, 0x04, 0xE5, 0x2C, 0xAC, 0xDD, 0xDA, 0x48
-};
-
-void Gbs_Emu::cpu_jsr( gb_addr_t addr )
-{
-	check( cpu::r.sp == GET_LE16( header_.stack_ptr ) );
-	cpu::r.pc = addr;
-	cpu_write( --cpu::r.sp, idle_addr >> 8 );
-	cpu_write( --cpu::r.sp, idle_addr&0xFF );
-}
-
-void Gbs_Emu::set_tempo_( double t )
-{
-	apu.set_tempo( t );
-	update_timer();
-}
-
-blargg_err_t Gbs_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( ram, 0, 0x4000 );
-	memset( ram + 0x4000, 0xFF, 0x1F80 );
-	memset( ram + 0x5F80, 0, sizeof ram - 0x5F80 );
-	ram [hi_page] = 0; // joypad reads back as 0
-
-	apu.reset();
-	for ( int i = 0; i < (int) sizeof sound_data; i++ )
-		apu.write_register( 0, i + apu.start_addr, sound_data [i] );
-
-	unsigned load_addr = GET_LE16( header_.load_addr );
-	rom.set_addr( load_addr );
-	cpu::rst_base = load_addr;
-
-	cpu::reset( rom.unmapped() );
-
-	cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
-	cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
-	set_bank( rom.size() > bank_size );
-
-	ram [hi_page + 6] = header_.timer_modulo;
-	ram [hi_page + 7] = header_.timer_mode;
-	update_timer();
-	next_play = play_period;
-
-	cpu::r.a  = track;
-	cpu::r.pc = idle_addr;
-	cpu::r.sp = GET_LE16( header_.stack_ptr );
-	cpu_time  = 0;
-	cpu_jsr( GET_LE16( header_.init_addr ) );
-
-	return 0;
-}
-
-blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
-{
-	cpu_time = 0;
-	while ( cpu_time < duration )
-	{
-		long count = duration - cpu_time;
-		cpu_time = duration;
-		bool result = cpu::run( count );
-		cpu_time -= cpu::remain();
-
-		if ( result )
-		{
-			if ( cpu::r.pc == idle_addr )
-			{
-				if ( next_play > duration )
-				{
-					cpu_time = duration;
-					break;
-				}
-
-				if ( cpu_time < next_play )
-					cpu_time = next_play;
-				next_play += play_period;
-				cpu_jsr( GET_LE16( header_.play_addr ) );
-				GME_FRAME_HOOK( this );
-				// TODO: handle timer rates different than 60 Hz
-			}
-			else if ( cpu::r.pc > 0xFFFF )
-			{
-				debug_printf( "PC wrapped around\n" );
-				cpu::r.pc &= 0xFFFF;
-			}
-			else
-			{
-				set_warning( "Emulation error (illegal/unsupported instruction)" );
-				debug_printf( "Bad opcode $%.2x at $%.4x\n",
-						(int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
-				cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
-				cpu_time += 6;
-			}
-		}
-	}
-
-	duration = cpu_time;
-	next_play -= cpu_time;
-	if ( next_play < 0 ) // could go negative if routine is taking too long to return
-		next_play = 0;
-	apu.end_frame( cpu_time );
-
-	return 0;
-}
diff --git a/src/console/Gme_File.cc b/src/console/Gme_File.cc
new file mode 100644
index 000000000000..303c7bad0a05
--- /dev/null
+++ b/src/console/Gme_File.cc
@@ -0,0 +1,215 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Gme_File.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+const char* const gme_wrong_file_type = "Wrong file type for this emulator";
+
+void Gme_File::clear_playlist()
+{
+	playlist.clear();
+	clear_playlist_();
+	track_count_ = raw_track_count_;
+}
+
+void Gme_File::unload()
+{
+	clear_playlist(); // *before* clearing track count
+	track_count_     = 0;
+	raw_track_count_ = 0;
+	file_data.clear();
+}
+
+Gme_File::Gme_File()
+{
+	type_         = 0;
+	user_data_    = 0;
+	user_cleanup_ = 0;
+	unload(); // clears fields
+}
+
+Gme_File::~Gme_File()
+{
+	if ( user_cleanup_ )
+		user_cleanup_( user_data_ );
+}
+
+blargg_err_t Gme_File::load_mem_( byte const* data, long size )
+{
+	require( data != file_data.begin() ); // load_mem_() or load_() must be overridden
+	Mem_File_Reader in( data, size );
+	return load_( in );
+}
+
+blargg_err_t Gme_File::load_( Data_Reader& in )
+{
+	RETURN_ERR( file_data.resize( in.remain() ) );
+	RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
+	return load_mem_( file_data.begin(), file_data.size() );
+}
+
+// public load functions call this at beginning
+void Gme_File::pre_load() { unload(); }
+
+void Gme_File::post_load_() { }
+
+// public load functions call this at end
+blargg_err_t Gme_File::post_load( blargg_err_t err )
+{
+	if ( !track_count() )
+		set_track_count( type()->track_count );
+	if ( !err )
+		post_load_();
+	else
+		unload();
+
+	return err;
+}
+
+// Public load functions
+
+blargg_err_t Gme_File::load_mem( void const* in, long size )
+{
+	pre_load();
+	return post_load( load_mem_( (byte const*) in, size ) );
+}
+
+blargg_err_t Gme_File::load( Data_Reader& in )
+{
+	pre_load();
+	return post_load( load_( in ) );
+}
+
+blargg_err_t Gme_File::load_file( const char* path )
+{
+	pre_load();
+	GME_FILE_READER in;
+	RETURN_ERR( in.open( path ) );
+	return post_load( load_( in ) );
+}
+
+blargg_err_t Gme_File::load_remaining_( void const* h, long s, Data_Reader& in )
+{
+	Remaining_Reader rem( h, s, &in );
+	return load( rem );
+}
+
+// Track info
+
+void Gme_File::copy_field_( char* out, const char* in, int in_size )
+{
+	if ( !in || !*in )
+		return;
+
+	// remove spaces/junk from beginning
+	while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
+	{
+		in++;
+		in_size--;
+	}
+
+	// truncate
+	if ( in_size > max_field_ )
+		in_size = max_field_;
+
+	// find terminator
+	int len = 0;
+	while ( len < in_size && in [len] )
+		len++;
+
+	// remove spaces/junk from end
+	while ( len && unsigned (in [len - 1]) <= ' ' )
+		len--;
+
+	// copy
+	out [len] = 0;
+	memcpy( out, in, len );
+
+	// strip out stupid fields that should have been left blank
+	if ( !strcmp( out, "?" ) || !strcmp( out, "<?>" ) || !strcmp( out, "< ? >" ) )
+		out [0] = 0;
+}
+
+void Gme_File::copy_field_( char* out, const char* in )
+{
+	copy_field_( out, in, max_field_ );
+}
+
+blargg_err_t Gme_File::remap_track_( int* track_io ) const
+{
+	if ( (unsigned) *track_io >= (unsigned) track_count() )
+		return "Invalid track";
+
+	if ( (unsigned) *track_io < (unsigned) playlist.size() )
+	{
+		M3u_Playlist::entry_t const& e = playlist [*track_io];
+		*track_io = 0;
+		if ( e.track >= 0 )
+		{
+			*track_io = e.track;
+			if ( !(type_->flags_ & 0x02) )
+				*track_io -= e.decimal_track;
+		}
+		if ( *track_io >= raw_track_count_ )
+			return "Invalid track in m3u playlist";
+	}
+	else
+	{
+		check( !playlist.size() );
+	}
+	return 0;
+}
+
+blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
+{
+	out->track_count = track_count();
+	out->length        = -1;
+	out->loop_length   = -1;
+	out->intro_length  = -1;
+	out->song [0]      = 0;
+
+	out->game [0]      = 0;
+	out->author [0]    = 0;
+	out->copyright [0] = 0;
+	out->comment [0]   = 0;
+	out->dumper [0]    = 0;
+	out->system [0]    = 0;
+
+	copy_field_( out->system, type()->system );
+
+	int remapped = track;
+	RETURN_ERR( remap_track_( &remapped ) );
+	RETURN_ERR( track_info_( out, remapped ) );
+
+	// override with m3u info
+	if ( playlist.size() )
+	{
+		M3u_Playlist::info_t const& i = playlist.info();
+		copy_field_( out->game  , i.title );
+		copy_field_( out->author, i.engineer );
+		copy_field_( out->author, i.composer );
+		copy_field_( out->dumper, i.ripping );
+
+		M3u_Playlist::entry_t const& e = playlist [track];
+		copy_field_( out->song, e.name );
+		if ( e.length >= 0 ) out->length       = e.length * 1000L;
+		if ( e.intro  >= 0 ) out->intro_length = e.intro  * 1000L;
+		if ( e.loop   >= 0 ) out->loop_length  = e.loop   * 1000L;
+	}
+	return 0;
+}
diff --git a/src/console/Gme_File.cxx b/src/console/Gme_File.cxx
deleted file mode 100644
index 303c7bad0a05..000000000000
--- a/src/console/Gme_File.cxx
+++ /dev/null
@@ -1,215 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gme_File.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char* const gme_wrong_file_type = "Wrong file type for this emulator";
-
-void Gme_File::clear_playlist()
-{
-	playlist.clear();
-	clear_playlist_();
-	track_count_ = raw_track_count_;
-}
-
-void Gme_File::unload()
-{
-	clear_playlist(); // *before* clearing track count
-	track_count_     = 0;
-	raw_track_count_ = 0;
-	file_data.clear();
-}
-
-Gme_File::Gme_File()
-{
-	type_         = 0;
-	user_data_    = 0;
-	user_cleanup_ = 0;
-	unload(); // clears fields
-}
-
-Gme_File::~Gme_File()
-{
-	if ( user_cleanup_ )
-		user_cleanup_( user_data_ );
-}
-
-blargg_err_t Gme_File::load_mem_( byte const* data, long size )
-{
-	require( data != file_data.begin() ); // load_mem_() or load_() must be overridden
-	Mem_File_Reader in( data, size );
-	return load_( in );
-}
-
-blargg_err_t Gme_File::load_( Data_Reader& in )
-{
-	RETURN_ERR( file_data.resize( in.remain() ) );
-	RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
-	return load_mem_( file_data.begin(), file_data.size() );
-}
-
-// public load functions call this at beginning
-void Gme_File::pre_load() { unload(); }
-
-void Gme_File::post_load_() { }
-
-// public load functions call this at end
-blargg_err_t Gme_File::post_load( blargg_err_t err )
-{
-	if ( !track_count() )
-		set_track_count( type()->track_count );
-	if ( !err )
-		post_load_();
-	else
-		unload();
-
-	return err;
-}
-
-// Public load functions
-
-blargg_err_t Gme_File::load_mem( void const* in, long size )
-{
-	pre_load();
-	return post_load( load_mem_( (byte const*) in, size ) );
-}
-
-blargg_err_t Gme_File::load( Data_Reader& in )
-{
-	pre_load();
-	return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_file( const char* path )
-{
-	pre_load();
-	GME_FILE_READER in;
-	RETURN_ERR( in.open( path ) );
-	return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_remaining_( void const* h, long s, Data_Reader& in )
-{
-	Remaining_Reader rem( h, s, &in );
-	return load( rem );
-}
-
-// Track info
-
-void Gme_File::copy_field_( char* out, const char* in, int in_size )
-{
-	if ( !in || !*in )
-		return;
-
-	// remove spaces/junk from beginning
-	while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
-	{
-		in++;
-		in_size--;
-	}
-
-	// truncate
-	if ( in_size > max_field_ )
-		in_size = max_field_;
-
-	// find terminator
-	int len = 0;
-	while ( len < in_size && in [len] )
-		len++;
-
-	// remove spaces/junk from end
-	while ( len && unsigned (in [len - 1]) <= ' ' )
-		len--;
-
-	// copy
-	out [len] = 0;
-	memcpy( out, in, len );
-
-	// strip out stupid fields that should have been left blank
-	if ( !strcmp( out, "?" ) || !strcmp( out, "<?>" ) || !strcmp( out, "< ? >" ) )
-		out [0] = 0;
-}
-
-void Gme_File::copy_field_( char* out, const char* in )
-{
-	copy_field_( out, in, max_field_ );
-}
-
-blargg_err_t Gme_File::remap_track_( int* track_io ) const
-{
-	if ( (unsigned) *track_io >= (unsigned) track_count() )
-		return "Invalid track";
-
-	if ( (unsigned) *track_io < (unsigned) playlist.size() )
-	{
-		M3u_Playlist::entry_t const& e = playlist [*track_io];
-		*track_io = 0;
-		if ( e.track >= 0 )
-		{
-			*track_io = e.track;
-			if ( !(type_->flags_ & 0x02) )
-				*track_io -= e.decimal_track;
-		}
-		if ( *track_io >= raw_track_count_ )
-			return "Invalid track in m3u playlist";
-	}
-	else
-	{
-		check( !playlist.size() );
-	}
-	return 0;
-}
-
-blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
-{
-	out->track_count = track_count();
-	out->length        = -1;
-	out->loop_length   = -1;
-	out->intro_length  = -1;
-	out->song [0]      = 0;
-
-	out->game [0]      = 0;
-	out->author [0]    = 0;
-	out->copyright [0] = 0;
-	out->comment [0]   = 0;
-	out->dumper [0]    = 0;
-	out->system [0]    = 0;
-
-	copy_field_( out->system, type()->system );
-
-	int remapped = track;
-	RETURN_ERR( remap_track_( &remapped ) );
-	RETURN_ERR( track_info_( out, remapped ) );
-
-	// override with m3u info
-	if ( playlist.size() )
-	{
-		M3u_Playlist::info_t const& i = playlist.info();
-		copy_field_( out->game  , i.title );
-		copy_field_( out->author, i.engineer );
-		copy_field_( out->author, i.composer );
-		copy_field_( out->dumper, i.ripping );
-
-		M3u_Playlist::entry_t const& e = playlist [track];
-		copy_field_( out->song, e.name );
-		if ( e.length >= 0 ) out->length       = e.length * 1000L;
-		if ( e.intro  >= 0 ) out->intro_length = e.intro  * 1000L;
-		if ( e.loop   >= 0 ) out->loop_length  = e.loop   * 1000L;
-	}
-	return 0;
-}
diff --git a/src/console/Gme_File.h b/src/console/Gme_File.h
index c47a6043e356..4554d9dce23a 100644
--- a/src/console/Gme_File.h
+++ b/src/console/Gme_File.h
@@ -76,7 +76,7 @@ public:
 	// is an NSFE emulator, and you can cast to an Nsfe_Emu* if necessary.
 	gme_type_t type() const;
 
-	// Most recent warning string, or NULL if none. Clears current warning after
+	// Most recent warning string, or nullptr if none. Clears current warning after
 	// returning.
 	const char* warning();
 
@@ -94,7 +94,7 @@ public:
 	void set_user_data( void* p )       { user_data_ = p; }
 	void* user_data() const             { return user_data_; }
 
-	// Register cleanup function to be called when deleting emulator, or NULL to
+	// Register cleanup function to be called when deleting emulator, or nullptr to
 	// clear it. Passes user_data to cleanup function.
 	void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
 
diff --git a/src/console/Gym_Emu.cc b/src/console/Gym_Emu.cc
new file mode 100644
index 000000000000..e850497976a9
--- /dev/null
+++ b/src/console/Gym_Emu.cc
@@ -0,0 +1,380 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Gym_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+double const min_tempo = 0.25;
+double const oversample_factor = 5 / 3.0;
+double const fm_gain = 3.0;
+
+const long base_clock = 53700300;
+const long clock_rate = base_clock / 15;
+
+Gym_Emu::Gym_Emu()
+{
+	data = 0;
+	pos  = 0;
+	set_type( gme_gym_type );
+
+	static const char* const names [] = {
+		"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
+	};
+	set_voice_names( names );
+	set_silence_lookahead( 1 ); // tracks should already be trimmed
+}
+
+Gym_Emu::~Gym_Emu() { }
+
+// Track info
+
+static void get_gym_info( Gym_Emu::header_t const& h, long length, track_info_t* out )
+{
+	if ( !memcmp( h.tag, "GYMX", 4 ) )
+	{
+		length = length * 50 / 3; // 1000 / 60
+		long loop = GET_LE32( h.loop_start );
+		if ( loop )
+		{
+			out->intro_length = loop * 50 / 3;
+			out->loop_length  = length - out->intro_length;
+		}
+		else
+		{
+			out->length = length;
+			out->intro_length = length; // make it clear that track is no longer than length
+			out->loop_length = 0;
+		}
+
+		// more stupidity where the field should have been left
+		if ( strcmp( h.song, "Unknown Song" ) )
+			GME_COPY_FIELD( h, out, song );
+
+		if ( strcmp( h.game, "Unknown Game" ) )
+			GME_COPY_FIELD( h, out, game );
+
+		if ( strcmp( h.copyright, "Unknown Publisher" ) )
+			GME_COPY_FIELD( h, out, copyright );
+
+		if ( strcmp( h.dumper, "Unknown Person" ) )
+			GME_COPY_FIELD( h, out, dumper );
+
+		if ( strcmp( h.comment, "Header added by YMAMP" ) )
+			GME_COPY_FIELD( h, out, comment );
+	}
+}
+
+blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
+{
+	get_gym_info( header_, track_length(), out );
+	return 0;
+}
+
+static long gym_track_length( byte const* p, byte const* end )
+{
+	long time = 0;
+	while ( p < end )
+	{
+		switch ( *p++ )
+		{
+			case 0:
+				time++;
+				break;
+
+			case 1:
+			case 2:
+				p += 2;
+				break;
+
+			case 3:
+				p += 1;
+				break;
+		}
+	}
+	return time;
+}
+
+long Gym_Emu::track_length() const { return gym_track_length( data, data_end ); }
+
+static blargg_err_t check_header( byte const* in, long size, int* data_offset = 0 )
+{
+	if ( size < 4 )
+		return gme_wrong_file_type;
+
+	if ( memcmp( in, "GYMX", 4 ) == 0 )
+	{
+		if ( size < Gym_Emu::header_size + 1 )
+			return gme_wrong_file_type;
+
+		if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
+			return "Packed GYM file not supported";
+
+		if ( data_offset )
+			*data_offset = Gym_Emu::header_size;
+	}
+	else if ( *in > 3 )
+	{
+		return gme_wrong_file_type;
+	}
+
+	return 0;
+}
+
+struct Gym_File : Gme_Info_
+{
+	byte const* file_begin;
+	byte const* file_end;
+	int data_offset;
+
+	Gym_File() { set_type( gme_gym_type ); }
+
+	blargg_err_t load_mem_( byte const* in, long size )
+	{
+		file_begin = in;
+		file_end   = in + size;
+		data_offset = 0;
+		return check_header( in, size, &data_offset );
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		long length = gym_track_length( &file_begin [data_offset], file_end );
+		get_gym_info( *(Gym_Emu::header_t const*) file_begin, length, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
+static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
+
+static gme_type_t_ const gme_gym_type_ = { "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 };
+gme_type_t const gme_gym_type = &gme_gym_type_;
+
+// Setup
+
+blargg_err_t Gym_Emu::set_sample_rate_( long sample_rate )
+{
+	blip_eq_t eq( -32, 8000, sample_rate );
+	apu.treble_eq( eq );
+	dac_synth.treble_eq( eq );
+	apu.volume( 0.135 * fm_gain * gain() );
+	dac_synth.volume( 0.125 / 256 * fm_gain * gain() );
+	double factor = Dual_Resampler::setup( oversample_factor, 0.990, fm_gain * gain() );
+	fm_sample_rate = sample_rate * factor;
+
+	RETURN_ERR( blip_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
+	blip_buf.clock_rate( clock_rate );
+
+	RETURN_ERR( fm.set_rate( fm_sample_rate, base_clock / 7.0 ) );
+	RETURN_ERR( Dual_Resampler::reset( long (1.0 / 60 / min_tempo * sample_rate) ) );
+
+	return 0;
+}
+
+void Gym_Emu::set_tempo_( double t )
+{
+	if ( t < min_tempo )
+	{
+		set_tempo( min_tempo );
+		return;
+	}
+
+	if ( blip_buf.sample_rate() )
+	{
+		clocks_per_frame = long (clock_rate / 60 / tempo());
+		Dual_Resampler::resize( long (sample_rate() / (60.0 * tempo())) );
+	}
+}
+
+void Gym_Emu::mute_voices_( int mask )
+{
+	Music_Emu::mute_voices_( mask );
+	fm.mute_voices( mask );
+	dac_muted = (mask & 0x40) != 0;
+	apu.output( (mask & 0x80) ? 0 : &blip_buf );
+}
+
+blargg_err_t Gym_Emu::load_mem_( byte const* in, long size )
+{
+	assert( offsetof (header_t,packed [4]) == header_size );
+	int offset = 0;
+	RETURN_ERR( check_header( in, size, &offset ) );
+	set_voice_count( 8 );
+
+	data     = in + offset;
+	data_end = in + size;
+	loop_begin = 0;
+
+	if ( offset )
+		header_ = *(header_t const*) in;
+	else
+		memset( &header_, 0, sizeof header_ );
+
+	return 0;
+}
+
+// Emulation
+
+blargg_err_t Gym_Emu::start_track_( int track )
+{
+	RETURN_ERR( Music_Emu::start_track_( track ) );
+
+	pos         = data;
+	loop_remain = GET_LE32( header_.loop_start );
+
+	prev_dac_count = 0;
+	dac_enabled    = false;
+	dac_amp        = -1;
+
+	fm.reset();
+	apu.reset();
+	blip_buf.clear();
+	Dual_Resampler::clear();
+	return 0;
+}
+
+void Gym_Emu::run_dac( int dac_count )
+{
+	// Guess beginning and end of sample and adjust rate and buffer position accordingly.
+
+	// count dac samples in next frame
+	int next_dac_count = 0;
+	const byte* p = this->pos;
+	int cmd;
+	while ( (cmd = *p++) != 0 )
+	{
+		int data = *p++;
+		if ( cmd <= 2 )
+			++p;
+		if ( cmd == 1 && data == 0x2A )
+			next_dac_count++;
+	}
+
+	// detect beginning and end of sample
+	int rate_count = dac_count;
+	int start = 0;
+	if ( !prev_dac_count && next_dac_count && dac_count < next_dac_count )
+	{
+		rate_count = next_dac_count;
+		start = next_dac_count - dac_count;
+	}
+	else if ( prev_dac_count && !next_dac_count && dac_count < prev_dac_count )
+	{
+		rate_count = prev_dac_count;
+	}
+
+	// Evenly space samples within buffer section being used
+	blip_resampled_time_t period = blip_buf.resampled_duration( clocks_per_frame ) / rate_count;
+
+	blip_resampled_time_t time = blip_buf.resampled_time( 0 ) +
+			period * start + (period >> 1);
+
+	int dac_amp = this->dac_amp;
+	if ( dac_amp < 0 )
+		dac_amp = dac_buf [0];
+
+	for ( int i = 0; i < dac_count; i++ )
+	{
+		int delta = dac_buf [i] - dac_amp;
+		dac_amp += delta;
+		dac_synth.offset_resampled( time, delta, &blip_buf );
+		time += period;
+	}
+	this->dac_amp = dac_amp;
+}
+
+void Gym_Emu::parse_frame()
+{
+	int dac_count = 0;
+	const byte* pos = this->pos;
+
+	if ( loop_remain && !--loop_remain )
+		loop_begin = pos; // find loop on first time through sequence
+
+	int cmd;
+	while ( (cmd = *pos++) != 0 )
+	{
+		int data = *pos++;
+		if ( cmd == 1 )
+		{
+			int data2 = *pos++;
+			if ( data != 0x2A )
+			{
+				if ( data == 0x2B )
+					dac_enabled = (data2 & 0x80) != 0;
+
+				fm.write0( data, data2 );
+			}
+			else if ( dac_count < (int) sizeof dac_buf )
+			{
+				dac_buf [dac_count] = data2;
+				dac_count += dac_enabled;
+			}
+		}
+		else if ( cmd == 2 )
+		{
+			fm.write1( data, *pos++ );
+		}
+		else if ( cmd == 3 )
+		{
+			apu.write_data( 0, data );
+		}
+		else
+		{
+			// to do: many GYM streams are full of errors, and error count should
+			// reflect cases where music is really having problems
+			//log_error();
+			--pos; // put data back
+		}
+	}
+
+	// loop
+	if ( pos >= data_end )
+	{
+		check( pos == data_end );
+
+		if ( loop_begin )
+			pos = loop_begin;
+		else
+			set_track_ended();
+	}
+	this->pos = pos;
+
+	// dac
+	if ( dac_count && !dac_muted )
+		run_dac( dac_count );
+	prev_dac_count = dac_count;
+}
+
+int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
+{
+	if ( !track_ended() )
+		parse_frame();
+
+	apu.end_frame( blip_time );
+
+	memset( buf, 0, sample_count * sizeof *buf );
+	fm.run( sample_count >> 1, buf );
+
+	return sample_count;
+}
+
+blargg_err_t Gym_Emu::play_( long count, sample_t* out )
+{
+	Dual_Resampler::dual_play( count, out, blip_buf );
+	return 0;
+}
diff --git a/src/console/Gym_Emu.cxx b/src/console/Gym_Emu.cxx
deleted file mode 100644
index e850497976a9..000000000000
--- a/src/console/Gym_Emu.cxx
+++ /dev/null
@@ -1,380 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gym_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const min_tempo = 0.25;
-double const oversample_factor = 5 / 3.0;
-double const fm_gain = 3.0;
-
-const long base_clock = 53700300;
-const long clock_rate = base_clock / 15;
-
-Gym_Emu::Gym_Emu()
-{
-	data = 0;
-	pos  = 0;
-	set_type( gme_gym_type );
-
-	static const char* const names [] = {
-		"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
-	};
-	set_voice_names( names );
-	set_silence_lookahead( 1 ); // tracks should already be trimmed
-}
-
-Gym_Emu::~Gym_Emu() { }
-
-// Track info
-
-static void get_gym_info( Gym_Emu::header_t const& h, long length, track_info_t* out )
-{
-	if ( !memcmp( h.tag, "GYMX", 4 ) )
-	{
-		length = length * 50 / 3; // 1000 / 60
-		long loop = GET_LE32( h.loop_start );
-		if ( loop )
-		{
-			out->intro_length = loop * 50 / 3;
-			out->loop_length  = length - out->intro_length;
-		}
-		else
-		{
-			out->length = length;
-			out->intro_length = length; // make it clear that track is no longer than length
-			out->loop_length = 0;
-		}
-
-		// more stupidity where the field should have been left
-		if ( strcmp( h.song, "Unknown Song" ) )
-			GME_COPY_FIELD( h, out, song );
-
-		if ( strcmp( h.game, "Unknown Game" ) )
-			GME_COPY_FIELD( h, out, game );
-
-		if ( strcmp( h.copyright, "Unknown Publisher" ) )
-			GME_COPY_FIELD( h, out, copyright );
-
-		if ( strcmp( h.dumper, "Unknown Person" ) )
-			GME_COPY_FIELD( h, out, dumper );
-
-		if ( strcmp( h.comment, "Header added by YMAMP" ) )
-			GME_COPY_FIELD( h, out, comment );
-	}
-}
-
-blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
-{
-	get_gym_info( header_, track_length(), out );
-	return 0;
-}
-
-static long gym_track_length( byte const* p, byte const* end )
-{
-	long time = 0;
-	while ( p < end )
-	{
-		switch ( *p++ )
-		{
-			case 0:
-				time++;
-				break;
-
-			case 1:
-			case 2:
-				p += 2;
-				break;
-
-			case 3:
-				p += 1;
-				break;
-		}
-	}
-	return time;
-}
-
-long Gym_Emu::track_length() const { return gym_track_length( data, data_end ); }
-
-static blargg_err_t check_header( byte const* in, long size, int* data_offset = 0 )
-{
-	if ( size < 4 )
-		return gme_wrong_file_type;
-
-	if ( memcmp( in, "GYMX", 4 ) == 0 )
-	{
-		if ( size < Gym_Emu::header_size + 1 )
-			return gme_wrong_file_type;
-
-		if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
-			return "Packed GYM file not supported";
-
-		if ( data_offset )
-			*data_offset = Gym_Emu::header_size;
-	}
-	else if ( *in > 3 )
-	{
-		return gme_wrong_file_type;
-	}
-
-	return 0;
-}
-
-struct Gym_File : Gme_Info_
-{
-	byte const* file_begin;
-	byte const* file_end;
-	int data_offset;
-
-	Gym_File() { set_type( gme_gym_type ); }
-
-	blargg_err_t load_mem_( byte const* in, long size )
-	{
-		file_begin = in;
-		file_end   = in + size;
-		data_offset = 0;
-		return check_header( in, size, &data_offset );
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		long length = gym_track_length( &file_begin [data_offset], file_end );
-		get_gym_info( *(Gym_Emu::header_t const*) file_begin, length, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
-static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
-
-static gme_type_t_ const gme_gym_type_ = { "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 };
-gme_type_t const gme_gym_type = &gme_gym_type_;
-
-// Setup
-
-blargg_err_t Gym_Emu::set_sample_rate_( long sample_rate )
-{
-	blip_eq_t eq( -32, 8000, sample_rate );
-	apu.treble_eq( eq );
-	dac_synth.treble_eq( eq );
-	apu.volume( 0.135 * fm_gain * gain() );
-	dac_synth.volume( 0.125 / 256 * fm_gain * gain() );
-	double factor = Dual_Resampler::setup( oversample_factor, 0.990, fm_gain * gain() );
-	fm_sample_rate = sample_rate * factor;
-
-	RETURN_ERR( blip_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
-	blip_buf.clock_rate( clock_rate );
-
-	RETURN_ERR( fm.set_rate( fm_sample_rate, base_clock / 7.0 ) );
-	RETURN_ERR( Dual_Resampler::reset( long (1.0 / 60 / min_tempo * sample_rate) ) );
-
-	return 0;
-}
-
-void Gym_Emu::set_tempo_( double t )
-{
-	if ( t < min_tempo )
-	{
-		set_tempo( min_tempo );
-		return;
-	}
-
-	if ( blip_buf.sample_rate() )
-	{
-		clocks_per_frame = long (clock_rate / 60 / tempo());
-		Dual_Resampler::resize( long (sample_rate() / (60.0 * tempo())) );
-	}
-}
-
-void Gym_Emu::mute_voices_( int mask )
-{
-	Music_Emu::mute_voices_( mask );
-	fm.mute_voices( mask );
-	dac_muted = (mask & 0x40) != 0;
-	apu.output( (mask & 0x80) ? 0 : &blip_buf );
-}
-
-blargg_err_t Gym_Emu::load_mem_( byte const* in, long size )
-{
-	assert( offsetof (header_t,packed [4]) == header_size );
-	int offset = 0;
-	RETURN_ERR( check_header( in, size, &offset ) );
-	set_voice_count( 8 );
-
-	data     = in + offset;
-	data_end = in + size;
-	loop_begin = 0;
-
-	if ( offset )
-		header_ = *(header_t const*) in;
-	else
-		memset( &header_, 0, sizeof header_ );
-
-	return 0;
-}
-
-// Emulation
-
-blargg_err_t Gym_Emu::start_track_( int track )
-{
-	RETURN_ERR( Music_Emu::start_track_( track ) );
-
-	pos         = data;
-	loop_remain = GET_LE32( header_.loop_start );
-
-	prev_dac_count = 0;
-	dac_enabled    = false;
-	dac_amp        = -1;
-
-	fm.reset();
-	apu.reset();
-	blip_buf.clear();
-	Dual_Resampler::clear();
-	return 0;
-}
-
-void Gym_Emu::run_dac( int dac_count )
-{
-	// Guess beginning and end of sample and adjust rate and buffer position accordingly.
-
-	// count dac samples in next frame
-	int next_dac_count = 0;
-	const byte* p = this->pos;
-	int cmd;
-	while ( (cmd = *p++) != 0 )
-	{
-		int data = *p++;
-		if ( cmd <= 2 )
-			++p;
-		if ( cmd == 1 && data == 0x2A )
-			next_dac_count++;
-	}
-
-	// detect beginning and end of sample
-	int rate_count = dac_count;
-	int start = 0;
-	if ( !prev_dac_count && next_dac_count && dac_count < next_dac_count )
-	{
-		rate_count = next_dac_count;
-		start = next_dac_count - dac_count;
-	}
-	else if ( prev_dac_count && !next_dac_count && dac_count < prev_dac_count )
-	{
-		rate_count = prev_dac_count;
-	}
-
-	// Evenly space samples within buffer section being used
-	blip_resampled_time_t period = blip_buf.resampled_duration( clocks_per_frame ) / rate_count;
-
-	blip_resampled_time_t time = blip_buf.resampled_time( 0 ) +
-			period * start + (period >> 1);
-
-	int dac_amp = this->dac_amp;
-	if ( dac_amp < 0 )
-		dac_amp = dac_buf [0];
-
-	for ( int i = 0; i < dac_count; i++ )
-	{
-		int delta = dac_buf [i] - dac_amp;
-		dac_amp += delta;
-		dac_synth.offset_resampled( time, delta, &blip_buf );
-		time += period;
-	}
-	this->dac_amp = dac_amp;
-}
-
-void Gym_Emu::parse_frame()
-{
-	int dac_count = 0;
-	const byte* pos = this->pos;
-
-	if ( loop_remain && !--loop_remain )
-		loop_begin = pos; // find loop on first time through sequence
-
-	int cmd;
-	while ( (cmd = *pos++) != 0 )
-	{
-		int data = *pos++;
-		if ( cmd == 1 )
-		{
-			int data2 = *pos++;
-			if ( data != 0x2A )
-			{
-				if ( data == 0x2B )
-					dac_enabled = (data2 & 0x80) != 0;
-
-				fm.write0( data, data2 );
-			}
-			else if ( dac_count < (int) sizeof dac_buf )
-			{
-				dac_buf [dac_count] = data2;
-				dac_count += dac_enabled;
-			}
-		}
-		else if ( cmd == 2 )
-		{
-			fm.write1( data, *pos++ );
-		}
-		else if ( cmd == 3 )
-		{
-			apu.write_data( 0, data );
-		}
-		else
-		{
-			// to do: many GYM streams are full of errors, and error count should
-			// reflect cases where music is really having problems
-			//log_error();
-			--pos; // put data back
-		}
-	}
-
-	// loop
-	if ( pos >= data_end )
-	{
-		check( pos == data_end );
-
-		if ( loop_begin )
-			pos = loop_begin;
-		else
-			set_track_ended();
-	}
-	this->pos = pos;
-
-	// dac
-	if ( dac_count && !dac_muted )
-		run_dac( dac_count );
-	prev_dac_count = dac_count;
-}
-
-int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
-	if ( !track_ended() )
-		parse_frame();
-
-	apu.end_frame( blip_time );
-
-	memset( buf, 0, sample_count * sizeof *buf );
-	fm.run( sample_count >> 1, buf );
-
-	return sample_count;
-}
-
-blargg_err_t Gym_Emu::play_( long count, sample_t* out )
-{
-	Dual_Resampler::dual_play( count, out, blip_buf );
-	return 0;
-}
diff --git a/src/console/Gzip_Reader.cc b/src/console/Gzip_Reader.cc
new file mode 100644
index 000000000000..2402cf5770ff
--- /dev/null
+++ b/src/console/Gzip_Reader.cc
@@ -0,0 +1,108 @@
+// File_Extractor 0.4.0. http://www.slack.net/~ant/
+
+#include "Gzip_Reader.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Gzip_Reader::close()
+{
+	in    = 0;
+	tell_ = 0;
+	size_ = 0;
+	inflater.end();
+}
+
+Gzip_Reader::Gzip_Reader() { close(); }
+
+Gzip_Reader::~Gzip_Reader() { }
+
+static blargg_err_t gzip_reader_read( void* file, void* out, long* count )
+{
+	*count = ((File_Reader*) file)->read_avail( out, *count );
+	return (*count < 0 ? "Read error" : 0);
+}
+
+blargg_err_t Gzip_Reader::open( File_Reader* new_in )
+{
+	close();
+
+	RETURN_ERR( inflater.begin( inflater.mode_auto, gzip_reader_read, new_in ) );
+
+	size_ = -1; // defer seeking to end of file until size is actually needed
+	in    = new_in;
+	return 0;
+}
+
+blargg_err_t Gzip_Reader::calc_size()
+{
+	long size = in->size();
+	if ( inflater.deflated() )
+	{
+		byte trailer [4];
+		long pos = in->tell();
+		RETURN_ERR( in->seek( size - sizeof trailer ) );
+		RETURN_ERR( in->read( trailer, sizeof trailer ) );
+		RETURN_ERR( in->seek( pos ) );
+		size = GET_LE32( trailer );
+	}
+	size_ = size;
+	return 0;
+}
+
+long Gzip_Reader::remain() const
+{
+	if ( size_ < 0 )
+	{
+		if ( !in )
+			return 0;
+
+		// need to cast away constness to change cached value
+		if ( ((Gzip_Reader*) this)->calc_size() )
+			return -1;
+	}
+	return size_ - tell_;
+}
+
+blargg_err_t Gzip_Reader::read_( void* out, long* count )
+{
+	blargg_err_t err = inflater.read( out, count, gzip_reader_read, in );
+	tell_ += *count;
+	if ( size_ >= 0 && tell_ > size_ )
+	{
+		tell_ = size_;
+		return "Corrupt gzip file";
+	}
+	return err;
+}
+
+blargg_err_t Gzip_Reader::read( void* out, long count )
+{
+	if ( in )
+	{
+		long actual = count;
+		RETURN_ERR( read_( out, &actual ) );
+		if ( actual == count )
+			return 0;
+	}
+	return eof_error;
+}
+
+long Gzip_Reader::read_avail( void* out, long count )
+{
+	if ( !in || read_( out, &count ) )
+		count = -1;
+	return count;
+}
diff --git a/src/console/Gzip_Reader.cxx b/src/console/Gzip_Reader.cxx
deleted file mode 100644
index 2402cf5770ff..000000000000
--- a/src/console/Gzip_Reader.cxx
+++ /dev/null
@@ -1,108 +0,0 @@
-// File_Extractor 0.4.0. http://www.slack.net/~ant/
-
-#include "Gzip_Reader.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Gzip_Reader::close()
-{
-	in    = 0;
-	tell_ = 0;
-	size_ = 0;
-	inflater.end();
-}
-
-Gzip_Reader::Gzip_Reader() { close(); }
-
-Gzip_Reader::~Gzip_Reader() { }
-
-static blargg_err_t gzip_reader_read( void* file, void* out, long* count )
-{
-	*count = ((File_Reader*) file)->read_avail( out, *count );
-	return (*count < 0 ? "Read error" : 0);
-}
-
-blargg_err_t Gzip_Reader::open( File_Reader* new_in )
-{
-	close();
-
-	RETURN_ERR( inflater.begin( inflater.mode_auto, gzip_reader_read, new_in ) );
-
-	size_ = -1; // defer seeking to end of file until size is actually needed
-	in    = new_in;
-	return 0;
-}
-
-blargg_err_t Gzip_Reader::calc_size()
-{
-	long size = in->size();
-	if ( inflater.deflated() )
-	{
-		byte trailer [4];
-		long pos = in->tell();
-		RETURN_ERR( in->seek( size - sizeof trailer ) );
-		RETURN_ERR( in->read( trailer, sizeof trailer ) );
-		RETURN_ERR( in->seek( pos ) );
-		size = GET_LE32( trailer );
-	}
-	size_ = size;
-	return 0;
-}
-
-long Gzip_Reader::remain() const
-{
-	if ( size_ < 0 )
-	{
-		if ( !in )
-			return 0;
-
-		// need to cast away constness to change cached value
-		if ( ((Gzip_Reader*) this)->calc_size() )
-			return -1;
-	}
-	return size_ - tell_;
-}
-
-blargg_err_t Gzip_Reader::read_( void* out, long* count )
-{
-	blargg_err_t err = inflater.read( out, count, gzip_reader_read, in );
-	tell_ += *count;
-	if ( size_ >= 0 && tell_ > size_ )
-	{
-		tell_ = size_;
-		return "Corrupt gzip file";
-	}
-	return err;
-}
-
-blargg_err_t Gzip_Reader::read( void* out, long count )
-{
-	if ( in )
-	{
-		long actual = count;
-		RETURN_ERR( read_( out, &actual ) );
-		if ( actual == count )
-			return 0;
-	}
-	return eof_error;
-}
-
-long Gzip_Reader::read_avail( void* out, long count )
-{
-	if ( !in || read_( out, &count ) )
-		count = -1;
-	return count;
-}
diff --git a/src/console/Hes_Apu.cc b/src/console/Hes_Apu.cc
new file mode 100644
index 000000000000..245a4bf55417
--- /dev/null
+++ b/src/console/Hes_Apu.cc
@@ -0,0 +1,315 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Hes_Apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+bool const center_waves = true; // reduces asymmetry and clamping when starting notes
+
+Hes_Apu::Hes_Apu()
+{
+	Hes_Osc* osc = &oscs [osc_count];
+	do
+	{
+		osc--;
+		osc->outputs [0] = 0;
+		osc->outputs [1] = 0;
+		osc->chans [0] = 0;
+		osc->chans [1] = 0;
+		osc->chans [2] = 0;
+	}
+	while ( osc != oscs );
+
+	reset();
+}
+
+void Hes_Apu::reset()
+{
+	latch   = 0;
+	balance = 0xFF;
+
+	Hes_Osc* osc = &oscs [osc_count];
+	do
+	{
+		osc--;
+		memset( osc, 0, offsetof (Hes_Osc,outputs) );
+		osc->noise_lfsr = 1;
+		osc->control    = 0x40;
+		osc->balance    = 0xFF;
+	}
+	while ( osc != oscs );
+}
+
+void Hes_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	require( (unsigned) index < osc_count );
+	oscs [index].chans [0] = center;
+	oscs [index].chans [1] = left;
+	oscs [index].chans [2] = right;
+
+	Hes_Osc* osc = &oscs [osc_count];
+	do
+	{
+		osc--;
+		balance_changed( *osc );
+	}
+	while ( osc != oscs );
+}
+
+void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
+{
+	Blip_Buffer* const osc_outputs_0 = outputs [0]; // cache often-used values
+	if ( osc_outputs_0 && control & 0x80 )
+	{
+		int dac = this->dac;
+
+		int const volume_0 = volume [0];
+		{
+			int delta = dac * volume_0 - last_amp [0];
+			if ( delta )
+				synth_.offset( last_time, delta, osc_outputs_0 );
+			osc_outputs_0->set_modified();
+		}
+
+		Blip_Buffer* const osc_outputs_1 = outputs [1];
+		int const volume_1 = volume [1];
+		if ( osc_outputs_1 )
+		{
+			int delta = dac * volume_1 - last_amp [1];
+			if ( delta )
+				synth_.offset( last_time, delta, osc_outputs_1 );
+			osc_outputs_1->set_modified();
+		}
+
+		blip_time_t time = last_time + delay;
+		if ( time < end_time )
+		{
+			if ( noise & 0x80 )
+			{
+				if ( volume_0 | volume_1 )
+				{
+					// noise
+					int const period = (32 - (noise & 0x1F)) * 64; // TODO: correct?
+					unsigned noise_lfsr = this->noise_lfsr;
+					do
+					{
+						int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
+						// Implemented using "Galios configuration"
+						// TODO: find correct LFSR algorithm
+						noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1));
+						//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
+						int delta = new_dac - dac;
+						if ( delta )
+						{
+							dac = new_dac;
+							synth_.offset( time, delta * volume_0, osc_outputs_0 );
+							if ( osc_outputs_1 )
+								synth_.offset( time, delta * volume_1, osc_outputs_1 );
+						}
+						time += period;
+					}
+					while ( time < end_time );
+
+					this->noise_lfsr = noise_lfsr;
+					assert( noise_lfsr );
+				}
+			}
+			else if ( !(control & 0x40) )
+			{
+				// wave
+				int phase = (this->phase + 1) & 0x1F; // pre-advance for optimal inner loop
+				int period = this->period * 2;
+				if ( period >= 14 && (volume_0 | volume_1) )
+				{
+					do
+					{
+						int new_dac = wave [phase];
+						phase = (phase + 1) & 0x1F;
+						int delta = new_dac - dac;
+						if ( delta )
+						{
+							dac = new_dac;
+							synth_.offset( time, delta * volume_0, osc_outputs_0 );
+							if ( osc_outputs_1 )
+								synth_.offset( time, delta * volume_1, osc_outputs_1 );
+						}
+						time += period;
+					}
+					while ( time < end_time );
+				}
+				else
+				{
+					if ( !period )
+					{
+						// TODO: Gekisha Boy assumes that period = 0 silences wave
+						//period = 0x1000 * 2;
+						period = 1;
+						//if ( !(volume_0 | volume_1) )
+						//  debug_printf( "Used period 0\n" );
+					}
+
+					// maintain phase when silent
+					blargg_long count = (end_time - time + period - 1) / period;
+					phase += count; // phase will be masked below
+					time += count * period;
+				}
+				this->phase = (phase - 1) & 0x1F; // undo pre-advance
+			}
+		}
+		time -= end_time;
+		if ( time < 0 )
+			time = 0;
+		delay = time;
+
+		this->dac = dac;
+		last_amp [0] = dac * volume_0;
+		last_amp [1] = dac * volume_1;
+	}
+	last_time = end_time;
+}
+
+void Hes_Apu::balance_changed( Hes_Osc& osc )
+{
+	static short const log_table [32] = { // ~1.5 db per step
+		#define ENTRY( factor ) short (factor * Hes_Osc::amp_range / 31.0 + 0.5)
+		ENTRY( 0.000000 ),ENTRY( 0.005524 ),ENTRY( 0.006570 ),ENTRY( 0.007813 ),
+		ENTRY( 0.009291 ),ENTRY( 0.011049 ),ENTRY( 0.013139 ),ENTRY( 0.015625 ),
+		ENTRY( 0.018581 ),ENTRY( 0.022097 ),ENTRY( 0.026278 ),ENTRY( 0.031250 ),
+		ENTRY( 0.037163 ),ENTRY( 0.044194 ),ENTRY( 0.052556 ),ENTRY( 0.062500 ),
+		ENTRY( 0.074325 ),ENTRY( 0.088388 ),ENTRY( 0.105112 ),ENTRY( 0.125000 ),
+		ENTRY( 0.148651 ),ENTRY( 0.176777 ),ENTRY( 0.210224 ),ENTRY( 0.250000 ),
+		ENTRY( 0.297302 ),ENTRY( 0.353553 ),ENTRY( 0.420448 ),ENTRY( 0.500000 ),
+		ENTRY( 0.594604 ),ENTRY( 0.707107 ),ENTRY( 0.840896 ),ENTRY( 1.000000 ),
+		#undef ENTRY
+	};
+
+	int vol = (osc.control & 0x1F) - 0x1E * 2;
+
+	int left  = vol + (osc.balance >> 3 & 0x1E) + (balance >> 3 & 0x1E);
+	if ( left  < 0 ) left  = 0;
+
+	int right = vol + (osc.balance << 1 & 0x1E) + (balance << 1 & 0x1E);
+	if ( right < 0 ) right = 0;
+
+	left  = log_table [left ];
+	right = log_table [right];
+
+	// optimizing for the common case of being centered also allows easy
+	// panning using Effects_Buffer
+	osc.outputs [0] = osc.chans [0]; // center
+	osc.outputs [1] = 0;
+	if ( left != right )
+	{
+		osc.outputs [0] = osc.chans [1]; // left
+		osc.outputs [1] = osc.chans [2]; // right
+	}
+
+	if ( center_waves )
+	{
+		osc.last_amp [0] += (left  - osc.volume [0]) * 16;
+		osc.last_amp [1] += (right - osc.volume [1]) * 16;
+	}
+
+	osc.volume [0] = left;
+	osc.volume [1] = right;
+}
+
+void Hes_Apu::write_data( blip_time_t time, int addr, int data )
+{
+	if ( addr == 0x800 )
+	{
+		latch = data & 7;
+	}
+	else if ( addr == 0x801 )
+	{
+		if ( balance != data )
+		{
+			balance = data;
+
+			Hes_Osc* osc = &oscs [osc_count];
+			do
+			{
+				osc--;
+				osc->run_until( synth, time );
+				balance_changed( *oscs );
+			}
+			while ( osc != oscs );
+		}
+	}
+	else if ( latch < osc_count )
+	{
+		Hes_Osc& osc = oscs [latch];
+		osc.run_until( synth, time );
+		switch ( addr )
+		{
+		case 0x802:
+			osc.period = (osc.period & 0xF00) | data;
+			break;
+
+		case 0x803:
+			osc.period = (osc.period & 0x0FF) | ((data & 0x0F) << 8);
+			break;
+
+		case 0x804:
+			if ( osc.control & 0x40 & ~data )
+				osc.phase = 0;
+			osc.control = data;
+			balance_changed( osc );
+			break;
+
+		case 0x805:
+			osc.balance = data;
+			balance_changed( osc );
+			break;
+
+		case 0x806:
+			data &= 0x1F;
+			if ( !(osc.control & 0x40) )
+			{
+				osc.wave [osc.phase] = data;
+				osc.phase = (osc.phase + 1) & 0x1F;
+			}
+			else if ( osc.control & 0x80 )
+			{
+				osc.dac = data;
+			}
+			break;
+
+		 case 0x807:
+		 	if ( &osc >= &oscs [4] )
+		 		osc.noise = data;
+		 	break;
+
+		 case 0x809:
+		 	if ( !(data & 0x80) && (data & 0x03) != 0 )
+		 		debug_printf( "HES LFO not supported\n" );
+		}
+	}
+}
+
+void Hes_Apu::end_frame( blip_time_t end_time )
+{
+	Hes_Osc* osc = &oscs [osc_count];
+	do
+	{
+		osc--;
+		if ( end_time > osc->last_time )
+			osc->run_until( synth, end_time );
+		assert( osc->last_time >= end_time );
+		osc->last_time -= end_time;
+	}
+	while ( osc != oscs );
+}
diff --git a/src/console/Hes_Apu.cxx b/src/console/Hes_Apu.cxx
deleted file mode 100644
index 245a4bf55417..000000000000
--- a/src/console/Hes_Apu.cxx
+++ /dev/null
@@ -1,315 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-bool const center_waves = true; // reduces asymmetry and clamping when starting notes
-
-Hes_Apu::Hes_Apu()
-{
-	Hes_Osc* osc = &oscs [osc_count];
-	do
-	{
-		osc--;
-		osc->outputs [0] = 0;
-		osc->outputs [1] = 0;
-		osc->chans [0] = 0;
-		osc->chans [1] = 0;
-		osc->chans [2] = 0;
-	}
-	while ( osc != oscs );
-
-	reset();
-}
-
-void Hes_Apu::reset()
-{
-	latch   = 0;
-	balance = 0xFF;
-
-	Hes_Osc* osc = &oscs [osc_count];
-	do
-	{
-		osc--;
-		memset( osc, 0, offsetof (Hes_Osc,outputs) );
-		osc->noise_lfsr = 1;
-		osc->control    = 0x40;
-		osc->balance    = 0xFF;
-	}
-	while ( osc != oscs );
-}
-
-void Hes_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	require( (unsigned) index < osc_count );
-	oscs [index].chans [0] = center;
-	oscs [index].chans [1] = left;
-	oscs [index].chans [2] = right;
-
-	Hes_Osc* osc = &oscs [osc_count];
-	do
-	{
-		osc--;
-		balance_changed( *osc );
-	}
-	while ( osc != oscs );
-}
-
-void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
-{
-	Blip_Buffer* const osc_outputs_0 = outputs [0]; // cache often-used values
-	if ( osc_outputs_0 && control & 0x80 )
-	{
-		int dac = this->dac;
-
-		int const volume_0 = volume [0];
-		{
-			int delta = dac * volume_0 - last_amp [0];
-			if ( delta )
-				synth_.offset( last_time, delta, osc_outputs_0 );
-			osc_outputs_0->set_modified();
-		}
-
-		Blip_Buffer* const osc_outputs_1 = outputs [1];
-		int const volume_1 = volume [1];
-		if ( osc_outputs_1 )
-		{
-			int delta = dac * volume_1 - last_amp [1];
-			if ( delta )
-				synth_.offset( last_time, delta, osc_outputs_1 );
-			osc_outputs_1->set_modified();
-		}
-
-		blip_time_t time = last_time + delay;
-		if ( time < end_time )
-		{
-			if ( noise & 0x80 )
-			{
-				if ( volume_0 | volume_1 )
-				{
-					// noise
-					int const period = (32 - (noise & 0x1F)) * 64; // TODO: correct?
-					unsigned noise_lfsr = this->noise_lfsr;
-					do
-					{
-						int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
-						// Implemented using "Galios configuration"
-						// TODO: find correct LFSR algorithm
-						noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1));
-						//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
-						int delta = new_dac - dac;
-						if ( delta )
-						{
-							dac = new_dac;
-							synth_.offset( time, delta * volume_0, osc_outputs_0 );
-							if ( osc_outputs_1 )
-								synth_.offset( time, delta * volume_1, osc_outputs_1 );
-						}
-						time += period;
-					}
-					while ( time < end_time );
-
-					this->noise_lfsr = noise_lfsr;
-					assert( noise_lfsr );
-				}
-			}
-			else if ( !(control & 0x40) )
-			{
-				// wave
-				int phase = (this->phase + 1) & 0x1F; // pre-advance for optimal inner loop
-				int period = this->period * 2;
-				if ( period >= 14 && (volume_0 | volume_1) )
-				{
-					do
-					{
-						int new_dac = wave [phase];
-						phase = (phase + 1) & 0x1F;
-						int delta = new_dac - dac;
-						if ( delta )
-						{
-							dac = new_dac;
-							synth_.offset( time, delta * volume_0, osc_outputs_0 );
-							if ( osc_outputs_1 )
-								synth_.offset( time, delta * volume_1, osc_outputs_1 );
-						}
-						time += period;
-					}
-					while ( time < end_time );
-				}
-				else
-				{
-					if ( !period )
-					{
-						// TODO: Gekisha Boy assumes that period = 0 silences wave
-						//period = 0x1000 * 2;
-						period = 1;
-						//if ( !(volume_0 | volume_1) )
-						//  debug_printf( "Used period 0\n" );
-					}
-
-					// maintain phase when silent
-					blargg_long count = (end_time - time + period - 1) / period;
-					phase += count; // phase will be masked below
-					time += count * period;
-				}
-				this->phase = (phase - 1) & 0x1F; // undo pre-advance
-			}
-		}
-		time -= end_time;
-		if ( time < 0 )
-			time = 0;
-		delay = time;
-
-		this->dac = dac;
-		last_amp [0] = dac * volume_0;
-		last_amp [1] = dac * volume_1;
-	}
-	last_time = end_time;
-}
-
-void Hes_Apu::balance_changed( Hes_Osc& osc )
-{
-	static short const log_table [32] = { // ~1.5 db per step
-		#define ENTRY( factor ) short (factor * Hes_Osc::amp_range / 31.0 + 0.5)
-		ENTRY( 0.000000 ),ENTRY( 0.005524 ),ENTRY( 0.006570 ),ENTRY( 0.007813 ),
-		ENTRY( 0.009291 ),ENTRY( 0.011049 ),ENTRY( 0.013139 ),ENTRY( 0.015625 ),
-		ENTRY( 0.018581 ),ENTRY( 0.022097 ),ENTRY( 0.026278 ),ENTRY( 0.031250 ),
-		ENTRY( 0.037163 ),ENTRY( 0.044194 ),ENTRY( 0.052556 ),ENTRY( 0.062500 ),
-		ENTRY( 0.074325 ),ENTRY( 0.088388 ),ENTRY( 0.105112 ),ENTRY( 0.125000 ),
-		ENTRY( 0.148651 ),ENTRY( 0.176777 ),ENTRY( 0.210224 ),ENTRY( 0.250000 ),
-		ENTRY( 0.297302 ),ENTRY( 0.353553 ),ENTRY( 0.420448 ),ENTRY( 0.500000 ),
-		ENTRY( 0.594604 ),ENTRY( 0.707107 ),ENTRY( 0.840896 ),ENTRY( 1.000000 ),
-		#undef ENTRY
-	};
-
-	int vol = (osc.control & 0x1F) - 0x1E * 2;
-
-	int left  = vol + (osc.balance >> 3 & 0x1E) + (balance >> 3 & 0x1E);
-	if ( left  < 0 ) left  = 0;
-
-	int right = vol + (osc.balance << 1 & 0x1E) + (balance << 1 & 0x1E);
-	if ( right < 0 ) right = 0;
-
-	left  = log_table [left ];
-	right = log_table [right];
-
-	// optimizing for the common case of being centered also allows easy
-	// panning using Effects_Buffer
-	osc.outputs [0] = osc.chans [0]; // center
-	osc.outputs [1] = 0;
-	if ( left != right )
-	{
-		osc.outputs [0] = osc.chans [1]; // left
-		osc.outputs [1] = osc.chans [2]; // right
-	}
-
-	if ( center_waves )
-	{
-		osc.last_amp [0] += (left  - osc.volume [0]) * 16;
-		osc.last_amp [1] += (right - osc.volume [1]) * 16;
-	}
-
-	osc.volume [0] = left;
-	osc.volume [1] = right;
-}
-
-void Hes_Apu::write_data( blip_time_t time, int addr, int data )
-{
-	if ( addr == 0x800 )
-	{
-		latch = data & 7;
-	}
-	else if ( addr == 0x801 )
-	{
-		if ( balance != data )
-		{
-			balance = data;
-
-			Hes_Osc* osc = &oscs [osc_count];
-			do
-			{
-				osc--;
-				osc->run_until( synth, time );
-				balance_changed( *oscs );
-			}
-			while ( osc != oscs );
-		}
-	}
-	else if ( latch < osc_count )
-	{
-		Hes_Osc& osc = oscs [latch];
-		osc.run_until( synth, time );
-		switch ( addr )
-		{
-		case 0x802:
-			osc.period = (osc.period & 0xF00) | data;
-			break;
-
-		case 0x803:
-			osc.period = (osc.period & 0x0FF) | ((data & 0x0F) << 8);
-			break;
-
-		case 0x804:
-			if ( osc.control & 0x40 & ~data )
-				osc.phase = 0;
-			osc.control = data;
-			balance_changed( osc );
-			break;
-
-		case 0x805:
-			osc.balance = data;
-			balance_changed( osc );
-			break;
-
-		case 0x806:
-			data &= 0x1F;
-			if ( !(osc.control & 0x40) )
-			{
-				osc.wave [osc.phase] = data;
-				osc.phase = (osc.phase + 1) & 0x1F;
-			}
-			else if ( osc.control & 0x80 )
-			{
-				osc.dac = data;
-			}
-			break;
-
-		 case 0x807:
-		 	if ( &osc >= &oscs [4] )
-		 		osc.noise = data;
-		 	break;
-
-		 case 0x809:
-		 	if ( !(data & 0x80) && (data & 0x03) != 0 )
-		 		debug_printf( "HES LFO not supported\n" );
-		}
-	}
-}
-
-void Hes_Apu::end_frame( blip_time_t end_time )
-{
-	Hes_Osc* osc = &oscs [osc_count];
-	do
-	{
-		osc--;
-		if ( end_time > osc->last_time )
-			osc->run_until( synth, end_time );
-		assert( osc->last_time >= end_time );
-		osc->last_time -= end_time;
-	}
-	while ( osc != oscs );
-}
diff --git a/src/console/Hes_Cpu.cc b/src/console/Hes_Cpu.cc
new file mode 100644
index 000000000000..24ef7b36835f
--- /dev/null
+++ b/src/console/Hes_Cpu.cc
@@ -0,0 +1,1301 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Hes_Cpu.h"
+
+#include "blargg_endian.h"
+
+//#include "hes_cpu_log.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+// TODO: support T flag, including clearing it at appropriate times?
+
+// all zero-page should really use whatever is at page 1, but that would
+// reduce efficiency quite a bit
+int const ram_addr = 0x2000;
+
+#define FLUSH_TIME()    (void) (s.time = s_time)
+#define CACHE_TIME()    (void) (s_time = s.time)
+
+#include "hes_cpu_io.h"
+
+#include "blargg_source.h"
+
+#if BLARGG_NONPORTABLE
+	#define PAGE_OFFSET( addr ) (addr)
+#else
+	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
+#endif
+
+// status flags
+int const st_n = 0x80;
+int const st_v = 0x40;
+//int const st_t = 0x20;
+int const st_b = 0x10;
+int const st_d = 0x08;
+int const st_i = 0x04;
+int const st_z = 0x02;
+int const st_c = 0x01;
+
+void Hes_Cpu::reset()
+{
+	check( state == &state_ );
+	state = &state_;
+
+	state_.time = 0;
+	state_.base = 0;
+	irq_time_   = future_hes_time;
+	end_time_   = future_hes_time;
+
+	r.status = st_i;
+	r.sp     = 0;
+	r.pc     = 0;
+	r.a      = 0;
+	r.x      = 0;
+	r.y      = 0;
+}
+
+void Hes_Cpu::set_mmr( int reg, int bank )
+{
+	assert( (unsigned) reg <= page_count ); // allow page past end to be set
+	assert( (unsigned) bank < 0x100 );
+	mmr [reg] = bank;
+	uint8_t const* code = CPU_SET_MMR( this, reg, bank );
+	state->code_map [reg] = code - PAGE_OFFSET( reg << page_shift );
+}
+
+#define TIME    (s_time + s.base)
+
+#define READ( addr )            CPU_READ( this, (addr), TIME )
+#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), TIME );}
+#define READ_LOW( addr )        (ram [int (addr)])
+#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
+#define READ_PROG( addr )       (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
+
+#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
+#define GET_SP()        ((sp - 1) & 0xFF)
+#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
+
+// even on x86, using short and unsigned char was slower
+typedef int         fint16;
+typedef unsigned    fuint16;
+typedef unsigned    fuint8;
+typedef blargg_long fint32;
+
+bool Hes_Cpu::run( hes_time_t end_time )
+{
+	bool illegal_encountered = false;
+	set_end_time( end_time );
+	state_t s = this->state_;
+	this->state = &s;
+	// even on x86, using s.time in place of s_time was slower
+	fint16 s_time = s.time;
+
+	// registers
+	fuint16 pc = r.pc;
+	fuint8 a = r.a;
+	fuint8 x = r.x;
+	fuint8 y = r.y;
+	fuint16 sp;
+	SET_SP( r.sp );
+
+	#define IS_NEG (nz & 0x8080)
+
+	#define CALC_STATUS( out ) do {\
+		out = status & (st_v | st_d | st_i);\
+		out |= ((nz >> 8) | nz) & st_n;\
+		out |= c >> 8 & st_c;\
+		if ( !(nz & 0xFF) ) out |= st_z;\
+	} while ( 0 )
+
+	#define SET_STATUS( in ) do {\
+		status = in & (st_v | st_d | st_i);\
+		nz = in << 8;\
+		c = nz;\
+		nz |= ~in & st_z;\
+	} while ( 0 )
+
+	fuint8 status;
+	fuint16 c;  // carry set if (c & 0x100) != 0
+	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
+	{
+		fuint8 temp = r.status;
+		SET_STATUS( temp );
+	}
+
+	goto loop;
+branch_not_taken:
+	s_time -= 2;
+loop:
+
+	#ifndef NDEBUG
+	{
+		hes_time_t correct = end_time_;
+		if ( !(status & st_i) && correct > irq_time_ )
+			correct = irq_time_;
+		check( s.base == correct );
+		/*
+		static long count;
+		if ( count == 1844 ) Debugger();
+		if ( s.base != correct ) debug_printf( "%ld\n", count );
+		count++;
+		*/
+	}
+	#endif
+
+	check( (unsigned) GET_SP() < 0x100 );
+	check( (unsigned) a < 0x100 );
+	check( (unsigned) x < 0x100 );
+
+	uint8_t const* instr = s.code_map [pc >> page_shift];
+	fuint8 opcode;
+
+	// TODO: eliminate this special case
+	#if BLARGG_NONPORTABLE
+		opcode = instr [pc];
+		pc++;
+		instr += pc;
+	#else
+		instr += PAGE_OFFSET( pc );
+		opcode = *instr++;
+		pc++;
+	#endif
+
+	// TODO: each reference lists slightly different timing values, ugh
+	static uint8_t const clock_table [256] =
+	{// 0 1 2  3 4 5 6 7 8 9 A B C D E F
+		1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,6,// 0
+		4,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,6,// 1
+		7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,6,// 2
+		4,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,6,// 3
+		7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,6,// 4
+		4,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,6,// 5
+		7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,6,// 6
+		4,7,7,17,4,4,6,7,2,5,4,2,7,5,7,6,// 7
+		4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// 8
+		4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// 9
+		2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// A
+		4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// B
+		2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// C
+		4,7,7,17,2,4,6,7,2,5,3,2,2,5,7,6,// D
+		2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// E
+		4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
+	}; // 0x00 was 8
+
+	fuint16 data;
+	data = clock_table [opcode];
+	if ( (s_time += data) >= 0 )
+		goto possibly_out_of_time;
+almost_out_of_time:
+
+	data = *instr;
+
+	#ifdef HES_CPU_LOG_H
+		log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
+				instr [3], instr [4], instr [5] );
+		//log_opcode( opcode );
+	#endif
+
+	switch ( opcode )
+	{
+possibly_out_of_time:
+		if ( s_time < (int) data )
+			goto almost_out_of_time;
+		s_time -= data;
+		goto out_of_time;
+
+// Macros
+
+#define GET_MSB()           (instr [1])
+#define ADD_PAGE( out )     (pc++, out = data + 0x100 * GET_MSB());
+#define GET_ADDR()          GET_LE16( instr )
+
+// TODO: is the penalty really always added? the original 6502 was much better
+//#define PAGE_CROSS_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
+#define PAGE_CROSS_PENALTY( lsb )
+
+// Branch
+
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define BRANCH( cond )\
+{\
+	fint16 offset = (int8_t) data;\
+	pc++;\
+	if ( !(cond) ) goto branch_not_taken;\
+	pc = uint16_t (pc + offset);\
+	goto loop;\
+}
+
+	case 0xF0: // BEQ
+		BRANCH( !((uint8_t) nz) );
+
+	case 0xD0: // BNE
+		BRANCH( (uint8_t) nz );
+
+	case 0x10: // BPL
+		BRANCH( !IS_NEG );
+
+	case 0x90: // BCC
+		BRANCH( !(c & 0x100) )
+
+	case 0x30: // BMI
+		BRANCH( IS_NEG )
+
+	case 0x50: // BVC
+		BRANCH( !(status & st_v) )
+
+	case 0x70: // BVS
+		BRANCH( status & st_v )
+
+	case 0xB0: // BCS
+		BRANCH( c & 0x100 )
+
+	case 0x80: // BRA
+	branch_taken:
+		BRANCH( true );
+
+	case 0xFF:
+		if ( pc == idle_addr + 1 )
+			goto idle_done;
+	case 0x0F: // BBRn
+	case 0x1F:
+	case 0x2F:
+	case 0x3F:
+	case 0x4F:
+	case 0x5F:
+	case 0x6F:
+	case 0x7F:
+	case 0x8F: // BBSn
+	case 0x9F:
+	case 0xAF:
+	case 0xBF:
+	case 0xCF:
+	case 0xDF:
+	case 0xEF: {
+		fuint16 t = 0x101 * READ_LOW( data );
+		t ^= 0xFF;
+		pc++;
+		data = GET_MSB();
+		BRANCH( t & (1 << (opcode >> 4)) )
+	}
+
+	case 0x4C: // JMP abs
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0x7C: // JMP (ind+X)
+		data += x;
+	case 0x6C:{// JMP (ind)
+		data += 0x100 * GET_MSB();
+		pc = GET_LE16( &READ_PROG( data ) );
+		goto loop;
+	}
+
+// Subroutine
+
+	case 0x44: // BSR
+		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
+		sp = (sp - 2) | 0x100;
+		WRITE_LOW( sp, pc );
+		goto branch_taken;
+
+	case 0x20: { // JSR
+		fuint16 temp = pc + 1;
+		pc = GET_ADDR();
+		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
+		sp = (sp - 2) | 0x100;
+		WRITE_LOW( sp, temp );
+		goto loop;
+	}
+
+	case 0x60: // RTS
+		pc = 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
+		pc += 1 + READ_LOW( sp );
+		sp = (sp - 0xFE) | 0x100;
+		goto loop;
+
+	case 0x00: // BRK
+		goto handle_brk;
+
+// Common
+
+	case 0xBD:{// LDA abs,X
+		PAGE_CROSS_PENALTY( data + x );
+		fuint16 addr = GET_ADDR() + x;
+		pc += 2;
+		CPU_READ_FAST( this, addr, TIME, nz );
+		a = nz;
+		goto loop;
+	}
+
+	case 0x9D:{// STA abs,X
+		fuint16 addr = GET_ADDR() + x;
+		pc += 2;
+		CPU_WRITE_FAST( this, addr, a, TIME );
+		goto loop;
+	}
+
+	case 0x95: // STA zp,x
+		data = uint8_t (data + x);
+	case 0x85: // STA zp
+		pc++;
+		WRITE_LOW( data, a );
+		goto loop;
+
+	case 0xAE:{// LDX abs
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		CPU_READ_FAST( this, addr, TIME, nz );
+		x = nz;
+		goto loop;
+	}
+
+	case 0xA5: // LDA zp
+		a = nz = READ_LOW( data );
+		pc++;
+		goto loop;
+
+// Load/store
+
+	{
+		fuint16 addr;
+	case 0x91: // STA (ind),Y
+		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
+		addr += READ_LOW( data ) + y;
+		pc++;
+		goto sta_ptr;
+
+	case 0x81: // STA (ind,X)
+		data = uint8_t (data + x);
+	case 0x92: // STA (ind)
+		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
+		addr += READ_LOW( data );
+		pc++;
+		goto sta_ptr;
+
+	case 0x99: // STA abs,Y
+		data += y;
+	case 0x8D: // STA abs
+		addr = data + 0x100 * GET_MSB();
+		pc += 2;
+	sta_ptr:
+		CPU_WRITE_FAST( this, addr, a, TIME );
+		goto loop;
+	}
+
+	{
+		fuint16 addr;
+	case 0xA1: // LDA (ind,X)
+		data = uint8_t (data + x);
+	case 0xB2: // LDA (ind)
+		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
+		addr += READ_LOW( data );
+		pc++;
+		goto a_nz_read_addr;
+
+	case 0xB1:// LDA (ind),Y
+		addr = READ_LOW( data ) + y;
+		PAGE_CROSS_PENALTY( addr );
+		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
+		pc++;
+		goto a_nz_read_addr;
+
+	case 0xB9: // LDA abs,Y
+		data += y;
+		PAGE_CROSS_PENALTY( data );
+	case 0xAD: // LDA abs
+		addr = data + 0x100 * GET_MSB();
+		pc += 2;
+	a_nz_read_addr:
+		CPU_READ_FAST( this, addr, TIME, nz );
+		a = nz;
+		goto loop;
+	}
+
+	case 0xBE:{// LDX abs,y
+		PAGE_CROSS_PENALTY( data + y );
+		fuint16 addr = GET_ADDR() + y;
+		pc += 2;
+		FLUSH_TIME();
+		x = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	case 0xB5: // LDA zp,x
+		a = nz = READ_LOW( uint8_t (data + x) );
+		pc++;
+		goto loop;
+
+	case 0xA9: // LDA #imm
+		pc++;
+		a  = data;
+		nz = data;
+		goto loop;
+
+// Bit operations
+
+	case 0x3C: // BIT abs,x
+		data += x;
+	case 0x2C:{// BIT abs
+		fuint16 addr;
+		ADD_PAGE( addr );
+		FLUSH_TIME();
+		nz = READ( addr );
+		CACHE_TIME();
+		goto bit_common;
+	}
+	case 0x34: // BIT zp,x
+		data = uint8_t (data + x);
+	case 0x24: // BIT zp
+		data = READ_LOW( data );
+	case 0x89: // BIT imm
+		nz = data;
+	bit_common:
+		pc++;
+		status &= ~st_v;
+		status |= nz & st_v;
+		if ( nz & a )
+			goto loop; // Z should be clear, and nz must be non-zero if nz & a is
+		nz <<= 8; // set Z flag without affecting N flag
+		goto loop;
+
+	{
+		fuint16 addr;
+
+	case 0xB3: // TST abs,x
+		addr = GET_MSB() + x;
+		goto tst_abs;
+
+	case 0x93: // TST abs
+		addr = GET_MSB();
+	tst_abs:
+		addr += 0x100 * instr [2];
+		pc++;
+		FLUSH_TIME();
+		nz = READ( addr );
+		CACHE_TIME();
+		goto tst_common;
+	}
+
+	case 0xA3: // TST zp,x
+		nz = READ_LOW( uint8_t (GET_MSB() + x) );
+		goto tst_common;
+
+	case 0x83: // TST zp
+		nz = READ_LOW( GET_MSB() );
+	tst_common:
+		pc += 2;
+		status &= ~st_v;
+		status |= nz & st_v;
+		if ( nz & data )
+			goto loop; // Z should be clear, and nz must be non-zero if nz & data is
+		nz <<= 8; // set Z flag without affecting N flag
+		goto loop;
+
+	{
+		fuint16 addr;
+	case 0x0C: // TSB abs
+	case 0x1C: // TRB abs
+		addr = GET_ADDR();
+		pc++;
+		goto txb_addr;
+
+	// TODO: everyone lists different behaviors for the status flags, ugh
+	case 0x04: // TSB zp
+	case 0x14: // TRB zp
+		addr = data + ram_addr;
+	txb_addr:
+		FLUSH_TIME();
+		nz = a | READ( addr );
+		if ( opcode & 0x10 )
+			nz ^= a; // bits from a will already be set, so this clears them
+		status &= ~st_v;
+		status |= nz & st_v;
+		pc++;
+		WRITE( addr, nz );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	case 0x07: // RMBn
+	case 0x17:
+	case 0x27:
+	case 0x37:
+	case 0x47:
+	case 0x57:
+	case 0x67:
+	case 0x77:
+		pc++;
+		READ_LOW( data ) &= ~(1 << (opcode >> 4));
+		goto loop;
+
+	case 0x87: // SMBn
+	case 0x97:
+	case 0xA7:
+	case 0xB7:
+	case 0xC7:
+	case 0xD7:
+	case 0xE7:
+	case 0xF7:
+		pc++;
+		READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
+		goto loop;
+
+// Load/store
+
+	case 0x9E: // STZ abs,x
+		data += x;
+	case 0x9C: // STZ abs
+		ADD_PAGE( data );
+		pc++;
+		FLUSH_TIME();
+		WRITE( data, 0 );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x74: // STZ zp,x
+		data = uint8_t (data + x);
+	case 0x64: // STZ zp
+		pc++;
+		WRITE_LOW( data, 0 );
+		goto loop;
+
+	case 0x94: // STY zp,x
+		data = uint8_t (data + x);
+	case 0x84: // STY zp
+		pc++;
+		WRITE_LOW( data, y );
+		goto loop;
+
+	case 0x96: // STX zp,y
+		data = uint8_t (data + y);
+	case 0x86: // STX zp
+		pc++;
+		WRITE_LOW( data, x );
+		goto loop;
+
+	case 0xB6: // LDX zp,y
+		data = uint8_t (data + y);
+	case 0xA6: // LDX zp
+		data = READ_LOW( data );
+	case 0xA2: // LDX #imm
+		pc++;
+		x = data;
+		nz = data;
+		goto loop;
+
+	case 0xB4: // LDY zp,x
+		data = uint8_t (data + x);
+	case 0xA4: // LDY zp
+		data = READ_LOW( data );
+	case 0xA0: // LDY #imm
+		pc++;
+		y = data;
+		nz = data;
+		goto loop;
+
+	case 0xBC: // LDY abs,X
+		data += x;
+		PAGE_CROSS_PENALTY( data );
+	case 0xAC:{// LDY abs
+		fuint16 addr = data + 0x100 * GET_MSB();
+		pc += 2;
+		FLUSH_TIME();
+		y = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	{
+		fuint8 temp;
+	case 0x8C: // STY abs
+		temp = y;
+		goto store_abs;
+
+	case 0x8E: // STX abs
+		temp = x;
+	store_abs:
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		FLUSH_TIME();
+		WRITE( addr, temp );
+		CACHE_TIME();
+		goto loop;
+	}
+
+// Compare
+
+	case 0xEC:{// CPX abs
+		fuint16 addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpx_data;
+	}
+
+	case 0xE4: // CPX zp
+		data = READ_LOW( data );
+	case 0xE0: // CPX #imm
+	cpx_data:
+		nz = x - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	case 0xCC:{// CPY abs
+		fuint16 addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpy_data;
+	}
+
+	case 0xC4: // CPY zp
+		data = READ_LOW( data );
+	case 0xC0: // CPY #imm
+	cpy_data:
+		nz = y - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+// Logical
+
+#define ARITH_ADDR_MODES( op )\
+	case op - 0x04: /* (ind,x) */\
+		data = uint8_t (data + x);\
+	case op + 0x0D: /* (ind) */\
+		data = 0x100 * READ_LOW( uint8_t (data + 1) ) + READ_LOW( data );\
+		goto ptr##op;\
+	case op + 0x0C:{/* (ind),y */\
+		fuint16 temp = READ_LOW( data ) + y;\
+		PAGE_CROSS_PENALTY( temp );\
+		data = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
+		goto ptr##op;\
+	}\
+	case op + 0x10: /* zp,X */\
+		data = uint8_t (data + x);\
+	case op + 0x00: /* zp */\
+		data = READ_LOW( data );\
+		goto imm##op;\
+	case op + 0x14: /* abs,Y */\
+		data += y;\
+		goto ind##op;\
+	case op + 0x18: /* abs,X */\
+		data += x;\
+	ind##op:\
+		PAGE_CROSS_PENALTY( data );\
+	case op + 0x08: /* abs */\
+		ADD_PAGE( data );\
+	ptr##op:\
+		FLUSH_TIME();\
+		data = READ( data );\
+		CACHE_TIME();\
+	case op + 0x04: /* imm */\
+	imm##op:
+
+	ARITH_ADDR_MODES( 0xC5 ) // CMP
+		nz = a - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x25 ) // AND
+		nz = (a &= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x45 ) // EOR
+		nz = (a ^= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x05 ) // ORA
+		nz = (a |= data);
+		pc++;
+		goto loop;
+
+// Add/subtract
+
+	ARITH_ADDR_MODES( 0xE5 ) // SBC
+		data ^= 0xFF;
+		goto adc_imm;
+
+	ARITH_ADDR_MODES( 0x65 ) // ADC
+	adc_imm: {
+		if ( status & st_d )
+			debug_printf( "Decimal mode not supported\n" );
+		fint16 carry = c >> 8 & 1;
+		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
+		status &= ~st_v;
+		status |= ov >> 2 & 0x40;
+		c = nz = a + data + carry;
+		pc++;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+// Shift/rotate
+
+	case 0x4A: // LSR A
+		c = 0;
+	case 0x6A: // ROR A
+		nz = c >> 1 & 0x80;
+		c = a << 8;
+		nz |= a >> 1;
+		a = nz;
+		goto loop;
+
+	case 0x0A: // ASL A
+		nz = a << 1;
+		c = nz;
+		a = (uint8_t) nz;
+		goto loop;
+
+	case 0x2A: { // ROL A
+		nz = a << 1;
+		fint16 temp = c >> 8 & 1;
+		c = nz;
+		nz |= temp;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+	case 0x5E: // LSR abs,X
+		data += x;
+	case 0x4E: // LSR abs
+		c = 0;
+	case 0x6E: // ROR abs
+	ror_abs: {
+		ADD_PAGE( data );
+		FLUSH_TIME();
+		int temp = READ( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto rotate_common;
+	}
+
+	case 0x3E: // ROL abs,X
+		data += x;
+		goto rol_abs;
+
+	case 0x1E: // ASL abs,X
+		data += x;
+	case 0x0E: // ASL abs
+		c = 0;
+	case 0x2E: // ROL abs
+	rol_abs:
+		ADD_PAGE( data );
+		nz = c >> 8 & 1;
+		FLUSH_TIME();
+		nz |= (c = READ( data ) << 1);
+	rotate_common:
+		pc++;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x7E: // ROR abs,X
+		data += x;
+		goto ror_abs;
+
+	case 0x76: // ROR zp,x
+		data = uint8_t (data + x);
+		goto ror_zp;
+
+	case 0x56: // LSR zp,x
+		data = uint8_t (data + x);
+	case 0x46: // LSR zp
+		c = 0;
+	case 0x66: // ROR zp
+	ror_zp: {
+		int temp = READ_LOW( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto write_nz_zp;
+	}
+
+	case 0x36: // ROL zp,x
+		data = uint8_t (data + x);
+		goto rol_zp;
+
+	case 0x16: // ASL zp,x
+		data = uint8_t (data + x);
+	case 0x06: // ASL zp
+		c = 0;
+	case 0x26: // ROL zp
+	rol_zp:
+		nz = c >> 8 & 1;
+		nz |= (c = READ_LOW( data ) << 1);
+		goto write_nz_zp;
+
+// Increment/decrement
+
+#define INC_DEC_AXY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
+
+	case 0x1A: // INA
+		INC_DEC_AXY( a, +1 )
+
+	case 0xE8: // INX
+		INC_DEC_AXY( x, +1 )
+
+	case 0xC8: // INY
+		INC_DEC_AXY( y, +1 )
+
+	case 0x3A: // DEA
+		INC_DEC_AXY( a, -1 )
+
+	case 0xCA: // DEX
+		INC_DEC_AXY( x, -1 )
+
+	case 0x88: // DEY
+		INC_DEC_AXY( y, -1 )
+
+	case 0xF6: // INC zp,x
+		data = uint8_t (data + x);
+	case 0xE6: // INC zp
+		nz = 1;
+		goto add_nz_zp;
+
+	case 0xD6: // DEC zp,x
+		data = uint8_t (data + x);
+	case 0xC6: // DEC zp
+		nz = (unsigned) -1;
+	add_nz_zp:
+		nz += READ_LOW( data );
+	write_nz_zp:
+		pc++;
+		WRITE_LOW( data, nz );
+		goto loop;
+
+	case 0xFE: // INC abs,x
+		data = x + GET_ADDR();
+		goto inc_ptr;
+
+	case 0xEE: // INC abs
+		data = GET_ADDR();
+	inc_ptr:
+		nz = 1;
+		goto inc_common;
+
+	case 0xDE: // DEC abs,x
+		data = x + GET_ADDR();
+		goto dec_ptr;
+
+	case 0xCE: // DEC abs
+		data = GET_ADDR();
+	dec_ptr:
+		nz = (unsigned) -1;
+	inc_common:
+		FLUSH_TIME();
+		nz += READ( data );
+		pc += 2;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+// Transfer
+
+	case 0xA8: // TAY
+		y  = a;
+		nz = a;
+		goto loop;
+
+	case 0x98: // TYA
+		a  = y;
+		nz = y;
+		goto loop;
+
+	case 0xAA: // TAX
+		x  = a;
+		nz = a;
+		goto loop;
+
+	case 0x8A: // TXA
+		a  = x;
+		nz = x;
+		goto loop;
+
+	case 0x9A: // TXS
+		SET_SP( x ); // verified (no flag change)
+		goto loop;
+
+	case 0xBA: // TSX
+		x = nz = GET_SP();
+		goto loop;
+
+	#define SWAP_REGS( r1, r2 ) {\
+		fuint8 t = r1;\
+		r1 = r2;\
+		r2 = t;\
+		goto loop;\
+	}
+
+	case 0x02: // SXY
+		SWAP_REGS( x, y );
+
+	case 0x22: // SAX
+		SWAP_REGS( a, x );
+
+	case 0x42: // SAY
+		SWAP_REGS( a, y );
+
+	case 0x62: // CLA
+		a = 0;
+		goto loop;
+
+	case 0x82: // CLX
+		x = 0;
+		goto loop;
+
+	case 0xC2: // CLY
+		y = 0;
+		goto loop;
+
+// Stack
+
+	case 0x48: // PHA
+		PUSH( a );
+		goto loop;
+
+	case 0xDA: // PHX
+		PUSH( x );
+		goto loop;
+
+	case 0x5A: // PHY
+		PUSH( y );
+		goto loop;
+
+	case 0x40:{// RTI
+		fuint8 temp = READ_LOW( sp );
+		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
+		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
+		sp = (sp - 0xFD) | 0x100;
+		data = status;
+		SET_STATUS( temp );
+		this->r.status = status; // update externally-visible I flag
+		if ( (data ^ status) & st_i )
+		{
+			hes_time_t new_time = end_time_;
+			if ( !(status & st_i) && new_time > irq_time_ )
+				new_time = irq_time_;
+			blargg_long delta = s.base - new_time;
+			s.base = new_time;
+			s_time += delta;
+		}
+		goto loop;
+	}
+
+	#define POP()  READ_LOW( sp ); sp = (sp - 0xFF) | 0x100
+
+	case 0x68: // PLA
+		a = nz = POP();
+		goto loop;
+
+	case 0xFA: // PLX
+		x = nz = POP();
+		goto loop;
+
+	case 0x7A: // PLY
+		y = nz = POP();
+		goto loop;
+
+	case 0x28:{// PLP
+		fuint8 temp = POP();
+		fuint8 changed = status ^ temp;
+		SET_STATUS( temp );
+		if ( !(changed & st_i) )
+			goto loop; // I flag didn't change
+		if ( status & st_i )
+			goto handle_sei;
+		goto handle_cli;
+	}
+	#undef POP
+
+	case 0x08: { // PHP
+		fuint8 temp;
+		CALC_STATUS( temp );
+		PUSH( temp | st_b );
+		goto loop;
+	}
+
+// Flags
+
+	case 0x38: // SEC
+		c = (unsigned) ~0;
+		goto loop;
+
+	case 0x18: // CLC
+		c = 0;
+		goto loop;
+
+	case 0xB8: // CLV
+		status &= ~st_v;
+		goto loop;
+
+	case 0xD8: // CLD
+		status &= ~st_d;
+		goto loop;
+
+	case 0xF8: // SED
+		status |= st_d;
+		goto loop;
+
+	case 0x58: // CLI
+		if ( !(status & st_i) )
+			goto loop;
+		status &= ~st_i;
+	handle_cli: {
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - irq_time_;
+		if ( delta <= 0 )
+		{
+			if ( TIME < irq_time_ )
+				goto loop;
+			goto delayed_cli;
+		}
+		s.base = irq_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+
+		if ( delta >= s_time + 1 )
+		{
+			// delayed irq until after next instruction
+			s.base += s_time + 1;
+			s_time = -1;
+			irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
+			goto loop;
+		}
+	delayed_cli:
+		debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
+		goto loop;
+	}
+
+	case 0x78: // SEI
+		if ( status & st_i )
+			goto loop;
+		status |= st_i;
+	handle_sei: {
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - end_time_;
+		s.base = end_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+		debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
+		goto loop;
+	}
+
+// Special
+
+	case 0x53:{// TAM
+		fuint8 const bits = data; // avoid using data across function call
+		pc++;
+		for ( int i = 0; i < 8; i++ )
+			if ( bits & (1 << i) )
+				set_mmr( i, a );
+		goto loop;
+	}
+
+	case 0x43:{// TMA
+		pc++;
+		byte const* in = mmr;
+		do
+		{
+			if ( data & 1 )
+				a = *in;
+			in++;
+		}
+		while ( (data >>= 1) != 0 );
+		goto loop;
+	}
+
+	case 0x03: // ST0
+	case 0x13: // ST1
+	case 0x23:{// ST2
+		fuint16 addr = opcode >> 4;
+		if ( addr )
+			addr++;
+		pc++;
+		FLUSH_TIME();
+		CPU_WRITE_VDP( this, addr, data, TIME );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	case 0xEA: // NOP
+		goto loop;
+
+	case 0x54: // CSL
+		debug_printf( "CSL not supported\n" );
+		illegal_encountered = true;
+		goto loop;
+
+	case 0xD4: // CSH
+		goto loop;
+
+	case 0xF4: { // SET
+		//fuint16 operand = GET_MSB();
+		debug_printf( "SET not handled\n" );
+		//switch ( data )
+		//{
+		//}
+		illegal_encountered = true;
+		goto loop;
+	}
+
+// Block transfer
+
+	{
+		fuint16 in_alt;
+		fint16 in_inc;
+		fuint16 out_alt;
+		fint16 out_inc;
+
+	case 0xE3: // TIA
+		in_alt  = 0;
+		goto bxfer_alt;
+
+	case 0xF3: // TAI
+		in_alt  = 1;
+	bxfer_alt:
+		in_inc  = in_alt ^ 1;
+		out_alt = in_inc;
+		out_inc = in_alt;
+		goto bxfer;
+
+	case 0xD3: // TIN
+		in_inc  = 1;
+		out_inc = 0;
+		goto bxfer_no_alt;
+
+	case 0xC3: // TDD
+		in_inc  = -1;
+		out_inc = -1;
+		goto bxfer_no_alt;
+
+	case 0x73: // TII
+		in_inc  = 1;
+		out_inc = 1;
+	bxfer_no_alt:
+		in_alt  = 0;
+		out_alt = 0;
+	bxfer:
+		fuint16 in    = GET_LE16( instr + 0 );
+		fuint16 out   = GET_LE16( instr + 2 );
+		int     count = GET_LE16( instr + 4 );
+		if ( !count )
+			count = 0x10000;
+		pc += 6;
+		WRITE_LOW( 0x100 | (sp - 1), y );
+		WRITE_LOW( 0x100 | (sp - 2), a );
+		WRITE_LOW( 0x100 | (sp - 3), x );
+		FLUSH_TIME();
+		do
+		{
+			// TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
+			fuint8 t = READ( in );
+			in += in_inc;
+			in &= 0xFFFF;
+			s.time += 6;
+			if ( in_alt )
+				in_inc = -in_inc;
+			WRITE( out, t );
+			out += out_inc;
+			out &= 0xFFFF;
+			if ( out_alt )
+				out_inc = -out_inc;
+		}
+		while ( --count );
+		CACHE_TIME();
+		goto loop;
+	}
+
+// Illegal
+
+	default:
+		assert( (unsigned) opcode <= 0xFF );
+		debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
+		illegal_encountered = true;
+		goto loop;
+	}
+	assert( false );
+
+	int result_;
+handle_brk:
+	pc++;
+	result_ = 6;
+
+interrupt:
+	{
+		s_time += 7;
+
+		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
+		WRITE_LOW( 0x100 | (sp - 2), pc );
+		pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
+
+		sp = (sp - 3) | 0x100;
+		fuint8 temp;
+		CALC_STATUS( temp );
+		if ( result_ == 6 )
+			temp |= st_b;
+		WRITE_LOW( sp, temp );
+
+		status &= ~st_d;
+		status |= st_i;
+		this->r.status = status; // update externally-visible I flag
+
+		blargg_long delta = s.base - end_time_;
+		s.base = end_time_;
+		s_time += delta;
+		goto loop;
+	}
+
+idle_done:
+	s_time = 0;
+out_of_time:
+	pc--;
+	FLUSH_TIME();
+	CPU_DONE( this, TIME, result_ );
+	CACHE_TIME();
+	if ( result_ > 0 )
+		goto interrupt;
+	if ( s_time < 0 )
+		goto loop;
+
+	s.time = s_time;
+
+	r.pc = pc;
+	r.sp = GET_SP();
+	r.a = a;
+	r.x = x;
+	r.y = y;
+
+	{
+		fuint8 temp;
+		CALC_STATUS( temp );
+		r.status = temp;
+	}
+
+	this->state_ = s;
+	this->state = &this->state_;
+
+	return illegal_encountered;
+}
+
diff --git a/src/console/Hes_Cpu.cxx b/src/console/Hes_Cpu.cxx
deleted file mode 100644
index bc0965ccfae8..000000000000
--- a/src/console/Hes_Cpu.cxx
+++ /dev/null
@@ -1,1301 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Cpu.h"
-
-#include "blargg_endian.h"
-
-//#include "hes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// TODO: support T flag, including clearing it at appropriate times?
-
-// all zero-page should really use whatever is at page 1, but that would
-// reduce efficiency quite a bit
-int const ram_addr = 0x2000;
-
-#define FLUSH_TIME()    (void) (s.time = s_time)
-#define CACHE_TIME()    (void) (s_time = s.time)
-
-#include "hes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#if BLARGG_NONPORTABLE
-	#define PAGE_OFFSET( addr ) (addr)
-#else
-	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-// status flags
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_t = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Hes_Cpu::reset()
-{
-	check( state == &state_ );
-	state = &state_;
-
-	state_.time = 0;
-	state_.base = 0;
-	irq_time_   = future_hes_time;
-	end_time_   = future_hes_time;
-
-	r.status = st_i;
-	r.sp     = 0;
-	r.pc     = 0;
-	r.a      = 0;
-	r.x      = 0;
-	r.y      = 0;
-}
-
-void Hes_Cpu::set_mmr( int reg, int bank )
-{
-	assert( (unsigned) reg <= page_count ); // allow page past end to be set
-	assert( (unsigned) bank < 0x100 );
-	mmr [reg] = bank;
-	uint8_t const* code = CPU_SET_MMR( this, reg, bank );
-	state->code_map [reg] = code - PAGE_OFFSET( reg << page_shift );
-}
-
-#define TIME    (s_time + s.base)
-
-#define READ( addr )            CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr )        (ram [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr )       (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
-#define GET_SP()        ((sp - 1) & 0xFF)
-#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int         fint16;
-typedef unsigned    fuint16;
-typedef unsigned    fuint8;
-typedef blargg_long fint32;
-
-bool Hes_Cpu::run( hes_time_t end_time )
-{
-	bool illegal_encountered = false;
-	set_end_time( end_time );
-	state_t s = this->state_;
-	this->state = &s;
-	// even on x86, using s.time in place of s_time was slower
-	fint16 s_time = s.time;
-
-	// registers
-	fuint16 pc = r.pc;
-	fuint8 a = r.a;
-	fuint8 x = r.x;
-	fuint8 y = r.y;
-	fuint16 sp;
-	SET_SP( r.sp );
-
-	#define IS_NEG (nz & 0x8080)
-
-	#define CALC_STATUS( out ) do {\
-		out = status & (st_v | st_d | st_i);\
-		out |= ((nz >> 8) | nz) & st_n;\
-		out |= c >> 8 & st_c;\
-		if ( !(nz & 0xFF) ) out |= st_z;\
-	} while ( 0 )
-
-	#define SET_STATUS( in ) do {\
-		status = in & (st_v | st_d | st_i);\
-		nz = in << 8;\
-		c = nz;\
-		nz |= ~in & st_z;\
-	} while ( 0 )
-
-	fuint8 status;
-	fuint16 c;  // carry set if (c & 0x100) != 0
-	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
-	{
-		fuint8 temp = r.status;
-		SET_STATUS( temp );
-	}
-
-	goto loop;
-branch_not_taken:
-	s_time -= 2;
-loop:
-
-	#ifndef NDEBUG
-	{
-		hes_time_t correct = end_time_;
-		if ( !(status & st_i) && correct > irq_time_ )
-			correct = irq_time_;
-		check( s.base == correct );
-		/*
-		static long count;
-		if ( count == 1844 ) Debugger();
-		if ( s.base != correct ) debug_printf( "%ld\n", count );
-		count++;
-		*/
-	}
-	#endif
-
-	check( (unsigned) GET_SP() < 0x100 );
-	check( (unsigned) a < 0x100 );
-	check( (unsigned) x < 0x100 );
-
-	uint8_t const* instr = s.code_map [pc >> page_shift];
-	fuint8 opcode;
-
-	// TODO: eliminate this special case
-	#if BLARGG_NONPORTABLE
-		opcode = instr [pc];
-		pc++;
-		instr += pc;
-	#else
-		instr += PAGE_OFFSET( pc );
-		opcode = *instr++;
-		pc++;
-	#endif
-
-	// TODO: each reference lists slightly different timing values, ugh
-	static uint8_t const clock_table [256] =
-	{// 0 1 2  3 4 5 6 7 8 9 A B C D E F
-		1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,6,// 0
-		4,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,6,// 1
-		7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,6,// 2
-		4,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,6,// 3
-		7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,6,// 4
-		4,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,6,// 5
-		7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,6,// 6
-		4,7,7,17,4,4,6,7,2,5,4,2,7,5,7,6,// 7
-		4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// 8
-		4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// 9
-		2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// A
-		4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// B
-		2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// C
-		4,7,7,17,2,4,6,7,2,5,3,2,2,5,7,6,// D
-		2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// E
-		4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
-	}; // 0x00 was 8
-
-	fuint16 data;
-	data = clock_table [opcode];
-	if ( (s_time += data) >= 0 )
-		goto possibly_out_of_time;
-almost_out_of_time:
-
-	data = *instr;
-
-	#ifdef HES_CPU_LOG_H
-		log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
-				instr [3], instr [4], instr [5] );
-		//log_opcode( opcode );
-	#endif
-
-	switch ( opcode )
-	{
-possibly_out_of_time:
-		if ( s_time < (int) data )
-			goto almost_out_of_time;
-		s_time -= data;
-		goto out_of_time;
-
-// Macros
-
-#define GET_MSB()           (instr [1])
-#define ADD_PAGE( out )     (pc++, out = data + 0x100 * GET_MSB());
-#define GET_ADDR()          GET_LE16( instr )
-
-// TODO: is the penalty really always added? the original 6502 was much better
-//#define PAGE_CROSS_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
-#define PAGE_CROSS_PENALTY( lsb )
-
-// Branch
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
-	fint16 offset = (int8_t) data;\
-	pc++;\
-	if ( !(cond) ) goto branch_not_taken;\
-	pc = uint16_t (pc + offset);\
-	goto loop;\
-}
-
-	case 0xF0: // BEQ
-		BRANCH( !((uint8_t) nz) );
-
-	case 0xD0: // BNE
-		BRANCH( (uint8_t) nz );
-
-	case 0x10: // BPL
-		BRANCH( !IS_NEG );
-
-	case 0x90: // BCC
-		BRANCH( !(c & 0x100) )
-
-	case 0x30: // BMI
-		BRANCH( IS_NEG )
-
-	case 0x50: // BVC
-		BRANCH( !(status & st_v) )
-
-	case 0x70: // BVS
-		BRANCH( status & st_v )
-
-	case 0xB0: // BCS
-		BRANCH( c & 0x100 )
-
-	case 0x80: // BRA
-	branch_taken:
-		BRANCH( true );
-
-	case 0xFF:
-		if ( pc == idle_addr + 1 )
-			goto idle_done;
-	case 0x0F: // BBRn
-	case 0x1F:
-	case 0x2F:
-	case 0x3F:
-	case 0x4F:
-	case 0x5F:
-	case 0x6F:
-	case 0x7F:
-	case 0x8F: // BBSn
-	case 0x9F:
-	case 0xAF:
-	case 0xBF:
-	case 0xCF:
-	case 0xDF:
-	case 0xEF: {
-		fuint16 t = 0x101 * READ_LOW( data );
-		t ^= 0xFF;
-		pc++;
-		data = GET_MSB();
-		BRANCH( t & (1 << (opcode >> 4)) )
-	}
-
-	case 0x4C: // JMP abs
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0x7C: // JMP (ind+X)
-		data += x;
-	case 0x6C:{// JMP (ind)
-		data += 0x100 * GET_MSB();
-		pc = GET_LE16( &READ_PROG( data ) );
-		goto loop;
-	}
-
-// Subroutine
-
-	case 0x44: // BSR
-		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
-		sp = (sp - 2) | 0x100;
-		WRITE_LOW( sp, pc );
-		goto branch_taken;
-
-	case 0x20: { // JSR
-		fuint16 temp = pc + 1;
-		pc = GET_ADDR();
-		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
-		sp = (sp - 2) | 0x100;
-		WRITE_LOW( sp, temp );
-		goto loop;
-	}
-
-	case 0x60: // RTS
-		pc = 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
-		pc += 1 + READ_LOW( sp );
-		sp = (sp - 0xFE) | 0x100;
-		goto loop;
-
-	case 0x00: // BRK
-		goto handle_brk;
-
-// Common
-
-	case 0xBD:{// LDA abs,X
-		PAGE_CROSS_PENALTY( data + x );
-		fuint16 addr = GET_ADDR() + x;
-		pc += 2;
-		CPU_READ_FAST( this, addr, TIME, nz );
-		a = nz;
-		goto loop;
-	}
-
-	case 0x9D:{// STA abs,X
-		fuint16 addr = GET_ADDR() + x;
-		pc += 2;
-		CPU_WRITE_FAST( this, addr, a, TIME );
-		goto loop;
-	}
-
-	case 0x95: // STA zp,x
-		data = uint8_t (data + x);
-	case 0x85: // STA zp
-		pc++;
-		WRITE_LOW( data, a );
-		goto loop;
-
-	case 0xAE:{// LDX abs
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		CPU_READ_FAST( this, addr, TIME, nz );
-		x = nz;
-		goto loop;
-	}
-
-	case 0xA5: // LDA zp
-		a = nz = READ_LOW( data );
-		pc++;
-		goto loop;
-
-// Load/store
-
-	{
-		fuint16 addr;
-	case 0x91: // STA (ind),Y
-		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
-		addr += READ_LOW( data ) + y;
-		pc++;
-		goto sta_ptr;
-
-	case 0x81: // STA (ind,X)
-		data = uint8_t (data + x);
-	case 0x92: // STA (ind)
-		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
-		addr += READ_LOW( data );
-		pc++;
-		goto sta_ptr;
-
-	case 0x99: // STA abs,Y
-		data += y;
-	case 0x8D: // STA abs
-		addr = data + 0x100 * GET_MSB();
-		pc += 2;
-	sta_ptr:
-		CPU_WRITE_FAST( this, addr, a, TIME );
-		goto loop;
-	}
-
-	{
-		fuint16 addr;
-	case 0xA1: // LDA (ind,X)
-		data = uint8_t (data + x);
-	case 0xB2: // LDA (ind)
-		addr = 0x100 * READ_LOW( uint8_t (data + 1) );
-		addr += READ_LOW( data );
-		pc++;
-		goto a_nz_read_addr;
-
-	case 0xB1:// LDA (ind),Y
-		addr = READ_LOW( data ) + y;
-		PAGE_CROSS_PENALTY( addr );
-		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
-		pc++;
-		goto a_nz_read_addr;
-
-	case 0xB9: // LDA abs,Y
-		data += y;
-		PAGE_CROSS_PENALTY( data );
-	case 0xAD: // LDA abs
-		addr = data + 0x100 * GET_MSB();
-		pc += 2;
-	a_nz_read_addr:
-		CPU_READ_FAST( this, addr, TIME, nz );
-		a = nz;
-		goto loop;
-	}
-
-	case 0xBE:{// LDX abs,y
-		PAGE_CROSS_PENALTY( data + y );
-		fuint16 addr = GET_ADDR() + y;
-		pc += 2;
-		FLUSH_TIME();
-		x = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	case 0xB5: // LDA zp,x
-		a = nz = READ_LOW( uint8_t (data + x) );
-		pc++;
-		goto loop;
-
-	case 0xA9: // LDA #imm
-		pc++;
-		a  = data;
-		nz = data;
-		goto loop;
-
-// Bit operations
-
-	case 0x3C: // BIT abs,x
-		data += x;
-	case 0x2C:{// BIT abs
-		fuint16 addr;
-		ADD_PAGE( addr );
-		FLUSH_TIME();
-		nz = READ( addr );
-		CACHE_TIME();
-		goto bit_common;
-	}
-	case 0x34: // BIT zp,x
-		data = uint8_t (data + x);
-	case 0x24: // BIT zp
-		data = READ_LOW( data );
-	case 0x89: // BIT imm
-		nz = data;
-	bit_common:
-		pc++;
-		status &= ~st_v;
-		status |= nz & st_v;
-		if ( nz & a )
-			goto loop; // Z should be clear, and nz must be non-zero if nz & a is
-		nz <<= 8; // set Z flag without affecting N flag
-		goto loop;
-
-	{
-		fuint16 addr;
-
-	case 0xB3: // TST abs,x
-		addr = GET_MSB() + x;
-		goto tst_abs;
-
-	case 0x93: // TST abs
-		addr = GET_MSB();
-	tst_abs:
-		addr += 0x100 * instr [2];
-		pc++;
-		FLUSH_TIME();
-		nz = READ( addr );
-		CACHE_TIME();
-		goto tst_common;
-	}
-
-	case 0xA3: // TST zp,x
-		nz = READ_LOW( uint8_t (GET_MSB() + x) );
-		goto tst_common;
-
-	case 0x83: // TST zp
-		nz = READ_LOW( GET_MSB() );
-	tst_common:
-		pc += 2;
-		status &= ~st_v;
-		status |= nz & st_v;
-		if ( nz & data )
-			goto loop; // Z should be clear, and nz must be non-zero if nz & data is
-		nz <<= 8; // set Z flag without affecting N flag
-		goto loop;
-
-	{
-		fuint16 addr;
-	case 0x0C: // TSB abs
-	case 0x1C: // TRB abs
-		addr = GET_ADDR();
-		pc++;
-		goto txb_addr;
-
-	// TODO: everyone lists different behaviors for the status flags, ugh
-	case 0x04: // TSB zp
-	case 0x14: // TRB zp
-		addr = data + ram_addr;
-	txb_addr:
-		FLUSH_TIME();
-		nz = a | READ( addr );
-		if ( opcode & 0x10 )
-			nz ^= a; // bits from a will already be set, so this clears them
-		status &= ~st_v;
-		status |= nz & st_v;
-		pc++;
-		WRITE( addr, nz );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	case 0x07: // RMBn
-	case 0x17:
-	case 0x27:
-	case 0x37:
-	case 0x47:
-	case 0x57:
-	case 0x67:
-	case 0x77:
-		pc++;
-		READ_LOW( data ) &= ~(1 << (opcode >> 4));
-		goto loop;
-
-	case 0x87: // SMBn
-	case 0x97:
-	case 0xA7:
-	case 0xB7:
-	case 0xC7:
-	case 0xD7:
-	case 0xE7:
-	case 0xF7:
-		pc++;
-		READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
-		goto loop;
-
-// Load/store
-
-	case 0x9E: // STZ abs,x
-		data += x;
-	case 0x9C: // STZ abs
-		ADD_PAGE( data );
-		pc++;
-		FLUSH_TIME();
-		WRITE( data, 0 );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x74: // STZ zp,x
-		data = uint8_t (data + x);
-	case 0x64: // STZ zp
-		pc++;
-		WRITE_LOW( data, 0 );
-		goto loop;
-
-	case 0x94: // STY zp,x
-		data = uint8_t (data + x);
-	case 0x84: // STY zp
-		pc++;
-		WRITE_LOW( data, y );
-		goto loop;
-
-	case 0x96: // STX zp,y
-		data = uint8_t (data + y);
-	case 0x86: // STX zp
-		pc++;
-		WRITE_LOW( data, x );
-		goto loop;
-
-	case 0xB6: // LDX zp,y
-		data = uint8_t (data + y);
-	case 0xA6: // LDX zp
-		data = READ_LOW( data );
-	case 0xA2: // LDX #imm
-		pc++;
-		x = data;
-		nz = data;
-		goto loop;
-
-	case 0xB4: // LDY zp,x
-		data = uint8_t (data + x);
-	case 0xA4: // LDY zp
-		data = READ_LOW( data );
-	case 0xA0: // LDY #imm
-		pc++;
-		y = data;
-		nz = data;
-		goto loop;
-
-	case 0xBC: // LDY abs,X
-		data += x;
-		PAGE_CROSS_PENALTY( data );
-	case 0xAC:{// LDY abs
-		fuint16 addr = data + 0x100 * GET_MSB();
-		pc += 2;
-		FLUSH_TIME();
-		y = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	{
-		fuint8 temp;
-	case 0x8C: // STY abs
-		temp = y;
-		goto store_abs;
-
-	case 0x8E: // STX abs
-		temp = x;
-	store_abs:
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		FLUSH_TIME();
-		WRITE( addr, temp );
-		CACHE_TIME();
-		goto loop;
-	}
-
-// Compare
-
-	case 0xEC:{// CPX abs
-		fuint16 addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpx_data;
-	}
-
-	case 0xE4: // CPX zp
-		data = READ_LOW( data );
-	case 0xE0: // CPX #imm
-	cpx_data:
-		nz = x - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	case 0xCC:{// CPY abs
-		fuint16 addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpy_data;
-	}
-
-	case 0xC4: // CPY zp
-		data = READ_LOW( data );
-	case 0xC0: // CPY #imm
-	cpy_data:
-		nz = y - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-// Logical
-
-#define ARITH_ADDR_MODES( op )\
-	case op - 0x04: /* (ind,x) */\
-		data = uint8_t (data + x);\
-	case op + 0x0D: /* (ind) */\
-		data = 0x100 * READ_LOW( uint8_t (data + 1) ) + READ_LOW( data );\
-		goto ptr##op;\
-	case op + 0x0C:{/* (ind),y */\
-		fuint16 temp = READ_LOW( data ) + y;\
-		PAGE_CROSS_PENALTY( temp );\
-		data = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
-		goto ptr##op;\
-	}\
-	case op + 0x10: /* zp,X */\
-		data = uint8_t (data + x);\
-	case op + 0x00: /* zp */\
-		data = READ_LOW( data );\
-		goto imm##op;\
-	case op + 0x14: /* abs,Y */\
-		data += y;\
-		goto ind##op;\
-	case op + 0x18: /* abs,X */\
-		data += x;\
-	ind##op:\
-		PAGE_CROSS_PENALTY( data );\
-	case op + 0x08: /* abs */\
-		ADD_PAGE( data );\
-	ptr##op:\
-		FLUSH_TIME();\
-		data = READ( data );\
-		CACHE_TIME();\
-	case op + 0x04: /* imm */\
-	imm##op:
-
-	ARITH_ADDR_MODES( 0xC5 ) // CMP
-		nz = a - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x25 ) // AND
-		nz = (a &= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x45 ) // EOR
-		nz = (a ^= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x05 ) // ORA
-		nz = (a |= data);
-		pc++;
-		goto loop;
-
-// Add/subtract
-
-	ARITH_ADDR_MODES( 0xE5 ) // SBC
-		data ^= 0xFF;
-		goto adc_imm;
-
-	ARITH_ADDR_MODES( 0x65 ) // ADC
-	adc_imm: {
-		if ( status & st_d )
-			debug_printf( "Decimal mode not supported\n" );
-		fint16 carry = c >> 8 & 1;
-		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
-		status &= ~st_v;
-		status |= ov >> 2 & 0x40;
-		c = nz = a + data + carry;
-		pc++;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-// Shift/rotate
-
-	case 0x4A: // LSR A
-		c = 0;
-	case 0x6A: // ROR A
-		nz = c >> 1 & 0x80;
-		c = a << 8;
-		nz |= a >> 1;
-		a = nz;
-		goto loop;
-
-	case 0x0A: // ASL A
-		nz = a << 1;
-		c = nz;
-		a = (uint8_t) nz;
-		goto loop;
-
-	case 0x2A: { // ROL A
-		nz = a << 1;
-		fint16 temp = c >> 8 & 1;
-		c = nz;
-		nz |= temp;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-	case 0x5E: // LSR abs,X
-		data += x;
-	case 0x4E: // LSR abs
-		c = 0;
-	case 0x6E: // ROR abs
-	ror_abs: {
-		ADD_PAGE( data );
-		FLUSH_TIME();
-		int temp = READ( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto rotate_common;
-	}
-
-	case 0x3E: // ROL abs,X
-		data += x;
-		goto rol_abs;
-
-	case 0x1E: // ASL abs,X
-		data += x;
-	case 0x0E: // ASL abs
-		c = 0;
-	case 0x2E: // ROL abs
-	rol_abs:
-		ADD_PAGE( data );
-		nz = c >> 8 & 1;
-		FLUSH_TIME();
-		nz |= (c = READ( data ) << 1);
-	rotate_common:
-		pc++;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x7E: // ROR abs,X
-		data += x;
-		goto ror_abs;
-
-	case 0x76: // ROR zp,x
-		data = uint8_t (data + x);
-		goto ror_zp;
-
-	case 0x56: // LSR zp,x
-		data = uint8_t (data + x);
-	case 0x46: // LSR zp
-		c = 0;
-	case 0x66: // ROR zp
-	ror_zp: {
-		int temp = READ_LOW( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto write_nz_zp;
-	}
-
-	case 0x36: // ROL zp,x
-		data = uint8_t (data + x);
-		goto rol_zp;
-
-	case 0x16: // ASL zp,x
-		data = uint8_t (data + x);
-	case 0x06: // ASL zp
-		c = 0;
-	case 0x26: // ROL zp
-	rol_zp:
-		nz = c >> 8 & 1;
-		nz |= (c = READ_LOW( data ) << 1);
-		goto write_nz_zp;
-
-// Increment/decrement
-
-#define INC_DEC_AXY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-	case 0x1A: // INA
-		INC_DEC_AXY( a, +1 )
-
-	case 0xE8: // INX
-		INC_DEC_AXY( x, +1 )
-
-	case 0xC8: // INY
-		INC_DEC_AXY( y, +1 )
-
-	case 0x3A: // DEA
-		INC_DEC_AXY( a, -1 )
-
-	case 0xCA: // DEX
-		INC_DEC_AXY( x, -1 )
-
-	case 0x88: // DEY
-		INC_DEC_AXY( y, -1 )
-
-	case 0xF6: // INC zp,x
-		data = uint8_t (data + x);
-	case 0xE6: // INC zp
-		nz = 1;
-		goto add_nz_zp;
-
-	case 0xD6: // DEC zp,x
-		data = uint8_t (data + x);
-	case 0xC6: // DEC zp
-		nz = (unsigned) -1;
-	add_nz_zp:
-		nz += READ_LOW( data );
-	write_nz_zp:
-		pc++;
-		WRITE_LOW( data, nz );
-		goto loop;
-
-	case 0xFE: // INC abs,x
-		data = x + GET_ADDR();
-		goto inc_ptr;
-
-	case 0xEE: // INC abs
-		data = GET_ADDR();
-	inc_ptr:
-		nz = 1;
-		goto inc_common;
-
-	case 0xDE: // DEC abs,x
-		data = x + GET_ADDR();
-		goto dec_ptr;
-
-	case 0xCE: // DEC abs
-		data = GET_ADDR();
-	dec_ptr:
-		nz = (unsigned) -1;
-	inc_common:
-		FLUSH_TIME();
-		nz += READ( data );
-		pc += 2;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-// Transfer
-
-	case 0xA8: // TAY
-		y  = a;
-		nz = a;
-		goto loop;
-
-	case 0x98: // TYA
-		a  = y;
-		nz = y;
-		goto loop;
-
-	case 0xAA: // TAX
-		x  = a;
-		nz = a;
-		goto loop;
-
-	case 0x8A: // TXA
-		a  = x;
-		nz = x;
-		goto loop;
-
-	case 0x9A: // TXS
-		SET_SP( x ); // verified (no flag change)
-		goto loop;
-
-	case 0xBA: // TSX
-		x = nz = GET_SP();
-		goto loop;
-
-	#define SWAP_REGS( r1, r2 ) {\
-		fuint8 t = r1;\
-		r1 = r2;\
-		r2 = t;\
-		goto loop;\
-	}
-
-	case 0x02: // SXY
-		SWAP_REGS( x, y );
-
-	case 0x22: // SAX
-		SWAP_REGS( a, x );
-
-	case 0x42: // SAY
-		SWAP_REGS( a, y );
-
-	case 0x62: // CLA
-		a = 0;
-		goto loop;
-
-	case 0x82: // CLX
-		x = 0;
-		goto loop;
-
-	case 0xC2: // CLY
-		y = 0;
-		goto loop;
-
-// Stack
-
-	case 0x48: // PHA
-		PUSH( a );
-		goto loop;
-
-	case 0xDA: // PHX
-		PUSH( x );
-		goto loop;
-
-	case 0x5A: // PHY
-		PUSH( y );
-		goto loop;
-
-	case 0x40:{// RTI
-		fuint8 temp = READ_LOW( sp );
-		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
-		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
-		sp = (sp - 0xFD) | 0x100;
-		data = status;
-		SET_STATUS( temp );
-		this->r.status = status; // update externally-visible I flag
-		if ( (data ^ status) & st_i )
-		{
-			hes_time_t new_time = end_time_;
-			if ( !(status & st_i) && new_time > irq_time_ )
-				new_time = irq_time_;
-			blargg_long delta = s.base - new_time;
-			s.base = new_time;
-			s_time += delta;
-		}
-		goto loop;
-	}
-
-	#define POP()  READ_LOW( sp ); sp = (sp - 0xFF) | 0x100
-
-	case 0x68: // PLA
-		a = nz = POP();
-		goto loop;
-
-	case 0xFA: // PLX
-		x = nz = POP();
-		goto loop;
-
-	case 0x7A: // PLY
-		y = nz = POP();
-		goto loop;
-
-	case 0x28:{// PLP
-		fuint8 temp = POP();
-		fuint8 changed = status ^ temp;
-		SET_STATUS( temp );
-		if ( !(changed & st_i) )
-			goto loop; // I flag didn't change
-		if ( status & st_i )
-			goto handle_sei;
-		goto handle_cli;
-	}
-	#undef POP
-
-	case 0x08: { // PHP
-		fuint8 temp;
-		CALC_STATUS( temp );
-		PUSH( temp | st_b );
-		goto loop;
-	}
-
-// Flags
-
-	case 0x38: // SEC
-		c = (unsigned) ~0;
-		goto loop;
-
-	case 0x18: // CLC
-		c = 0;
-		goto loop;
-
-	case 0xB8: // CLV
-		status &= ~st_v;
-		goto loop;
-
-	case 0xD8: // CLD
-		status &= ~st_d;
-		goto loop;
-
-	case 0xF8: // SED
-		status |= st_d;
-		goto loop;
-
-	case 0x58: // CLI
-		if ( !(status & st_i) )
-			goto loop;
-		status &= ~st_i;
-	handle_cli: {
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - irq_time_;
-		if ( delta <= 0 )
-		{
-			if ( TIME < irq_time_ )
-				goto loop;
-			goto delayed_cli;
-		}
-		s.base = irq_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-
-		if ( delta >= s_time + 1 )
-		{
-			// delayed irq until after next instruction
-			s.base += s_time + 1;
-			s_time = -1;
-			irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
-			goto loop;
-		}
-	delayed_cli:
-		debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
-		goto loop;
-	}
-
-	case 0x78: // SEI
-		if ( status & st_i )
-			goto loop;
-		status |= st_i;
-	handle_sei: {
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - end_time_;
-		s.base = end_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-		debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
-		goto loop;
-	}
-
-// Special
-
-	case 0x53:{// TAM
-		fuint8 const bits = data; // avoid using data across function call
-		pc++;
-		for ( int i = 0; i < 8; i++ )
-			if ( bits & (1 << i) )
-				set_mmr( i, a );
-		goto loop;
-	}
-
-	case 0x43:{// TMA
-		pc++;
-		byte const* in = mmr;
-		do
-		{
-			if ( data & 1 )
-				a = *in;
-			in++;
-		}
-		while ( (data >>= 1) != 0 );
-		goto loop;
-	}
-
-	case 0x03: // ST0
-	case 0x13: // ST1
-	case 0x23:{// ST2
-		fuint16 addr = opcode >> 4;
-		if ( addr )
-			addr++;
-		pc++;
-		FLUSH_TIME();
-		CPU_WRITE_VDP( this, addr, data, TIME );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	case 0xEA: // NOP
-		goto loop;
-
-	case 0x54: // CSL
-		debug_printf( "CSL not supported\n" );
-		illegal_encountered = true;
-		goto loop;
-
-	case 0xD4: // CSH
-		goto loop;
-
-	case 0xF4: { // SET
-		//fuint16 operand = GET_MSB();
-		debug_printf( "SET not handled\n" );
-		//switch ( data )
-		//{
-		//}
-		illegal_encountered = true;
-		goto loop;
-	}
-
-// Block transfer
-
-	{
-		fuint16 in_alt;
-		fint16 in_inc;
-		fuint16 out_alt;
-		fint16 out_inc;
-
-	case 0xE3: // TIA
-		in_alt  = 0;
-		goto bxfer_alt;
-
-	case 0xF3: // TAI
-		in_alt  = 1;
-	bxfer_alt:
-		in_inc  = in_alt ^ 1;
-		out_alt = in_inc;
-		out_inc = in_alt;
-		goto bxfer;
-
-	case 0xD3: // TIN
-		in_inc  = 1;
-		out_inc = 0;
-		goto bxfer_no_alt;
-
-	case 0xC3: // TDD
-		in_inc  = -1;
-		out_inc = -1;
-		goto bxfer_no_alt;
-
-	case 0x73: // TII
-		in_inc  = 1;
-		out_inc = 1;
-	bxfer_no_alt:
-		in_alt  = 0;
-		out_alt = 0;
-	bxfer:
-		fuint16 in    = GET_LE16( instr + 0 );
-		fuint16 out   = GET_LE16( instr + 2 );
-		int     count = GET_LE16( instr + 4 );
-		if ( !count )
-			count = 0x10000;
-		pc += 6;
-		WRITE_LOW( 0x100 | (sp - 1), y );
-		WRITE_LOW( 0x100 | (sp - 2), a );
-		WRITE_LOW( 0x100 | (sp - 3), x );
-		FLUSH_TIME();
-		do
-		{
-			// TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
-			fuint8 t = READ( in );
-			in += in_inc;
-			in &= 0xFFFF;
-			s.time += 6;
-			if ( in_alt )
-				in_inc = -in_inc;
-			WRITE( out, t );
-			out += out_inc;
-			out &= 0xFFFF;
-			if ( out_alt )
-				out_inc = -out_inc;
-		}
-		while ( --count );
-		CACHE_TIME();
-		goto loop;
-	}
-
-// Illegal
-
-	default:
-		assert( (unsigned) opcode <= 0xFF );
-		debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
-		illegal_encountered = true;
-		goto loop;
-	}
-	assert( false );
-
-	int result_;
-handle_brk:
-	pc++;
-	result_ = 6;
-
-interrupt:
-	{
-		s_time += 7;
-
-		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
-		WRITE_LOW( 0x100 | (sp - 2), pc );
-		pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
-
-		sp = (sp - 3) | 0x100;
-		fuint8 temp;
-		CALC_STATUS( temp );
-		if ( result_ == 6 )
-			temp |= st_b;
-		WRITE_LOW( sp, temp );
-
-		status &= ~st_d;
-		status |= st_i;
-		this->r.status = status; // update externally-visible I flag
-
-		blargg_long delta = s.base - end_time_;
-		s.base = end_time_;
-		s_time += delta;
-		goto loop;
-	}
-
-idle_done:
-	s_time = 0;
-out_of_time:
-	pc--;
-	FLUSH_TIME();
-	CPU_DONE( this, TIME, result_ );
-	CACHE_TIME();
-	if ( result_ > 0 )
-		goto interrupt;
-	if ( s_time < 0 )
-		goto loop;
-
-	s.time = s_time;
-
-	r.pc = pc;
-	r.sp = GET_SP();
-	r.a = a;
-	r.x = x;
-	r.y = y;
-
-	{
-		fuint8 temp;
-		CALC_STATUS( temp );
-		r.status = temp;
-	}
-
-	this->state_ = s;
-	this->state = &this->state_;
-
-	return illegal_encountered;
-}
-
diff --git a/src/console/Hes_Emu.cc b/src/console/Hes_Emu.cc
new file mode 100644
index 000000000000..265d3d780c9f
--- /dev/null
+++ b/src/console/Hes_Emu.cc
@@ -0,0 +1,531 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Hes_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const timer_mask  = 0x04;
+int const vdp_mask    = 0x02;
+int const i_flag_mask = 0x04;
+int const unmapped    = 0xFF;
+
+long const period_60hz = 262 * 455L; // scanlines * clocks per scanline
+
+Hes_Emu::Hes_Emu()
+{
+	timer.raw_load = 0;
+	set_type( gme_hes_type );
+
+	static const char* const names [Hes_Apu::osc_count] = {
+		"Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2"
+	};
+	set_voice_names( names );
+
+	static int const types [Hes_Apu::osc_count] = {
+		wave_type  | 0, wave_type  | 1, wave_type | 2, wave_type | 3,
+		mixed_type | 0, mixed_type | 1
+	};
+	set_voice_types( types );
+	set_silence_lookahead( 6 );
+	set_gain( 1.11 );
+}
+
+Hes_Emu::~Hes_Emu() { }
+
+void Hes_Emu::unload()
+{
+	rom.clear();
+	Music_Emu::unload();
+}
+
+// Track info
+
+static byte const* copy_field( byte const* in, char* out )
+{
+	if ( in )
+	{
+		int len = 0x20;
+		if ( in [0x1F] && !in [0x2F] )
+			len = 0x30; // fields are sometimes 16 bytes longer (ugh)
+
+		// since text fields are where any data could be, detect non-text
+		// and fields with data after zero byte terminator
+
+		int i = 0;
+		for ( i = 0; i < len && in [i]; i++ )
+			if ( ((in [i] + 1) & 0xFF) < ' ' + 1 ) // also treat 0xFF as non-text
+				return 0; // non-ASCII found
+
+		for ( ; i < len; i++ )
+			if ( in [i] )
+				return 0; // data after terminator
+
+		Gme_File::copy_field_( out, (char const*) in, len );
+		in += len;
+	}
+	return in;
+}
+
+static void copy_hes_fields( byte const* in, track_info_t* out )
+{
+	if ( *in >= ' ' )
+	{
+		in = copy_field( in, out->game );
+		in = copy_field( in, out->author );
+		in = copy_field( in, out->copyright );
+	}
+}
+
+blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
+{
+	copy_hes_fields( rom.begin() + 0x20, out );
+	return 0;
+}
+
+static blargg_err_t check_hes_header( void const* header )
+{
+	if ( memcmp( header, "HESM", 4 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Hes_File : Gme_Info_
+{
+	struct header_t {
+		char header [Hes_Emu::header_size];
+		char unused [0x20];
+		byte fields [0x30 * 3];
+	} h;
+
+	Hes_File() { set_type( gme_hes_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20 );
+		blargg_err_t err = in.read( &h, sizeof h );
+		if ( err )
+			return (err == in.eof_error ? gme_wrong_file_type : err);
+		return check_hes_header( &h );
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		copy_hes_fields( h.fields, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
+static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
+
+static gme_type_t_ const gme_hes_type_ = { "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 };
+gme_type_t const gme_hes_type = &gme_hes_type_;
+
+
+// Setup
+
+blargg_err_t Hes_Emu::load_( Data_Reader& in )
+{
+	assert( offsetof (header_t,unused [4]) == header_size );
+	RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) );
+
+	RETURN_ERR( check_hes_header( header_.tag ) );
+
+	if ( header_.vers != 0 )
+		set_warning( "Unknown file version" );
+
+	if ( memcmp( header_.data_tag, "DATA", 4 ) )
+		set_warning( "Data header missing" );
+
+	if ( memcmp( header_.unused, "\0\0\0\0", 4 ) )
+		set_warning( "Unknown header data" );
+
+	// File spec supports multiple blocks, but I haven't found any, and
+	// many files have bad sizes in the only block, so it's simpler to
+	// just try to load the damn data as best as possible.
+
+	long addr = GET_LE32( header_.addr );
+	long size = GET_LE32( header_.size );
+	long const rom_max = 0x100000;
+	if ( addr & ~(rom_max - 1) )
+	{
+		set_warning( "Invalid address" );
+		addr &= rom_max - 1;
+	}
+	if ( (unsigned long) (addr + size) > (unsigned long) rom_max )
+		set_warning( "Invalid size" );
+
+	if ( size != rom.file_size() )
+	{
+		if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) )
+			set_warning( "Multiple DATA not supported" );
+		else if ( size < rom.file_size() )
+			set_warning( "Extra file data" );
+		else
+			set_warning( "Missing file data" );
+	}
+
+	rom.set_addr( addr );
+
+	set_voice_count( apu.osc_count );
+
+	apu.volume( gain() );
+
+	return setup_buffer( 7159091 );
+}
+
+void Hes_Emu::update_eq( blip_eq_t const& eq )
+{
+	apu.treble_eq( eq );
+}
+
+void Hes_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	apu.osc_output( i, center, left, right );
+}
+
+// Emulation
+
+void Hes_Emu::recalc_timer_load()
+{
+	timer.load = timer.raw_load * timer_base + 1;
+}
+
+void Hes_Emu::set_tempo_( double t )
+{
+	play_period = hes_time_t (period_60hz / t);
+	timer_base = int (1024 / t);
+	recalc_timer_load();
+}
+
+blargg_err_t Hes_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( ram, 0, sizeof ram ); // some HES music relies on zero fill
+	memset( sgx, 0, sizeof sgx );
+
+	apu.reset();
+	cpu::reset();
+
+	for ( unsigned i = 0; i < sizeof header_.banks; i++ )
+		set_mmr( i, header_.banks [i] );
+	set_mmr( page_count, 0xFF ); // unmapped beyond end of address space
+
+	irq.disables  = timer_mask | vdp_mask;
+	irq.timer     = future_hes_time;
+	irq.vdp       = future_hes_time;
+
+	timer.enabled = false;
+	timer.raw_load= 0x80;
+	timer.count   = timer.load;
+	timer.fired   = false;
+	timer.last_time = 0;
+
+	vdp.latch     = 0;
+	vdp.control   = 0;
+	vdp.next_vbl  = 0;
+
+	ram [0x1FF] = (idle_addr - 1) >> 8;
+	ram [0x1FE] = (idle_addr - 1) & 0xFF;
+	r.sp = 0xFD;
+	r.pc = GET_LE16( header_.init_addr );
+	r.a  = track;
+
+	recalc_timer_load();
+	last_frame_hook = 0;
+
+	return 0;
+}
+
+// Hardware
+
+void Hes_Emu::cpu_write_vdp( int addr, int data )
+{
+	switch ( addr )
+	{
+	case 0:
+		vdp.latch = data & 0x1F;
+		break;
+
+	case 2:
+		if ( vdp.latch == 5 )
+		{
+			if ( data & 0x04 )
+				set_warning( "Scanline interrupt unsupported" );
+			run_until( time() );
+			vdp.control = data;
+			irq_changed();
+		}
+		else
+		{
+			debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
+		}
+		break;
+
+	case 3:
+		debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
+		break;
+	}
+}
+
+void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
+{
+	if ( unsigned (addr - apu.start_addr) <= apu.end_addr - apu.start_addr )
+	{
+		GME_APU_HOOK( this, addr - apu.start_addr, data );
+		// avoid going way past end when a long block xfer is writing to I/O space
+		hes_time_t t = min( time(), end_time() + 8 );
+		apu.write_data( t, addr, data );
+		return;
+	}
+
+	hes_time_t time = this->time();
+	switch ( addr )
+	{
+	case 0x0000:
+	case 0x0002:
+	case 0x0003:
+		cpu_write_vdp( addr, data );
+		return;
+
+	case 0x0C00: {
+		run_until( time );
+		timer.raw_load = (data & 0x7F) + 1;
+		recalc_timer_load();
+		timer.count = timer.load;
+		break;
+	}
+
+	case 0x0C01:
+		data &= 1;
+		if ( timer.enabled == data )
+			return;
+		run_until( time );
+		timer.enabled = data;
+		if ( data )
+			timer.count = timer.load;
+		break;
+
+	case 0x1402:
+		run_until( time );
+		irq.disables = data;
+		if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
+			debug_printf( "Int mask: $%02X\n", data );
+		break;
+
+	case 0x1403:
+		run_until( time );
+		if ( timer.enabled )
+			timer.count = timer.load;
+		timer.fired = false;
+		break;
+
+#ifndef NDEBUG
+	case 0x1000: // I/O port
+	case 0x0402: // palette
+	case 0x0403:
+	case 0x0404:
+	case 0x0405:
+		return;
+
+	default:
+		debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
+		return;
+#endif
+	}
+
+	irq_changed();
+}
+
+int Hes_Emu::cpu_read_( hes_addr_t addr )
+{
+	hes_time_t time = this->time();
+	addr &= page_size - 1;
+	switch ( addr )
+	{
+	case 0x0000:
+		if ( irq.vdp > time )
+			return 0;
+		irq.vdp = future_hes_time;
+		run_until( time );
+		irq_changed();
+		return 0x20;
+
+	case 0x0002:
+	case 0x0003:
+		debug_printf( "VDP read not supported: %d\n", addr );
+		return 0;
+
+	case 0x0C01:
+		//return timer.enabled; // TODO: remove?
+	case 0x0C00:
+		run_until( time );
+		debug_printf( "Timer count read\n" );
+		return (unsigned) (timer.count - 1) / timer_base;
+
+	case 0x1402:
+		return irq.disables;
+
+	case 0x1403:
+		{
+			int status = 0;
+			if ( irq.timer <= time ) status |= timer_mask;
+			if ( irq.vdp   <= time ) status |= vdp_mask;
+			return status;
+		}
+
+	#ifndef NDEBUG
+		case 0x1000: // I/O port
+		case 0x180C: // CD-ROM
+		case 0x180D:
+			break;
+
+		default:
+			debug_printf( "unmapped read  $%04X\n", addr );
+	#endif
+	}
+
+	return unmapped;
+}
+
+// see hes_cpu_io.h for core read/write functions
+
+// Emulation
+
+void Hes_Emu::run_until( hes_time_t present )
+{
+	while ( vdp.next_vbl < present )
+		vdp.next_vbl += play_period;
+
+	hes_time_t elapsed = present - timer.last_time;
+	if ( elapsed > 0 )
+	{
+		if ( timer.enabled )
+		{
+			timer.count -= elapsed;
+			if ( timer.count <= 0 )
+				timer.count += timer.load;
+		}
+		timer.last_time = present;
+	}
+}
+
+void Hes_Emu::irq_changed()
+{
+	hes_time_t present = time();
+
+	if ( irq.timer > present )
+	{
+		irq.timer = future_hes_time;
+		if ( timer.enabled && !timer.fired )
+			irq.timer = present + timer.count;
+	}
+
+	if ( irq.vdp > present )
+	{
+		irq.vdp = future_hes_time;
+		if ( vdp.control & 0x08 )
+			irq.vdp = vdp.next_vbl;
+	}
+
+	hes_time_t time = future_hes_time;
+	if ( !(irq.disables & timer_mask) ) time = irq.timer;
+	if ( !(irq.disables &   vdp_mask) ) time = min( time, irq.vdp );
+
+	set_irq_time( time );
+}
+
+int Hes_Emu::cpu_done()
+{
+	check( time() >= end_time() ||
+			(!(r.status & i_flag_mask) && time() >= irq_time()) );
+
+	if ( !(r.status & i_flag_mask) )
+	{
+		hes_time_t present = time();
+
+		if ( irq.timer <= present && !(irq.disables & timer_mask) )
+		{
+			timer.fired = true;
+			irq.timer = future_hes_time;
+			irq_changed(); // overkill, but not worth writing custom code
+			#if GME_FRAME_HOOK_DEFINED
+			{
+				unsigned const threshold = period_60hz / 30;
+				unsigned long elapsed = present - last_frame_hook;
+				if ( elapsed - period_60hz + threshold / 2 < threshold )
+				{
+					last_frame_hook = present;
+					GME_FRAME_HOOK( this );
+				}
+			}
+			#endif
+			return 0x0A;
+		}
+
+		if ( irq.vdp <= present && !(irq.disables & vdp_mask) )
+		{
+			// work around for bugs with music not acknowledging VDP
+			//run_until( present );
+			//irq.vdp = future_hes_time;
+			//irq_changed();
+			#if GME_FRAME_HOOK_DEFINED
+				last_frame_hook = present;
+				GME_FRAME_HOOK( this );
+			#endif
+			return 0x08;
+		}
+	}
+	return 0;
+}
+
+static void adjust_time( blargg_long& time, hes_time_t delta )
+{
+	if ( time < future_hes_time )
+	{
+		time -= delta;
+		if ( time < 0 )
+			time = 0;
+	}
+}
+
+blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
+{
+	blip_time_t const duration = duration_; // cache
+
+	if ( cpu::run( duration ) )
+		set_warning( "Emulation error (illegal instruction)" );
+
+	check( time() >= duration );
+	//check( time() - duration < 20 ); // Txx instruction could cause going way over
+
+	run_until( duration );
+
+	// end time frame
+	timer.last_time -= duration;
+	vdp.next_vbl    -= duration;
+	#if GME_FRAME_HOOK_DEFINED
+		last_frame_hook -= duration;
+	#endif
+	cpu::end_frame( duration );
+	::adjust_time( irq.timer, duration );
+	::adjust_time( irq.vdp,   duration );
+	apu.end_frame( duration );
+
+	return 0;
+}
diff --git a/src/console/Hes_Emu.cxx b/src/console/Hes_Emu.cxx
deleted file mode 100644
index 265d3d780c9f..000000000000
--- a/src/console/Hes_Emu.cxx
+++ /dev/null
@@ -1,531 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const timer_mask  = 0x04;
-int const vdp_mask    = 0x02;
-int const i_flag_mask = 0x04;
-int const unmapped    = 0xFF;
-
-long const period_60hz = 262 * 455L; // scanlines * clocks per scanline
-
-Hes_Emu::Hes_Emu()
-{
-	timer.raw_load = 0;
-	set_type( gme_hes_type );
-
-	static const char* const names [Hes_Apu::osc_count] = {
-		"Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2"
-	};
-	set_voice_names( names );
-
-	static int const types [Hes_Apu::osc_count] = {
-		wave_type  | 0, wave_type  | 1, wave_type | 2, wave_type | 3,
-		mixed_type | 0, mixed_type | 1
-	};
-	set_voice_types( types );
-	set_silence_lookahead( 6 );
-	set_gain( 1.11 );
-}
-
-Hes_Emu::~Hes_Emu() { }
-
-void Hes_Emu::unload()
-{
-	rom.clear();
-	Music_Emu::unload();
-}
-
-// Track info
-
-static byte const* copy_field( byte const* in, char* out )
-{
-	if ( in )
-	{
-		int len = 0x20;
-		if ( in [0x1F] && !in [0x2F] )
-			len = 0x30; // fields are sometimes 16 bytes longer (ugh)
-
-		// since text fields are where any data could be, detect non-text
-		// and fields with data after zero byte terminator
-
-		int i = 0;
-		for ( i = 0; i < len && in [i]; i++ )
-			if ( ((in [i] + 1) & 0xFF) < ' ' + 1 ) // also treat 0xFF as non-text
-				return 0; // non-ASCII found
-
-		for ( ; i < len; i++ )
-			if ( in [i] )
-				return 0; // data after terminator
-
-		Gme_File::copy_field_( out, (char const*) in, len );
-		in += len;
-	}
-	return in;
-}
-
-static void copy_hes_fields( byte const* in, track_info_t* out )
-{
-	if ( *in >= ' ' )
-	{
-		in = copy_field( in, out->game );
-		in = copy_field( in, out->author );
-		in = copy_field( in, out->copyright );
-	}
-}
-
-blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
-{
-	copy_hes_fields( rom.begin() + 0x20, out );
-	return 0;
-}
-
-static blargg_err_t check_hes_header( void const* header )
-{
-	if ( memcmp( header, "HESM", 4 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Hes_File : Gme_Info_
-{
-	struct header_t {
-		char header [Hes_Emu::header_size];
-		char unused [0x20];
-		byte fields [0x30 * 3];
-	} h;
-
-	Hes_File() { set_type( gme_hes_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20 );
-		blargg_err_t err = in.read( &h, sizeof h );
-		if ( err )
-			return (err == in.eof_error ? gme_wrong_file_type : err);
-		return check_hes_header( &h );
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		copy_hes_fields( h.fields, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
-static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
-
-static gme_type_t_ const gme_hes_type_ = { "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 };
-gme_type_t const gme_hes_type = &gme_hes_type_;
-
-
-// Setup
-
-blargg_err_t Hes_Emu::load_( Data_Reader& in )
-{
-	assert( offsetof (header_t,unused [4]) == header_size );
-	RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) );
-
-	RETURN_ERR( check_hes_header( header_.tag ) );
-
-	if ( header_.vers != 0 )
-		set_warning( "Unknown file version" );
-
-	if ( memcmp( header_.data_tag, "DATA", 4 ) )
-		set_warning( "Data header missing" );
-
-	if ( memcmp( header_.unused, "\0\0\0\0", 4 ) )
-		set_warning( "Unknown header data" );
-
-	// File spec supports multiple blocks, but I haven't found any, and
-	// many files have bad sizes in the only block, so it's simpler to
-	// just try to load the damn data as best as possible.
-
-	long addr = GET_LE32( header_.addr );
-	long size = GET_LE32( header_.size );
-	long const rom_max = 0x100000;
-	if ( addr & ~(rom_max - 1) )
-	{
-		set_warning( "Invalid address" );
-		addr &= rom_max - 1;
-	}
-	if ( (unsigned long) (addr + size) > (unsigned long) rom_max )
-		set_warning( "Invalid size" );
-
-	if ( size != rom.file_size() )
-	{
-		if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) )
-			set_warning( "Multiple DATA not supported" );
-		else if ( size < rom.file_size() )
-			set_warning( "Extra file data" );
-		else
-			set_warning( "Missing file data" );
-	}
-
-	rom.set_addr( addr );
-
-	set_voice_count( apu.osc_count );
-
-	apu.volume( gain() );
-
-	return setup_buffer( 7159091 );
-}
-
-void Hes_Emu::update_eq( blip_eq_t const& eq )
-{
-	apu.treble_eq( eq );
-}
-
-void Hes_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	apu.osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Hes_Emu::recalc_timer_load()
-{
-	timer.load = timer.raw_load * timer_base + 1;
-}
-
-void Hes_Emu::set_tempo_( double t )
-{
-	play_period = hes_time_t (period_60hz / t);
-	timer_base = int (1024 / t);
-	recalc_timer_load();
-}
-
-blargg_err_t Hes_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( ram, 0, sizeof ram ); // some HES music relies on zero fill
-	memset( sgx, 0, sizeof sgx );
-
-	apu.reset();
-	cpu::reset();
-
-	for ( unsigned i = 0; i < sizeof header_.banks; i++ )
-		set_mmr( i, header_.banks [i] );
-	set_mmr( page_count, 0xFF ); // unmapped beyond end of address space
-
-	irq.disables  = timer_mask | vdp_mask;
-	irq.timer     = future_hes_time;
-	irq.vdp       = future_hes_time;
-
-	timer.enabled = false;
-	timer.raw_load= 0x80;
-	timer.count   = timer.load;
-	timer.fired   = false;
-	timer.last_time = 0;
-
-	vdp.latch     = 0;
-	vdp.control   = 0;
-	vdp.next_vbl  = 0;
-
-	ram [0x1FF] = (idle_addr - 1) >> 8;
-	ram [0x1FE] = (idle_addr - 1) & 0xFF;
-	r.sp = 0xFD;
-	r.pc = GET_LE16( header_.init_addr );
-	r.a  = track;
-
-	recalc_timer_load();
-	last_frame_hook = 0;
-
-	return 0;
-}
-
-// Hardware
-
-void Hes_Emu::cpu_write_vdp( int addr, int data )
-{
-	switch ( addr )
-	{
-	case 0:
-		vdp.latch = data & 0x1F;
-		break;
-
-	case 2:
-		if ( vdp.latch == 5 )
-		{
-			if ( data & 0x04 )
-				set_warning( "Scanline interrupt unsupported" );
-			run_until( time() );
-			vdp.control = data;
-			irq_changed();
-		}
-		else
-		{
-			debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
-		}
-		break;
-
-	case 3:
-		debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
-		break;
-	}
-}
-
-void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
-{
-	if ( unsigned (addr - apu.start_addr) <= apu.end_addr - apu.start_addr )
-	{
-		GME_APU_HOOK( this, addr - apu.start_addr, data );
-		// avoid going way past end when a long block xfer is writing to I/O space
-		hes_time_t t = min( time(), end_time() + 8 );
-		apu.write_data( t, addr, data );
-		return;
-	}
-
-	hes_time_t time = this->time();
-	switch ( addr )
-	{
-	case 0x0000:
-	case 0x0002:
-	case 0x0003:
-		cpu_write_vdp( addr, data );
-		return;
-
-	case 0x0C00: {
-		run_until( time );
-		timer.raw_load = (data & 0x7F) + 1;
-		recalc_timer_load();
-		timer.count = timer.load;
-		break;
-	}
-
-	case 0x0C01:
-		data &= 1;
-		if ( timer.enabled == data )
-			return;
-		run_until( time );
-		timer.enabled = data;
-		if ( data )
-			timer.count = timer.load;
-		break;
-
-	case 0x1402:
-		run_until( time );
-		irq.disables = data;
-		if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
-			debug_printf( "Int mask: $%02X\n", data );
-		break;
-
-	case 0x1403:
-		run_until( time );
-		if ( timer.enabled )
-			timer.count = timer.load;
-		timer.fired = false;
-		break;
-
-#ifndef NDEBUG
-	case 0x1000: // I/O port
-	case 0x0402: // palette
-	case 0x0403:
-	case 0x0404:
-	case 0x0405:
-		return;
-
-	default:
-		debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
-		return;
-#endif
-	}
-
-	irq_changed();
-}
-
-int Hes_Emu::cpu_read_( hes_addr_t addr )
-{
-	hes_time_t time = this->time();
-	addr &= page_size - 1;
-	switch ( addr )
-	{
-	case 0x0000:
-		if ( irq.vdp > time )
-			return 0;
-		irq.vdp = future_hes_time;
-		run_until( time );
-		irq_changed();
-		return 0x20;
-
-	case 0x0002:
-	case 0x0003:
-		debug_printf( "VDP read not supported: %d\n", addr );
-		return 0;
-
-	case 0x0C01:
-		//return timer.enabled; // TODO: remove?
-	case 0x0C00:
-		run_until( time );
-		debug_printf( "Timer count read\n" );
-		return (unsigned) (timer.count - 1) / timer_base;
-
-	case 0x1402:
-		return irq.disables;
-
-	case 0x1403:
-		{
-			int status = 0;
-			if ( irq.timer <= time ) status |= timer_mask;
-			if ( irq.vdp   <= time ) status |= vdp_mask;
-			return status;
-		}
-
-	#ifndef NDEBUG
-		case 0x1000: // I/O port
-		case 0x180C: // CD-ROM
-		case 0x180D:
-			break;
-
-		default:
-			debug_printf( "unmapped read  $%04X\n", addr );
-	#endif
-	}
-
-	return unmapped;
-}
-
-// see hes_cpu_io.h for core read/write functions
-
-// Emulation
-
-void Hes_Emu::run_until( hes_time_t present )
-{
-	while ( vdp.next_vbl < present )
-		vdp.next_vbl += play_period;
-
-	hes_time_t elapsed = present - timer.last_time;
-	if ( elapsed > 0 )
-	{
-		if ( timer.enabled )
-		{
-			timer.count -= elapsed;
-			if ( timer.count <= 0 )
-				timer.count += timer.load;
-		}
-		timer.last_time = present;
-	}
-}
-
-void Hes_Emu::irq_changed()
-{
-	hes_time_t present = time();
-
-	if ( irq.timer > present )
-	{
-		irq.timer = future_hes_time;
-		if ( timer.enabled && !timer.fired )
-			irq.timer = present + timer.count;
-	}
-
-	if ( irq.vdp > present )
-	{
-		irq.vdp = future_hes_time;
-		if ( vdp.control & 0x08 )
-			irq.vdp = vdp.next_vbl;
-	}
-
-	hes_time_t time = future_hes_time;
-	if ( !(irq.disables & timer_mask) ) time = irq.timer;
-	if ( !(irq.disables &   vdp_mask) ) time = min( time, irq.vdp );
-
-	set_irq_time( time );
-}
-
-int Hes_Emu::cpu_done()
-{
-	check( time() >= end_time() ||
-			(!(r.status & i_flag_mask) && time() >= irq_time()) );
-
-	if ( !(r.status & i_flag_mask) )
-	{
-		hes_time_t present = time();
-
-		if ( irq.timer <= present && !(irq.disables & timer_mask) )
-		{
-			timer.fired = true;
-			irq.timer = future_hes_time;
-			irq_changed(); // overkill, but not worth writing custom code
-			#if GME_FRAME_HOOK_DEFINED
-			{
-				unsigned const threshold = period_60hz / 30;
-				unsigned long elapsed = present - last_frame_hook;
-				if ( elapsed - period_60hz + threshold / 2 < threshold )
-				{
-					last_frame_hook = present;
-					GME_FRAME_HOOK( this );
-				}
-			}
-			#endif
-			return 0x0A;
-		}
-
-		if ( irq.vdp <= present && !(irq.disables & vdp_mask) )
-		{
-			// work around for bugs with music not acknowledging VDP
-			//run_until( present );
-			//irq.vdp = future_hes_time;
-			//irq_changed();
-			#if GME_FRAME_HOOK_DEFINED
-				last_frame_hook = present;
-				GME_FRAME_HOOK( this );
-			#endif
-			return 0x08;
-		}
-	}
-	return 0;
-}
-
-static void adjust_time( blargg_long& time, hes_time_t delta )
-{
-	if ( time < future_hes_time )
-	{
-		time -= delta;
-		if ( time < 0 )
-			time = 0;
-	}
-}
-
-blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
-{
-	blip_time_t const duration = duration_; // cache
-
-	if ( cpu::run( duration ) )
-		set_warning( "Emulation error (illegal instruction)" );
-
-	check( time() >= duration );
-	//check( time() - duration < 20 ); // Txx instruction could cause going way over
-
-	run_until( duration );
-
-	// end time frame
-	timer.last_time -= duration;
-	vdp.next_vbl    -= duration;
-	#if GME_FRAME_HOOK_DEFINED
-		last_frame_hook -= duration;
-	#endif
-	cpu::end_frame( duration );
-	::adjust_time( irq.timer, duration );
-	::adjust_time( irq.vdp,   duration );
-	apu.end_frame( duration );
-
-	return 0;
-}
diff --git a/src/console/Kss_Cpu.cc b/src/console/Kss_Cpu.cc
new file mode 100644
index 000000000000..0f397e1fc4bb
--- /dev/null
+++ b/src/console/Kss_Cpu.cc
@@ -0,0 +1,1704 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+/*
+Last validated with zexall 2006.11.14 2:19 PM
+* Doesn't implement the R register or immediate interrupt after EI.
+* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
+*/
+
+#include "Kss_Cpu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+//#include "z80_cpu_log.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#define SYNC_TIME()     (void) (s.time = s_time)
+#define RELOAD_TIME()   (void) (s_time = s.time)
+
+// Callbacks to emulator
+
+#define CPU_OUT( cpu, addr, data, time )\
+	kss_cpu_out( this, time, addr, data )
+
+#define CPU_IN( cpu, addr, time )\
+	kss_cpu_in( this, time, addr )
+
+#define CPU_WRITE( cpu, addr, data, time )\
+	(SYNC_TIME(), kss_cpu_write( this, addr, data ))
+
+#include "blargg_source.h"
+
+// flags, named with hex value for clarity
+int const S80 = 0x80;
+int const Z40 = 0x40;
+int const F20 = 0x20;
+int const H10 = 0x10;
+int const F08 = 0x08;
+int const V04 = 0x04;
+int const P04 = 0x04;
+int const N02 = 0x02;
+int const C01 = 0x01;
+
+#define SZ28P( n )  szpc [n]
+#define SZ28PC( n ) szpc [n]
+#define SZ28C( n )  (szpc [n] & ~P04)
+#define SZ28( n )   SZ28C( n )
+
+#define SET_R( n )  (void) (r.r = n)
+#define GET_R()     (r.r)
+
+Kss_Cpu::Kss_Cpu()
+{
+	state = &state_;
+
+	for ( int i = 0x100; --i >= 0; )
+	{
+		int even = 1;
+		for ( int p = i; p; p >>= 1 )
+			even ^= p;
+		int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
+		szpc [i] = n;
+		szpc [i + 0x100] = n | C01;
+	}
+	szpc [0x000] |= Z40;
+	szpc [0x100] |= Z40;
+}
+
+inline void Kss_Cpu::set_page( int i, void* write, void const* read )
+{
+	blargg_long offset = KSS_CPU_PAGE_OFFSET( i * (blargg_long) page_size );
+	state->write [i] = (byte      *) write - offset;
+	state->read  [i] = (byte const*) read  - offset;
+}
+
+void Kss_Cpu::reset( void* unmapped_write, void const* unmapped_read )
+{
+	check( state == &state_ );
+	state = &state_;
+	state_.time = 0;
+	state_.base = 0;
+	end_time_   = 0;
+
+	for ( int i = 0; i < page_count + 1; i++ )
+		set_page( i, unmapped_write, unmapped_read );
+
+	memset( &r, 0, sizeof r );
+}
+
+void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const* read )
+{
+	// address range must begin and end on page boundaries
+	require( addr % page_size == 0 );
+	require( size % page_size == 0 );
+
+	unsigned first_page = addr / page_size;
+	for ( unsigned i = size / page_size; i--; )
+	{
+		blargg_long offset = i * (blargg_long) page_size;
+		set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset );
+	}
+}
+
+#define TIME                        (s_time + s.base)
+#define RW_MEM( addr, rw )          (s.rw [(addr) >> page_shift] [KSS_CPU_PAGE_OFFSET( addr )])
+#define READ_PROG( addr )           RW_MEM( addr, read )
+#define READ( addr )                READ_PROG( addr )
+//#define WRITE( addr, data )       (void) (RW_MEM( addr, write ) = data)
+#define WRITE( addr, data )         CPU_WRITE( this, addr, data, TIME )
+#define READ_WORD( addr )           GET_LE16( &READ( addr ) )
+#define WRITE_WORD( addr, data )    SET_LE16( &RW_MEM( addr, write ), data )
+#define IN( addr )                  CPU_IN( this, addr, TIME )
+#define OUT( addr, data )           CPU_OUT( this, addr, data, TIME )
+
+#if BLARGG_BIG_ENDIAN
+	#define R8( n, offset ) ((r8_ - offset) [n])
+#elif BLARGG_LITTLE_ENDIAN
+	#define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
+#else
+	#error "Byte order of CPU must be known"
+#endif
+
+//#define R16( n, shift, offset )   (r16_ [((n) >> shift) - (offset >> shift)])
+
+// help compiler see that it can just adjust stack offset, saving an extra instruction
+#define R16( n, shift, offset )\
+	(*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
+
+#define CASE5( a, b, c, d, e          ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
+#define CASE6( a, b, c, d, e, f       ) CASE5( a, b, c, d, e       ): case 0x##f
+#define CASE7( a, b, c, d, e, f, g    ) CASE6( a, b, c, d, e, f    ): case 0x##g
+#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
+
+// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
+static byte const ed_dd_timing [0x100] = {
+//0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
+0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
+0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
+0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+// even on x86, using short and unsigned char was slower
+typedef int         fint16;
+typedef unsigned    fuint16;
+typedef unsigned    fuint8;
+
+bool Kss_Cpu::run( cpu_time_t end_time )
+{
+	set_end_time( end_time );
+	state_t s = this->state_;
+	this->state = &s;
+	bool warning = false;
+
+	typedef int8_t int8_t;
+
+	union {
+		regs_t rg;
+		pairs_t rp;
+		uint8_t r8_ [8]; // indexed
+		uint16_t r16_ [4];
+	};
+	rg = this->r.b;
+
+	cpu_time_t s_time = s.time;
+	fuint16 pc = r.pc;
+	fuint16 sp = r.sp;
+	fuint16 ix = r.ix; // TODO: keep in memory for direct access?
+	fuint16 iy = r.iy;
+	int flags = r.b.flags;
+
+	goto loop;
+jr_not_taken:
+	s_time -= 5;
+	goto loop;
+call_not_taken:
+	s_time -= 7;
+jp_not_taken:
+	pc += 2;
+loop:
+
+	check( (unsigned long) pc < 0x10000 );
+	check( (unsigned long) sp < 0x10000 );
+	check( (unsigned) flags < 0x100 );
+	check( (unsigned) ix < 0x10000 );
+	check( (unsigned) iy < 0x10000 );
+
+	uint8_t const* instr = s.read [pc >> page_shift];
+#define GET_ADDR()  GET_LE16( instr )
+
+	fuint8 opcode;
+
+	// TODO: eliminate this special case
+	#if BLARGG_NONPORTABLE
+		opcode = instr [pc];
+		pc++;
+		instr += pc;
+	#else
+		instr += KSS_CPU_PAGE_OFFSET( pc );
+		opcode = *instr++;
+		pc++;
+	#endif
+
+	static byte const base_timing [0x100] = {
+	//   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
+		 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
+		13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
+		12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
+		12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
+		 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
+		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
+		11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
+		11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
+		11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
+		11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
+	};
+
+	fuint16 data;
+	data = base_timing [opcode];
+	if ( (s_time += data) >= 0 )
+		goto possibly_out_of_time;
+almost_out_of_time:
+
+	data = READ_PROG( pc );
+
+	#ifdef Z80_CPU_LOG_H
+		//log_opcode( opcode, READ_PROG( pc ) );
+		z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
+		z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
+				READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
+	#endif
+
+	switch ( opcode )
+	{
+possibly_out_of_time:
+		if ( s_time < (int) data )
+			goto almost_out_of_time;
+		s_time -= data;
+		goto out_of_time;
+
+// Common
+
+	case 0x00: // NOP
+	CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
+		goto loop;
+
+	case 0x08:{// EX AF,AF'
+		int temp = r.alt.b.a;
+		r.alt.b.a = rg.a;
+		rg.a = temp;
+
+		temp = r.alt.b.flags;
+		r.alt.b.flags = flags;
+		flags = temp;
+		goto loop;
+	}
+
+	case 0xD3: // OUT (imm),A
+		pc++;
+		OUT( data + rg.a * 0x100, rg.a );
+		goto loop;
+
+	case 0x2E: // LD L,imm
+		pc++;
+		rg.l = data;
+		goto loop;
+
+	case 0x3E: // LD A,imm
+		pc++;
+		rg.a = data;
+		goto loop;
+
+	case 0x3A:{// LD A,(addr)
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		rg.a = READ( addr );
+		goto loop;
+	}
+
+// Conditional
+
+#define ZERO    (flags & Z40)
+#define CARRY   (flags & C01)
+#define EVEN    (flags & P04)
+#define MINUS   (flags & S80)
+
+// JR
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define JR( cond ) {\
+	int offset = (int8_t) data;\
+	pc++;\
+	if ( !(cond) )\
+		goto jr_not_taken;\
+	pc = uint16_t (pc + offset);\
+	goto loop;\
+}
+
+	case 0x20: JR( !ZERO  ) // JR NZ,disp
+	case 0x28: JR(  ZERO  ) // JR Z,disp
+	case 0x30: JR( !CARRY ) // JR NC,disp
+	case 0x38: JR(  CARRY ) // JR C,disp
+	case 0x18: JR(  true  ) // JR disp
+
+	case 0x10:{// DJNZ disp
+		int temp = rg.b - 1;
+		rg.b = temp;
+		JR( temp )
+	}
+
+// JP
+#define JP( cond )  if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
+
+	case 0xC2: JP( !ZERO  ) // JP NZ,addr
+	case 0xCA: JP(  ZERO  ) // JP Z,addr
+	case 0xD2: JP( !CARRY ) // JP NC,addr
+	case 0xDA: JP(  CARRY ) // JP C,addr
+	case 0xE2: JP( !EVEN  ) // JP PO,addr
+	case 0xEA: JP(  EVEN  ) // JP PE,addr
+	case 0xF2: JP( !MINUS ) // JP P,addr
+	case 0xFA: JP(  MINUS ) // JP M,addr
+
+	case 0xC3: // JP addr
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xE9: // JP HL
+		pc = rp.hl;
+		goto loop;
+
+// RET
+#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
+
+	case 0xC0: RET( !ZERO  ) // RET NZ
+	case 0xC8: RET(  ZERO  ) // RET Z
+	case 0xD0: RET( !CARRY ) // RET NC
+	case 0xD8: RET(  CARRY ) // RET C
+	case 0xE0: RET( !EVEN  ) // RET PO
+	case 0xE8: RET(  EVEN  ) // RET PE
+	case 0xF0: RET( !MINUS ) // RET P
+	case 0xF8: RET(  MINUS ) // RET M
+
+	case 0xC9: // RET
+	ret_taken:
+		pc = READ_WORD( sp );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+// CALL
+#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
+
+	case 0xC4: CALL( !ZERO  ) // CALL NZ,addr
+	case 0xCC: CALL(  ZERO  ) // CALL Z,addr
+	case 0xD4: CALL( !CARRY ) // CALL NC,addr
+	case 0xDC: CALL(  CARRY ) // CALL C,addr
+	case 0xE4: CALL( !EVEN  ) // CALL PO,addr
+	case 0xEC: CALL(  EVEN  ) // CALL PE,addr
+	case 0xF4: CALL( !MINUS ) // CALL P,addr
+	case 0xFC: CALL(  MINUS ) // CALL M,addr
+
+	case 0xCD:{// CALL addr
+	call_taken:
+		fuint16 addr = pc + 2;
+		pc = GET_ADDR();
+		sp = uint16_t (sp - 2);
+		WRITE_WORD( sp, addr );
+		goto loop;
+	}
+
+	case 0xFF: // RST
+		if ( pc > idle_addr )
+			goto hit_idle_addr;
+	CASE7( C7, CF, D7, DF, E7, EF, F7 ):
+		data = pc;
+		pc = opcode & 0x38;
+		goto push_data;
+
+// PUSH/POP
+	case 0xF5: // PUSH AF
+		data = rg.a * 0x100u + flags;
+		goto push_data;
+
+	case 0xC5: // PUSH BC
+	case 0xD5: // PUSH DE
+	case 0xE5: // PUSH HL
+		data = R16( opcode, 4, 0xC5 );
+	push_data:
+		sp = uint16_t (sp - 2);
+		WRITE_WORD( sp, data );
+		goto loop;
+
+	case 0xF1: // POP AF
+		flags = READ( sp );
+		rg.a = READ( sp + 1 );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+	case 0xC1: // POP BC
+	case 0xD1: // POP DE
+	case 0xE1: // POP HL
+		R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
+		sp = uint16_t (sp + 2);
+		goto loop;
+
+// ADC/ADD/SBC/SUB
+	case 0x96: // SUB (HL)
+	case 0x86: // ADD (HL)
+		flags &= ~C01;
+	case 0x9E: // SBC (HL)
+	case 0x8E: // ADC (HL)
+		data = READ( rp.hl );
+		goto adc_data;
+
+	case 0xD6: // SUB A,imm
+	case 0xC6: // ADD imm
+		flags &= ~C01;
+	case 0xDE: // SBC A,imm
+	case 0xCE: // ADC imm
+		pc++;
+		goto adc_data;
+
+	CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
+	CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
+		flags &= ~C01;
+	CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
+	CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
+		data = R8( opcode & 7, 0 );
+	adc_data: {
+		int result = data + (flags & C01);
+		data ^= rg.a;
+		flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
+		if ( flags )
+			result = -result;
+		result += rg.a;
+		data ^= result;
+		flags |=(data & H10) |
+				((data - -0x80) >> 6 & V04) |
+				SZ28C( result & 0x1FF );
+		rg.a = result;
+		goto loop;
+	}
+
+// CP
+	case 0xBE: // CP (HL)
+		data = READ( rp.hl );
+		goto cp_data;
+
+	case 0xFE: // CP imm
+		pc++;
+		goto cp_data;
+
+	CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
+		data = R8( opcode, 0xB8 );
+	cp_data: {
+		int result = rg.a - data;
+		flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
+		data ^= rg.a;
+		flags |=(((result ^ rg.a) & data) >> 5 & V04) |
+				(((data & H10) ^ result) & (S80 | H10));
+		if ( (uint8_t) result )
+			goto loop;
+		flags |= Z40;
+		goto loop;
+	}
+
+// ADD HL,rp
+
+	case 0x39: // ADD HL,SP
+		data = sp;
+		goto add_hl_data;
+
+	case 0x09: // ADD HL,BC
+	case 0x19: // ADD HL,DE
+	case 0x29: // ADD HL,HL
+		data = R16( opcode, 4, 0x09 );
+	add_hl_data: {
+		blargg_ulong sum = rp.hl + data;
+		data ^= rp.hl;
+		rp.hl = sum;
+		flags = (flags & (S80 | Z40 | V04)) |
+				(sum >> 16) |
+				(sum >> 8 & (F20 | F08)) |
+				((data ^ sum) >> 8 & H10);
+		goto loop;
+	}
+
+	case 0x27:{// DAA
+		int a = rg.a;
+		if ( a > 0x99 )
+			flags |= C01;
+
+		int adjust = 0x60 & -(flags & C01);
+
+		if ( flags & H10 || (a & 0x0F) > 9 )
+			adjust |= 0x06;
+
+		if ( flags & N02 )
+			adjust = -adjust;
+		a += adjust;
+
+		flags = (flags & (C01 | N02)) |
+				((rg.a ^ a) & H10) |
+				SZ28P( (uint8_t) a );
+		rg.a = a;
+		goto loop;
+	}
+	/*
+	case 0x27:{// DAA
+		// more optimized, but probably not worth the obscurity
+		int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
+		int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
+
+		if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
+			adjust |= 0x06;
+
+		if ( f & N02 )
+			adjust = -adjust;
+		int a = rg.a + adjust;
+
+		flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
+		rg.a = a;
+		goto loop;
+	}
+	*/
+
+// INC/DEC
+	case 0x34: // INC (HL)
+		data = READ( rp.hl ) + 1;
+		WRITE( rp.hl, data );
+		goto inc_set_flags;
+
+	CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
+		data = ++R8( opcode >> 3, 0 );
+	inc_set_flags:
+		flags = (flags & C01) |
+				(((data & 0x0F) - 1) & H10) |
+				SZ28( (uint8_t) data );
+		if ( data != 0x80 )
+			goto loop;
+		flags |= V04;
+		goto loop;
+
+	case 0x35: // DEC (HL)
+		data = READ( rp.hl ) - 1;
+		WRITE( rp.hl, data );
+		goto dec_set_flags;
+
+	CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
+		data = --R8( opcode >> 3, 0 );
+	dec_set_flags:
+		flags = (flags & C01) | N02 |
+				(((data & 0x0F) + 1) & H10) |
+				SZ28( (uint8_t) data );
+		if ( data != 0x7F )
+			goto loop;
+		flags |= V04;
+		goto loop;
+
+	case 0x03: // INC BC
+	case 0x13: // INC DE
+	case 0x23: // INC HL
+		R16( opcode, 4, 0x03 )++;
+		goto loop;
+
+	case 0x33: // INC SP
+		sp = uint16_t (sp + 1);
+		goto loop;
+
+	case 0x0B: // DEC BC
+	case 0x1B: // DEC DE
+	case 0x2B: // DEC HL
+		R16( opcode, 4, 0x0B )--;
+		goto loop;
+
+	case 0x3B: // DEC SP
+		sp = uint16_t (sp - 1);
+		goto loop;
+
+// AND
+	case 0xA6: // AND (HL)
+		data = READ( rp.hl );
+		goto and_data;
+
+	case 0xE6: // AND imm
+		pc++;
+		goto and_data;
+
+	CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
+		data = R8( opcode, 0xA0 );
+	and_data:
+		rg.a &= data;
+		flags = SZ28P( rg.a ) | H10;
+		goto loop;
+
+// OR
+	case 0xB6: // OR (HL)
+		data = READ( rp.hl );
+		goto or_data;
+
+	case 0xF6: // OR imm
+		pc++;
+		goto or_data;
+
+	CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
+		data = R8( opcode, 0xB0 );
+	or_data:
+		rg.a |= data;
+		flags = SZ28P( rg.a );
+		goto loop;
+
+// XOR
+	case 0xAE: // XOR (HL)
+		data = READ( rp.hl );
+		goto xor_data;
+
+	case 0xEE: // XOR imm
+		pc++;
+		goto xor_data;
+
+	CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
+		data = R8( opcode, 0xA8 );
+	xor_data:
+		rg.a ^= data;
+		flags = SZ28P( rg.a );
+		goto loop;
+
+// LD
+	CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
+		WRITE( rp.hl, R8( opcode, 0x70 ) );
+		goto loop;
+
+	CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
+	CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
+	CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
+	CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
+	CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
+	CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
+	CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
+		R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
+		goto loop;
+
+	CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
+		R8( opcode >> 3, 0 ) = data;
+		pc++;
+		goto loop;
+
+	case 0x36: // LD (HL),imm
+		pc++;
+		WRITE( rp.hl, data );
+		goto loop;
+
+	CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
+		R8( opcode >> 3, 8 ) = READ( rp.hl );
+		goto loop;
+
+	case 0x01: // LD rp,imm
+	case 0x11:
+	case 0x21:
+		R16( opcode, 4, 0x01 ) = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x31: // LD sp,imm
+		sp = GET_ADDR();
+		pc += 2;
+		goto loop;
+
+	case 0x2A:{// LD HL,(addr)
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		rp.hl = READ_WORD( addr );
+		goto loop;
+	}
+
+	case 0x32:{// LD (addr),A
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		WRITE( addr, rg.a );
+		goto loop;
+	}
+
+	case 0x22:{// LD (addr),HL
+		fuint16 addr = GET_ADDR();
+		pc += 2;
+		WRITE_WORD( addr, rp.hl );
+		goto loop;
+	}
+
+	case 0x02: // LD (BC),A
+	case 0x12: // LD (DE),A
+		WRITE( R16( opcode, 4, 0x02 ), rg.a );
+		goto loop;
+
+	case 0x0A: // LD A,(BC)
+	case 0x1A: // LD A,(DE)
+		rg.a = READ( R16( opcode, 4, 0x0A ) );
+		goto loop;
+
+	case 0xF9: // LD SP,HL
+		sp = rp.hl;
+		goto loop;
+
+// Rotate
+
+	case 0x07:{// RLCA
+		fuint16 temp = rg.a;
+		temp = (temp << 1) | (temp >> 7);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08 | C01));
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x0F:{// RRCA
+		fuint16 temp = rg.a;
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & C01);
+		temp = (temp << 7) | (temp >> 1);
+		flags |= temp & (F20 | F08);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x17:{// RLA
+		blargg_ulong temp = (rg.a << 1) | (flags & C01);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08)) |
+				(temp >> 8);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x1F:{// RRA
+		fuint16 temp = (flags << 7) | (rg.a >> 1);
+		flags = (flags & (S80 | Z40 | P04)) |
+				(temp & (F20 | F08)) |
+				(rg.a & C01);
+		rg.a = temp;
+		goto loop;
+	}
+
+// Misc
+	case 0x2F:{// CPL
+		fuint16 temp = ~rg.a;
+		flags = (flags & (S80 | Z40 | P04 | C01)) |
+				(temp & (F20 | F08)) |
+				(H10 | N02);
+		rg.a = temp;
+		goto loop;
+	}
+
+	case 0x3F:{// CCF
+		flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
+				(flags << 4 & H10) |
+				(rg.a & (F20 | F08));
+		goto loop;
+	}
+
+	case 0x37: // SCF
+		flags = (flags & (S80 | Z40 | P04)) | C01 |
+				(rg.a & (F20 | F08));
+		goto loop;
+
+	case 0xDB: // IN A,(imm)
+		pc++;
+		rg.a = IN( data + rg.a * 0x100 );
+		goto loop;
+
+	case 0xE3:{// EX (SP),HL
+		fuint16 temp = READ_WORD( sp );
+		WRITE_WORD( sp, rp.hl );
+		rp.hl = temp;
+		goto loop;
+	}
+
+	case 0xEB:{// EX DE,HL
+		fuint16 temp = rp.hl;
+		rp.hl = rp.de;
+		rp.de = temp;
+		goto loop;
+	}
+
+	case 0xD9:{// EXX DE,HL
+		fuint16 temp = r.alt.w.bc;
+		r.alt.w.bc = rp.bc;
+		rp.bc = temp;
+
+		temp = r.alt.w.de;
+		r.alt.w.de = rp.de;
+		rp.de = temp;
+
+		temp = r.alt.w.hl;
+		r.alt.w.hl = rp.hl;
+		rp.hl = temp;
+		goto loop;
+	}
+
+	case 0xF3: // DI
+		r.iff1 = 0;
+		r.iff2 = 0;
+		goto loop;
+
+	case 0xFB: // EI
+		r.iff1 = 1;
+		r.iff2 = 1;
+		// TODO: delayed effect
+		goto loop;
+
+	case 0x76: // HALT
+		goto halt;
+
+//////////////////////////////////////// CB prefix
+	{
+	case 0xCB:
+		pc++;
+		switch ( data )
+		{
+
+	// Rotate left
+
+	#define RLC( read, write ) {\
+		fuint8 result = read;\
+		result = uint8_t (result << 1) | (result >> 7);\
+		flags = SZ28P( result ) | (result & C01);\
+		write;\
+		goto loop;\
+	}
+
+		case 0x06: // RLC (HL)
+			s_time += 7;
+			data = rp.hl;
+		rlc_data_addr:
+			RLC( READ( data ), WRITE( data, result ) )
+
+		CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
+			uint8_t& reg = R8( data, 0 );
+			RLC( reg, reg = result )
+		}
+
+	#define RL( read, write ) {\
+		fuint16 result = (read << 1) | (flags & C01);\
+		flags = SZ28PC( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x16: // RL (HL)
+			s_time += 7;
+			data = rp.hl;
+		rl_data_addr:
+			RL( READ( data ), WRITE( data, result ) )
+
+		CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
+			uint8_t& reg = R8( data, 0x10 );
+			RL( reg, reg = result )
+		}
+
+	#define SLA( read, add, write ) {\
+		fuint16 result = (read << 1) | add;\
+		flags = SZ28PC( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x26: // SLA (HL)
+			s_time += 7;
+			data = rp.hl;
+		sla_data_addr:
+			SLA( READ( data ), 0, WRITE( data, result ) )
+
+		CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
+			uint8_t& reg = R8( data, 0x20 );
+			SLA( reg, 0, reg = result )
+		}
+
+		case 0x36: // SLL (HL)
+			s_time += 7;
+			data = rp.hl;
+		sll_data_addr:
+			SLA( READ( data ), 1, WRITE( data, result ) )
+
+		CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
+			uint8_t& reg = R8( data, 0x30 );
+			SLA( reg, 1, reg = result )
+		}
+
+	// Rotate right
+
+	#define RRC( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result = uint8_t (result << 7) | (result >> 1);\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x0E: // RRC (HL)
+			s_time += 7;
+			data = rp.hl;
+		rrc_data_addr:
+			RRC( READ( data ), WRITE( data, result ) )
+
+		CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
+			uint8_t& reg = R8( data, 0x08 );
+			RRC( reg, reg = result )
+		}
+
+	#define RR( read, write ) {\
+		fuint8 result = read;\
+		fuint8 temp = result & C01;\
+		result = uint8_t (flags << 7) | (result >> 1);\
+		flags = SZ28P( result ) | temp;\
+		write;\
+		goto loop;\
+	}
+
+		case 0x1E: // RR (HL)
+			s_time += 7;
+			data = rp.hl;
+		rr_data_addr:
+			RR( READ( data ), WRITE( data, result ) )
+
+		CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
+			uint8_t& reg = R8( data, 0x18 );
+			RR( reg, reg = result )
+		}
+
+	#define SRA( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result = (result & 0x80) | (result >> 1);\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x2E: // SRA (HL)
+			data = rp.hl;
+			s_time += 7;
+		sra_data_addr:
+			SRA( READ( data ), WRITE( data, result ) )
+
+		CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
+			uint8_t& reg = R8( data, 0x28 );
+			SRA( reg, reg = result )
+		}
+
+	#define SRL( read, write ) {\
+		fuint8 result = read;\
+		flags = result & C01;\
+		result >>= 1;\
+		flags |= SZ28P( result );\
+		write;\
+		goto loop;\
+	}
+
+		case 0x3E: // SRL (HL)
+			s_time += 7;
+			data = rp.hl;
+		srl_data_addr:
+			SRL( READ( data ), WRITE( data, result ) )
+
+		CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
+			uint8_t& reg = R8( data, 0x38 );
+			SRL( reg, reg = result )
+		}
+
+	// BIT
+		{
+			unsigned temp;
+		CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
+			s_time += 4;
+			temp = READ( rp.hl );
+			flags &= C01;
+			goto bit_temp;
+		CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
+		CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
+		CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
+		CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
+		CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
+		CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
+		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
+		CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
+			temp = R8( data & 7, 0 );
+			flags = (flags & C01) | (temp & (F20 | F08));
+		bit_temp:
+			int masked = temp & 1 << (data >> 3 & 7);
+			flags |=(masked & S80) | H10 |
+					((masked - 1) >> 8 & (Z40 | P04));
+			goto loop;
+		}
+
+	// SET/RES
+		CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
+		CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
+			s_time += 7;
+			int temp = READ( rp.hl );
+			int bit = 1 << (data >> 3 & 7);
+			temp |= bit; // SET
+			if ( !(data & 0x40) )
+				temp ^= bit; // RES
+			WRITE( rp.hl, temp );
+			goto loop;
+		}
+
+		CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
+		CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
+		CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
+		CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
+		CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
+		CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
+		CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
+		CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
+			R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
+			goto loop;
+
+		CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
+		CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
+		CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
+		CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
+		CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
+		CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
+		CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
+		CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
+			R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
+			goto loop;
+		}
+		assert( false );
+	}
+
+#undef GET_ADDR
+#define GET_ADDR()  GET_LE16( instr + 1 )
+
+//////////////////////////////////////// ED prefix
+	{
+	case 0xED:
+		pc++;
+		s_time += ed_dd_timing [data] >> 4;
+		switch ( data )
+		{
+		{
+			blargg_ulong temp;
+		case 0x72: // SBC HL,SP
+		case 0x7A: // ADC HL,SP
+			temp = sp;
+			if ( 0 )
+		case 0x42: // SBC HL,BC
+		case 0x52: // SBC HL,DE
+		case 0x62: // SBC HL,HL
+		case 0x4A: // ADC HL,BC
+		case 0x5A: // ADC HL,DE
+		case 0x6A: // ADC HL,HL
+				temp = R16( data >> 3 & 6, 1, 0 );
+			blargg_ulong sum = temp + (flags & C01);
+			flags = ~data >> 2 & N02;
+			if ( flags )
+				sum = -sum;
+			sum += rp.hl;
+			temp ^= rp.hl;
+			temp ^= sum;
+			flags |=(sum >> 16 & C01) |
+					(temp >> 8 & H10) |
+					(sum >> 8 & (S80 | F20 | F08)) |
+					((temp - -0x8000) >> 14 & V04);
+			rp.hl = sum;
+			if ( (uint16_t) sum )
+				goto loop;
+			flags |= Z40;
+			goto loop;
+		}
+
+		CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
+			int temp = IN( rp.bc );
+			R8( data >> 3, 8 ) = temp;
+			flags = (flags & C01) | SZ28P( temp );
+			goto loop;
+		}
+
+		case 0x71: // OUT (C),0
+			rg.flags = 0;
+		CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
+			OUT( rp.bc, R8( data >> 3, 8 ) );
+			goto loop;
+
+		{
+			unsigned temp;
+		case 0x73: // LD (ADDR),SP
+			temp = sp;
+			if ( 0 )
+		case 0x43: // LD (ADDR),BC
+		case 0x53: // LD (ADDR),DE
+				temp = R16( data, 4, 0x43 );
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			WRITE_WORD( addr, temp );
+			goto loop;
+		}
+
+		case 0x4B: // LD BC,(ADDR)
+		case 0x5B:{// LD DE,(ADDR)
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			R16( data, 4, 0x4B ) = READ_WORD( addr );
+			goto loop;
+		}
+
+		case 0x7B:{// LD SP,(ADDR)
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			sp = READ_WORD( addr );
+			goto loop;
+		}
+
+		case 0x67:{// RRD
+			fuint8 temp = READ( rp.hl );
+			WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
+			temp = (rg.a & 0xF0) | (temp & 0x0F);
+			flags = (flags & C01) | SZ28P( temp );
+			rg.a = temp;
+			goto loop;
+		}
+
+		case 0x6F:{// RLD
+			fuint8 temp = READ( rp.hl );
+			WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
+			temp = (rg.a & 0xF0) | (temp >> 4);
+			flags = (flags & C01) | SZ28P( temp );
+			rg.a = temp;
+			goto loop;
+		}
+
+		CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
+			opcode = 0x10; // flag to do SBC instead of ADC
+			flags &= ~C01;
+			data = rg.a;
+			rg.a = 0;
+			goto adc_data;
+
+		{
+			int inc;
+		case 0xA9: // CPD
+		case 0xB9: // CPDR
+			inc = -1;
+			if ( 0 )
+		case 0xA1: // CPI
+		case 0xB1: // CPIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			int result = rg.a - temp;
+			flags = (flags & C01) | N02 |
+					((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
+
+			if ( !(uint8_t) result ) flags |= Z40;
+			result -= (flags & H10) >> 4;
+			flags |= result & F08;
+			flags |= result << 4 & F20;
+			if ( !--rp.bc )
+				goto loop;
+
+			flags |= V04;
+			if ( flags & Z40 || data < 0xB0 )
+				goto loop;
+
+			pc -= 2;
+			s_time += 5;
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xA8: // LDD
+		case 0xB8: // LDDR
+			inc = -1;
+			if ( 0 )
+		case 0xA0: // LDI
+		case 0xB0: // LDIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			addr = rp.de;
+			rp.de = addr + inc;
+			WRITE( addr, temp );
+
+			temp += rg.a;
+			flags = (flags & (S80 | Z40 | C01)) |
+					(temp & F08) | (temp << 4 & F20);
+			if ( !--rp.bc )
+				goto loop;
+
+			flags |= V04;
+			if ( data < 0xB0 )
+				goto loop;
+
+			pc -= 2;
+			s_time += 5;
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xAB: // OUTD
+		case 0xBB: // OTDR
+			inc = -1;
+			if ( 0 )
+		case 0xA3: // OUTI
+		case 0xB3: // OTIR
+				inc = +1;
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+			int temp = READ( addr );
+
+			int b = --rg.b;
+			flags = (temp >> 6 & N02) | SZ28( b );
+			if ( b && data >= 0xB0 )
+			{
+				pc -= 2;
+				s_time += 5;
+			}
+
+			OUT( rp.bc, temp );
+			goto loop;
+		}
+
+		{
+			int inc;
+		case 0xAA: // IND
+		case 0xBA: // INDR
+			inc = -1;
+			if ( 0 )
+		case 0xA2: // INI
+		case 0xB2: // INIR
+				inc = +1;
+
+			fuint16 addr = rp.hl;
+			rp.hl = addr + inc;
+
+			int temp = IN( rp.bc );
+
+			int b = --rg.b;
+			flags = (temp >> 6 & N02) | SZ28( b );
+			if ( b && data >= 0xB0 )
+			{
+				pc -= 2;
+				s_time += 5;
+			}
+
+			WRITE( addr, temp );
+			goto loop;
+		}
+
+		case 0x47: // LD I,A
+			r.i = rg.a;
+			goto loop;
+
+		case 0x4F: // LD R,A
+			SET_R( rg.a );
+			debug_printf( "LD R,A not supported\n" );
+			warning = true;
+			goto loop;
+
+		case 0x57: // LD A,I
+			rg.a = r.i;
+			goto ld_ai_common;
+
+		case 0x5F: // LD A,R
+			rg.a = GET_R();
+			debug_printf( "LD A,R not supported\n" );
+			warning = true;
+		ld_ai_common:
+			flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
+			goto loop;
+
+		CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
+			r.iff1 = r.iff2;
+			goto ret_taken;
+
+		case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
+			r.im = 0;
+			goto loop;
+
+		case 0x56: case 0x76: // IM 1
+			r.im = 1;
+			goto loop;
+
+		case 0x5E: case 0x7E: // IM 2
+			r.im = 2;
+			goto loop;
+
+		default:
+			debug_printf( "Opcode $ED $%02X not supported\n", data );
+			warning = true;
+			goto loop;
+		}
+		assert( false );
+	}
+
+//////////////////////////////////////// DD/FD prefix
+	{
+	fuint16 ixy;
+	case 0xDD:
+		ixy = ix;
+		goto ix_prefix;
+	case 0xFD:
+		ixy = iy;
+	ix_prefix:
+		pc++;
+		unsigned data2 = READ_PROG( pc );
+		s_time += ed_dd_timing [data] & 0x0F;
+		switch ( data )
+		{
+	// TODO: more efficient way of avoid negative address
+	// TODO: avoid using this as argument to READ() since it is evaluated twice
+	#define IXY_DISP( ixy, disp )   uint16_t ((ixy) + (disp))
+
+	#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
+
+	// ADD/ADC/SUB/SBC
+
+		case 0x96: // SUB (IXY+disp)
+		case 0x86: // ADD (IXY+disp)
+			flags &= ~C01;
+		case 0x9E: // SBC (IXY+disp)
+		case 0x8E: // ADC (IXY+disp)
+			pc++;
+			opcode = data;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto adc_data;
+
+		case 0x94: // SUB HXY
+		case 0x84: // ADD HXY
+			flags &= ~C01;
+		case 0x9C: // SBC HXY
+		case 0x8C: // ADC HXY
+			opcode = data;
+			data = ixy >> 8;
+			goto adc_data;
+
+		case 0x95: // SUB LXY
+		case 0x85: // ADD LXY
+			flags &= ~C01;
+		case 0x9D: // SBC LXY
+		case 0x8D: // ADC LXY
+			opcode = data;
+			data = (uint8_t) ixy;
+			goto adc_data;
+
+		{
+			unsigned temp;
+		case 0x39: // ADD IXY,SP
+			temp = sp;
+			goto add_ixy_data;
+
+		case 0x29: // ADD IXY,HL
+			temp = ixy;
+			goto add_ixy_data;
+
+		case 0x09: // ADD IXY,BC
+		case 0x19: // ADD IXY,DE
+			temp = R16( data, 4, 0x09 );
+		add_ixy_data: {
+			blargg_ulong sum = ixy + temp;
+			temp ^= ixy;
+			ixy = (uint16_t) sum;
+			flags = (flags & (S80 | Z40 | V04)) |
+					(sum >> 16) |
+					(sum >> 8 & (F20 | F08)) |
+					((temp ^ sum) >> 8 & H10);
+			goto set_ixy;
+		}
+		}
+
+	// AND
+		case 0xA6: // AND (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto and_data;
+
+		case 0xA4: // AND HXY
+			data = ixy >> 8;
+			goto and_data;
+
+		case 0xA5: // AND LXY
+			data = (uint8_t) ixy;
+			goto and_data;
+
+	// OR
+		case 0xB6: // OR (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto or_data;
+
+		case 0xB4: // OR HXY
+			data = ixy >> 8;
+			goto or_data;
+
+		case 0xB5: // OR LXY
+			data = (uint8_t) ixy;
+			goto or_data;
+
+	// XOR
+		case 0xAE: // XOR (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto xor_data;
+
+		case 0xAC: // XOR HXY
+			data = ixy >> 8;
+			goto xor_data;
+
+		case 0xAD: // XOR LXY
+			data = (uint8_t) ixy;
+			goto xor_data;
+
+	// CP
+		case 0xBE: // CP (IXY+disp)
+			pc++;
+			data = READ( IXY_DISP( ixy, (int8_t) data2 )  );
+			goto cp_data;
+
+		case 0xBC: // CP HXY
+			data = ixy >> 8;
+			goto cp_data;
+
+		case 0xBD: // CP LXY
+			data = (uint8_t) ixy;
+			goto cp_data;
+
+	// LD
+		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
+			data = R8( data, 0x70 );
+			if ( 0 )
+		case 0x36: // LD (IXY+disp),imm
+				pc++, data = READ_PROG( pc );
+			pc++;
+			WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
+			goto loop;
+
+		CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
+			R8( data >> 3, 8 ) = ixy >> 8;
+			goto loop;
+
+		case 0x64: // LD HXY,HXY
+		case 0x6D: // LD LXY,LXY
+			goto loop;
+
+		CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
+			R8( data >> 3, 8 ) = ixy;
+			goto loop;
+
+		CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
+			pc++;
+			R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
+			goto loop;
+
+		case 0x26: // LD HXY,imm
+			pc++;
+			goto ld_hxy_data;
+
+		case 0x65: // LD HXY,LXY
+			data2 = (uint8_t) ixy;
+			goto ld_hxy_data;
+
+		CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
+			data2 = R8( data, 0x60 );
+		ld_hxy_data:
+			ixy = (uint8_t) ixy | (data2 << 8);
+			goto set_ixy;
+
+		case 0x2E: // LD LXY,imm
+			pc++;
+			goto ld_lxy_data;
+
+		case 0x6C: // LD LXY,HXY
+			data2 = ixy >> 8;
+			goto ld_lxy_data;
+
+		CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
+			data2 = R8( data, 0x68 );
+		ld_lxy_data:
+			ixy = (ixy & 0xFF00) | data2;
+		set_ixy:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto loop;
+			}
+			iy = ixy;
+			goto loop;
+
+		case 0xF9: // LD SP,IXY
+			sp = ixy;
+			goto loop;
+
+		case 0x22:{// LD (ADDR),IXY
+			fuint16 addr = GET_ADDR();
+			pc += 2;
+			WRITE_WORD( addr, ixy );
+			goto loop;
+		}
+
+		case 0x21: // LD IXY,imm
+			ixy = GET_ADDR();
+			pc += 2;
+			goto set_ixy;
+
+		case 0x2A:{// LD IXY,(addr)
+			fuint16 addr = GET_ADDR();
+			ixy = READ_WORD( addr );
+			pc += 2;
+			goto set_ixy;
+		}
+
+	// DD/FD CB prefix
+		case 0xCB: {
+			data = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data2 = READ_PROG( pc );
+			pc++;
+			switch ( data2 )
+			{
+			case 0x06: goto rlc_data_addr; // RLC (IXY)
+			case 0x16: goto rl_data_addr;  // RL (IXY)
+			case 0x26: goto sla_data_addr; // SLA (IXY)
+			case 0x36: goto sll_data_addr; // SLL (IXY)
+			case 0x0E: goto rrc_data_addr; // RRC (IXY)
+			case 0x1E: goto rr_data_addr;  // RR (IXY)
+			case 0x2E: goto sra_data_addr; // SRA (IXY)
+			case 0x3E: goto srl_data_addr; // SRL (IXY)
+
+			CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
+				fuint8 temp = READ( data );
+				int masked = temp & 1 << (data2 >> 3 & 7);
+				flags = (flags & C01) | H10 |
+						(masked & S80) |
+						((masked - 1) >> 8 & (Z40 | P04));
+				goto loop;
+			}
+
+			CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
+			CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
+				int temp = READ( data );
+				int bit = 1 << (data2 >> 3 & 7);
+				temp |= bit; // SET
+				if ( !(data2 & 0x40) )
+					temp ^= bit; // RES
+				WRITE( data, temp );
+				goto loop;
+			}
+
+			default:
+				debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
+				warning = true;
+				goto loop;
+			}
+			assert( false );
+		}
+
+	// INC/DEC
+		case 0x23: // INC IXY
+			ixy = uint16_t (ixy + 1);
+			goto set_ixy;
+
+		case 0x2B: // DEC IXY
+			ixy = uint16_t (ixy - 1);
+			goto set_ixy;
+
+		case 0x34: // INC (IXY+disp)
+			ixy = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data = READ( ixy ) + 1;
+			WRITE( ixy, data );
+			goto inc_set_flags;
+
+		case 0x35: // DEC (IXY+disp)
+			ixy = IXY_DISP( ixy, (int8_t) data2 );
+			pc++;
+			data = READ( ixy ) - 1;
+			WRITE( ixy, data );
+			goto dec_set_flags;
+
+		case 0x24: // INC HXY
+			ixy = uint16_t (ixy + 0x100);
+			data = ixy >> 8;
+			goto inc_xy_common;
+
+		case 0x2C: // INC LXY
+			data = uint8_t (ixy + 1);
+			ixy = (ixy & 0xFF00) | data;
+		inc_xy_common:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto inc_set_flags;
+			}
+			iy = ixy;
+			goto inc_set_flags;
+
+		case 0x25: // DEC HXY
+			ixy = uint16_t (ixy - 0x100);
+			data = ixy >> 8;
+			goto dec_xy_common;
+
+		case 0x2D: // DEC LXY
+			data = uint8_t (ixy - 1);
+			ixy = (ixy & 0xFF00) | data;
+		dec_xy_common:
+			if ( opcode == 0xDD )
+			{
+				ix = ixy;
+				goto dec_set_flags;
+			}
+			iy = ixy;
+			goto dec_set_flags;
+
+	// PUSH/POP
+		case 0xE5: // PUSH IXY
+			data = ixy;
+			goto push_data;
+
+		case 0xE1:{// POP IXY
+			ixy = READ_WORD( sp );
+			sp = uint16_t (sp + 2);
+			goto set_ixy;
+		}
+
+	// Misc
+
+		case 0xE9: // JP (IXY)
+			pc = ixy;
+			goto loop;
+
+		case 0xE3:{// EX (SP),IXY
+			fuint16 temp = READ_WORD( sp );
+			WRITE_WORD( sp, ixy );
+			ixy = temp;
+			goto set_ixy;
+		}
+
+		default:
+			debug_printf( "Unnecessary DD/FD prefix encountered\n" );
+			warning = true;
+			pc--;
+			goto loop;
+		}
+		assert( false );
+	}
+
+	}
+	debug_printf( "Unhandled main opcode: $%02X\n", opcode );
+	assert( false );
+
+hit_idle_addr:
+	s_time -= 11;
+	goto out_of_time;
+halt:
+	s_time &= 3; // increment by multiple of 4
+out_of_time:
+	pc--;
+
+	s.time = s_time;
+	rg.flags = flags;
+	r.ix    = ix;
+	r.iy    = iy;
+	r.sp    = sp;
+	r.pc    = pc;
+	this->r.b = rg;
+	this->state_ = s;
+	this->state = &this->state_;
+
+	return warning;
+}
diff --git a/src/console/Kss_Cpu.cxx b/src/console/Kss_Cpu.cxx
deleted file mode 100644
index 0f397e1fc4bb..000000000000
--- a/src/console/Kss_Cpu.cxx
+++ /dev/null
@@ -1,1704 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.14 2:19 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Kss_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME()     (void) (s.time = s_time)
-#define RELOAD_TIME()   (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, time )\
-	kss_cpu_out( this, time, addr, data )
-
-#define CPU_IN( cpu, addr, time )\
-	kss_cpu_in( this, time, addr )
-
-#define CPU_WRITE( cpu, addr, data, time )\
-	(SYNC_TIME(), kss_cpu_write( this, addr, data ))
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n )  szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n )  (szpc [n] & ~P04)
-#define SZ28( n )   SZ28C( n )
-
-#define SET_R( n )  (void) (r.r = n)
-#define GET_R()     (r.r)
-
-Kss_Cpu::Kss_Cpu()
-{
-	state = &state_;
-
-	for ( int i = 0x100; --i >= 0; )
-	{
-		int even = 1;
-		for ( int p = i; p; p >>= 1 )
-			even ^= p;
-		int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
-		szpc [i] = n;
-		szpc [i + 0x100] = n | C01;
-	}
-	szpc [0x000] |= Z40;
-	szpc [0x100] |= Z40;
-}
-
-inline void Kss_Cpu::set_page( int i, void* write, void const* read )
-{
-	blargg_long offset = KSS_CPU_PAGE_OFFSET( i * (blargg_long) page_size );
-	state->write [i] = (byte      *) write - offset;
-	state->read  [i] = (byte const*) read  - offset;
-}
-
-void Kss_Cpu::reset( void* unmapped_write, void const* unmapped_read )
-{
-	check( state == &state_ );
-	state = &state_;
-	state_.time = 0;
-	state_.base = 0;
-	end_time_   = 0;
-
-	for ( int i = 0; i < page_count + 1; i++ )
-		set_page( i, unmapped_write, unmapped_read );
-
-	memset( &r, 0, sizeof r );
-}
-
-void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const* read )
-{
-	// address range must begin and end on page boundaries
-	require( addr % page_size == 0 );
-	require( size % page_size == 0 );
-
-	unsigned first_page = addr / page_size;
-	for ( unsigned i = size / page_size; i--; )
-	{
-		blargg_long offset = i * (blargg_long) page_size;
-		set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset );
-	}
-}
-
-#define TIME                        (s_time + s.base)
-#define RW_MEM( addr, rw )          (s.rw [(addr) >> page_shift] [KSS_CPU_PAGE_OFFSET( addr )])
-#define READ_PROG( addr )           RW_MEM( addr, read )
-#define READ( addr )                READ_PROG( addr )
-//#define WRITE( addr, data )       (void) (RW_MEM( addr, write ) = data)
-#define WRITE( addr, data )         CPU_WRITE( this, addr, data, TIME )
-#define READ_WORD( addr )           GET_LE16( &READ( addr ) )
-#define WRITE_WORD( addr, data )    SET_LE16( &RW_MEM( addr, write ), data )
-#define IN( addr )                  CPU_IN( this, addr, TIME )
-#define OUT( addr, data )           CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
-	#define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
-	#define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
-	#error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset )   (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
-	(*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e          ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f       ) CASE5( a, b, c, d, e       ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g    ) CASE6( a, b, c, d, e, f    ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int         fint16;
-typedef unsigned    fuint16;
-typedef unsigned    fuint8;
-
-bool Kss_Cpu::run( cpu_time_t end_time )
-{
-	set_end_time( end_time );
-	state_t s = this->state_;
-	this->state = &s;
-	bool warning = false;
-
-	typedef int8_t int8_t;
-
-	union {
-		regs_t rg;
-		pairs_t rp;
-		uint8_t r8_ [8]; // indexed
-		uint16_t r16_ [4];
-	};
-	rg = this->r.b;
-
-	cpu_time_t s_time = s.time;
-	fuint16 pc = r.pc;
-	fuint16 sp = r.sp;
-	fuint16 ix = r.ix; // TODO: keep in memory for direct access?
-	fuint16 iy = r.iy;
-	int flags = r.b.flags;
-
-	goto loop;
-jr_not_taken:
-	s_time -= 5;
-	goto loop;
-call_not_taken:
-	s_time -= 7;
-jp_not_taken:
-	pc += 2;
-loop:
-
-	check( (unsigned long) pc < 0x10000 );
-	check( (unsigned long) sp < 0x10000 );
-	check( (unsigned) flags < 0x100 );
-	check( (unsigned) ix < 0x10000 );
-	check( (unsigned) iy < 0x10000 );
-
-	uint8_t const* instr = s.read [pc >> page_shift];
-#define GET_ADDR()  GET_LE16( instr )
-
-	fuint8 opcode;
-
-	// TODO: eliminate this special case
-	#if BLARGG_NONPORTABLE
-		opcode = instr [pc];
-		pc++;
-		instr += pc;
-	#else
-		instr += KSS_CPU_PAGE_OFFSET( pc );
-		opcode = *instr++;
-		pc++;
-	#endif
-
-	static byte const base_timing [0x100] = {
-	//   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
-		 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
-		13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
-		12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
-		12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
-		 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
-		 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
-		11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
-		11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
-		11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
-		11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
-	};
-
-	fuint16 data;
-	data = base_timing [opcode];
-	if ( (s_time += data) >= 0 )
-		goto possibly_out_of_time;
-almost_out_of_time:
-
-	data = READ_PROG( pc );
-
-	#ifdef Z80_CPU_LOG_H
-		//log_opcode( opcode, READ_PROG( pc ) );
-		z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
-		z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
-				READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
-	#endif
-
-	switch ( opcode )
-	{
-possibly_out_of_time:
-		if ( s_time < (int) data )
-			goto almost_out_of_time;
-		s_time -= data;
-		goto out_of_time;
-
-// Common
-
-	case 0x00: // NOP
-	CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
-		goto loop;
-
-	case 0x08:{// EX AF,AF'
-		int temp = r.alt.b.a;
-		r.alt.b.a = rg.a;
-		rg.a = temp;
-
-		temp = r.alt.b.flags;
-		r.alt.b.flags = flags;
-		flags = temp;
-		goto loop;
-	}
-
-	case 0xD3: // OUT (imm),A
-		pc++;
-		OUT( data + rg.a * 0x100, rg.a );
-		goto loop;
-
-	case 0x2E: // LD L,imm
-		pc++;
-		rg.l = data;
-		goto loop;
-
-	case 0x3E: // LD A,imm
-		pc++;
-		rg.a = data;
-		goto loop;
-
-	case 0x3A:{// LD A,(addr)
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		rg.a = READ( addr );
-		goto loop;
-	}
-
-// Conditional
-
-#define ZERO    (flags & Z40)
-#define CARRY   (flags & C01)
-#define EVEN    (flags & P04)
-#define MINUS   (flags & S80)
-
-// JR
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define JR( cond ) {\
-	int offset = (int8_t) data;\
-	pc++;\
-	if ( !(cond) )\
-		goto jr_not_taken;\
-	pc = uint16_t (pc + offset);\
-	goto loop;\
-}
-
-	case 0x20: JR( !ZERO  ) // JR NZ,disp
-	case 0x28: JR(  ZERO  ) // JR Z,disp
-	case 0x30: JR( !CARRY ) // JR NC,disp
-	case 0x38: JR(  CARRY ) // JR C,disp
-	case 0x18: JR(  true  ) // JR disp
-
-	case 0x10:{// DJNZ disp
-		int temp = rg.b - 1;
-		rg.b = temp;
-		JR( temp )
-	}
-
-// JP
-#define JP( cond )  if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
-	case 0xC2: JP( !ZERO  ) // JP NZ,addr
-	case 0xCA: JP(  ZERO  ) // JP Z,addr
-	case 0xD2: JP( !CARRY ) // JP NC,addr
-	case 0xDA: JP(  CARRY ) // JP C,addr
-	case 0xE2: JP( !EVEN  ) // JP PO,addr
-	case 0xEA: JP(  EVEN  ) // JP PE,addr
-	case 0xF2: JP( !MINUS ) // JP P,addr
-	case 0xFA: JP(  MINUS ) // JP M,addr
-
-	case 0xC3: // JP addr
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xE9: // JP HL
-		pc = rp.hl;
-		goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
-	case 0xC0: RET( !ZERO  ) // RET NZ
-	case 0xC8: RET(  ZERO  ) // RET Z
-	case 0xD0: RET( !CARRY ) // RET NC
-	case 0xD8: RET(  CARRY ) // RET C
-	case 0xE0: RET( !EVEN  ) // RET PO
-	case 0xE8: RET(  EVEN  ) // RET PE
-	case 0xF0: RET( !MINUS ) // RET P
-	case 0xF8: RET(  MINUS ) // RET M
-
-	case 0xC9: // RET
-	ret_taken:
-		pc = READ_WORD( sp );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
-	case 0xC4: CALL( !ZERO  ) // CALL NZ,addr
-	case 0xCC: CALL(  ZERO  ) // CALL Z,addr
-	case 0xD4: CALL( !CARRY ) // CALL NC,addr
-	case 0xDC: CALL(  CARRY ) // CALL C,addr
-	case 0xE4: CALL( !EVEN  ) // CALL PO,addr
-	case 0xEC: CALL(  EVEN  ) // CALL PE,addr
-	case 0xF4: CALL( !MINUS ) // CALL P,addr
-	case 0xFC: CALL(  MINUS ) // CALL M,addr
-
-	case 0xCD:{// CALL addr
-	call_taken:
-		fuint16 addr = pc + 2;
-		pc = GET_ADDR();
-		sp = uint16_t (sp - 2);
-		WRITE_WORD( sp, addr );
-		goto loop;
-	}
-
-	case 0xFF: // RST
-		if ( pc > idle_addr )
-			goto hit_idle_addr;
-	CASE7( C7, CF, D7, DF, E7, EF, F7 ):
-		data = pc;
-		pc = opcode & 0x38;
-		goto push_data;
-
-// PUSH/POP
-	case 0xF5: // PUSH AF
-		data = rg.a * 0x100u + flags;
-		goto push_data;
-
-	case 0xC5: // PUSH BC
-	case 0xD5: // PUSH DE
-	case 0xE5: // PUSH HL
-		data = R16( opcode, 4, 0xC5 );
-	push_data:
-		sp = uint16_t (sp - 2);
-		WRITE_WORD( sp, data );
-		goto loop;
-
-	case 0xF1: // POP AF
-		flags = READ( sp );
-		rg.a = READ( sp + 1 );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-	case 0xC1: // POP BC
-	case 0xD1: // POP DE
-	case 0xE1: // POP HL
-		R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
-		sp = uint16_t (sp + 2);
-		goto loop;
-
-// ADC/ADD/SBC/SUB
-	case 0x96: // SUB (HL)
-	case 0x86: // ADD (HL)
-		flags &= ~C01;
-	case 0x9E: // SBC (HL)
-	case 0x8E: // ADC (HL)
-		data = READ( rp.hl );
-		goto adc_data;
-
-	case 0xD6: // SUB A,imm
-	case 0xC6: // ADD imm
-		flags &= ~C01;
-	case 0xDE: // SBC A,imm
-	case 0xCE: // ADC imm
-		pc++;
-		goto adc_data;
-
-	CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
-	CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
-		flags &= ~C01;
-	CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
-	CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
-		data = R8( opcode & 7, 0 );
-	adc_data: {
-		int result = data + (flags & C01);
-		data ^= rg.a;
-		flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
-		if ( flags )
-			result = -result;
-		result += rg.a;
-		data ^= result;
-		flags |=(data & H10) |
-				((data - -0x80) >> 6 & V04) |
-				SZ28C( result & 0x1FF );
-		rg.a = result;
-		goto loop;
-	}
-
-// CP
-	case 0xBE: // CP (HL)
-		data = READ( rp.hl );
-		goto cp_data;
-
-	case 0xFE: // CP imm
-		pc++;
-		goto cp_data;
-
-	CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
-		data = R8( opcode, 0xB8 );
-	cp_data: {
-		int result = rg.a - data;
-		flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
-		data ^= rg.a;
-		flags |=(((result ^ rg.a) & data) >> 5 & V04) |
-				(((data & H10) ^ result) & (S80 | H10));
-		if ( (uint8_t) result )
-			goto loop;
-		flags |= Z40;
-		goto loop;
-	}
-
-// ADD HL,rp
-
-	case 0x39: // ADD HL,SP
-		data = sp;
-		goto add_hl_data;
-
-	case 0x09: // ADD HL,BC
-	case 0x19: // ADD HL,DE
-	case 0x29: // ADD HL,HL
-		data = R16( opcode, 4, 0x09 );
-	add_hl_data: {
-		blargg_ulong sum = rp.hl + data;
-		data ^= rp.hl;
-		rp.hl = sum;
-		flags = (flags & (S80 | Z40 | V04)) |
-				(sum >> 16) |
-				(sum >> 8 & (F20 | F08)) |
-				((data ^ sum) >> 8 & H10);
-		goto loop;
-	}
-
-	case 0x27:{// DAA
-		int a = rg.a;
-		if ( a > 0x99 )
-			flags |= C01;
-
-		int adjust = 0x60 & -(flags & C01);
-
-		if ( flags & H10 || (a & 0x0F) > 9 )
-			adjust |= 0x06;
-
-		if ( flags & N02 )
-			adjust = -adjust;
-		a += adjust;
-
-		flags = (flags & (C01 | N02)) |
-				((rg.a ^ a) & H10) |
-				SZ28P( (uint8_t) a );
-		rg.a = a;
-		goto loop;
-	}
-	/*
-	case 0x27:{// DAA
-		// more optimized, but probably not worth the obscurity
-		int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
-		int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
-		if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
-			adjust |= 0x06;
-
-		if ( f & N02 )
-			adjust = -adjust;
-		int a = rg.a + adjust;
-
-		flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
-		rg.a = a;
-		goto loop;
-	}
-	*/
-
-// INC/DEC
-	case 0x34: // INC (HL)
-		data = READ( rp.hl ) + 1;
-		WRITE( rp.hl, data );
-		goto inc_set_flags;
-
-	CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
-		data = ++R8( opcode >> 3, 0 );
-	inc_set_flags:
-		flags = (flags & C01) |
-				(((data & 0x0F) - 1) & H10) |
-				SZ28( (uint8_t) data );
-		if ( data != 0x80 )
-			goto loop;
-		flags |= V04;
-		goto loop;
-
-	case 0x35: // DEC (HL)
-		data = READ( rp.hl ) - 1;
-		WRITE( rp.hl, data );
-		goto dec_set_flags;
-
-	CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
-		data = --R8( opcode >> 3, 0 );
-	dec_set_flags:
-		flags = (flags & C01) | N02 |
-				(((data & 0x0F) + 1) & H10) |
-				SZ28( (uint8_t) data );
-		if ( data != 0x7F )
-			goto loop;
-		flags |= V04;
-		goto loop;
-
-	case 0x03: // INC BC
-	case 0x13: // INC DE
-	case 0x23: // INC HL
-		R16( opcode, 4, 0x03 )++;
-		goto loop;
-
-	case 0x33: // INC SP
-		sp = uint16_t (sp + 1);
-		goto loop;
-
-	case 0x0B: // DEC BC
-	case 0x1B: // DEC DE
-	case 0x2B: // DEC HL
-		R16( opcode, 4, 0x0B )--;
-		goto loop;
-
-	case 0x3B: // DEC SP
-		sp = uint16_t (sp - 1);
-		goto loop;
-
-// AND
-	case 0xA6: // AND (HL)
-		data = READ( rp.hl );
-		goto and_data;
-
-	case 0xE6: // AND imm
-		pc++;
-		goto and_data;
-
-	CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
-		data = R8( opcode, 0xA0 );
-	and_data:
-		rg.a &= data;
-		flags = SZ28P( rg.a ) | H10;
-		goto loop;
-
-// OR
-	case 0xB6: // OR (HL)
-		data = READ( rp.hl );
-		goto or_data;
-
-	case 0xF6: // OR imm
-		pc++;
-		goto or_data;
-
-	CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
-		data = R8( opcode, 0xB0 );
-	or_data:
-		rg.a |= data;
-		flags = SZ28P( rg.a );
-		goto loop;
-
-// XOR
-	case 0xAE: // XOR (HL)
-		data = READ( rp.hl );
-		goto xor_data;
-
-	case 0xEE: // XOR imm
-		pc++;
-		goto xor_data;
-
-	CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
-		data = R8( opcode, 0xA8 );
-	xor_data:
-		rg.a ^= data;
-		flags = SZ28P( rg.a );
-		goto loop;
-
-// LD
-	CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
-		WRITE( rp.hl, R8( opcode, 0x70 ) );
-		goto loop;
-
-	CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
-	CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
-	CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
-	CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
-	CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
-	CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
-	CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
-		R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
-		goto loop;
-
-	CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
-		R8( opcode >> 3, 0 ) = data;
-		pc++;
-		goto loop;
-
-	case 0x36: // LD (HL),imm
-		pc++;
-		WRITE( rp.hl, data );
-		goto loop;
-
-	CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
-		R8( opcode >> 3, 8 ) = READ( rp.hl );
-		goto loop;
-
-	case 0x01: // LD rp,imm
-	case 0x11:
-	case 0x21:
-		R16( opcode, 4, 0x01 ) = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x31: // LD sp,imm
-		sp = GET_ADDR();
-		pc += 2;
-		goto loop;
-
-	case 0x2A:{// LD HL,(addr)
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		rp.hl = READ_WORD( addr );
-		goto loop;
-	}
-
-	case 0x32:{// LD (addr),A
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		WRITE( addr, rg.a );
-		goto loop;
-	}
-
-	case 0x22:{// LD (addr),HL
-		fuint16 addr = GET_ADDR();
-		pc += 2;
-		WRITE_WORD( addr, rp.hl );
-		goto loop;
-	}
-
-	case 0x02: // LD (BC),A
-	case 0x12: // LD (DE),A
-		WRITE( R16( opcode, 4, 0x02 ), rg.a );
-		goto loop;
-
-	case 0x0A: // LD A,(BC)
-	case 0x1A: // LD A,(DE)
-		rg.a = READ( R16( opcode, 4, 0x0A ) );
-		goto loop;
-
-	case 0xF9: // LD SP,HL
-		sp = rp.hl;
-		goto loop;
-
-// Rotate
-
-	case 0x07:{// RLCA
-		fuint16 temp = rg.a;
-		temp = (temp << 1) | (temp >> 7);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08 | C01));
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x0F:{// RRCA
-		fuint16 temp = rg.a;
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & C01);
-		temp = (temp << 7) | (temp >> 1);
-		flags |= temp & (F20 | F08);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x17:{// RLA
-		blargg_ulong temp = (rg.a << 1) | (flags & C01);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08)) |
-				(temp >> 8);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x1F:{// RRA
-		fuint16 temp = (flags << 7) | (rg.a >> 1);
-		flags = (flags & (S80 | Z40 | P04)) |
-				(temp & (F20 | F08)) |
-				(rg.a & C01);
-		rg.a = temp;
-		goto loop;
-	}
-
-// Misc
-	case 0x2F:{// CPL
-		fuint16 temp = ~rg.a;
-		flags = (flags & (S80 | Z40 | P04 | C01)) |
-				(temp & (F20 | F08)) |
-				(H10 | N02);
-		rg.a = temp;
-		goto loop;
-	}
-
-	case 0x3F:{// CCF
-		flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
-				(flags << 4 & H10) |
-				(rg.a & (F20 | F08));
-		goto loop;
-	}
-
-	case 0x37: // SCF
-		flags = (flags & (S80 | Z40 | P04)) | C01 |
-				(rg.a & (F20 | F08));
-		goto loop;
-
-	case 0xDB: // IN A,(imm)
-		pc++;
-		rg.a = IN( data + rg.a * 0x100 );
-		goto loop;
-
-	case 0xE3:{// EX (SP),HL
-		fuint16 temp = READ_WORD( sp );
-		WRITE_WORD( sp, rp.hl );
-		rp.hl = temp;
-		goto loop;
-	}
-
-	case 0xEB:{// EX DE,HL
-		fuint16 temp = rp.hl;
-		rp.hl = rp.de;
-		rp.de = temp;
-		goto loop;
-	}
-
-	case 0xD9:{// EXX DE,HL
-		fuint16 temp = r.alt.w.bc;
-		r.alt.w.bc = rp.bc;
-		rp.bc = temp;
-
-		temp = r.alt.w.de;
-		r.alt.w.de = rp.de;
-		rp.de = temp;
-
-		temp = r.alt.w.hl;
-		r.alt.w.hl = rp.hl;
-		rp.hl = temp;
-		goto loop;
-	}
-
-	case 0xF3: // DI
-		r.iff1 = 0;
-		r.iff2 = 0;
-		goto loop;
-
-	case 0xFB: // EI
-		r.iff1 = 1;
-		r.iff2 = 1;
-		// TODO: delayed effect
-		goto loop;
-
-	case 0x76: // HALT
-		goto halt;
-
-//////////////////////////////////////// CB prefix
-	{
-	case 0xCB:
-		pc++;
-		switch ( data )
-		{
-
-	// Rotate left
-
-	#define RLC( read, write ) {\
-		fuint8 result = read;\
-		result = uint8_t (result << 1) | (result >> 7);\
-		flags = SZ28P( result ) | (result & C01);\
-		write;\
-		goto loop;\
-	}
-
-		case 0x06: // RLC (HL)
-			s_time += 7;
-			data = rp.hl;
-		rlc_data_addr:
-			RLC( READ( data ), WRITE( data, result ) )
-
-		CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
-			uint8_t& reg = R8( data, 0 );
-			RLC( reg, reg = result )
-		}
-
-	#define RL( read, write ) {\
-		fuint16 result = (read << 1) | (flags & C01);\
-		flags = SZ28PC( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x16: // RL (HL)
-			s_time += 7;
-			data = rp.hl;
-		rl_data_addr:
-			RL( READ( data ), WRITE( data, result ) )
-
-		CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
-			uint8_t& reg = R8( data, 0x10 );
-			RL( reg, reg = result )
-		}
-
-	#define SLA( read, add, write ) {\
-		fuint16 result = (read << 1) | add;\
-		flags = SZ28PC( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x26: // SLA (HL)
-			s_time += 7;
-			data = rp.hl;
-		sla_data_addr:
-			SLA( READ( data ), 0, WRITE( data, result ) )
-
-		CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
-			uint8_t& reg = R8( data, 0x20 );
-			SLA( reg, 0, reg = result )
-		}
-
-		case 0x36: // SLL (HL)
-			s_time += 7;
-			data = rp.hl;
-		sll_data_addr:
-			SLA( READ( data ), 1, WRITE( data, result ) )
-
-		CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
-			uint8_t& reg = R8( data, 0x30 );
-			SLA( reg, 1, reg = result )
-		}
-
-	// Rotate right
-
-	#define RRC( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result = uint8_t (result << 7) | (result >> 1);\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x0E: // RRC (HL)
-			s_time += 7;
-			data = rp.hl;
-		rrc_data_addr:
-			RRC( READ( data ), WRITE( data, result ) )
-
-		CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
-			uint8_t& reg = R8( data, 0x08 );
-			RRC( reg, reg = result )
-		}
-
-	#define RR( read, write ) {\
-		fuint8 result = read;\
-		fuint8 temp = result & C01;\
-		result = uint8_t (flags << 7) | (result >> 1);\
-		flags = SZ28P( result ) | temp;\
-		write;\
-		goto loop;\
-	}
-
-		case 0x1E: // RR (HL)
-			s_time += 7;
-			data = rp.hl;
-		rr_data_addr:
-			RR( READ( data ), WRITE( data, result ) )
-
-		CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
-			uint8_t& reg = R8( data, 0x18 );
-			RR( reg, reg = result )
-		}
-
-	#define SRA( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result = (result & 0x80) | (result >> 1);\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x2E: // SRA (HL)
-			data = rp.hl;
-			s_time += 7;
-		sra_data_addr:
-			SRA( READ( data ), WRITE( data, result ) )
-
-		CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
-			uint8_t& reg = R8( data, 0x28 );
-			SRA( reg, reg = result )
-		}
-
-	#define SRL( read, write ) {\
-		fuint8 result = read;\
-		flags = result & C01;\
-		result >>= 1;\
-		flags |= SZ28P( result );\
-		write;\
-		goto loop;\
-	}
-
-		case 0x3E: // SRL (HL)
-			s_time += 7;
-			data = rp.hl;
-		srl_data_addr:
-			SRL( READ( data ), WRITE( data, result ) )
-
-		CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
-			uint8_t& reg = R8( data, 0x38 );
-			SRL( reg, reg = result )
-		}
-
-	// BIT
-		{
-			unsigned temp;
-		CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
-			s_time += 4;
-			temp = READ( rp.hl );
-			flags &= C01;
-			goto bit_temp;
-		CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
-		CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
-		CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
-		CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
-		CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
-		CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
-		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
-		CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
-			temp = R8( data & 7, 0 );
-			flags = (flags & C01) | (temp & (F20 | F08));
-		bit_temp:
-			int masked = temp & 1 << (data >> 3 & 7);
-			flags |=(masked & S80) | H10 |
-					((masked - 1) >> 8 & (Z40 | P04));
-			goto loop;
-		}
-
-	// SET/RES
-		CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
-		CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
-			s_time += 7;
-			int temp = READ( rp.hl );
-			int bit = 1 << (data >> 3 & 7);
-			temp |= bit; // SET
-			if ( !(data & 0x40) )
-				temp ^= bit; // RES
-			WRITE( rp.hl, temp );
-			goto loop;
-		}
-
-		CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
-		CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
-		CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
-		CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
-		CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
-		CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
-		CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
-		CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
-			R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
-			goto loop;
-
-		CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
-		CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
-		CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
-		CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
-		CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
-		CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
-		CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
-		CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
-			R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
-			goto loop;
-		}
-		assert( false );
-	}
-
-#undef GET_ADDR
-#define GET_ADDR()  GET_LE16( instr + 1 )
-
-//////////////////////////////////////// ED prefix
-	{
-	case 0xED:
-		pc++;
-		s_time += ed_dd_timing [data] >> 4;
-		switch ( data )
-		{
-		{
-			blargg_ulong temp;
-		case 0x72: // SBC HL,SP
-		case 0x7A: // ADC HL,SP
-			temp = sp;
-			if ( 0 )
-		case 0x42: // SBC HL,BC
-		case 0x52: // SBC HL,DE
-		case 0x62: // SBC HL,HL
-		case 0x4A: // ADC HL,BC
-		case 0x5A: // ADC HL,DE
-		case 0x6A: // ADC HL,HL
-				temp = R16( data >> 3 & 6, 1, 0 );
-			blargg_ulong sum = temp + (flags & C01);
-			flags = ~data >> 2 & N02;
-			if ( flags )
-				sum = -sum;
-			sum += rp.hl;
-			temp ^= rp.hl;
-			temp ^= sum;
-			flags |=(sum >> 16 & C01) |
-					(temp >> 8 & H10) |
-					(sum >> 8 & (S80 | F20 | F08)) |
-					((temp - -0x8000) >> 14 & V04);
-			rp.hl = sum;
-			if ( (uint16_t) sum )
-				goto loop;
-			flags |= Z40;
-			goto loop;
-		}
-
-		CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
-			int temp = IN( rp.bc );
-			R8( data >> 3, 8 ) = temp;
-			flags = (flags & C01) | SZ28P( temp );
-			goto loop;
-		}
-
-		case 0x71: // OUT (C),0
-			rg.flags = 0;
-		CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
-			OUT( rp.bc, R8( data >> 3, 8 ) );
-			goto loop;
-
-		{
-			unsigned temp;
-		case 0x73: // LD (ADDR),SP
-			temp = sp;
-			if ( 0 )
-		case 0x43: // LD (ADDR),BC
-		case 0x53: // LD (ADDR),DE
-				temp = R16( data, 4, 0x43 );
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			WRITE_WORD( addr, temp );
-			goto loop;
-		}
-
-		case 0x4B: // LD BC,(ADDR)
-		case 0x5B:{// LD DE,(ADDR)
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			R16( data, 4, 0x4B ) = READ_WORD( addr );
-			goto loop;
-		}
-
-		case 0x7B:{// LD SP,(ADDR)
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			sp = READ_WORD( addr );
-			goto loop;
-		}
-
-		case 0x67:{// RRD
-			fuint8 temp = READ( rp.hl );
-			WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
-			temp = (rg.a & 0xF0) | (temp & 0x0F);
-			flags = (flags & C01) | SZ28P( temp );
-			rg.a = temp;
-			goto loop;
-		}
-
-		case 0x6F:{// RLD
-			fuint8 temp = READ( rp.hl );
-			WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
-			temp = (rg.a & 0xF0) | (temp >> 4);
-			flags = (flags & C01) | SZ28P( temp );
-			rg.a = temp;
-			goto loop;
-		}
-
-		CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
-			opcode = 0x10; // flag to do SBC instead of ADC
-			flags &= ~C01;
-			data = rg.a;
-			rg.a = 0;
-			goto adc_data;
-
-		{
-			int inc;
-		case 0xA9: // CPD
-		case 0xB9: // CPDR
-			inc = -1;
-			if ( 0 )
-		case 0xA1: // CPI
-		case 0xB1: // CPIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			int result = rg.a - temp;
-			flags = (flags & C01) | N02 |
-					((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
-			if ( !(uint8_t) result ) flags |= Z40;
-			result -= (flags & H10) >> 4;
-			flags |= result & F08;
-			flags |= result << 4 & F20;
-			if ( !--rp.bc )
-				goto loop;
-
-			flags |= V04;
-			if ( flags & Z40 || data < 0xB0 )
-				goto loop;
-
-			pc -= 2;
-			s_time += 5;
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xA8: // LDD
-		case 0xB8: // LDDR
-			inc = -1;
-			if ( 0 )
-		case 0xA0: // LDI
-		case 0xB0: // LDIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			addr = rp.de;
-			rp.de = addr + inc;
-			WRITE( addr, temp );
-
-			temp += rg.a;
-			flags = (flags & (S80 | Z40 | C01)) |
-					(temp & F08) | (temp << 4 & F20);
-			if ( !--rp.bc )
-				goto loop;
-
-			flags |= V04;
-			if ( data < 0xB0 )
-				goto loop;
-
-			pc -= 2;
-			s_time += 5;
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xAB: // OUTD
-		case 0xBB: // OTDR
-			inc = -1;
-			if ( 0 )
-		case 0xA3: // OUTI
-		case 0xB3: // OTIR
-				inc = +1;
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-			int temp = READ( addr );
-
-			int b = --rg.b;
-			flags = (temp >> 6 & N02) | SZ28( b );
-			if ( b && data >= 0xB0 )
-			{
-				pc -= 2;
-				s_time += 5;
-			}
-
-			OUT( rp.bc, temp );
-			goto loop;
-		}
-
-		{
-			int inc;
-		case 0xAA: // IND
-		case 0xBA: // INDR
-			inc = -1;
-			if ( 0 )
-		case 0xA2: // INI
-		case 0xB2: // INIR
-				inc = +1;
-
-			fuint16 addr = rp.hl;
-			rp.hl = addr + inc;
-
-			int temp = IN( rp.bc );
-
-			int b = --rg.b;
-			flags = (temp >> 6 & N02) | SZ28( b );
-			if ( b && data >= 0xB0 )
-			{
-				pc -= 2;
-				s_time += 5;
-			}
-
-			WRITE( addr, temp );
-			goto loop;
-		}
-
-		case 0x47: // LD I,A
-			r.i = rg.a;
-			goto loop;
-
-		case 0x4F: // LD R,A
-			SET_R( rg.a );
-			debug_printf( "LD R,A not supported\n" );
-			warning = true;
-			goto loop;
-
-		case 0x57: // LD A,I
-			rg.a = r.i;
-			goto ld_ai_common;
-
-		case 0x5F: // LD A,R
-			rg.a = GET_R();
-			debug_printf( "LD A,R not supported\n" );
-			warning = true;
-		ld_ai_common:
-			flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
-			goto loop;
-
-		CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
-			r.iff1 = r.iff2;
-			goto ret_taken;
-
-		case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
-			r.im = 0;
-			goto loop;
-
-		case 0x56: case 0x76: // IM 1
-			r.im = 1;
-			goto loop;
-
-		case 0x5E: case 0x7E: // IM 2
-			r.im = 2;
-			goto loop;
-
-		default:
-			debug_printf( "Opcode $ED $%02X not supported\n", data );
-			warning = true;
-			goto loop;
-		}
-		assert( false );
-	}
-
-//////////////////////////////////////// DD/FD prefix
-	{
-	fuint16 ixy;
-	case 0xDD:
-		ixy = ix;
-		goto ix_prefix;
-	case 0xFD:
-		ixy = iy;
-	ix_prefix:
-		pc++;
-		unsigned data2 = READ_PROG( pc );
-		s_time += ed_dd_timing [data] & 0x0F;
-		switch ( data )
-		{
-	// TODO: more efficient way of avoid negative address
-	// TODO: avoid using this as argument to READ() since it is evaluated twice
-	#define IXY_DISP( ixy, disp )   uint16_t ((ixy) + (disp))
-
-	#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
-	// ADD/ADC/SUB/SBC
-
-		case 0x96: // SUB (IXY+disp)
-		case 0x86: // ADD (IXY+disp)
-			flags &= ~C01;
-		case 0x9E: // SBC (IXY+disp)
-		case 0x8E: // ADC (IXY+disp)
-			pc++;
-			opcode = data;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto adc_data;
-
-		case 0x94: // SUB HXY
-		case 0x84: // ADD HXY
-			flags &= ~C01;
-		case 0x9C: // SBC HXY
-		case 0x8C: // ADC HXY
-			opcode = data;
-			data = ixy >> 8;
-			goto adc_data;
-
-		case 0x95: // SUB LXY
-		case 0x85: // ADD LXY
-			flags &= ~C01;
-		case 0x9D: // SBC LXY
-		case 0x8D: // ADC LXY
-			opcode = data;
-			data = (uint8_t) ixy;
-			goto adc_data;
-
-		{
-			unsigned temp;
-		case 0x39: // ADD IXY,SP
-			temp = sp;
-			goto add_ixy_data;
-
-		case 0x29: // ADD IXY,HL
-			temp = ixy;
-			goto add_ixy_data;
-
-		case 0x09: // ADD IXY,BC
-		case 0x19: // ADD IXY,DE
-			temp = R16( data, 4, 0x09 );
-		add_ixy_data: {
-			blargg_ulong sum = ixy + temp;
-			temp ^= ixy;
-			ixy = (uint16_t) sum;
-			flags = (flags & (S80 | Z40 | V04)) |
-					(sum >> 16) |
-					(sum >> 8 & (F20 | F08)) |
-					((temp ^ sum) >> 8 & H10);
-			goto set_ixy;
-		}
-		}
-
-	// AND
-		case 0xA6: // AND (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto and_data;
-
-		case 0xA4: // AND HXY
-			data = ixy >> 8;
-			goto and_data;
-
-		case 0xA5: // AND LXY
-			data = (uint8_t) ixy;
-			goto and_data;
-
-	// OR
-		case 0xB6: // OR (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto or_data;
-
-		case 0xB4: // OR HXY
-			data = ixy >> 8;
-			goto or_data;
-
-		case 0xB5: // OR LXY
-			data = (uint8_t) ixy;
-			goto or_data;
-
-	// XOR
-		case 0xAE: // XOR (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto xor_data;
-
-		case 0xAC: // XOR HXY
-			data = ixy >> 8;
-			goto xor_data;
-
-		case 0xAD: // XOR LXY
-			data = (uint8_t) ixy;
-			goto xor_data;
-
-	// CP
-		case 0xBE: // CP (IXY+disp)
-			pc++;
-			data = READ( IXY_DISP( ixy, (int8_t) data2 )  );
-			goto cp_data;
-
-		case 0xBC: // CP HXY
-			data = ixy >> 8;
-			goto cp_data;
-
-		case 0xBD: // CP LXY
-			data = (uint8_t) ixy;
-			goto cp_data;
-
-	// LD
-		CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
-			data = R8( data, 0x70 );
-			if ( 0 )
-		case 0x36: // LD (IXY+disp),imm
-				pc++, data = READ_PROG( pc );
-			pc++;
-			WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
-			goto loop;
-
-		CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
-			R8( data >> 3, 8 ) = ixy >> 8;
-			goto loop;
-
-		case 0x64: // LD HXY,HXY
-		case 0x6D: // LD LXY,LXY
-			goto loop;
-
-		CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
-			R8( data >> 3, 8 ) = ixy;
-			goto loop;
-
-		CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
-			pc++;
-			R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
-			goto loop;
-
-		case 0x26: // LD HXY,imm
-			pc++;
-			goto ld_hxy_data;
-
-		case 0x65: // LD HXY,LXY
-			data2 = (uint8_t) ixy;
-			goto ld_hxy_data;
-
-		CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
-			data2 = R8( data, 0x60 );
-		ld_hxy_data:
-			ixy = (uint8_t) ixy | (data2 << 8);
-			goto set_ixy;
-
-		case 0x2E: // LD LXY,imm
-			pc++;
-			goto ld_lxy_data;
-
-		case 0x6C: // LD LXY,HXY
-			data2 = ixy >> 8;
-			goto ld_lxy_data;
-
-		CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
-			data2 = R8( data, 0x68 );
-		ld_lxy_data:
-			ixy = (ixy & 0xFF00) | data2;
-		set_ixy:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto loop;
-			}
-			iy = ixy;
-			goto loop;
-
-		case 0xF9: // LD SP,IXY
-			sp = ixy;
-			goto loop;
-
-		case 0x22:{// LD (ADDR),IXY
-			fuint16 addr = GET_ADDR();
-			pc += 2;
-			WRITE_WORD( addr, ixy );
-			goto loop;
-		}
-
-		case 0x21: // LD IXY,imm
-			ixy = GET_ADDR();
-			pc += 2;
-			goto set_ixy;
-
-		case 0x2A:{// LD IXY,(addr)
-			fuint16 addr = GET_ADDR();
-			ixy = READ_WORD( addr );
-			pc += 2;
-			goto set_ixy;
-		}
-
-	// DD/FD CB prefix
-		case 0xCB: {
-			data = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data2 = READ_PROG( pc );
-			pc++;
-			switch ( data2 )
-			{
-			case 0x06: goto rlc_data_addr; // RLC (IXY)
-			case 0x16: goto rl_data_addr;  // RL (IXY)
-			case 0x26: goto sla_data_addr; // SLA (IXY)
-			case 0x36: goto sll_data_addr; // SLL (IXY)
-			case 0x0E: goto rrc_data_addr; // RRC (IXY)
-			case 0x1E: goto rr_data_addr;  // RR (IXY)
-			case 0x2E: goto sra_data_addr; // SRA (IXY)
-			case 0x3E: goto srl_data_addr; // SRL (IXY)
-
-			CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
-				fuint8 temp = READ( data );
-				int masked = temp & 1 << (data2 >> 3 & 7);
-				flags = (flags & C01) | H10 |
-						(masked & S80) |
-						((masked - 1) >> 8 & (Z40 | P04));
-				goto loop;
-			}
-
-			CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
-			CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
-				int temp = READ( data );
-				int bit = 1 << (data2 >> 3 & 7);
-				temp |= bit; // SET
-				if ( !(data2 & 0x40) )
-					temp ^= bit; // RES
-				WRITE( data, temp );
-				goto loop;
-			}
-
-			default:
-				debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
-				warning = true;
-				goto loop;
-			}
-			assert( false );
-		}
-
-	// INC/DEC
-		case 0x23: // INC IXY
-			ixy = uint16_t (ixy + 1);
-			goto set_ixy;
-
-		case 0x2B: // DEC IXY
-			ixy = uint16_t (ixy - 1);
-			goto set_ixy;
-
-		case 0x34: // INC (IXY+disp)
-			ixy = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data = READ( ixy ) + 1;
-			WRITE( ixy, data );
-			goto inc_set_flags;
-
-		case 0x35: // DEC (IXY+disp)
-			ixy = IXY_DISP( ixy, (int8_t) data2 );
-			pc++;
-			data = READ( ixy ) - 1;
-			WRITE( ixy, data );
-			goto dec_set_flags;
-
-		case 0x24: // INC HXY
-			ixy = uint16_t (ixy + 0x100);
-			data = ixy >> 8;
-			goto inc_xy_common;
-
-		case 0x2C: // INC LXY
-			data = uint8_t (ixy + 1);
-			ixy = (ixy & 0xFF00) | data;
-		inc_xy_common:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto inc_set_flags;
-			}
-			iy = ixy;
-			goto inc_set_flags;
-
-		case 0x25: // DEC HXY
-			ixy = uint16_t (ixy - 0x100);
-			data = ixy >> 8;
-			goto dec_xy_common;
-
-		case 0x2D: // DEC LXY
-			data = uint8_t (ixy - 1);
-			ixy = (ixy & 0xFF00) | data;
-		dec_xy_common:
-			if ( opcode == 0xDD )
-			{
-				ix = ixy;
-				goto dec_set_flags;
-			}
-			iy = ixy;
-			goto dec_set_flags;
-
-	// PUSH/POP
-		case 0xE5: // PUSH IXY
-			data = ixy;
-			goto push_data;
-
-		case 0xE1:{// POP IXY
-			ixy = READ_WORD( sp );
-			sp = uint16_t (sp + 2);
-			goto set_ixy;
-		}
-
-	// Misc
-
-		case 0xE9: // JP (IXY)
-			pc = ixy;
-			goto loop;
-
-		case 0xE3:{// EX (SP),IXY
-			fuint16 temp = READ_WORD( sp );
-			WRITE_WORD( sp, ixy );
-			ixy = temp;
-			goto set_ixy;
-		}
-
-		default:
-			debug_printf( "Unnecessary DD/FD prefix encountered\n" );
-			warning = true;
-			pc--;
-			goto loop;
-		}
-		assert( false );
-	}
-
-	}
-	debug_printf( "Unhandled main opcode: $%02X\n", opcode );
-	assert( false );
-
-hit_idle_addr:
-	s_time -= 11;
-	goto out_of_time;
-halt:
-	s_time &= 3; // increment by multiple of 4
-out_of_time:
-	pc--;
-
-	s.time = s_time;
-	rg.flags = flags;
-	r.ix    = ix;
-	r.iy    = iy;
-	r.sp    = sp;
-	r.pc    = pc;
-	this->r.b = rg;
-	this->state_ = s;
-	this->state = &this->state_;
-
-	return warning;
-}
diff --git a/src/console/Kss_Emu.cc b/src/console/Kss_Emu.cc
new file mode 100644
index 000000000000..1de2361e67f0
--- /dev/null
+++ b/src/console/Kss_Emu.cc
@@ -0,0 +1,416 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Kss_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+long const clock_rate = 3579545;
+int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count;
+
+Kss_Emu::Kss_Emu()
+{
+	sn = 0;
+	set_type( gme_kss_type );
+	set_silence_lookahead( 6 );
+	static const char* const names [osc_count] = {
+		"Square 1", "Square 2", "Square 3",
+		"Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5"
+	};
+	set_voice_names( names );
+
+	static int const types [osc_count] = {
+		wave_type | 0, wave_type | 1, wave_type | 2,
+		wave_type | 3, wave_type | 4, wave_type | 5, wave_type | 6, wave_type | 7
+	};
+	set_voice_types( types );
+
+	memset( unmapped_read, 0xFF, sizeof unmapped_read );
+}
+
+Kss_Emu::~Kss_Emu() { unload(); }
+
+void Kss_Emu::unload()
+{
+	delete sn;
+	sn = 0;
+	Classic_Emu::unload();
+}
+
+// Track info
+
+static void copy_kss_fields( Kss_Emu::header_t const& h, track_info_t* out )
+{
+	const char* system = "MSX";
+	if ( h.device_flags & 0x02 )
+	{
+		system = "Sega Master System";
+		if ( h.device_flags & 0x04 )
+			system = "Game Gear";
+	}
+	Gme_File::copy_field_( out->system, system );
+}
+
+blargg_err_t Kss_Emu::track_info_( track_info_t* out, int ) const
+{
+	copy_kss_fields( header_, out );
+	return 0;
+}
+
+static blargg_err_t check_kss_header( void const* header )
+{
+	if ( memcmp( header, "KSCC", 4 ) && memcmp( header, "KSSX", 4 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Kss_File : Gme_Info_
+{
+	Kss_Emu::header_t header_;
+
+	Kss_File() { set_type( gme_kss_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		blargg_err_t err = in.read( &header_, Kss_Emu::header_size );
+		if ( err )
+			return (err == in.eof_error ? gme_wrong_file_type : err);
+		return check_kss_header( &header_ );
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		copy_kss_fields( header_, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_kss_emu () { return BLARGG_NEW Kss_Emu ; }
+static Music_Emu* new_kss_file() { return BLARGG_NEW Kss_File; }
+
+static gme_type_t_ const gme_kss_type_ = { "MSX", 256, &new_kss_emu, &new_kss_file, "KSS", 0x03 };
+gme_type_t const gme_kss_type = &gme_kss_type_;
+
+
+// Setup
+
+void Kss_Emu::update_gain()
+{
+	double g = gain() * 1.4;
+	if ( scc_accessed )
+		g *= 1.5;
+	ay.volume( g );
+	scc.volume( g );
+	if ( sn )
+		sn->volume( g );
+}
+
+blargg_err_t Kss_Emu::load_( Data_Reader& in )
+{
+	memset( &header_, 0, sizeof header_ );
+	assert( offsetof (header_t,device_flags) == header_size - 1 );
+	assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1 );
+	RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) );
+
+	RETURN_ERR( check_kss_header( header_.tag ) );
+
+	if ( header_.tag [3] == 'C' )
+	{
+		if ( header_.extra_header )
+		{
+			header_.extra_header = 0;
+			set_warning( "Unknown data in header" );
+		}
+		if ( header_.device_flags & ~0x0F )
+		{
+			header_.device_flags &= 0x0F;
+			set_warning( "Unknown data in header" );
+		}
+	}
+	else
+	{
+		ext_header_t& ext = header_;
+		memcpy( &ext, rom.begin(), min( (int) ext_header_size, (int) header_.extra_header ) );
+		if ( header_.extra_header > 0x10 )
+			set_warning( "Unknown data in header" );
+	}
+
+	if ( header_.device_flags & 0x09 )
+		set_warning( "FM sound not supported" );
+
+	scc_enabled = 0xC000;
+	if ( header_.device_flags & 0x04 )
+		scc_enabled = 0;
+
+	if ( header_.device_flags & 0x02 && !sn )
+		CHECK_ALLOC( sn = BLARGG_NEW( Sms_Apu ) );
+
+	set_voice_count( osc_count );
+
+	return setup_buffer( ::clock_rate );
+}
+
+void Kss_Emu::update_eq( blip_eq_t const& eq )
+{
+	ay.treble_eq( eq );
+	scc.treble_eq( eq );
+	if ( sn )
+		sn->treble_eq( eq );
+}
+
+void Kss_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	int i2 = i - ay.osc_count;
+	if ( i2 >= 0 )
+		scc.osc_output( i2, center );
+	else
+		ay.osc_output( i, center );
+	if ( sn && i < sn->osc_count )
+		sn->osc_output( i, center, left, right );
+}
+
+// Emulation
+
+void Kss_Emu::set_tempo_( double t )
+{
+	blip_time_t period =
+			(header_.device_flags & 0x40 ? ::clock_rate / 50 : ::clock_rate / 60);
+	play_period = blip_time_t (period / t);
+}
+
+blargg_err_t Kss_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( ram, 0xC9, 0x4000 );
+	memset( ram + 0x4000, 0, sizeof ram - 0x4000 );
+
+	// copy driver code to lo RAM
+	static byte const bios [] = {
+		0xD3, 0xA0, 0xF5, 0x7B, 0xD3, 0xA1, 0xF1, 0xC9, // $0001: WRTPSG
+		0xD3, 0xA0, 0xDB, 0xA2, 0xC9                    // $0009: RDPSG
+	};
+	static byte const vectors [] = {
+		0xC3, 0x01, 0x00,   // $0093: WRTPSG vector
+		0xC3, 0x09, 0x00,   // $0096: RDPSG vector
+	};
+	memcpy( ram + 0x01, bios,    sizeof bios );
+	memcpy( ram + 0x93, vectors, sizeof vectors );
+
+	// copy non-banked data into RAM
+	unsigned load_addr = GET_LE16( header_.load_addr );
+	long orig_load_size = GET_LE16( header_.load_size );
+	long load_size = min( orig_load_size, rom.file_size() );
+	load_size = min( load_size, long (mem_size - load_addr) );
+	if ( load_size != orig_load_size )
+		set_warning( "Excessive data size" );
+	memcpy( ram + load_addr, rom.begin() + header_.extra_header, load_size );
+
+	rom.set_addr( -load_size - header_.extra_header );
+
+	// check available bank data
+	blargg_long const bank_size = this->bank_size();
+	int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size;
+	bank_count = header_.bank_mode & 0x7F;
+	if ( bank_count > max_banks )
+	{
+		bank_count = max_banks;
+		set_warning( "Bank data missing" );
+	}
+	//debug_printf( "load_size : $%X\n", load_size );
+	//debug_printf( "bank_size : $%X\n", bank_size );
+	//debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
+
+	ram [idle_addr] = 0xFF;
+	cpu::reset( unmapped_write, unmapped_read );
+	cpu::map_mem( 0, mem_size, ram, ram );
+
+	ay.reset();
+	scc.reset();
+	if ( sn )
+		sn->reset();
+	r.sp = 0xF380;
+	ram [--r.sp] = idle_addr >> 8;
+	ram [--r.sp] = idle_addr & 0xFF;
+	r.b.a = track;
+	r.pc = GET_LE16( header_.init_addr );
+	next_play = play_period;
+	scc_accessed = false;
+	gain_updated = false;
+	update_gain();
+	ay_latch = 0;
+
+	return 0;
+}
+
+void Kss_Emu::set_bank( int logical, int physical )
+{
+	unsigned const bank_size = this->bank_size();
+
+	unsigned addr = 0x8000;
+	if ( logical && bank_size == 8 * 1024 )
+		addr = 0xA000;
+
+	physical -= header_.first_bank;
+	if ( (unsigned) physical >= (unsigned) bank_count )
+	{
+		byte* data = ram + addr;
+		cpu::map_mem( addr, bank_size, data, data );
+	}
+	else
+	{
+		long phys = physical * (blargg_long) bank_size;
+		for ( unsigned offset = 0; offset < bank_size; offset += page_size )
+			cpu::map_mem( addr + offset, page_size,
+					unmapped_write, rom.at_addr( phys + offset ) );
+	}
+}
+
+void Kss_Emu::cpu_write( unsigned addr, int data )
+{
+	data &= 0xFF;
+	switch ( addr )
+	{
+	case 0x9000:
+		set_bank( 0, data );
+		return;
+
+	case 0xB000:
+		set_bank( 1, data );
+		return;
+	}
+
+	int scc_addr = (addr & 0xDFFF) ^ 0x9800;
+	if ( scc_addr < scc.reg_count )
+	{
+		scc_accessed = true;
+		scc.write( time(), scc_addr, data );
+		return;
+	}
+
+	debug_printf( "LD ($%04X),$%02X\n", addr, data );
+}
+
+void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
+{
+	*cpu->write( addr ) = data;
+	if ( (addr & STATIC_CAST(Kss_Emu&,*cpu).scc_enabled) == 0x8000 )
+		STATIC_CAST(Kss_Emu&,*cpu).cpu_write( addr, data );
+}
+
+void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
+{
+	data &= 0xFF;
+	Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
+	switch ( addr & 0xFF )
+	{
+	case 0xA0:
+		emu.ay_latch = data & 0x0F;
+		return;
+
+	case 0xA1:
+		GME_APU_HOOK( &emu, emu.ay_latch, data );
+		emu.ay.write( time, emu.ay_latch, data );
+		return;
+
+	case 0x06:
+		if ( emu.sn && (emu.header_.device_flags & 0x04) )
+		{
+			emu.sn->write_ggstereo( time, data );
+			return;
+		}
+		break;
+
+	case 0x7E:
+	case 0x7F:
+		if ( emu.sn )
+		{
+			GME_APU_HOOK( &emu, 16, data );
+			emu.sn->write_data( time, data );
+			return;
+		}
+		break;
+
+	case 0xFE:
+		emu.set_bank( 0, data );
+		return;
+
+	#ifndef NDEBUG
+	case 0xF1: // FM data
+		if ( data )
+			break; // trap non-zero data
+	case 0xF0: // FM addr
+	case 0xA8: // PPI
+		return;
+	#endif
+	}
+
+	debug_printf( "OUT $%04X,$%02X\n", addr, data );
+}
+
+int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
+{
+	//Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
+	//switch ( addr & 0xFF )
+	//{
+	//}
+
+	debug_printf( "IN $%04X\n", addr );
+	return 0;
+}
+
+// Emulation
+
+blargg_err_t Kss_Emu::run_clocks( blip_time_t& duration, int )
+{
+	while ( time() < duration )
+	{
+		blip_time_t end = min( duration, next_play );
+		cpu::run( min( duration, next_play ) );
+		if ( r.pc == idle_addr )
+			set_time( end );
+
+		if ( time() >= next_play )
+		{
+			next_play += play_period;
+			if ( r.pc == idle_addr )
+			{
+				if ( !gain_updated )
+				{
+					gain_updated = true;
+					if ( scc_accessed )
+						update_gain();
+				}
+
+				ram [--r.sp] = idle_addr >> 8;
+				ram [--r.sp] = idle_addr & 0xFF;
+				r.pc = GET_LE16( header_.play_addr );
+				GME_FRAME_HOOK( this );
+			}
+		}
+	}
+
+	duration = time();
+	next_play -= duration;
+	check( next_play >= 0 );
+	adjust_time( -duration );
+	ay.end_frame( duration );
+	scc.end_frame( duration );
+	if ( sn )
+		sn->end_frame( duration );
+
+	return 0;
+}
diff --git a/src/console/Kss_Emu.cxx b/src/console/Kss_Emu.cxx
deleted file mode 100644
index 1de2361e67f0..000000000000
--- a/src/console/Kss_Emu.cxx
+++ /dev/null
@@ -1,416 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Kss_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const clock_rate = 3579545;
-int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count;
-
-Kss_Emu::Kss_Emu()
-{
-	sn = 0;
-	set_type( gme_kss_type );
-	set_silence_lookahead( 6 );
-	static const char* const names [osc_count] = {
-		"Square 1", "Square 2", "Square 3",
-		"Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5"
-	};
-	set_voice_names( names );
-
-	static int const types [osc_count] = {
-		wave_type | 0, wave_type | 1, wave_type | 2,
-		wave_type | 3, wave_type | 4, wave_type | 5, wave_type | 6, wave_type | 7
-	};
-	set_voice_types( types );
-
-	memset( unmapped_read, 0xFF, sizeof unmapped_read );
-}
-
-Kss_Emu::~Kss_Emu() { unload(); }
-
-void Kss_Emu::unload()
-{
-	delete sn;
-	sn = 0;
-	Classic_Emu::unload();
-}
-
-// Track info
-
-static void copy_kss_fields( Kss_Emu::header_t const& h, track_info_t* out )
-{
-	const char* system = "MSX";
-	if ( h.device_flags & 0x02 )
-	{
-		system = "Sega Master System";
-		if ( h.device_flags & 0x04 )
-			system = "Game Gear";
-	}
-	Gme_File::copy_field_( out->system, system );
-}
-
-blargg_err_t Kss_Emu::track_info_( track_info_t* out, int ) const
-{
-	copy_kss_fields( header_, out );
-	return 0;
-}
-
-static blargg_err_t check_kss_header( void const* header )
-{
-	if ( memcmp( header, "KSCC", 4 ) && memcmp( header, "KSSX", 4 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Kss_File : Gme_Info_
-{
-	Kss_Emu::header_t header_;
-
-	Kss_File() { set_type( gme_kss_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		blargg_err_t err = in.read( &header_, Kss_Emu::header_size );
-		if ( err )
-			return (err == in.eof_error ? gme_wrong_file_type : err);
-		return check_kss_header( &header_ );
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		copy_kss_fields( header_, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_kss_emu () { return BLARGG_NEW Kss_Emu ; }
-static Music_Emu* new_kss_file() { return BLARGG_NEW Kss_File; }
-
-static gme_type_t_ const gme_kss_type_ = { "MSX", 256, &new_kss_emu, &new_kss_file, "KSS", 0x03 };
-gme_type_t const gme_kss_type = &gme_kss_type_;
-
-
-// Setup
-
-void Kss_Emu::update_gain()
-{
-	double g = gain() * 1.4;
-	if ( scc_accessed )
-		g *= 1.5;
-	ay.volume( g );
-	scc.volume( g );
-	if ( sn )
-		sn->volume( g );
-}
-
-blargg_err_t Kss_Emu::load_( Data_Reader& in )
-{
-	memset( &header_, 0, sizeof header_ );
-	assert( offsetof (header_t,device_flags) == header_size - 1 );
-	assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1 );
-	RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) );
-
-	RETURN_ERR( check_kss_header( header_.tag ) );
-
-	if ( header_.tag [3] == 'C' )
-	{
-		if ( header_.extra_header )
-		{
-			header_.extra_header = 0;
-			set_warning( "Unknown data in header" );
-		}
-		if ( header_.device_flags & ~0x0F )
-		{
-			header_.device_flags &= 0x0F;
-			set_warning( "Unknown data in header" );
-		}
-	}
-	else
-	{
-		ext_header_t& ext = header_;
-		memcpy( &ext, rom.begin(), min( (int) ext_header_size, (int) header_.extra_header ) );
-		if ( header_.extra_header > 0x10 )
-			set_warning( "Unknown data in header" );
-	}
-
-	if ( header_.device_flags & 0x09 )
-		set_warning( "FM sound not supported" );
-
-	scc_enabled = 0xC000;
-	if ( header_.device_flags & 0x04 )
-		scc_enabled = 0;
-
-	if ( header_.device_flags & 0x02 && !sn )
-		CHECK_ALLOC( sn = BLARGG_NEW( Sms_Apu ) );
-
-	set_voice_count( osc_count );
-
-	return setup_buffer( ::clock_rate );
-}
-
-void Kss_Emu::update_eq( blip_eq_t const& eq )
-{
-	ay.treble_eq( eq );
-	scc.treble_eq( eq );
-	if ( sn )
-		sn->treble_eq( eq );
-}
-
-void Kss_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	int i2 = i - ay.osc_count;
-	if ( i2 >= 0 )
-		scc.osc_output( i2, center );
-	else
-		ay.osc_output( i, center );
-	if ( sn && i < sn->osc_count )
-		sn->osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Kss_Emu::set_tempo_( double t )
-{
-	blip_time_t period =
-			(header_.device_flags & 0x40 ? ::clock_rate / 50 : ::clock_rate / 60);
-	play_period = blip_time_t (period / t);
-}
-
-blargg_err_t Kss_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( ram, 0xC9, 0x4000 );
-	memset( ram + 0x4000, 0, sizeof ram - 0x4000 );
-
-	// copy driver code to lo RAM
-	static byte const bios [] = {
-		0xD3, 0xA0, 0xF5, 0x7B, 0xD3, 0xA1, 0xF1, 0xC9, // $0001: WRTPSG
-		0xD3, 0xA0, 0xDB, 0xA2, 0xC9                    // $0009: RDPSG
-	};
-	static byte const vectors [] = {
-		0xC3, 0x01, 0x00,   // $0093: WRTPSG vector
-		0xC3, 0x09, 0x00,   // $0096: RDPSG vector
-	};
-	memcpy( ram + 0x01, bios,    sizeof bios );
-	memcpy( ram + 0x93, vectors, sizeof vectors );
-
-	// copy non-banked data into RAM
-	unsigned load_addr = GET_LE16( header_.load_addr );
-	long orig_load_size = GET_LE16( header_.load_size );
-	long load_size = min( orig_load_size, rom.file_size() );
-	load_size = min( load_size, long (mem_size - load_addr) );
-	if ( load_size != orig_load_size )
-		set_warning( "Excessive data size" );
-	memcpy( ram + load_addr, rom.begin() + header_.extra_header, load_size );
-
-	rom.set_addr( -load_size - header_.extra_header );
-
-	// check available bank data
-	blargg_long const bank_size = this->bank_size();
-	int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size;
-	bank_count = header_.bank_mode & 0x7F;
-	if ( bank_count > max_banks )
-	{
-		bank_count = max_banks;
-		set_warning( "Bank data missing" );
-	}
-	//debug_printf( "load_size : $%X\n", load_size );
-	//debug_printf( "bank_size : $%X\n", bank_size );
-	//debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
-
-	ram [idle_addr] = 0xFF;
-	cpu::reset( unmapped_write, unmapped_read );
-	cpu::map_mem( 0, mem_size, ram, ram );
-
-	ay.reset();
-	scc.reset();
-	if ( sn )
-		sn->reset();
-	r.sp = 0xF380;
-	ram [--r.sp] = idle_addr >> 8;
-	ram [--r.sp] = idle_addr & 0xFF;
-	r.b.a = track;
-	r.pc = GET_LE16( header_.init_addr );
-	next_play = play_period;
-	scc_accessed = false;
-	gain_updated = false;
-	update_gain();
-	ay_latch = 0;
-
-	return 0;
-}
-
-void Kss_Emu::set_bank( int logical, int physical )
-{
-	unsigned const bank_size = this->bank_size();
-
-	unsigned addr = 0x8000;
-	if ( logical && bank_size == 8 * 1024 )
-		addr = 0xA000;
-
-	physical -= header_.first_bank;
-	if ( (unsigned) physical >= (unsigned) bank_count )
-	{
-		byte* data = ram + addr;
-		cpu::map_mem( addr, bank_size, data, data );
-	}
-	else
-	{
-		long phys = physical * (blargg_long) bank_size;
-		for ( unsigned offset = 0; offset < bank_size; offset += page_size )
-			cpu::map_mem( addr + offset, page_size,
-					unmapped_write, rom.at_addr( phys + offset ) );
-	}
-}
-
-void Kss_Emu::cpu_write( unsigned addr, int data )
-{
-	data &= 0xFF;
-	switch ( addr )
-	{
-	case 0x9000:
-		set_bank( 0, data );
-		return;
-
-	case 0xB000:
-		set_bank( 1, data );
-		return;
-	}
-
-	int scc_addr = (addr & 0xDFFF) ^ 0x9800;
-	if ( scc_addr < scc.reg_count )
-	{
-		scc_accessed = true;
-		scc.write( time(), scc_addr, data );
-		return;
-	}
-
-	debug_printf( "LD ($%04X),$%02X\n", addr, data );
-}
-
-void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
-{
-	*cpu->write( addr ) = data;
-	if ( (addr & STATIC_CAST(Kss_Emu&,*cpu).scc_enabled) == 0x8000 )
-		STATIC_CAST(Kss_Emu&,*cpu).cpu_write( addr, data );
-}
-
-void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
-	data &= 0xFF;
-	Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
-	switch ( addr & 0xFF )
-	{
-	case 0xA0:
-		emu.ay_latch = data & 0x0F;
-		return;
-
-	case 0xA1:
-		GME_APU_HOOK( &emu, emu.ay_latch, data );
-		emu.ay.write( time, emu.ay_latch, data );
-		return;
-
-	case 0x06:
-		if ( emu.sn && (emu.header_.device_flags & 0x04) )
-		{
-			emu.sn->write_ggstereo( time, data );
-			return;
-		}
-		break;
-
-	case 0x7E:
-	case 0x7F:
-		if ( emu.sn )
-		{
-			GME_APU_HOOK( &emu, 16, data );
-			emu.sn->write_data( time, data );
-			return;
-		}
-		break;
-
-	case 0xFE:
-		emu.set_bank( 0, data );
-		return;
-
-	#ifndef NDEBUG
-	case 0xF1: // FM data
-		if ( data )
-			break; // trap non-zero data
-	case 0xF0: // FM addr
-	case 0xA8: // PPI
-		return;
-	#endif
-	}
-
-	debug_printf( "OUT $%04X,$%02X\n", addr, data );
-}
-
-int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
-{
-	//Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
-	//switch ( addr & 0xFF )
-	//{
-	//}
-
-	debug_printf( "IN $%04X\n", addr );
-	return 0;
-}
-
-// Emulation
-
-blargg_err_t Kss_Emu::run_clocks( blip_time_t& duration, int )
-{
-	while ( time() < duration )
-	{
-		blip_time_t end = min( duration, next_play );
-		cpu::run( min( duration, next_play ) );
-		if ( r.pc == idle_addr )
-			set_time( end );
-
-		if ( time() >= next_play )
-		{
-			next_play += play_period;
-			if ( r.pc == idle_addr )
-			{
-				if ( !gain_updated )
-				{
-					gain_updated = true;
-					if ( scc_accessed )
-						update_gain();
-				}
-
-				ram [--r.sp] = idle_addr >> 8;
-				ram [--r.sp] = idle_addr & 0xFF;
-				r.pc = GET_LE16( header_.play_addr );
-				GME_FRAME_HOOK( this );
-			}
-		}
-	}
-
-	duration = time();
-	next_play -= duration;
-	check( next_play >= 0 );
-	adjust_time( -duration );
-	ay.end_frame( duration );
-	scc.end_frame( duration );
-	if ( sn )
-		sn->end_frame( duration );
-
-	return 0;
-}
diff --git a/src/console/Kss_Emu.h b/src/console/Kss_Emu.h
index e209555a0cec..715cd37ff0f5 100644
--- a/src/console/Kss_Emu.h
+++ b/src/console/Kss_Emu.h
@@ -68,7 +68,6 @@ private:
 	void update_gain();
 
 	unsigned scc_enabled; // 0 or 0xC000
-	byte const* bank_data;
 	int bank_count;
 	void set_bank( int logical, int physical );
 	blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
diff --git a/src/console/Kss_Scc_Apu.cc b/src/console/Kss_Scc_Apu.cc
new file mode 100644
index 000000000000..960ab6010eae
--- /dev/null
+++ b/src/console/Kss_Scc_Apu.cc
@@ -0,0 +1,97 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Kss_Scc_Apu.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Tones above this frequency are treated as disabled tone at half volume.
+// Power of two is more efficient (avoids division).
+unsigned const inaudible_freq = 16384;
+
+int const wave_size = 0x20;
+
+void Scc_Apu::run_until( blip_time_t end_time )
+{
+	for ( int index = 0; index < osc_count; index++ )
+	{
+		osc_t& osc = oscs [index];
+
+		Blip_Buffer* const output = osc.output;
+		if ( !output )
+			continue;
+		output->set_modified();
+
+		blip_time_t period = (regs [0x80 + index * 2 + 1] & 0x0F) * 0x100 +
+				regs [0x80 + index * 2] + 1;
+		int volume = 0;
+		if ( regs [0x8F] & (1 << index) )
+		{
+			blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() +
+					inaudible_freq * 32) / (inaudible_freq * 16);
+			if ( period > inaudible_period )
+				volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15);
+		}
+
+		int8_t const* wave = (int8_t*) regs + index * wave_size;
+		if ( index == osc_count - 1 )
+			wave -= wave_size; // last two oscs share wave
+		{
+			int amp = wave [osc.phase] * volume;
+			int delta = amp - osc.last_amp;
+			if ( delta )
+			{
+				osc.last_amp = amp;
+				synth.offset( last_time, delta, output );
+			}
+		}
+
+		blip_time_t time = last_time + osc.delay;
+		if ( time < end_time )
+		{
+			if ( !volume )
+			{
+				// maintain phase
+				blargg_long count = (end_time - time + period - 1) / period;
+				osc.phase = (osc.phase + count) & (wave_size - 1);
+				time += count * period;
+			}
+			else
+			{
+
+				int phase = osc.phase;
+				int last_wave = wave [phase];
+				phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop
+
+				do
+				{
+					int amp = wave [phase];
+					phase = (phase + 1) & (wave_size - 1);
+					int delta = amp - last_wave;
+					if ( delta )
+					{
+						last_wave = amp;
+						synth.offset( time, delta * volume, output );
+					}
+					time += period;
+				}
+				while ( time < end_time );
+
+				osc.phase = phase = (phase - 1) & (wave_size - 1); // undo pre-advance
+				osc.last_amp = wave [phase] * volume;
+			}
+		}
+		osc.delay = time - end_time;
+	}
+	last_time = end_time;
+}
diff --git a/src/console/Kss_Scc_Apu.cxx b/src/console/Kss_Scc_Apu.cxx
deleted file mode 100644
index 960ab6010eae..000000000000
--- a/src/console/Kss_Scc_Apu.cxx
+++ /dev/null
@@ -1,97 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Kss_Scc_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const wave_size = 0x20;
-
-void Scc_Apu::run_until( blip_time_t end_time )
-{
-	for ( int index = 0; index < osc_count; index++ )
-	{
-		osc_t& osc = oscs [index];
-
-		Blip_Buffer* const output = osc.output;
-		if ( !output )
-			continue;
-		output->set_modified();
-
-		blip_time_t period = (regs [0x80 + index * 2 + 1] & 0x0F) * 0x100 +
-				regs [0x80 + index * 2] + 1;
-		int volume = 0;
-		if ( regs [0x8F] & (1 << index) )
-		{
-			blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() +
-					inaudible_freq * 32) / (inaudible_freq * 16);
-			if ( period > inaudible_period )
-				volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15);
-		}
-
-		int8_t const* wave = (int8_t*) regs + index * wave_size;
-		if ( index == osc_count - 1 )
-			wave -= wave_size; // last two oscs share wave
-		{
-			int amp = wave [osc.phase] * volume;
-			int delta = amp - osc.last_amp;
-			if ( delta )
-			{
-				osc.last_amp = amp;
-				synth.offset( last_time, delta, output );
-			}
-		}
-
-		blip_time_t time = last_time + osc.delay;
-		if ( time < end_time )
-		{
-			if ( !volume )
-			{
-				// maintain phase
-				blargg_long count = (end_time - time + period - 1) / period;
-				osc.phase = (osc.phase + count) & (wave_size - 1);
-				time += count * period;
-			}
-			else
-			{
-
-				int phase = osc.phase;
-				int last_wave = wave [phase];
-				phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop
-
-				do
-				{
-					int amp = wave [phase];
-					phase = (phase + 1) & (wave_size - 1);
-					int delta = amp - last_wave;
-					if ( delta )
-					{
-						last_wave = amp;
-						synth.offset( time, delta * volume, output );
-					}
-					time += period;
-				}
-				while ( time < end_time );
-
-				osc.phase = phase = (phase - 1) & (wave_size - 1); // undo pre-advance
-				osc.last_amp = wave [phase] * volume;
-			}
-		}
-		osc.delay = time - end_time;
-	}
-	last_time = end_time;
-}
diff --git a/src/console/Kss_Scc_Apu.h b/src/console/Kss_Scc_Apu.h
index 59587331f947..74dffa861e48 100644
--- a/src/console/Kss_Scc_Apu.h
+++ b/src/console/Kss_Scc_Apu.h
@@ -10,7 +10,7 @@
 
 class Scc_Apu {
 public:
-	// Set buffer to generate all sound into, or disable sound if NULL
+	// Set buffer to generate all sound into, or disable sound if nullptr
 	void output( Blip_Buffer* );
 
 	// Reset sound chip
@@ -28,7 +28,7 @@ public:
 // Additional features
 
 	// Set sound output of specific oscillator to buffer, where index is
-	// 0 to 4. If buffer is NULL, the specified oscillator is muted.
+	// 0 to 4. If buffer is nullptr, the specified oscillator is muted.
 	enum { osc_count = 5 };
 	void osc_output( int index, Blip_Buffer* );
 
diff --git a/src/console/M3u_Playlist.cc b/src/console/M3u_Playlist.cc
new file mode 100644
index 000000000000..a52248c689ff
--- /dev/null
+++ b/src/console/M3u_Playlist.cc
@@ -0,0 +1,426 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "M3u_Playlist.h"
+#include "Music_Emu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// gme functions defined here to avoid linking in m3u code unless it's used
+
+blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
+{
+	require( raw_track_count_ ); // file must be loaded first
+
+	if ( !err )
+	{
+		if ( playlist.size() )
+			track_count_ = playlist.size();
+
+		int line = playlist.first_error();
+		if ( line )
+		{
+			// avoid using bloated printf()
+			char* out = &playlist_warning [sizeof playlist_warning];
+			*--out = 0;
+			do {
+				*--out = line % 10 + '0';
+			} while ( (line /= 10) > 0 );
+
+			static const char str [] = "Problem in m3u at line ";
+			out -= sizeof str - 1;
+			memcpy( out, str, sizeof str - 1 );
+			set_warning( out );
+		}
+	}
+	return err;
+}
+
+blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist.load( path ) ); }
+
+blargg_err_t Gme_File::load_m3u( Data_Reader& in )  { return load_m3u_( playlist.load( in ) ); }
+
+BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
+
+BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
+{
+	Mem_File_Reader in( data, size );
+	return me->load_m3u( in );
+}
+
+
+
+static char* skip_white( char* in )
+{
+	while ( *in == ' ' )
+		in++;
+	return in;
+}
+
+inline unsigned from_dec( unsigned n ) { return n - '0'; }
+
+static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
+{
+	entry.file = in;
+	entry.type = "";
+	char* out = in;
+	while ( 1 )
+	{
+		int c = *in;
+		if ( !c ) break;
+		in++;
+
+		if ( c == ',' ) // commas in filename
+		{
+			char* p = skip_white( in );
+			if ( *p == '$' || from_dec( *p ) <= 9 )
+			{
+				in = p;
+				break;
+			}
+		}
+
+		if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
+		{
+			entry.type = ++in;
+			while ( (c = *in) != 0 && c != ',' )
+				in++;
+			if ( c == ',' )
+			{
+				*in++ = 0; // terminate type
+				in = skip_white( in );
+			}
+			break;
+		}
+
+		if ( c == '\\' ) // \ prefix for special characters
+		{
+			c = *in;
+			if ( !c ) break;
+			in++;
+		}
+		*out++ = (char) c;
+	}
+	*out = 0; // terminate string
+	return in;
+}
+
+static char* next_field( char* in, int* result )
+{
+	while ( 1 )
+	{
+		in = skip_white( in );
+
+		if ( !*in )
+			break;
+
+		if ( *in == ',' )
+		{
+			in++;
+			break;
+		}
+
+		*result = 1;
+		in++;
+	}
+	return skip_white( in );
+}
+
+static char* parse_int_( char* in, int* out )
+{
+	int n = 0;
+	while ( 1 )
+	{
+		unsigned d = from_dec( *in );
+		if ( d > 9 )
+			break;
+		in++;
+		n = n * 10 + d;
+		*out = n;
+	}
+	return in;
+}
+
+static char* parse_int( char* in, int* out, int* result )
+{
+	return next_field( parse_int_( in, out ), result );
+}
+
+// Returns 16 or greater if not hex
+inline int from_hex_char( int h )
+{
+	h -= 0x30;
+	if ( (unsigned) h > 9 )
+		h = ((h - 0x11) & 0xDF) + 10;
+	return h;
+}
+
+static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
+{
+	if ( *in == '$' )
+	{
+		in++;
+		int n = 0;
+		while ( 1 )
+		{
+			int h = from_hex_char( *in );
+			if ( h > 15 )
+				break;
+			in++;
+			n = n * 16 + h;
+			entry.track = n;
+		}
+	}
+	else
+	{
+		in = parse_int_( in, &entry.track );
+		if ( entry.track >= 0 )
+			entry.decimal_track = 1;
+	}
+	return next_field( in, result );
+}
+
+static char* parse_time_( char* in, int* out )
+{
+	*out = -1;
+	int n = -1;
+	in = parse_int_( in, &n );
+	if ( n >= 0 )
+	{
+		*out = n;
+		if ( *in == ':' )
+		{
+			n = -1;
+			in = parse_int_( in + 1, &n );
+			if ( n >= 0 )
+				*out = *out * 60 + n;
+		}
+	}
+	return in;
+}
+
+static char* parse_time( char* in, int* out, int* result )
+{
+	return next_field( parse_time_( in, out ), result );
+}
+
+static char* parse_name( char* in )
+{
+	char* out = in;
+	while ( 1 )
+	{
+		int c = *in;
+		if ( !c ) break;
+		in++;
+
+		if ( c == ',' ) // commas in string
+		{
+			char* p = skip_white( in );
+			if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
+			{
+				in = p;
+				break;
+			}
+		}
+
+		if ( c == '\\' ) // \ prefix for special characters
+		{
+			c = *in;
+			if ( !c ) break;
+			in++;
+		}
+		*out++ = (char) c;
+	}
+	*out = 0; // terminate string
+	return in;
+}
+
+static int parse_line( char* in, M3u_Playlist::entry_t& entry )
+{
+	int result = 0;
+
+	// file
+	entry.file = in;
+	entry.type = "";
+	in = parse_filename( in, entry );
+
+	// track
+	entry.track = -1;
+	entry.decimal_track = 0;
+	in = parse_track( in, entry, &result );
+
+	// name
+	entry.name = in;
+	in = parse_name( in );
+
+	// time
+	entry.length = -1;
+	in = parse_time( in, &entry.length, &result );
+
+	// loop
+	entry.intro = -1;
+	entry.loop  = -1;
+	if ( *in == '-' )
+	{
+		entry.loop = entry.length;
+		in++;
+	}
+	else
+	{
+		in = parse_time_( in, &entry.loop );
+		if ( entry.loop >= 0 )
+		{
+			entry.intro = 0;
+			if ( *in == '-' ) // trailing '-' means that intro length was specified
+			{
+				in++;
+				entry.intro = entry.loop;
+				entry.loop  = entry.length - entry.intro;
+			}
+		}
+	}
+	in = next_field( in, &result );
+
+	// fade
+	entry.fade = -1;
+	in = parse_time( in, &entry.fade, &result );
+
+	// repeat
+	entry.repeat = -1;
+	in = parse_int( in, &entry.repeat, &result );
+
+	return result;
+}
+
+static void parse_comment( char* in, M3u_Playlist::info_t& info, bool first )
+{
+	in = skip_white( in + 1 );
+	const char* field = in;
+	while ( *in && *in != ':' )
+		in++;
+
+	if ( *in == ':' )
+	{
+		const char* text = skip_white( in + 1 );
+		if ( *text )
+		{
+			*in = 0;
+			     if ( !strcmp( "Composer", field ) ) info.composer = text;
+			else if ( !strcmp( "Engineer", field ) ) info.engineer = text;
+			else if ( !strcmp( "Ripping" , field ) ) info.ripping  = text;
+			else if ( !strcmp( "Tagging" , field ) ) info.tagging  = text;
+			else
+				text = 0;
+			if ( text )
+				return;
+			*in = ':';
+		}
+	}
+
+	if ( first )
+		info.title = field;
+}
+
+blargg_err_t M3u_Playlist::parse_()
+{
+	info_.title    = "";
+	info_.composer = "";
+	info_.engineer = "";
+	info_.ripping  = "";
+	info_.tagging  = "";
+
+	int const CR = 13;
+	int const LF = 10;
+
+	data.end() [-1] = LF; // terminate input
+
+	first_error_ = 0;
+	bool first_comment = true;
+	int line  = 0;
+	int count = 0;
+	char* in  = data.begin();
+	while ( in < data.end() )
+	{
+		// find end of line and terminate it
+		line++;
+		char* begin = in;
+		while ( *in != CR && *in != LF )
+		{
+			if ( !*in )
+				return "Not an m3u playlist";
+			in++;
+		}
+		if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
+			*in++ = 0;
+		*in++ = 0;
+
+		// parse line
+		if ( *begin == '#' )
+		{
+			parse_comment( begin, info_, first_comment );
+			first_comment = false;
+		}
+		else if ( *begin )
+		{
+			if ( (int) entries.size() <= count )
+				RETURN_ERR( entries.resize( count * 2 + 64 ) );
+
+			if ( !parse_line( begin, entries [count] ) )
+				count++;
+			else if ( !first_error_ )
+				first_error_ = line;
+			first_comment = false;
+		}
+	}
+	if ( count <= 0 )
+		return "Not an m3u playlist";
+
+	if ( !(info_.composer [0] | info_.engineer [0] | info_.ripping [0] | info_.tagging [0]) )
+		info_.title = "";
+
+	return entries.resize( count );
+}
+
+blargg_err_t M3u_Playlist::parse()
+{
+	blargg_err_t err = parse_();
+	if ( err )
+	{
+		entries.clear();
+		data.clear();
+	}
+	return err;
+}
+
+blargg_err_t M3u_Playlist::load( Data_Reader& in )
+{
+	RETURN_ERR( data.resize( in.remain() + 1 ) );
+	RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
+	return parse();
+}
+
+blargg_err_t M3u_Playlist::load( const char* path )
+{
+	GME_FILE_READER in;
+	RETURN_ERR( in.open( path ) );
+	return load( in );
+}
+
+blargg_err_t M3u_Playlist::load( void const* in, long size )
+{
+	RETURN_ERR( data.resize( size + 1 ) );
+	memcpy( data.begin(), in, size );
+	return parse();
+}
diff --git a/src/console/M3u_Playlist.cxx b/src/console/M3u_Playlist.cxx
deleted file mode 100644
index a52248c689ff..000000000000
--- a/src/console/M3u_Playlist.cxx
+++ /dev/null
@@ -1,426 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "M3u_Playlist.h"
-#include "Music_Emu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// gme functions defined here to avoid linking in m3u code unless it's used
-
-blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
-{
-	require( raw_track_count_ ); // file must be loaded first
-
-	if ( !err )
-	{
-		if ( playlist.size() )
-			track_count_ = playlist.size();
-
-		int line = playlist.first_error();
-		if ( line )
-		{
-			// avoid using bloated printf()
-			char* out = &playlist_warning [sizeof playlist_warning];
-			*--out = 0;
-			do {
-				*--out = line % 10 + '0';
-			} while ( (line /= 10) > 0 );
-
-			static const char str [] = "Problem in m3u at line ";
-			out -= sizeof str - 1;
-			memcpy( out, str, sizeof str - 1 );
-			set_warning( out );
-		}
-	}
-	return err;
-}
-
-blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist.load( path ) ); }
-
-blargg_err_t Gme_File::load_m3u( Data_Reader& in )  { return load_m3u_( playlist.load( in ) ); }
-
-BLARGG_EXPORT gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
-
-BLARGG_EXPORT gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
-{
-	Mem_File_Reader in( data, size );
-	return me->load_m3u( in );
-}
-
-
-
-static char* skip_white( char* in )
-{
-	while ( *in == ' ' )
-		in++;
-	return in;
-}
-
-inline unsigned from_dec( unsigned n ) { return n - '0'; }
-
-static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
-{
-	entry.file = in;
-	entry.type = "";
-	char* out = in;
-	while ( 1 )
-	{
-		int c = *in;
-		if ( !c ) break;
-		in++;
-
-		if ( c == ',' ) // commas in filename
-		{
-			char* p = skip_white( in );
-			if ( *p == '$' || from_dec( *p ) <= 9 )
-			{
-				in = p;
-				break;
-			}
-		}
-
-		if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
-		{
-			entry.type = ++in;
-			while ( (c = *in) != 0 && c != ',' )
-				in++;
-			if ( c == ',' )
-			{
-				*in++ = 0; // terminate type
-				in = skip_white( in );
-			}
-			break;
-		}
-
-		if ( c == '\\' ) // \ prefix for special characters
-		{
-			c = *in;
-			if ( !c ) break;
-			in++;
-		}
-		*out++ = (char) c;
-	}
-	*out = 0; // terminate string
-	return in;
-}
-
-static char* next_field( char* in, int* result )
-{
-	while ( 1 )
-	{
-		in = skip_white( in );
-
-		if ( !*in )
-			break;
-
-		if ( *in == ',' )
-		{
-			in++;
-			break;
-		}
-
-		*result = 1;
-		in++;
-	}
-	return skip_white( in );
-}
-
-static char* parse_int_( char* in, int* out )
-{
-	int n = 0;
-	while ( 1 )
-	{
-		unsigned d = from_dec( *in );
-		if ( d > 9 )
-			break;
-		in++;
-		n = n * 10 + d;
-		*out = n;
-	}
-	return in;
-}
-
-static char* parse_int( char* in, int* out, int* result )
-{
-	return next_field( parse_int_( in, out ), result );
-}
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
-	h -= 0x30;
-	if ( (unsigned) h > 9 )
-		h = ((h - 0x11) & 0xDF) + 10;
-	return h;
-}
-
-static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
-{
-	if ( *in == '$' )
-	{
-		in++;
-		int n = 0;
-		while ( 1 )
-		{
-			int h = from_hex_char( *in );
-			if ( h > 15 )
-				break;
-			in++;
-			n = n * 16 + h;
-			entry.track = n;
-		}
-	}
-	else
-	{
-		in = parse_int_( in, &entry.track );
-		if ( entry.track >= 0 )
-			entry.decimal_track = 1;
-	}
-	return next_field( in, result );
-}
-
-static char* parse_time_( char* in, int* out )
-{
-	*out = -1;
-	int n = -1;
-	in = parse_int_( in, &n );
-	if ( n >= 0 )
-	{
-		*out = n;
-		if ( *in == ':' )
-		{
-			n = -1;
-			in = parse_int_( in + 1, &n );
-			if ( n >= 0 )
-				*out = *out * 60 + n;
-		}
-	}
-	return in;
-}
-
-static char* parse_time( char* in, int* out, int* result )
-{
-	return next_field( parse_time_( in, out ), result );
-}
-
-static char* parse_name( char* in )
-{
-	char* out = in;
-	while ( 1 )
-	{
-		int c = *in;
-		if ( !c ) break;
-		in++;
-
-		if ( c == ',' ) // commas in string
-		{
-			char* p = skip_white( in );
-			if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
-			{
-				in = p;
-				break;
-			}
-		}
-
-		if ( c == '\\' ) // \ prefix for special characters
-		{
-			c = *in;
-			if ( !c ) break;
-			in++;
-		}
-		*out++ = (char) c;
-	}
-	*out = 0; // terminate string
-	return in;
-}
-
-static int parse_line( char* in, M3u_Playlist::entry_t& entry )
-{
-	int result = 0;
-
-	// file
-	entry.file = in;
-	entry.type = "";
-	in = parse_filename( in, entry );
-
-	// track
-	entry.track = -1;
-	entry.decimal_track = 0;
-	in = parse_track( in, entry, &result );
-
-	// name
-	entry.name = in;
-	in = parse_name( in );
-
-	// time
-	entry.length = -1;
-	in = parse_time( in, &entry.length, &result );
-
-	// loop
-	entry.intro = -1;
-	entry.loop  = -1;
-	if ( *in == '-' )
-	{
-		entry.loop = entry.length;
-		in++;
-	}
-	else
-	{
-		in = parse_time_( in, &entry.loop );
-		if ( entry.loop >= 0 )
-		{
-			entry.intro = 0;
-			if ( *in == '-' ) // trailing '-' means that intro length was specified
-			{
-				in++;
-				entry.intro = entry.loop;
-				entry.loop  = entry.length - entry.intro;
-			}
-		}
-	}
-	in = next_field( in, &result );
-
-	// fade
-	entry.fade = -1;
-	in = parse_time( in, &entry.fade, &result );
-
-	// repeat
-	entry.repeat = -1;
-	in = parse_int( in, &entry.repeat, &result );
-
-	return result;
-}
-
-static void parse_comment( char* in, M3u_Playlist::info_t& info, bool first )
-{
-	in = skip_white( in + 1 );
-	const char* field = in;
-	while ( *in && *in != ':' )
-		in++;
-
-	if ( *in == ':' )
-	{
-		const char* text = skip_white( in + 1 );
-		if ( *text )
-		{
-			*in = 0;
-			     if ( !strcmp( "Composer", field ) ) info.composer = text;
-			else if ( !strcmp( "Engineer", field ) ) info.engineer = text;
-			else if ( !strcmp( "Ripping" , field ) ) info.ripping  = text;
-			else if ( !strcmp( "Tagging" , field ) ) info.tagging  = text;
-			else
-				text = 0;
-			if ( text )
-				return;
-			*in = ':';
-		}
-	}
-
-	if ( first )
-		info.title = field;
-}
-
-blargg_err_t M3u_Playlist::parse_()
-{
-	info_.title    = "";
-	info_.composer = "";
-	info_.engineer = "";
-	info_.ripping  = "";
-	info_.tagging  = "";
-
-	int const CR = 13;
-	int const LF = 10;
-
-	data.end() [-1] = LF; // terminate input
-
-	first_error_ = 0;
-	bool first_comment = true;
-	int line  = 0;
-	int count = 0;
-	char* in  = data.begin();
-	while ( in < data.end() )
-	{
-		// find end of line and terminate it
-		line++;
-		char* begin = in;
-		while ( *in != CR && *in != LF )
-		{
-			if ( !*in )
-				return "Not an m3u playlist";
-			in++;
-		}
-		if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
-			*in++ = 0;
-		*in++ = 0;
-
-		// parse line
-		if ( *begin == '#' )
-		{
-			parse_comment( begin, info_, first_comment );
-			first_comment = false;
-		}
-		else if ( *begin )
-		{
-			if ( (int) entries.size() <= count )
-				RETURN_ERR( entries.resize( count * 2 + 64 ) );
-
-			if ( !parse_line( begin, entries [count] ) )
-				count++;
-			else if ( !first_error_ )
-				first_error_ = line;
-			first_comment = false;
-		}
-	}
-	if ( count <= 0 )
-		return "Not an m3u playlist";
-
-	if ( !(info_.composer [0] | info_.engineer [0] | info_.ripping [0] | info_.tagging [0]) )
-		info_.title = "";
-
-	return entries.resize( count );
-}
-
-blargg_err_t M3u_Playlist::parse()
-{
-	blargg_err_t err = parse_();
-	if ( err )
-	{
-		entries.clear();
-		data.clear();
-	}
-	return err;
-}
-
-blargg_err_t M3u_Playlist::load( Data_Reader& in )
-{
-	RETURN_ERR( data.resize( in.remain() + 1 ) );
-	RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
-	return parse();
-}
-
-blargg_err_t M3u_Playlist::load( const char* path )
-{
-	GME_FILE_READER in;
-	RETURN_ERR( in.open( path ) );
-	return load( in );
-}
-
-blargg_err_t M3u_Playlist::load( void const* in, long size )
-{
-	RETURN_ERR( data.resize( size + 1 ) );
-	memcpy( data.begin(), in, size );
-	return parse();
-}
diff --git a/src/console/Makefile b/src/console/Makefile
index 33fd260c5023..c3714b894e5a 100644
--- a/src/console/Makefile
+++ b/src/console/Makefile
@@ -1,57 +1,57 @@
 PLUGIN = console${PLUGIN_SUFFIX}
 
-SRCS = Ay_Apu.cxx              \
-       Ay_Cpu.cxx              \
-       Ay_Emu.cxx              \
-       Blip_Buffer.cxx         \
-       Classic_Emu.cxx         \
-       Data_Reader.cxx         \
-       Dual_Resampler.cxx      \
-       Effects_Buffer.cxx      \
-       Fir_Resampler.cxx       \
-       Gbs_Emu.cxx             \
-       Gb_Apu.cxx              \
-       Gb_Cpu.cxx              \
-       Gb_Oscs.cxx             \
-       gme.cxx                 \
-       Gme_File.cxx            \
-       Gym_Emu.cxx             \
-       Gzip_Reader.cxx         \
-       Hes_Apu.cxx             \
-       Hes_Cpu.cxx             \
-       Hes_Emu.cxx             \
-       Kss_Cpu.cxx             \
-       Kss_Emu.cxx             \
-       Kss_Scc_Apu.cxx         \
-       M3u_Playlist.cxx        \
-       Multi_Buffer.cxx        \
-       Music_Emu.cxx           \
-       Nes_Apu.cxx             \
-       Nes_Cpu.cxx             \
-       Nes_Fme7_Apu.cxx        \
-       Nes_Namco_Apu.cxx       \
-       Nes_Oscs.cxx            \
-       Nes_Vrc6_Apu.cxx        \
-       Nsfe_Emu.cxx            \
-       Nsf_Emu.cxx             \
-       Sap_Apu.cxx             \
-       Sap_Cpu.cxx             \
-       Sap_Emu.cxx             \
-       Sms_Apu.cxx             \
-       Snes_Spc.cxx            \
-       Spc_Cpu.cxx             \
-       Spc_Dsp.cxx             \
-       Spc_Emu.cxx             \
-       Spc_Filter.cxx          \
-       Vfs_File.cxx            \
-       Vgm_Emu.cxx             \
-       Vgm_Emu_Impl.cxx        \
-       Ym2413_Emu.cxx          \
-       Ym2612_Emu.cxx          \
-       Zlib_Inflater.cxx       \
-       Audacious_Driver.cxx    \
-       configure.c             \
-       plugin.c
+SRCS = Ay_Apu.cc              \
+       Ay_Cpu.cc              \
+       Ay_Emu.cc              \
+       Blip_Buffer.cc         \
+       Classic_Emu.cc         \
+       Data_Reader.cc         \
+       Dual_Resampler.cc      \
+       Effects_Buffer.cc      \
+       Fir_Resampler.cc       \
+       Gbs_Emu.cc             \
+       Gb_Apu.cc              \
+       Gb_Cpu.cc              \
+       Gb_Oscs.cc             \
+       gme.cc                 \
+       Gme_File.cc            \
+       Gym_Emu.cc             \
+       Gzip_Reader.cc         \
+       Hes_Apu.cc             \
+       Hes_Cpu.cc             \
+       Hes_Emu.cc             \
+       Kss_Cpu.cc             \
+       Kss_Emu.cc             \
+       Kss_Scc_Apu.cc         \
+       M3u_Playlist.cc        \
+       Multi_Buffer.cc        \
+       Music_Emu.cc           \
+       Nes_Apu.cc             \
+       Nes_Cpu.cc             \
+       Nes_Fme7_Apu.cc        \
+       Nes_Namco_Apu.cc       \
+       Nes_Oscs.cc            \
+       Nes_Vrc6_Apu.cc        \
+       Nsfe_Emu.cc            \
+       Nsf_Emu.cc             \
+       Sap_Apu.cc             \
+       Sap_Cpu.cc             \
+       Sap_Emu.cc             \
+       Sms_Apu.cc             \
+       Snes_Spc.cc            \
+       Spc_Cpu.cc             \
+       Spc_Dsp.cc             \
+       Spc_Emu.cc             \
+       Spc_Filter.cc          \
+       Vfs_File.cc            \
+       Vgm_Emu.cc             \
+       Vgm_Emu_Impl.cc        \
+       Ym2413_Emu.cc          \
+       Ym2612_Emu.cc          \
+       Zlib_Inflater.cc       \
+       Audacious_Driver.cc    \
+       configure.cc             \
+       plugin.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -62,5 +62,5 @@ LD = ${CXX}
 
 CFLAGS += ${PLUGIN_CFLAGS}
 CXXFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
 LIBS += -lz
diff --git a/src/console/Multi_Buffer.cc b/src/console/Multi_Buffer.cc
new file mode 100644
index 000000000000..13770dbb287f
--- /dev/null
+++ b/src/console/Multi_Buffer.cc
@@ -0,0 +1,232 @@
+// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+
+#include "Multi_Buffer.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
+{
+	length_ = 0;
+	sample_rate_ = 0;
+	channels_changed_count_ = 1;
+}
+
+blargg_err_t Multi_Buffer::set_channel_count( int ) { return 0; }
+
+// Silent_Buffer
+
+Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
+{
+	// TODO: better to use empty Blip_Buffer so caller never has to check for nullptr?
+	chan.left   = 0;
+	chan.center = 0;
+	chan.right  = 0;
+}
+
+// Mono_Buffer
+
+Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
+{
+	chan.center = &buf;
+	chan.left   = &buf;
+	chan.right  = &buf;
+}
+
+Mono_Buffer::~Mono_Buffer() { }
+
+blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
+{
+	RETURN_ERR( buf.set_sample_rate( rate, msec ) );
+	return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
+}
+
+// Stereo_Buffer
+
+Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
+{
+	chan.center = &bufs [0];
+	chan.left = &bufs [1];
+	chan.right = &bufs [2];
+}
+
+Stereo_Buffer::~Stereo_Buffer() { }
+
+blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
+{
+	for ( int i = 0; i < buf_count; i++ )
+		RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
+	return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
+}
+
+void Stereo_Buffer::clock_rate( long rate )
+{
+	for ( int i = 0; i < buf_count; i++ )
+		bufs [i].clock_rate( rate );
+}
+
+void Stereo_Buffer::bass_freq( int bass )
+{
+	for ( unsigned i = 0; i < buf_count; i++ )
+		bufs [i].bass_freq( bass );
+}
+
+void Stereo_Buffer::clear()
+{
+	stereo_added = 0;
+	was_stereo   = false;
+	for ( int i = 0; i < buf_count; i++ )
+		bufs [i].clear();
+}
+
+void Stereo_Buffer::end_frame( blip_time_t clock_count )
+{
+	stereo_added = 0;
+	for ( unsigned i = 0; i < buf_count; i++ )
+	{
+		stereo_added |= bufs [i].clear_modified() << i;
+		bufs [i].end_frame( clock_count );
+	}
+}
+
+long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
+{
+	require( !(count & 1) ); // count must be even
+	count = (unsigned) count / 2;
+
+	long avail = bufs [0].samples_avail();
+	if ( count > avail )
+		count = avail;
+	if ( count )
+	{
+		int bufs_used = stereo_added | was_stereo;
+		//debug_printf( "%X\n", bufs_used );
+		if ( bufs_used <= 1 )
+		{
+			mix_mono( out, count );
+			bufs [0].remove_samples( count );
+			bufs [1].remove_silence( count );
+			bufs [2].remove_silence( count );
+		}
+		else if ( bufs_used & 1 )
+		{
+			mix_stereo( out, count );
+			bufs [0].remove_samples( count );
+			bufs [1].remove_samples( count );
+			bufs [2].remove_samples( count );
+		}
+		else
+		{
+			mix_stereo_no_center( out, count );
+			bufs [0].remove_silence( count );
+			bufs [1].remove_samples( count );
+			bufs [2].remove_samples( count );
+		}
+
+		// to do: this might miss opportunities for optimization
+		if ( !bufs [0].samples_avail() )
+		{
+			was_stereo   = stereo_added;
+			stereo_added = 0;
+		}
+	}
+
+	return count * 2;
+}
+
+void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [1] );
+	BLIP_READER_BEGIN( left, bufs [1] );
+	BLIP_READER_BEGIN( right, bufs [2] );
+	BLIP_READER_BEGIN( center, bufs [0] );
+
+	for ( ; count; --count )
+	{
+		int c = BLIP_READER_READ( center );
+		blargg_long l = c + BLIP_READER_READ( left );
+		blargg_long r = c + BLIP_READER_READ( right );
+		if ( (int16_t) l != l )
+			l = 0x7FFF - (l >> 24);
+
+		BLIP_READER_NEXT( center, bass );
+		if ( (int16_t) r != r )
+			r = 0x7FFF - (r >> 24);
+
+		BLIP_READER_NEXT( left, bass );
+		BLIP_READER_NEXT( right, bass );
+
+		out [0] = l;
+		out [1] = r;
+		out += 2;
+	}
+
+	BLIP_READER_END( center, bufs [0] );
+	BLIP_READER_END( right, bufs [2] );
+	BLIP_READER_END( left, bufs [1] );
+}
+
+void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [1] );
+	BLIP_READER_BEGIN( left, bufs [1] );
+	BLIP_READER_BEGIN( right, bufs [2] );
+
+	for ( ; count; --count )
+	{
+		blargg_long l = BLIP_READER_READ( left );
+		if ( (int16_t) l != l )
+			l = 0x7FFF - (l >> 24);
+
+		blargg_long r = BLIP_READER_READ( right );
+		if ( (int16_t) r != r )
+			r = 0x7FFF - (r >> 24);
+
+		BLIP_READER_NEXT( left, bass );
+		BLIP_READER_NEXT( right, bass );
+
+		out [0] = l;
+		out [1] = r;
+		out += 2;
+	}
+
+	BLIP_READER_END( right, bufs [2] );
+	BLIP_READER_END( left, bufs [1] );
+}
+
+void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( bufs [0] );
+	BLIP_READER_BEGIN( center, bufs [0] );
+
+	for ( ; count; --count )
+	{
+		blargg_long s = BLIP_READER_READ( center );
+		if ( (int16_t) s != s )
+			s = 0x7FFF - (s >> 24);
+
+		BLIP_READER_NEXT( center, bass );
+		out [0] = s;
+		out [1] = s;
+		out += 2;
+	}
+
+	BLIP_READER_END( center, bufs [0] );
+}
diff --git a/src/console/Multi_Buffer.cxx b/src/console/Multi_Buffer.cxx
deleted file mode 100644
index dd74b44f5387..000000000000
--- a/src/console/Multi_Buffer.cxx
+++ /dev/null
@@ -1,232 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Multi_Buffer.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
-	length_ = 0;
-	sample_rate_ = 0;
-	channels_changed_count_ = 1;
-}
-
-blargg_err_t Multi_Buffer::set_channel_count( int ) { return 0; }
-
-// Silent_Buffer
-
-Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
-{
-	// TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
-	chan.left   = 0;
-	chan.center = 0;
-	chan.right  = 0;
-}
-
-// Mono_Buffer
-
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
-	chan.center = &buf;
-	chan.left   = &buf;
-	chan.right  = &buf;
-}
-
-Mono_Buffer::~Mono_Buffer() { }
-
-blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
-{
-	RETURN_ERR( buf.set_sample_rate( rate, msec ) );
-	return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
-}
-
-// Stereo_Buffer
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
-	chan.center = &bufs [0];
-	chan.left = &bufs [1];
-	chan.right = &bufs [2];
-}
-
-Stereo_Buffer::~Stereo_Buffer() { }
-
-blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
-{
-	for ( int i = 0; i < buf_count; i++ )
-		RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
-	return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( long rate )
-{
-	for ( int i = 0; i < buf_count; i++ )
-		bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
-	for ( unsigned i = 0; i < buf_count; i++ )
-		bufs [i].bass_freq( bass );
-}
-
-void Stereo_Buffer::clear()
-{
-	stereo_added = 0;
-	was_stereo   = false;
-	for ( int i = 0; i < buf_count; i++ )
-		bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t clock_count )
-{
-	stereo_added = 0;
-	for ( unsigned i = 0; i < buf_count; i++ )
-	{
-		stereo_added |= bufs [i].clear_modified() << i;
-		bufs [i].end_frame( clock_count );
-	}
-}
-
-long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
-{
-	require( !(count & 1) ); // count must be even
-	count = (unsigned) count / 2;
-
-	long avail = bufs [0].samples_avail();
-	if ( count > avail )
-		count = avail;
-	if ( count )
-	{
-		int bufs_used = stereo_added | was_stereo;
-		//debug_printf( "%X\n", bufs_used );
-		if ( bufs_used <= 1 )
-		{
-			mix_mono( out, count );
-			bufs [0].remove_samples( count );
-			bufs [1].remove_silence( count );
-			bufs [2].remove_silence( count );
-		}
-		else if ( bufs_used & 1 )
-		{
-			mix_stereo( out, count );
-			bufs [0].remove_samples( count );
-			bufs [1].remove_samples( count );
-			bufs [2].remove_samples( count );
-		}
-		else
-		{
-			mix_stereo_no_center( out, count );
-			bufs [0].remove_silence( count );
-			bufs [1].remove_samples( count );
-			bufs [2].remove_samples( count );
-		}
-
-		// to do: this might miss opportunities for optimization
-		if ( !bufs [0].samples_avail() )
-		{
-			was_stereo   = stereo_added;
-			stereo_added = 0;
-		}
-	}
-
-	return count * 2;
-}
-
-void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [1] );
-	BLIP_READER_BEGIN( left, bufs [1] );
-	BLIP_READER_BEGIN( right, bufs [2] );
-	BLIP_READER_BEGIN( center, bufs [0] );
-
-	for ( ; count; --count )
-	{
-		int c = BLIP_READER_READ( center );
-		blargg_long l = c + BLIP_READER_READ( left );
-		blargg_long r = c + BLIP_READER_READ( right );
-		if ( (int16_t) l != l )
-			l = 0x7FFF - (l >> 24);
-
-		BLIP_READER_NEXT( center, bass );
-		if ( (int16_t) r != r )
-			r = 0x7FFF - (r >> 24);
-
-		BLIP_READER_NEXT( left, bass );
-		BLIP_READER_NEXT( right, bass );
-
-		out [0] = l;
-		out [1] = r;
-		out += 2;
-	}
-
-	BLIP_READER_END( center, bufs [0] );
-	BLIP_READER_END( right, bufs [2] );
-	BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [1] );
-	BLIP_READER_BEGIN( left, bufs [1] );
-	BLIP_READER_BEGIN( right, bufs [2] );
-
-	for ( ; count; --count )
-	{
-		blargg_long l = BLIP_READER_READ( left );
-		if ( (int16_t) l != l )
-			l = 0x7FFF - (l >> 24);
-
-		blargg_long r = BLIP_READER_READ( right );
-		if ( (int16_t) r != r )
-			r = 0x7FFF - (r >> 24);
-
-		BLIP_READER_NEXT( left, bass );
-		BLIP_READER_NEXT( right, bass );
-
-		out [0] = l;
-		out [1] = r;
-		out += 2;
-	}
-
-	BLIP_READER_END( right, bufs [2] );
-	BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
-	blip_sample_t* BLIP_RESTRICT out = out_;
-	int const bass = BLIP_READER_BASS( bufs [0] );
-	BLIP_READER_BEGIN( center, bufs [0] );
-
-	for ( ; count; --count )
-	{
-		blargg_long s = BLIP_READER_READ( center );
-		if ( (int16_t) s != s )
-			s = 0x7FFF - (s >> 24);
-
-		BLIP_READER_NEXT( center, bass );
-		out [0] = s;
-		out [1] = s;
-		out += 2;
-	}
-
-	BLIP_READER_END( center, bufs [0] );
-}
diff --git a/src/console/Music_Emu.cc b/src/console/Music_Emu.cc
new file mode 100644
index 000000000000..0500aa015a0e
--- /dev/null
+++ b/src/console/Music_Emu.cc
@@ -0,0 +1,411 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Music_Emu.h"
+
+#include "Multi_Buffer.h"
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const stereo = 2; // number of channels for stereo
+int const silence_max = 6; // seconds
+int const silence_threshold = 0x10;
+long const fade_block_size = 512;
+int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
+
+Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180 };
+
+void Music_Emu::clear_track_vars()
+{
+	current_track_   = -1;
+	out_time         = 0;
+	emu_time         = 0;
+	emu_track_ended_ = true;
+	track_ended_     = true;
+	fade_start       = INT_MAX / 2 + 1;
+	fade_step        = 1;
+	silence_time     = 0;
+	silence_count    = 0;
+	buf_remain       = 0;
+	warning(); // clear warning
+}
+
+void Music_Emu::unload()
+{
+	voice_count_ = 0;
+	clear_track_vars();
+	Gme_File::unload();
+}
+
+Music_Emu::Music_Emu()
+{
+	effects_buffer = 0;
+
+	sample_rate_ = 0;
+	mute_mask_   = 0;
+	tempo_       = 1.0;
+	gain_        = 1.0;
+
+	// defaults
+	max_initial_silence = 2;
+	silence_lookahead   = 3;
+	ignore_silence_     = false;
+	equalizer_.treble   = -1.0;
+	equalizer_.bass     = 60;
+
+	static const char* const names [] = {
+		"Voice 1", "Voice 2", "Voice 3", "Voice 4",
+		"Voice 5", "Voice 6", "Voice 7", "Voice 8"
+	};
+	set_voice_names( names );
+	Music_Emu::unload(); // non-virtual
+}
+
+Music_Emu::~Music_Emu() { delete effects_buffer; }
+
+blargg_err_t Music_Emu::set_sample_rate( long rate )
+{
+	require( !sample_rate() ); // sample rate can't be changed once set
+	RETURN_ERR( set_sample_rate_( rate ) );
+	RETURN_ERR( buf.resize( buf_size ) );
+	sample_rate_ = rate;
+	return 0;
+}
+
+void Music_Emu::pre_load()
+{
+	require( sample_rate() ); // set_sample_rate() must be called before loading a file
+	Gme_File::pre_load();
+}
+
+void Music_Emu::set_equalizer( equalizer_t const& eq )
+{
+	equalizer_ = eq;
+	set_equalizer_( eq );
+}
+
+void Music_Emu::mute_voice( int index, bool mute )
+{
+	require( (unsigned) index < (unsigned) voice_count() );
+	int bit = 1 << index;
+	int mask = mute_mask_ | bit;
+	if ( !mute )
+		mask ^= bit;
+	mute_voices( mask );
+}
+
+void Music_Emu::mute_voices( int mask )
+{
+	require( sample_rate() ); // sample rate must be set first
+	mute_mask_ = mask;
+	mute_voices_( mask );
+}
+
+void Music_Emu::set_tempo( double t )
+{
+	require( sample_rate() ); // sample rate must be set first
+	double const min = 0.02;
+	double const max = 4.00;
+	if ( t < min ) t = min;
+	if ( t > max ) t = max;
+	tempo_ = t;
+	set_tempo_( t );
+}
+
+void Music_Emu::post_load_()
+{
+	set_tempo( tempo_ );
+	remute_voices();
+}
+
+blargg_err_t Music_Emu::start_track( int track )
+{
+	clear_track_vars();
+
+	int remapped = track;
+	RETURN_ERR( remap_track_( &remapped ) );
+	current_track_ = track;
+	RETURN_ERR( start_track_( remapped ) );
+
+	emu_track_ended_ = false;
+	track_ended_     = false;
+
+	if ( !ignore_silence_ )
+	{
+		// play until non-silence or end of track
+		for ( long end = max_initial_silence * stereo * sample_rate(); emu_time < end; )
+		{
+			fill_buf();
+			if ( buf_remain | (int) emu_track_ended_ )
+				break;
+		}
+
+		emu_time      = buf_remain;
+		out_time      = 0;
+		silence_time  = 0;
+		silence_count = 0;
+	}
+	return track_ended() ? warning() : 0;
+}
+
+void Music_Emu::end_track_if_error( blargg_err_t err )
+{
+	if ( err )
+	{
+		emu_track_ended_ = true;
+		set_warning( err );
+	}
+}
+
+// Tell/Seek
+
+blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
+{
+	blargg_long sec = msec / 1000;
+	msec -= sec * 1000;
+	return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
+}
+
+long Music_Emu::tell() const
+{
+	blargg_long rate = sample_rate() * stereo;
+	blargg_long sec = out_time / rate;
+	return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Music_Emu::seek( long msec )
+{
+	blargg_long time = msec_to_samples( msec );
+	if ( time < out_time )
+		RETURN_ERR( start_track( current_track_ ) );
+	return skip( time - out_time );
+}
+
+blargg_err_t Music_Emu::skip( long count )
+{
+	require( current_track() >= 0 ); // start_track() must have been called already
+	out_time += count;
+
+	// remove from silence and buf first
+	{
+		long n = min( count, silence_count );
+		silence_count -= n;
+		count -= n;
+
+		n = min( count, buf_remain );
+		buf_remain -= n;
+		count -= n;
+	}
+
+	if ( count && !emu_track_ended_ )
+	{
+		emu_time += count;
+		end_track_if_error( skip_( count ) );
+	}
+
+	if ( !(silence_count | buf_remain) ) // caught up to emulator, so update track ended
+		track_ended_ |= emu_track_ended_;
+
+	return 0;
+}
+
+blargg_err_t Music_Emu::skip_( long count )
+{
+	// for long skip, mute sound
+	const long threshold = 30000;
+	if ( count > threshold )
+	{
+		int saved_mute = mute_mask_;
+		mute_voices( ~0 );
+
+		while ( count > threshold / 2 && !emu_track_ended_ )
+		{
+			RETURN_ERR( play_( buf_size, buf.begin() ) );
+			count -= buf_size;
+		}
+
+		mute_voices( saved_mute );
+	}
+
+	while ( count && !emu_track_ended_ )
+	{
+		long n = buf_size;
+		if ( n > count )
+			n = count;
+		count -= n;
+		RETURN_ERR( play_( n, buf.begin() ) );
+	}
+	return 0;
+}
+
+// Fading
+
+void Music_Emu::set_fade( long start_msec, long length_msec )
+{
+	fade_step = sample_rate() * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
+	fade_start = msec_to_samples( start_msec );
+}
+
+// unit / pow( 2.0, (double) x / step )
+static int int_log( blargg_long x, int step, int unit )
+{
+	int shift = x / step;
+	int fraction = (x - shift * step) * unit / step;
+	return ((unit - fraction) + (fraction >> 1)) >> shift;
+}
+
+void Music_Emu::handle_fade( long out_count, sample_t* out )
+{
+	for ( int i = 0; i < out_count; i += fade_block_size )
+	{
+		int const shift = 14;
+		int const unit = 1 << shift;
+		int gain = int_log( (out_time + i - fade_start) / fade_block_size,
+				fade_step, unit );
+		if ( gain < (unit >> fade_shift) )
+			track_ended_ = emu_track_ended_ = true;
+
+		sample_t* io = &out [i];
+		for ( int count = min( fade_block_size, out_count - i ); count; --count )
+		{
+			*io = sample_t ((*io * gain) >> shift);
+			++io;
+		}
+	}
+}
+
+// Silence detection
+
+void Music_Emu::emu_play( long count, sample_t* out )
+{
+	check( current_track_ >= 0 );
+	emu_time += count;
+	if ( current_track_ >= 0 && !emu_track_ended_ )
+		end_track_if_error( play_( count, out ) );
+	else
+		memset( out, 0, count * sizeof *out );
+}
+
+// number of consecutive silent samples at end
+static long count_silence( Music_Emu::sample_t* begin, long size )
+{
+	Music_Emu::sample_t first = *begin;
+	*begin = silence_threshold; // sentinel
+	Music_Emu::sample_t* p = begin + size;
+	while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
+	*begin = first;
+	return size - (p - begin);
+}
+
+// fill internal buffer and check it for silence
+void Music_Emu::fill_buf()
+{
+	assert( !buf_remain );
+	if ( !emu_track_ended_ )
+	{
+		emu_play( buf_size, buf.begin() );
+		long silence = count_silence( buf.begin(), buf_size );
+		if ( silence < buf_size )
+		{
+			silence_time = emu_time - silence;
+			buf_remain   = buf_size;
+			return;
+		}
+	}
+	silence_count += buf_size;
+}
+
+blargg_err_t Music_Emu::play( long out_count, sample_t* out )
+{
+	if ( track_ended_ )
+	{
+		memset( out, 0, out_count * sizeof *out );
+	}
+	else
+	{
+		require( current_track() >= 0 );
+		require( out_count % stereo == 0 );
+
+		assert( emu_time >= out_time );
+
+		// prints nifty graph of how far ahead we are when searching for silence
+		//debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
+
+		long pos = 0;
+		if ( silence_count )
+		{
+			// during a run of silence, run emulator at >=2x speed so it gets ahead
+			long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
+			while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) )
+				fill_buf();
+
+			// fill with silence
+			pos = min( silence_count, out_count );
+			memset( out, 0, pos * sizeof *out );
+			silence_count -= pos;
+
+			if ( emu_time - silence_time > silence_max * stereo * sample_rate() )
+			{
+				track_ended_  = emu_track_ended_ = true;
+				silence_count = 0;
+				buf_remain    = 0;
+			}
+		}
+
+		if ( buf_remain )
+		{
+			// empty silence buf
+			long n = min( buf_remain, out_count - pos );
+			memcpy( &out [pos], buf.begin() + (buf_size - buf_remain), n * sizeof *out );
+			buf_remain -= n;
+			pos += n;
+		}
+
+		// generate remaining samples normally
+		long remain = out_count - pos;
+		if ( remain )
+		{
+			emu_play( remain, out + pos );
+			track_ended_ |= emu_track_ended_;
+
+			if ( !ignore_silence_ || out_time > fade_start )
+			{
+				// check end for a new run of silence
+				long silence = count_silence( out + pos, remain );
+				if ( silence < remain )
+					silence_time = emu_time - silence;
+
+				if ( emu_time - silence_time >= buf_size )
+					fill_buf(); // cause silence detection on next play()
+			}
+		}
+
+		if ( out_time > fade_start )
+			handle_fade( out_count, out );
+	}
+	out_time += out_count;
+	return 0;
+}
+
+// Gme_Info_
+
+blargg_err_t Gme_Info_::set_sample_rate_( long )            { return 0; }
+void         Gme_Info_::pre_load()                          { Gme_File::pre_load(); } // skip Music_Emu
+void         Gme_Info_::post_load_()                        { Gme_File::post_load_(); } // skip Music_Emu
+void         Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
+void         Gme_Info_::enable_accuracy_( bool )            { check( false ); }
+void         Gme_Info_::mute_voices_( int )                 { check( false ); }
+void         Gme_Info_::set_tempo_( double )                { }
+blargg_err_t Gme_Info_::start_track_( int )                 { return "Use full emulator for playback"; }
+blargg_err_t Gme_Info_::play_( long, sample_t* )            { return "Use full emulator for playback"; }
diff --git a/src/console/Music_Emu.cxx b/src/console/Music_Emu.cxx
deleted file mode 100644
index 0500aa015a0e..000000000000
--- a/src/console/Music_Emu.cxx
+++ /dev/null
@@ -1,411 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const stereo = 2; // number of channels for stereo
-int const silence_max = 6; // seconds
-int const silence_threshold = 0x10;
-long const fade_block_size = 512;
-int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
-
-Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180 };
-
-void Music_Emu::clear_track_vars()
-{
-	current_track_   = -1;
-	out_time         = 0;
-	emu_time         = 0;
-	emu_track_ended_ = true;
-	track_ended_     = true;
-	fade_start       = INT_MAX / 2 + 1;
-	fade_step        = 1;
-	silence_time     = 0;
-	silence_count    = 0;
-	buf_remain       = 0;
-	warning(); // clear warning
-}
-
-void Music_Emu::unload()
-{
-	voice_count_ = 0;
-	clear_track_vars();
-	Gme_File::unload();
-}
-
-Music_Emu::Music_Emu()
-{
-	effects_buffer = 0;
-
-	sample_rate_ = 0;
-	mute_mask_   = 0;
-	tempo_       = 1.0;
-	gain_        = 1.0;
-
-	// defaults
-	max_initial_silence = 2;
-	silence_lookahead   = 3;
-	ignore_silence_     = false;
-	equalizer_.treble   = -1.0;
-	equalizer_.bass     = 60;
-
-	static const char* const names [] = {
-		"Voice 1", "Voice 2", "Voice 3", "Voice 4",
-		"Voice 5", "Voice 6", "Voice 7", "Voice 8"
-	};
-	set_voice_names( names );
-	Music_Emu::unload(); // non-virtual
-}
-
-Music_Emu::~Music_Emu() { delete effects_buffer; }
-
-blargg_err_t Music_Emu::set_sample_rate( long rate )
-{
-	require( !sample_rate() ); // sample rate can't be changed once set
-	RETURN_ERR( set_sample_rate_( rate ) );
-	RETURN_ERR( buf.resize( buf_size ) );
-	sample_rate_ = rate;
-	return 0;
-}
-
-void Music_Emu::pre_load()
-{
-	require( sample_rate() ); // set_sample_rate() must be called before loading a file
-	Gme_File::pre_load();
-}
-
-void Music_Emu::set_equalizer( equalizer_t const& eq )
-{
-	equalizer_ = eq;
-	set_equalizer_( eq );
-}
-
-void Music_Emu::mute_voice( int index, bool mute )
-{
-	require( (unsigned) index < (unsigned) voice_count() );
-	int bit = 1 << index;
-	int mask = mute_mask_ | bit;
-	if ( !mute )
-		mask ^= bit;
-	mute_voices( mask );
-}
-
-void Music_Emu::mute_voices( int mask )
-{
-	require( sample_rate() ); // sample rate must be set first
-	mute_mask_ = mask;
-	mute_voices_( mask );
-}
-
-void Music_Emu::set_tempo( double t )
-{
-	require( sample_rate() ); // sample rate must be set first
-	double const min = 0.02;
-	double const max = 4.00;
-	if ( t < min ) t = min;
-	if ( t > max ) t = max;
-	tempo_ = t;
-	set_tempo_( t );
-}
-
-void Music_Emu::post_load_()
-{
-	set_tempo( tempo_ );
-	remute_voices();
-}
-
-blargg_err_t Music_Emu::start_track( int track )
-{
-	clear_track_vars();
-
-	int remapped = track;
-	RETURN_ERR( remap_track_( &remapped ) );
-	current_track_ = track;
-	RETURN_ERR( start_track_( remapped ) );
-
-	emu_track_ended_ = false;
-	track_ended_     = false;
-
-	if ( !ignore_silence_ )
-	{
-		// play until non-silence or end of track
-		for ( long end = max_initial_silence * stereo * sample_rate(); emu_time < end; )
-		{
-			fill_buf();
-			if ( buf_remain | (int) emu_track_ended_ )
-				break;
-		}
-
-		emu_time      = buf_remain;
-		out_time      = 0;
-		silence_time  = 0;
-		silence_count = 0;
-	}
-	return track_ended() ? warning() : 0;
-}
-
-void Music_Emu::end_track_if_error( blargg_err_t err )
-{
-	if ( err )
-	{
-		emu_track_ended_ = true;
-		set_warning( err );
-	}
-}
-
-// Tell/Seek
-
-blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
-{
-	blargg_long sec = msec / 1000;
-	msec -= sec * 1000;
-	return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
-}
-
-long Music_Emu::tell() const
-{
-	blargg_long rate = sample_rate() * stereo;
-	blargg_long sec = out_time / rate;
-	return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Music_Emu::seek( long msec )
-{
-	blargg_long time = msec_to_samples( msec );
-	if ( time < out_time )
-		RETURN_ERR( start_track( current_track_ ) );
-	return skip( time - out_time );
-}
-
-blargg_err_t Music_Emu::skip( long count )
-{
-	require( current_track() >= 0 ); // start_track() must have been called already
-	out_time += count;
-
-	// remove from silence and buf first
-	{
-		long n = min( count, silence_count );
-		silence_count -= n;
-		count -= n;
-
-		n = min( count, buf_remain );
-		buf_remain -= n;
-		count -= n;
-	}
-
-	if ( count && !emu_track_ended_ )
-	{
-		emu_time += count;
-		end_track_if_error( skip_( count ) );
-	}
-
-	if ( !(silence_count | buf_remain) ) // caught up to emulator, so update track ended
-		track_ended_ |= emu_track_ended_;
-
-	return 0;
-}
-
-blargg_err_t Music_Emu::skip_( long count )
-{
-	// for long skip, mute sound
-	const long threshold = 30000;
-	if ( count > threshold )
-	{
-		int saved_mute = mute_mask_;
-		mute_voices( ~0 );
-
-		while ( count > threshold / 2 && !emu_track_ended_ )
-		{
-			RETURN_ERR( play_( buf_size, buf.begin() ) );
-			count -= buf_size;
-		}
-
-		mute_voices( saved_mute );
-	}
-
-	while ( count && !emu_track_ended_ )
-	{
-		long n = buf_size;
-		if ( n > count )
-			n = count;
-		count -= n;
-		RETURN_ERR( play_( n, buf.begin() ) );
-	}
-	return 0;
-}
-
-// Fading
-
-void Music_Emu::set_fade( long start_msec, long length_msec )
-{
-	fade_step = sample_rate() * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
-	fade_start = msec_to_samples( start_msec );
-}
-
-// unit / pow( 2.0, (double) x / step )
-static int int_log( blargg_long x, int step, int unit )
-{
-	int shift = x / step;
-	int fraction = (x - shift * step) * unit / step;
-	return ((unit - fraction) + (fraction >> 1)) >> shift;
-}
-
-void Music_Emu::handle_fade( long out_count, sample_t* out )
-{
-	for ( int i = 0; i < out_count; i += fade_block_size )
-	{
-		int const shift = 14;
-		int const unit = 1 << shift;
-		int gain = int_log( (out_time + i - fade_start) / fade_block_size,
-				fade_step, unit );
-		if ( gain < (unit >> fade_shift) )
-			track_ended_ = emu_track_ended_ = true;
-
-		sample_t* io = &out [i];
-		for ( int count = min( fade_block_size, out_count - i ); count; --count )
-		{
-			*io = sample_t ((*io * gain) >> shift);
-			++io;
-		}
-	}
-}
-
-// Silence detection
-
-void Music_Emu::emu_play( long count, sample_t* out )
-{
-	check( current_track_ >= 0 );
-	emu_time += count;
-	if ( current_track_ >= 0 && !emu_track_ended_ )
-		end_track_if_error( play_( count, out ) );
-	else
-		memset( out, 0, count * sizeof *out );
-}
-
-// number of consecutive silent samples at end
-static long count_silence( Music_Emu::sample_t* begin, long size )
-{
-	Music_Emu::sample_t first = *begin;
-	*begin = silence_threshold; // sentinel
-	Music_Emu::sample_t* p = begin + size;
-	while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
-	*begin = first;
-	return size - (p - begin);
-}
-
-// fill internal buffer and check it for silence
-void Music_Emu::fill_buf()
-{
-	assert( !buf_remain );
-	if ( !emu_track_ended_ )
-	{
-		emu_play( buf_size, buf.begin() );
-		long silence = count_silence( buf.begin(), buf_size );
-		if ( silence < buf_size )
-		{
-			silence_time = emu_time - silence;
-			buf_remain   = buf_size;
-			return;
-		}
-	}
-	silence_count += buf_size;
-}
-
-blargg_err_t Music_Emu::play( long out_count, sample_t* out )
-{
-	if ( track_ended_ )
-	{
-		memset( out, 0, out_count * sizeof *out );
-	}
-	else
-	{
-		require( current_track() >= 0 );
-		require( out_count % stereo == 0 );
-
-		assert( emu_time >= out_time );
-
-		// prints nifty graph of how far ahead we are when searching for silence
-		//debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
-
-		long pos = 0;
-		if ( silence_count )
-		{
-			// during a run of silence, run emulator at >=2x speed so it gets ahead
-			long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
-			while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) )
-				fill_buf();
-
-			// fill with silence
-			pos = min( silence_count, out_count );
-			memset( out, 0, pos * sizeof *out );
-			silence_count -= pos;
-
-			if ( emu_time - silence_time > silence_max * stereo * sample_rate() )
-			{
-				track_ended_  = emu_track_ended_ = true;
-				silence_count = 0;
-				buf_remain    = 0;
-			}
-		}
-
-		if ( buf_remain )
-		{
-			// empty silence buf
-			long n = min( buf_remain, out_count - pos );
-			memcpy( &out [pos], buf.begin() + (buf_size - buf_remain), n * sizeof *out );
-			buf_remain -= n;
-			pos += n;
-		}
-
-		// generate remaining samples normally
-		long remain = out_count - pos;
-		if ( remain )
-		{
-			emu_play( remain, out + pos );
-			track_ended_ |= emu_track_ended_;
-
-			if ( !ignore_silence_ || out_time > fade_start )
-			{
-				// check end for a new run of silence
-				long silence = count_silence( out + pos, remain );
-				if ( silence < remain )
-					silence_time = emu_time - silence;
-
-				if ( emu_time - silence_time >= buf_size )
-					fill_buf(); // cause silence detection on next play()
-			}
-		}
-
-		if ( out_time > fade_start )
-			handle_fade( out_count, out );
-	}
-	out_time += out_count;
-	return 0;
-}
-
-// Gme_Info_
-
-blargg_err_t Gme_Info_::set_sample_rate_( long )            { return 0; }
-void         Gme_Info_::pre_load()                          { Gme_File::pre_load(); } // skip Music_Emu
-void         Gme_Info_::post_load_()                        { Gme_File::post_load_(); } // skip Music_Emu
-void         Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
-void         Gme_Info_::enable_accuracy_( bool )            { check( false ); }
-void         Gme_Info_::mute_voices_( int )                 { check( false ); }
-void         Gme_Info_::set_tempo_( double )                { }
-blargg_err_t Gme_Info_::start_track_( int )                 { return "Use full emulator for playback"; }
-blargg_err_t Gme_Info_::play_( long, sample_t* )            { return "Use full emulator for playback"; }
diff --git a/src/console/Nes_Apu.cc b/src/console/Nes_Apu.cc
new file mode 100644
index 000000000000..1fe3f3f0df62
--- /dev/null
+++ b/src/console/Nes_Apu.cc
@@ -0,0 +1,391 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "Nes_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const amp_range = 15;
+
+Nes_Apu::Nes_Apu() :
+	square1( &square_synth ),
+	square2( &square_synth )
+{
+	tempo_ = 1.0;
+	dmc.apu = this;
+	dmc.prg_reader = nullptr;
+	irq_notifier_ = nullptr;
+
+	oscs [0] = &square1;
+	oscs [1] = &square2;
+	oscs [2] = ▵
+	oscs [3] = &noise;
+	oscs [4] = &dmc;
+
+	output( nullptr );
+	volume( 1.0 );
+	reset( false );
+}
+
+void Nes_Apu::treble_eq( const blip_eq_t& eq )
+{
+	square_synth.treble_eq( eq );
+	triangle.synth.treble_eq( eq );
+	noise.synth.treble_eq( eq );
+	dmc.synth.treble_eq( eq );
+}
+
+void Nes_Apu::enable_nonlinear( double v )
+{
+	dmc.nonlinear = true;
+	square_synth.volume( 1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v );
+
+	const double tnd = 0.48 / 202 * nonlinear_tnd_gain();
+	triangle.synth.volume( 3.0 * tnd );
+	noise.synth.volume( 2.0 * tnd );
+	dmc.synth.volume( tnd );
+
+	square1 .last_amp = 0;
+	square2 .last_amp = 0;
+	triangle.last_amp = 0;
+	noise   .last_amp = 0;
+	dmc     .last_amp = 0;
+}
+
+void Nes_Apu::volume( double v )
+{
+	dmc.nonlinear = false;
+	square_synth.volume(   0.1128  / amp_range * v );
+	triangle.synth.volume( 0.12765 / amp_range * v );
+	noise.synth.volume(    0.0741  / amp_range * v );
+	dmc.synth.volume(      0.42545 / 127 * v );
+}
+
+void Nes_Apu::output( Blip_Buffer* buffer )
+{
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, buffer );
+}
+
+void Nes_Apu::set_tempo( double t )
+{
+	tempo_ = t;
+	frame_period = (dmc.pal_mode ? 8314 : 7458);
+	if ( t != 1.0 )
+		frame_period = (int) (frame_period / t) & ~1; // must be even
+}
+
+void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
+{
+	dmc.pal_mode = pal_mode;
+	set_tempo( tempo_ );
+
+	square1.reset();
+	square2.reset();
+	triangle.reset();
+	noise.reset();
+	dmc.reset();
+
+	last_time = 0;
+	last_dmc_time = 0;
+	osc_enables = 0;
+	irq_flag = false;
+	earliest_irq_ = no_irq;
+	frame_delay = 1;
+	write_register( 0, 0x4017, 0x00 );
+	write_register( 0, 0x4015, 0x00 );
+
+	for ( nes_addr_t addr = start_addr; addr <= 0x4013; addr++ )
+		write_register( 0, addr, (addr & 3) ? 0x00 : 0x10 );
+
+	dmc.dac = initial_dmc_dac;
+	if ( !dmc.nonlinear )
+		triangle.last_amp = 15;
+	if ( !dmc.nonlinear ) // TODO: remove?
+		dmc.last_amp = initial_dmc_dac; // prevent output transition
+}
+
+void Nes_Apu::irq_changed()
+{
+	nes_time_t new_irq = dmc.next_irq;
+	if ( dmc.irq_flag | irq_flag ) {
+		new_irq = 0;
+	}
+	else if ( new_irq > next_irq ) {
+		new_irq = next_irq;
+	}
+
+	if ( new_irq != earliest_irq_ ) {
+		earliest_irq_ = new_irq;
+		if ( irq_notifier_ )
+			irq_notifier_( irq_data );
+	}
+}
+
+// frames
+
+void Nes_Apu::run_until( nes_time_t end_time )
+{
+	require( end_time >= last_dmc_time );
+	if ( end_time > next_dmc_read_time() )
+	{
+		nes_time_t start = last_dmc_time;
+		last_dmc_time = end_time;
+		dmc.run( start, end_time );
+	}
+}
+
+void Nes_Apu::run_until_( nes_time_t end_time )
+{
+	require( end_time >= last_time );
+
+	if ( end_time == last_time )
+		return;
+
+	if ( last_dmc_time < end_time )
+	{
+		nes_time_t start = last_dmc_time;
+		last_dmc_time = end_time;
+		dmc.run( start, end_time );
+	}
+
+	while ( true )
+	{
+		// earlier of next frame time or end time
+		nes_time_t time = last_time + frame_delay;
+		if ( time > end_time )
+			time = end_time;
+		frame_delay -= time - last_time;
+
+		// run oscs to present
+		square1.run( last_time, time );
+		square2.run( last_time, time );
+		triangle.run( last_time, time );
+		noise.run( last_time, time );
+		last_time = time;
+
+		if ( time == end_time )
+			break; // no more frames to run
+
+		// take frame-specific actions
+		frame_delay = frame_period;
+		switch ( frame++ )
+		{
+			case 0:
+				if ( !(frame_mode & 0xC0) ) {
+		 			next_irq = time + frame_period * 4 + 2;
+		 			irq_flag = true;
+		 		}
+		 		// fall through
+		 	case 2:
+		 		// clock length and sweep on frames 0 and 2
+				square1.clock_length( 0x20 );
+				square2.clock_length( 0x20 );
+				noise.clock_length( 0x20 );
+				triangle.clock_length( 0x80 ); // different bit for halt flag on triangle
+
+				square1.clock_sweep( -1 );
+				square2.clock_sweep( 0 );
+
+				// frame 2 is slightly shorter in mode 1
+				if ( dmc.pal_mode && frame == 3 )
+					frame_delay -= 2;
+		 		break;
+
+			case 1:
+				// frame 1 is slightly shorter in mode 0
+				if ( !dmc.pal_mode )
+					frame_delay -= 2;
+				break;
+
+		 	case 3:
+		 		frame = 0;
+
+		 		// frame 3 is almost twice as long in mode 1
+		 		if ( frame_mode & 0x80 )
+					frame_delay += frame_period - (dmc.pal_mode ? 2 : 6);
+				break;
+		}
+
+		// clock envelopes and linear counter every frame
+		triangle.clock_linear_counter();
+		square1.clock_envelope();
+		square2.clock_envelope();
+		noise.clock_envelope();
+	}
+}
+
+template<class T>
+inline void zero_apu_osc( T* osc, nes_time_t time )
+{
+	Blip_Buffer* output = osc->output;
+	int last_amp = osc->last_amp;
+	osc->last_amp = 0;
+	if ( output && last_amp )
+		osc->synth.offset( time, -last_amp, output );
+}
+
+void Nes_Apu::end_frame( nes_time_t end_time )
+{
+	if ( end_time > last_time )
+		run_until_( end_time );
+
+	if ( dmc.nonlinear )
+	{
+		zero_apu_osc( &square1,  last_time );
+		zero_apu_osc( &square2,  last_time );
+		zero_apu_osc( &triangle, last_time );
+		zero_apu_osc( &noise,    last_time );
+		zero_apu_osc( &dmc,      last_time );
+	}
+
+	// make times relative to new frame
+	last_time -= end_time;
+	require( last_time >= 0 );
+
+	last_dmc_time -= end_time;
+	require( last_dmc_time >= 0 );
+
+	if ( next_irq != no_irq ) {
+		next_irq -= end_time;
+		check( next_irq >= 0 );
+	}
+	if ( dmc.next_irq != no_irq ) {
+		dmc.next_irq -= end_time;
+		check( dmc.next_irq >= 0 );
+	}
+	if ( earliest_irq_ != no_irq ) {
+		earliest_irq_ -= end_time;
+		if ( earliest_irq_ < 0 )
+			earliest_irq_ = 0;
+	}
+}
+
+// registers
+
+static const unsigned char length_table [0x20] = {
+	0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
+	0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
+	0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
+	0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
+};
+
+void Nes_Apu::write_register( nes_time_t time, nes_addr_t addr, int data )
+{
+	require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
+	require( (unsigned) data <= 0xFF );
+
+	// Ignore addresses outside range
+	if ( unsigned (addr - start_addr) > end_addr - start_addr )
+		return;
+
+	run_until_( time );
+
+	if ( addr < 0x4014 )
+	{
+		// Write to channel
+		int osc_index = (addr - start_addr) >> 2;
+		Nes_Osc* osc = oscs [osc_index];
+
+		int reg = addr & 3;
+		osc->regs [reg] = data;
+		osc->reg_written [reg] = true;
+
+		if ( osc_index == 4 )
+		{
+			// handle DMC specially
+			dmc.write_register( reg, data );
+		}
+		else if ( reg == 3 )
+		{
+			// load length counter
+			if ( (osc_enables >> osc_index) & 1 )
+				osc->length_counter = length_table [(data >> 3) & 0x1F];
+
+			// reset square phase
+			if ( osc_index < 2 )
+				((Nes_Square*) osc)->phase = Nes_Square::phase_range - 1;
+		}
+	}
+	else if ( addr == 0x4015 )
+	{
+		// Channel enables
+		for ( int i = osc_count; i--; )
+			if ( !((data >> i) & 1) )
+				oscs [i]->length_counter = 0;
+
+		bool recalc_irq = dmc.irq_flag;
+		dmc.irq_flag = false;
+
+		int old_enables = osc_enables;
+		osc_enables = data;
+		if ( !(data & 0x10) ) {
+			dmc.next_irq = no_irq;
+			recalc_irq = true;
+		}
+		else if ( !(old_enables & 0x10) ) {
+			dmc.start(); // dmc just enabled
+		}
+
+		if ( recalc_irq )
+			irq_changed();
+	}
+	else if ( addr == 0x4017 )
+	{
+		// Frame mode
+		frame_mode = data;
+
+		bool irq_enabled = !(data & 0x40);
+		irq_flag &= irq_enabled;
+		next_irq = no_irq;
+
+		// mode 1
+		frame_delay = (frame_delay & 1);
+		frame = 0;
+
+		if ( !(data & 0x80) )
+		{
+			// mode 0
+			frame = 1;
+			frame_delay += frame_period;
+			if ( irq_enabled )
+				next_irq = time + frame_delay + frame_period * 3 + 1;
+		}
+
+		irq_changed();
+	}
+}
+
+int Nes_Apu::read_status( nes_time_t time )
+{
+	run_until_( time - 1 );
+
+	int result = (dmc.irq_flag << 7) | (irq_flag << 6);
+
+	for ( int i = 0; i < osc_count; i++ )
+		if ( oscs [i]->length_counter )
+			result |= 1 << i;
+
+	run_until_( time );
+
+	if ( irq_flag )
+	{
+		result |= 0x40;
+		irq_flag = false;
+		irq_changed();
+	}
+
+	//debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
+
+	return result;
+}
diff --git a/src/console/Nes_Apu.cxx b/src/console/Nes_Apu.cxx
deleted file mode 100644
index 6da8ac88cd31..000000000000
--- a/src/console/Nes_Apu.cxx
+++ /dev/null
@@ -1,391 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const amp_range = 15;
-
-Nes_Apu::Nes_Apu() :
-	square1( &square_synth ),
-	square2( &square_synth )
-{
-	tempo_ = 1.0;
-	dmc.apu = this;
-	dmc.prg_reader = NULL;
-	irq_notifier_ = NULL;
-
-	oscs [0] = &square1;
-	oscs [1] = &square2;
-	oscs [2] = ▵
-	oscs [3] = &noise;
-	oscs [4] = &dmc;
-
-	output( NULL );
-	volume( 1.0 );
-	reset( false );
-}
-
-void Nes_Apu::treble_eq( const blip_eq_t& eq )
-{
-	square_synth.treble_eq( eq );
-	triangle.synth.treble_eq( eq );
-	noise.synth.treble_eq( eq );
-	dmc.synth.treble_eq( eq );
-}
-
-void Nes_Apu::enable_nonlinear( double v )
-{
-	dmc.nonlinear = true;
-	square_synth.volume( 1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v );
-
-	const double tnd = 0.48 / 202 * nonlinear_tnd_gain();
-	triangle.synth.volume( 3.0 * tnd );
-	noise.synth.volume( 2.0 * tnd );
-	dmc.synth.volume( tnd );
-
-	square1 .last_amp = 0;
-	square2 .last_amp = 0;
-	triangle.last_amp = 0;
-	noise   .last_amp = 0;
-	dmc     .last_amp = 0;
-}
-
-void Nes_Apu::volume( double v )
-{
-	dmc.nonlinear = false;
-	square_synth.volume(   0.1128  / amp_range * v );
-	triangle.synth.volume( 0.12765 / amp_range * v );
-	noise.synth.volume(    0.0741  / amp_range * v );
-	dmc.synth.volume(      0.42545 / 127 * v );
-}
-
-void Nes_Apu::output( Blip_Buffer* buffer )
-{
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, buffer );
-}
-
-void Nes_Apu::set_tempo( double t )
-{
-	tempo_ = t;
-	frame_period = (dmc.pal_mode ? 8314 : 7458);
-	if ( t != 1.0 )
-		frame_period = (int) (frame_period / t) & ~1; // must be even
-}
-
-void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
-{
-	dmc.pal_mode = pal_mode;
-	set_tempo( tempo_ );
-
-	square1.reset();
-	square2.reset();
-	triangle.reset();
-	noise.reset();
-	dmc.reset();
-
-	last_time = 0;
-	last_dmc_time = 0;
-	osc_enables = 0;
-	irq_flag = false;
-	earliest_irq_ = no_irq;
-	frame_delay = 1;
-	write_register( 0, 0x4017, 0x00 );
-	write_register( 0, 0x4015, 0x00 );
-
-	for ( nes_addr_t addr = start_addr; addr <= 0x4013; addr++ )
-		write_register( 0, addr, (addr & 3) ? 0x00 : 0x10 );
-
-	dmc.dac = initial_dmc_dac;
-	if ( !dmc.nonlinear )
-		triangle.last_amp = 15;
-	if ( !dmc.nonlinear ) // TODO: remove?
-		dmc.last_amp = initial_dmc_dac; // prevent output transition
-}
-
-void Nes_Apu::irq_changed()
-{
-	nes_time_t new_irq = dmc.next_irq;
-	if ( dmc.irq_flag | irq_flag ) {
-		new_irq = 0;
-	}
-	else if ( new_irq > next_irq ) {
-		new_irq = next_irq;
-	}
-
-	if ( new_irq != earliest_irq_ ) {
-		earliest_irq_ = new_irq;
-		if ( irq_notifier_ )
-			irq_notifier_( irq_data );
-	}
-}
-
-// frames
-
-void Nes_Apu::run_until( nes_time_t end_time )
-{
-	require( end_time >= last_dmc_time );
-	if ( end_time > next_dmc_read_time() )
-	{
-		nes_time_t start = last_dmc_time;
-		last_dmc_time = end_time;
-		dmc.run( start, end_time );
-	}
-}
-
-void Nes_Apu::run_until_( nes_time_t end_time )
-{
-	require( end_time >= last_time );
-
-	if ( end_time == last_time )
-		return;
-
-	if ( last_dmc_time < end_time )
-	{
-		nes_time_t start = last_dmc_time;
-		last_dmc_time = end_time;
-		dmc.run( start, end_time );
-	}
-
-	while ( true )
-	{
-		// earlier of next frame time or end time
-		nes_time_t time = last_time + frame_delay;
-		if ( time > end_time )
-			time = end_time;
-		frame_delay -= time - last_time;
-
-		// run oscs to present
-		square1.run( last_time, time );
-		square2.run( last_time, time );
-		triangle.run( last_time, time );
-		noise.run( last_time, time );
-		last_time = time;
-
-		if ( time == end_time )
-			break; // no more frames to run
-
-		// take frame-specific actions
-		frame_delay = frame_period;
-		switch ( frame++ )
-		{
-			case 0:
-				if ( !(frame_mode & 0xC0) ) {
-		 			next_irq = time + frame_period * 4 + 2;
-		 			irq_flag = true;
-		 		}
-		 		// fall through
-		 	case 2:
-		 		// clock length and sweep on frames 0 and 2
-				square1.clock_length( 0x20 );
-				square2.clock_length( 0x20 );
-				noise.clock_length( 0x20 );
-				triangle.clock_length( 0x80 ); // different bit for halt flag on triangle
-
-				square1.clock_sweep( -1 );
-				square2.clock_sweep( 0 );
-
-				// frame 2 is slightly shorter in mode 1
-				if ( dmc.pal_mode && frame == 3 )
-					frame_delay -= 2;
-		 		break;
-
-			case 1:
-				// frame 1 is slightly shorter in mode 0
-				if ( !dmc.pal_mode )
-					frame_delay -= 2;
-				break;
-
-		 	case 3:
-		 		frame = 0;
-
-		 		// frame 3 is almost twice as long in mode 1
-		 		if ( frame_mode & 0x80 )
-					frame_delay += frame_period - (dmc.pal_mode ? 2 : 6);
-				break;
-		}
-
-		// clock envelopes and linear counter every frame
-		triangle.clock_linear_counter();
-		square1.clock_envelope();
-		square2.clock_envelope();
-		noise.clock_envelope();
-	}
-}
-
-template<class T>
-inline void zero_apu_osc( T* osc, nes_time_t time )
-{
-	Blip_Buffer* output = osc->output;
-	int last_amp = osc->last_amp;
-	osc->last_amp = 0;
-	if ( output && last_amp )
-		osc->synth.offset( time, -last_amp, output );
-}
-
-void Nes_Apu::end_frame( nes_time_t end_time )
-{
-	if ( end_time > last_time )
-		run_until_( end_time );
-
-	if ( dmc.nonlinear )
-	{
-		zero_apu_osc( &square1,  last_time );
-		zero_apu_osc( &square2,  last_time );
-		zero_apu_osc( &triangle, last_time );
-		zero_apu_osc( &noise,    last_time );
-		zero_apu_osc( &dmc,      last_time );
-	}
-
-	// make times relative to new frame
-	last_time -= end_time;
-	require( last_time >= 0 );
-
-	last_dmc_time -= end_time;
-	require( last_dmc_time >= 0 );
-
-	if ( next_irq != no_irq ) {
-		next_irq -= end_time;
-		check( next_irq >= 0 );
-	}
-	if ( dmc.next_irq != no_irq ) {
-		dmc.next_irq -= end_time;
-		check( dmc.next_irq >= 0 );
-	}
-	if ( earliest_irq_ != no_irq ) {
-		earliest_irq_ -= end_time;
-		if ( earliest_irq_ < 0 )
-			earliest_irq_ = 0;
-	}
-}
-
-// registers
-
-static const unsigned char length_table [0x20] = {
-	0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
-	0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
-	0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
-	0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
-};
-
-void Nes_Apu::write_register( nes_time_t time, nes_addr_t addr, int data )
-{
-	require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
-	require( (unsigned) data <= 0xFF );
-
-	// Ignore addresses outside range
-	if ( unsigned (addr - start_addr) > end_addr - start_addr )
-		return;
-
-	run_until_( time );
-
-	if ( addr < 0x4014 )
-	{
-		// Write to channel
-		int osc_index = (addr - start_addr) >> 2;
-		Nes_Osc* osc = oscs [osc_index];
-
-		int reg = addr & 3;
-		osc->regs [reg] = data;
-		osc->reg_written [reg] = true;
-
-		if ( osc_index == 4 )
-		{
-			// handle DMC specially
-			dmc.write_register( reg, data );
-		}
-		else if ( reg == 3 )
-		{
-			// load length counter
-			if ( (osc_enables >> osc_index) & 1 )
-				osc->length_counter = length_table [(data >> 3) & 0x1F];
-
-			// reset square phase
-			if ( osc_index < 2 )
-				((Nes_Square*) osc)->phase = Nes_Square::phase_range - 1;
-		}
-	}
-	else if ( addr == 0x4015 )
-	{
-		// Channel enables
-		for ( int i = osc_count; i--; )
-			if ( !((data >> i) & 1) )
-				oscs [i]->length_counter = 0;
-
-		bool recalc_irq = dmc.irq_flag;
-		dmc.irq_flag = false;
-
-		int old_enables = osc_enables;
-		osc_enables = data;
-		if ( !(data & 0x10) ) {
-			dmc.next_irq = no_irq;
-			recalc_irq = true;
-		}
-		else if ( !(old_enables & 0x10) ) {
-			dmc.start(); // dmc just enabled
-		}
-
-		if ( recalc_irq )
-			irq_changed();
-	}
-	else if ( addr == 0x4017 )
-	{
-		// Frame mode
-		frame_mode = data;
-
-		bool irq_enabled = !(data & 0x40);
-		irq_flag &= irq_enabled;
-		next_irq = no_irq;
-
-		// mode 1
-		frame_delay = (frame_delay & 1);
-		frame = 0;
-
-		if ( !(data & 0x80) )
-		{
-			// mode 0
-			frame = 1;
-			frame_delay += frame_period;
-			if ( irq_enabled )
-				next_irq = time + frame_delay + frame_period * 3 + 1;
-		}
-
-		irq_changed();
-	}
-}
-
-int Nes_Apu::read_status( nes_time_t time )
-{
-	run_until_( time - 1 );
-
-	int result = (dmc.irq_flag << 7) | (irq_flag << 6);
-
-	for ( int i = 0; i < osc_count; i++ )
-		if ( oscs [i]->length_counter )
-			result |= 1 << i;
-
-	run_until_( time );
-
-	if ( irq_flag )
-	{
-		result |= 0x40;
-		irq_flag = false;
-		irq_changed();
-	}
-
-	//debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
-
-	return result;
-}
diff --git a/src/console/Nes_Apu.h b/src/console/Nes_Apu.h
index 69b9f55f1298..5a8f486faa14 100644
--- a/src/console/Nes_Apu.h
+++ b/src/console/Nes_Apu.h
@@ -16,13 +16,13 @@ class Nes_Buffer;
 
 class Nes_Apu {
 public:
-	// Set buffer to generate all sound into, or disable sound if NULL
+	// Set buffer to generate all sound into, or disable sound if nullptr
 	void output( Blip_Buffer* );
 
 	// Set memory reader callback used by DMC oscillator to fetch samples.
 	// When callback is invoked, 'user_data' is passed unchanged as the
 	// first parameter.
-	void dmc_reader( int (*callback)( void* user_data, nes_addr_t ), void* user_data = NULL );
+	void dmc_reader( int (*callback)( void* user_data, nes_addr_t ), void* user_data = nullptr );
 
 	// All time values are the number of CPU clock cycles relative to the
 	// beginning of the current time frame. Before resetting the CPU clock
@@ -63,7 +63,7 @@ public:
 	// Set treble equalization (see notes.txt)
 	void treble_eq( const blip_eq_t& );
 
-	// Set sound output of specific oscillator to buffer. If buffer is NULL,
+	// Set sound output of specific oscillator to buffer. If buffer is nullptr,
 	// the specified oscillator is muted and emulation accuracy is reduced.
 	// The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
 	// 2) Triangle, 3) Noise, 4) DMC.
@@ -71,9 +71,9 @@ public:
 	void osc_output( int index, Blip_Buffer* buffer );
 
 	// Set IRQ time callback that is invoked when the time of earliest IRQ
-	// may have changed, or NULL to disable. When callback is invoked,
+	// may have changed, or nullptr to disable. When callback is invoked,
 	// 'user_data' is passed unchanged as the first parameter.
-	void irq_notifier( void (*callback)( void* user_data ), void* user_data = NULL );
+	void irq_notifier( void (*callback)( void* user_data ), void* user_data = nullptr );
 
 	// Get time that APU-generated IRQ will occur if no further register reads
 	// or writes occur. If IRQ is already pending, returns irq_waiting. If no
@@ -83,9 +83,9 @@ public:
 	nes_time_t earliest_irq( nes_time_t ) const;
 
 	// Count number of DMC reads that would occur if 'run_until( t )' were executed.
-	// If last_read is not NULL, set *last_read to the earliest time that
+	// If last_read is not nullptr, set *last_read to the earliest time that
 	// 'count_dmc_reads( time )' would result in the same result.
-	int count_dmc_reads( nes_time_t t, nes_time_t* last_read = NULL ) const;
+	int count_dmc_reads( nes_time_t t, nes_time_t* last_read = nullptr ) const;
 
 	// Time when next DMC memory read will occur
 	nes_time_t next_dmc_read_time() const;
diff --git a/src/console/Nes_Cpu.cc b/src/console/Nes_Cpu.cc
new file mode 100644
index 000000000000..ce9b5df7981d
--- /dev/null
+++ b/src/console/Nes_Cpu.cc
@@ -0,0 +1,1082 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Nes_Cpu.h"
+
+#include "blargg_endian.h"
+#include <limits.h>
+
+#define BLARGG_CPU_X86 1
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+#define FLUSH_TIME()    (void) (s.time = s_time)
+#define CACHE_TIME()    (void) (s_time = s.time)
+
+#include "nes_cpu_io.h"
+
+#include "blargg_source.h"
+
+#ifndef CPU_DONE
+	#define CPU_DONE( cpu, time, result_out )   { result_out = -1; }
+#endif
+
+#ifndef CPU_READ_PPU
+	#define CPU_READ_PPU( cpu, addr, out, time )\
+	{\
+		FLUSH_TIME();\
+		out = CPU_READ( cpu, addr, time );\
+		CACHE_TIME();\
+	}
+#endif
+
+#if BLARGG_NONPORTABLE
+	#define PAGE_OFFSET( addr ) (addr)
+#else
+	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
+#endif
+
+inline void Nes_Cpu::set_code_page( int i, void const* p )
+{
+	state->code_map [i] = (uint8_t const*) p - PAGE_OFFSET( i * page_size );
+}
+
+int const st_n = 0x80;
+int const st_v = 0x40;
+int const st_r = 0x20;
+int const st_b = 0x10;
+int const st_d = 0x08;
+int const st_i = 0x04;
+int const st_z = 0x02;
+int const st_c = 0x01;
+
+void Nes_Cpu::reset( void const* unmapped_page )
+{
+	check( state == &state_ );
+	state = &state_;
+	r.status = st_i;
+	r.sp = 0xFF;
+	r.pc = 0;
+	r.a  = 0;
+	r.x  = 0;
+	r.y  = 0;
+	state_.time = 0;
+	state_.base = 0;
+	irq_time_ = future_nes_time;
+	end_time_ = future_nes_time;
+	error_count_ = 0;
+
+	assert( page_size == 0x800 ); // assumes this
+	set_code_page( page_count, unmapped_page );
+	map_code( 0x2000, 0xE000, unmapped_page, true );
+	map_code( 0x0000, 0x2000, low_mem, true );
+}
+
+void Nes_Cpu::map_code( nes_addr_t start, unsigned size, void const* data, bool mirror )
+{
+	// address range must begin and end on page boundaries
+	require( start % page_size == 0 );
+	require( size % page_size == 0 );
+	require( start + size <= 0x10000 );
+
+	unsigned page = start / page_size;
+	for ( unsigned n = size / page_size; n; --n )
+	{
+		set_code_page( page++, data );
+		if ( !mirror )
+			data = (char const*) data + page_size;
+	}
+}
+
+#define TIME    (s_time + s.base)
+#define READ_LIKELY_PPU( addr, out )    {CPU_READ_PPU( this, (addr), out, TIME );}
+#define READ( addr )                    CPU_READ( this, (addr), TIME )
+#define WRITE( addr, data )             {CPU_WRITE( this, (addr), (data), TIME );}
+#define READ_LOW( addr )        (low_mem [int (addr)])
+#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
+#define READ_PROG( addr )       (s.code_map [(addr) >> page_bits] [PAGE_OFFSET( addr )])
+
+#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
+#define GET_SP()        ((sp - 1) & 0xFF)
+#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
+
+// even on x86, using short and unsigned char was slower
+typedef int         fint16;
+typedef unsigned    fuint16;
+typedef unsigned    fuint8;
+
+bool Nes_Cpu::run( nes_time_t end_time )
+{
+	set_end_time( end_time );
+	state_t s = this->state_;
+	this->state = &s;
+	// even on x86, using s.time in place of s_time was slower
+	fint16 s_time = s.time;
+
+	// registers
+	fuint16 pc = r.pc;
+	fuint8 a = r.a;
+	fuint8 x = r.x;
+	fuint8 y = r.y;
+	fuint16 sp;
+	SET_SP( r.sp );
+
+	// status flags
+	#define IS_NEG (nz & 0x8080)
+
+	#define CALC_STATUS( out ) do {\
+		out = status & (st_v | st_d | st_i);\
+		out |= ((nz >> 8) | nz) & st_n;\
+		out |= c >> 8 & st_c;\
+		if ( !(nz & 0xFF) ) out |= st_z;\
+	} while ( 0 )
+
+	#define SET_STATUS( in ) do {\
+		status = in & (st_v | st_d | st_i);\
+		nz = in << 8;\
+		c = nz;\
+		nz |= ~in & st_z;\
+	} while ( 0 )
+
+	fuint8 status;
+	fuint16 c;  // carry set if (c & 0x100) != 0
+	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
+	{
+		fuint8 temp = r.status;
+		SET_STATUS( temp );
+	}
+
+	goto loop;
+dec_clock_loop:
+	s_time--;
+loop:
+
+	check( (unsigned) GET_SP() < 0x100 );
+	check( (unsigned) pc < 0x10000 );
+	check( (unsigned) a < 0x100 );
+	check( (unsigned) x < 0x100 );
+	check( (unsigned) y < 0x100 );
+	check( -32768 <= s_time && s_time < 32767 );
+
+	uint8_t const* instr = s.code_map [pc >> page_bits];
+	fuint8 opcode;
+
+	// TODO: eliminate this special case
+	#if BLARGG_NONPORTABLE
+		opcode = instr [pc];
+		pc++;
+		instr += pc;
+	#else
+		instr += PAGE_OFFSET( pc );
+		opcode = *instr++;
+		pc++;
+	#endif
+
+	static uint8_t const clock_table [256] =
+	{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+		0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
+		6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
+		6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
+		6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
+		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
+		3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
+		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
+		3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
+		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
+		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
+		3,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
+	}; // 0x00 was 7 and 0xF2 was 2
+
+	fuint16 data;
+
+#if !BLARGG_CPU_X86
+	if ( s_time >= 0 )
+		goto out_of_time;
+	s_time += clock_table [opcode];
+
+	data = *instr;
+
+	switch ( opcode )
+	{
+#else
+
+	data = clock_table [opcode];
+	if ( (s_time += data) >= 0 )
+		goto possibly_out_of_time;
+almost_out_of_time:
+
+	data = *instr;
+
+	switch ( opcode )
+	{
+possibly_out_of_time:
+		if ( s_time < (int) data )
+			goto almost_out_of_time;
+		s_time -= data;
+		goto out_of_time;
+#endif
+
+// Macros
+
+#define GET_MSB()   (instr [1])
+#define ADD_PAGE()  (pc++, data += 0x100 * GET_MSB())
+#define GET_ADDR()  GET_LE16( instr )
+
+#define NO_PAGE_CROSSING( lsb )
+#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
+
+#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
+
+#define IND_Y( cross, out ) {\
+		fuint16 temp = READ_LOW( data ) + y;\
+		out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
+		cross( temp );\
+	}
+
+#define IND_X( out ) {\
+		fuint16 temp = data + x;\
+		out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
+	}
+
+#define ARITH_ADDR_MODES( op )\
+case op - 0x04: /* (ind,x) */\
+	IND_X( data )\
+	goto ptr##op;\
+case op + 0x0C: /* (ind),y */\
+	IND_Y( HANDLE_PAGE_CROSSING, data )\
+	goto ptr##op;\
+case op + 0x10: /* zp,X */\
+	data = uint8_t (data + x);\
+case op + 0x00: /* zp */\
+	data = READ_LOW( data );\
+	goto imm##op;\
+case op + 0x14: /* abs,Y */\
+	data += y;\
+	goto ind##op;\
+case op + 0x18: /* abs,X */\
+	data += x;\
+ind##op:\
+	HANDLE_PAGE_CROSSING( data );\
+case op + 0x08: /* abs */\
+	ADD_PAGE();\
+ptr##op:\
+	FLUSH_TIME();\
+	data = READ( data );\
+	CACHE_TIME();\
+case op + 0x04: /* imm */\
+imm##op:
+
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define BRANCH( cond )\
+{\
+	fint16 offset = (int8_t) data;\
+	fuint16 extra_clock = (++pc & 0xFF) + offset;\
+	if ( !(cond) ) goto dec_clock_loop;\
+	pc = uint16_t (pc + offset);\
+	s_time += extra_clock >> 8 & 1;\
+	goto loop;\
+}
+
+// Often-Used
+
+	case 0xB5: // LDA zp,x
+		a = nz = READ_LOW( uint8_t (data + x) );
+		pc++;
+		goto loop;
+
+	case 0xA5: // LDA zp
+		a = nz = READ_LOW( data );
+		pc++;
+		goto loop;
+
+	case 0xD0: // BNE
+		BRANCH( (uint8_t) nz );
+
+	case 0x20: { // JSR
+		fuint16 temp = pc + 1;
+		pc = GET_ADDR();
+		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
+		sp = (sp - 2) | 0x100;
+		WRITE_LOW( sp, temp );
+		goto loop;
+	}
+
+	case 0x4C: // JMP abs
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xE8: // INX
+		INC_DEC_XY( x, 1 )
+
+	case 0x10: // BPL
+		BRANCH( !IS_NEG )
+
+	ARITH_ADDR_MODES( 0xC5 ) // CMP
+		nz = a - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	case 0x30: // BMI
+		BRANCH( IS_NEG )
+
+	case 0xF0: // BEQ
+		BRANCH( !(uint8_t) nz );
+
+	case 0x95: // STA zp,x
+		data = uint8_t (data + x);
+	case 0x85: // STA zp
+		pc++;
+		WRITE_LOW( data, a );
+		goto loop;
+
+	case 0xC8: // INY
+		INC_DEC_XY( y, 1 )
+
+	case 0xA8: // TAY
+		y  = a;
+		nz = a;
+		goto loop;
+
+	case 0x98: // TYA
+		a  = y;
+		nz = y;
+		goto loop;
+
+	case 0xAD:{// LDA abs
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		READ_LIKELY_PPU( addr, nz );
+		a = nz;
+		goto loop;
+	}
+
+	case 0x60: // RTS
+		pc = 1 + READ_LOW( sp );
+		pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
+		sp = (sp - 0xFE) | 0x100;
+		goto loop;
+
+	{
+		fuint16 addr;
+
+	case 0x99: // STA abs,Y
+		addr = y + GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+		goto sta_ptr;
+
+	case 0x8D: // STA abs
+		addr = GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+		goto sta_ptr;
+
+	case 0x9D: // STA abs,X (slightly more common than STA abs)
+		addr = x + GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+	sta_ptr:
+		FLUSH_TIME();
+		WRITE( addr, a );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x91: // STA (ind),Y
+		IND_Y( NO_PAGE_CROSSING, addr )
+		pc++;
+		goto sta_ptr;
+
+	case 0x81: // STA (ind,X)
+		IND_X( addr )
+		pc++;
+		goto sta_ptr;
+
+	}
+
+	case 0xA9: // LDA #imm
+		pc++;
+		a  = data;
+		nz = data;
+		goto loop;
+
+	// common read instructions
+	{
+		fuint16 addr;
+
+	case 0xA1: // LDA (ind,X)
+		IND_X( addr )
+		pc++;
+		goto a_nz_read_addr;
+
+	case 0xB1:// LDA (ind),Y
+		addr = READ_LOW( data ) + y;
+		HANDLE_PAGE_CROSSING( addr );
+		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
+		pc++;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+		goto a_nz_read_addr;
+
+	case 0xB9: // LDA abs,Y
+		HANDLE_PAGE_CROSSING( data + y );
+		addr = GET_ADDR() + y;
+		pc += 2;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+		goto a_nz_read_addr;
+
+	case 0xBD: // LDA abs,X
+		HANDLE_PAGE_CROSSING( data + x );
+		addr = GET_ADDR() + x;
+		pc += 2;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+	a_nz_read_addr:
+		FLUSH_TIME();
+		a = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+
+	}
+
+// Branch
+
+	case 0x50: // BVC
+		BRANCH( !(status & st_v) )
+
+	case 0x70: // BVS
+		BRANCH( status & st_v )
+
+	case 0xB0: // BCS
+		BRANCH( c & 0x100 )
+
+	case 0x90: // BCC
+		BRANCH( !(c & 0x100) )
+
+// Load/store
+
+	case 0x94: // STY zp,x
+		data = uint8_t (data + x);
+	case 0x84: // STY zp
+		pc++;
+		WRITE_LOW( data, y );
+		goto loop;
+
+	case 0x96: // STX zp,y
+		data = uint8_t (data + y);
+	case 0x86: // STX zp
+		pc++;
+		WRITE_LOW( data, x );
+		goto loop;
+
+	case 0xB6: // LDX zp,y
+		data = uint8_t (data + y);
+	case 0xA6: // LDX zp
+		data = READ_LOW( data );
+	case 0xA2: // LDX #imm
+		pc++;
+		x = data;
+		nz = data;
+		goto loop;
+
+	case 0xB4: // LDY zp,x
+		data = uint8_t (data + x);
+	case 0xA4: // LDY zp
+		data = READ_LOW( data );
+	case 0xA0: // LDY #imm
+		pc++;
+		y = data;
+		nz = data;
+		goto loop;
+
+	case 0xBC: // LDY abs,X
+		data += x;
+		HANDLE_PAGE_CROSSING( data );
+	case 0xAC:{// LDY abs
+		unsigned addr = data + 0x100 * GET_MSB();
+		pc += 2;
+		FLUSH_TIME();
+		y = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	case 0xBE: // LDX abs,y
+		data += y;
+		HANDLE_PAGE_CROSSING( data );
+	case 0xAE:{// LDX abs
+		unsigned addr = data + 0x100 * GET_MSB();
+		pc += 2;
+		FLUSH_TIME();
+		x = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	{
+		fuint8 temp;
+	case 0x8C: // STY abs
+		temp = y;
+		goto store_abs;
+
+	case 0x8E: // STX abs
+		temp = x;
+	store_abs:
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, temp );
+			goto loop;
+		}
+		FLUSH_TIME();
+		WRITE( addr, temp );
+		CACHE_TIME();
+		goto loop;
+	}
+
+// Compare
+
+	case 0xEC:{// CPX abs
+		unsigned addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpx_data;
+	}
+
+	case 0xE4: // CPX zp
+		data = READ_LOW( data );
+	case 0xE0: // CPX #imm
+	cpx_data:
+		nz = x - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	case 0xCC:{// CPY abs
+		unsigned addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpy_data;
+	}
+
+	case 0xC4: // CPY zp
+		data = READ_LOW( data );
+	case 0xC0: // CPY #imm
+	cpy_data:
+		nz = y - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+// Logical
+
+	ARITH_ADDR_MODES( 0x25 ) // AND
+		nz = (a &= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x45 ) // EOR
+		nz = (a ^= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x05 ) // ORA
+		nz = (a |= data);
+		pc++;
+		goto loop;
+
+	case 0x2C:{// BIT abs
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		status &= ~st_v;
+		READ_LIKELY_PPU( addr, nz );
+		status |= nz & st_v;
+		if ( a & nz )
+			goto loop;
+		nz <<= 8; // result must be zero, even if N bit is set
+		goto loop;
+	}
+
+	case 0x24: // BIT zp
+		nz = READ_LOW( data );
+		pc++;
+		status &= ~st_v;
+		status |= nz & st_v;
+		if ( a & nz )
+			goto loop;
+		nz <<= 8; // result must be zero, even if N bit is set
+		goto loop;
+
+// Add/subtract
+
+	ARITH_ADDR_MODES( 0xE5 ) // SBC
+	case 0xEB: // unofficial equivalent
+		data ^= 0xFF;
+		goto adc_imm;
+
+	ARITH_ADDR_MODES( 0x65 ) // ADC
+	adc_imm: {
+		fint16 carry = c >> 8 & 1;
+		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
+		status &= ~st_v;
+		status |= ov >> 2 & 0x40;
+		c = nz = a + data + carry;
+		pc++;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+// Shift/rotate
+
+	case 0x4A: // LSR A
+		c = 0;
+	case 0x6A: // ROR A
+		nz = c >> 1 & 0x80;
+		c = a << 8;
+		nz |= a >> 1;
+		a = nz;
+		goto loop;
+
+	case 0x0A: // ASL A
+		nz = a << 1;
+		c = nz;
+		a = (uint8_t) nz;
+		goto loop;
+
+	case 0x2A: { // ROL A
+		nz = a << 1;
+		fint16 temp = c >> 8 & 1;
+		c = nz;
+		nz |= temp;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+	case 0x5E: // LSR abs,X
+		data += x;
+	case 0x4E: // LSR abs
+		c = 0;
+	case 0x6E: // ROR abs
+	ror_abs: {
+		ADD_PAGE();
+		FLUSH_TIME();
+		int temp = READ( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto rotate_common;
+	}
+
+	case 0x3E: // ROL abs,X
+		data += x;
+		goto rol_abs;
+
+	case 0x1E: // ASL abs,X
+		data += x;
+	case 0x0E: // ASL abs
+		c = 0;
+	case 0x2E: // ROL abs
+	rol_abs:
+		ADD_PAGE();
+		nz = c >> 8 & 1;
+		FLUSH_TIME();
+		nz |= (c = READ( data ) << 1);
+	rotate_common:
+		pc++;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x7E: // ROR abs,X
+		data += x;
+		goto ror_abs;
+
+	case 0x76: // ROR zp,x
+		data = uint8_t (data + x);
+		goto ror_zp;
+
+	case 0x56: // LSR zp,x
+		data = uint8_t (data + x);
+	case 0x46: // LSR zp
+		c = 0;
+	case 0x66: // ROR zp
+	ror_zp: {
+		int temp = READ_LOW( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto write_nz_zp;
+	}
+
+	case 0x36: // ROL zp,x
+		data = uint8_t (data + x);
+		goto rol_zp;
+
+	case 0x16: // ASL zp,x
+		data = uint8_t (data + x);
+	case 0x06: // ASL zp
+		c = 0;
+	case 0x26: // ROL zp
+	rol_zp:
+		nz = c >> 8 & 1;
+		nz |= (c = READ_LOW( data ) << 1);
+		goto write_nz_zp;
+
+// Increment/decrement
+
+	case 0xCA: // DEX
+		INC_DEC_XY( x, -1 )
+
+	case 0x88: // DEY
+		INC_DEC_XY( y, -1 )
+
+	case 0xF6: // INC zp,x
+		data = uint8_t (data + x);
+	case 0xE6: // INC zp
+		nz = 1;
+		goto add_nz_zp;
+
+	case 0xD6: // DEC zp,x
+		data = uint8_t (data + x);
+	case 0xC6: // DEC zp
+		nz = (unsigned) -1;
+	add_nz_zp:
+		nz += READ_LOW( data );
+	write_nz_zp:
+		pc++;
+		WRITE_LOW( data, nz );
+		goto loop;
+
+	case 0xFE: // INC abs,x
+		data = x + GET_ADDR();
+		goto inc_ptr;
+
+	case 0xEE: // INC abs
+		data = GET_ADDR();
+	inc_ptr:
+		nz = 1;
+		goto inc_common;
+
+	case 0xDE: // DEC abs,x
+		data = x + GET_ADDR();
+		goto dec_ptr;
+
+	case 0xCE: // DEC abs
+		data = GET_ADDR();
+	dec_ptr:
+		nz = (unsigned) -1;
+	inc_common:
+		FLUSH_TIME();
+		nz += READ( data );
+		pc += 2;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+// Transfer
+
+	case 0xAA: // TAX
+		x  = a;
+		nz = a;
+		goto loop;
+
+	case 0x8A: // TXA
+		a  = x;
+		nz = x;
+		goto loop;
+
+	case 0x9A: // TXS
+		SET_SP( x ); // verified (no flag change)
+		goto loop;
+
+	case 0xBA: // TSX
+		x = nz = GET_SP();
+		goto loop;
+
+// Stack
+
+	case 0x48: // PHA
+		PUSH( a ); // verified
+		goto loop;
+
+	case 0x68: // PLA
+		a = nz = READ_LOW( sp );
+		sp = (sp - 0xFF) | 0x100;
+		goto loop;
+
+	case 0x40:{// RTI
+		fuint8 temp = READ_LOW( sp );
+		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
+		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
+		sp = (sp - 0xFD) | 0x100;
+		data = status;
+		SET_STATUS( temp );
+		if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - irq_time_;
+		if ( delta <= 0 ) goto loop;
+		if ( status & st_i ) goto loop;
+		s_time += delta;
+		s.base = irq_time_;
+		goto loop;
+	}
+
+	case 0x28:{// PLP
+		fuint8 temp = READ_LOW( sp );
+		sp = (sp - 0xFF) | 0x100;
+		fuint8 changed = status ^ temp;
+		SET_STATUS( temp );
+		if ( !(changed & st_i) )
+			goto loop; // I flag didn't change
+		if ( status & st_i )
+			goto handle_sei;
+		goto handle_cli;
+	}
+
+	case 0x08: { // PHP
+		fuint8 temp;
+		CALC_STATUS( temp );
+		PUSH( temp | (st_b | st_r) );
+		goto loop;
+	}
+
+	case 0x6C:{// JMP (ind)
+		data = GET_ADDR();
+		check( unsigned (data - 0x2000) >= 0x4000 ); // ensure it's outside I/O space
+		uint8_t const* page = s.code_map [data >> page_bits];
+		pc = page [PAGE_OFFSET( data )];
+		data = (data & 0xFF00) | ((data + 1) & 0xFF);
+		pc |= page [PAGE_OFFSET( data )] << 8;
+		goto loop;
+	}
+
+	case 0x00: // BRK
+		goto handle_brk;
+
+// Flags
+
+	case 0x38: // SEC
+		c = (unsigned) ~0;
+		goto loop;
+
+	case 0x18: // CLC
+		c = 0;
+		goto loop;
+
+	case 0xB8: // CLV
+		status &= ~st_v;
+		goto loop;
+
+	case 0xD8: // CLD
+		status &= ~st_d;
+		goto loop;
+
+	case 0xF8: // SED
+		status |= st_d;
+		goto loop;
+
+	case 0x58: // CLI
+		if ( !(status & st_i) )
+			goto loop;
+		status &= ~st_i;
+	handle_cli: {
+		//debug_printf( "CLI at %d\n", TIME );
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - irq_time_;
+		if ( delta <= 0 )
+		{
+			if ( TIME < irq_time_ )
+				goto loop;
+			goto delayed_cli;
+		}
+		s.base = irq_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+
+		if ( delta >= s_time + 1 )
+		{
+			s.base += s_time + 1;
+			s_time = -1;
+			goto loop;
+		}
+
+		// TODO: implement
+	delayed_cli:
+		debug_printf( "Delayed CLI not emulated\n" );
+		goto loop;
+	}
+
+	case 0x78: // SEI
+		if ( status & st_i )
+			goto loop;
+		status |= st_i;
+	handle_sei: {
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - end_time_;
+		s.base = end_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+
+		debug_printf( "Delayed SEI not emulated\n" );
+		goto loop;
+	}
+
+// Unofficial
+
+	// SKW - Skip word
+	case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
+		HANDLE_PAGE_CROSSING( data + x );
+	case 0x0C:
+		pc++;
+	// SKB - Skip byte
+	case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
+	case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
+		pc++;
+		goto loop;
+
+	// NOP
+	case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
+		goto loop;
+
+	case bad_opcode: // HLT
+		pc--;
+		if ( pc > 0xFFFF )
+		{
+			// handle wrap-around (assumes caller has put page of HLT at 0x10000)
+			pc &= 0xFFFF;
+			goto loop;
+		}
+	case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
+	case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2:
+		goto stop;
+
+// Unimplemented
+
+	case 0xFF: // force 256-entry jump table for optimization purposes
+		c |= 1;
+	default:
+		check( (unsigned) opcode <= 0xFF );
+		// skip over proper number of bytes
+		static unsigned char const illop_lens [8] = {
+			0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
+		};
+		fuint8 opcode = instr [-1];
+		fint16 len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
+		if ( opcode == 0x9C )
+			len = 2;
+		pc += len;
+		error_count_++;
+
+		if ( (opcode >> 4) == 0x0B )
+		{
+			if ( opcode == 0xB3 )
+				data = READ_LOW( data );
+			if ( opcode != 0xB7 )
+				HANDLE_PAGE_CROSSING( data + y );
+		}
+		goto loop;
+	}
+	assert( false );
+
+	int result_;
+handle_brk:
+	pc++;
+	result_ = 4;
+
+interrupt:
+	{
+		s_time += 7;
+
+		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
+		WRITE_LOW( 0x100 | (sp - 2), pc );
+		pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
+
+		sp = (sp - 3) | 0x100;
+		fuint8 temp;
+		CALC_STATUS( temp );
+		temp |= st_r;
+		if ( result_ )
+			temp |= st_b; // TODO: incorrectly sets B flag for IRQ
+		WRITE_LOW( sp, temp );
+
+		this->r.status = status |= st_i;
+		blargg_long delta = s.base - end_time_;
+		if ( delta >= 0 ) goto loop;
+		s_time += delta;
+		s.base = end_time_;
+		goto loop;
+	}
+
+out_of_time:
+	pc--;
+	FLUSH_TIME();
+	CPU_DONE( this, TIME, result_ );
+	CACHE_TIME();
+	if ( result_ >= 0 )
+		goto interrupt;
+	if ( s_time < 0 )
+		goto loop;
+
+stop:
+
+	s.time = s_time;
+
+	r.pc = pc;
+	r.sp = GET_SP();
+	r.a = a;
+	r.x = x;
+	r.y = y;
+
+	{
+		fuint8 temp;
+		CALC_STATUS( temp );
+		r.status = temp;
+	}
+
+	this->state_ = s;
+	this->state = &this->state_;
+
+	return s_time < 0;
+}
+
diff --git a/src/console/Nes_Cpu.cxx b/src/console/Nes_Cpu.cxx
deleted file mode 100644
index ce9b5df7981d..000000000000
--- a/src/console/Nes_Cpu.cxx
+++ /dev/null
@@ -1,1082 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nes_Cpu.h"
-
-#include "blargg_endian.h"
-#include <limits.h>
-
-#define BLARGG_CPU_X86 1
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-#define FLUSH_TIME()    (void) (s.time = s_time)
-#define CACHE_TIME()    (void) (s_time = s.time)
-
-#include "nes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#ifndef CPU_DONE
-	#define CPU_DONE( cpu, time, result_out )   { result_out = -1; }
-#endif
-
-#ifndef CPU_READ_PPU
-	#define CPU_READ_PPU( cpu, addr, out, time )\
-	{\
-		FLUSH_TIME();\
-		out = CPU_READ( cpu, addr, time );\
-		CACHE_TIME();\
-	}
-#endif
-
-#if BLARGG_NONPORTABLE
-	#define PAGE_OFFSET( addr ) (addr)
-#else
-	#define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Nes_Cpu::set_code_page( int i, void const* p )
-{
-	state->code_map [i] = (uint8_t const*) p - PAGE_OFFSET( i * page_size );
-}
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Nes_Cpu::reset( void const* unmapped_page )
-{
-	check( state == &state_ );
-	state = &state_;
-	r.status = st_i;
-	r.sp = 0xFF;
-	r.pc = 0;
-	r.a  = 0;
-	r.x  = 0;
-	r.y  = 0;
-	state_.time = 0;
-	state_.base = 0;
-	irq_time_ = future_nes_time;
-	end_time_ = future_nes_time;
-	error_count_ = 0;
-
-	assert( page_size == 0x800 ); // assumes this
-	set_code_page( page_count, unmapped_page );
-	map_code( 0x2000, 0xE000, unmapped_page, true );
-	map_code( 0x0000, 0x2000, low_mem, true );
-}
-
-void Nes_Cpu::map_code( nes_addr_t start, unsigned size, void const* data, bool mirror )
-{
-	// address range must begin and end on page boundaries
-	require( start % page_size == 0 );
-	require( size % page_size == 0 );
-	require( start + size <= 0x10000 );
-
-	unsigned page = start / page_size;
-	for ( unsigned n = size / page_size; n; --n )
-	{
-		set_code_page( page++, data );
-		if ( !mirror )
-			data = (char const*) data + page_size;
-	}
-}
-
-#define TIME    (s_time + s.base)
-#define READ_LIKELY_PPU( addr, out )    {CPU_READ_PPU( this, (addr), out, TIME );}
-#define READ( addr )                    CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data )             {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr )        (low_mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr )       (s.code_map [(addr) >> page_bits] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
-#define GET_SP()        ((sp - 1) & 0xFF)
-#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int         fint16;
-typedef unsigned    fuint16;
-typedef unsigned    fuint8;
-
-bool Nes_Cpu::run( nes_time_t end_time )
-{
-	set_end_time( end_time );
-	state_t s = this->state_;
-	this->state = &s;
-	// even on x86, using s.time in place of s_time was slower
-	fint16 s_time = s.time;
-
-	// registers
-	fuint16 pc = r.pc;
-	fuint8 a = r.a;
-	fuint8 x = r.x;
-	fuint8 y = r.y;
-	fuint16 sp;
-	SET_SP( r.sp );
-
-	// status flags
-	#define IS_NEG (nz & 0x8080)
-
-	#define CALC_STATUS( out ) do {\
-		out = status & (st_v | st_d | st_i);\
-		out |= ((nz >> 8) | nz) & st_n;\
-		out |= c >> 8 & st_c;\
-		if ( !(nz & 0xFF) ) out |= st_z;\
-	} while ( 0 )
-
-	#define SET_STATUS( in ) do {\
-		status = in & (st_v | st_d | st_i);\
-		nz = in << 8;\
-		c = nz;\
-		nz |= ~in & st_z;\
-	} while ( 0 )
-
-	fuint8 status;
-	fuint16 c;  // carry set if (c & 0x100) != 0
-	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
-	{
-		fuint8 temp = r.status;
-		SET_STATUS( temp );
-	}
-
-	goto loop;
-dec_clock_loop:
-	s_time--;
-loop:
-
-	check( (unsigned) GET_SP() < 0x100 );
-	check( (unsigned) pc < 0x10000 );
-	check( (unsigned) a < 0x100 );
-	check( (unsigned) x < 0x100 );
-	check( (unsigned) y < 0x100 );
-	check( -32768 <= s_time && s_time < 32767 );
-
-	uint8_t const* instr = s.code_map [pc >> page_bits];
-	fuint8 opcode;
-
-	// TODO: eliminate this special case
-	#if BLARGG_NONPORTABLE
-		opcode = instr [pc];
-		pc++;
-		instr += pc;
-	#else
-		instr += PAGE_OFFSET( pc );
-		opcode = *instr++;
-		pc++;
-	#endif
-
-	static uint8_t const clock_table [256] =
-	{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
-		0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
-		6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
-		6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
-		6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
-		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
-		3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
-		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
-		3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
-		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
-		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
-		3,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
-	}; // 0x00 was 7 and 0xF2 was 2
-
-	fuint16 data;
-
-#if !BLARGG_CPU_X86
-	if ( s_time >= 0 )
-		goto out_of_time;
-	s_time += clock_table [opcode];
-
-	data = *instr;
-
-	switch ( opcode )
-	{
-#else
-
-	data = clock_table [opcode];
-	if ( (s_time += data) >= 0 )
-		goto possibly_out_of_time;
-almost_out_of_time:
-
-	data = *instr;
-
-	switch ( opcode )
-	{
-possibly_out_of_time:
-		if ( s_time < (int) data )
-			goto almost_out_of_time;
-		s_time -= data;
-		goto out_of_time;
-#endif
-
-// Macros
-
-#define GET_MSB()   (instr [1])
-#define ADD_PAGE()  (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR()  GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
-		fuint16 temp = READ_LOW( data ) + y;\
-		out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
-		cross( temp );\
-	}
-
-#define IND_X( out ) {\
-		fuint16 temp = data + x;\
-		out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
-	}
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
-	IND_X( data )\
-	goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
-	IND_Y( HANDLE_PAGE_CROSSING, data )\
-	goto ptr##op;\
-case op + 0x10: /* zp,X */\
-	data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
-	data = READ_LOW( data );\
-	goto imm##op;\
-case op + 0x14: /* abs,Y */\
-	data += y;\
-	goto ind##op;\
-case op + 0x18: /* abs,X */\
-	data += x;\
-ind##op:\
-	HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
-	ADD_PAGE();\
-ptr##op:\
-	FLUSH_TIME();\
-	data = READ( data );\
-	CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
-	fint16 offset = (int8_t) data;\
-	fuint16 extra_clock = (++pc & 0xFF) + offset;\
-	if ( !(cond) ) goto dec_clock_loop;\
-	pc = uint16_t (pc + offset);\
-	s_time += extra_clock >> 8 & 1;\
-	goto loop;\
-}
-
-// Often-Used
-
-	case 0xB5: // LDA zp,x
-		a = nz = READ_LOW( uint8_t (data + x) );
-		pc++;
-		goto loop;
-
-	case 0xA5: // LDA zp
-		a = nz = READ_LOW( data );
-		pc++;
-		goto loop;
-
-	case 0xD0: // BNE
-		BRANCH( (uint8_t) nz );
-
-	case 0x20: { // JSR
-		fuint16 temp = pc + 1;
-		pc = GET_ADDR();
-		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
-		sp = (sp - 2) | 0x100;
-		WRITE_LOW( sp, temp );
-		goto loop;
-	}
-
-	case 0x4C: // JMP abs
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xE8: // INX
-		INC_DEC_XY( x, 1 )
-
-	case 0x10: // BPL
-		BRANCH( !IS_NEG )
-
-	ARITH_ADDR_MODES( 0xC5 ) // CMP
-		nz = a - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	case 0x30: // BMI
-		BRANCH( IS_NEG )
-
-	case 0xF0: // BEQ
-		BRANCH( !(uint8_t) nz );
-
-	case 0x95: // STA zp,x
-		data = uint8_t (data + x);
-	case 0x85: // STA zp
-		pc++;
-		WRITE_LOW( data, a );
-		goto loop;
-
-	case 0xC8: // INY
-		INC_DEC_XY( y, 1 )
-
-	case 0xA8: // TAY
-		y  = a;
-		nz = a;
-		goto loop;
-
-	case 0x98: // TYA
-		a  = y;
-		nz = y;
-		goto loop;
-
-	case 0xAD:{// LDA abs
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		READ_LIKELY_PPU( addr, nz );
-		a = nz;
-		goto loop;
-	}
-
-	case 0x60: // RTS
-		pc = 1 + READ_LOW( sp );
-		pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
-		sp = (sp - 0xFE) | 0x100;
-		goto loop;
-
-	{
-		fuint16 addr;
-
-	case 0x99: // STA abs,Y
-		addr = y + GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-		goto sta_ptr;
-
-	case 0x8D: // STA abs
-		addr = GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-		goto sta_ptr;
-
-	case 0x9D: // STA abs,X (slightly more common than STA abs)
-		addr = x + GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-	sta_ptr:
-		FLUSH_TIME();
-		WRITE( addr, a );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x91: // STA (ind),Y
-		IND_Y( NO_PAGE_CROSSING, addr )
-		pc++;
-		goto sta_ptr;
-
-	case 0x81: // STA (ind,X)
-		IND_X( addr )
-		pc++;
-		goto sta_ptr;
-
-	}
-
-	case 0xA9: // LDA #imm
-		pc++;
-		a  = data;
-		nz = data;
-		goto loop;
-
-	// common read instructions
-	{
-		fuint16 addr;
-
-	case 0xA1: // LDA (ind,X)
-		IND_X( addr )
-		pc++;
-		goto a_nz_read_addr;
-
-	case 0xB1:// LDA (ind),Y
-		addr = READ_LOW( data ) + y;
-		HANDLE_PAGE_CROSSING( addr );
-		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
-		pc++;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-		goto a_nz_read_addr;
-
-	case 0xB9: // LDA abs,Y
-		HANDLE_PAGE_CROSSING( data + y );
-		addr = GET_ADDR() + y;
-		pc += 2;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-		goto a_nz_read_addr;
-
-	case 0xBD: // LDA abs,X
-		HANDLE_PAGE_CROSSING( data + x );
-		addr = GET_ADDR() + x;
-		pc += 2;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-	a_nz_read_addr:
-		FLUSH_TIME();
-		a = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-
-	}
-
-// Branch
-
-	case 0x50: // BVC
-		BRANCH( !(status & st_v) )
-
-	case 0x70: // BVS
-		BRANCH( status & st_v )
-
-	case 0xB0: // BCS
-		BRANCH( c & 0x100 )
-
-	case 0x90: // BCC
-		BRANCH( !(c & 0x100) )
-
-// Load/store
-
-	case 0x94: // STY zp,x
-		data = uint8_t (data + x);
-	case 0x84: // STY zp
-		pc++;
-		WRITE_LOW( data, y );
-		goto loop;
-
-	case 0x96: // STX zp,y
-		data = uint8_t (data + y);
-	case 0x86: // STX zp
-		pc++;
-		WRITE_LOW( data, x );
-		goto loop;
-
-	case 0xB6: // LDX zp,y
-		data = uint8_t (data + y);
-	case 0xA6: // LDX zp
-		data = READ_LOW( data );
-	case 0xA2: // LDX #imm
-		pc++;
-		x = data;
-		nz = data;
-		goto loop;
-
-	case 0xB4: // LDY zp,x
-		data = uint8_t (data + x);
-	case 0xA4: // LDY zp
-		data = READ_LOW( data );
-	case 0xA0: // LDY #imm
-		pc++;
-		y = data;
-		nz = data;
-		goto loop;
-
-	case 0xBC: // LDY abs,X
-		data += x;
-		HANDLE_PAGE_CROSSING( data );
-	case 0xAC:{// LDY abs
-		unsigned addr = data + 0x100 * GET_MSB();
-		pc += 2;
-		FLUSH_TIME();
-		y = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	case 0xBE: // LDX abs,y
-		data += y;
-		HANDLE_PAGE_CROSSING( data );
-	case 0xAE:{// LDX abs
-		unsigned addr = data + 0x100 * GET_MSB();
-		pc += 2;
-		FLUSH_TIME();
-		x = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	{
-		fuint8 temp;
-	case 0x8C: // STY abs
-		temp = y;
-		goto store_abs;
-
-	case 0x8E: // STX abs
-		temp = x;
-	store_abs:
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, temp );
-			goto loop;
-		}
-		FLUSH_TIME();
-		WRITE( addr, temp );
-		CACHE_TIME();
-		goto loop;
-	}
-
-// Compare
-
-	case 0xEC:{// CPX abs
-		unsigned addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpx_data;
-	}
-
-	case 0xE4: // CPX zp
-		data = READ_LOW( data );
-	case 0xE0: // CPX #imm
-	cpx_data:
-		nz = x - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	case 0xCC:{// CPY abs
-		unsigned addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpy_data;
-	}
-
-	case 0xC4: // CPY zp
-		data = READ_LOW( data );
-	case 0xC0: // CPY #imm
-	cpy_data:
-		nz = y - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-// Logical
-
-	ARITH_ADDR_MODES( 0x25 ) // AND
-		nz = (a &= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x45 ) // EOR
-		nz = (a ^= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x05 ) // ORA
-		nz = (a |= data);
-		pc++;
-		goto loop;
-
-	case 0x2C:{// BIT abs
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		status &= ~st_v;
-		READ_LIKELY_PPU( addr, nz );
-		status |= nz & st_v;
-		if ( a & nz )
-			goto loop;
-		nz <<= 8; // result must be zero, even if N bit is set
-		goto loop;
-	}
-
-	case 0x24: // BIT zp
-		nz = READ_LOW( data );
-		pc++;
-		status &= ~st_v;
-		status |= nz & st_v;
-		if ( a & nz )
-			goto loop;
-		nz <<= 8; // result must be zero, even if N bit is set
-		goto loop;
-
-// Add/subtract
-
-	ARITH_ADDR_MODES( 0xE5 ) // SBC
-	case 0xEB: // unofficial equivalent
-		data ^= 0xFF;
-		goto adc_imm;
-
-	ARITH_ADDR_MODES( 0x65 ) // ADC
-	adc_imm: {
-		fint16 carry = c >> 8 & 1;
-		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
-		status &= ~st_v;
-		status |= ov >> 2 & 0x40;
-		c = nz = a + data + carry;
-		pc++;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-// Shift/rotate
-
-	case 0x4A: // LSR A
-		c = 0;
-	case 0x6A: // ROR A
-		nz = c >> 1 & 0x80;
-		c = a << 8;
-		nz |= a >> 1;
-		a = nz;
-		goto loop;
-
-	case 0x0A: // ASL A
-		nz = a << 1;
-		c = nz;
-		a = (uint8_t) nz;
-		goto loop;
-
-	case 0x2A: { // ROL A
-		nz = a << 1;
-		fint16 temp = c >> 8 & 1;
-		c = nz;
-		nz |= temp;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-	case 0x5E: // LSR abs,X
-		data += x;
-	case 0x4E: // LSR abs
-		c = 0;
-	case 0x6E: // ROR abs
-	ror_abs: {
-		ADD_PAGE();
-		FLUSH_TIME();
-		int temp = READ( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto rotate_common;
-	}
-
-	case 0x3E: // ROL abs,X
-		data += x;
-		goto rol_abs;
-
-	case 0x1E: // ASL abs,X
-		data += x;
-	case 0x0E: // ASL abs
-		c = 0;
-	case 0x2E: // ROL abs
-	rol_abs:
-		ADD_PAGE();
-		nz = c >> 8 & 1;
-		FLUSH_TIME();
-		nz |= (c = READ( data ) << 1);
-	rotate_common:
-		pc++;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x7E: // ROR abs,X
-		data += x;
-		goto ror_abs;
-
-	case 0x76: // ROR zp,x
-		data = uint8_t (data + x);
-		goto ror_zp;
-
-	case 0x56: // LSR zp,x
-		data = uint8_t (data + x);
-	case 0x46: // LSR zp
-		c = 0;
-	case 0x66: // ROR zp
-	ror_zp: {
-		int temp = READ_LOW( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto write_nz_zp;
-	}
-
-	case 0x36: // ROL zp,x
-		data = uint8_t (data + x);
-		goto rol_zp;
-
-	case 0x16: // ASL zp,x
-		data = uint8_t (data + x);
-	case 0x06: // ASL zp
-		c = 0;
-	case 0x26: // ROL zp
-	rol_zp:
-		nz = c >> 8 & 1;
-		nz |= (c = READ_LOW( data ) << 1);
-		goto write_nz_zp;
-
-// Increment/decrement
-
-	case 0xCA: // DEX
-		INC_DEC_XY( x, -1 )
-
-	case 0x88: // DEY
-		INC_DEC_XY( y, -1 )
-
-	case 0xF6: // INC zp,x
-		data = uint8_t (data + x);
-	case 0xE6: // INC zp
-		nz = 1;
-		goto add_nz_zp;
-
-	case 0xD6: // DEC zp,x
-		data = uint8_t (data + x);
-	case 0xC6: // DEC zp
-		nz = (unsigned) -1;
-	add_nz_zp:
-		nz += READ_LOW( data );
-	write_nz_zp:
-		pc++;
-		WRITE_LOW( data, nz );
-		goto loop;
-
-	case 0xFE: // INC abs,x
-		data = x + GET_ADDR();
-		goto inc_ptr;
-
-	case 0xEE: // INC abs
-		data = GET_ADDR();
-	inc_ptr:
-		nz = 1;
-		goto inc_common;
-
-	case 0xDE: // DEC abs,x
-		data = x + GET_ADDR();
-		goto dec_ptr;
-
-	case 0xCE: // DEC abs
-		data = GET_ADDR();
-	dec_ptr:
-		nz = (unsigned) -1;
-	inc_common:
-		FLUSH_TIME();
-		nz += READ( data );
-		pc += 2;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-// Transfer
-
-	case 0xAA: // TAX
-		x  = a;
-		nz = a;
-		goto loop;
-
-	case 0x8A: // TXA
-		a  = x;
-		nz = x;
-		goto loop;
-
-	case 0x9A: // TXS
-		SET_SP( x ); // verified (no flag change)
-		goto loop;
-
-	case 0xBA: // TSX
-		x = nz = GET_SP();
-		goto loop;
-
-// Stack
-
-	case 0x48: // PHA
-		PUSH( a ); // verified
-		goto loop;
-
-	case 0x68: // PLA
-		a = nz = READ_LOW( sp );
-		sp = (sp - 0xFF) | 0x100;
-		goto loop;
-
-	case 0x40:{// RTI
-		fuint8 temp = READ_LOW( sp );
-		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
-		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
-		sp = (sp - 0xFD) | 0x100;
-		data = status;
-		SET_STATUS( temp );
-		if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - irq_time_;
-		if ( delta <= 0 ) goto loop;
-		if ( status & st_i ) goto loop;
-		s_time += delta;
-		s.base = irq_time_;
-		goto loop;
-	}
-
-	case 0x28:{// PLP
-		fuint8 temp = READ_LOW( sp );
-		sp = (sp - 0xFF) | 0x100;
-		fuint8 changed = status ^ temp;
-		SET_STATUS( temp );
-		if ( !(changed & st_i) )
-			goto loop; // I flag didn't change
-		if ( status & st_i )
-			goto handle_sei;
-		goto handle_cli;
-	}
-
-	case 0x08: { // PHP
-		fuint8 temp;
-		CALC_STATUS( temp );
-		PUSH( temp | (st_b | st_r) );
-		goto loop;
-	}
-
-	case 0x6C:{// JMP (ind)
-		data = GET_ADDR();
-		check( unsigned (data - 0x2000) >= 0x4000 ); // ensure it's outside I/O space
-		uint8_t const* page = s.code_map [data >> page_bits];
-		pc = page [PAGE_OFFSET( data )];
-		data = (data & 0xFF00) | ((data + 1) & 0xFF);
-		pc |= page [PAGE_OFFSET( data )] << 8;
-		goto loop;
-	}
-
-	case 0x00: // BRK
-		goto handle_brk;
-
-// Flags
-
-	case 0x38: // SEC
-		c = (unsigned) ~0;
-		goto loop;
-
-	case 0x18: // CLC
-		c = 0;
-		goto loop;
-
-	case 0xB8: // CLV
-		status &= ~st_v;
-		goto loop;
-
-	case 0xD8: // CLD
-		status &= ~st_d;
-		goto loop;
-
-	case 0xF8: // SED
-		status |= st_d;
-		goto loop;
-
-	case 0x58: // CLI
-		if ( !(status & st_i) )
-			goto loop;
-		status &= ~st_i;
-	handle_cli: {
-		//debug_printf( "CLI at %d\n", TIME );
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - irq_time_;
-		if ( delta <= 0 )
-		{
-			if ( TIME < irq_time_ )
-				goto loop;
-			goto delayed_cli;
-		}
-		s.base = irq_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-
-		if ( delta >= s_time + 1 )
-		{
-			s.base += s_time + 1;
-			s_time = -1;
-			goto loop;
-		}
-
-		// TODO: implement
-	delayed_cli:
-		debug_printf( "Delayed CLI not emulated\n" );
-		goto loop;
-	}
-
-	case 0x78: // SEI
-		if ( status & st_i )
-			goto loop;
-		status |= st_i;
-	handle_sei: {
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - end_time_;
-		s.base = end_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-
-		debug_printf( "Delayed SEI not emulated\n" );
-		goto loop;
-	}
-
-// Unofficial
-
-	// SKW - Skip word
-	case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
-		HANDLE_PAGE_CROSSING( data + x );
-	case 0x0C:
-		pc++;
-	// SKB - Skip byte
-	case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
-	case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
-		pc++;
-		goto loop;
-
-	// NOP
-	case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
-		goto loop;
-
-	case bad_opcode: // HLT
-		pc--;
-		if ( pc > 0xFFFF )
-		{
-			// handle wrap-around (assumes caller has put page of HLT at 0x10000)
-			pc &= 0xFFFF;
-			goto loop;
-		}
-	case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
-	case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2:
-		goto stop;
-
-// Unimplemented
-
-	case 0xFF: // force 256-entry jump table for optimization purposes
-		c |= 1;
-	default:
-		check( (unsigned) opcode <= 0xFF );
-		// skip over proper number of bytes
-		static unsigned char const illop_lens [8] = {
-			0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
-		};
-		fuint8 opcode = instr [-1];
-		fint16 len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
-		if ( opcode == 0x9C )
-			len = 2;
-		pc += len;
-		error_count_++;
-
-		if ( (opcode >> 4) == 0x0B )
-		{
-			if ( opcode == 0xB3 )
-				data = READ_LOW( data );
-			if ( opcode != 0xB7 )
-				HANDLE_PAGE_CROSSING( data + y );
-		}
-		goto loop;
-	}
-	assert( false );
-
-	int result_;
-handle_brk:
-	pc++;
-	result_ = 4;
-
-interrupt:
-	{
-		s_time += 7;
-
-		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
-		WRITE_LOW( 0x100 | (sp - 2), pc );
-		pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
-		sp = (sp - 3) | 0x100;
-		fuint8 temp;
-		CALC_STATUS( temp );
-		temp |= st_r;
-		if ( result_ )
-			temp |= st_b; // TODO: incorrectly sets B flag for IRQ
-		WRITE_LOW( sp, temp );
-
-		this->r.status = status |= st_i;
-		blargg_long delta = s.base - end_time_;
-		if ( delta >= 0 ) goto loop;
-		s_time += delta;
-		s.base = end_time_;
-		goto loop;
-	}
-
-out_of_time:
-	pc--;
-	FLUSH_TIME();
-	CPU_DONE( this, TIME, result_ );
-	CACHE_TIME();
-	if ( result_ >= 0 )
-		goto interrupt;
-	if ( s_time < 0 )
-		goto loop;
-
-stop:
-
-	s.time = s_time;
-
-	r.pc = pc;
-	r.sp = GET_SP();
-	r.a = a;
-	r.x = x;
-	r.y = y;
-
-	{
-		fuint8 temp;
-		CALC_STATUS( temp );
-		r.status = temp;
-	}
-
-	this->state_ = s;
-	this->state = &this->state_;
-
-	return s_time < 0;
-}
-
diff --git a/src/console/Nes_Fme7_Apu.cc b/src/console/Nes_Fme7_Apu.cc
new file mode 100644
index 000000000000..84030f865da4
--- /dev/null
+++ b/src/console/Nes_Fme7_Apu.cc
@@ -0,0 +1,121 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Nes_Fme7_Apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Nes_Fme7_Apu::reset()
+{
+	last_time = 0;
+
+	for ( int i = 0; i < osc_count; i++ )
+		oscs [i].last_amp = 0;
+
+	fme7_apu_state_t* state = this;
+	memset( state, 0, sizeof *state );
+}
+
+unsigned char const Nes_Fme7_Apu::amp_table [16] =
+{
+	#define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
+	ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
+	ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
+	ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
+	ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
+	#undef ENTRY
+};
+
+void Nes_Fme7_Apu::run_until( blip_time_t end_time )
+{
+	require( end_time >= last_time );
+
+	for ( int index = 0; index < osc_count; index++ )
+	{
+		int mode = regs [7] >> index;
+		int vol_mode = regs [010 + index];
+		int volume = amp_table [vol_mode & 0x0F];
+
+		Blip_Buffer* const osc_output = oscs [index].output;
+		if ( !osc_output )
+			continue;
+		osc_output->set_modified();
+
+		// check for unsupported mode
+		#ifndef NDEBUG
+			if ( (mode & 011) <= 001 && vol_mode & 0x1F )
+				debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
+						mode, vol_mode & 0x1F );
+		#endif
+
+		if ( (mode & 001) | (vol_mode & 0x10) )
+			volume = 0; // noise and envelope aren't supported
+
+		// period
+		int const period_factor = 16;
+		unsigned period = (regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
+				regs [index * 2] * period_factor;
+		if ( period < 50 ) // around 22 kHz
+		{
+			volume = 0;
+			if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
+				period = period_factor;
+		}
+
+		// current amplitude
+		int amp = volume;
+		if ( !phases [index] )
+			amp = 0;
+		{
+			int delta = amp - oscs [index].last_amp;
+			if ( delta )
+			{
+				oscs [index].last_amp = amp;
+				synth.offset( last_time, delta, osc_output );
+			}
+		}
+
+		blip_time_t time = last_time + delays [index];
+		if ( time < end_time )
+		{
+			int delta = amp * 2 - volume;
+			if ( volume )
+			{
+				do
+				{
+					delta = -delta;
+					synth.offset_inline( time, delta, osc_output );
+					time += period;
+				}
+				while ( time < end_time );
+
+				oscs [index].last_amp = (delta + volume) >> 1;
+				phases [index] = (delta > 0);
+			}
+			else
+			{
+				// maintain phase when silent
+				int count = (end_time - time + period - 1) / period;
+				phases [index] ^= count & 1;
+				time += (blargg_long) count * period;
+			}
+		}
+
+		delays [index] = time - end_time;
+	}
+
+	last_time = end_time;
+}
+
diff --git a/src/console/Nes_Fme7_Apu.cxx b/src/console/Nes_Fme7_Apu.cxx
deleted file mode 100644
index 84030f865da4..000000000000
--- a/src/console/Nes_Fme7_Apu.cxx
+++ /dev/null
@@ -1,121 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nes_Fme7_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Nes_Fme7_Apu::reset()
-{
-	last_time = 0;
-
-	for ( int i = 0; i < osc_count; i++ )
-		oscs [i].last_amp = 0;
-
-	fme7_apu_state_t* state = this;
-	memset( state, 0, sizeof *state );
-}
-
-unsigned char const Nes_Fme7_Apu::amp_table [16] =
-{
-	#define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
-	ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
-	ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
-	ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
-	ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
-	#undef ENTRY
-};
-
-void Nes_Fme7_Apu::run_until( blip_time_t end_time )
-{
-	require( end_time >= last_time );
-
-	for ( int index = 0; index < osc_count; index++ )
-	{
-		int mode = regs [7] >> index;
-		int vol_mode = regs [010 + index];
-		int volume = amp_table [vol_mode & 0x0F];
-
-		Blip_Buffer* const osc_output = oscs [index].output;
-		if ( !osc_output )
-			continue;
-		osc_output->set_modified();
-
-		// check for unsupported mode
-		#ifndef NDEBUG
-			if ( (mode & 011) <= 001 && vol_mode & 0x1F )
-				debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
-						mode, vol_mode & 0x1F );
-		#endif
-
-		if ( (mode & 001) | (vol_mode & 0x10) )
-			volume = 0; // noise and envelope aren't supported
-
-		// period
-		int const period_factor = 16;
-		unsigned period = (regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
-				regs [index * 2] * period_factor;
-		if ( period < 50 ) // around 22 kHz
-		{
-			volume = 0;
-			if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
-				period = period_factor;
-		}
-
-		// current amplitude
-		int amp = volume;
-		if ( !phases [index] )
-			amp = 0;
-		{
-			int delta = amp - oscs [index].last_amp;
-			if ( delta )
-			{
-				oscs [index].last_amp = amp;
-				synth.offset( last_time, delta, osc_output );
-			}
-		}
-
-		blip_time_t time = last_time + delays [index];
-		if ( time < end_time )
-		{
-			int delta = amp * 2 - volume;
-			if ( volume )
-			{
-				do
-				{
-					delta = -delta;
-					synth.offset_inline( time, delta, osc_output );
-					time += period;
-				}
-				while ( time < end_time );
-
-				oscs [index].last_amp = (delta + volume) >> 1;
-				phases [index] = (delta > 0);
-			}
-			else
-			{
-				// maintain phase when silent
-				int count = (end_time - time + period - 1) / period;
-				phases [index] ^= count & 1;
-				time += (blargg_long) count * period;
-			}
-		}
-
-		delays [index] = time - end_time;
-	}
-
-	last_time = end_time;
-}
-
diff --git a/src/console/Nes_Fme7_Apu.h b/src/console/Nes_Fme7_Apu.h
index 4b2d6fba8146..4df44acb4f25 100644
--- a/src/console/Nes_Fme7_Apu.h
+++ b/src/console/Nes_Fme7_Apu.h
@@ -85,7 +85,7 @@ inline void Nes_Fme7_Apu::output( Blip_Buffer* buf )
 
 inline Nes_Fme7_Apu::Nes_Fme7_Apu()
 {
-	output( NULL );
+	output( nullptr );
 	volume( 1.0 );
 	reset();
 }
diff --git a/src/console/Nes_Namco_Apu.cc b/src/console/Nes_Namco_Apu.cc
new file mode 100644
index 000000000000..e382dfb13054
--- /dev/null
+++ b/src/console/Nes_Namco_Apu.cc
@@ -0,0 +1,145 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "Nes_Namco_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Nes_Namco_Apu::Nes_Namco_Apu()
+{
+	output( nullptr );
+	volume( 1.0 );
+	reset();
+}
+
+void Nes_Namco_Apu::reset()
+{
+	last_time = 0;
+	addr_reg = 0;
+
+	int i;
+	for ( i = 0; i < reg_count; i++ )
+		reg [i] = 0;
+
+	for ( i = 0; i < osc_count; i++ )
+	{
+		Namco_Osc& osc = oscs [i];
+		osc.delay = 0;
+		osc.last_amp = 0;
+		osc.wave_pos = 0;
+	}
+}
+
+void Nes_Namco_Apu::output( Blip_Buffer* buf )
+{
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, buf );
+}
+
+/*
+void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
+{
+	reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
+
+	static const char hex [17] = "0123456789ABCDEF";
+	int i;
+	for ( i = 0; i < reg_count; i++ )
+		reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
+
+	for ( i = 0; i < osc_count; i++ )
+	{
+		reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
+		reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
+	}
+}
+*/
+
+void Nes_Namco_Apu::end_frame( blip_time_t time )
+{
+	if ( time > last_time )
+		run_until( time );
+
+	assert( last_time >= time );
+	last_time -= time;
+}
+
+void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
+{
+	int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
+	for ( int i = osc_count - active_oscs; i < osc_count; i++ )
+	{
+		Namco_Osc& osc = oscs [i];
+		Blip_Buffer* output = osc.output;
+		if ( !output )
+			continue;
+		output->set_modified();
+
+		blip_resampled_time_t time =
+				output->resampled_time( last_time ) + osc.delay;
+		blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
+		osc.delay = 0;
+		if ( time < end_time )
+		{
+			const uint8_t* osc_reg = &reg [i * 8 + 0x40];
+			if ( !(osc_reg [4] & 0xE0) )
+				continue;
+
+			int volume = osc_reg [7] & 15;
+			if ( !volume )
+				continue;
+
+			blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
+			if ( freq < 64 * active_oscs )
+				continue; // prevent low frequencies from excessively delaying freq changes
+			blip_resampled_time_t period =
+					output->resampled_duration( 983040 ) / freq * active_oscs;
+
+			int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
+			if ( !wave_size )
+				continue;
+
+			int last_amp = osc.last_amp;
+			int wave_pos = osc.wave_pos;
+
+			do
+			{
+				// read wave sample
+				int addr = wave_pos + osc_reg [6];
+				int sample = reg [addr >> 1] >> (addr << 2 & 4);
+				wave_pos++;
+				sample = (sample & 15) * volume;
+
+				// output impulse if amplitude changed
+				int delta = sample - last_amp;
+				if ( delta )
+				{
+					last_amp = sample;
+					synth.offset_resampled( time, delta, output );
+				}
+
+				// next sample
+				time += period;
+				if ( wave_pos >= wave_size )
+					wave_pos = 0;
+			}
+			while ( time < end_time );
+
+			osc.wave_pos = wave_pos;
+			osc.last_amp = last_amp;
+		}
+		osc.delay = time - end_time;
+	}
+
+	last_time = nes_end_time;
+}
+
diff --git a/src/console/Nes_Namco_Apu.cxx b/src/console/Nes_Namco_Apu.cxx
deleted file mode 100644
index 76bdb70d31db..000000000000
--- a/src/console/Nes_Namco_Apu.cxx
+++ /dev/null
@@ -1,145 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Namco_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Namco_Apu::Nes_Namco_Apu()
-{
-	output( NULL );
-	volume( 1.0 );
-	reset();
-}
-
-void Nes_Namco_Apu::reset()
-{
-	last_time = 0;
-	addr_reg = 0;
-
-	int i;
-	for ( i = 0; i < reg_count; i++ )
-		reg [i] = 0;
-
-	for ( i = 0; i < osc_count; i++ )
-	{
-		Namco_Osc& osc = oscs [i];
-		osc.delay = 0;
-		osc.last_amp = 0;
-		osc.wave_pos = 0;
-	}
-}
-
-void Nes_Namco_Apu::output( Blip_Buffer* buf )
-{
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, buf );
-}
-
-/*
-void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
-{
-	reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
-
-	static const char hex [17] = "0123456789ABCDEF";
-	int i;
-	for ( i = 0; i < reg_count; i++ )
-		reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
-
-	for ( i = 0; i < osc_count; i++ )
-	{
-		reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
-		reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
-	}
-}
-*/
-
-void Nes_Namco_Apu::end_frame( blip_time_t time )
-{
-	if ( time > last_time )
-		run_until( time );
-
-	assert( last_time >= time );
-	last_time -= time;
-}
-
-void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
-{
-	int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
-	for ( int i = osc_count - active_oscs; i < osc_count; i++ )
-	{
-		Namco_Osc& osc = oscs [i];
-		Blip_Buffer* output = osc.output;
-		if ( !output )
-			continue;
-		output->set_modified();
-
-		blip_resampled_time_t time =
-				output->resampled_time( last_time ) + osc.delay;
-		blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
-		osc.delay = 0;
-		if ( time < end_time )
-		{
-			const uint8_t* osc_reg = &reg [i * 8 + 0x40];
-			if ( !(osc_reg [4] & 0xE0) )
-				continue;
-
-			int volume = osc_reg [7] & 15;
-			if ( !volume )
-				continue;
-
-			blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
-			if ( freq < 64 * active_oscs )
-				continue; // prevent low frequencies from excessively delaying freq changes
-			blip_resampled_time_t period =
-					output->resampled_duration( 983040 ) / freq * active_oscs;
-
-			int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
-			if ( !wave_size )
-				continue;
-
-			int last_amp = osc.last_amp;
-			int wave_pos = osc.wave_pos;
-
-			do
-			{
-				// read wave sample
-				int addr = wave_pos + osc_reg [6];
-				int sample = reg [addr >> 1] >> (addr << 2 & 4);
-				wave_pos++;
-				sample = (sample & 15) * volume;
-
-				// output impulse if amplitude changed
-				int delta = sample - last_amp;
-				if ( delta )
-				{
-					last_amp = sample;
-					synth.offset_resampled( time, delta, output );
-				}
-
-				// next sample
-				time += period;
-				if ( wave_pos >= wave_size )
-					wave_pos = 0;
-			}
-			while ( time < end_time );
-
-			osc.wave_pos = wave_pos;
-			osc.last_amp = last_amp;
-		}
-		osc.delay = time - end_time;
-	}
-
-	last_time = nes_end_time;
-}
-
diff --git a/src/console/Nes_Oscs.cc b/src/console/Nes_Oscs.cc
new file mode 100644
index 000000000000..5ab7d084a2bd
--- /dev/null
+++ b/src/console/Nes_Oscs.cc
@@ -0,0 +1,551 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "Nes_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Nes_Osc
+
+void Nes_Osc::clock_length( int halt_mask )
+{
+	if ( length_counter && !(regs [0] & halt_mask) )
+		length_counter--;
+}
+
+void Nes_Envelope::clock_envelope()
+{
+	int period = regs [0] & 15;
+	if ( reg_written [3] ) {
+		reg_written [3] = false;
+		env_delay = period;
+		envelope = 15;
+	}
+	else if ( --env_delay < 0 ) {
+		env_delay = period;
+		if ( envelope | (regs [0] & 0x20) )
+			envelope = (envelope - 1) & 15;
+	}
+}
+
+int Nes_Envelope::volume() const
+{
+	return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
+}
+
+// Nes_Square
+
+void Nes_Square::clock_sweep( int negative_adjust )
+{
+	int sweep = regs [1];
+
+	if ( --sweep_delay < 0 )
+	{
+		reg_written [1] = true;
+
+		int period = this->period();
+		int shift = sweep & shift_mask;
+		if ( shift && (sweep & 0x80) && period >= 8 )
+		{
+			int offset = period >> shift;
+
+			if ( sweep & negate_flag )
+				offset = negative_adjust - offset;
+
+			if ( period + offset < 0x800 )
+			{
+				period += offset;
+				// rewrite period
+				regs [2] = period & 0xFF;
+				regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
+			}
+		}
+	}
+
+	if ( reg_written [1] ) {
+		reg_written [1] = false;
+		sweep_delay = (sweep >> 4) & 7;
+	}
+}
+
+// TODO: clean up
+inline nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_time,
+		nes_time_t timer_period )
+{
+	nes_time_t remain = end_time - time;
+	if ( remain > 0 )
+	{
+		int count = (remain + timer_period - 1) / timer_period;
+		phase = (phase + count) & (phase_range - 1);
+		time += (blargg_long) count * timer_period;
+	}
+	return time;
+}
+
+void Nes_Square::run( nes_time_t time, nes_time_t end_time )
+{
+	const int period = this->period();
+	const int timer_period = (period + 1) * 2;
+
+	if ( !output )
+	{
+		delay = maintain_phase( time + delay, end_time, timer_period ) - end_time;
+		return;
+	}
+
+	output->set_modified();
+
+	int offset = period >> (regs [1] & shift_mask);
+	if ( regs [1] & negate_flag )
+		offset = 0;
+
+	const int volume = this->volume();
+	if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
+	{
+		if ( last_amp ) {
+			synth.offset( time, -last_amp, output );
+			last_amp = 0;
+		}
+
+		time += delay;
+		time = maintain_phase( time, end_time, timer_period );
+	}
+	else
+	{
+		// handle duty select
+		int duty_select = (regs [0] >> 6) & 3;
+		int duty = 1 << duty_select; // 1, 2, 4, 2
+		int amp = 0;
+		if ( duty_select == 3 ) {
+			duty = 2; // negated 25%
+			amp = volume;
+		}
+		if ( phase < duty )
+			amp ^= volume;
+
+		{
+			int delta = update_amp( amp );
+			if ( delta )
+				synth.offset( time, delta, output );
+		}
+
+		time += delay;
+		if ( time < end_time )
+		{
+			Blip_Buffer* const output = this->output;
+			const Synth& synth = this->synth;
+			int delta = amp * 2 - volume;
+			int phase = this->phase;
+
+			do {
+				phase = (phase + 1) & (phase_range - 1);
+				if ( phase == 0 || phase == duty ) {
+					delta = -delta;
+					synth.offset_inline( time, delta, output );
+				}
+				time += timer_period;
+			}
+			while ( time < end_time );
+
+			last_amp = (delta + volume) >> 1;
+			this->phase = phase;
+		}
+	}
+
+	delay = time - end_time;
+}
+
+// Nes_Triangle
+
+void Nes_Triangle::clock_linear_counter()
+{
+	if ( reg_written [3] )
+		linear_counter = regs [0] & 0x7F;
+	else if ( linear_counter )
+		linear_counter--;
+
+	if ( !(regs [0] & 0x80) )
+		reg_written [3] = false;
+}
+
+inline int Nes_Triangle::calc_amp() const
+{
+	int amp = phase_range - phase;
+	if ( amp < 0 )
+		amp = phase - (phase_range + 1);
+	return amp;
+}
+
+// TODO: clean up
+inline nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_time,
+		nes_time_t timer_period )
+{
+	nes_time_t remain = end_time - time;
+	if ( remain > 0 )
+	{
+		int count = (remain + timer_period - 1) / timer_period;
+		phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
+		phase++;
+		time += (blargg_long) count * timer_period;
+	}
+	return time;
+}
+
+void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
+{
+	const int timer_period = period() + 1;
+	if ( !output )
+	{
+		time += delay;
+		delay = 0;
+		if ( length_counter && linear_counter && timer_period >= 3 )
+			delay = maintain_phase( time, end_time, timer_period ) - end_time;
+		return;
+	}
+
+	output->set_modified();
+
+	// to do: track phase when period < 3
+	// to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
+
+	int delta = update_amp( calc_amp() );
+	if ( delta )
+		synth.offset( time, delta, output );
+
+	time += delay;
+	if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
+	{
+		time = end_time;
+	}
+	else if ( time < end_time )
+	{
+		Blip_Buffer* const output = this->output;
+
+		int phase = this->phase;
+		int volume = 1;
+		if ( phase > phase_range ) {
+			phase -= phase_range;
+			volume = -volume;
+		}
+
+		do {
+			if ( --phase == 0 ) {
+				phase = phase_range;
+				volume = -volume;
+			}
+			else {
+				synth.offset_inline( time, volume, output );
+			}
+
+			time += timer_period;
+		}
+		while ( time < end_time );
+
+		if ( volume < 0 )
+			phase += phase_range;
+		this->phase = phase;
+		last_amp = calc_amp();
+ 	}
+	delay = time - end_time;
+}
+
+// Nes_Dmc
+
+void Nes_Dmc::reset()
+{
+	address = 0;
+	dac = 0;
+	buf = 0;
+	bits_remain = 1;
+	bits = 0;
+	buf_full = false;
+	silence = true;
+	next_irq = Nes_Apu::no_irq;
+	irq_flag = false;
+	irq_enabled = false;
+
+	Nes_Osc::reset();
+	period = 0x1AC;
+}
+
+void Nes_Dmc::recalc_irq()
+{
+	nes_time_t irq = Nes_Apu::no_irq;
+	if ( irq_enabled && length_counter )
+		irq = apu->last_dmc_time + delay +
+				((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t (period) + 1;
+	if ( irq != next_irq ) {
+		next_irq = irq;
+		apu->irq_changed();
+	}
+}
+
+int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
+{
+	if ( last_read )
+		*last_read = time;
+
+	if ( length_counter == 0 )
+		return 0; // not reading
+
+	nes_time_t first_read = next_read_time();
+	nes_time_t avail = time - first_read;
+	if ( avail <= 0 )
+		return 0;
+
+	int count = (avail - 1) / (period * 8) + 1;
+	if ( !(regs [0] & loop_flag) && count > length_counter )
+		count = length_counter;
+
+	if ( last_read )
+	{
+		*last_read = first_read + (count - 1) * (period * 8) + 1;
+		check( *last_read <= time );
+		check( count == count_reads( *last_read, nullptr ) );
+		check( count - 1 == count_reads( *last_read - 1, nullptr ) );
+	}
+
+	return count;
+}
+
+static short const dmc_period_table [2] [16] = {
+	{428, 380, 340, 320, 286, 254, 226, 214, // NTSC
+	190, 160, 142, 128, 106,  84,  72,  54},
+
+	{398, 354, 316, 298, 276, 236, 210, 198, // PAL
+	176, 148, 132, 118,  98,  78,  66,  50}
+};
+
+inline void Nes_Dmc::reload_sample()
+{
+	address = 0x4000 + regs [2] * 0x40;
+	length_counter = regs [3] * 0x10 + 1;
+}
+
+static byte const dac_table [128] =
+{
+	 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
+	15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
+	27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
+	39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
+	50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
+	59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
+	68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
+	76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
+};
+
+void Nes_Dmc::write_register( int addr, int data )
+{
+	if ( addr == 0 )
+	{
+		period = dmc_period_table [pal_mode] [data & 15];
+		irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
+		irq_flag &= irq_enabled;
+		recalc_irq();
+	}
+	else if ( addr == 1 )
+	{
+		int old_dac = dac;
+		dac = data & 0x7F;
+
+		// adjust last_amp so that "pop" amplitude will be properly non-linear
+		// with respect to change in dac
+		int faked_nonlinear = dac - (dac_table [dac] - dac_table [old_dac]);
+		if ( !nonlinear )
+			last_amp = faked_nonlinear;
+	}
+}
+
+void Nes_Dmc::start()
+{
+	reload_sample();
+	fill_buffer();
+	recalc_irq();
+}
+
+void Nes_Dmc::fill_buffer()
+{
+	if ( !buf_full && length_counter )
+	{
+		require( prg_reader ); // prg_reader must be set
+		buf = prg_reader( prg_reader_data, 0x8000u + address );
+		address = (address + 1) & 0x7FFF;
+		buf_full = true;
+		if ( --length_counter == 0 )
+		{
+			if ( regs [0] & loop_flag ) {
+				reload_sample();
+			}
+			else {
+				apu->osc_enables &= ~0x10;
+				irq_flag = irq_enabled;
+				next_irq = Nes_Apu::no_irq;
+				apu->irq_changed();
+			}
+		}
+	}
+}
+
+void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
+{
+	int delta = update_amp( dac );
+	if ( !output )
+	{
+		silence = true;
+	}
+	else
+	{
+		output->set_modified();
+		if ( delta )
+			synth.offset( time, delta, output );
+	}
+
+	time += delay;
+	if ( time < end_time )
+	{
+		int bits_remain = this->bits_remain;
+		if ( silence && !buf_full )
+		{
+			int count = (end_time - time + period - 1) / period;
+			bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
+			time += count * period;
+		}
+		else
+		{
+			Blip_Buffer* const output = this->output;
+			const int period = this->period;
+			int bits = this->bits;
+			int dac = this->dac;
+
+			do
+			{
+				if ( !silence )
+				{
+					int step = (bits & 1) * 4 - 2;
+					bits >>= 1;
+					if ( unsigned (dac + step) <= 0x7F ) {
+						dac += step;
+						synth.offset_inline( time, step, output );
+					}
+				}
+
+				time += period;
+
+				if ( --bits_remain == 0 )
+				{
+					bits_remain = 8;
+					if ( !buf_full ) {
+						silence = true;
+					}
+					else {
+						silence = false;
+						bits = buf;
+						buf_full = false;
+						if ( !output )
+							silence = true;
+						fill_buffer();
+					}
+				}
+			}
+			while ( time < end_time );
+
+			this->dac = dac;
+			this->last_amp = dac;
+			this->bits = bits;
+		}
+		this->bits_remain = bits_remain;
+	}
+	delay = time - end_time;
+}
+
+// Nes_Noise
+
+static short const noise_period_table [16] = {
+	0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
+	0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
+};
+
+void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
+{
+	int period = noise_period_table [regs [2] & 15];
+
+	if ( !output )
+	{
+		// TODO: clean up
+		time += delay;
+		delay = time + (end_time - time + period - 1) / period * period - end_time;
+		return;
+	}
+
+	output->set_modified();
+
+	const int volume = this->volume();
+	int amp = (noise & 1) ? volume : 0;
+	{
+		int delta = update_amp( amp );
+		if ( delta )
+			synth.offset( time, delta, output );
+	}
+
+	time += delay;
+	if ( time < end_time )
+	{
+		const int mode_flag = 0x80;
+
+		if ( !volume )
+		{
+			// round to next multiple of period
+			time += (end_time - time + period - 1) / period * period;
+
+			// approximate noise cycling while muted, by shuffling up noise register
+			// to do: precise muted noise cycling?
+			if ( !(regs [2] & mode_flag) ) {
+				int feedback = (noise << 13) ^ (noise << 14);
+				noise = (feedback & 0x4000) | (noise >> 1);
+			}
+		}
+		else
+		{
+			Blip_Buffer* const output = this->output;
+
+			// using resampled time avoids conversion in synth.offset()
+			blip_resampled_time_t rperiod = output->resampled_duration( period );
+			blip_resampled_time_t rtime = output->resampled_time( time );
+
+			int noise = this->noise;
+			int delta = amp * 2 - volume;
+			const int tap = (regs [2] & mode_flag ? 8 : 13);
+
+			do {
+				int feedback = (noise << tap) ^ (noise << 14);
+				time += period;
+
+				if ( (noise + 1) & 2 ) {
+					// bits 0 and 1 of noise differ
+					delta = -delta;
+					synth.offset_resampled( rtime, delta, output );
+				}
+
+				rtime += rperiod;
+				noise = (feedback & 0x4000) | (noise >> 1);
+			}
+			while ( time < end_time );
+
+			last_amp = (delta + volume) >> 1;
+			this->noise = noise;
+		}
+	}
+
+	delay = time - end_time;
+}
+
diff --git a/src/console/Nes_Oscs.cxx b/src/console/Nes_Oscs.cxx
deleted file mode 100644
index f09a0e183cdc..000000000000
--- a/src/console/Nes_Oscs.cxx
+++ /dev/null
@@ -1,551 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Nes_Osc
-
-void Nes_Osc::clock_length( int halt_mask )
-{
-	if ( length_counter && !(regs [0] & halt_mask) )
-		length_counter--;
-}
-
-void Nes_Envelope::clock_envelope()
-{
-	int period = regs [0] & 15;
-	if ( reg_written [3] ) {
-		reg_written [3] = false;
-		env_delay = period;
-		envelope = 15;
-	}
-	else if ( --env_delay < 0 ) {
-		env_delay = period;
-		if ( envelope | (regs [0] & 0x20) )
-			envelope = (envelope - 1) & 15;
-	}
-}
-
-int Nes_Envelope::volume() const
-{
-	return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
-}
-
-// Nes_Square
-
-void Nes_Square::clock_sweep( int negative_adjust )
-{
-	int sweep = regs [1];
-
-	if ( --sweep_delay < 0 )
-	{
-		reg_written [1] = true;
-
-		int period = this->period();
-		int shift = sweep & shift_mask;
-		if ( shift && (sweep & 0x80) && period >= 8 )
-		{
-			int offset = period >> shift;
-
-			if ( sweep & negate_flag )
-				offset = negative_adjust - offset;
-
-			if ( period + offset < 0x800 )
-			{
-				period += offset;
-				// rewrite period
-				regs [2] = period & 0xFF;
-				regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
-			}
-		}
-	}
-
-	if ( reg_written [1] ) {
-		reg_written [1] = false;
-		sweep_delay = (sweep >> 4) & 7;
-	}
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_time,
-		nes_time_t timer_period )
-{
-	nes_time_t remain = end_time - time;
-	if ( remain > 0 )
-	{
-		int count = (remain + timer_period - 1) / timer_period;
-		phase = (phase + count) & (phase_range - 1);
-		time += (blargg_long) count * timer_period;
-	}
-	return time;
-}
-
-void Nes_Square::run( nes_time_t time, nes_time_t end_time )
-{
-	const int period = this->period();
-	const int timer_period = (period + 1) * 2;
-
-	if ( !output )
-	{
-		delay = maintain_phase( time + delay, end_time, timer_period ) - end_time;
-		return;
-	}
-
-	output->set_modified();
-
-	int offset = period >> (regs [1] & shift_mask);
-	if ( regs [1] & negate_flag )
-		offset = 0;
-
-	const int volume = this->volume();
-	if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
-	{
-		if ( last_amp ) {
-			synth.offset( time, -last_amp, output );
-			last_amp = 0;
-		}
-
-		time += delay;
-		time = maintain_phase( time, end_time, timer_period );
-	}
-	else
-	{
-		// handle duty select
-		int duty_select = (regs [0] >> 6) & 3;
-		int duty = 1 << duty_select; // 1, 2, 4, 2
-		int amp = 0;
-		if ( duty_select == 3 ) {
-			duty = 2; // negated 25%
-			amp = volume;
-		}
-		if ( phase < duty )
-			amp ^= volume;
-
-		{
-			int delta = update_amp( amp );
-			if ( delta )
-				synth.offset( time, delta, output );
-		}
-
-		time += delay;
-		if ( time < end_time )
-		{
-			Blip_Buffer* const output = this->output;
-			const Synth& synth = this->synth;
-			int delta = amp * 2 - volume;
-			int phase = this->phase;
-
-			do {
-				phase = (phase + 1) & (phase_range - 1);
-				if ( phase == 0 || phase == duty ) {
-					delta = -delta;
-					synth.offset_inline( time, delta, output );
-				}
-				time += timer_period;
-			}
-			while ( time < end_time );
-
-			last_amp = (delta + volume) >> 1;
-			this->phase = phase;
-		}
-	}
-
-	delay = time - end_time;
-}
-
-// Nes_Triangle
-
-void Nes_Triangle::clock_linear_counter()
-{
-	if ( reg_written [3] )
-		linear_counter = regs [0] & 0x7F;
-	else if ( linear_counter )
-		linear_counter--;
-
-	if ( !(regs [0] & 0x80) )
-		reg_written [3] = false;
-}
-
-inline int Nes_Triangle::calc_amp() const
-{
-	int amp = phase_range - phase;
-	if ( amp < 0 )
-		amp = phase - (phase_range + 1);
-	return amp;
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_time,
-		nes_time_t timer_period )
-{
-	nes_time_t remain = end_time - time;
-	if ( remain > 0 )
-	{
-		int count = (remain + timer_period - 1) / timer_period;
-		phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
-		phase++;
-		time += (blargg_long) count * timer_period;
-	}
-	return time;
-}
-
-void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
-{
-	const int timer_period = period() + 1;
-	if ( !output )
-	{
-		time += delay;
-		delay = 0;
-		if ( length_counter && linear_counter && timer_period >= 3 )
-			delay = maintain_phase( time, end_time, timer_period ) - end_time;
-		return;
-	}
-
-	output->set_modified();
-
-	// to do: track phase when period < 3
-	// to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
-
-	int delta = update_amp( calc_amp() );
-	if ( delta )
-		synth.offset( time, delta, output );
-
-	time += delay;
-	if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
-	{
-		time = end_time;
-	}
-	else if ( time < end_time )
-	{
-		Blip_Buffer* const output = this->output;
-
-		int phase = this->phase;
-		int volume = 1;
-		if ( phase > phase_range ) {
-			phase -= phase_range;
-			volume = -volume;
-		}
-
-		do {
-			if ( --phase == 0 ) {
-				phase = phase_range;
-				volume = -volume;
-			}
-			else {
-				synth.offset_inline( time, volume, output );
-			}
-
-			time += timer_period;
-		}
-		while ( time < end_time );
-
-		if ( volume < 0 )
-			phase += phase_range;
-		this->phase = phase;
-		last_amp = calc_amp();
- 	}
-	delay = time - end_time;
-}
-
-// Nes_Dmc
-
-void Nes_Dmc::reset()
-{
-	address = 0;
-	dac = 0;
-	buf = 0;
-	bits_remain = 1;
-	bits = 0;
-	buf_full = false;
-	silence = true;
-	next_irq = Nes_Apu::no_irq;
-	irq_flag = false;
-	irq_enabled = false;
-
-	Nes_Osc::reset();
-	period = 0x1AC;
-}
-
-void Nes_Dmc::recalc_irq()
-{
-	nes_time_t irq = Nes_Apu::no_irq;
-	if ( irq_enabled && length_counter )
-		irq = apu->last_dmc_time + delay +
-				((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t (period) + 1;
-	if ( irq != next_irq ) {
-		next_irq = irq;
-		apu->irq_changed();
-	}
-}
-
-int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
-{
-	if ( last_read )
-		*last_read = time;
-
-	if ( length_counter == 0 )
-		return 0; // not reading
-
-	nes_time_t first_read = next_read_time();
-	nes_time_t avail = time - first_read;
-	if ( avail <= 0 )
-		return 0;
-
-	int count = (avail - 1) / (period * 8) + 1;
-	if ( !(regs [0] & loop_flag) && count > length_counter )
-		count = length_counter;
-
-	if ( last_read )
-	{
-		*last_read = first_read + (count - 1) * (period * 8) + 1;
-		check( *last_read <= time );
-		check( count == count_reads( *last_read, NULL ) );
-		check( count - 1 == count_reads( *last_read - 1, NULL ) );
-	}
-
-	return count;
-}
-
-static short const dmc_period_table [2] [16] = {
-	{428, 380, 340, 320, 286, 254, 226, 214, // NTSC
-	190, 160, 142, 128, 106,  84,  72,  54},
-
-	{398, 354, 316, 298, 276, 236, 210, 198, // PAL
-	176, 148, 132, 118,  98,  78,  66,  50}
-};
-
-inline void Nes_Dmc::reload_sample()
-{
-	address = 0x4000 + regs [2] * 0x40;
-	length_counter = regs [3] * 0x10 + 1;
-}
-
-static byte const dac_table [128] =
-{
-	 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
-	15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
-	27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
-	39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
-	50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
-	59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
-	68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
-	76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
-};
-
-void Nes_Dmc::write_register( int addr, int data )
-{
-	if ( addr == 0 )
-	{
-		period = dmc_period_table [pal_mode] [data & 15];
-		irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
-		irq_flag &= irq_enabled;
-		recalc_irq();
-	}
-	else if ( addr == 1 )
-	{
-		int old_dac = dac;
-		dac = data & 0x7F;
-
-		// adjust last_amp so that "pop" amplitude will be properly non-linear
-		// with respect to change in dac
-		int faked_nonlinear = dac - (dac_table [dac] - dac_table [old_dac]);
-		if ( !nonlinear )
-			last_amp = faked_nonlinear;
-	}
-}
-
-void Nes_Dmc::start()
-{
-	reload_sample();
-	fill_buffer();
-	recalc_irq();
-}
-
-void Nes_Dmc::fill_buffer()
-{
-	if ( !buf_full && length_counter )
-	{
-		require( prg_reader ); // prg_reader must be set
-		buf = prg_reader( prg_reader_data, 0x8000u + address );
-		address = (address + 1) & 0x7FFF;
-		buf_full = true;
-		if ( --length_counter == 0 )
-		{
-			if ( regs [0] & loop_flag ) {
-				reload_sample();
-			}
-			else {
-				apu->osc_enables &= ~0x10;
-				irq_flag = irq_enabled;
-				next_irq = Nes_Apu::no_irq;
-				apu->irq_changed();
-			}
-		}
-	}
-}
-
-void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
-{
-	int delta = update_amp( dac );
-	if ( !output )
-	{
-		silence = true;
-	}
-	else
-	{
-		output->set_modified();
-		if ( delta )
-			synth.offset( time, delta, output );
-	}
-
-	time += delay;
-	if ( time < end_time )
-	{
-		int bits_remain = this->bits_remain;
-		if ( silence && !buf_full )
-		{
-			int count = (end_time - time + period - 1) / period;
-			bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
-			time += count * period;
-		}
-		else
-		{
-			Blip_Buffer* const output = this->output;
-			const int period = this->period;
-			int bits = this->bits;
-			int dac = this->dac;
-
-			do
-			{
-				if ( !silence )
-				{
-					int step = (bits & 1) * 4 - 2;
-					bits >>= 1;
-					if ( unsigned (dac + step) <= 0x7F ) {
-						dac += step;
-						synth.offset_inline( time, step, output );
-					}
-				}
-
-				time += period;
-
-				if ( --bits_remain == 0 )
-				{
-					bits_remain = 8;
-					if ( !buf_full ) {
-						silence = true;
-					}
-					else {
-						silence = false;
-						bits = buf;
-						buf_full = false;
-						if ( !output )
-							silence = true;
-						fill_buffer();
-					}
-				}
-			}
-			while ( time < end_time );
-
-			this->dac = dac;
-			this->last_amp = dac;
-			this->bits = bits;
-		}
-		this->bits_remain = bits_remain;
-	}
-	delay = time - end_time;
-}
-
-// Nes_Noise
-
-static short const noise_period_table [16] = {
-	0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
-	0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
-};
-
-void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
-{
-	int period = noise_period_table [regs [2] & 15];
-
-	if ( !output )
-	{
-		// TODO: clean up
-		time += delay;
-		delay = time + (end_time - time + period - 1) / period * period - end_time;
-		return;
-	}
-
-	output->set_modified();
-
-	const int volume = this->volume();
-	int amp = (noise & 1) ? volume : 0;
-	{
-		int delta = update_amp( amp );
-		if ( delta )
-			synth.offset( time, delta, output );
-	}
-
-	time += delay;
-	if ( time < end_time )
-	{
-		const int mode_flag = 0x80;
-
-		if ( !volume )
-		{
-			// round to next multiple of period
-			time += (end_time - time + period - 1) / period * period;
-
-			// approximate noise cycling while muted, by shuffling up noise register
-			// to do: precise muted noise cycling?
-			if ( !(regs [2] & mode_flag) ) {
-				int feedback = (noise << 13) ^ (noise << 14);
-				noise = (feedback & 0x4000) | (noise >> 1);
-			}
-		}
-		else
-		{
-			Blip_Buffer* const output = this->output;
-
-			// using resampled time avoids conversion in synth.offset()
-			blip_resampled_time_t rperiod = output->resampled_duration( period );
-			blip_resampled_time_t rtime = output->resampled_time( time );
-
-			int noise = this->noise;
-			int delta = amp * 2 - volume;
-			const int tap = (regs [2] & mode_flag ? 8 : 13);
-
-			do {
-				int feedback = (noise << tap) ^ (noise << 14);
-				time += period;
-
-				if ( (noise + 1) & 2 ) {
-					// bits 0 and 1 of noise differ
-					delta = -delta;
-					synth.offset_resampled( rtime, delta, output );
-				}
-
-				rtime += rperiod;
-				noise = (feedback & 0x4000) | (noise >> 1);
-			}
-			while ( time < end_time );
-
-			last_amp = (delta + volume) >> 1;
-			this->noise = noise;
-		}
-	}
-
-	delay = time - end_time;
-}
-
diff --git a/src/console/Nes_Vrc6_Apu.cc b/src/console/Nes_Vrc6_Apu.cc
new file mode 100644
index 000000000000..195f60588e9a
--- /dev/null
+++ b/src/console/Nes_Vrc6_Apu.cc
@@ -0,0 +1,215 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "Nes_Vrc6_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Nes_Vrc6_Apu::Nes_Vrc6_Apu()
+{
+	output( nullptr );
+	volume( 1.0 );
+	reset();
+}
+
+void Nes_Vrc6_Apu::reset()
+{
+	last_time = 0;
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		Vrc6_Osc& osc = oscs [i];
+		for ( int j = 0; j < reg_count; j++ )
+			osc.regs [j] = 0;
+		osc.delay = 0;
+		osc.last_amp = 0;
+		osc.phase = 1;
+		osc.amp = 0;
+	}
+}
+
+void Nes_Vrc6_Apu::output( Blip_Buffer* buf )
+{
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, buf );
+}
+
+void Nes_Vrc6_Apu::run_until( blip_time_t time )
+{
+	require( time >= last_time );
+	run_square( oscs [0], time );
+	run_square( oscs [1], time );
+	run_saw( time );
+	last_time = time;
+}
+
+void Nes_Vrc6_Apu::write_osc( blip_time_t time, int osc_index, int reg, int data )
+{
+	require( (unsigned) osc_index < osc_count );
+	require( (unsigned) reg < reg_count );
+
+	run_until( time );
+	oscs [osc_index].regs [reg] = data;
+}
+
+void Nes_Vrc6_Apu::end_frame( blip_time_t time )
+{
+	if ( time > last_time )
+		run_until( time );
+
+	assert( last_time >= time );
+	last_time -= time;
+}
+
+void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const
+{
+	assert( sizeof (vrc6_apu_state_t) == 20 );
+	out->saw_amp = oscs [2].amp;
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		Vrc6_Osc const& osc = oscs [i];
+		for ( int r = 0; r < reg_count; r++ )
+			out->regs [i] [r] = osc.regs [r];
+
+		out->delays [i] = osc.delay;
+		out->phases [i] = osc.phase;
+	}
+}
+
+void Nes_Vrc6_Apu::load_state( vrc6_apu_state_t const& in )
+{
+	reset();
+	oscs [2].amp = in.saw_amp;
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		Vrc6_Osc& osc = oscs [i];
+		for ( int r = 0; r < reg_count; r++ )
+			osc.regs [r] = in.regs [i] [r];
+
+		osc.delay = in.delays [i];
+		osc.phase = in.phases [i];
+	}
+	if ( !oscs [2].phase )
+		oscs [2].phase = 1;
+}
+
+void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, blip_time_t end_time )
+{
+	Blip_Buffer* output = osc.output;
+	if ( !output )
+		return;
+	output->set_modified();
+
+	int volume = osc.regs [0] & 15;
+	if ( !(osc.regs [2] & 0x80) )
+		volume = 0;
+
+	int gate = osc.regs [0] & 0x80;
+	int duty = ((osc.regs [0] >> 4) & 7) + 1;
+	int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp;
+	blip_time_t time = last_time;
+	if ( delta )
+	{
+		osc.last_amp += delta;
+		square_synth.offset( time, delta, output );
+	}
+
+	time += osc.delay;
+	osc.delay = 0;
+	int period = osc.period();
+	if ( volume && !gate && period > 4 )
+	{
+		if ( time < end_time )
+		{
+			int phase = osc.phase;
+
+			do
+			{
+				phase++;
+				if ( phase == 16 )
+				{
+					phase = 0;
+					osc.last_amp = volume;
+					square_synth.offset( time, volume, output );
+				}
+				if ( phase == duty )
+				{
+					osc.last_amp = 0;
+					square_synth.offset( time, -volume, output );
+				}
+				time += period;
+			}
+			while ( time < end_time );
+
+			osc.phase = phase;
+		}
+		osc.delay = time - end_time;
+	}
+}
+
+void Nes_Vrc6_Apu::run_saw( blip_time_t end_time )
+{
+	Vrc6_Osc& osc = oscs [2];
+	Blip_Buffer* output = osc.output;
+	if ( !output )
+		return;
+	output->set_modified();
+
+	int amp = osc.amp;
+	int amp_step = osc.regs [0] & 0x3F;
+	blip_time_t time = last_time;
+	int last_amp = osc.last_amp;
+	if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) )
+	{
+		osc.delay = 0;
+		int delta = (amp >> 3) - last_amp;
+		last_amp = amp >> 3;
+		saw_synth.offset( time, delta, output );
+	}
+	else
+	{
+		time += osc.delay;
+		if ( time < end_time )
+		{
+			int period = osc.period() * 2;
+			int phase = osc.phase;
+
+			do
+			{
+				if ( --phase == 0 )
+				{
+					phase = 7;
+					amp = 0;
+				}
+
+				int delta = (amp >> 3) - last_amp;
+				if ( delta )
+				{
+					last_amp = amp >> 3;
+					saw_synth.offset( time, delta, output );
+				}
+
+				time += period;
+				amp = (amp + amp_step) & 0xFF;
+			}
+			while ( time < end_time );
+
+			osc.phase = phase;
+			osc.amp = amp;
+		}
+
+		osc.delay = time - end_time;
+	}
+
+	osc.last_amp = last_amp;
+}
+
diff --git a/src/console/Nes_Vrc6_Apu.cxx b/src/console/Nes_Vrc6_Apu.cxx
deleted file mode 100644
index bd689c5a1743..000000000000
--- a/src/console/Nes_Vrc6_Apu.cxx
+++ /dev/null
@@ -1,215 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Vrc6_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Vrc6_Apu::Nes_Vrc6_Apu()
-{
-	output( NULL );
-	volume( 1.0 );
-	reset();
-}
-
-void Nes_Vrc6_Apu::reset()
-{
-	last_time = 0;
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		Vrc6_Osc& osc = oscs [i];
-		for ( int j = 0; j < reg_count; j++ )
-			osc.regs [j] = 0;
-		osc.delay = 0;
-		osc.last_amp = 0;
-		osc.phase = 1;
-		osc.amp = 0;
-	}
-}
-
-void Nes_Vrc6_Apu::output( Blip_Buffer* buf )
-{
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, buf );
-}
-
-void Nes_Vrc6_Apu::run_until( blip_time_t time )
-{
-	require( time >= last_time );
-	run_square( oscs [0], time );
-	run_square( oscs [1], time );
-	run_saw( time );
-	last_time = time;
-}
-
-void Nes_Vrc6_Apu::write_osc( blip_time_t time, int osc_index, int reg, int data )
-{
-	require( (unsigned) osc_index < osc_count );
-	require( (unsigned) reg < reg_count );
-
-	run_until( time );
-	oscs [osc_index].regs [reg] = data;
-}
-
-void Nes_Vrc6_Apu::end_frame( blip_time_t time )
-{
-	if ( time > last_time )
-		run_until( time );
-
-	assert( last_time >= time );
-	last_time -= time;
-}
-
-void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const
-{
-	assert( sizeof (vrc6_apu_state_t) == 20 );
-	out->saw_amp = oscs [2].amp;
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		Vrc6_Osc const& osc = oscs [i];
-		for ( int r = 0; r < reg_count; r++ )
-			out->regs [i] [r] = osc.regs [r];
-
-		out->delays [i] = osc.delay;
-		out->phases [i] = osc.phase;
-	}
-}
-
-void Nes_Vrc6_Apu::load_state( vrc6_apu_state_t const& in )
-{
-	reset();
-	oscs [2].amp = in.saw_amp;
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		Vrc6_Osc& osc = oscs [i];
-		for ( int r = 0; r < reg_count; r++ )
-			osc.regs [r] = in.regs [i] [r];
-
-		osc.delay = in.delays [i];
-		osc.phase = in.phases [i];
-	}
-	if ( !oscs [2].phase )
-		oscs [2].phase = 1;
-}
-
-void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, blip_time_t end_time )
-{
-	Blip_Buffer* output = osc.output;
-	if ( !output )
-		return;
-	output->set_modified();
-
-	int volume = osc.regs [0] & 15;
-	if ( !(osc.regs [2] & 0x80) )
-		volume = 0;
-
-	int gate = osc.regs [0] & 0x80;
-	int duty = ((osc.regs [0] >> 4) & 7) + 1;
-	int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp;
-	blip_time_t time = last_time;
-	if ( delta )
-	{
-		osc.last_amp += delta;
-		square_synth.offset( time, delta, output );
-	}
-
-	time += osc.delay;
-	osc.delay = 0;
-	int period = osc.period();
-	if ( volume && !gate && period > 4 )
-	{
-		if ( time < end_time )
-		{
-			int phase = osc.phase;
-
-			do
-			{
-				phase++;
-				if ( phase == 16 )
-				{
-					phase = 0;
-					osc.last_amp = volume;
-					square_synth.offset( time, volume, output );
-				}
-				if ( phase == duty )
-				{
-					osc.last_amp = 0;
-					square_synth.offset( time, -volume, output );
-				}
-				time += period;
-			}
-			while ( time < end_time );
-
-			osc.phase = phase;
-		}
-		osc.delay = time - end_time;
-	}
-}
-
-void Nes_Vrc6_Apu::run_saw( blip_time_t end_time )
-{
-	Vrc6_Osc& osc = oscs [2];
-	Blip_Buffer* output = osc.output;
-	if ( !output )
-		return;
-	output->set_modified();
-
-	int amp = osc.amp;
-	int amp_step = osc.regs [0] & 0x3F;
-	blip_time_t time = last_time;
-	int last_amp = osc.last_amp;
-	if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) )
-	{
-		osc.delay = 0;
-		int delta = (amp >> 3) - last_amp;
-		last_amp = amp >> 3;
-		saw_synth.offset( time, delta, output );
-	}
-	else
-	{
-		time += osc.delay;
-		if ( time < end_time )
-		{
-			int period = osc.period() * 2;
-			int phase = osc.phase;
-
-			do
-			{
-				if ( --phase == 0 )
-				{
-					phase = 7;
-					amp = 0;
-				}
-
-				int delta = (amp >> 3) - last_amp;
-				if ( delta )
-				{
-					last_amp = amp >> 3;
-					saw_synth.offset( time, delta, output );
-				}
-
-				time += period;
-				amp = (amp + amp_step) & 0xFF;
-			}
-			while ( time < end_time );
-
-			osc.phase = phase;
-			osc.amp = amp;
-		}
-
-		osc.delay = time - end_time;
-	}
-
-	osc.last_amp = last_amp;
-}
-
diff --git a/src/console/Nsf_Emu.cc b/src/console/Nsf_Emu.cc
new file mode 100644
index 000000000000..80c9038712ad
--- /dev/null
+++ b/src/console/Nsf_Emu.cc
@@ -0,0 +1,559 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Nsf_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+#include <stdio.h>
+
+#if !NSF_EMU_APU_ONLY
+	#include "Nes_Namco_Apu.h"
+	#include "Nes_Vrc6_Apu.h"
+	#include "Nes_Fme7_Apu.h"
+#endif
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const vrc6_flag  = 0x01;
+int const namco_flag = 0x10;
+int const fme7_flag  = 0x20;
+
+long const clock_divisor = 12;
+
+Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq     = {  -1.0, 80 };
+Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80 };
+
+int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
+{
+	return *((Nsf_Emu*) emu)->cpu::get_code( addr );
+}
+
+Nsf_Emu::Nsf_Emu()
+{
+	vrc6  = 0;
+	namco = 0;
+	fme7  = 0;
+
+	set_type( gme_nsf_type );
+	set_silence_lookahead( 6 );
+	apu.dmc_reader( pcm_read, this );
+	Music_Emu::set_equalizer( nes_eq );
+	set_gain( 1.4 );
+	memset( unmapped_code, Nes_Cpu::bad_opcode, sizeof unmapped_code );
+}
+
+Nsf_Emu::~Nsf_Emu() { unload(); }
+
+void Nsf_Emu::unload()
+{
+	#if !NSF_EMU_APU_ONLY
+	{
+		delete vrc6;
+		vrc6  = 0;
+
+		delete namco;
+		namco = 0;
+
+		delete fme7;
+		fme7  = 0;
+	}
+	#endif
+
+	rom.clear();
+	Music_Emu::unload();
+}
+
+// Track info
+
+static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
+{
+	GME_COPY_FIELD( h, out, game );
+	GME_COPY_FIELD( h, out, author );
+	GME_COPY_FIELD( h, out, copyright );
+	if ( h.chip_flags )
+		Gme_File::copy_field_( out->system, "Famicom" );
+}
+
+blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
+{
+	copy_nsf_fields( header_, out );
+	return 0;
+}
+
+static blargg_err_t check_nsf_header( void const* header )
+{
+	if ( memcmp( header, "NESM\x1A", 5 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Nsf_File : Gme_Info_
+{
+	Nsf_Emu::header_t h;
+
+	Nsf_File() { set_type( gme_nsf_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		blargg_err_t err = in.read( &h, Nsf_Emu::header_size );
+		if ( err )
+			return (err == in.eof_error ? gme_wrong_file_type : err);
+
+		if ( h.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
+			set_warning( "Uses unsupported audio expansion hardware" );
+
+		set_track_count( h.track_count );
+		return check_nsf_header( &h );
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		copy_nsf_fields( h, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
+static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
+
+static gme_type_t_ const gme_nsf_type_ = { "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 };
+gme_type_t const gme_nsf_type = &gme_nsf_type_;
+
+
+// Setup
+
+void Nsf_Emu::set_tempo_( double t )
+{
+	unsigned playback_rate = GET_LE16( header_.ntsc_speed );
+	unsigned standard_rate = 0x411A;
+	clock_rate_ = 1789772.72727;
+	play_period = 262 * 341L * 4 - 2; // two fewer PPU clocks every four frames
+
+	if ( pal_only )
+	{
+		play_period   = 33247 * clock_divisor;
+		clock_rate_   = 1662607.125;
+		standard_rate = 0x4E20;
+		playback_rate = GET_LE16( header_.pal_speed );
+	}
+
+	if ( !playback_rate )
+		playback_rate = standard_rate;
+
+	if ( playback_rate != standard_rate || t != 1.0 )
+		play_period = long (playback_rate * clock_rate_ / (1000000.0 / clock_divisor * t));
+
+	apu.set_tempo( t );
+}
+
+blargg_err_t Nsf_Emu::init_sound()
+{
+	if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
+		set_warning( "Uses unsupported audio expansion hardware" );
+
+	{
+		#define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC"
+
+		int const count = Nes_Apu::osc_count;
+		static const char* const apu_names [count] = { APU_NAMES };
+		set_voice_count( count );
+		set_voice_names( apu_names );
+
+	}
+
+	static int const types [] = {
+		wave_type  | 1, wave_type  | 2, wave_type | 0,
+		noise_type | 0, mixed_type | 1,
+		wave_type  | 3, wave_type  | 4, wave_type | 5,
+		wave_type  | 6, wave_type  | 7, wave_type | 8, wave_type | 9,
+		wave_type  |10, wave_type  |11, wave_type |12, wave_type |13
+	};
+	set_voice_types( types ); // common to all sound chip configurations
+
+	double adjusted_gain = gain();
+
+	#if NSF_EMU_APU_ONLY
+	{
+		if ( header_.chip_flags )
+			set_warning( "Uses unsupported audio expansion hardware" );
+	}
+	#else
+	{
+		if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) )
+			set_voice_count( Nes_Apu::osc_count + 3 );
+
+		if ( header_.chip_flags & namco_flag )
+		{
+			namco = BLARGG_NEW Nes_Namco_Apu;
+			CHECK_ALLOC( namco );
+			adjusted_gain *= 0.75;
+
+			int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count;
+			static const char* const names [count] = {
+				APU_NAMES,
+				"Wave 1", "Wave 2", "Wave 3", "Wave 4",
+				"Wave 5", "Wave 6", "Wave 7", "Wave 8"
+			};
+			set_voice_count( count );
+			set_voice_names( names );
+		}
+
+		if ( header_.chip_flags & vrc6_flag )
+		{
+			vrc6 = BLARGG_NEW Nes_Vrc6_Apu;
+			CHECK_ALLOC( vrc6 );
+			adjusted_gain *= 0.75;
+
+			{
+				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count;
+				static const char* const names [count] = {
+					APU_NAMES,
+					"Saw Wave", "Square 3", "Square 4"
+				};
+				set_voice_count( count );
+				set_voice_names( names );
+			}
+
+			if ( header_.chip_flags & namco_flag )
+			{
+				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count +
+						Nes_Namco_Apu::osc_count;
+				static const char* const names [count] = {
+					APU_NAMES,
+					"Saw Wave", "Square 3", "Square 4",
+					"Wave 1", "Wave 2", "Wave 3", "Wave 4",
+					"Wave 5", "Wave 6", "Wave 7", "Wave 8"
+				};
+				set_voice_count( count );
+				set_voice_names( names );
+			}
+		}
+
+		if ( header_.chip_flags & fme7_flag )
+		{
+			fme7 = BLARGG_NEW Nes_Fme7_Apu;
+			CHECK_ALLOC( fme7 );
+			adjusted_gain *= 0.75;
+
+			int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count;
+			static const char* const names [count] = {
+				APU_NAMES,
+				"Square 3", "Square 4", "Square 5"
+			};
+			set_voice_count( count );
+			set_voice_names( names );
+		}
+
+		if ( namco ) namco->volume( adjusted_gain );
+		if ( vrc6  ) vrc6 ->volume( adjusted_gain );
+		if ( fme7  ) fme7 ->volume( adjusted_gain );
+	}
+	#endif
+
+	apu.volume( adjusted_gain );
+
+	return 0;
+}
+
+blargg_err_t Nsf_Emu::load_( Data_Reader& in )
+{
+	assert( offsetof (header_t,unused [4]) == header_size );
+	RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
+
+	set_track_count( header_.track_count );
+	RETURN_ERR( check_nsf_header( &header_ ) );
+
+	if ( header_.vers != 1 )
+		set_warning( "Unknown file version" );
+
+	// sound and memory
+	blargg_err_t err = init_sound();
+	if ( err )
+		return err;
+
+	// set up data
+	nes_addr_t load_addr = GET_LE16( header_.load_addr );
+	init_addr = GET_LE16( header_.init_addr );
+	play_addr = GET_LE16( header_.play_addr );
+	if ( !load_addr ) load_addr = rom_begin;
+	if ( !init_addr ) init_addr = rom_begin;
+	if ( !play_addr ) play_addr = rom_begin;
+	if ( load_addr < rom_begin || init_addr < rom_begin )
+	{
+		const char* w = warning();
+		if ( !w )
+			w = "Corrupt file (invalid load/init/play address)";
+		return w;
+	}
+
+	rom.set_addr( load_addr % bank_size );
+	int total_banks = rom.size() / bank_size;
+
+	// bank switching
+	int first_bank = (load_addr - rom_begin) / bank_size;
+	for ( int i = 0; i < bank_count; i++ )
+	{
+		unsigned bank = i - first_bank;
+		if ( bank >= (unsigned) total_banks )
+			bank = 0;
+		initial_banks [i] = bank;
+
+		if ( header_.banks [i] )
+		{
+			// bank-switched
+			memcpy( initial_banks, header_.banks, sizeof initial_banks );
+			break;
+		}
+	}
+
+	pal_only = (header_.speed_flags & 3) == 1;
+
+	#if !NSF_EMU_EXTRA_FLAGS
+		header_.speed_flags = 0;
+	#endif
+
+	set_tempo( tempo() );
+
+	return setup_buffer( (long) (clock_rate_ + 0.5) );
+}
+
+void Nsf_Emu::update_eq( blip_eq_t const& eq )
+{
+	apu.treble_eq( eq );
+
+	#if !NSF_EMU_APU_ONLY
+	{
+		if ( namco ) namco->treble_eq( eq );
+		if ( vrc6  ) vrc6 ->treble_eq( eq );
+		if ( fme7  ) fme7 ->treble_eq( eq );
+	}
+	#endif
+}
+
+void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
+{
+	if ( i < Nes_Apu::osc_count )
+	{
+		apu.osc_output( i, buf );
+		return;
+	}
+	i -= Nes_Apu::osc_count;
+
+	#if !NSF_EMU_APU_ONLY
+	{
+		if ( fme7 && i < Nes_Fme7_Apu::osc_count )
+		{
+			fme7->osc_output( i, buf );
+			return;
+		}
+
+		if ( vrc6 )
+		{
+			if ( i < Nes_Vrc6_Apu::osc_count )
+			{
+				// put saw first
+				if ( --i < 0 )
+					i = 2;
+				vrc6->osc_output( i, buf );
+				return;
+			}
+			i -= Nes_Vrc6_Apu::osc_count;
+		}
+
+		if ( namco && i < Nes_Namco_Apu::osc_count )
+		{
+			namco->osc_output( i, buf );
+			return;
+		}
+	}
+	#endif
+}
+
+// Emulation
+
+// see nes_cpu_io.h for read/write functions
+
+void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
+{
+	#if !NSF_EMU_APU_ONLY
+	{
+		if ( namco )
+		{
+			switch ( addr )
+			{
+			case Nes_Namco_Apu::data_reg_addr:
+				namco->write_data( time(), data );
+				return;
+
+			case Nes_Namco_Apu::addr_reg_addr:
+				namco->write_addr( data );
+				return;
+			}
+		}
+
+		if ( addr >= Nes_Fme7_Apu::latch_addr && fme7 )
+		{
+			switch ( addr & Nes_Fme7_Apu::addr_mask )
+			{
+			case Nes_Fme7_Apu::latch_addr:
+				fme7->write_latch( data );
+				return;
+
+			case Nes_Fme7_Apu::data_addr:
+				fme7->write_data( time(), data );
+				return;
+			}
+		}
+
+		if ( vrc6 )
+		{
+			unsigned reg = addr & (Nes_Vrc6_Apu::addr_step - 1);
+			unsigned osc = unsigned (addr - Nes_Vrc6_Apu::base_addr) / Nes_Vrc6_Apu::addr_step;
+			if ( osc < Nes_Vrc6_Apu::osc_count && reg < Nes_Vrc6_Apu::reg_count )
+			{
+				vrc6->write_osc( time(), osc, reg, data );
+				return;
+			}
+		}
+	}
+	#endif
+
+	// unmapped write
+
+	#ifndef NDEBUG
+	{
+		// some games write to $8000 and $8001 repeatedly
+		if ( addr == 0x8000 || addr == 0x8001 ) return;
+
+		// probably namco sound mistakenly turned on in mck
+		if ( addr == 0x4800 || addr == 0xF800 ) return;
+
+		// memory mapper?
+		if ( addr == 0xFFF8 ) return;
+
+		debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
+	}
+	#endif
+}
+
+blargg_err_t Nsf_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( low_mem, 0, sizeof low_mem );
+	memset( sram,    0, sizeof sram );
+
+	cpu::reset( unmapped_code ); // also maps low_mem
+	cpu::map_code( sram_addr, sizeof sram, sram );
+	for ( int i = 0; i < bank_count; ++i )
+		cpu_write( bank_select_addr + i, initial_banks [i] );
+
+	apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
+	apu.write_register( 0, 0x4015, 0x0F );
+	apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );
+	#if !NSF_EMU_APU_ONLY
+	{
+		if ( namco ) namco->reset();
+		if ( vrc6  ) vrc6 ->reset();
+		if ( fme7  ) fme7 ->reset();
+	}
+	#endif
+
+	play_ready = 4;
+	play_extra = 0;
+	next_play = play_period / clock_divisor;
+
+	saved_state.pc = badop_addr;
+	low_mem [0x1FF] = (badop_addr - 1) >> 8;
+	low_mem [0x1FE] = (badop_addr - 1) & 0xFF;
+	r.sp = 0xFD;
+	r.pc = init_addr;
+	r.a  = track;
+	r.x  = pal_only;
+
+	return 0;
+}
+
+blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
+{
+	set_time( 0 );
+	while ( time() < duration )
+	{
+		nes_time_t end = min( (blip_time_t) next_play, duration );
+		end = min( end, time() + 32767 ); // allows CPU to use 16-bit time delta
+		if ( cpu::run( end ) )
+		{
+			if ( r.pc != badop_addr )
+			{
+				set_warning( "Emulation error (illegal instruction)" );
+				r.pc++;
+			}
+			else
+			{
+				play_ready = 1;
+				if ( saved_state.pc != badop_addr )
+				{
+					cpu::r = saved_state;
+					saved_state.pc = badop_addr;
+				}
+				else
+				{
+					set_time( end );
+				}
+			}
+		}
+
+		if ( time() >= next_play )
+		{
+			nes_time_t period = (play_period + play_extra) / clock_divisor;
+			play_extra = play_period - period * clock_divisor;
+			next_play += period;
+			if ( play_ready && !--play_ready )
+			{
+				check( saved_state.pc == badop_addr );
+				if ( r.pc != badop_addr )
+					saved_state = cpu::r;
+
+				r.pc = play_addr;
+				low_mem [0x100 + r.sp--] = (badop_addr - 1) >> 8;
+				low_mem [0x100 + r.sp--] = (badop_addr - 1) & 0xFF;
+				GME_FRAME_HOOK( this );
+			}
+		}
+	}
+
+	if ( cpu::error_count() )
+	{
+		cpu::clear_error_count();
+		set_warning( "Emulation error (illegal instruction)" );
+	}
+
+	duration = time();
+	next_play -= duration;
+	check( next_play >= 0 );
+	if ( next_play < 0 )
+		next_play = 0;
+
+	apu.end_frame( duration );
+
+	#if !NSF_EMU_APU_ONLY
+	{
+		if ( namco ) namco->end_frame( duration );
+		if ( vrc6  ) vrc6 ->end_frame( duration );
+		if ( fme7  ) fme7 ->end_frame( duration );
+	}
+	#endif
+
+	return 0;
+}
diff --git a/src/console/Nsf_Emu.cxx b/src/console/Nsf_Emu.cxx
deleted file mode 100644
index 80c9038712ad..000000000000
--- a/src/console/Nsf_Emu.cxx
+++ /dev/null
@@ -1,559 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nsf_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <stdio.h>
-
-#if !NSF_EMU_APU_ONLY
-	#include "Nes_Namco_Apu.h"
-	#include "Nes_Vrc6_Apu.h"
-	#include "Nes_Fme7_Apu.h"
-#endif
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const vrc6_flag  = 0x01;
-int const namco_flag = 0x10;
-int const fme7_flag  = 0x20;
-
-long const clock_divisor = 12;
-
-Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq     = {  -1.0, 80 };
-Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80 };
-
-int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
-{
-	return *((Nsf_Emu*) emu)->cpu::get_code( addr );
-}
-
-Nsf_Emu::Nsf_Emu()
-{
-	vrc6  = 0;
-	namco = 0;
-	fme7  = 0;
-
-	set_type( gme_nsf_type );
-	set_silence_lookahead( 6 );
-	apu.dmc_reader( pcm_read, this );
-	Music_Emu::set_equalizer( nes_eq );
-	set_gain( 1.4 );
-	memset( unmapped_code, Nes_Cpu::bad_opcode, sizeof unmapped_code );
-}
-
-Nsf_Emu::~Nsf_Emu() { unload(); }
-
-void Nsf_Emu::unload()
-{
-	#if !NSF_EMU_APU_ONLY
-	{
-		delete vrc6;
-		vrc6  = 0;
-
-		delete namco;
-		namco = 0;
-
-		delete fme7;
-		fme7  = 0;
-	}
-	#endif
-
-	rom.clear();
-	Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
-{
-	GME_COPY_FIELD( h, out, game );
-	GME_COPY_FIELD( h, out, author );
-	GME_COPY_FIELD( h, out, copyright );
-	if ( h.chip_flags )
-		Gme_File::copy_field_( out->system, "Famicom" );
-}
-
-blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
-{
-	copy_nsf_fields( header_, out );
-	return 0;
-}
-
-static blargg_err_t check_nsf_header( void const* header )
-{
-	if ( memcmp( header, "NESM\x1A", 5 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Nsf_File : Gme_Info_
-{
-	Nsf_Emu::header_t h;
-
-	Nsf_File() { set_type( gme_nsf_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		blargg_err_t err = in.read( &h, Nsf_Emu::header_size );
-		if ( err )
-			return (err == in.eof_error ? gme_wrong_file_type : err);
-
-		if ( h.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
-			set_warning( "Uses unsupported audio expansion hardware" );
-
-		set_track_count( h.track_count );
-		return check_nsf_header( &h );
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		copy_nsf_fields( h, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
-static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
-
-static gme_type_t_ const gme_nsf_type_ = { "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 };
-gme_type_t const gme_nsf_type = &gme_nsf_type_;
-
-
-// Setup
-
-void Nsf_Emu::set_tempo_( double t )
-{
-	unsigned playback_rate = GET_LE16( header_.ntsc_speed );
-	unsigned standard_rate = 0x411A;
-	clock_rate_ = 1789772.72727;
-	play_period = 262 * 341L * 4 - 2; // two fewer PPU clocks every four frames
-
-	if ( pal_only )
-	{
-		play_period   = 33247 * clock_divisor;
-		clock_rate_   = 1662607.125;
-		standard_rate = 0x4E20;
-		playback_rate = GET_LE16( header_.pal_speed );
-	}
-
-	if ( !playback_rate )
-		playback_rate = standard_rate;
-
-	if ( playback_rate != standard_rate || t != 1.0 )
-		play_period = long (playback_rate * clock_rate_ / (1000000.0 / clock_divisor * t));
-
-	apu.set_tempo( t );
-}
-
-blargg_err_t Nsf_Emu::init_sound()
-{
-	if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
-		set_warning( "Uses unsupported audio expansion hardware" );
-
-	{
-		#define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC"
-
-		int const count = Nes_Apu::osc_count;
-		static const char* const apu_names [count] = { APU_NAMES };
-		set_voice_count( count );
-		set_voice_names( apu_names );
-
-	}
-
-	static int const types [] = {
-		wave_type  | 1, wave_type  | 2, wave_type | 0,
-		noise_type | 0, mixed_type | 1,
-		wave_type  | 3, wave_type  | 4, wave_type | 5,
-		wave_type  | 6, wave_type  | 7, wave_type | 8, wave_type | 9,
-		wave_type  |10, wave_type  |11, wave_type |12, wave_type |13
-	};
-	set_voice_types( types ); // common to all sound chip configurations
-
-	double adjusted_gain = gain();
-
-	#if NSF_EMU_APU_ONLY
-	{
-		if ( header_.chip_flags )
-			set_warning( "Uses unsupported audio expansion hardware" );
-	}
-	#else
-	{
-		if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) )
-			set_voice_count( Nes_Apu::osc_count + 3 );
-
-		if ( header_.chip_flags & namco_flag )
-		{
-			namco = BLARGG_NEW Nes_Namco_Apu;
-			CHECK_ALLOC( namco );
-			adjusted_gain *= 0.75;
-
-			int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count;
-			static const char* const names [count] = {
-				APU_NAMES,
-				"Wave 1", "Wave 2", "Wave 3", "Wave 4",
-				"Wave 5", "Wave 6", "Wave 7", "Wave 8"
-			};
-			set_voice_count( count );
-			set_voice_names( names );
-		}
-
-		if ( header_.chip_flags & vrc6_flag )
-		{
-			vrc6 = BLARGG_NEW Nes_Vrc6_Apu;
-			CHECK_ALLOC( vrc6 );
-			adjusted_gain *= 0.75;
-
-			{
-				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count;
-				static const char* const names [count] = {
-					APU_NAMES,
-					"Saw Wave", "Square 3", "Square 4"
-				};
-				set_voice_count( count );
-				set_voice_names( names );
-			}
-
-			if ( header_.chip_flags & namco_flag )
-			{
-				int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count +
-						Nes_Namco_Apu::osc_count;
-				static const char* const names [count] = {
-					APU_NAMES,
-					"Saw Wave", "Square 3", "Square 4",
-					"Wave 1", "Wave 2", "Wave 3", "Wave 4",
-					"Wave 5", "Wave 6", "Wave 7", "Wave 8"
-				};
-				set_voice_count( count );
-				set_voice_names( names );
-			}
-		}
-
-		if ( header_.chip_flags & fme7_flag )
-		{
-			fme7 = BLARGG_NEW Nes_Fme7_Apu;
-			CHECK_ALLOC( fme7 );
-			adjusted_gain *= 0.75;
-
-			int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count;
-			static const char* const names [count] = {
-				APU_NAMES,
-				"Square 3", "Square 4", "Square 5"
-			};
-			set_voice_count( count );
-			set_voice_names( names );
-		}
-
-		if ( namco ) namco->volume( adjusted_gain );
-		if ( vrc6  ) vrc6 ->volume( adjusted_gain );
-		if ( fme7  ) fme7 ->volume( adjusted_gain );
-	}
-	#endif
-
-	apu.volume( adjusted_gain );
-
-	return 0;
-}
-
-blargg_err_t Nsf_Emu::load_( Data_Reader& in )
-{
-	assert( offsetof (header_t,unused [4]) == header_size );
-	RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
-	set_track_count( header_.track_count );
-	RETURN_ERR( check_nsf_header( &header_ ) );
-
-	if ( header_.vers != 1 )
-		set_warning( "Unknown file version" );
-
-	// sound and memory
-	blargg_err_t err = init_sound();
-	if ( err )
-		return err;
-
-	// set up data
-	nes_addr_t load_addr = GET_LE16( header_.load_addr );
-	init_addr = GET_LE16( header_.init_addr );
-	play_addr = GET_LE16( header_.play_addr );
-	if ( !load_addr ) load_addr = rom_begin;
-	if ( !init_addr ) init_addr = rom_begin;
-	if ( !play_addr ) play_addr = rom_begin;
-	if ( load_addr < rom_begin || init_addr < rom_begin )
-	{
-		const char* w = warning();
-		if ( !w )
-			w = "Corrupt file (invalid load/init/play address)";
-		return w;
-	}
-
-	rom.set_addr( load_addr % bank_size );
-	int total_banks = rom.size() / bank_size;
-
-	// bank switching
-	int first_bank = (load_addr - rom_begin) / bank_size;
-	for ( int i = 0; i < bank_count; i++ )
-	{
-		unsigned bank = i - first_bank;
-		if ( bank >= (unsigned) total_banks )
-			bank = 0;
-		initial_banks [i] = bank;
-
-		if ( header_.banks [i] )
-		{
-			// bank-switched
-			memcpy( initial_banks, header_.banks, sizeof initial_banks );
-			break;
-		}
-	}
-
-	pal_only = (header_.speed_flags & 3) == 1;
-
-	#if !NSF_EMU_EXTRA_FLAGS
-		header_.speed_flags = 0;
-	#endif
-
-	set_tempo( tempo() );
-
-	return setup_buffer( (long) (clock_rate_ + 0.5) );
-}
-
-void Nsf_Emu::update_eq( blip_eq_t const& eq )
-{
-	apu.treble_eq( eq );
-
-	#if !NSF_EMU_APU_ONLY
-	{
-		if ( namco ) namco->treble_eq( eq );
-		if ( vrc6  ) vrc6 ->treble_eq( eq );
-		if ( fme7  ) fme7 ->treble_eq( eq );
-	}
-	#endif
-}
-
-void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
-{
-	if ( i < Nes_Apu::osc_count )
-	{
-		apu.osc_output( i, buf );
-		return;
-	}
-	i -= Nes_Apu::osc_count;
-
-	#if !NSF_EMU_APU_ONLY
-	{
-		if ( fme7 && i < Nes_Fme7_Apu::osc_count )
-		{
-			fme7->osc_output( i, buf );
-			return;
-		}
-
-		if ( vrc6 )
-		{
-			if ( i < Nes_Vrc6_Apu::osc_count )
-			{
-				// put saw first
-				if ( --i < 0 )
-					i = 2;
-				vrc6->osc_output( i, buf );
-				return;
-			}
-			i -= Nes_Vrc6_Apu::osc_count;
-		}
-
-		if ( namco && i < Nes_Namco_Apu::osc_count )
-		{
-			namco->osc_output( i, buf );
-			return;
-		}
-	}
-	#endif
-}
-
-// Emulation
-
-// see nes_cpu_io.h for read/write functions
-
-void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
-{
-	#if !NSF_EMU_APU_ONLY
-	{
-		if ( namco )
-		{
-			switch ( addr )
-			{
-			case Nes_Namco_Apu::data_reg_addr:
-				namco->write_data( time(), data );
-				return;
-
-			case Nes_Namco_Apu::addr_reg_addr:
-				namco->write_addr( data );
-				return;
-			}
-		}
-
-		if ( addr >= Nes_Fme7_Apu::latch_addr && fme7 )
-		{
-			switch ( addr & Nes_Fme7_Apu::addr_mask )
-			{
-			case Nes_Fme7_Apu::latch_addr:
-				fme7->write_latch( data );
-				return;
-
-			case Nes_Fme7_Apu::data_addr:
-				fme7->write_data( time(), data );
-				return;
-			}
-		}
-
-		if ( vrc6 )
-		{
-			unsigned reg = addr & (Nes_Vrc6_Apu::addr_step - 1);
-			unsigned osc = unsigned (addr - Nes_Vrc6_Apu::base_addr) / Nes_Vrc6_Apu::addr_step;
-			if ( osc < Nes_Vrc6_Apu::osc_count && reg < Nes_Vrc6_Apu::reg_count )
-			{
-				vrc6->write_osc( time(), osc, reg, data );
-				return;
-			}
-		}
-	}
-	#endif
-
-	// unmapped write
-
-	#ifndef NDEBUG
-	{
-		// some games write to $8000 and $8001 repeatedly
-		if ( addr == 0x8000 || addr == 0x8001 ) return;
-
-		// probably namco sound mistakenly turned on in mck
-		if ( addr == 0x4800 || addr == 0xF800 ) return;
-
-		// memory mapper?
-		if ( addr == 0xFFF8 ) return;
-
-		debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
-	}
-	#endif
-}
-
-blargg_err_t Nsf_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( low_mem, 0, sizeof low_mem );
-	memset( sram,    0, sizeof sram );
-
-	cpu::reset( unmapped_code ); // also maps low_mem
-	cpu::map_code( sram_addr, sizeof sram, sram );
-	for ( int i = 0; i < bank_count; ++i )
-		cpu_write( bank_select_addr + i, initial_banks [i] );
-
-	apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
-	apu.write_register( 0, 0x4015, 0x0F );
-	apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );
-	#if !NSF_EMU_APU_ONLY
-	{
-		if ( namco ) namco->reset();
-		if ( vrc6  ) vrc6 ->reset();
-		if ( fme7  ) fme7 ->reset();
-	}
-	#endif
-
-	play_ready = 4;
-	play_extra = 0;
-	next_play = play_period / clock_divisor;
-
-	saved_state.pc = badop_addr;
-	low_mem [0x1FF] = (badop_addr - 1) >> 8;
-	low_mem [0x1FE] = (badop_addr - 1) & 0xFF;
-	r.sp = 0xFD;
-	r.pc = init_addr;
-	r.a  = track;
-	r.x  = pal_only;
-
-	return 0;
-}
-
-blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
-{
-	set_time( 0 );
-	while ( time() < duration )
-	{
-		nes_time_t end = min( (blip_time_t) next_play, duration );
-		end = min( end, time() + 32767 ); // allows CPU to use 16-bit time delta
-		if ( cpu::run( end ) )
-		{
-			if ( r.pc != badop_addr )
-			{
-				set_warning( "Emulation error (illegal instruction)" );
-				r.pc++;
-			}
-			else
-			{
-				play_ready = 1;
-				if ( saved_state.pc != badop_addr )
-				{
-					cpu::r = saved_state;
-					saved_state.pc = badop_addr;
-				}
-				else
-				{
-					set_time( end );
-				}
-			}
-		}
-
-		if ( time() >= next_play )
-		{
-			nes_time_t period = (play_period + play_extra) / clock_divisor;
-			play_extra = play_period - period * clock_divisor;
-			next_play += period;
-			if ( play_ready && !--play_ready )
-			{
-				check( saved_state.pc == badop_addr );
-				if ( r.pc != badop_addr )
-					saved_state = cpu::r;
-
-				r.pc = play_addr;
-				low_mem [0x100 + r.sp--] = (badop_addr - 1) >> 8;
-				low_mem [0x100 + r.sp--] = (badop_addr - 1) & 0xFF;
-				GME_FRAME_HOOK( this );
-			}
-		}
-	}
-
-	if ( cpu::error_count() )
-	{
-		cpu::clear_error_count();
-		set_warning( "Emulation error (illegal instruction)" );
-	}
-
-	duration = time();
-	next_play -= duration;
-	check( next_play >= 0 );
-	if ( next_play < 0 )
-		next_play = 0;
-
-	apu.end_frame( duration );
-
-	#if !NSF_EMU_APU_ONLY
-	{
-		if ( namco ) namco->end_frame( duration );
-		if ( vrc6  ) vrc6 ->end_frame( duration );
-		if ( fme7  ) fme7 ->end_frame( duration );
-	}
-	#endif
-
-	return 0;
-}
diff --git a/src/console/Nsfe_Emu.cc b/src/console/Nsfe_Emu.cc
new file mode 100644
index 000000000000..2f3d5a762ed4
--- /dev/null
+++ b/src/console/Nsfe_Emu.cc
@@ -0,0 +1,332 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Nsfe_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+#include <ctype.h>
+
+/* Copyright (C) 2005-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
+
+Nsfe_Info::~Nsfe_Info() { }
+
+inline void Nsfe_Info::unload()
+{
+	track_name_data.clear();
+	track_names.clear();
+	playlist.clear();
+	track_times.clear();
+}
+
+// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
+void Nsfe_Info::disable_playlist( bool b )
+{
+	playlist_disabled = b;
+	info.track_count = playlist.size();
+	if ( !info.track_count || playlist_disabled )
+		info.track_count = actual_track_count_;
+}
+
+int Nsfe_Info::remap_track( int track ) const
+{
+	if ( !playlist_disabled && (unsigned) track < playlist.size() )
+		track = playlist [track];
+	return track;
+}
+
+// Read multiple strings and separate into individual strings
+static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
+		blargg_vector<const char*>& strs )
+{
+	RETURN_ERR( chars.resize( size + 1 ) );
+	chars [size] = 0; // in case last string doesn't have terminator
+	RETURN_ERR( in.read( &chars [0], size ) );
+
+	RETURN_ERR( strs.resize( 128 ) );
+	int count = 0;
+	for ( int i = 0; i < size; i++ )
+	{
+		if ( (int) strs.size() <= count )
+			RETURN_ERR( strs.resize( count * 2 ) );
+		strs [count++] = &chars [i];
+		while ( i < size && chars [i] )
+			i++;
+	}
+
+	return strs.resize( count );
+}
+
+// Copy in to out, where out has out_max characters allocated. Truncate to
+// out_max - 1 characters.
+static void copy_str( const char* in, char* out, int out_max )
+{
+	out [out_max - 1] = 0;
+	strncpy( out, in, out_max - 1 );
+}
+
+struct nsfe_info_t
+{
+	byte load_addr [2];
+	byte init_addr [2];
+	byte play_addr [2];
+	byte speed_flags;
+	byte chip_flags;
+	byte track_count;
+	byte first_track;
+	byte unused [6];
+};
+
+blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
+{
+	int const nsfe_info_size = 16;
+	assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
+
+	// check header
+	byte signature [4];
+	blargg_err_t err = in.read( signature, sizeof signature );
+	if ( err )
+		return (err == in.eof_error ? gme_wrong_file_type : err);
+	if ( memcmp( signature, "NSFE", 4 ) )
+		return gme_wrong_file_type;
+
+	// free previous info
+	track_name_data.clear();
+	track_names.clear();
+	playlist.clear();
+	track_times.clear();
+
+	// default nsf header
+	static const Nsf_Emu::header_t base_header =
+	{
+		{'N','E','S','M','\x1A'},// tag
+		1,                  // version
+		1, 1,               // track count, first track
+		{0,0},{0,0},{0,0},  // addresses
+		"","","",           // strings
+		{0x1A, 0x41},       // NTSC rate
+		{0,0,0,0,0,0,0,0},  // banks
+		{0x20, 0x4E},       // PAL rate
+		0, 0,               // flags
+		{0,0,0,0}           // unused
+	};
+	Nsf_Emu::header_t& header = info;
+	header = base_header;
+
+	// parse tags
+	int phase = 0;
+	while ( phase != 3 )
+	{
+		// read size and tag
+		byte block_header [2] [4];
+		RETURN_ERR( in.read( block_header, sizeof block_header ) );
+		blargg_long size = GET_LE32( block_header [0] );
+		blargg_long tag  = GET_LE32( block_header [1] );
+
+		//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
+
+		switch ( tag )
+		{
+			case BLARGG_4CHAR('O','F','N','I'): {
+				check( phase == 0 );
+				if ( size < 8 )
+					return "Corrupt file";
+
+				nsfe_info_t finfo;
+				finfo.track_count = 1;
+				finfo.first_track = 0;
+
+				RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
+				if ( size > nsfe_info_size )
+					RETURN_ERR( in.skip( size - nsfe_info_size ) );
+				phase = 1;
+				info.speed_flags = finfo.speed_flags;
+				info.chip_flags  = finfo.chip_flags;
+				info.track_count = finfo.track_count;
+				this->actual_track_count_ = finfo.track_count;
+				info.first_track = finfo.first_track;
+				memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
+				break;
+			}
+
+			case BLARGG_4CHAR('K','N','A','B'):
+				if ( size > (int) sizeof info.banks )
+					return "Corrupt file";
+				RETURN_ERR( in.read( info.banks, size ) );
+				break;
+
+			case BLARGG_4CHAR('h','t','u','a'): {
+				blargg_vector<char> chars;
+				blargg_vector<const char*> strs;
+				RETURN_ERR( read_strs( in, size, chars, strs ) );
+				int n = strs.size();
+
+				if ( n > 3 )
+					copy_str( strs [3], info.dumper, sizeof info.dumper );
+
+				if ( n > 2 )
+					copy_str( strs [2], info.copyright, sizeof info.copyright );
+
+				if ( n > 1 )
+					copy_str( strs [1], info.author, sizeof info.author );
+
+				if ( n > 0 )
+					copy_str( strs [0], info.game, sizeof info.game );
+
+				break;
+			}
+
+			case BLARGG_4CHAR('e','m','i','t'):
+				RETURN_ERR( track_times.resize( size / 4 ) );
+				RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
+				break;
+
+			case BLARGG_4CHAR('l','b','l','t'):
+				RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
+				break;
+
+			case BLARGG_4CHAR('t','s','l','p'):
+				RETURN_ERR( playlist.resize( size ) );
+				RETURN_ERR( in.read( &playlist [0], size ) );
+				break;
+
+			case BLARGG_4CHAR('A','T','A','D'): {
+				check( phase == 1 );
+				phase = 2;
+				if ( !nsf_emu )
+				{
+					RETURN_ERR( in.skip( size ) );
+				}
+				else
+				{
+					Subset_Reader sub( &in, size ); // limit emu to nsf data
+					Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
+					RETURN_ERR( nsf_emu->load( rem ) );
+					check( rem.remain() == 0 );
+				}
+				break;
+			}
+
+			case BLARGG_4CHAR('D','N','E','N'):
+				check( phase == 2 );
+				phase = 3;
+				break;
+
+			default:
+				// tags that can be skipped start with a lowercase character
+				check( islower( (tag >> 24) & 0xFF ) );
+				RETURN_ERR( in.skip( size ) );
+				break;
+		}
+	}
+
+	return 0;
+}
+
+blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
+{
+	int remapped = remap_track( track );
+	if ( (unsigned) remapped < track_times.size() )
+	{
+		long length = (int32_t) GET_LE32( track_times [remapped] );
+		if ( length > 0 )
+			out->length = length;
+	}
+	if ( (unsigned) remapped < track_names.size() )
+		Gme_File::copy_field_( out->song, track_names [remapped] );
+
+	GME_COPY_FIELD( info, out, game );
+	GME_COPY_FIELD( info, out, author );
+	GME_COPY_FIELD( info, out, copyright );
+	GME_COPY_FIELD( info, out, dumper );
+	return 0;
+}
+
+Nsfe_Emu::Nsfe_Emu()
+{
+	loading = false;
+	set_type( gme_nsfe_type );
+}
+
+Nsfe_Emu::~Nsfe_Emu() { }
+
+void Nsfe_Emu::unload()
+{
+	if ( !loading )
+		info.unload(); // TODO: extremely hacky!
+	Nsf_Emu::unload();
+}
+
+blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
+{
+	return info.track_info_( out, track );
+}
+
+struct Nsfe_File : Gme_Info_
+{
+	Nsfe_Info info;
+
+	Nsfe_File() { set_type( gme_nsfe_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		RETURN_ERR( info.load( in, 0 ) );
+		info.disable_playlist( false );
+		set_track_count( info.info.track_count );
+		return 0;
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int track ) const
+	{
+		return info.track_info_( out, track );
+	}
+};
+
+static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
+static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
+
+static gme_type_t_ const gme_nsfe_type_ = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
+gme_type_t const gme_nsfe_type = &gme_nsfe_type_;
+
+
+blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
+{
+	if ( loading )
+		return Nsf_Emu::load_( in );
+
+	// TODO: this hacky recursion-avoidance could have subtle problems
+	loading = true;
+	blargg_err_t err = info.load( in, this );
+	loading = false;
+	disable_playlist( false );
+	return err;
+}
+
+void Nsfe_Emu::disable_playlist( bool b )
+{
+	info.disable_playlist( b );
+	set_track_count( info.info.track_count );
+}
+
+void Nsfe_Emu::clear_playlist_()
+{
+	disable_playlist();
+	Nsf_Emu::clear_playlist_();
+}
+
+blargg_err_t Nsfe_Emu::start_track_( int track )
+{
+	return Nsf_Emu::start_track_( info.remap_track( track ) );
+}
diff --git a/src/console/Nsfe_Emu.cxx b/src/console/Nsfe_Emu.cxx
deleted file mode 100644
index 2f3d5a762ed4..000000000000
--- a/src/console/Nsfe_Emu.cxx
+++ /dev/null
@@ -1,332 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nsfe_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
-
-Nsfe_Info::~Nsfe_Info() { }
-
-inline void Nsfe_Info::unload()
-{
-	track_name_data.clear();
-	track_names.clear();
-	playlist.clear();
-	track_times.clear();
-}
-
-// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
-void Nsfe_Info::disable_playlist( bool b )
-{
-	playlist_disabled = b;
-	info.track_count = playlist.size();
-	if ( !info.track_count || playlist_disabled )
-		info.track_count = actual_track_count_;
-}
-
-int Nsfe_Info::remap_track( int track ) const
-{
-	if ( !playlist_disabled && (unsigned) track < playlist.size() )
-		track = playlist [track];
-	return track;
-}
-
-// Read multiple strings and separate into individual strings
-static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
-		blargg_vector<const char*>& strs )
-{
-	RETURN_ERR( chars.resize( size + 1 ) );
-	chars [size] = 0; // in case last string doesn't have terminator
-	RETURN_ERR( in.read( &chars [0], size ) );
-
-	RETURN_ERR( strs.resize( 128 ) );
-	int count = 0;
-	for ( int i = 0; i < size; i++ )
-	{
-		if ( (int) strs.size() <= count )
-			RETURN_ERR( strs.resize( count * 2 ) );
-		strs [count++] = &chars [i];
-		while ( i < size && chars [i] )
-			i++;
-	}
-
-	return strs.resize( count );
-}
-
-// Copy in to out, where out has out_max characters allocated. Truncate to
-// out_max - 1 characters.
-static void copy_str( const char* in, char* out, int out_max )
-{
-	out [out_max - 1] = 0;
-	strncpy( out, in, out_max - 1 );
-}
-
-struct nsfe_info_t
-{
-	byte load_addr [2];
-	byte init_addr [2];
-	byte play_addr [2];
-	byte speed_flags;
-	byte chip_flags;
-	byte track_count;
-	byte first_track;
-	byte unused [6];
-};
-
-blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
-{
-	int const nsfe_info_size = 16;
-	assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
-
-	// check header
-	byte signature [4];
-	blargg_err_t err = in.read( signature, sizeof signature );
-	if ( err )
-		return (err == in.eof_error ? gme_wrong_file_type : err);
-	if ( memcmp( signature, "NSFE", 4 ) )
-		return gme_wrong_file_type;
-
-	// free previous info
-	track_name_data.clear();
-	track_names.clear();
-	playlist.clear();
-	track_times.clear();
-
-	// default nsf header
-	static const Nsf_Emu::header_t base_header =
-	{
-		{'N','E','S','M','\x1A'},// tag
-		1,                  // version
-		1, 1,               // track count, first track
-		{0,0},{0,0},{0,0},  // addresses
-		"","","",           // strings
-		{0x1A, 0x41},       // NTSC rate
-		{0,0,0,0,0,0,0,0},  // banks
-		{0x20, 0x4E},       // PAL rate
-		0, 0,               // flags
-		{0,0,0,0}           // unused
-	};
-	Nsf_Emu::header_t& header = info;
-	header = base_header;
-
-	// parse tags
-	int phase = 0;
-	while ( phase != 3 )
-	{
-		// read size and tag
-		byte block_header [2] [4];
-		RETURN_ERR( in.read( block_header, sizeof block_header ) );
-		blargg_long size = GET_LE32( block_header [0] );
-		blargg_long tag  = GET_LE32( block_header [1] );
-
-		//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
-
-		switch ( tag )
-		{
-			case BLARGG_4CHAR('O','F','N','I'): {
-				check( phase == 0 );
-				if ( size < 8 )
-					return "Corrupt file";
-
-				nsfe_info_t finfo;
-				finfo.track_count = 1;
-				finfo.first_track = 0;
-
-				RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
-				if ( size > nsfe_info_size )
-					RETURN_ERR( in.skip( size - nsfe_info_size ) );
-				phase = 1;
-				info.speed_flags = finfo.speed_flags;
-				info.chip_flags  = finfo.chip_flags;
-				info.track_count = finfo.track_count;
-				this->actual_track_count_ = finfo.track_count;
-				info.first_track = finfo.first_track;
-				memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
-				break;
-			}
-
-			case BLARGG_4CHAR('K','N','A','B'):
-				if ( size > (int) sizeof info.banks )
-					return "Corrupt file";
-				RETURN_ERR( in.read( info.banks, size ) );
-				break;
-
-			case BLARGG_4CHAR('h','t','u','a'): {
-				blargg_vector<char> chars;
-				blargg_vector<const char*> strs;
-				RETURN_ERR( read_strs( in, size, chars, strs ) );
-				int n = strs.size();
-
-				if ( n > 3 )
-					copy_str( strs [3], info.dumper, sizeof info.dumper );
-
-				if ( n > 2 )
-					copy_str( strs [2], info.copyright, sizeof info.copyright );
-
-				if ( n > 1 )
-					copy_str( strs [1], info.author, sizeof info.author );
-
-				if ( n > 0 )
-					copy_str( strs [0], info.game, sizeof info.game );
-
-				break;
-			}
-
-			case BLARGG_4CHAR('e','m','i','t'):
-				RETURN_ERR( track_times.resize( size / 4 ) );
-				RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
-				break;
-
-			case BLARGG_4CHAR('l','b','l','t'):
-				RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
-				break;
-
-			case BLARGG_4CHAR('t','s','l','p'):
-				RETURN_ERR( playlist.resize( size ) );
-				RETURN_ERR( in.read( &playlist [0], size ) );
-				break;
-
-			case BLARGG_4CHAR('A','T','A','D'): {
-				check( phase == 1 );
-				phase = 2;
-				if ( !nsf_emu )
-				{
-					RETURN_ERR( in.skip( size ) );
-				}
-				else
-				{
-					Subset_Reader sub( &in, size ); // limit emu to nsf data
-					Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
-					RETURN_ERR( nsf_emu->load( rem ) );
-					check( rem.remain() == 0 );
-				}
-				break;
-			}
-
-			case BLARGG_4CHAR('D','N','E','N'):
-				check( phase == 2 );
-				phase = 3;
-				break;
-
-			default:
-				// tags that can be skipped start with a lowercase character
-				check( islower( (tag >> 24) & 0xFF ) );
-				RETURN_ERR( in.skip( size ) );
-				break;
-		}
-	}
-
-	return 0;
-}
-
-blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
-{
-	int remapped = remap_track( track );
-	if ( (unsigned) remapped < track_times.size() )
-	{
-		long length = (int32_t) GET_LE32( track_times [remapped] );
-		if ( length > 0 )
-			out->length = length;
-	}
-	if ( (unsigned) remapped < track_names.size() )
-		Gme_File::copy_field_( out->song, track_names [remapped] );
-
-	GME_COPY_FIELD( info, out, game );
-	GME_COPY_FIELD( info, out, author );
-	GME_COPY_FIELD( info, out, copyright );
-	GME_COPY_FIELD( info, out, dumper );
-	return 0;
-}
-
-Nsfe_Emu::Nsfe_Emu()
-{
-	loading = false;
-	set_type( gme_nsfe_type );
-}
-
-Nsfe_Emu::~Nsfe_Emu() { }
-
-void Nsfe_Emu::unload()
-{
-	if ( !loading )
-		info.unload(); // TODO: extremely hacky!
-	Nsf_Emu::unload();
-}
-
-blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
-{
-	return info.track_info_( out, track );
-}
-
-struct Nsfe_File : Gme_Info_
-{
-	Nsfe_Info info;
-
-	Nsfe_File() { set_type( gme_nsfe_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		RETURN_ERR( info.load( in, 0 ) );
-		info.disable_playlist( false );
-		set_track_count( info.info.track_count );
-		return 0;
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int track ) const
-	{
-		return info.track_info_( out, track );
-	}
-};
-
-static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
-static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
-
-static gme_type_t_ const gme_nsfe_type_ = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
-gme_type_t const gme_nsfe_type = &gme_nsfe_type_;
-
-
-blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
-{
-	if ( loading )
-		return Nsf_Emu::load_( in );
-
-	// TODO: this hacky recursion-avoidance could have subtle problems
-	loading = true;
-	blargg_err_t err = info.load( in, this );
-	loading = false;
-	disable_playlist( false );
-	return err;
-}
-
-void Nsfe_Emu::disable_playlist( bool b )
-{
-	info.disable_playlist( b );
-	set_track_count( info.info.track_count );
-}
-
-void Nsfe_Emu::clear_playlist_()
-{
-	disable_playlist();
-	Nsf_Emu::clear_playlist_();
-}
-
-blargg_err_t Nsfe_Emu::start_track_( int track )
-{
-	return Nsf_Emu::start_track_( info.remap_track( track ) );
-}
diff --git a/src/console/Sap_Apu.cc b/src/console/Sap_Apu.cc
new file mode 100644
index 000000000000..064f487c72c0
--- /dev/null
+++ b/src/console/Sap_Apu.cc
@@ -0,0 +1,334 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Sap_Apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const max_frequency = 12000; // pure waves above this frequency are silenced
+
+static void gen_poly( blargg_ulong mask, int count, byte* out )
+{
+	blargg_ulong n = 1;
+	do
+	{
+		int bits = 0;
+		int b = 0;
+		do
+		{
+			// implemented using "Galios configuration"
+			bits |= (n & 1) << b;
+			n = (n >> 1) ^ (mask & -(n & 1));
+		}
+		while ( b++ < 7 );
+		*out++ = bits;
+	}
+	while ( --count );
+}
+
+// poly5
+int const poly5_len = (1 <<  5) - 1;
+blargg_ulong const poly5_mask = (1UL << poly5_len) - 1;
+blargg_ulong const poly5 = 0x167C6EA1;
+
+inline blargg_ulong run_poly5( blargg_ulong in, int shift )
+{
+	return (in << shift & poly5_mask) | (in >> (poly5_len - shift));
+}
+
+#define POLY_MASK( width, tap1, tap2 ) \
+	((1UL << (width - 1 - tap1)) | (1UL << (width - 1 - tap2)))
+
+Sap_Apu_Impl::Sap_Apu_Impl()
+{
+	gen_poly( POLY_MASK(  4, 1, 0 ), sizeof poly4,  poly4  );
+	gen_poly( POLY_MASK(  9, 5, 0 ), sizeof poly9,  poly9  );
+	gen_poly( POLY_MASK( 17, 5, 0 ), sizeof poly17, poly17 );
+
+	if ( 0 ) // comment out to recauculate poly5 constant
+	{
+		byte poly5 [4];
+		gen_poly( POLY_MASK(  5, 2, 0 ), sizeof poly5,  poly5  );
+		blargg_ulong n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L +
+				poly5 [1] * 0x100L + poly5 [0];
+		blargg_ulong rev = n & 1;
+		for ( int i = 1; i < poly5_len; i++ )
+			rev |= (n >> i & 1) << (poly5_len - i);
+		debug_printf( "poly5: 0x%08lX\n", rev );
+	}
+}
+
+Sap_Apu::Sap_Apu()
+{
+	impl = 0;
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, 0 );
+}
+
+void Sap_Apu::reset( Sap_Apu_Impl* new_impl )
+{
+	impl      = new_impl;
+	last_time = 0;
+	poly5_pos = 0;
+	poly4_pos = 0;
+	polym_pos = 0;
+	control   = 0;
+
+	for ( int i = 0; i < osc_count; i++ )
+		memset( &oscs [i], 0, offsetof (osc_t,output) );
+}
+
+inline void Sap_Apu::calc_periods()
+{
+	 // 15/64 kHz clock
+	int divider = 28;
+	if ( this->control & 1 )
+		divider = 114;
+
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		osc_t* const osc = &oscs [i];
+
+		int const osc_reload = osc->regs [0]; // cache
+		blargg_long period = (osc_reload + 1) * divider;
+		static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 };
+		if ( this->control & fast_bits [i] )
+		{
+			period = osc_reload + 4;
+			if ( i & 1 )
+			{
+				period = osc_reload * 0x100L + osc [-1].regs [0] + 7;
+				if ( !(this->control & fast_bits [i - 1]) )
+					period = (period - 6) * divider;
+
+				if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
+					debug_printf( "Use of slave channel in 16-bit mode not supported\n" );
+			}
+		}
+		osc->period = period;
+	}
+}
+
+void Sap_Apu::run_until( blip_time_t end_time )
+{
+	calc_periods();
+	Sap_Apu_Impl* const impl = this->impl; // cache
+
+	// 17/9-bit poly selection
+	byte const* polym = impl->poly17;
+	int polym_len = poly17_len;
+	if ( this->control & 0x80 )
+	{
+		polym_len = poly9_len;
+		polym = impl->poly9;
+	}
+	polym_pos %= polym_len;
+
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		osc_t* const osc = &oscs [i];
+		blip_time_t time = last_time + osc->delay;
+		blip_time_t const period = osc->period;
+
+		// output
+		Blip_Buffer* output = osc->output;
+		if ( output )
+		{
+			output->set_modified();
+
+			int const osc_control = osc->regs [1]; // cache
+			int volume = (osc_control & 0x0F) * 2;
+			if ( !volume || osc_control & 0x10 || // silent, DAC mode, or inaudible frequency
+					((osc_control & 0xA0) == 0xA0 && period < 1789773 / 2 / max_frequency) )
+			{
+				if ( !(osc_control & 0x10) )
+					volume >>= 1; // inaudible frequency = half volume
+
+				int delta = volume - osc->last_amp;
+				if ( delta )
+				{
+					osc->last_amp = volume;
+					impl->synth.offset( last_time, delta, output );
+				}
+
+				// TODO: doesn't maintain high pass flip-flop (very minor issue)
+			}
+			else
+			{
+				// high pass
+				static byte const hipass_bits [osc_count] = { 1 << 2, 1 << 1, 0, 0 };
+				blip_time_t period2 = 0; // unused if no high pass
+				blip_time_t time2 = end_time;
+				if ( this->control & hipass_bits [i] )
+				{
+					period2 = osc [2].period;
+					time2 = last_time + osc [2].delay;
+					if ( osc->invert )
+					{
+						// trick inner wave loop into inverting output
+						osc->last_amp -= volume;
+						volume = -volume;
+					}
+				}
+
+				if ( time < end_time || time2 < end_time )
+				{
+					// poly source
+					static byte const poly1 [] = { 0x55, 0x55 }; // square wave
+					byte const* poly = poly1;
+					int poly_len = 8 * sizeof poly1; // can be just 2 bits, but this is faster
+					int poly_pos = osc->phase & 1;
+					int poly_inc = 1;
+					if ( !(osc_control & 0x20) )
+					{
+						poly     = polym;
+						poly_len = polym_len;
+						poly_pos = polym_pos;
+						if ( osc_control & 0x40 )
+						{
+							poly     = impl->poly4;
+							poly_len = poly4_len;
+							poly_pos = poly4_pos;
+						}
+						poly_inc = period % poly_len;
+						poly_pos = (poly_pos + osc->delay) % poly_len;
+					}
+					poly_inc -= poly_len; // allows more optimized inner loop below
+
+					// square/poly5 wave
+					blargg_ulong wave = poly5;
+					check( poly5 & 1 ); // low bit is set for pure wave
+					int poly5_inc = 0;
+					if ( !(osc_control & 0x80) )
+					{
+						wave = run_poly5( wave, (osc->delay + poly5_pos) % poly5_len );
+						poly5_inc = period % poly5_len;
+					}
+
+					// Run wave and high pass interleved with each catching up to the other.
+					// Disabled high pass has no performance effect since inner wave loop
+					// makes no compromise for high pass, and only runs once in that case.
+					int osc_last_amp = osc->last_amp;
+					do
+					{
+						// run high pass
+						if ( time2 < time )
+						{
+							int delta = -osc_last_amp;
+							if ( volume < 0 )
+								delta += volume;
+							if ( delta )
+							{
+								osc_last_amp += delta - volume;
+								volume = -volume;
+								impl->synth.offset( time2, delta, output );
+							}
+						}
+						while ( time2 <= time ) // must advance *past* time to avoid hang
+							time2 += period2;
+
+						// run wave
+						blip_time_t end = end_time;
+						if ( end > time2 )
+							end = time2;
+						while ( time < end )
+						{
+							if ( wave & 1 )
+							{
+								int amp = volume & -(poly [poly_pos >> 3] >> (poly_pos & 7) & 1);
+								if ( (poly_pos += poly_inc) < 0 )
+									poly_pos += poly_len;
+								int delta = amp - osc_last_amp;
+								if ( delta )
+								{
+									osc_last_amp = amp;
+									impl->synth.offset( time, delta, output );
+								}
+							}
+							wave = run_poly5( wave, poly5_inc );
+							time += period;
+						}
+					}
+					while ( time < end_time || time2 < end_time );
+
+					osc->phase = poly_pos;
+					osc->last_amp = osc_last_amp;
+				}
+
+				osc->invert = 0;
+				if ( volume < 0 )
+				{
+					// undo inversion trickery
+					osc->last_amp -= volume;
+					osc->invert = 1;
+				}
+			}
+		}
+
+		// maintain divider
+		blip_time_t remain = end_time - time;
+		if ( remain > 0 )
+		{
+			blargg_long count = (remain + period - 1) / period;
+			osc->phase ^= count;
+			time += count * period;
+		}
+		osc->delay = time - end_time;
+	}
+
+	// advance polies
+	blip_time_t duration = end_time - last_time;
+	last_time = end_time;
+	poly4_pos = (poly4_pos + duration) % poly4_len;
+	poly5_pos = (poly5_pos + duration) % poly5_len;
+	polym_pos += duration; // will get %'d on next call
+}
+
+void Sap_Apu::write_data( blip_time_t time, unsigned addr, int data )
+{
+	run_until( time );
+	int i = (addr ^ 0xD200) >> 1;
+	if ( i < osc_count )
+	{
+		oscs [i].regs [addr & 1] = data;
+	}
+	else if ( addr == 0xD208 )
+	{
+		control = data;
+	}
+	else if ( addr == 0xD209 )
+	{
+		oscs [0].delay = 0;
+		oscs [1].delay = 0;
+		oscs [2].delay = 0;
+		oscs [3].delay = 0;
+	}
+	/*
+	// TODO: are polynomials reset in this case?
+	else if ( addr == 0xD20F )
+	{
+		if ( (data & 3) == 0 )
+			polym_pos = 0;
+	}
+	*/
+}
+
+void Sap_Apu::end_frame( blip_time_t end_time )
+{
+	if ( end_time > last_time )
+		run_until( end_time );
+
+	last_time -= end_time;
+}
diff --git a/src/console/Sap_Apu.cxx b/src/console/Sap_Apu.cxx
deleted file mode 100644
index 064f487c72c0..000000000000
--- a/src/console/Sap_Apu.cxx
+++ /dev/null
@@ -1,334 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const max_frequency = 12000; // pure waves above this frequency are silenced
-
-static void gen_poly( blargg_ulong mask, int count, byte* out )
-{
-	blargg_ulong n = 1;
-	do
-	{
-		int bits = 0;
-		int b = 0;
-		do
-		{
-			// implemented using "Galios configuration"
-			bits |= (n & 1) << b;
-			n = (n >> 1) ^ (mask & -(n & 1));
-		}
-		while ( b++ < 7 );
-		*out++ = bits;
-	}
-	while ( --count );
-}
-
-// poly5
-int const poly5_len = (1 <<  5) - 1;
-blargg_ulong const poly5_mask = (1UL << poly5_len) - 1;
-blargg_ulong const poly5 = 0x167C6EA1;
-
-inline blargg_ulong run_poly5( blargg_ulong in, int shift )
-{
-	return (in << shift & poly5_mask) | (in >> (poly5_len - shift));
-}
-
-#define POLY_MASK( width, tap1, tap2 ) \
-	((1UL << (width - 1 - tap1)) | (1UL << (width - 1 - tap2)))
-
-Sap_Apu_Impl::Sap_Apu_Impl()
-{
-	gen_poly( POLY_MASK(  4, 1, 0 ), sizeof poly4,  poly4  );
-	gen_poly( POLY_MASK(  9, 5, 0 ), sizeof poly9,  poly9  );
-	gen_poly( POLY_MASK( 17, 5, 0 ), sizeof poly17, poly17 );
-
-	if ( 0 ) // comment out to recauculate poly5 constant
-	{
-		byte poly5 [4];
-		gen_poly( POLY_MASK(  5, 2, 0 ), sizeof poly5,  poly5  );
-		blargg_ulong n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L +
-				poly5 [1] * 0x100L + poly5 [0];
-		blargg_ulong rev = n & 1;
-		for ( int i = 1; i < poly5_len; i++ )
-			rev |= (n >> i & 1) << (poly5_len - i);
-		debug_printf( "poly5: 0x%08lX\n", rev );
-	}
-}
-
-Sap_Apu::Sap_Apu()
-{
-	impl = 0;
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, 0 );
-}
-
-void Sap_Apu::reset( Sap_Apu_Impl* new_impl )
-{
-	impl      = new_impl;
-	last_time = 0;
-	poly5_pos = 0;
-	poly4_pos = 0;
-	polym_pos = 0;
-	control   = 0;
-
-	for ( int i = 0; i < osc_count; i++ )
-		memset( &oscs [i], 0, offsetof (osc_t,output) );
-}
-
-inline void Sap_Apu::calc_periods()
-{
-	 // 15/64 kHz clock
-	int divider = 28;
-	if ( this->control & 1 )
-		divider = 114;
-
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		osc_t* const osc = &oscs [i];
-
-		int const osc_reload = osc->regs [0]; // cache
-		blargg_long period = (osc_reload + 1) * divider;
-		static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 };
-		if ( this->control & fast_bits [i] )
-		{
-			period = osc_reload + 4;
-			if ( i & 1 )
-			{
-				period = osc_reload * 0x100L + osc [-1].regs [0] + 7;
-				if ( !(this->control & fast_bits [i - 1]) )
-					period = (period - 6) * divider;
-
-				if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
-					debug_printf( "Use of slave channel in 16-bit mode not supported\n" );
-			}
-		}
-		osc->period = period;
-	}
-}
-
-void Sap_Apu::run_until( blip_time_t end_time )
-{
-	calc_periods();
-	Sap_Apu_Impl* const impl = this->impl; // cache
-
-	// 17/9-bit poly selection
-	byte const* polym = impl->poly17;
-	int polym_len = poly17_len;
-	if ( this->control & 0x80 )
-	{
-		polym_len = poly9_len;
-		polym = impl->poly9;
-	}
-	polym_pos %= polym_len;
-
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		osc_t* const osc = &oscs [i];
-		blip_time_t time = last_time + osc->delay;
-		blip_time_t const period = osc->period;
-
-		// output
-		Blip_Buffer* output = osc->output;
-		if ( output )
-		{
-			output->set_modified();
-
-			int const osc_control = osc->regs [1]; // cache
-			int volume = (osc_control & 0x0F) * 2;
-			if ( !volume || osc_control & 0x10 || // silent, DAC mode, or inaudible frequency
-					((osc_control & 0xA0) == 0xA0 && period < 1789773 / 2 / max_frequency) )
-			{
-				if ( !(osc_control & 0x10) )
-					volume >>= 1; // inaudible frequency = half volume
-
-				int delta = volume - osc->last_amp;
-				if ( delta )
-				{
-					osc->last_amp = volume;
-					impl->synth.offset( last_time, delta, output );
-				}
-
-				// TODO: doesn't maintain high pass flip-flop (very minor issue)
-			}
-			else
-			{
-				// high pass
-				static byte const hipass_bits [osc_count] = { 1 << 2, 1 << 1, 0, 0 };
-				blip_time_t period2 = 0; // unused if no high pass
-				blip_time_t time2 = end_time;
-				if ( this->control & hipass_bits [i] )
-				{
-					period2 = osc [2].period;
-					time2 = last_time + osc [2].delay;
-					if ( osc->invert )
-					{
-						// trick inner wave loop into inverting output
-						osc->last_amp -= volume;
-						volume = -volume;
-					}
-				}
-
-				if ( time < end_time || time2 < end_time )
-				{
-					// poly source
-					static byte const poly1 [] = { 0x55, 0x55 }; // square wave
-					byte const* poly = poly1;
-					int poly_len = 8 * sizeof poly1; // can be just 2 bits, but this is faster
-					int poly_pos = osc->phase & 1;
-					int poly_inc = 1;
-					if ( !(osc_control & 0x20) )
-					{
-						poly     = polym;
-						poly_len = polym_len;
-						poly_pos = polym_pos;
-						if ( osc_control & 0x40 )
-						{
-							poly     = impl->poly4;
-							poly_len = poly4_len;
-							poly_pos = poly4_pos;
-						}
-						poly_inc = period % poly_len;
-						poly_pos = (poly_pos + osc->delay) % poly_len;
-					}
-					poly_inc -= poly_len; // allows more optimized inner loop below
-
-					// square/poly5 wave
-					blargg_ulong wave = poly5;
-					check( poly5 & 1 ); // low bit is set for pure wave
-					int poly5_inc = 0;
-					if ( !(osc_control & 0x80) )
-					{
-						wave = run_poly5( wave, (osc->delay + poly5_pos) % poly5_len );
-						poly5_inc = period % poly5_len;
-					}
-
-					// Run wave and high pass interleved with each catching up to the other.
-					// Disabled high pass has no performance effect since inner wave loop
-					// makes no compromise for high pass, and only runs once in that case.
-					int osc_last_amp = osc->last_amp;
-					do
-					{
-						// run high pass
-						if ( time2 < time )
-						{
-							int delta = -osc_last_amp;
-							if ( volume < 0 )
-								delta += volume;
-							if ( delta )
-							{
-								osc_last_amp += delta - volume;
-								volume = -volume;
-								impl->synth.offset( time2, delta, output );
-							}
-						}
-						while ( time2 <= time ) // must advance *past* time to avoid hang
-							time2 += period2;
-
-						// run wave
-						blip_time_t end = end_time;
-						if ( end > time2 )
-							end = time2;
-						while ( time < end )
-						{
-							if ( wave & 1 )
-							{
-								int amp = volume & -(poly [poly_pos >> 3] >> (poly_pos & 7) & 1);
-								if ( (poly_pos += poly_inc) < 0 )
-									poly_pos += poly_len;
-								int delta = amp - osc_last_amp;
-								if ( delta )
-								{
-									osc_last_amp = amp;
-									impl->synth.offset( time, delta, output );
-								}
-							}
-							wave = run_poly5( wave, poly5_inc );
-							time += period;
-						}
-					}
-					while ( time < end_time || time2 < end_time );
-
-					osc->phase = poly_pos;
-					osc->last_amp = osc_last_amp;
-				}
-
-				osc->invert = 0;
-				if ( volume < 0 )
-				{
-					// undo inversion trickery
-					osc->last_amp -= volume;
-					osc->invert = 1;
-				}
-			}
-		}
-
-		// maintain divider
-		blip_time_t remain = end_time - time;
-		if ( remain > 0 )
-		{
-			blargg_long count = (remain + period - 1) / period;
-			osc->phase ^= count;
-			time += count * period;
-		}
-		osc->delay = time - end_time;
-	}
-
-	// advance polies
-	blip_time_t duration = end_time - last_time;
-	last_time = end_time;
-	poly4_pos = (poly4_pos + duration) % poly4_len;
-	poly5_pos = (poly5_pos + duration) % poly5_len;
-	polym_pos += duration; // will get %'d on next call
-}
-
-void Sap_Apu::write_data( blip_time_t time, unsigned addr, int data )
-{
-	run_until( time );
-	int i = (addr ^ 0xD200) >> 1;
-	if ( i < osc_count )
-	{
-		oscs [i].regs [addr & 1] = data;
-	}
-	else if ( addr == 0xD208 )
-	{
-		control = data;
-	}
-	else if ( addr == 0xD209 )
-	{
-		oscs [0].delay = 0;
-		oscs [1].delay = 0;
-		oscs [2].delay = 0;
-		oscs [3].delay = 0;
-	}
-	/*
-	// TODO: are polynomials reset in this case?
-	else if ( addr == 0xD20F )
-	{
-		if ( (data & 3) == 0 )
-			polym_pos = 0;
-	}
-	*/
-}
-
-void Sap_Apu::end_frame( blip_time_t end_time )
-{
-	if ( end_time > last_time )
-		run_until( end_time );
-
-	last_time -= end_time;
-}
diff --git a/src/console/Sap_Cpu.cc b/src/console/Sap_Cpu.cc
new file mode 100644
index 000000000000..7528de1b36a9
--- /dev/null
+++ b/src/console/Sap_Cpu.cc
@@ -0,0 +1,1009 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Sap_Cpu.h"
+
+#include <limits.h>
+#include "blargg_endian.h"
+
+//#include "nes_cpu_log.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#define FLUSH_TIME()    (void) (s.time = s_time)
+#define CACHE_TIME()    (void) (s_time = s.time)
+
+#include "sap_cpu_io.h"
+
+#ifndef CPU_DONE
+	#define CPU_DONE( cpu, time, result_out )   { result_out = -1; }
+#endif
+
+#include "blargg_source.h"
+
+int const st_n = 0x80;
+int const st_v = 0x40;
+int const st_r = 0x20;
+int const st_b = 0x10;
+int const st_d = 0x08;
+int const st_i = 0x04;
+int const st_z = 0x02;
+int const st_c = 0x01;
+
+void Sap_Cpu::reset( void* new_mem )
+{
+	check( state == &state_ );
+	state = &state_;
+	mem = (uint8_t*) new_mem;
+	r.status = st_i;
+	r.sp = 0xFF;
+	r.pc = 0;
+	r.a  = 0;
+	r.x  = 0;
+	r.y  = 0;
+	state_.time = 0;
+	state_.base = 0;
+	irq_time_ = future_sap_time;
+	end_time_ = future_sap_time;
+}
+
+#define TIME                    (s_time + s.base)
+#define READ( addr )            CPU_READ( this, (addr), TIME )
+#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), TIME );}
+#define READ_LOW( addr )        (mem [int (addr)])
+#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
+#define READ_PROG( addr )       (READ_LOW( addr ))
+
+#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
+#define GET_SP()        ((sp - 1) & 0xFF)
+#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
+
+// even on x86, using short and unsigned char was slower
+typedef int         fint16;
+typedef unsigned    fuint16;
+typedef unsigned    fuint8;
+typedef blargg_long fint32;
+
+bool Sap_Cpu::run( sap_time_t end_time )
+{
+	bool illegal_encountered = false;
+	set_end_time( end_time );
+	state_t s = this->state_;
+	this->state = &s;
+	fint32 s_time = s.time;
+	uint8_t* const mem = this->mem; // cache
+
+	// registers
+	fuint16 pc = r.pc;
+	fuint8 a = r.a;
+	fuint8 x = r.x;
+	fuint8 y = r.y;
+	fuint16 sp;
+	SET_SP( r.sp );
+
+	// status flags
+	#define IS_NEG (nz & 0x8080)
+
+	#define CALC_STATUS( out ) do {\
+		out = status & (st_v | st_d | st_i);\
+		out |= ((nz >> 8) | nz) & st_n;\
+		out |= c >> 8 & st_c;\
+		if ( !(nz & 0xFF) ) out |= st_z;\
+	} while ( 0 )
+
+	#define SET_STATUS( in ) do {\
+		status = in & (st_v | st_d | st_i);\
+		nz = in << 8;\
+		c = nz;\
+		nz |= ~in & st_z;\
+	} while ( 0 )
+
+	fuint8 status;
+	fuint16 c;  // carry set if (c & 0x100) != 0
+	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
+	{
+		fuint8 temp = r.status;
+		SET_STATUS( temp );
+	}
+
+	goto loop;
+dec_clock_loop:
+	s_time--;
+loop:
+
+	#ifndef NDEBUG
+	{
+		sap_time_t correct = end_time_;
+		if ( !(status & st_i) && correct > irq_time_ )
+			correct = irq_time_;
+		check( s.base == correct );
+	}
+	#endif
+
+	check( (unsigned) GET_SP() < 0x100 );
+	check( (unsigned) a < 0x100 );
+	check( (unsigned) x < 0x100 );
+	check( (unsigned) y < 0x100 );
+
+	fuint8 opcode = mem [pc];
+	pc++;
+	uint8_t const* instr = mem + pc;
+
+	static uint8_t const clock_table [256] =
+	{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+		0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
+		6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
+		6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
+		6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
+		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
+		3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
+		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
+		3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
+		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
+		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
+		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
+	}; // 0x00 was 7
+
+	fuint16 data;
+	data = clock_table [opcode];
+	if ( (s_time += data) >= 0 )
+		goto possibly_out_of_time;
+almost_out_of_time:
+
+	data = *instr;
+
+	#ifdef NES_CPU_LOG_H
+		nes_cpu_log( "cpu_log", pc - 1, opcode, instr [0], instr [1] );
+	#endif
+
+	switch ( opcode )
+	{
+possibly_out_of_time:
+		if ( s_time < (int) data )
+			goto almost_out_of_time;
+		s_time -= data;
+		goto out_of_time;
+
+// Macros
+
+#define GET_MSB()   (instr [1])
+#define ADD_PAGE()  (pc++, data += 0x100 * GET_MSB())
+#define GET_ADDR()  GET_LE16( instr )
+
+#define NO_PAGE_CROSSING( lsb )
+#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
+
+#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
+
+#define IND_Y( cross, out ) {\
+		fuint16 temp = READ_LOW( data ) + y;\
+		out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
+		cross( temp );\
+	}
+
+#define IND_X( out ) {\
+		fuint16 temp = data + x;\
+		out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
+	}
+
+#define ARITH_ADDR_MODES( op )\
+case op - 0x04: /* (ind,x) */\
+	IND_X( data )\
+	goto ptr##op;\
+case op + 0x0C: /* (ind),y */\
+	IND_Y( HANDLE_PAGE_CROSSING, data )\
+	goto ptr##op;\
+case op + 0x10: /* zp,X */\
+	data = uint8_t (data + x);\
+case op + 0x00: /* zp */\
+	data = READ_LOW( data );\
+	goto imm##op;\
+case op + 0x14: /* abs,Y */\
+	data += y;\
+	goto ind##op;\
+case op + 0x18: /* abs,X */\
+	data += x;\
+ind##op:\
+	HANDLE_PAGE_CROSSING( data );\
+case op + 0x08: /* abs */\
+	ADD_PAGE();\
+ptr##op:\
+	FLUSH_TIME();\
+	data = READ( data );\
+	CACHE_TIME();\
+case op + 0x04: /* imm */\
+imm##op:
+
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define BRANCH( cond )\
+{\
+	fint16 offset = (int8_t) data;\
+	fuint16 extra_clock = (++pc & 0xFF) + offset;\
+	if ( !(cond) ) goto dec_clock_loop;\
+	pc += offset;\
+	s_time += extra_clock >> 8 & 1;\
+	goto loop;\
+}
+
+// Often-Used
+
+	case 0xB5: // LDA zp,x
+		a = nz = READ_LOW( uint8_t (data + x) );
+		pc++;
+		goto loop;
+
+	case 0xA5: // LDA zp
+		a = nz = READ_LOW( data );
+		pc++;
+		goto loop;
+
+	case 0xD0: // BNE
+		BRANCH( (uint8_t) nz );
+
+	case 0x20: { // JSR
+		fuint16 temp = pc + 1;
+		pc = GET_ADDR();
+		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
+		sp = (sp - 2) | 0x100;
+		WRITE_LOW( sp, temp );
+		goto loop;
+	}
+
+	case 0x4C: // JMP abs
+		pc = GET_ADDR();
+		goto loop;
+
+	case 0xE8: // INX
+		INC_DEC_XY( x, 1 )
+
+	case 0x10: // BPL
+		BRANCH( !IS_NEG )
+
+	ARITH_ADDR_MODES( 0xC5 ) // CMP
+		nz = a - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	case 0x30: // BMI
+		BRANCH( IS_NEG )
+
+	case 0xF0: // BEQ
+		BRANCH( !(uint8_t) nz );
+
+	case 0x95: // STA zp,x
+		data = uint8_t (data + x);
+	case 0x85: // STA zp
+		pc++;
+		WRITE_LOW( data, a );
+		goto loop;
+
+	case 0xC8: // INY
+		INC_DEC_XY( y, 1 )
+
+	case 0xA8: // TAY
+		y  = a;
+		nz = a;
+		goto loop;
+
+	case 0x98: // TYA
+		a  = y;
+		nz = y;
+		goto loop;
+
+	case 0xAD:{// LDA abs
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		nz = READ( addr );
+		a = nz;
+		goto loop;
+	}
+
+	case 0x60: // RTS
+		pc = 1 + READ_LOW( sp );
+		pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
+		sp = (sp - 0xFE) | 0x100;
+		goto loop;
+
+	{
+		fuint16 addr;
+
+	case 0x99: // STA abs,Y
+		addr = y + GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+		goto sta_ptr;
+
+	case 0x8D: // STA abs
+		addr = GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+		goto sta_ptr;
+
+	case 0x9D: // STA abs,X (slightly more common than STA abs)
+		addr = x + GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, a );
+			goto loop;
+		}
+	sta_ptr:
+		FLUSH_TIME();
+		WRITE( addr, a );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x91: // STA (ind),Y
+		IND_Y( NO_PAGE_CROSSING, addr )
+		pc++;
+		goto sta_ptr;
+
+	case 0x81: // STA (ind,X)
+		IND_X( addr )
+		pc++;
+		goto sta_ptr;
+
+	}
+
+	case 0xA9: // LDA #imm
+		pc++;
+		a  = data;
+		nz = data;
+		goto loop;
+
+	// common read instructions
+	{
+		fuint16 addr;
+
+	case 0xA1: // LDA (ind,X)
+		IND_X( addr )
+		pc++;
+		goto a_nz_read_addr;
+
+	case 0xB1:// LDA (ind),Y
+		addr = READ_LOW( data ) + y;
+		HANDLE_PAGE_CROSSING( addr );
+		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
+		pc++;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+		goto a_nz_read_addr;
+
+	case 0xB9: // LDA abs,Y
+		HANDLE_PAGE_CROSSING( data + y );
+		addr = GET_ADDR() + y;
+		pc += 2;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+		goto a_nz_read_addr;
+
+	case 0xBD: // LDA abs,X
+		HANDLE_PAGE_CROSSING( data + x );
+		addr = GET_ADDR() + x;
+		pc += 2;
+		a = nz = READ_PROG( addr );
+		if ( (addr ^ 0x8000) <= 0x9FFF )
+			goto loop;
+	a_nz_read_addr:
+		FLUSH_TIME();
+		a = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+
+	}
+
+// Branch
+
+	case 0x50: // BVC
+		BRANCH( !(status & st_v) )
+
+	case 0x70: // BVS
+		BRANCH( status & st_v )
+
+	case 0xB0: // BCS
+		BRANCH( c & 0x100 )
+
+	case 0x90: // BCC
+		BRANCH( !(c & 0x100) )
+
+// Load/store
+
+	case 0x94: // STY zp,x
+		data = uint8_t (data + x);
+	case 0x84: // STY zp
+		pc++;
+		WRITE_LOW( data, y );
+		goto loop;
+
+	case 0x96: // STX zp,y
+		data = uint8_t (data + y);
+	case 0x86: // STX zp
+		pc++;
+		WRITE_LOW( data, x );
+		goto loop;
+
+	case 0xB6: // LDX zp,y
+		data = uint8_t (data + y);
+	case 0xA6: // LDX zp
+		data = READ_LOW( data );
+	case 0xA2: // LDX #imm
+		pc++;
+		x = data;
+		nz = data;
+		goto loop;
+
+	case 0xB4: // LDY zp,x
+		data = uint8_t (data + x);
+	case 0xA4: // LDY zp
+		data = READ_LOW( data );
+	case 0xA0: // LDY #imm
+		pc++;
+		y = data;
+		nz = data;
+		goto loop;
+
+	case 0xBC: // LDY abs,X
+		data += x;
+		HANDLE_PAGE_CROSSING( data );
+	case 0xAC:{// LDY abs
+		unsigned addr = data + 0x100 * GET_MSB();
+		pc += 2;
+		FLUSH_TIME();
+		y = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	case 0xBE: // LDX abs,y
+		data += y;
+		HANDLE_PAGE_CROSSING( data );
+	case 0xAE:{// LDX abs
+		unsigned addr = data + 0x100 * GET_MSB();
+		pc += 2;
+		FLUSH_TIME();
+		x = nz = READ( addr );
+		CACHE_TIME();
+		goto loop;
+	}
+
+	{
+		fuint8 temp;
+	case 0x8C: // STY abs
+		temp = y;
+		goto store_abs;
+
+	case 0x8E: // STX abs
+		temp = x;
+	store_abs:
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		if ( addr <= 0x7FF )
+		{
+			WRITE_LOW( addr, temp );
+			goto loop;
+		}
+		FLUSH_TIME();
+		WRITE( addr, temp );
+		CACHE_TIME();
+		goto loop;
+	}
+
+// Compare
+
+	case 0xEC:{// CPX abs
+		unsigned addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpx_data;
+	}
+
+	case 0xE4: // CPX zp
+		data = READ_LOW( data );
+	case 0xE0: // CPX #imm
+	cpx_data:
+		nz = x - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+	case 0xCC:{// CPY abs
+		unsigned addr = GET_ADDR();
+		pc++;
+		FLUSH_TIME();
+		data = READ( addr );
+		CACHE_TIME();
+		goto cpy_data;
+	}
+
+	case 0xC4: // CPY zp
+		data = READ_LOW( data );
+	case 0xC0: // CPY #imm
+	cpy_data:
+		nz = y - data;
+		pc++;
+		c = ~nz;
+		nz &= 0xFF;
+		goto loop;
+
+// Logical
+
+	ARITH_ADDR_MODES( 0x25 ) // AND
+		nz = (a &= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x45 ) // EOR
+		nz = (a ^= data);
+		pc++;
+		goto loop;
+
+	ARITH_ADDR_MODES( 0x05 ) // ORA
+		nz = (a |= data);
+		pc++;
+		goto loop;
+
+	case 0x2C:{// BIT abs
+		unsigned addr = GET_ADDR();
+		pc += 2;
+		status &= ~st_v;
+		nz = READ( addr );
+		status |= nz & st_v;
+		if ( a & nz )
+			goto loop;
+		nz <<= 8; // result must be zero, even if N bit is set
+		goto loop;
+	}
+
+	case 0x24: // BIT zp
+		nz = READ_LOW( data );
+		pc++;
+		status &= ~st_v;
+		status |= nz & st_v;
+		if ( a & nz )
+			goto loop;
+		nz <<= 8; // result must be zero, even if N bit is set
+		goto loop;
+
+// Add/subtract
+
+	ARITH_ADDR_MODES( 0xE5 ) // SBC
+	case 0xEB: // unofficial equivalent
+		data ^= 0xFF;
+		goto adc_imm;
+
+	ARITH_ADDR_MODES( 0x65 ) // ADC
+	adc_imm: {
+		check( !(status & st_d) );
+		fint16 carry = c >> 8 & 1;
+		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
+		status &= ~st_v;
+		status |= ov >> 2 & 0x40;
+		c = nz = a + data + carry;
+		pc++;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+// Shift/rotate
+
+	case 0x4A: // LSR A
+		c = 0;
+	case 0x6A: // ROR A
+		nz = c >> 1 & 0x80;
+		c = a << 8;
+		nz |= a >> 1;
+		a = nz;
+		goto loop;
+
+	case 0x0A: // ASL A
+		nz = a << 1;
+		c = nz;
+		a = (uint8_t) nz;
+		goto loop;
+
+	case 0x2A: { // ROL A
+		nz = a << 1;
+		fint16 temp = c >> 8 & 1;
+		c = nz;
+		nz |= temp;
+		a = (uint8_t) nz;
+		goto loop;
+	}
+
+	case 0x5E: // LSR abs,X
+		data += x;
+	case 0x4E: // LSR abs
+		c = 0;
+	case 0x6E: // ROR abs
+	ror_abs: {
+		ADD_PAGE();
+		FLUSH_TIME();
+		int temp = READ( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto rotate_common;
+	}
+
+	case 0x3E: // ROL abs,X
+		data += x;
+		goto rol_abs;
+
+	case 0x1E: // ASL abs,X
+		data += x;
+	case 0x0E: // ASL abs
+		c = 0;
+	case 0x2E: // ROL abs
+	rol_abs:
+		ADD_PAGE();
+		nz = c >> 8 & 1;
+		FLUSH_TIME();
+		nz |= (c = READ( data ) << 1);
+	rotate_common:
+		pc++;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+	case 0x7E: // ROR abs,X
+		data += x;
+		goto ror_abs;
+
+	case 0x76: // ROR zp,x
+		data = uint8_t (data + x);
+		goto ror_zp;
+
+	case 0x56: // LSR zp,x
+		data = uint8_t (data + x);
+	case 0x46: // LSR zp
+		c = 0;
+	case 0x66: // ROR zp
+	ror_zp: {
+		int temp = READ_LOW( data );
+		nz = (c >> 1 & 0x80) | (temp >> 1);
+		c = temp << 8;
+		goto write_nz_zp;
+	}
+
+	case 0x36: // ROL zp,x
+		data = uint8_t (data + x);
+		goto rol_zp;
+
+	case 0x16: // ASL zp,x
+		data = uint8_t (data + x);
+	case 0x06: // ASL zp
+		c = 0;
+	case 0x26: // ROL zp
+	rol_zp:
+		nz = c >> 8 & 1;
+		nz |= (c = READ_LOW( data ) << 1);
+		goto write_nz_zp;
+
+// Increment/decrement
+
+	case 0xCA: // DEX
+		INC_DEC_XY( x, -1 )
+
+	case 0x88: // DEY
+		INC_DEC_XY( y, -1 )
+
+	case 0xF6: // INC zp,x
+		data = uint8_t (data + x);
+	case 0xE6: // INC zp
+		nz = 1;
+		goto add_nz_zp;
+
+	case 0xD6: // DEC zp,x
+		data = uint8_t (data + x);
+	case 0xC6: // DEC zp
+		nz = (unsigned) -1;
+	add_nz_zp:
+		nz += READ_LOW( data );
+	write_nz_zp:
+		pc++;
+		WRITE_LOW( data, nz );
+		goto loop;
+
+	case 0xFE: // INC abs,x
+		data = x + GET_ADDR();
+		goto inc_ptr;
+
+	case 0xEE: // INC abs
+		data = GET_ADDR();
+	inc_ptr:
+		nz = 1;
+		goto inc_common;
+
+	case 0xDE: // DEC abs,x
+		data = x + GET_ADDR();
+		goto dec_ptr;
+
+	case 0xCE: // DEC abs
+		data = GET_ADDR();
+	dec_ptr:
+		nz = (unsigned) -1;
+	inc_common:
+		FLUSH_TIME();
+		nz += READ( data );
+		pc += 2;
+		WRITE( data, (uint8_t) nz );
+		CACHE_TIME();
+		goto loop;
+
+// Transfer
+
+	case 0xAA: // TAX
+		x  = a;
+		nz = a;
+		goto loop;
+
+	case 0x8A: // TXA
+		a  = x;
+		nz = x;
+		goto loop;
+
+	case 0x9A: // TXS
+		SET_SP( x ); // verified (no flag change)
+		goto loop;
+
+	case 0xBA: // TSX
+		x = nz = GET_SP();
+		goto loop;
+
+// Stack
+
+	case 0x48: // PHA
+		PUSH( a ); // verified
+		goto loop;
+
+	case 0x68: // PLA
+		a = nz = READ_LOW( sp );
+		sp = (sp - 0xFF) | 0x100;
+		goto loop;
+
+	case 0x40:{// RTI
+		fuint8 temp = READ_LOW( sp );
+		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
+		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
+		sp = (sp - 0xFD) | 0x100;
+		data = status;
+		SET_STATUS( temp );
+		this->r.status = status; // update externally-visible I flag
+		if ( (data ^ status) & st_i )
+		{
+			sap_time_t new_time = end_time_;
+			if ( !(status & st_i) && new_time > irq_time_ )
+				new_time = irq_time_;
+			blargg_long delta = s.base - new_time;
+			s.base = new_time;
+			s_time += delta;
+		}
+		goto loop;
+	}
+
+	case 0x28:{// PLP
+		fuint8 temp = READ_LOW( sp );
+		sp = (sp - 0xFF) | 0x100;
+		fuint8 changed = status ^ temp;
+		SET_STATUS( temp );
+		if ( !(changed & st_i) )
+			goto loop; // I flag didn't change
+		if ( status & st_i )
+			goto handle_sei;
+		goto handle_cli;
+	}
+
+	case 0x08: { // PHP
+		fuint8 temp;
+		CALC_STATUS( temp );
+		PUSH( temp | (st_b | st_r) );
+		goto loop;
+	}
+
+	case 0x6C:{// JMP (ind)
+		data = GET_ADDR();
+		pc = READ_PROG( data );
+		data = (data & 0xFF00) | ((data + 1) & 0xFF);
+		pc |= 0x100 * READ_PROG( data );
+		goto loop;
+	}
+
+	case 0x00: // BRK
+		goto handle_brk;
+
+// Flags
+
+	case 0x38: // SEC
+		c = (unsigned) ~0;
+		goto loop;
+
+	case 0x18: // CLC
+		c = 0;
+		goto loop;
+
+	case 0xB8: // CLV
+		status &= ~st_v;
+		goto loop;
+
+	case 0xD8: // CLD
+		status &= ~st_d;
+		goto loop;
+
+	case 0xF8: // SED
+		status |= st_d;
+		goto loop;
+
+	case 0x58: // CLI
+		if ( !(status & st_i) )
+			goto loop;
+		status &= ~st_i;
+	handle_cli: {
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - irq_time_;
+		if ( delta <= 0 )
+		{
+			if ( TIME < irq_time_ )
+				goto loop;
+			goto delayed_cli;
+		}
+		s.base = irq_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+
+		if ( delta >= s_time + 1 )
+		{
+			// delayed irq until after next instruction
+			s.base += s_time + 1;
+			s_time = -1;
+			irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
+			goto loop;
+		}
+	delayed_cli:
+		debug_printf( "Delayed CLI not emulated\n" );
+		goto loop;
+	}
+
+	case 0x78: // SEI
+		if ( status & st_i )
+			goto loop;
+		status |= st_i;
+	handle_sei: {
+		this->r.status = status; // update externally-visible I flag
+		blargg_long delta = s.base - end_time_;
+		s.base = end_time_;
+		s_time += delta;
+		if ( s_time < 0 )
+			goto loop;
+		debug_printf( "Delayed SEI not emulated\n" );
+		goto loop;
+	}
+
+// Unofficial
+
+	// SKW - Skip word
+	case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
+		HANDLE_PAGE_CROSSING( data + x );
+	case 0x0C:
+		pc++;
+	// SKB - Skip byte
+	case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
+	case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
+		pc++;
+		goto loop;
+
+	// NOP
+	case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
+		goto loop;
+
+// Unimplemented
+
+	// halt
+	//case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
+	//case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
+
+	default:
+		assert( (unsigned) opcode <= 0xFF );
+		illegal_encountered = true;
+		pc--;
+		goto stop;
+	}
+	assert( false );
+
+	int result_;
+handle_brk:
+	if ( (pc - 1) >= idle_addr )
+		goto idle_done;
+	pc++;
+	result_ = 4;
+	debug_printf( "BRK executed\n" );
+
+interrupt:
+	{
+		s_time += 7;
+
+		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
+		WRITE_LOW( 0x100 | (sp - 2), pc );
+		pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
+
+		sp = (sp - 3) | 0x100;
+		fuint8 temp;
+		CALC_STATUS( temp );
+		temp |= st_r;
+		if ( result_ )
+			temp |= st_b; // TODO: incorrectly sets B flag for IRQ
+		WRITE_LOW( sp, temp );
+
+		status &= ~st_d;
+		status |= st_i;
+		this->r.status = status; // update externally-visible I flag
+
+		blargg_long delta = s.base - end_time_;
+		s.base = end_time_;
+		s_time += delta;
+		goto loop;
+	}
+
+idle_done:
+	//s_time = 0;
+	pc--;
+	goto stop;
+out_of_time:
+	pc--;
+	FLUSH_TIME();
+	CPU_DONE( this, TIME, result_ );
+	CACHE_TIME();
+	if ( result_ >= 0 )
+		goto interrupt;
+	if ( s_time < 0 )
+		goto loop;
+
+stop:
+
+	s.time = s_time;
+
+	r.pc = pc;
+	r.sp = GET_SP();
+	r.a = a;
+	r.x = x;
+	r.y = y;
+
+	{
+		fuint8 temp;
+		CALC_STATUS( temp );
+		r.status = temp;
+	}
+
+	this->state_ = s;
+	this->state = &this->state_;
+
+	return illegal_encountered;
+}
+
diff --git a/src/console/Sap_Cpu.cxx b/src/console/Sap_Cpu.cxx
deleted file mode 100644
index 7528de1b36a9..000000000000
--- a/src/console/Sap_Cpu.cxx
+++ /dev/null
@@ -1,1009 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Cpu.h"
-
-#include <limits.h>
-#include "blargg_endian.h"
-
-//#include "nes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define FLUSH_TIME()    (void) (s.time = s_time)
-#define CACHE_TIME()    (void) (s_time = s.time)
-
-#include "sap_cpu_io.h"
-
-#ifndef CPU_DONE
-	#define CPU_DONE( cpu, time, result_out )   { result_out = -1; }
-#endif
-
-#include "blargg_source.h"
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Sap_Cpu::reset( void* new_mem )
-{
-	check( state == &state_ );
-	state = &state_;
-	mem = (uint8_t*) new_mem;
-	r.status = st_i;
-	r.sp = 0xFF;
-	r.pc = 0;
-	r.a  = 0;
-	r.x  = 0;
-	r.y  = 0;
-	state_.time = 0;
-	state_.base = 0;
-	irq_time_ = future_sap_time;
-	end_time_ = future_sap_time;
-}
-
-#define TIME                    (s_time + s.base)
-#define READ( addr )            CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data )     {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr )        (mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr )       (READ_LOW( addr ))
-
-#define SET_SP( v )     (sp = ((v) + 1) | 0x100)
-#define GET_SP()        ((sp - 1) & 0xFF)
-#define PUSH( v )       ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int         fint16;
-typedef unsigned    fuint16;
-typedef unsigned    fuint8;
-typedef blargg_long fint32;
-
-bool Sap_Cpu::run( sap_time_t end_time )
-{
-	bool illegal_encountered = false;
-	set_end_time( end_time );
-	state_t s = this->state_;
-	this->state = &s;
-	fint32 s_time = s.time;
-	uint8_t* const mem = this->mem; // cache
-
-	// registers
-	fuint16 pc = r.pc;
-	fuint8 a = r.a;
-	fuint8 x = r.x;
-	fuint8 y = r.y;
-	fuint16 sp;
-	SET_SP( r.sp );
-
-	// status flags
-	#define IS_NEG (nz & 0x8080)
-
-	#define CALC_STATUS( out ) do {\
-		out = status & (st_v | st_d | st_i);\
-		out |= ((nz >> 8) | nz) & st_n;\
-		out |= c >> 8 & st_c;\
-		if ( !(nz & 0xFF) ) out |= st_z;\
-	} while ( 0 )
-
-	#define SET_STATUS( in ) do {\
-		status = in & (st_v | st_d | st_i);\
-		nz = in << 8;\
-		c = nz;\
-		nz |= ~in & st_z;\
-	} while ( 0 )
-
-	fuint8 status;
-	fuint16 c;  // carry set if (c & 0x100) != 0
-	fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
-	{
-		fuint8 temp = r.status;
-		SET_STATUS( temp );
-	}
-
-	goto loop;
-dec_clock_loop:
-	s_time--;
-loop:
-
-	#ifndef NDEBUG
-	{
-		sap_time_t correct = end_time_;
-		if ( !(status & st_i) && correct > irq_time_ )
-			correct = irq_time_;
-		check( s.base == correct );
-	}
-	#endif
-
-	check( (unsigned) GET_SP() < 0x100 );
-	check( (unsigned) a < 0x100 );
-	check( (unsigned) x < 0x100 );
-	check( (unsigned) y < 0x100 );
-
-	fuint8 opcode = mem [pc];
-	pc++;
-	uint8_t const* instr = mem + pc;
-
-	static uint8_t const clock_table [256] =
-	{// 0 1 2 3 4 5 6 7 8 9 A B C D E F
-		0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
-		6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
-		6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
-		6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
-		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
-		3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
-		2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
-		3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
-		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
-		2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
-		3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
-	}; // 0x00 was 7
-
-	fuint16 data;
-	data = clock_table [opcode];
-	if ( (s_time += data) >= 0 )
-		goto possibly_out_of_time;
-almost_out_of_time:
-
-	data = *instr;
-
-	#ifdef NES_CPU_LOG_H
-		nes_cpu_log( "cpu_log", pc - 1, opcode, instr [0], instr [1] );
-	#endif
-
-	switch ( opcode )
-	{
-possibly_out_of_time:
-		if ( s_time < (int) data )
-			goto almost_out_of_time;
-		s_time -= data;
-		goto out_of_time;
-
-// Macros
-
-#define GET_MSB()   (instr [1])
-#define ADD_PAGE()  (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR()  GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
-		fuint16 temp = READ_LOW( data ) + y;\
-		out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
-		cross( temp );\
-	}
-
-#define IND_X( out ) {\
-		fuint16 temp = data + x;\
-		out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
-	}
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
-	IND_X( data )\
-	goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
-	IND_Y( HANDLE_PAGE_CROSSING, data )\
-	goto ptr##op;\
-case op + 0x10: /* zp,X */\
-	data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
-	data = READ_LOW( data );\
-	goto imm##op;\
-case op + 0x14: /* abs,Y */\
-	data += y;\
-	goto ind##op;\
-case op + 0x18: /* abs,X */\
-	data += x;\
-ind##op:\
-	HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
-	ADD_PAGE();\
-ptr##op:\
-	FLUSH_TIME();\
-	data = READ( data );\
-	CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
-	fint16 offset = (int8_t) data;\
-	fuint16 extra_clock = (++pc & 0xFF) + offset;\
-	if ( !(cond) ) goto dec_clock_loop;\
-	pc += offset;\
-	s_time += extra_clock >> 8 & 1;\
-	goto loop;\
-}
-
-// Often-Used
-
-	case 0xB5: // LDA zp,x
-		a = nz = READ_LOW( uint8_t (data + x) );
-		pc++;
-		goto loop;
-
-	case 0xA5: // LDA zp
-		a = nz = READ_LOW( data );
-		pc++;
-		goto loop;
-
-	case 0xD0: // BNE
-		BRANCH( (uint8_t) nz );
-
-	case 0x20: { // JSR
-		fuint16 temp = pc + 1;
-		pc = GET_ADDR();
-		WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
-		sp = (sp - 2) | 0x100;
-		WRITE_LOW( sp, temp );
-		goto loop;
-	}
-
-	case 0x4C: // JMP abs
-		pc = GET_ADDR();
-		goto loop;
-
-	case 0xE8: // INX
-		INC_DEC_XY( x, 1 )
-
-	case 0x10: // BPL
-		BRANCH( !IS_NEG )
-
-	ARITH_ADDR_MODES( 0xC5 ) // CMP
-		nz = a - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	case 0x30: // BMI
-		BRANCH( IS_NEG )
-
-	case 0xF0: // BEQ
-		BRANCH( !(uint8_t) nz );
-
-	case 0x95: // STA zp,x
-		data = uint8_t (data + x);
-	case 0x85: // STA zp
-		pc++;
-		WRITE_LOW( data, a );
-		goto loop;
-
-	case 0xC8: // INY
-		INC_DEC_XY( y, 1 )
-
-	case 0xA8: // TAY
-		y  = a;
-		nz = a;
-		goto loop;
-
-	case 0x98: // TYA
-		a  = y;
-		nz = y;
-		goto loop;
-
-	case 0xAD:{// LDA abs
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		nz = READ( addr );
-		a = nz;
-		goto loop;
-	}
-
-	case 0x60: // RTS
-		pc = 1 + READ_LOW( sp );
-		pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
-		sp = (sp - 0xFE) | 0x100;
-		goto loop;
-
-	{
-		fuint16 addr;
-
-	case 0x99: // STA abs,Y
-		addr = y + GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-		goto sta_ptr;
-
-	case 0x8D: // STA abs
-		addr = GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-		goto sta_ptr;
-
-	case 0x9D: // STA abs,X (slightly more common than STA abs)
-		addr = x + GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, a );
-			goto loop;
-		}
-	sta_ptr:
-		FLUSH_TIME();
-		WRITE( addr, a );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x91: // STA (ind),Y
-		IND_Y( NO_PAGE_CROSSING, addr )
-		pc++;
-		goto sta_ptr;
-
-	case 0x81: // STA (ind,X)
-		IND_X( addr )
-		pc++;
-		goto sta_ptr;
-
-	}
-
-	case 0xA9: // LDA #imm
-		pc++;
-		a  = data;
-		nz = data;
-		goto loop;
-
-	// common read instructions
-	{
-		fuint16 addr;
-
-	case 0xA1: // LDA (ind,X)
-		IND_X( addr )
-		pc++;
-		goto a_nz_read_addr;
-
-	case 0xB1:// LDA (ind),Y
-		addr = READ_LOW( data ) + y;
-		HANDLE_PAGE_CROSSING( addr );
-		addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
-		pc++;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-		goto a_nz_read_addr;
-
-	case 0xB9: // LDA abs,Y
-		HANDLE_PAGE_CROSSING( data + y );
-		addr = GET_ADDR() + y;
-		pc += 2;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-		goto a_nz_read_addr;
-
-	case 0xBD: // LDA abs,X
-		HANDLE_PAGE_CROSSING( data + x );
-		addr = GET_ADDR() + x;
-		pc += 2;
-		a = nz = READ_PROG( addr );
-		if ( (addr ^ 0x8000) <= 0x9FFF )
-			goto loop;
-	a_nz_read_addr:
-		FLUSH_TIME();
-		a = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-
-	}
-
-// Branch
-
-	case 0x50: // BVC
-		BRANCH( !(status & st_v) )
-
-	case 0x70: // BVS
-		BRANCH( status & st_v )
-
-	case 0xB0: // BCS
-		BRANCH( c & 0x100 )
-
-	case 0x90: // BCC
-		BRANCH( !(c & 0x100) )
-
-// Load/store
-
-	case 0x94: // STY zp,x
-		data = uint8_t (data + x);
-	case 0x84: // STY zp
-		pc++;
-		WRITE_LOW( data, y );
-		goto loop;
-
-	case 0x96: // STX zp,y
-		data = uint8_t (data + y);
-	case 0x86: // STX zp
-		pc++;
-		WRITE_LOW( data, x );
-		goto loop;
-
-	case 0xB6: // LDX zp,y
-		data = uint8_t (data + y);
-	case 0xA6: // LDX zp
-		data = READ_LOW( data );
-	case 0xA2: // LDX #imm
-		pc++;
-		x = data;
-		nz = data;
-		goto loop;
-
-	case 0xB4: // LDY zp,x
-		data = uint8_t (data + x);
-	case 0xA4: // LDY zp
-		data = READ_LOW( data );
-	case 0xA0: // LDY #imm
-		pc++;
-		y = data;
-		nz = data;
-		goto loop;
-
-	case 0xBC: // LDY abs,X
-		data += x;
-		HANDLE_PAGE_CROSSING( data );
-	case 0xAC:{// LDY abs
-		unsigned addr = data + 0x100 * GET_MSB();
-		pc += 2;
-		FLUSH_TIME();
-		y = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	case 0xBE: // LDX abs,y
-		data += y;
-		HANDLE_PAGE_CROSSING( data );
-	case 0xAE:{// LDX abs
-		unsigned addr = data + 0x100 * GET_MSB();
-		pc += 2;
-		FLUSH_TIME();
-		x = nz = READ( addr );
-		CACHE_TIME();
-		goto loop;
-	}
-
-	{
-		fuint8 temp;
-	case 0x8C: // STY abs
-		temp = y;
-		goto store_abs;
-
-	case 0x8E: // STX abs
-		temp = x;
-	store_abs:
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		if ( addr <= 0x7FF )
-		{
-			WRITE_LOW( addr, temp );
-			goto loop;
-		}
-		FLUSH_TIME();
-		WRITE( addr, temp );
-		CACHE_TIME();
-		goto loop;
-	}
-
-// Compare
-
-	case 0xEC:{// CPX abs
-		unsigned addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpx_data;
-	}
-
-	case 0xE4: // CPX zp
-		data = READ_LOW( data );
-	case 0xE0: // CPX #imm
-	cpx_data:
-		nz = x - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-	case 0xCC:{// CPY abs
-		unsigned addr = GET_ADDR();
-		pc++;
-		FLUSH_TIME();
-		data = READ( addr );
-		CACHE_TIME();
-		goto cpy_data;
-	}
-
-	case 0xC4: // CPY zp
-		data = READ_LOW( data );
-	case 0xC0: // CPY #imm
-	cpy_data:
-		nz = y - data;
-		pc++;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-
-// Logical
-
-	ARITH_ADDR_MODES( 0x25 ) // AND
-		nz = (a &= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x45 ) // EOR
-		nz = (a ^= data);
-		pc++;
-		goto loop;
-
-	ARITH_ADDR_MODES( 0x05 ) // ORA
-		nz = (a |= data);
-		pc++;
-		goto loop;
-
-	case 0x2C:{// BIT abs
-		unsigned addr = GET_ADDR();
-		pc += 2;
-		status &= ~st_v;
-		nz = READ( addr );
-		status |= nz & st_v;
-		if ( a & nz )
-			goto loop;
-		nz <<= 8; // result must be zero, even if N bit is set
-		goto loop;
-	}
-
-	case 0x24: // BIT zp
-		nz = READ_LOW( data );
-		pc++;
-		status &= ~st_v;
-		status |= nz & st_v;
-		if ( a & nz )
-			goto loop;
-		nz <<= 8; // result must be zero, even if N bit is set
-		goto loop;
-
-// Add/subtract
-
-	ARITH_ADDR_MODES( 0xE5 ) // SBC
-	case 0xEB: // unofficial equivalent
-		data ^= 0xFF;
-		goto adc_imm;
-
-	ARITH_ADDR_MODES( 0x65 ) // ADC
-	adc_imm: {
-		check( !(status & st_d) );
-		fint16 carry = c >> 8 & 1;
-		fint16 ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
-		status &= ~st_v;
-		status |= ov >> 2 & 0x40;
-		c = nz = a + data + carry;
-		pc++;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-// Shift/rotate
-
-	case 0x4A: // LSR A
-		c = 0;
-	case 0x6A: // ROR A
-		nz = c >> 1 & 0x80;
-		c = a << 8;
-		nz |= a >> 1;
-		a = nz;
-		goto loop;
-
-	case 0x0A: // ASL A
-		nz = a << 1;
-		c = nz;
-		a = (uint8_t) nz;
-		goto loop;
-
-	case 0x2A: { // ROL A
-		nz = a << 1;
-		fint16 temp = c >> 8 & 1;
-		c = nz;
-		nz |= temp;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-
-	case 0x5E: // LSR abs,X
-		data += x;
-	case 0x4E: // LSR abs
-		c = 0;
-	case 0x6E: // ROR abs
-	ror_abs: {
-		ADD_PAGE();
-		FLUSH_TIME();
-		int temp = READ( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto rotate_common;
-	}
-
-	case 0x3E: // ROL abs,X
-		data += x;
-		goto rol_abs;
-
-	case 0x1E: // ASL abs,X
-		data += x;
-	case 0x0E: // ASL abs
-		c = 0;
-	case 0x2E: // ROL abs
-	rol_abs:
-		ADD_PAGE();
-		nz = c >> 8 & 1;
-		FLUSH_TIME();
-		nz |= (c = READ( data ) << 1);
-	rotate_common:
-		pc++;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-	case 0x7E: // ROR abs,X
-		data += x;
-		goto ror_abs;
-
-	case 0x76: // ROR zp,x
-		data = uint8_t (data + x);
-		goto ror_zp;
-
-	case 0x56: // LSR zp,x
-		data = uint8_t (data + x);
-	case 0x46: // LSR zp
-		c = 0;
-	case 0x66: // ROR zp
-	ror_zp: {
-		int temp = READ_LOW( data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		goto write_nz_zp;
-	}
-
-	case 0x36: // ROL zp,x
-		data = uint8_t (data + x);
-		goto rol_zp;
-
-	case 0x16: // ASL zp,x
-		data = uint8_t (data + x);
-	case 0x06: // ASL zp
-		c = 0;
-	case 0x26: // ROL zp
-	rol_zp:
-		nz = c >> 8 & 1;
-		nz |= (c = READ_LOW( data ) << 1);
-		goto write_nz_zp;
-
-// Increment/decrement
-
-	case 0xCA: // DEX
-		INC_DEC_XY( x, -1 )
-
-	case 0x88: // DEY
-		INC_DEC_XY( y, -1 )
-
-	case 0xF6: // INC zp,x
-		data = uint8_t (data + x);
-	case 0xE6: // INC zp
-		nz = 1;
-		goto add_nz_zp;
-
-	case 0xD6: // DEC zp,x
-		data = uint8_t (data + x);
-	case 0xC6: // DEC zp
-		nz = (unsigned) -1;
-	add_nz_zp:
-		nz += READ_LOW( data );
-	write_nz_zp:
-		pc++;
-		WRITE_LOW( data, nz );
-		goto loop;
-
-	case 0xFE: // INC abs,x
-		data = x + GET_ADDR();
-		goto inc_ptr;
-
-	case 0xEE: // INC abs
-		data = GET_ADDR();
-	inc_ptr:
-		nz = 1;
-		goto inc_common;
-
-	case 0xDE: // DEC abs,x
-		data = x + GET_ADDR();
-		goto dec_ptr;
-
-	case 0xCE: // DEC abs
-		data = GET_ADDR();
-	dec_ptr:
-		nz = (unsigned) -1;
-	inc_common:
-		FLUSH_TIME();
-		nz += READ( data );
-		pc += 2;
-		WRITE( data, (uint8_t) nz );
-		CACHE_TIME();
-		goto loop;
-
-// Transfer
-
-	case 0xAA: // TAX
-		x  = a;
-		nz = a;
-		goto loop;
-
-	case 0x8A: // TXA
-		a  = x;
-		nz = x;
-		goto loop;
-
-	case 0x9A: // TXS
-		SET_SP( x ); // verified (no flag change)
-		goto loop;
-
-	case 0xBA: // TSX
-		x = nz = GET_SP();
-		goto loop;
-
-// Stack
-
-	case 0x48: // PHA
-		PUSH( a ); // verified
-		goto loop;
-
-	case 0x68: // PLA
-		a = nz = READ_LOW( sp );
-		sp = (sp - 0xFF) | 0x100;
-		goto loop;
-
-	case 0x40:{// RTI
-		fuint8 temp = READ_LOW( sp );
-		pc  = READ_LOW( 0x100 | (sp - 0xFF) );
-		pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
-		sp = (sp - 0xFD) | 0x100;
-		data = status;
-		SET_STATUS( temp );
-		this->r.status = status; // update externally-visible I flag
-		if ( (data ^ status) & st_i )
-		{
-			sap_time_t new_time = end_time_;
-			if ( !(status & st_i) && new_time > irq_time_ )
-				new_time = irq_time_;
-			blargg_long delta = s.base - new_time;
-			s.base = new_time;
-			s_time += delta;
-		}
-		goto loop;
-	}
-
-	case 0x28:{// PLP
-		fuint8 temp = READ_LOW( sp );
-		sp = (sp - 0xFF) | 0x100;
-		fuint8 changed = status ^ temp;
-		SET_STATUS( temp );
-		if ( !(changed & st_i) )
-			goto loop; // I flag didn't change
-		if ( status & st_i )
-			goto handle_sei;
-		goto handle_cli;
-	}
-
-	case 0x08: { // PHP
-		fuint8 temp;
-		CALC_STATUS( temp );
-		PUSH( temp | (st_b | st_r) );
-		goto loop;
-	}
-
-	case 0x6C:{// JMP (ind)
-		data = GET_ADDR();
-		pc = READ_PROG( data );
-		data = (data & 0xFF00) | ((data + 1) & 0xFF);
-		pc |= 0x100 * READ_PROG( data );
-		goto loop;
-	}
-
-	case 0x00: // BRK
-		goto handle_brk;
-
-// Flags
-
-	case 0x38: // SEC
-		c = (unsigned) ~0;
-		goto loop;
-
-	case 0x18: // CLC
-		c = 0;
-		goto loop;
-
-	case 0xB8: // CLV
-		status &= ~st_v;
-		goto loop;
-
-	case 0xD8: // CLD
-		status &= ~st_d;
-		goto loop;
-
-	case 0xF8: // SED
-		status |= st_d;
-		goto loop;
-
-	case 0x58: // CLI
-		if ( !(status & st_i) )
-			goto loop;
-		status &= ~st_i;
-	handle_cli: {
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - irq_time_;
-		if ( delta <= 0 )
-		{
-			if ( TIME < irq_time_ )
-				goto loop;
-			goto delayed_cli;
-		}
-		s.base = irq_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-
-		if ( delta >= s_time + 1 )
-		{
-			// delayed irq until after next instruction
-			s.base += s_time + 1;
-			s_time = -1;
-			irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
-			goto loop;
-		}
-	delayed_cli:
-		debug_printf( "Delayed CLI not emulated\n" );
-		goto loop;
-	}
-
-	case 0x78: // SEI
-		if ( status & st_i )
-			goto loop;
-		status |= st_i;
-	handle_sei: {
-		this->r.status = status; // update externally-visible I flag
-		blargg_long delta = s.base - end_time_;
-		s.base = end_time_;
-		s_time += delta;
-		if ( s_time < 0 )
-			goto loop;
-		debug_printf( "Delayed SEI not emulated\n" );
-		goto loop;
-	}
-
-// Unofficial
-
-	// SKW - Skip word
-	case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
-		HANDLE_PAGE_CROSSING( data + x );
-	case 0x0C:
-		pc++;
-	// SKB - Skip byte
-	case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
-	case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
-		pc++;
-		goto loop;
-
-	// NOP
-	case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
-		goto loop;
-
-// Unimplemented
-
-	// halt
-	//case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
-	//case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
-
-	default:
-		assert( (unsigned) opcode <= 0xFF );
-		illegal_encountered = true;
-		pc--;
-		goto stop;
-	}
-	assert( false );
-
-	int result_;
-handle_brk:
-	if ( (pc - 1) >= idle_addr )
-		goto idle_done;
-	pc++;
-	result_ = 4;
-	debug_printf( "BRK executed\n" );
-
-interrupt:
-	{
-		s_time += 7;
-
-		WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
-		WRITE_LOW( 0x100 | (sp - 2), pc );
-		pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
-		sp = (sp - 3) | 0x100;
-		fuint8 temp;
-		CALC_STATUS( temp );
-		temp |= st_r;
-		if ( result_ )
-			temp |= st_b; // TODO: incorrectly sets B flag for IRQ
-		WRITE_LOW( sp, temp );
-
-		status &= ~st_d;
-		status |= st_i;
-		this->r.status = status; // update externally-visible I flag
-
-		blargg_long delta = s.base - end_time_;
-		s.base = end_time_;
-		s_time += delta;
-		goto loop;
-	}
-
-idle_done:
-	//s_time = 0;
-	pc--;
-	goto stop;
-out_of_time:
-	pc--;
-	FLUSH_TIME();
-	CPU_DONE( this, TIME, result_ );
-	CACHE_TIME();
-	if ( result_ >= 0 )
-		goto interrupt;
-	if ( s_time < 0 )
-		goto loop;
-
-stop:
-
-	s.time = s_time;
-
-	r.pc = pc;
-	r.sp = GET_SP();
-	r.a = a;
-	r.x = x;
-	r.y = y;
-
-	{
-		fuint8 temp;
-		CALC_STATUS( temp );
-		r.status = temp;
-	}
-
-	this->state_ = s;
-	this->state = &this->state_;
-
-	return illegal_encountered;
-}
-
diff --git a/src/console/Sap_Emu.cc b/src/console/Sap_Emu.cc
new file mode 100644
index 000000000000..75fbd2655a37
--- /dev/null
+++ b/src/console/Sap_Emu.cc
@@ -0,0 +1,525 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Sap_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+long const base_scanline_period = 114;
+
+Sap_Emu::Sap_Emu()
+{
+	set_type( gme_sap_type );
+
+	static const char* const names [Sap_Apu::osc_count * 2] = {
+		"Wave 1", "Wave 2", "Wave 3", "Wave 4",
+		"Wave 5", "Wave 6", "Wave 7", "Wave 8",
+	};
+	set_voice_names( names );
+
+	static int const types [Sap_Apu::osc_count * 2] = {
+		wave_type | 1, wave_type | 2, wave_type | 3, wave_type | 0,
+		wave_type | 5, wave_type | 6, wave_type | 7, wave_type | 4,
+	};
+	set_voice_types( types );
+	set_silence_lookahead( 6 );
+}
+
+Sap_Emu::~Sap_Emu() { }
+
+// Track info
+
+// Returns 16 or greater if not hex
+inline int from_hex_char( int h )
+{
+	h -= 0x30;
+	if ( (unsigned) h > 9 )
+		h = ((h - 0x11) & 0xDF) + 10;
+	return h;
+}
+
+static long from_hex( byte const* in )
+{
+	unsigned result = 0;
+	for ( int n = 4; n--; )
+	{
+		int h = from_hex_char( *in++ );
+		if ( h > 15 )
+			return -1;
+		result = result * 0x10 + h;
+	}
+	return result;
+}
+
+static int from_dec( byte const* in, byte const* end )
+{
+	if ( in >= end )
+		return -1;
+
+	int n = 0;
+	while ( in < end )
+	{
+		int dig = *in++ - '0';
+		if ( (unsigned) dig > 9 )
+			return -1;
+		n = n * 10 + dig;
+	}
+	return n;
+}
+
+static void parse_string( byte const* in, byte const* end, int len, char* out )
+{
+	byte const* start = in;
+	if ( *in++ == '\"' )
+	{
+		start++;
+		while ( in < end && *in != '\"' )
+			in++;
+	}
+	else
+	{
+		in = end;
+	}
+	len = min( len - 1, int (in - start) );
+	out [len] = 0;
+	memcpy( out, start, len );
+}
+
+static byte const* parse_int_( byte const* in, int* out )
+{
+	int n = 0;
+	while ( 1 )
+	{
+		unsigned d = from_dec( in, in + 1 );
+		if ( d > 9 )
+			break;
+		in++;
+		n = n * 10 + d;
+		*out = n;
+	}
+	return in;
+}
+
+static byte const* parse_time( byte const* in, int* out )
+{
+	*out = -1;
+	int n = -1;
+	in = parse_int_( in, &n );
+	if ( n >= 0 )
+	{
+		*out = n;
+		if ( *in == ':' )
+		{
+			n = -1;
+			in = parse_int_( in + 1, &n );
+			if ( n >= 0 )
+				*out = *out * 60 + n;
+		}
+	}
+	*out = *out * 1000;
+	return in;
+}
+
+static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out )
+{
+	out->track_count   = 1;
+	out->author    [0] = 0;
+	out->name      [0] = 0;
+	out->copyright [0] = 0;
+
+	if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
+		return gme_wrong_file_type;
+
+	byte const* file_end = in + size - 5;
+	in += 5;
+	while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
+	{
+		byte const* line_end = in;
+		while ( line_end < file_end && *line_end != 0x0D )
+			line_end++;
+
+		char const* tag = (char const*) in;
+		while ( in < line_end && *in > ' ' )
+			in++;
+		int tag_len = (char const*) in - tag;
+
+		while ( in < line_end && *in <= ' ' ) in++;
+
+		if ( tag_len <= 0 )
+		{
+			// skip line
+		}
+		else if ( !strncmp( "INIT", tag, tag_len ) )
+		{
+			out->init_addr = from_hex( in );
+			if ( (unsigned long) out->init_addr > 0xFFFF )
+				return "Invalid init address";
+		}
+		else if ( !strncmp( "PLAYER", tag, tag_len ) )
+		{
+			out->play_addr = from_hex( in );
+			if ( (unsigned long) out->play_addr > 0xFFFF )
+				return "Invalid play address";
+		}
+		else if ( !strncmp( "MUSIC", tag, tag_len ) )
+		{
+			out->music_addr = from_hex( in );
+			if ( (unsigned long) out->music_addr > 0xFFFF )
+				return "Invalid music address";
+		}
+		else if ( !strncmp( "SONGS", tag, tag_len ) )
+		{
+			out->track_count = from_dec( in, line_end );
+			if ( out->track_count <= 0 )
+				return "Invalid track count";
+		}
+		else if ( !strncmp( "TYPE", tag, tag_len ) )
+		{
+			switch ( out->type = *in )
+			{
+			case 'D':
+			case 'C':
+			case 'B':
+				break;
+
+			default:
+				return "Unsupported player type";
+			}
+		}
+		else if ( !strncmp( "STEREO", tag, tag_len ) )
+		{
+			out->stereo = true;
+		}
+		else if ( !strncmp( "NTSC", tag, tag_len ) )
+		{
+			out->ntsc = true;
+		}
+		else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
+		{
+			out->fastplay = from_dec( in, line_end );
+			if ( out->fastplay <= 0 )
+				return "Invalid fastplay value";
+		}
+		else if ( !strncmp( "AUTHOR", tag, tag_len ) )
+		{
+			parse_string( in, line_end, sizeof out->author, out->author );
+		}
+		else if ( !strncmp( "NAME", tag, tag_len ) )
+		{
+			parse_string( in, line_end, sizeof out->name, out->name );
+		}
+		else if ( !strncmp( "DATE", tag, tag_len ) )
+		{
+			parse_string( in, line_end, sizeof out->copyright, out->copyright );
+		}
+		else if ( !strncmp( "TIME", tag, tag_len ) )
+		{
+			parse_time( in, &out->length );
+		}
+
+		in = line_end + 2;
+	}
+
+	if ( in [0] != 0xFF || in [1] != 0xFF )
+		return "ROM data missing";
+	out->rom_data = in + 2;
+
+	return 0;
+}
+
+static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
+{
+	Gme_File::copy_field_( out->song,      in.name );
+	Gme_File::copy_field_( out->author,    in.author );
+	Gme_File::copy_field_( out->copyright, in.copyright );
+	out->length = in.length;
+}
+
+blargg_err_t Sap_Emu::track_info_( track_info_t* out, int ) const
+{
+	copy_sap_fields( info, out );
+	return 0;
+}
+
+struct Sap_File : Gme_Info_
+{
+	Sap_Emu::info_t info;
+
+	Sap_File() { set_type( gme_sap_type ); }
+
+	blargg_err_t load_mem_( byte const* begin, long size )
+	{
+		RETURN_ERR( parse_info( begin, size, &info ) );
+		set_track_count( info.track_count );
+		return 0;
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		copy_sap_fields( info, out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
+static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
+
+static gme_type_t_ const gme_sap_type_ = { "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 };
+gme_type_t const gme_sap_type = &gme_sap_type_;
+
+
+// Setup
+
+blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
+{
+	file_end = in + size;
+
+	info.warning    = 0;
+	info.type       = 'B';
+	info.stereo     = false;
+	info.init_addr  = -1;
+	info.play_addr  = -1;
+	info.music_addr = -1;
+	info.fastplay   = 312;
+	RETURN_ERR( parse_info( in, size, &info ) );
+
+	set_warning( info.warning );
+	set_track_count( info.track_count );
+	set_voice_count( Sap_Apu::osc_count << info.stereo );
+	apu_impl.volume( gain() );
+
+	return setup_buffer( 1773447 );
+}
+
+void Sap_Emu::update_eq( blip_eq_t const& eq )
+{
+	apu_impl.synth.treble_eq( eq );
+}
+
+void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	int i2 = i - Sap_Apu::osc_count;
+	if ( i2 >= 0 )
+		apu2.osc_output( i2, right );
+	else
+		apu.osc_output( i, (info.stereo ? left : center) );
+}
+
+// Emulation
+
+void Sap_Emu::set_tempo_( double t )
+{
+	scanline_period = sap_time_t (base_scanline_period / t);
+}
+
+inline sap_time_t Sap_Emu::play_period() const { return info.fastplay * scanline_period; }
+
+void Sap_Emu::cpu_jsr( sap_addr_t addr )
+{
+	check( r.sp >= 0xFE ); // catch anything trying to leave data on stack
+	r.pc = addr;
+	int high_byte = (idle_addr - 1) >> 8;
+	if ( r.sp == 0xFE && mem.ram [0x1FF] == high_byte )
+		r.sp = 0xFF; // pop extra byte off
+	mem.ram [0x100 + r.sp--] = high_byte; // some routines use RTI to return
+	mem.ram [0x100 + r.sp--] = high_byte;
+	mem.ram [0x100 + r.sp--] = (idle_addr - 1) & 0xFF;
+}
+
+void Sap_Emu::run_routine( sap_addr_t addr )
+{
+	cpu_jsr( addr );
+	cpu::run( ( info.ntsc ? 262 : 312 ) * base_scanline_period * 60 );
+	check( r.pc == idle_addr );
+}
+
+inline void Sap_Emu::call_init( int track )
+{
+	uint8_t sp;
+	uint16_t code_base;
+
+	switch ( info.type )
+	{
+	case 'B':
+		r.a = track;
+		run_routine( info.init_addr );
+		break;
+
+	case 'C':
+		r.a = 0x70;
+		r.x = info.music_addr&0xFF;
+		r.y = info.music_addr >> 8;
+		run_routine( info.play_addr + 3 );
+		r.a = 0;
+		r.x = track;
+		run_routine( info.play_addr + 3 );
+		break;
+
+	case 'D':
+		r.a = track;
+		r.x = 0;
+		r.y = 0;
+		r.sp = 0xFF;
+		run_routine( info.init_addr );
+
+		sp = r.sp;
+
+		mem.ram [0x100 + sp] = r.pc >> 8;
+		sp = (sp - 1) & 0xFF;
+		mem.ram [0x100 + sp] = ( r.pc & 0xFF );
+		r.sp = (sp - 1) & 0xFF;
+
+		code_base = 0xd200;
+		mem.ram [code_base] = 0x08;
+		mem.ram [code_base + 1] = 0x48;
+		mem.ram [code_base + 2] = 0x8a;
+		mem.ram [code_base + 3] = 0x48;
+		mem.ram [code_base + 4] = 0x98;
+		mem.ram [code_base + 5] = 0x48;
+		mem.ram [code_base + 6] = 0x20;
+		mem.ram [code_base + 7] = code_base & 0xFF;
+		mem.ram [code_base + 8] = (code_base >> 8);
+		mem.ram [code_base + 9] = 0x68;
+		mem.ram [code_base + 10] = 0xa8;
+		mem.ram [code_base + 11] = 0x68;
+		mem.ram [code_base + 12] = 0xaa;
+		mem.ram [code_base + 13] = 0x68;
+		mem.ram [code_base + 14] = 0x40;
+		info.play_addr = code_base;
+		break;
+	}
+}
+
+blargg_err_t Sap_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+	memset( &mem, 0, sizeof mem );
+
+	byte const* in = info.rom_data;
+	while ( file_end - in >= 5 )
+	{
+		unsigned start = GET_LE16( in );
+		unsigned end   = GET_LE16( in + 2 );
+		//debug_printf( "Block $%04X-$%04X\n", start, end );
+		in += 4;
+		if ( end < start )
+		{
+			set_warning( "Invalid file data block" );
+			break;
+		}
+		long len = end - start + 1;
+		if ( len > file_end - in )
+		{
+			set_warning( "Invalid file data block" );
+			break;
+		}
+
+		memcpy( mem.ram + start, in, len );
+		in += len;
+		if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
+			in += 2;
+	}
+
+	apu.reset( &apu_impl );
+	apu2.reset( &apu_impl );
+	cpu::reset( mem.ram );
+	time_mask = 0; // disables sound during init
+	call_init( track );
+	time_mask = -1;
+
+	next_play = play_period();
+
+	return 0;
+}
+
+// Emulation
+
+// see sap_cpu_io.h for read/write functions
+
+void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
+{
+	if ( (addr ^ Sap_Apu::start_addr) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) )
+	{
+		GME_APU_HOOK( this, addr - Sap_Apu::start_addr, data );
+		apu.write_data( time() & time_mask, addr, data );
+		return;
+	}
+
+	if ( (addr ^ (Sap_Apu::start_addr + 0x10)) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) &&
+			info.stereo )
+	{
+		GME_APU_HOOK( this, addr - 0x10 - Sap_Apu::start_addr + 10, data );
+		apu2.write_data( time() & time_mask, addr ^ 0x10, data );
+		return;
+	}
+
+	if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
+		debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data );
+}
+
+inline void Sap_Emu::call_play()
+{
+	switch ( info.type )
+	{
+	case 'D':
+		cpu_jsr( info.play_addr );
+		break;
+	case 'B':
+		cpu_jsr( info.play_addr );
+		break;
+
+	case 'C':
+		cpu_jsr( info.play_addr + 6 );
+		break;
+	}
+}
+
+blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
+{
+	set_time( 0 );
+	while ( time() < duration )
+	{
+		if ( cpu::run( duration ) || r.pc > idle_addr )
+			return "Emulation error (illegal instruction)";
+
+		if ( r.pc == idle_addr )
+		{
+			if ( next_play <= duration )
+			{
+				set_time( next_play );
+				next_play += play_period();
+				call_play();
+				GME_FRAME_HOOK( this );
+			}
+			else
+			{
+				set_time( duration );
+			}
+		}
+	}
+
+	duration = time();
+	next_play -= duration;
+	check( next_play >= 0 );
+	if ( next_play < 0 )
+		next_play = 0;
+	apu.end_frame( duration );
+	if ( info.stereo )
+		apu2.end_frame( duration );
+
+	return 0;
+}
diff --git a/src/console/Sap_Emu.cxx b/src/console/Sap_Emu.cxx
deleted file mode 100644
index 64a47303c729..000000000000
--- a/src/console/Sap_Emu.cxx
+++ /dev/null
@@ -1,444 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const base_scanline_period = 114;
-
-Sap_Emu::Sap_Emu()
-{
-	set_type( gme_sap_type );
-
-	static const char* const names [Sap_Apu::osc_count * 2] = {
-		"Wave 1", "Wave 2", "Wave 3", "Wave 4",
-		"Wave 5", "Wave 6", "Wave 7", "Wave 8",
-	};
-	set_voice_names( names );
-
-	static int const types [Sap_Apu::osc_count * 2] = {
-		wave_type | 1, wave_type | 2, wave_type | 3, wave_type | 0,
-		wave_type | 5, wave_type | 6, wave_type | 7, wave_type | 4,
-	};
-	set_voice_types( types );
-	set_silence_lookahead( 6 );
-}
-
-Sap_Emu::~Sap_Emu() { }
-
-// Track info
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
-	h -= 0x30;
-	if ( (unsigned) h > 9 )
-		h = ((h - 0x11) & 0xDF) + 10;
-	return h;
-}
-
-static long from_hex( byte const* in )
-{
-	unsigned result = 0;
-	for ( int n = 4; n--; )
-	{
-		int h = from_hex_char( *in++ );
-		if ( h > 15 )
-			return -1;
-		result = result * 0x10 + h;
-	}
-	return result;
-}
-
-static int from_dec( byte const* in, byte const* end )
-{
-	if ( in >= end )
-		return -1;
-
-	int n = 0;
-	while ( in < end )
-	{
-		int dig = *in++ - '0';
-		if ( (unsigned) dig > 9 )
-			return -1;
-		n = n * 10 + dig;
-	}
-	return n;
-}
-
-static void parse_string( byte const* in, byte const* end, int len, char* out )
-{
-	byte const* start = in;
-	if ( *in++ == '\"' )
-	{
-		start++;
-		while ( in < end && *in != '\"' )
-			in++;
-	}
-	else
-	{
-		in = end;
-	}
-	len = min( len - 1, int (in - start) );
-	out [len] = 0;
-	memcpy( out, start, len );
-}
-
-static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out )
-{
-	out->track_count   = 1;
-	out->author    [0] = 0;
-	out->name      [0] = 0;
-	out->copyright [0] = 0;
-
-	if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
-		return gme_wrong_file_type;
-
-	byte const* file_end = in + size - 5;
-	in += 5;
-	while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
-	{
-		byte const* line_end = in;
-		while ( line_end < file_end && *line_end != 0x0D )
-			line_end++;
-
-		char const* tag = (char const*) in;
-		while ( in < line_end && *in > ' ' )
-			in++;
-		int tag_len = (char const*) in - tag;
-
-		while ( in < line_end && *in <= ' ' ) in++;
-
-		if ( tag_len <= 0 )
-		{
-			// skip line
-		}
-		else if ( !strncmp( "INIT", tag, tag_len ) )
-		{
-			out->init_addr = from_hex( in );
-			if ( (unsigned long) out->init_addr > 0xFFFF )
-				return "Invalid init address";
-		}
-		else if ( !strncmp( "PLAYER", tag, tag_len ) )
-		{
-			out->play_addr = from_hex( in );
-			if ( (unsigned long) out->play_addr > 0xFFFF )
-				return "Invalid play address";
-		}
-		else if ( !strncmp( "MUSIC", tag, tag_len ) )
-		{
-			out->music_addr = from_hex( in );
-			if ( (unsigned long) out->music_addr > 0xFFFF )
-				return "Invalid music address";
-		}
-		else if ( !strncmp( "SONGS", tag, tag_len ) )
-		{
-			out->track_count = from_dec( in, line_end );
-			if ( out->track_count <= 0 )
-				return "Invalid track count";
-		}
-		else if ( !strncmp( "TYPE", tag, tag_len ) )
-		{
-			switch ( out->type = *in )
-			{
-			case 'C':
-			case 'B':
-				break;
-
-			case 'D':
-				return "Digimusic not supported";
-
-			default:
-				return "Unsupported player type";
-			}
-		}
-		else if ( !strncmp( "STEREO", tag, tag_len ) )
-		{
-			out->stereo = true;
-		}
-		else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
-		{
-			out->fastplay = from_dec( in, line_end );
-			if ( out->fastplay <= 0 )
-				return "Invalid fastplay value";
-		}
-		else if ( !strncmp( "AUTHOR", tag, tag_len ) )
-		{
-			parse_string( in, line_end, sizeof out->author, out->author );
-		}
-		else if ( !strncmp( "NAME", tag, tag_len ) )
-		{
-			parse_string( in, line_end, sizeof out->name, out->name );
-		}
-		else if ( !strncmp( "DATE", tag, tag_len ) )
-		{
-			parse_string( in, line_end, sizeof out->copyright, out->copyright );
-		}
-
-		in = line_end + 2;
-	}
-
-	if ( in [0] != 0xFF || in [1] != 0xFF )
-		return "ROM data missing";
-	out->rom_data = in + 2;
-
-	return 0;
-}
-
-static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
-{
-	Gme_File::copy_field_( out->song,      in.name );
-	Gme_File::copy_field_( out->author,    in.author );
-	Gme_File::copy_field_( out->copyright, in.copyright );
-}
-
-blargg_err_t Sap_Emu::track_info_( track_info_t* out, int ) const
-{
-	copy_sap_fields( info, out );
-	return 0;
-}
-
-struct Sap_File : Gme_Info_
-{
-	Sap_Emu::info_t info;
-
-	Sap_File() { set_type( gme_sap_type ); }
-
-	blargg_err_t load_mem_( byte const* begin, long size )
-	{
-		RETURN_ERR( parse_info( begin, size, &info ) );
-		set_track_count( info.track_count );
-		return 0;
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		copy_sap_fields( info, out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
-static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
-
-static gme_type_t_ const gme_sap_type_ = { "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 };
-gme_type_t const gme_sap_type = &gme_sap_type_;
-
-
-// Setup
-
-blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
-{
-	file_end = in + size;
-
-	info.warning    = 0;
-	info.type       = 'B';
-	info.stereo     = false;
-	info.init_addr  = -1;
-	info.play_addr  = -1;
-	info.music_addr = -1;
-	info.fastplay   = 312;
-	RETURN_ERR( parse_info( in, size, &info ) );
-
-	set_warning( info.warning );
-	set_track_count( info.track_count );
-	set_voice_count( Sap_Apu::osc_count << info.stereo );
-	apu_impl.volume( gain() );
-
-	return setup_buffer( 1773447 );
-}
-
-void Sap_Emu::update_eq( blip_eq_t const& eq )
-{
-	apu_impl.synth.treble_eq( eq );
-}
-
-void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	int i2 = i - Sap_Apu::osc_count;
-	if ( i2 >= 0 )
-		apu2.osc_output( i2, right );
-	else
-		apu.osc_output( i, (info.stereo ? left : center) );
-}
-
-// Emulation
-
-void Sap_Emu::set_tempo_( double t )
-{
-	scanline_period = sap_time_t (base_scanline_period / t);
-}
-
-inline sap_time_t Sap_Emu::play_period() const { return info.fastplay * scanline_period; }
-
-void Sap_Emu::cpu_jsr( sap_addr_t addr )
-{
-	check( r.sp >= 0xFE ); // catch anything trying to leave data on stack
-	r.pc = addr;
-	int high_byte = (idle_addr - 1) >> 8;
-	if ( r.sp == 0xFE && mem.ram [0x1FF] == high_byte )
-		r.sp = 0xFF; // pop extra byte off
-	mem.ram [0x100 + r.sp--] = high_byte; // some routines use RTI to return
-	mem.ram [0x100 + r.sp--] = high_byte;
-	mem.ram [0x100 + r.sp--] = (idle_addr - 1) & 0xFF;
-}
-
-void Sap_Emu::run_routine( sap_addr_t addr )
-{
-	cpu_jsr( addr );
-	cpu::run( 312 * base_scanline_period * 60 );
-	check( r.pc == idle_addr );
-}
-
-inline void Sap_Emu::call_init( int track )
-{
-	switch ( info.type )
-	{
-	case 'B':
-		r.a = track;
-		run_routine( info.init_addr );
-		break;
-
-	case 'C':
-		r.a = 0x70;
-		r.x = info.music_addr&0xFF;
-		r.y = info.music_addr >> 8;
-		run_routine( info.play_addr + 3 );
-		r.a = 0;
-		r.x = track;
-		run_routine( info.play_addr + 3 );
-		break;
-	}
-}
-
-blargg_err_t Sap_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-
-	memset( &mem, 0, sizeof mem );
-
-	byte const* in = info.rom_data;
-	while ( file_end - in >= 5 )
-	{
-		unsigned start = GET_LE16( in );
-		unsigned end   = GET_LE16( in + 2 );
-		//debug_printf( "Block $%04X-$%04X\n", start, end );
-		in += 4;
-		if ( end < start )
-		{
-			set_warning( "Invalid file data block" );
-			break;
-		}
-		long len = end - start + 1;
-		if ( len > file_end - in )
-		{
-			set_warning( "Invalid file data block" );
-			break;
-		}
-
-		memcpy( mem.ram + start, in, len );
-		in += len;
-		if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
-			in += 2;
-	}
-
-	apu.reset( &apu_impl );
-	apu2.reset( &apu_impl );
-	cpu::reset( mem.ram );
-	time_mask = 0; // disables sound during init
-	call_init( track );
-	time_mask = -1;
-
-	next_play = play_period();
-
-	return 0;
-}
-
-// Emulation
-
-// see sap_cpu_io.h for read/write functions
-
-void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
-{
-	if ( (addr ^ Sap_Apu::start_addr) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) )
-	{
-		GME_APU_HOOK( this, addr - Sap_Apu::start_addr, data );
-		apu.write_data( time() & time_mask, addr, data );
-		return;
-	}
-
-	if ( (addr ^ (Sap_Apu::start_addr + 0x10)) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) &&
-			info.stereo )
-	{
-		GME_APU_HOOK( this, addr - 0x10 - Sap_Apu::start_addr + 10, data );
-		apu2.write_data( time() & time_mask, addr ^ 0x10, data );
-		return;
-	}
-
-	if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
-		debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data );
-}
-
-inline void Sap_Emu::call_play()
-{
-	switch ( info.type )
-	{
-	case 'B':
-		cpu_jsr( info.play_addr );
-		break;
-
-	case 'C':
-		cpu_jsr( info.play_addr + 6 );
-		break;
-	}
-}
-
-blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
-{
-	set_time( 0 );
-	while ( time() < duration )
-	{
-		if ( cpu::run( duration ) || r.pc > idle_addr )
-			return "Emulation error (illegal instruction)";
-
-		if ( r.pc == idle_addr )
-		{
-			if ( next_play <= duration )
-			{
-				set_time( next_play );
-				next_play += play_period();
-				call_play();
-				GME_FRAME_HOOK( this );
-			}
-			else
-			{
-				set_time( duration );
-			}
-		}
-	}
-
-	duration = time();
-	next_play -= duration;
-	check( next_play >= 0 );
-	if ( next_play < 0 )
-		next_play = 0;
-	apu.end_frame( duration );
-	if ( info.stereo )
-		apu2.end_frame( duration );
-
-	return 0;
-}
diff --git a/src/console/Sap_Emu.h b/src/console/Sap_Emu.h
index 818129a5ea7a..426ad3e7596c 100644
--- a/src/console/Sap_Emu.h
+++ b/src/console/Sap_Emu.h
@@ -24,7 +24,9 @@ public:
 		int  type;
 		int  track_count;
 		int  fastplay;
+		int  length;
 		bool stereo;
+		bool ntsc;
 		char author    [256];
 		char name      [256];
 		char copyright [ 32];
diff --git a/src/console/Sms_Apu.cc b/src/console/Sms_Apu.cc
new file mode 100644
index 000000000000..60d093701694
--- /dev/null
+++ b/src/console/Sms_Apu.cc
@@ -0,0 +1,330 @@
+// Sms_Snd_Emu 0.1.4. http://www.slack.net/~ant/
+
+#include "Sms_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Sms_Osc
+
+Sms_Osc::Sms_Osc()
+{
+	output = 0;
+	outputs [0] = 0; // always stays nullptr
+	outputs [1] = 0;
+	outputs [2] = 0;
+	outputs [3] = 0;
+}
+
+void Sms_Osc::reset()
+{
+	delay = 0;
+	last_amp = 0;
+	volume = 0;
+	output_select = 3;
+	output = outputs [3];
+}
+
+// Sms_Square
+
+inline void Sms_Square::reset()
+{
+	period = 0;
+	phase = 0;
+	Sms_Osc::reset();
+}
+
+void Sms_Square::run( blip_time_t time, blip_time_t end_time )
+{
+	if ( !volume || period <= 128 )
+	{
+		// ignore 16kHz and higher
+		if ( last_amp )
+		{
+			synth->offset( time, -last_amp, output );
+			last_amp = 0;
+		}
+		time += delay;
+		if ( !period )
+		{
+			time = end_time;
+		}
+		else if ( time < end_time )
+		{
+			// keep calculating phase
+			int count = (end_time - time + period - 1) / period;
+			phase = (phase + count) & 1;
+			time += count * period;
+		}
+	}
+	else
+	{
+		int amp = phase ? volume : -volume;
+		{
+			int delta = amp - last_amp;
+			if ( delta )
+			{
+				last_amp = amp;
+				synth->offset( time, delta, output );
+			}
+		}
+
+		time += delay;
+		if ( time < end_time )
+		{
+			Blip_Buffer* const output = this->output;
+			int delta = amp * 2;
+			do
+			{
+				delta = -delta;
+				synth->offset_inline( time, delta, output );
+				time += period;
+				phase ^= 1;
+			}
+			while ( time < end_time );
+			this->last_amp = phase ? volume : -volume;
+		}
+	}
+	delay = time - end_time;
+}
+
+// Sms_Noise
+
+static int const noise_periods [3] = { 0x100, 0x200, 0x400 };
+
+inline void Sms_Noise::reset()
+{
+	period = &noise_periods [0];
+	shifter = 0x8000;
+	feedback = 0x9000;
+	Sms_Osc::reset();
+}
+
+void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
+{
+	int amp = volume;
+	if ( shifter & 1 )
+		amp = -amp;
+
+	{
+		int delta = amp - last_amp;
+		if ( delta )
+		{
+			last_amp = amp;
+			synth.offset( time, delta, output );
+		}
+	}
+
+	time += delay;
+	if ( !volume )
+		time = end_time;
+
+	if ( time < end_time )
+	{
+		Blip_Buffer* const output = this->output;
+		unsigned shifter = this->shifter;
+		int delta = amp * 2;
+		int period = *this->period * 2;
+		if ( !period )
+			period = 16;
+
+		do
+		{
+			int changed = shifter + 1;
+			shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1);
+			if ( changed & 2 ) // true if bits 0 and 1 differ
+			{
+				delta = -delta;
+				synth.offset_inline( time, delta, output );
+			}
+			time += period;
+		}
+		while ( time < end_time );
+
+		this->shifter = shifter;
+		this->last_amp = delta >> 1;
+	}
+	delay = time - end_time;
+}
+
+// Sms_Apu
+
+Sms_Apu::Sms_Apu()
+{
+	for ( int i = 0; i < 3; i++ )
+	{
+		squares [i].synth = &square_synth;
+		oscs [i] = &squares [i];
+	}
+	oscs [3] = &noise;
+
+	volume( 1.0 );
+	reset();
+}
+
+Sms_Apu::~Sms_Apu()
+{
+}
+
+void Sms_Apu::volume( double vol )
+{
+	vol *= 0.85 / (osc_count * 64 * 2);
+	square_synth.volume( vol );
+	noise.synth.volume( vol );
+}
+
+void Sms_Apu::treble_eq( const blip_eq_t& eq )
+{
+	square_synth.treble_eq( eq );
+	noise.synth.treble_eq( eq );
+}
+
+void Sms_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	require( (unsigned) index < osc_count );
+	require( (center && left && right) || (!center && !left && !right) );
+	Sms_Osc& osc = *oscs [index];
+	osc.outputs [1] = right;
+	osc.outputs [2] = left;
+	osc.outputs [3] = center;
+	osc.output = osc.outputs [osc.output_select];
+}
+
+void Sms_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+	for ( int i = 0; i < osc_count; i++ )
+		osc_output( i, center, left, right );
+}
+
+void Sms_Apu::reset( unsigned feedback, int noise_width )
+{
+	last_time = 0;
+	latch = 0;
+
+	if ( !feedback || !noise_width )
+	{
+		feedback = 0x0009;
+		noise_width = 16;
+	}
+	// convert to "Galios configuration"
+	looped_feedback = 1 << (noise_width - 1);
+	noise_feedback  = 0;
+	while ( noise_width-- )
+	{
+		noise_feedback = (noise_feedback << 1) | (feedback & 1);
+		feedback >>= 1;
+	}
+
+	squares [0].reset();
+	squares [1].reset();
+	squares [2].reset();
+	noise.reset();
+}
+
+void Sms_Apu::run_until( blip_time_t end_time )
+{
+	require( end_time >= last_time ); // end_time must not be before previous time
+
+	if ( end_time > last_time )
+	{
+		// run oscillators
+		for ( int i = 0; i < osc_count; ++i )
+		{
+			Sms_Osc& osc = *oscs [i];
+			if ( osc.output )
+			{
+				osc.output->set_modified();
+				if ( i < 3 )
+					squares [i].run( last_time, end_time );
+				else
+					noise.run( last_time, end_time );
+			}
+		}
+
+		last_time = end_time;
+	}
+}
+
+void Sms_Apu::end_frame( blip_time_t end_time )
+{
+	if ( end_time > last_time )
+		run_until( end_time );
+
+	assert( last_time >= end_time );
+	last_time -= end_time;
+}
+
+void Sms_Apu::write_ggstereo( blip_time_t time, int data )
+{
+	require( (unsigned) data <= 0xFF );
+
+	run_until( time );
+
+	for ( int i = 0; i < osc_count; i++ )
+	{
+		Sms_Osc& osc = *oscs [i];
+		int flags = data >> i;
+		Blip_Buffer* old_output = osc.output;
+		osc.output_select = (flags >> 3 & 2) | (flags & 1);
+		osc.output = osc.outputs [osc.output_select];
+		if ( osc.output != old_output && osc.last_amp )
+		{
+			if ( old_output )
+			{
+				old_output->set_modified();
+				square_synth.offset( time, -osc.last_amp, old_output );
+			}
+			osc.last_amp = 0;
+		}
+	}
+}
+
+// volumes [i] = 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
+static unsigned char const volumes [16] = {
+	64, 50, 39, 31, 24, 19, 15, 12, 9, 7, 5, 4, 3, 2, 1, 0
+};
+
+void Sms_Apu::write_data( blip_time_t time, int data )
+{
+	require( (unsigned) data <= 0xFF );
+
+	run_until( time );
+
+	if ( data & 0x80 )
+		latch = data;
+
+	int index = (latch >> 5) & 3;
+	if ( latch & 0x10 )
+	{
+		oscs [index]->volume = volumes [data & 15];
+	}
+	else if ( index < 3 )
+	{
+		Sms_Square& sq = squares [index];
+		if ( data & 0x80 )
+			sq.period = (sq.period & 0xFF00) | (data << 4 & 0x00FF);
+		else
+			sq.period = (sq.period & 0x00FF) | (data << 8 & 0x3F00);
+	}
+	else
+	{
+		int select = data & 3;
+		if ( select < 3 )
+			noise.period = &noise_periods [select];
+		else
+			noise.period = &squares [2].period;
+
+		noise.feedback = (data & 0x04) ? noise_feedback : looped_feedback;
+		noise.shifter = 0x8000;
+	}
+}
diff --git a/src/console/Sms_Apu.cxx b/src/console/Sms_Apu.cxx
deleted file mode 100644
index 7a91385f4786..000000000000
--- a/src/console/Sms_Apu.cxx
+++ /dev/null
@@ -1,330 +0,0 @@
-// Sms_Snd_Emu 0.1.4. http://www.slack.net/~ant/
-
-#include "Sms_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Sms_Osc
-
-Sms_Osc::Sms_Osc()
-{
-	output = 0;
-	outputs [0] = 0; // always stays NULL
-	outputs [1] = 0;
-	outputs [2] = 0;
-	outputs [3] = 0;
-}
-
-void Sms_Osc::reset()
-{
-	delay = 0;
-	last_amp = 0;
-	volume = 0;
-	output_select = 3;
-	output = outputs [3];
-}
-
-// Sms_Square
-
-inline void Sms_Square::reset()
-{
-	period = 0;
-	phase = 0;
-	Sms_Osc::reset();
-}
-
-void Sms_Square::run( blip_time_t time, blip_time_t end_time )
-{
-	if ( !volume || period <= 128 )
-	{
-		// ignore 16kHz and higher
-		if ( last_amp )
-		{
-			synth->offset( time, -last_amp, output );
-			last_amp = 0;
-		}
-		time += delay;
-		if ( !period )
-		{
-			time = end_time;
-		}
-		else if ( time < end_time )
-		{
-			// keep calculating phase
-			int count = (end_time - time + period - 1) / period;
-			phase = (phase + count) & 1;
-			time += count * period;
-		}
-	}
-	else
-	{
-		int amp = phase ? volume : -volume;
-		{
-			int delta = amp - last_amp;
-			if ( delta )
-			{
-				last_amp = amp;
-				synth->offset( time, delta, output );
-			}
-		}
-
-		time += delay;
-		if ( time < end_time )
-		{
-			Blip_Buffer* const output = this->output;
-			int delta = amp * 2;
-			do
-			{
-				delta = -delta;
-				synth->offset_inline( time, delta, output );
-				time += period;
-				phase ^= 1;
-			}
-			while ( time < end_time );
-			this->last_amp = phase ? volume : -volume;
-		}
-	}
-	delay = time - end_time;
-}
-
-// Sms_Noise
-
-static int const noise_periods [3] = { 0x100, 0x200, 0x400 };
-
-inline void Sms_Noise::reset()
-{
-	period = &noise_periods [0];
-	shifter = 0x8000;
-	feedback = 0x9000;
-	Sms_Osc::reset();
-}
-
-void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
-{
-	int amp = volume;
-	if ( shifter & 1 )
-		amp = -amp;
-
-	{
-		int delta = amp - last_amp;
-		if ( delta )
-		{
-			last_amp = amp;
-			synth.offset( time, delta, output );
-		}
-	}
-
-	time += delay;
-	if ( !volume )
-		time = end_time;
-
-	if ( time < end_time )
-	{
-		Blip_Buffer* const output = this->output;
-		unsigned shifter = this->shifter;
-		int delta = amp * 2;
-		int period = *this->period * 2;
-		if ( !period )
-			period = 16;
-
-		do
-		{
-			int changed = shifter + 1;
-			shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1);
-			if ( changed & 2 ) // true if bits 0 and 1 differ
-			{
-				delta = -delta;
-				synth.offset_inline( time, delta, output );
-			}
-			time += period;
-		}
-		while ( time < end_time );
-
-		this->shifter = shifter;
-		this->last_amp = delta >> 1;
-	}
-	delay = time - end_time;
-}
-
-// Sms_Apu
-
-Sms_Apu::Sms_Apu()
-{
-	for ( int i = 0; i < 3; i++ )
-	{
-		squares [i].synth = &square_synth;
-		oscs [i] = &squares [i];
-	}
-	oscs [3] = &noise;
-
-	volume( 1.0 );
-	reset();
-}
-
-Sms_Apu::~Sms_Apu()
-{
-}
-
-void Sms_Apu::volume( double vol )
-{
-	vol *= 0.85 / (osc_count * 64 * 2);
-	square_synth.volume( vol );
-	noise.synth.volume( vol );
-}
-
-void Sms_Apu::treble_eq( const blip_eq_t& eq )
-{
-	square_synth.treble_eq( eq );
-	noise.synth.treble_eq( eq );
-}
-
-void Sms_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	require( (unsigned) index < osc_count );
-	require( (center && left && right) || (!center && !left && !right) );
-	Sms_Osc& osc = *oscs [index];
-	osc.outputs [1] = right;
-	osc.outputs [2] = left;
-	osc.outputs [3] = center;
-	osc.output = osc.outputs [osc.output_select];
-}
-
-void Sms_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
-	for ( int i = 0; i < osc_count; i++ )
-		osc_output( i, center, left, right );
-}
-
-void Sms_Apu::reset( unsigned feedback, int noise_width )
-{
-	last_time = 0;
-	latch = 0;
-
-	if ( !feedback || !noise_width )
-	{
-		feedback = 0x0009;
-		noise_width = 16;
-	}
-	// convert to "Galios configuration"
-	looped_feedback = 1 << (noise_width - 1);
-	noise_feedback  = 0;
-	while ( noise_width-- )
-	{
-		noise_feedback = (noise_feedback << 1) | (feedback & 1);
-		feedback >>= 1;
-	}
-
-	squares [0].reset();
-	squares [1].reset();
-	squares [2].reset();
-	noise.reset();
-}
-
-void Sms_Apu::run_until( blip_time_t end_time )
-{
-	require( end_time >= last_time ); // end_time must not be before previous time
-
-	if ( end_time > last_time )
-	{
-		// run oscillators
-		for ( int i = 0; i < osc_count; ++i )
-		{
-			Sms_Osc& osc = *oscs [i];
-			if ( osc.output )
-			{
-				osc.output->set_modified();
-				if ( i < 3 )
-					squares [i].run( last_time, end_time );
-				else
-					noise.run( last_time, end_time );
-			}
-		}
-
-		last_time = end_time;
-	}
-}
-
-void Sms_Apu::end_frame( blip_time_t end_time )
-{
-	if ( end_time > last_time )
-		run_until( end_time );
-
-	assert( last_time >= end_time );
-	last_time -= end_time;
-}
-
-void Sms_Apu::write_ggstereo( blip_time_t time, int data )
-{
-	require( (unsigned) data <= 0xFF );
-
-	run_until( time );
-
-	for ( int i = 0; i < osc_count; i++ )
-	{
-		Sms_Osc& osc = *oscs [i];
-		int flags = data >> i;
-		Blip_Buffer* old_output = osc.output;
-		osc.output_select = (flags >> 3 & 2) | (flags & 1);
-		osc.output = osc.outputs [osc.output_select];
-		if ( osc.output != old_output && osc.last_amp )
-		{
-			if ( old_output )
-			{
-				old_output->set_modified();
-				square_synth.offset( time, -osc.last_amp, old_output );
-			}
-			osc.last_amp = 0;
-		}
-	}
-}
-
-// volumes [i] = 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
-static unsigned char const volumes [16] = {
-	64, 50, 39, 31, 24, 19, 15, 12, 9, 7, 5, 4, 3, 2, 1, 0
-};
-
-void Sms_Apu::write_data( blip_time_t time, int data )
-{
-	require( (unsigned) data <= 0xFF );
-
-	run_until( time );
-
-	if ( data & 0x80 )
-		latch = data;
-
-	int index = (latch >> 5) & 3;
-	if ( latch & 0x10 )
-	{
-		oscs [index]->volume = volumes [data & 15];
-	}
-	else if ( index < 3 )
-	{
-		Sms_Square& sq = squares [index];
-		if ( data & 0x80 )
-			sq.period = (sq.period & 0xFF00) | (data << 4 & 0x00FF);
-		else
-			sq.period = (sq.period & 0x00FF) | (data << 8 & 0x3F00);
-	}
-	else
-	{
-		int select = data & 3;
-		if ( select < 3 )
-			noise.period = &noise_periods [select];
-		else
-			noise.period = &squares [2].period;
-
-		noise.feedback = (data & 0x04) ? noise_feedback : looped_feedback;
-		noise.shifter = 0x8000;
-	}
-}
diff --git a/src/console/Sms_Apu.h b/src/console/Sms_Apu.h
index ec8bc87ec379..c8401f10aab5 100644
--- a/src/console/Sms_Apu.h
+++ b/src/console/Sms_Apu.h
@@ -18,12 +18,12 @@ public:
 	// buffers for stereo output (using Stereo_Buffer to do the mixing).
 
 	// Assign all oscillator outputs to specified buffer(s). If buffer
-	// is NULL, silences all oscillators.
+	// is nullptr, silences all oscillators.
 	void output( Blip_Buffer* mono );
 	void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
 
 	// Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
-	// which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL,
+	// which refer to Square 1, Square 2, Square 3, and Noise. If buffer is nullptr,
 	// silences oscillator.
 	enum { osc_count = 4 };
 	void osc_output( int index, Blip_Buffer* mono );
diff --git a/src/console/Sms_Oscs.h b/src/console/Sms_Oscs.h
index 282cb18a0af4..ba7e14d90d67 100644
--- a/src/console/Sms_Oscs.h
+++ b/src/console/Sms_Oscs.h
@@ -9,7 +9,7 @@
 
 struct Sms_Osc
 {
-	Blip_Buffer* outputs [4]; // NULL, right, left, center
+	Blip_Buffer* outputs [4]; // nullptr, right, left, center
 	Blip_Buffer* output;
 	int output_select;
 
diff --git a/src/console/Snes_Spc.cc b/src/console/Snes_Spc.cc
new file mode 100644
index 000000000000..2b2e9eff229f
--- /dev/null
+++ b/src/console/Snes_Spc.cc
@@ -0,0 +1,380 @@
+// SPC emulation support: init, sample buffering, reset, SPC loading
+
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Snes_Spc.h"
+
+#include <string.h>
+
+/* Copyright (C) 2004-2007 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#define RAM         (m.ram.ram)
+#define REGS        (m.smp_regs [0])
+#define REGS_IN     (m.smp_regs [1])
+
+// (n ? n : 256)
+#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
+
+
+//// Init
+
+blargg_err_t Snes_Spc::init()
+{
+	memset( &m, 0, sizeof m );
+	dsp.init( RAM );
+
+	m.tempo = tempo_unit;
+
+	// Most SPC music doesn't need ROM, and almost all the rest only rely
+	// on these two bytes
+	m.rom [0x3E] = 0xFF;
+	m.rom [0x3F] = 0xC0;
+
+	static unsigned char const cycle_table [128] =
+	{//   01   23   45   67   89   AB   CD   EF
+	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0
+	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1
+	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2
+	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3
+	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4
+	    0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5
+	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6
+	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7
+	    0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8
+	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9
+	    0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A
+	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B
+	    0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C
+	    0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D
+	    0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E
+	    0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F
+	};
+
+	// unpack cycle table
+	for ( int i = 0; i < 128; i++ )
+	{
+		int n = cycle_table [i];
+		m.cycle_table [i * 2 + 0] = n >> 4;
+		m.cycle_table [i * 2 + 1] = n & 0x0F;
+	}
+
+	#if SPC_LESS_ACCURATE
+		memcpy( reg_times, reg_times_, sizeof reg_times );
+	#endif
+
+	reset();
+	return 0;
+}
+
+void Snes_Spc::init_rom( uint8_t const in [rom_size] )
+{
+	memcpy( m.rom, in, sizeof m.rom );
+}
+
+void Snes_Spc::set_tempo( int t )
+{
+	m.tempo = t;
+	int const timer2_shift = 4; // 64 kHz
+	int const other_shift  = 3; //  8 kHz
+
+	#if SPC_DISABLE_TEMPO
+		m.timers [2].prescaler = timer2_shift;
+		m.timers [1].prescaler = timer2_shift + other_shift;
+		m.timers [0].prescaler = timer2_shift + other_shift;
+	#else
+		if ( !t )
+			t = 1;
+		int const timer2_rate  = 1 << timer2_shift;
+		int rate = (timer2_rate * tempo_unit + (t >> 1)) / t;
+		if ( rate < timer2_rate / 4 )
+			rate = timer2_rate / 4; // max 4x tempo
+		m.timers [2].prescaler = rate;
+		m.timers [1].prescaler = rate << other_shift;
+		m.timers [0].prescaler = rate << other_shift;
+	#endif
+}
+
+// Timer registers have been loaded. Applies these to the timers. Does not
+// reset timer prescalers or dividers.
+void Snes_Spc::timers_loaded()
+{
+	int i;
+	for ( i = 0; i < timer_count; i++ )
+	{
+		Timer* t = &m.timers [i];
+		t->period  = IF_0_THEN_256( REGS [r_t0target + i] );
+		t->enabled = REGS [r_control] >> i & 1;
+		t->counter = REGS_IN [r_t0out + i] & 0x0F;
+	}
+
+	set_tempo( m.tempo );
+}
+
+// Loads registers from unified 16-byte format
+void Snes_Spc::load_regs( uint8_t const in [reg_count] )
+{
+	memcpy( REGS, in, reg_count );
+	memcpy( REGS_IN, REGS, reg_count );
+
+	// These always read back as 0
+	REGS_IN [r_test    ] = 0;
+	REGS_IN [r_control ] = 0;
+	REGS_IN [r_t0target] = 0;
+	REGS_IN [r_t1target] = 0;
+	REGS_IN [r_t2target] = 0;
+}
+
+// RAM was just loaded from SPC, with $F0-$FF containing SMP registers
+// and timer counts. Copies these to proper registers.
+void Snes_Spc::ram_loaded()
+{
+	m.rom_enabled = 0;
+	load_regs( &RAM [0xF0] );
+
+	// Put STOP instruction around memory to catch PC underflow/overflow
+	memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 );
+	memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 );
+}
+
+// Registers were just loaded. Applies these new values.
+void Snes_Spc::regs_loaded()
+{
+	enable_rom( REGS [r_control] & 0x80 );
+	timers_loaded();
+}
+
+void Snes_Spc::reset_time_regs()
+{
+	m.cpu_error     = 0;
+	m.echo_accessed = 0;
+	m.spc_time      = 0;
+	m.dsp_time      = 0;
+	#if SPC_LESS_ACCURATE
+		m.dsp_time = clocks_per_sample + 1;
+	#endif
+
+	for ( int i = 0; i < timer_count; i++ )
+	{
+		Timer* t = &m.timers [i];
+		t->next_time = 1;
+		t->divider   = 0;
+	}
+
+	regs_loaded();
+
+	m.extra_clocks = 0;
+	reset_buf();
+}
+
+void Snes_Spc::reset_common( int timer_counter_init )
+{
+	int i;
+	for ( i = 0; i < timer_count; i++ )
+		REGS_IN [r_t0out + i] = timer_counter_init;
+
+	// Run IPL ROM
+	memset( &m.cpu_regs, 0, sizeof m.cpu_regs );
+	m.cpu_regs.pc = rom_addr;
+
+	REGS [r_test   ] = 0x0A;
+	REGS [r_control] = 0xB0; // ROM enabled, clear ports
+	for ( i = 0; i < port_count; i++ )
+		REGS_IN [r_cpuio0 + i] = 0;
+
+	reset_time_regs();
+}
+
+void Snes_Spc::soft_reset()
+{
+	reset_common( 0 );
+	dsp.soft_reset();
+}
+
+void Snes_Spc::reset()
+{
+	memset( RAM, 0xFF, 0x10000 );
+	ram_loaded();
+	reset_common( 0x0F );
+	dsp.reset();
+}
+
+char const Snes_Spc::signature [signature_size + 1] =
+		"SNES-SPC700 Sound File Data v0.30\x1A\x1A";
+
+blargg_err_t Snes_Spc::load_spc( void const* data, long size )
+{
+	spc_file_t const* const spc = (spc_file_t const*) data;
+
+	// be sure compiler didn't insert any padding into fle_t
+	assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 );
+
+	// Check signature and file size
+	if ( size < signature_size || memcmp( spc, signature, 27 ) )
+		return "Not an SPC file";
+
+	if ( size < spc_min_file_size )
+		return "Corrupt SPC file";
+
+	// CPU registers
+	m.cpu_regs.pc  = spc->pch * 0x100 + spc->pcl;
+	m.cpu_regs.a   = spc->a;
+	m.cpu_regs.x   = spc->x;
+	m.cpu_regs.y   = spc->y;
+	m.cpu_regs.psw = spc->psw;
+	m.cpu_regs.sp  = spc->sp;
+
+	// RAM and registers
+	memcpy( RAM, spc->ram, 0x10000 );
+	ram_loaded();
+
+	// DSP registers
+	dsp.load( spc->dsp );
+
+	reset_time_regs();
+
+	return 0;
+}
+
+void Snes_Spc::clear_echo()
+{
+	if ( !(dsp.read( Spc_Dsp::r_flg ) & 0x20) )
+	{
+		int addr = 0x100 * dsp.read( Spc_Dsp::r_esa );
+		int end  = addr + 0x800 * (dsp.read( Spc_Dsp::r_edl ) & 0x0F);
+		if ( end > 0x10000 )
+			end = 0x10000;
+		memset( &RAM [addr], 0xFF, end - addr );
+	}
+}
+
+
+//// Sample output
+
+void Snes_Spc::reset_buf()
+{
+	// Start with half extra buffer of silence
+	sample_t* out = m.extra_buf;
+	while ( out < &m.extra_buf [extra_size / 2] )
+		*out++ = 0;
+
+	m.extra_pos = out;
+	m.buf_begin = 0;
+
+	dsp.set_output( 0, 0 );
+}
+
+void Snes_Spc::set_output( sample_t* out, int size )
+{
+	require( (size & 1) == 0 ); // size must be even
+
+	m.extra_clocks &= clocks_per_sample - 1;
+	if ( out )
+	{
+		sample_t const* out_end = out + size;
+		m.buf_begin = out;
+		m.buf_end   = out_end;
+
+		// Copy extra to output
+		sample_t const* in = m.extra_buf;
+		while ( in < m.extra_pos && out < out_end )
+			*out++ = *in++;
+
+		// Handle output being full already
+		if ( out >= out_end )
+		{
+			// Have DSP write to remaining extra space
+			out     = dsp.extra();
+			out_end = &dsp.extra() [extra_size];
+
+			// Copy any remaining extra samples as if DSP wrote them
+			while ( in < m.extra_pos )
+				*out++ = *in++;
+			assert( out <= out_end );
+		}
+
+		dsp.set_output( out, out_end - out );
+	}
+	else
+	{
+		reset_buf();
+	}
+}
+
+void Snes_Spc::save_extra()
+{
+	// Get end pointers
+	sample_t const* main_end = m.buf_end;     // end of data written to buf
+	sample_t const* dsp_end  = dsp.out_pos(); // end of data written to dsp.extra()
+	if ( m.buf_begin <= dsp_end && dsp_end <= main_end )
+	{
+		main_end = dsp_end;
+		dsp_end  = dsp.extra(); // nothing in DSP's extra
+	}
+
+	// Copy any extra samples at these ends into extra_buf
+	sample_t* out = m.extra_buf;
+	sample_t const* in;
+	for ( in = m.buf_begin + sample_count(); in < main_end; in++ )
+		*out++ = *in;
+	for ( in = dsp.extra(); in < dsp_end ; in++ )
+		*out++ = *in;
+
+	m.extra_pos = out;
+	assert( out <= &m.extra_buf [extra_size] );
+}
+
+blargg_err_t Snes_Spc::play( int count, sample_t* out )
+{
+	require( (count & 1) == 0 ); // must be even
+	if ( count )
+	{
+		set_output( out, count );
+		end_frame( count * (clocks_per_sample / 2) );
+	}
+
+	const char* err = m.cpu_error;
+	m.cpu_error = 0;
+	return err;
+}
+
+blargg_err_t Snes_Spc::skip( int count )
+{
+	#if SPC_LESS_ACCURATE
+	if ( count > 2 * sample_rate * 2 )
+	{
+		set_output( 0, 0 );
+
+		// Skip a multiple of 4 samples
+		time_t end = count;
+		count = (count & 3) + 1 * sample_rate * 2;
+		end = (end - count) * (clocks_per_sample / 2);
+
+		m.skipped_kon  = 0;
+		m.skipped_koff = 0;
+
+		// Preserve DSP and timer synchronization
+		// TODO: verify that this really preserves it
+		int old_dsp_time = m.dsp_time + m.spc_time;
+		m.dsp_time = end - m.spc_time + skipping_time;
+		end_frame( end );
+		m.dsp_time = m.dsp_time - skipping_time + old_dsp_time;
+
+		dsp.write( Spc_Dsp::r_koff, m.skipped_koff & ~m.skipped_kon );
+		dsp.write( Spc_Dsp::r_kon , m.skipped_kon );
+		clear_echo();
+	}
+	#endif
+
+	return play( count, 0 );
+}
diff --git a/src/console/Snes_Spc.cxx b/src/console/Snes_Spc.cxx
deleted file mode 100644
index 2b2e9eff229f..000000000000
--- a/src/console/Snes_Spc.cxx
+++ /dev/null
@@ -1,380 +0,0 @@
-// SPC emulation support: init, sample buffering, reset, SPC loading
-
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Snes_Spc.h"
-
-#include <string.h>
-
-/* Copyright (C) 2004-2007 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#define RAM         (m.ram.ram)
-#define REGS        (m.smp_regs [0])
-#define REGS_IN     (m.smp_regs [1])
-
-// (n ? n : 256)
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-
-
-//// Init
-
-blargg_err_t Snes_Spc::init()
-{
-	memset( &m, 0, sizeof m );
-	dsp.init( RAM );
-
-	m.tempo = tempo_unit;
-
-	// Most SPC music doesn't need ROM, and almost all the rest only rely
-	// on these two bytes
-	m.rom [0x3E] = 0xFF;
-	m.rom [0x3F] = 0xC0;
-
-	static unsigned char const cycle_table [128] =
-	{//   01   23   45   67   89   AB   CD   EF
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0
-	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2
-	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3
-	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4
-	    0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5
-	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9
-	    0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B
-	    0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C
-	    0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D
-	    0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E
-	    0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F
-	};
-
-	// unpack cycle table
-	for ( int i = 0; i < 128; i++ )
-	{
-		int n = cycle_table [i];
-		m.cycle_table [i * 2 + 0] = n >> 4;
-		m.cycle_table [i * 2 + 1] = n & 0x0F;
-	}
-
-	#if SPC_LESS_ACCURATE
-		memcpy( reg_times, reg_times_, sizeof reg_times );
-	#endif
-
-	reset();
-	return 0;
-}
-
-void Snes_Spc::init_rom( uint8_t const in [rom_size] )
-{
-	memcpy( m.rom, in, sizeof m.rom );
-}
-
-void Snes_Spc::set_tempo( int t )
-{
-	m.tempo = t;
-	int const timer2_shift = 4; // 64 kHz
-	int const other_shift  = 3; //  8 kHz
-
-	#if SPC_DISABLE_TEMPO
-		m.timers [2].prescaler = timer2_shift;
-		m.timers [1].prescaler = timer2_shift + other_shift;
-		m.timers [0].prescaler = timer2_shift + other_shift;
-	#else
-		if ( !t )
-			t = 1;
-		int const timer2_rate  = 1 << timer2_shift;
-		int rate = (timer2_rate * tempo_unit + (t >> 1)) / t;
-		if ( rate < timer2_rate / 4 )
-			rate = timer2_rate / 4; // max 4x tempo
-		m.timers [2].prescaler = rate;
-		m.timers [1].prescaler = rate << other_shift;
-		m.timers [0].prescaler = rate << other_shift;
-	#endif
-}
-
-// Timer registers have been loaded. Applies these to the timers. Does not
-// reset timer prescalers or dividers.
-void Snes_Spc::timers_loaded()
-{
-	int i;
-	for ( i = 0; i < timer_count; i++ )
-	{
-		Timer* t = &m.timers [i];
-		t->period  = IF_0_THEN_256( REGS [r_t0target + i] );
-		t->enabled = REGS [r_control] >> i & 1;
-		t->counter = REGS_IN [r_t0out + i] & 0x0F;
-	}
-
-	set_tempo( m.tempo );
-}
-
-// Loads registers from unified 16-byte format
-void Snes_Spc::load_regs( uint8_t const in [reg_count] )
-{
-	memcpy( REGS, in, reg_count );
-	memcpy( REGS_IN, REGS, reg_count );
-
-	// These always read back as 0
-	REGS_IN [r_test    ] = 0;
-	REGS_IN [r_control ] = 0;
-	REGS_IN [r_t0target] = 0;
-	REGS_IN [r_t1target] = 0;
-	REGS_IN [r_t2target] = 0;
-}
-
-// RAM was just loaded from SPC, with $F0-$FF containing SMP registers
-// and timer counts. Copies these to proper registers.
-void Snes_Spc::ram_loaded()
-{
-	m.rom_enabled = 0;
-	load_regs( &RAM [0xF0] );
-
-	// Put STOP instruction around memory to catch PC underflow/overflow
-	memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 );
-	memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 );
-}
-
-// Registers were just loaded. Applies these new values.
-void Snes_Spc::regs_loaded()
-{
-	enable_rom( REGS [r_control] & 0x80 );
-	timers_loaded();
-}
-
-void Snes_Spc::reset_time_regs()
-{
-	m.cpu_error     = 0;
-	m.echo_accessed = 0;
-	m.spc_time      = 0;
-	m.dsp_time      = 0;
-	#if SPC_LESS_ACCURATE
-		m.dsp_time = clocks_per_sample + 1;
-	#endif
-
-	for ( int i = 0; i < timer_count; i++ )
-	{
-		Timer* t = &m.timers [i];
-		t->next_time = 1;
-		t->divider   = 0;
-	}
-
-	regs_loaded();
-
-	m.extra_clocks = 0;
-	reset_buf();
-}
-
-void Snes_Spc::reset_common( int timer_counter_init )
-{
-	int i;
-	for ( i = 0; i < timer_count; i++ )
-		REGS_IN [r_t0out + i] = timer_counter_init;
-
-	// Run IPL ROM
-	memset( &m.cpu_regs, 0, sizeof m.cpu_regs );
-	m.cpu_regs.pc = rom_addr;
-
-	REGS [r_test   ] = 0x0A;
-	REGS [r_control] = 0xB0; // ROM enabled, clear ports
-	for ( i = 0; i < port_count; i++ )
-		REGS_IN [r_cpuio0 + i] = 0;
-
-	reset_time_regs();
-}
-
-void Snes_Spc::soft_reset()
-{
-	reset_common( 0 );
-	dsp.soft_reset();
-}
-
-void Snes_Spc::reset()
-{
-	memset( RAM, 0xFF, 0x10000 );
-	ram_loaded();
-	reset_common( 0x0F );
-	dsp.reset();
-}
-
-char const Snes_Spc::signature [signature_size + 1] =
-		"SNES-SPC700 Sound File Data v0.30\x1A\x1A";
-
-blargg_err_t Snes_Spc::load_spc( void const* data, long size )
-{
-	spc_file_t const* const spc = (spc_file_t const*) data;
-
-	// be sure compiler didn't insert any padding into fle_t
-	assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 );
-
-	// Check signature and file size
-	if ( size < signature_size || memcmp( spc, signature, 27 ) )
-		return "Not an SPC file";
-
-	if ( size < spc_min_file_size )
-		return "Corrupt SPC file";
-
-	// CPU registers
-	m.cpu_regs.pc  = spc->pch * 0x100 + spc->pcl;
-	m.cpu_regs.a   = spc->a;
-	m.cpu_regs.x   = spc->x;
-	m.cpu_regs.y   = spc->y;
-	m.cpu_regs.psw = spc->psw;
-	m.cpu_regs.sp  = spc->sp;
-
-	// RAM and registers
-	memcpy( RAM, spc->ram, 0x10000 );
-	ram_loaded();
-
-	// DSP registers
-	dsp.load( spc->dsp );
-
-	reset_time_regs();
-
-	return 0;
-}
-
-void Snes_Spc::clear_echo()
-{
-	if ( !(dsp.read( Spc_Dsp::r_flg ) & 0x20) )
-	{
-		int addr = 0x100 * dsp.read( Spc_Dsp::r_esa );
-		int end  = addr + 0x800 * (dsp.read( Spc_Dsp::r_edl ) & 0x0F);
-		if ( end > 0x10000 )
-			end = 0x10000;
-		memset( &RAM [addr], 0xFF, end - addr );
-	}
-}
-
-
-//// Sample output
-
-void Snes_Spc::reset_buf()
-{
-	// Start with half extra buffer of silence
-	sample_t* out = m.extra_buf;
-	while ( out < &m.extra_buf [extra_size / 2] )
-		*out++ = 0;
-
-	m.extra_pos = out;
-	m.buf_begin = 0;
-
-	dsp.set_output( 0, 0 );
-}
-
-void Snes_Spc::set_output( sample_t* out, int size )
-{
-	require( (size & 1) == 0 ); // size must be even
-
-	m.extra_clocks &= clocks_per_sample - 1;
-	if ( out )
-	{
-		sample_t const* out_end = out + size;
-		m.buf_begin = out;
-		m.buf_end   = out_end;
-
-		// Copy extra to output
-		sample_t const* in = m.extra_buf;
-		while ( in < m.extra_pos && out < out_end )
-			*out++ = *in++;
-
-		// Handle output being full already
-		if ( out >= out_end )
-		{
-			// Have DSP write to remaining extra space
-			out     = dsp.extra();
-			out_end = &dsp.extra() [extra_size];
-
-			// Copy any remaining extra samples as if DSP wrote them
-			while ( in < m.extra_pos )
-				*out++ = *in++;
-			assert( out <= out_end );
-		}
-
-		dsp.set_output( out, out_end - out );
-	}
-	else
-	{
-		reset_buf();
-	}
-}
-
-void Snes_Spc::save_extra()
-{
-	// Get end pointers
-	sample_t const* main_end = m.buf_end;     // end of data written to buf
-	sample_t const* dsp_end  = dsp.out_pos(); // end of data written to dsp.extra()
-	if ( m.buf_begin <= dsp_end && dsp_end <= main_end )
-	{
-		main_end = dsp_end;
-		dsp_end  = dsp.extra(); // nothing in DSP's extra
-	}
-
-	// Copy any extra samples at these ends into extra_buf
-	sample_t* out = m.extra_buf;
-	sample_t const* in;
-	for ( in = m.buf_begin + sample_count(); in < main_end; in++ )
-		*out++ = *in;
-	for ( in = dsp.extra(); in < dsp_end ; in++ )
-		*out++ = *in;
-
-	m.extra_pos = out;
-	assert( out <= &m.extra_buf [extra_size] );
-}
-
-blargg_err_t Snes_Spc::play( int count, sample_t* out )
-{
-	require( (count & 1) == 0 ); // must be even
-	if ( count )
-	{
-		set_output( out, count );
-		end_frame( count * (clocks_per_sample / 2) );
-	}
-
-	const char* err = m.cpu_error;
-	m.cpu_error = 0;
-	return err;
-}
-
-blargg_err_t Snes_Spc::skip( int count )
-{
-	#if SPC_LESS_ACCURATE
-	if ( count > 2 * sample_rate * 2 )
-	{
-		set_output( 0, 0 );
-
-		// Skip a multiple of 4 samples
-		time_t end = count;
-		count = (count & 3) + 1 * sample_rate * 2;
-		end = (end - count) * (clocks_per_sample / 2);
-
-		m.skipped_kon  = 0;
-		m.skipped_koff = 0;
-
-		// Preserve DSP and timer synchronization
-		// TODO: verify that this really preserves it
-		int old_dsp_time = m.dsp_time + m.spc_time;
-		m.dsp_time = end - m.spc_time + skipping_time;
-		end_frame( end );
-		m.dsp_time = m.dsp_time - skipping_time + old_dsp_time;
-
-		dsp.write( Spc_Dsp::r_koff, m.skipped_koff & ~m.skipped_kon );
-		dsp.write( Spc_Dsp::r_kon , m.skipped_kon );
-		clear_echo();
-	}
-	#endif
-
-	return play( count, 0 );
-}
diff --git a/src/console/Snes_Spc.h b/src/console/Snes_Spc.h
index 63f54ad54d51..477ced4de6cd 100644
--- a/src/console/Snes_Spc.h
+++ b/src/console/Snes_Spc.h
@@ -76,7 +76,7 @@ public:
 	void clear_echo();
 
 	// Plays for count samples and write samples to out. Discards samples if out
-	// is NULL. Count must be a multiple of 2 since output is stereo.
+	// is nullptr. Count must be a multiple of 2 since output is stereo.
 	blargg_err_t play( int count, sample_t* out );
 
 	// Skips count samples. Several times faster than play() when using fast DSP.
diff --git a/src/console/Spc_Cpu.cc b/src/console/Spc_Cpu.cc
new file mode 100644
index 000000000000..603447e9940b
--- /dev/null
+++ b/src/console/Spc_Cpu.cc
@@ -0,0 +1,565 @@
+// Core SPC emulation: CPU, timers, SMP registers, memory
+
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Snes_Spc.h"
+
+#include <string.h>
+
+/* Copyright (C) 2004-2007 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#define RAM         (m.ram.ram)
+#define REGS        (m.smp_regs [0])
+#define REGS_IN     (m.smp_regs [1])
+
+// (n ? n : 256)
+#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
+
+// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which
+// do crazy echo buffer accesses.
+#ifndef SPC_MORE_ACCURACY
+	#define SPC_MORE_ACCURACY 0
+#endif
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+
+//// Timers
+
+#if SPC_DISABLE_TEMPO
+	#define TIMER_DIV( t, n ) ((n) >> t->prescaler)
+	#define TIMER_MUL( t, n ) ((n) << t->prescaler)
+#else
+	#define TIMER_DIV( t, n ) ((n) / t->prescaler)
+	#define TIMER_MUL( t, n ) ((n) * t->prescaler)
+#endif
+
+Snes_Spc::Timer* Snes_Spc::run_timer_( Timer* t, rel_time_t time )
+{
+	int elapsed = TIMER_DIV( t, time - t->next_time ) + 1;
+	t->next_time += TIMER_MUL( t, elapsed );
+
+	if ( t->enabled )
+	{
+		int remain = IF_0_THEN_256( t->period - t->divider );
+		int divider = t->divider + elapsed;
+		int over = elapsed - remain;
+		if ( over >= 0 )
+		{
+			int n = over / t->period;
+			t->counter = (t->counter + 1 + n) & 0x0F;
+			divider = over - n * t->period;
+		}
+		t->divider = (uint8_t) divider;
+	}
+	return t;
+}
+
+inline Snes_Spc::Timer* Snes_Spc::run_timer( Timer* t, rel_time_t time )
+{
+	if ( time >= t->next_time )
+		t = run_timer_( t, time );
+	return t;
+}
+
+
+//// ROM
+
+void Snes_Spc::enable_rom( int enable )
+{
+	if ( m.rom_enabled != enable )
+	{
+		m.rom_enabled = enable;
+		if ( enable )
+			memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram );
+		memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size );
+		// TODO: ROM can still get overwritten when DSP writes to echo buffer
+	}
+}
+
+
+//// DSP
+
+#if SPC_LESS_ACCURATE
+	int const max_reg_time = 29;
+
+	signed char const Snes_Spc::reg_times_ [256] =
+	{
+		 -1,  0,-11,-10,-15,-11, -2, -2,  4,  3, 14, 14, 26, 26, 14, 22,
+		  2,  3,  0,  1,-12,  0,  1,  1,  7,  6, 14, 14, 27, 14, 14, 23,
+		  5,  6,  3,  4, -1,  3,  4,  4, 10,  9, 14, 14, 26, -5, 14, 23,
+		  8,  9,  6,  7,  2,  6,  7,  7, 13, 12, 14, 14, 27, -4, 14, 24,
+		 11, 12,  9, 10,  5,  9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24,
+		 14, 15, 12, 13,  8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24,
+		 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25,
+		 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25,
+
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+	};
+
+	#define RUN_DSP( time, offset ) \
+		int count = (time) - (offset) - m.dsp_time;\
+		if ( count >= 0 )\
+		{\
+			int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\
+			m.dsp_time += clock_count;\
+			dsp.run( clock_count );\
+		}
+#else
+	#define RUN_DSP( time, offset ) \
+		{\
+			int count = (time) - m.dsp_time;\
+			if ( !SPC_MORE_ACCURACY || count )\
+			{\
+				assert( count > 0 );\
+				m.dsp_time = (time);\
+				dsp.run( count );\
+			}\
+		}
+#endif
+
+int Snes_Spc::dsp_read( rel_time_t time )
+{
+	RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] );
+
+	int result = dsp.read( REGS [r_dspaddr] & 0x7F );
+
+	#ifdef SPC_DSP_READ_HOOK
+		SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result );
+	#endif
+
+	return result;
+}
+
+inline void Snes_Spc::dsp_write( int data, rel_time_t time )
+{
+	RUN_DSP( time, reg_times [REGS [r_dspaddr]] )
+	#if SPC_LESS_ACCURATE
+		else if ( m.dsp_time == skipping_time )
+		{
+			int r = REGS [r_dspaddr];
+			if ( r == Spc_Dsp::r_kon )
+				m.skipped_kon |= data & ~dsp.read( Spc_Dsp::r_koff );
+
+			if ( r == Spc_Dsp::r_koff )
+			{
+				m.skipped_koff |= data;
+				m.skipped_kon &= ~data;
+			}
+		}
+	#endif
+
+	#ifdef SPC_DSP_WRITE_HOOK
+		SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data );
+	#endif
+
+	if ( REGS [r_dspaddr] <= 0x7F )
+		dsp.write( REGS [r_dspaddr], data );
+	else if ( !SPC_MORE_ACCURACY )
+		debug_printf( "SPC wrote to DSP register > $7F\n" );
+}
+
+
+//// Memory access extras
+
+#if SPC_MORE_ACCURACY
+	#define MEM_ACCESS( time, addr ) \
+	{\
+		if ( time >= m.dsp_time )\
+		{\
+			RUN_DSP( time, max_reg_time );\
+		}\
+	}
+#elif !defined (NDEBUG)
+	// Debug-only check for read/write within echo buffer, since this might result in
+	// inaccurate emulation due to the DSP not being caught up to the present.
+
+	bool Snes_Spc::check_echo_access( int addr )
+	{
+		if ( !(dsp.read( Spc_Dsp::r_flg ) & 0x20) )
+		{
+			int start = 0x100 * dsp.read( Spc_Dsp::r_esa );
+			int size  = 0x800 * (dsp.read( Spc_Dsp::r_edl ) & 0x0F);
+			int end   = start + (size ? size : 4);
+			if ( start <= addr && addr < end )
+			{
+				if ( !m.echo_accessed )
+				{
+					m.echo_accessed = 1;
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	#define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) );
+#else
+	#define MEM_ACCESS( time, addr )
+#endif
+
+
+//// CPU write
+
+#if SPC_MORE_ACCURACY
+static unsigned char const glitch_probs [3] [256] =
+{
+	0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B,
+	0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08,
+	0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09,
+	0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01,
+	0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05,
+	0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07,
+	0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07,
+	0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01,
+	0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09,
+	0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08,
+	0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03,
+	0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03,
+	0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07,
+	0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02,
+	0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02,
+	0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01,
+
+	0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07,
+	0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06,
+	0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09,
+	0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03,
+	0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07,
+	0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03,
+	0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06,
+	0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03,
+	0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05,
+	0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04,
+	0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05,
+	0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01,
+	0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05,
+	0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01,
+	0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03,
+	0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01,
+
+	0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A,
+	0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A,
+	0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A,
+	0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09,
+	0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09,
+	0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02,
+	0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07,
+	0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04,
+	0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A,
+	0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07,
+	0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04,
+	0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02,
+	0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06,
+	0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03,
+	0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02,
+	0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03,
+};
+#endif
+
+// Read/write handlers are divided into multiple functions to keep rarely-used
+// functionality separate so often-used functionality can be optimized better
+// by compiler.
+
+// If write isn't preceded by read, data has this added to it
+int const no_read_before_write = 0x2000;
+
+void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
+{
+	switch ( addr )
+	{
+	case r_t0target:
+	case r_t1target:
+	case r_t2target: {
+		Timer* t = &m.timers [addr - r_t0target];
+		int period = IF_0_THEN_256( data );
+		if ( t->period != period )
+		{
+			t = run_timer( t, time );
+			#if SPC_MORE_ACCURACY
+				// Insane behavior when target is written just after counter is
+				// clocked and counter matches new period and new period isn't 1, 2, 4, or 8
+				if ( t->divider == (period & 0xFF) &&
+						t->next_time == time + TIMER_MUL( t, 1 ) &&
+						((period - 1) | ~0x0F) & period )
+				{
+					//debug_printf( "SPC pathological timer target write\n" );
+
+					// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
+					// based on the previous period
+					int prob = 0xFF;
+					int old_period = t->period & 0xFF;
+					if ( period == 3 ) prob = glitch_probs [0] [old_period];
+					if ( period == 5 ) prob = glitch_probs [1] [old_period];
+					if ( period == 9 ) prob = glitch_probs [2] [old_period];
+
+					// The glitch suppresses incrementing of one of the counter bits, based on
+					// the lowest set bit in the new period
+					int b = 1;
+					while ( !(period & b) )
+						b <<= 1;
+
+					if ( (rand() >> 4 & 0xFF) <= prob )
+						t->divider = (t->divider - b) & 0xFF;
+				}
+			#endif
+			t->period = period;
+		}
+		break;
+	}
+
+	case r_t0out:
+	case r_t1out:
+	case r_t2out:
+		if ( !SPC_MORE_ACCURACY )
+			debug_printf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
+
+		if ( data < no_read_before_write  / 2 )
+			run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
+		break;
+
+	// Registers that act like RAM
+	case 0x8:
+	case 0x9:
+		REGS_IN [addr] = (uint8_t) data;
+		break;
+
+	case r_test:
+		if ( (uint8_t) data != 0x0A )
+			debug_printf( "SPC wrote to test register\n" );
+		break;
+
+	case r_control:
+		// port clears
+		if ( data & 0x10 )
+		{
+			REGS_IN [r_cpuio0] = 0;
+			REGS_IN [r_cpuio1] = 0;
+		}
+		if ( data & 0x20 )
+		{
+			REGS_IN [r_cpuio2] = 0;
+			REGS_IN [r_cpuio3] = 0;
+		}
+
+		// timers
+		{
+			for ( int i = 0; i < timer_count; i++ )
+			{
+				Timer* t = &m.timers [i];
+				int enabled = data >> i & 1;
+				if ( t->enabled != enabled )
+				{
+					t = run_timer( t, time );
+					t->enabled = enabled;
+					if ( enabled )
+					{
+						t->divider = 0;
+						t->counter = 0;
+					}
+				}
+			}
+		}
+		enable_rom( data & 0x80 );
+		break;
+	}
+}
+
+void Snes_Spc::cpu_write_smp_reg( int data, rel_time_t time, int addr )
+{
+	if ( addr == r_dspdata ) // 99%
+		dsp_write( data, time );
+	else
+		cpu_write_smp_reg_( data, time, addr );
+}
+
+void Snes_Spc::cpu_write_high( int data, int i, rel_time_t time )
+{
+	if ( i < rom_size )
+	{
+		m.hi_ram [i] = (uint8_t) data;
+		if ( m.rom_enabled )
+			RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM
+	}
+	else
+	{
+		assert( RAM [i + rom_addr - 0x10000] == (uint8_t) data );
+		RAM [i + rom_addr - 0x10000] = cpu_pad_fill; // restore overwritten padding
+		cpu_write( data, i + rom_addr - 0x10000, time );
+	}
+}
+
+int const bits_in_int = CHAR_BIT * sizeof (int);
+
+void Snes_Spc::cpu_write( int data, int addr, rel_time_t time )
+{
+	MEM_ACCESS( time, addr )
+
+	// RAM
+	RAM [addr] = (uint8_t) data;
+	int reg = addr - 0xF0;
+	if ( reg >= 0 ) // 64%
+	{
+		// $F0-$FF
+		if ( reg < reg_count ) // 87%
+		{
+			REGS [reg] = (uint8_t) data;
+
+			// Ports
+			#ifdef SPC_PORT_WRITE_HOOK
+				if ( (unsigned) (reg - r_cpuio0) < port_count )
+					SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0),
+							(uint8_t) data, &REGS [r_cpuio0] );
+			#endif
+
+			// Registers other than $F2 and $F4-$F7
+			//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
+			// TODO: this is a bit on the fragile side
+			if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
+				cpu_write_smp_reg( data, time, reg );
+		}
+		// High mem/address wrap-around
+		else
+		{
+			reg -= rom_addr - 0xF0;
+			if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around
+				cpu_write_high( data, reg, time );
+		}
+	}
+}
+
+
+//// CPU read
+
+inline int Snes_Spc::cpu_read_smp_reg( int reg, rel_time_t time )
+{
+	int result = REGS_IN [reg];
+	reg -= r_dspaddr;
+	// DSP addr and data
+	if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3
+	{
+		result = REGS [r_dspaddr];
+		if ( (unsigned) reg == 1 )
+			result = dsp_read( time ); // 0xF3
+	}
+	return result;
+}
+
+int Snes_Spc::cpu_read( int addr, rel_time_t time )
+{
+	MEM_ACCESS( time, addr )
+
+	// RAM
+	int result = RAM [addr];
+	int reg = addr - 0xF0;
+	if ( reg >= 0 ) // 40%
+	{
+		reg -= 0x10;
+		if ( (unsigned) reg >= 0xFF00 ) // 21%
+		{
+			reg += 0x10 - r_t0out;
+
+			// Timers
+			if ( (unsigned) reg < timer_count ) // 90%
+			{
+				Timer* t = &m.timers [reg];
+				if ( time >= t->next_time )
+					t = run_timer_( t, time );
+				result = t->counter;
+				t->counter = 0;
+			}
+			// Other registers
+			else if ( reg < 0 ) // 10%
+			{
+				result = cpu_read_smp_reg( reg + r_t0out, time );
+			}
+			else // 1%
+			{
+				assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 );
+				result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time );
+			}
+		}
+	}
+
+	return result;
+}
+
+
+//// Run
+
+// Prefix and suffix for CPU emulator function
+#define SPC_CPU_RUN_FUNC \
+uint8_t* Snes_Spc::run_until_( time_t end_time )\
+{\
+	rel_time_t rel_time = m.spc_time - end_time;\
+	assert( rel_time <= 0 );\
+	m.spc_time = end_time;\
+	m.dsp_time += rel_time;\
+	m.timers [0].next_time += rel_time;\
+	m.timers [1].next_time += rel_time;\
+	m.timers [2].next_time += rel_time;
+
+#define SPC_CPU_RUN_FUNC_END \
+	m.spc_time += rel_time;\
+	m.dsp_time -= rel_time;\
+	m.timers [0].next_time -= rel_time;\
+	m.timers [1].next_time -= rel_time;\
+	m.timers [2].next_time -= rel_time;\
+	assert( m.spc_time <= end_time );\
+	return &REGS [r_cpuio0];\
+}
+
+int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
+
+void Snes_Spc::end_frame( time_t end_time )
+{
+	// Catch CPU up to as close to end as possible. If final instruction
+	// would exceed end, does NOT execute it and leaves m.spc_time < end.
+	if ( end_time > m.spc_time )
+		run_until_( end_time );
+
+	m.spc_time     -= end_time;
+	m.extra_clocks += end_time;
+
+	// Greatest number of clocks early that emulation can stop early due to
+	// not being able to execute current instruction without going over
+	// allowed time.
+	assert( -cpu_lag_max <= m.spc_time && m.spc_time <= 0 );
+
+	// Catch timers up to CPU
+	for ( int i = 0; i < timer_count; i++ )
+		run_timer( &m.timers [i], 0 );
+
+	// Catch DSP up to CPU
+	if ( m.dsp_time < 0 )
+	{
+		RUN_DSP( 0, max_reg_time );
+	}
+
+	// Save any extra samples beyond what should be generated
+	if ( m.buf_begin )
+		save_extra();
+}
+
+// Inclusion here allows static memory access functions and better optimization
+#include "Spc_Cpu.h"
diff --git a/src/console/Spc_Cpu.cxx b/src/console/Spc_Cpu.cxx
deleted file mode 100644
index 603447e9940b..000000000000
--- a/src/console/Spc_Cpu.cxx
+++ /dev/null
@@ -1,565 +0,0 @@
-// Core SPC emulation: CPU, timers, SMP registers, memory
-
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Snes_Spc.h"
-
-#include <string.h>
-
-/* Copyright (C) 2004-2007 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#define RAM         (m.ram.ram)
-#define REGS        (m.smp_regs [0])
-#define REGS_IN     (m.smp_regs [1])
-
-// (n ? n : 256)
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-
-// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which
-// do crazy echo buffer accesses.
-#ifndef SPC_MORE_ACCURACY
-	#define SPC_MORE_ACCURACY 0
-#endif
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-
-//// Timers
-
-#if SPC_DISABLE_TEMPO
-	#define TIMER_DIV( t, n ) ((n) >> t->prescaler)
-	#define TIMER_MUL( t, n ) ((n) << t->prescaler)
-#else
-	#define TIMER_DIV( t, n ) ((n) / t->prescaler)
-	#define TIMER_MUL( t, n ) ((n) * t->prescaler)
-#endif
-
-Snes_Spc::Timer* Snes_Spc::run_timer_( Timer* t, rel_time_t time )
-{
-	int elapsed = TIMER_DIV( t, time - t->next_time ) + 1;
-	t->next_time += TIMER_MUL( t, elapsed );
-
-	if ( t->enabled )
-	{
-		int remain = IF_0_THEN_256( t->period - t->divider );
-		int divider = t->divider + elapsed;
-		int over = elapsed - remain;
-		if ( over >= 0 )
-		{
-			int n = over / t->period;
-			t->counter = (t->counter + 1 + n) & 0x0F;
-			divider = over - n * t->period;
-		}
-		t->divider = (uint8_t) divider;
-	}
-	return t;
-}
-
-inline Snes_Spc::Timer* Snes_Spc::run_timer( Timer* t, rel_time_t time )
-{
-	if ( time >= t->next_time )
-		t = run_timer_( t, time );
-	return t;
-}
-
-
-//// ROM
-
-void Snes_Spc::enable_rom( int enable )
-{
-	if ( m.rom_enabled != enable )
-	{
-		m.rom_enabled = enable;
-		if ( enable )
-			memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram );
-		memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size );
-		// TODO: ROM can still get overwritten when DSP writes to echo buffer
-	}
-}
-
-
-//// DSP
-
-#if SPC_LESS_ACCURATE
-	int const max_reg_time = 29;
-
-	signed char const Snes_Spc::reg_times_ [256] =
-	{
-		 -1,  0,-11,-10,-15,-11, -2, -2,  4,  3, 14, 14, 26, 26, 14, 22,
-		  2,  3,  0,  1,-12,  0,  1,  1,  7,  6, 14, 14, 27, 14, 14, 23,
-		  5,  6,  3,  4, -1,  3,  4,  4, 10,  9, 14, 14, 26, -5, 14, 23,
-		  8,  9,  6,  7,  2,  6,  7,  7, 13, 12, 14, 14, 27, -4, 14, 24,
-		 11, 12,  9, 10,  5,  9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24,
-		 14, 15, 12, 13,  8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24,
-		 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25,
-		 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25,
-
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-	};
-
-	#define RUN_DSP( time, offset ) \
-		int count = (time) - (offset) - m.dsp_time;\
-		if ( count >= 0 )\
-		{\
-			int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\
-			m.dsp_time += clock_count;\
-			dsp.run( clock_count );\
-		}
-#else
-	#define RUN_DSP( time, offset ) \
-		{\
-			int count = (time) - m.dsp_time;\
-			if ( !SPC_MORE_ACCURACY || count )\
-			{\
-				assert( count > 0 );\
-				m.dsp_time = (time);\
-				dsp.run( count );\
-			}\
-		}
-#endif
-
-int Snes_Spc::dsp_read( rel_time_t time )
-{
-	RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] );
-
-	int result = dsp.read( REGS [r_dspaddr] & 0x7F );
-
-	#ifdef SPC_DSP_READ_HOOK
-		SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result );
-	#endif
-
-	return result;
-}
-
-inline void Snes_Spc::dsp_write( int data, rel_time_t time )
-{
-	RUN_DSP( time, reg_times [REGS [r_dspaddr]] )
-	#if SPC_LESS_ACCURATE
-		else if ( m.dsp_time == skipping_time )
-		{
-			int r = REGS [r_dspaddr];
-			if ( r == Spc_Dsp::r_kon )
-				m.skipped_kon |= data & ~dsp.read( Spc_Dsp::r_koff );
-
-			if ( r == Spc_Dsp::r_koff )
-			{
-				m.skipped_koff |= data;
-				m.skipped_kon &= ~data;
-			}
-		}
-	#endif
-
-	#ifdef SPC_DSP_WRITE_HOOK
-		SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data );
-	#endif
-
-	if ( REGS [r_dspaddr] <= 0x7F )
-		dsp.write( REGS [r_dspaddr], data );
-	else if ( !SPC_MORE_ACCURACY )
-		debug_printf( "SPC wrote to DSP register > $7F\n" );
-}
-
-
-//// Memory access extras
-
-#if SPC_MORE_ACCURACY
-	#define MEM_ACCESS( time, addr ) \
-	{\
-		if ( time >= m.dsp_time )\
-		{\
-			RUN_DSP( time, max_reg_time );\
-		}\
-	}
-#elif !defined (NDEBUG)
-	// Debug-only check for read/write within echo buffer, since this might result in
-	// inaccurate emulation due to the DSP not being caught up to the present.
-
-	bool Snes_Spc::check_echo_access( int addr )
-	{
-		if ( !(dsp.read( Spc_Dsp::r_flg ) & 0x20) )
-		{
-			int start = 0x100 * dsp.read( Spc_Dsp::r_esa );
-			int size  = 0x800 * (dsp.read( Spc_Dsp::r_edl ) & 0x0F);
-			int end   = start + (size ? size : 4);
-			if ( start <= addr && addr < end )
-			{
-				if ( !m.echo_accessed )
-				{
-					m.echo_accessed = 1;
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	#define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) );
-#else
-	#define MEM_ACCESS( time, addr )
-#endif
-
-
-//// CPU write
-
-#if SPC_MORE_ACCURACY
-static unsigned char const glitch_probs [3] [256] =
-{
-	0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B,
-	0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08,
-	0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09,
-	0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01,
-	0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05,
-	0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07,
-	0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07,
-	0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01,
-	0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09,
-	0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08,
-	0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03,
-	0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03,
-	0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07,
-	0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02,
-	0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02,
-	0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01,
-
-	0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07,
-	0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06,
-	0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09,
-	0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03,
-	0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07,
-	0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03,
-	0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06,
-	0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03,
-	0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05,
-	0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04,
-	0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05,
-	0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01,
-	0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05,
-	0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01,
-	0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03,
-	0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01,
-
-	0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A,
-	0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A,
-	0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A,
-	0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09,
-	0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09,
-	0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02,
-	0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07,
-	0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04,
-	0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A,
-	0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07,
-	0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04,
-	0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02,
-	0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06,
-	0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03,
-	0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02,
-	0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03,
-};
-#endif
-
-// Read/write handlers are divided into multiple functions to keep rarely-used
-// functionality separate so often-used functionality can be optimized better
-// by compiler.
-
-// If write isn't preceded by read, data has this added to it
-int const no_read_before_write = 0x2000;
-
-void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
-{
-	switch ( addr )
-	{
-	case r_t0target:
-	case r_t1target:
-	case r_t2target: {
-		Timer* t = &m.timers [addr - r_t0target];
-		int period = IF_0_THEN_256( data );
-		if ( t->period != period )
-		{
-			t = run_timer( t, time );
-			#if SPC_MORE_ACCURACY
-				// Insane behavior when target is written just after counter is
-				// clocked and counter matches new period and new period isn't 1, 2, 4, or 8
-				if ( t->divider == (period & 0xFF) &&
-						t->next_time == time + TIMER_MUL( t, 1 ) &&
-						((period - 1) | ~0x0F) & period )
-				{
-					//debug_printf( "SPC pathological timer target write\n" );
-
-					// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
-					// based on the previous period
-					int prob = 0xFF;
-					int old_period = t->period & 0xFF;
-					if ( period == 3 ) prob = glitch_probs [0] [old_period];
-					if ( period == 5 ) prob = glitch_probs [1] [old_period];
-					if ( period == 9 ) prob = glitch_probs [2] [old_period];
-
-					// The glitch suppresses incrementing of one of the counter bits, based on
-					// the lowest set bit in the new period
-					int b = 1;
-					while ( !(period & b) )
-						b <<= 1;
-
-					if ( (rand() >> 4 & 0xFF) <= prob )
-						t->divider = (t->divider - b) & 0xFF;
-				}
-			#endif
-			t->period = period;
-		}
-		break;
-	}
-
-	case r_t0out:
-	case r_t1out:
-	case r_t2out:
-		if ( !SPC_MORE_ACCURACY )
-			debug_printf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
-
-		if ( data < no_read_before_write  / 2 )
-			run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
-		break;
-
-	// Registers that act like RAM
-	case 0x8:
-	case 0x9:
-		REGS_IN [addr] = (uint8_t) data;
-		break;
-
-	case r_test:
-		if ( (uint8_t) data != 0x0A )
-			debug_printf( "SPC wrote to test register\n" );
-		break;
-
-	case r_control:
-		// port clears
-		if ( data & 0x10 )
-		{
-			REGS_IN [r_cpuio0] = 0;
-			REGS_IN [r_cpuio1] = 0;
-		}
-		if ( data & 0x20 )
-		{
-			REGS_IN [r_cpuio2] = 0;
-			REGS_IN [r_cpuio3] = 0;
-		}
-
-		// timers
-		{
-			for ( int i = 0; i < timer_count; i++ )
-			{
-				Timer* t = &m.timers [i];
-				int enabled = data >> i & 1;
-				if ( t->enabled != enabled )
-				{
-					t = run_timer( t, time );
-					t->enabled = enabled;
-					if ( enabled )
-					{
-						t->divider = 0;
-						t->counter = 0;
-					}
-				}
-			}
-		}
-		enable_rom( data & 0x80 );
-		break;
-	}
-}
-
-void Snes_Spc::cpu_write_smp_reg( int data, rel_time_t time, int addr )
-{
-	if ( addr == r_dspdata ) // 99%
-		dsp_write( data, time );
-	else
-		cpu_write_smp_reg_( data, time, addr );
-}
-
-void Snes_Spc::cpu_write_high( int data, int i, rel_time_t time )
-{
-	if ( i < rom_size )
-	{
-		m.hi_ram [i] = (uint8_t) data;
-		if ( m.rom_enabled )
-			RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM
-	}
-	else
-	{
-		assert( RAM [i + rom_addr - 0x10000] == (uint8_t) data );
-		RAM [i + rom_addr - 0x10000] = cpu_pad_fill; // restore overwritten padding
-		cpu_write( data, i + rom_addr - 0x10000, time );
-	}
-}
-
-int const bits_in_int = CHAR_BIT * sizeof (int);
-
-void Snes_Spc::cpu_write( int data, int addr, rel_time_t time )
-{
-	MEM_ACCESS( time, addr )
-
-	// RAM
-	RAM [addr] = (uint8_t) data;
-	int reg = addr - 0xF0;
-	if ( reg >= 0 ) // 64%
-	{
-		// $F0-$FF
-		if ( reg < reg_count ) // 87%
-		{
-			REGS [reg] = (uint8_t) data;
-
-			// Ports
-			#ifdef SPC_PORT_WRITE_HOOK
-				if ( (unsigned) (reg - r_cpuio0) < port_count )
-					SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0),
-							(uint8_t) data, &REGS [r_cpuio0] );
-			#endif
-
-			// Registers other than $F2 and $F4-$F7
-			//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
-			// TODO: this is a bit on the fragile side
-			if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
-				cpu_write_smp_reg( data, time, reg );
-		}
-		// High mem/address wrap-around
-		else
-		{
-			reg -= rom_addr - 0xF0;
-			if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around
-				cpu_write_high( data, reg, time );
-		}
-	}
-}
-
-
-//// CPU read
-
-inline int Snes_Spc::cpu_read_smp_reg( int reg, rel_time_t time )
-{
-	int result = REGS_IN [reg];
-	reg -= r_dspaddr;
-	// DSP addr and data
-	if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3
-	{
-		result = REGS [r_dspaddr];
-		if ( (unsigned) reg == 1 )
-			result = dsp_read( time ); // 0xF3
-	}
-	return result;
-}
-
-int Snes_Spc::cpu_read( int addr, rel_time_t time )
-{
-	MEM_ACCESS( time, addr )
-
-	// RAM
-	int result = RAM [addr];
-	int reg = addr - 0xF0;
-	if ( reg >= 0 ) // 40%
-	{
-		reg -= 0x10;
-		if ( (unsigned) reg >= 0xFF00 ) // 21%
-		{
-			reg += 0x10 - r_t0out;
-
-			// Timers
-			if ( (unsigned) reg < timer_count ) // 90%
-			{
-				Timer* t = &m.timers [reg];
-				if ( time >= t->next_time )
-					t = run_timer_( t, time );
-				result = t->counter;
-				t->counter = 0;
-			}
-			// Other registers
-			else if ( reg < 0 ) // 10%
-			{
-				result = cpu_read_smp_reg( reg + r_t0out, time );
-			}
-			else // 1%
-			{
-				assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 );
-				result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time );
-			}
-		}
-	}
-
-	return result;
-}
-
-
-//// Run
-
-// Prefix and suffix for CPU emulator function
-#define SPC_CPU_RUN_FUNC \
-uint8_t* Snes_Spc::run_until_( time_t end_time )\
-{\
-	rel_time_t rel_time = m.spc_time - end_time;\
-	assert( rel_time <= 0 );\
-	m.spc_time = end_time;\
-	m.dsp_time += rel_time;\
-	m.timers [0].next_time += rel_time;\
-	m.timers [1].next_time += rel_time;\
-	m.timers [2].next_time += rel_time;
-
-#define SPC_CPU_RUN_FUNC_END \
-	m.spc_time += rel_time;\
-	m.dsp_time -= rel_time;\
-	m.timers [0].next_time -= rel_time;\
-	m.timers [1].next_time -= rel_time;\
-	m.timers [2].next_time -= rel_time;\
-	assert( m.spc_time <= end_time );\
-	return &REGS [r_cpuio0];\
-}
-
-int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
-
-void Snes_Spc::end_frame( time_t end_time )
-{
-	// Catch CPU up to as close to end as possible. If final instruction
-	// would exceed end, does NOT execute it and leaves m.spc_time < end.
-	if ( end_time > m.spc_time )
-		run_until_( end_time );
-
-	m.spc_time     -= end_time;
-	m.extra_clocks += end_time;
-
-	// Greatest number of clocks early that emulation can stop early due to
-	// not being able to execute current instruction without going over
-	// allowed time.
-	assert( -cpu_lag_max <= m.spc_time && m.spc_time <= 0 );
-
-	// Catch timers up to CPU
-	for ( int i = 0; i < timer_count; i++ )
-		run_timer( &m.timers [i], 0 );
-
-	// Catch DSP up to CPU
-	if ( m.dsp_time < 0 )
-	{
-		RUN_DSP( 0, max_reg_time );
-	}
-
-	// Save any extra samples beyond what should be generated
-	if ( m.buf_begin )
-		save_extra();
-}
-
-// Inclusion here allows static memory access functions and better optimization
-#include "Spc_Cpu.h"
diff --git a/src/console/Spc_Dsp.cc b/src/console/Spc_Dsp.cc
new file mode 100644
index 000000000000..1786addc008f
--- /dev/null
+++ b/src/console/Spc_Dsp.cc
@@ -0,0 +1,701 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Spc_Dsp.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2007 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+#if INT_MAX < 0x7FFFFFFF
+	#error "Requires that int type have at least 32 bits"
+#endif
+
+
+// TODO: add to blargg_endian.h
+#define GET_LE16SA( addr )      ((int16_t) GET_LE16( addr ))
+#define GET_LE16A( addr )       GET_LE16( addr )
+#define SET_LE16A( addr, data ) SET_LE16( addr, data )
+
+static uint8_t const initial_regs [Spc_Dsp::register_count] =
+{
+	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
+	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
+	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
+	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
+	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
+	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
+	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
+	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
+};
+
+// if ( io < -32768 ) io = -32768;
+// if ( io >  32767 ) io =  32767;
+#define CLAMP16( io )\
+{\
+	if ( (int16_t) io != io )\
+		io = (io >> 31) ^ 0x7FFF;\
+}
+
+// Access global DSP register
+#define REG(n)      m.regs [r_##n]
+
+// Access voice DSP register
+#define VREG(r,n)   r [v_##n]
+
+#define WRITE_SAMPLES( l, r, out ) \
+{\
+	out [0] = l;\
+	out [1] = r;\
+	out += 2;\
+	if ( out >= m.out_end )\
+	{\
+		check( out == m.out_end );\
+		check( m.out_end != &m.extra [extra_size] || \
+			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
+		out       = m.extra;\
+		m.out_end = &m.extra [extra_size];\
+	}\
+}\
+
+void Spc_Dsp::set_output( sample_t* out, int size )
+{
+	require( (size & 1) == 0 ); // must be even
+	if ( !out )
+	{
+		out  = m.extra;
+		size = extra_size;
+	}
+	m.out_begin = out;
+	m.out       = out;
+	m.out_end   = out + size;
+}
+
+// Volume registers and efb are signed! Easy to forget int8_t cast.
+// Prefixes are to avoid accidental use of locals with same names.
+
+// Interleved gauss table (to improve cache coherency)
+// interleved_gauss [i] = gauss [(i & 1) * 256 + 255 - (i >> 1 & 0xFF)]
+static short const interleved_gauss [512] =
+{
+ 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
+ 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
+ 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
+ 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
+ 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
+ 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
+ 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
+ 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
+ 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
+ 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
+ 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
+ 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
+ 102,1102, 100,1098,  99,1094,  97,1090,  95,1086,  94,1082,  92,1078,  90,1074,
+  89,1070,  87,1066,  86,1061,  84,1057,  83,1053,  81,1049,  80,1045,  78,1040,
+  77,1036,  76,1032,  74,1027,  73,1023,  71,1019,  70,1014,  69,1010,  67,1005,
+  66,1001,  65, 997,  64, 992,  62, 988,  61, 983,  60, 978,  59, 974,  58, 969,
+  56, 965,  55, 960,  54, 955,  53, 951,  52, 946,  51, 941,  50, 937,  49, 932,
+  48, 927,  47, 923,  46, 918,  45, 913,  44, 908,  43, 904,  42, 899,  41, 894,
+  40, 889,  39, 884,  38, 880,  37, 875,  36, 870,  36, 865,  35, 860,  34, 855,
+  33, 851,  32, 846,  32, 841,  31, 836,  30, 831,  29, 826,  29, 821,  28, 816,
+  27, 811,  27, 806,  26, 802,  25, 797,  24, 792,  24, 787,  23, 782,  23, 777,
+  22, 772,  21, 767,  21, 762,  20, 757,  20, 752,  19, 747,  19, 742,  18, 737,
+  17, 732,  17, 728,  16, 723,  16, 718,  15, 713,  15, 708,  15, 703,  14, 698,
+  14, 693,  13, 688,  13, 683,  12, 678,  12, 674,  11, 669,  11, 664,  11, 659,
+  10, 654,  10, 649,  10, 644,   9, 640,   9, 635,   9, 630,   8, 625,   8, 620,
+   8, 615,   7, 611,   7, 606,   7, 601,   6, 596,   6, 592,   6, 587,   6, 582,
+   5, 577,   5, 573,   5, 568,   5, 563,   4, 559,   4, 554,   4, 550,   4, 545,
+   4, 540,   3, 536,   3, 531,   3, 527,   3, 522,   3, 517,   2, 513,   2, 508,
+   2, 504,   2, 499,   2, 495,   2, 491,   2, 486,   1, 482,   1, 477,   1, 473,
+   1, 469,   1, 464,   1, 460,   1, 456,   1, 451,   1, 447,   1, 443,   1, 439,
+   0, 434,   0, 430,   0, 426,   0, 422,   0, 418,   0, 414,   0, 410,   0, 405,
+   0, 401,   0, 397,   0, 393,   0, 389,   0, 385,   0, 381,   0, 378,   0, 374,
+};
+
+
+//// Counters
+
+#define RATE( rate, div )\
+	(rate >= div ? rate / div * 8 - 1 : rate - 1)
+
+static unsigned const counter_mask [32] =
+{
+	RATE(   2,2), RATE(2048,4), RATE(1536,3),
+	RATE(1280,5), RATE(1024,4), RATE( 768,3),
+	RATE( 640,5), RATE( 512,4), RATE( 384,3),
+	RATE( 320,5), RATE( 256,4), RATE( 192,3),
+	RATE( 160,5), RATE( 128,4), RATE(  96,3),
+	RATE(  80,5), RATE(  64,4), RATE(  48,3),
+	RATE(  40,5), RATE(  32,4), RATE(  24,3),
+	RATE(  20,5), RATE(  16,4), RATE(  12,3),
+	RATE(  10,5), RATE(   8,4), RATE(   6,3),
+	RATE(   5,5), RATE(   4,4), RATE(   3,3),
+	              RATE(   2,4),
+	              RATE(   1,4)
+};
+#undef RATE
+
+inline void Spc_Dsp::init_counter()
+{
+	// counters start out with this synchronization
+	m.counters [0] =     1;
+	m.counters [1] =     0;
+	m.counters [2] = -0x20u;
+	m.counters [3] =  0x0B;
+
+	int n = 2;
+	for ( int i = 1; i < 32; i++ )
+	{
+		m.counter_select [i] = &m.counters [n];
+		if ( !--n )
+			n = 3;
+	}
+	m.counter_select [ 0] = &m.counters [0];
+	m.counter_select [30] = &m.counters [2];
+}
+
+inline void Spc_Dsp::run_counter( int i )
+{
+	int n = m.counters [i];
+	if ( !(n-- & 7) )
+		n -= 6 - i;
+	m.counters [i] = n;
+}
+
+#define READ_COUNTER( rate )\
+	(*m.counter_select [rate] & counter_mask [rate])
+
+
+//// Emulation
+
+void Spc_Dsp::run( int clock_count )
+{
+	int new_phase = m.phase + clock_count;
+	int count = new_phase >> 5;
+	m.phase = new_phase & 31;
+	if ( !count )
+		return;
+
+	uint8_t* const ram = m.ram;
+	uint8_t const* const dir = &ram [REG(dir) * 0x100];
+	int const slow_gaussian = (REG(pmon) >> 1) | REG(non);
+	int const noise_rate = REG(flg) & 0x1F;
+
+	// Global volume
+	int mvoll = (int8_t) REG(mvoll);
+	int mvolr = (int8_t) REG(mvolr);
+	if ( mvoll * mvolr < m.surround_threshold )
+		mvoll = -mvoll; // eliminate surround
+
+	do
+	{
+		// KON/KOFF reading
+		if ( (m.every_other_sample ^= 1) != 0 )
+		{
+			m.new_kon &= ~m.kon;
+			m.kon    = m.new_kon;
+			m.t_koff = REG(koff);
+		}
+
+		run_counter( 1 );
+		run_counter( 2 );
+		run_counter( 3 );
+
+		// Noise
+		if ( !READ_COUNTER( noise_rate ) )
+		{
+			int feedback = (m.noise << 13) ^ (m.noise << 14);
+			m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
+		}
+
+		// Voices
+		int pmon_input = 0;
+		int main_out_l = 0;
+		int main_out_r = 0;
+		int echo_out_l = 0;
+		int echo_out_r = 0;
+		voice_t* v = m.voices;
+		uint8_t* v_regs = m.regs;
+		int vbit = 1;
+		do
+		{
+			#define SAMPLE_PTR(i) GET_LE16A( &dir [VREG(v_regs,srcn) * 4 + i * 2] )
+
+			int brr_header = ram [v->brr_addr];
+			int kon_delay = v->kon_delay;
+
+			// Pitch
+			int pitch = GET_LE16A( &VREG(v_regs,pitchl) ) & 0x3FFF;
+			if ( REG(pmon) & vbit )
+				pitch += ((pmon_input >> 5) * pitch) >> 10;
+
+			// KON phases
+			if ( --kon_delay >= 0 )
+			{
+				v->kon_delay = kon_delay;
+
+				// Get ready to start BRR decoding on next sample
+				if ( kon_delay == 4 )
+				{
+					v->brr_addr   = SAMPLE_PTR( 0 );
+					v->brr_offset = 1;
+					v->buf_pos    = v->buf;
+					brr_header    = 0; // header is ignored on this sample
+				}
+
+				// Envelope is never run during KON
+				v->env        = 0;
+				v->hidden_env = 0;
+
+				// Disable BRR decoding until last three samples
+				v->interp_pos = (kon_delay & 3 ? 0x4000 : 0);
+
+				// Pitch is never added during KON
+				pitch = 0;
+			}
+
+			int env = v->env;
+
+			// Gaussian interpolation
+			{
+				int output = 0;
+				VREG(v_regs,envx) = (uint8_t) (env >> 4);
+				if ( env )
+				{
+					// Make pointers into gaussian based on fractional position between samples
+					int offset = (unsigned) v->interp_pos >> 3 & 0x1FE;
+					short const* fwd = interleved_gauss       + offset;
+					short const* rev = interleved_gauss + 510 - offset; // mirror left half of gaussian
+
+					int const* in = &v->buf_pos [(unsigned) v->interp_pos >> 12];
+
+					if ( !(slow_gaussian & vbit) ) // 99%
+					{
+						// Faster approximation when exact sample value isn't necessary for pitch mod
+						output = (fwd [0] * in [0] +
+						          fwd [1] * in [1] +
+						          rev [1] * in [2] +
+						          rev [0] * in [3]) >> 11;
+						output = (output * env) >> 11;
+					}
+					else
+					{
+						output = (int16_t) (m.noise * 2);
+						if ( !(REG(non) & vbit) )
+						{
+							output  = (fwd [0] * in [0]) >> 11;
+							output += (fwd [1] * in [1]) >> 11;
+							output += (rev [1] * in [2]) >> 11;
+							output = (int16_t) output;
+							output += (rev [0] * in [3]) >> 11;
+
+							CLAMP16( output );
+							output &= ~1;
+						}
+						output = (output * env) >> 11 & ~1;
+					}
+
+					// Output
+					int l = output * v->volume [0];
+					int r = output * v->volume [1];
+
+					main_out_l += l;
+					main_out_r += r;
+
+					if ( REG(eon) & vbit )
+					{
+						echo_out_l += l;
+						echo_out_r += r;
+					}
+				}
+
+				pmon_input = output;
+				VREG(v_regs,outx) = (uint8_t) (output >> 8);
+			}
+
+			// Soft reset or end of sample
+			if ( REG(flg) & 0x80 || (brr_header & 3) == 1 )
+			{
+				v->env_mode = env_release;
+				env         = 0;
+			}
+
+			if ( m.every_other_sample )
+			{
+				// KOFF
+				if ( m.t_koff & vbit )
+					v->env_mode = env_release;
+
+				// KON
+				if ( m.kon & vbit )
+				{
+					v->kon_delay = 5;
+					v->env_mode  = env_attack;
+					REG(endx) &= ~vbit;
+				}
+			}
+
+			// Envelope
+			if ( !v->kon_delay )
+			{
+				if ( v->env_mode == env_release ) // 97%
+				{
+					env -= 0x8;
+					v->env = env;
+					if ( env <= 0 )
+					{
+						v->env = 0;
+						goto skip_brr; // no BRR decoding for you!
+					}
+				}
+				else // 3%
+				{
+					int rate;
+					int const adsr0 = VREG(v_regs,adsr0);
+					int env_data = VREG(v_regs,adsr1);
+					if ( adsr0 >= 0x80 ) // 97% ADSR
+					{
+						if ( v->env_mode > env_decay ) // 89%
+						{
+							env--;
+							env -= env >> 8;
+							rate = env_data & 0x1F;
+
+							// optimized handling
+							v->hidden_env = env;
+							if ( READ_COUNTER( rate ) )
+								goto exit_env;
+							v->env = env;
+							goto exit_env;
+						}
+						else if ( v->env_mode == env_decay )
+						{
+							env--;
+							env -= env >> 8;
+							rate = (adsr0 >> 3 & 0x0E) + 0x10;
+						}
+						else // env_attack
+						{
+							rate = (adsr0 & 0x0F) * 2 + 1;
+							env += rate < 31 ? 0x20 : 0x400;
+						}
+					}
+					else // GAIN
+					{
+						int mode;
+						env_data = VREG(v_regs,gain);
+						mode = env_data >> 5;
+						if ( mode < 4 ) // direct
+						{
+							env = env_data * 0x10;
+							rate = 31;
+						}
+						else
+						{
+							rate = env_data & 0x1F;
+							if ( mode == 4 ) // 4: linear decrease
+							{
+								env -= 0x20;
+							}
+							else if ( mode < 6 ) // 5: exponential decrease
+							{
+								env--;
+								env -= env >> 8;
+							}
+							else // 6,7: linear increase
+							{
+								env += 0x20;
+								if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
+									env += 0x8 - 0x20; // 7: two-slope linear increase
+							}
+						}
+					}
+
+					// Sustain level
+					if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
+						v->env_mode = env_sustain;
+
+					v->hidden_env = env;
+
+					// unsigned cast because linear decrease going negative also triggers this
+					if ( (unsigned) env > 0x7FF )
+					{
+						env = (env < 0 ? 0 : 0x7FF);
+						if ( v->env_mode == env_attack )
+							v->env_mode = env_decay;
+					}
+
+					if ( !READ_COUNTER( rate ) )
+						v->env = env; // nothing else is controlled by the counter
+				}
+			}
+		exit_env:
+
+			{
+				// Apply pitch
+				int old_pos = v->interp_pos;
+				int interp_pos = (old_pos & 0x3FFF) + pitch;
+				if ( interp_pos > 0x7FFF )
+					interp_pos = 0x7FFF;
+				v->interp_pos = interp_pos;
+
+				// BRR decode if necessary
+				if ( old_pos >= 0x4000 )
+				{
+					// Arrange the four input nybbles in 0xABCD order for easy decoding
+					int nybbles = ram [(v->brr_addr + v->brr_offset) & 0xFFFF] * 0x100 +
+							ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
+
+					// Advance read position
+					int const brr_block_size = 9;
+					int brr_offset = v->brr_offset;
+					if ( (brr_offset += 2) >= brr_block_size )
+					{
+						// Next BRR block
+						int brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
+						assert( brr_offset == brr_block_size );
+						if ( brr_header & 1 )
+						{
+							brr_addr = SAMPLE_PTR( 1 );
+							if ( !v->kon_delay )
+								REG(endx) |= vbit;
+						}
+						v->brr_addr = brr_addr;
+						brr_offset  = 1;
+					}
+					v->brr_offset = brr_offset;
+
+					// Decode
+
+					// 0: >>1  1: <<0  2: <<1 ... 12: <<11  13-15: >>4 <<11
+					static unsigned char const shifts [16 * 2] = {
+						13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
+						 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
+					};
+					int const scale = brr_header >> 4;
+					int const right_shift = shifts [scale];
+					int const left_shift  = shifts [scale + 16];
+
+					// Write to next four samples in circular buffer
+					int* pos = v->buf_pos;
+					int* end;
+
+					// Decode four samples
+					for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
+					{
+						// Extract upper nybble and scale appropriately
+						int s = ((int16_t) nybbles >> right_shift) << left_shift;
+
+						// Apply IIR filter (8 is the most commonly used)
+						int const filter = brr_header & 0x0C;
+						int const p1 = pos [brr_buf_size - 1];
+						int const p2 = pos [brr_buf_size - 2] >> 1;
+						if ( filter >= 8 )
+						{
+							s += p1;
+							s -= p2;
+							if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
+							{
+								s += p2 >> 4;
+								s += (p1 * -3) >> 6;
+							}
+							else // s += p1 * 0.8984375 - p2 * 0.40625
+							{
+								s += (p1 * -13) >> 7;
+								s += (p2 * 3) >> 4;
+							}
+						}
+						else if ( filter ) // s += p1 * 0.46875
+						{
+							s += p1 >> 1;
+							s += (-p1) >> 5;
+						}
+
+						// Adjust and write sample
+						CLAMP16( s );
+						s = (int16_t) (s * 2);
+						pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
+					}
+
+					if ( pos >= &v->buf [brr_buf_size] )
+						pos = v->buf;
+					v->buf_pos = pos;
+				}
+			}
+skip_brr:
+			// Next voice
+			vbit <<= 1;
+			v_regs += 0x10;
+			v++;
+		}
+		while ( vbit < 0x100 );
+
+		// Echo position
+		int echo_offset = m.echo_offset;
+		uint8_t* const echo_ptr = &ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
+		if ( !echo_offset )
+			m.echo_length = (REG(edl) & 0x0F) * 0x800;
+		echo_offset += 4;
+		if ( echo_offset >= m.echo_length )
+			echo_offset = 0;
+		m.echo_offset = echo_offset;
+
+		// FIR
+		int echo_in_l = GET_LE16SA( echo_ptr + 0 );
+		int echo_in_r = GET_LE16SA( echo_ptr + 2 );
+
+		int (*echo_hist_pos) [2] = m.echo_hist_pos;
+		if ( ++echo_hist_pos >= &m.echo_hist [echo_hist_size] )
+			echo_hist_pos = m.echo_hist;
+		m.echo_hist_pos = echo_hist_pos;
+
+		echo_hist_pos [0] [0] = echo_hist_pos [8] [0] = echo_in_l;
+		echo_hist_pos [0] [1] = echo_hist_pos [8] [1] = echo_in_r;
+
+		#define CALC_FIR_( i, in )  ((in) * (int8_t) REG(fir + i * 0x10))
+		echo_in_l = CALC_FIR_( 7, echo_in_l );
+		echo_in_r = CALC_FIR_( 7, echo_in_r );
+
+		#define CALC_FIR( i, ch )   CALC_FIR_( i, echo_hist_pos [i + 1] [ch] )
+		#define DO_FIR( i )\
+			echo_in_l += CALC_FIR( i, 0 );\
+			echo_in_r += CALC_FIR( i, 1 );
+		DO_FIR( 0 );
+		DO_FIR( 1 );
+		DO_FIR( 2 );
+		#if defined (__MWERKS__) && __MWERKS__ < 0x3200
+			__eieio(); // keeps compiler from stupidly "caching" things in memory
+		#endif
+		DO_FIR( 3 );
+		DO_FIR( 4 );
+		DO_FIR( 5 );
+		DO_FIR( 6 );
+
+		// Echo out
+		if ( !(REG(flg) & 0x20) )
+		{
+			int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 14);
+			int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 14);
+
+			// just to help pass more validation tests
+			#if SPC_MORE_ACCURACY
+				l &= ~1;
+				r &= ~1;
+			#endif
+
+			CLAMP16( l );
+			CLAMP16( r );
+
+			SET_LE16A( echo_ptr + 0, l );
+			SET_LE16A( echo_ptr + 2, r );
+		}
+
+		// Sound out
+		int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
+		int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
+
+		CLAMP16( l );
+		CLAMP16( r );
+
+		if ( (REG(flg) & 0x40) )
+		{
+			l = 0;
+			r = 0;
+		}
+
+		sample_t* out = m.out;
+		WRITE_SAMPLES( l, r, out );
+		m.out = out;
+	}
+	while ( --count );
+}
+
+
+//// Setup
+
+void Spc_Dsp::mute_voices( int mask )
+{
+	m.mute_mask = mask;
+	for ( int i = 0; i < voice_count; i++ )
+	{
+		m.voices [i].enabled = (mask >> i & 1) - 1;
+		update_voice_vol( i * 0x10 );
+	}
+}
+
+void Spc_Dsp::init( void* ram_64k )
+{
+	m.ram = (uint8_t*) ram_64k;
+	mute_voices( 0 );
+	disable_surround( false );
+	set_output( 0, 0 );
+	reset();
+
+	#ifndef NDEBUG
+		// be sure this sign-extends
+		assert( (int16_t) 0x8000 == -0x8000 );
+
+		// be sure right shift preserves sign
+		assert( (-1 >> 1) == -1 );
+
+		// check clamp macro
+		int i;
+		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
+		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
+	#endif
+}
+
+void Spc_Dsp::soft_reset_common()
+{
+	require( m.ram ); // init() must have been called already
+
+	m.noise              = 0x4000;
+	m.echo_hist_pos      = m.echo_hist;
+	m.every_other_sample = 1;
+	m.echo_offset        = 0;
+	m.phase              = 0;
+
+	init_counter();
+}
+
+void Spc_Dsp::soft_reset()
+{
+	REG(flg) = 0xE0;
+	soft_reset_common();
+}
+
+void Spc_Dsp::load( uint8_t const regs [register_count] )
+{
+	memcpy( m.regs, regs, sizeof m.regs );
+	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
+
+	// Internal state
+	int i;
+	for ( i = voice_count; --i >= 0; )
+	{
+		voice_t& v = m.voices [i];
+		v.brr_offset = 1;
+		v.buf_pos    = v.buf;
+	}
+	m.new_kon = REG(kon);
+
+	mute_voices( m.mute_mask );
+	soft_reset_common();
+}
+
+void Spc_Dsp::reset() { load( initial_regs ); }
diff --git a/src/console/Spc_Dsp.cxx b/src/console/Spc_Dsp.cxx
deleted file mode 100644
index 1786addc008f..000000000000
--- a/src/console/Spc_Dsp.cxx
+++ /dev/null
@@ -1,701 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Spc_Dsp.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2007 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-#if INT_MAX < 0x7FFFFFFF
-	#error "Requires that int type have at least 32 bits"
-#endif
-
-
-// TODO: add to blargg_endian.h
-#define GET_LE16SA( addr )      ((int16_t) GET_LE16( addr ))
-#define GET_LE16A( addr )       GET_LE16( addr )
-#define SET_LE16A( addr, data ) SET_LE16( addr, data )
-
-static uint8_t const initial_regs [Spc_Dsp::register_count] =
-{
-	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
-	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
-	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
-	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
-	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
-	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
-	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
-	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
-};
-
-// if ( io < -32768 ) io = -32768;
-// if ( io >  32767 ) io =  32767;
-#define CLAMP16( io )\
-{\
-	if ( (int16_t) io != io )\
-		io = (io >> 31) ^ 0x7FFF;\
-}
-
-// Access global DSP register
-#define REG(n)      m.regs [r_##n]
-
-// Access voice DSP register
-#define VREG(r,n)   r [v_##n]
-
-#define WRITE_SAMPLES( l, r, out ) \
-{\
-	out [0] = l;\
-	out [1] = r;\
-	out += 2;\
-	if ( out >= m.out_end )\
-	{\
-		check( out == m.out_end );\
-		check( m.out_end != &m.extra [extra_size] || \
-			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
-		out       = m.extra;\
-		m.out_end = &m.extra [extra_size];\
-	}\
-}\
-
-void Spc_Dsp::set_output( sample_t* out, int size )
-{
-	require( (size & 1) == 0 ); // must be even
-	if ( !out )
-	{
-		out  = m.extra;
-		size = extra_size;
-	}
-	m.out_begin = out;
-	m.out       = out;
-	m.out_end   = out + size;
-}
-
-// Volume registers and efb are signed! Easy to forget int8_t cast.
-// Prefixes are to avoid accidental use of locals with same names.
-
-// Interleved gauss table (to improve cache coherency)
-// interleved_gauss [i] = gauss [(i & 1) * 256 + 255 - (i >> 1 & 0xFF)]
-static short const interleved_gauss [512] =
-{
- 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
- 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
- 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
- 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
- 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
- 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
- 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
- 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
- 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
- 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
- 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
- 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
- 102,1102, 100,1098,  99,1094,  97,1090,  95,1086,  94,1082,  92,1078,  90,1074,
-  89,1070,  87,1066,  86,1061,  84,1057,  83,1053,  81,1049,  80,1045,  78,1040,
-  77,1036,  76,1032,  74,1027,  73,1023,  71,1019,  70,1014,  69,1010,  67,1005,
-  66,1001,  65, 997,  64, 992,  62, 988,  61, 983,  60, 978,  59, 974,  58, 969,
-  56, 965,  55, 960,  54, 955,  53, 951,  52, 946,  51, 941,  50, 937,  49, 932,
-  48, 927,  47, 923,  46, 918,  45, 913,  44, 908,  43, 904,  42, 899,  41, 894,
-  40, 889,  39, 884,  38, 880,  37, 875,  36, 870,  36, 865,  35, 860,  34, 855,
-  33, 851,  32, 846,  32, 841,  31, 836,  30, 831,  29, 826,  29, 821,  28, 816,
-  27, 811,  27, 806,  26, 802,  25, 797,  24, 792,  24, 787,  23, 782,  23, 777,
-  22, 772,  21, 767,  21, 762,  20, 757,  20, 752,  19, 747,  19, 742,  18, 737,
-  17, 732,  17, 728,  16, 723,  16, 718,  15, 713,  15, 708,  15, 703,  14, 698,
-  14, 693,  13, 688,  13, 683,  12, 678,  12, 674,  11, 669,  11, 664,  11, 659,
-  10, 654,  10, 649,  10, 644,   9, 640,   9, 635,   9, 630,   8, 625,   8, 620,
-   8, 615,   7, 611,   7, 606,   7, 601,   6, 596,   6, 592,   6, 587,   6, 582,
-   5, 577,   5, 573,   5, 568,   5, 563,   4, 559,   4, 554,   4, 550,   4, 545,
-   4, 540,   3, 536,   3, 531,   3, 527,   3, 522,   3, 517,   2, 513,   2, 508,
-   2, 504,   2, 499,   2, 495,   2, 491,   2, 486,   1, 482,   1, 477,   1, 473,
-   1, 469,   1, 464,   1, 460,   1, 456,   1, 451,   1, 447,   1, 443,   1, 439,
-   0, 434,   0, 430,   0, 426,   0, 422,   0, 418,   0, 414,   0, 410,   0, 405,
-   0, 401,   0, 397,   0, 393,   0, 389,   0, 385,   0, 381,   0, 378,   0, 374,
-};
-
-
-//// Counters
-
-#define RATE( rate, div )\
-	(rate >= div ? rate / div * 8 - 1 : rate - 1)
-
-static unsigned const counter_mask [32] =
-{
-	RATE(   2,2), RATE(2048,4), RATE(1536,3),
-	RATE(1280,5), RATE(1024,4), RATE( 768,3),
-	RATE( 640,5), RATE( 512,4), RATE( 384,3),
-	RATE( 320,5), RATE( 256,4), RATE( 192,3),
-	RATE( 160,5), RATE( 128,4), RATE(  96,3),
-	RATE(  80,5), RATE(  64,4), RATE(  48,3),
-	RATE(  40,5), RATE(  32,4), RATE(  24,3),
-	RATE(  20,5), RATE(  16,4), RATE(  12,3),
-	RATE(  10,5), RATE(   8,4), RATE(   6,3),
-	RATE(   5,5), RATE(   4,4), RATE(   3,3),
-	              RATE(   2,4),
-	              RATE(   1,4)
-};
-#undef RATE
-
-inline void Spc_Dsp::init_counter()
-{
-	// counters start out with this synchronization
-	m.counters [0] =     1;
-	m.counters [1] =     0;
-	m.counters [2] = -0x20u;
-	m.counters [3] =  0x0B;
-
-	int n = 2;
-	for ( int i = 1; i < 32; i++ )
-	{
-		m.counter_select [i] = &m.counters [n];
-		if ( !--n )
-			n = 3;
-	}
-	m.counter_select [ 0] = &m.counters [0];
-	m.counter_select [30] = &m.counters [2];
-}
-
-inline void Spc_Dsp::run_counter( int i )
-{
-	int n = m.counters [i];
-	if ( !(n-- & 7) )
-		n -= 6 - i;
-	m.counters [i] = n;
-}
-
-#define READ_COUNTER( rate )\
-	(*m.counter_select [rate] & counter_mask [rate])
-
-
-//// Emulation
-
-void Spc_Dsp::run( int clock_count )
-{
-	int new_phase = m.phase + clock_count;
-	int count = new_phase >> 5;
-	m.phase = new_phase & 31;
-	if ( !count )
-		return;
-
-	uint8_t* const ram = m.ram;
-	uint8_t const* const dir = &ram [REG(dir) * 0x100];
-	int const slow_gaussian = (REG(pmon) >> 1) | REG(non);
-	int const noise_rate = REG(flg) & 0x1F;
-
-	// Global volume
-	int mvoll = (int8_t) REG(mvoll);
-	int mvolr = (int8_t) REG(mvolr);
-	if ( mvoll * mvolr < m.surround_threshold )
-		mvoll = -mvoll; // eliminate surround
-
-	do
-	{
-		// KON/KOFF reading
-		if ( (m.every_other_sample ^= 1) != 0 )
-		{
-			m.new_kon &= ~m.kon;
-			m.kon    = m.new_kon;
-			m.t_koff = REG(koff);
-		}
-
-		run_counter( 1 );
-		run_counter( 2 );
-		run_counter( 3 );
-
-		// Noise
-		if ( !READ_COUNTER( noise_rate ) )
-		{
-			int feedback = (m.noise << 13) ^ (m.noise << 14);
-			m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
-		}
-
-		// Voices
-		int pmon_input = 0;
-		int main_out_l = 0;
-		int main_out_r = 0;
-		int echo_out_l = 0;
-		int echo_out_r = 0;
-		voice_t* v = m.voices;
-		uint8_t* v_regs = m.regs;
-		int vbit = 1;
-		do
-		{
-			#define SAMPLE_PTR(i) GET_LE16A( &dir [VREG(v_regs,srcn) * 4 + i * 2] )
-
-			int brr_header = ram [v->brr_addr];
-			int kon_delay = v->kon_delay;
-
-			// Pitch
-			int pitch = GET_LE16A( &VREG(v_regs,pitchl) ) & 0x3FFF;
-			if ( REG(pmon) & vbit )
-				pitch += ((pmon_input >> 5) * pitch) >> 10;
-
-			// KON phases
-			if ( --kon_delay >= 0 )
-			{
-				v->kon_delay = kon_delay;
-
-				// Get ready to start BRR decoding on next sample
-				if ( kon_delay == 4 )
-				{
-					v->brr_addr   = SAMPLE_PTR( 0 );
-					v->brr_offset = 1;
-					v->buf_pos    = v->buf;
-					brr_header    = 0; // header is ignored on this sample
-				}
-
-				// Envelope is never run during KON
-				v->env        = 0;
-				v->hidden_env = 0;
-
-				// Disable BRR decoding until last three samples
-				v->interp_pos = (kon_delay & 3 ? 0x4000 : 0);
-
-				// Pitch is never added during KON
-				pitch = 0;
-			}
-
-			int env = v->env;
-
-			// Gaussian interpolation
-			{
-				int output = 0;
-				VREG(v_regs,envx) = (uint8_t) (env >> 4);
-				if ( env )
-				{
-					// Make pointers into gaussian based on fractional position between samples
-					int offset = (unsigned) v->interp_pos >> 3 & 0x1FE;
-					short const* fwd = interleved_gauss       + offset;
-					short const* rev = interleved_gauss + 510 - offset; // mirror left half of gaussian
-
-					int const* in = &v->buf_pos [(unsigned) v->interp_pos >> 12];
-
-					if ( !(slow_gaussian & vbit) ) // 99%
-					{
-						// Faster approximation when exact sample value isn't necessary for pitch mod
-						output = (fwd [0] * in [0] +
-						          fwd [1] * in [1] +
-						          rev [1] * in [2] +
-						          rev [0] * in [3]) >> 11;
-						output = (output * env) >> 11;
-					}
-					else
-					{
-						output = (int16_t) (m.noise * 2);
-						if ( !(REG(non) & vbit) )
-						{
-							output  = (fwd [0] * in [0]) >> 11;
-							output += (fwd [1] * in [1]) >> 11;
-							output += (rev [1] * in [2]) >> 11;
-							output = (int16_t) output;
-							output += (rev [0] * in [3]) >> 11;
-
-							CLAMP16( output );
-							output &= ~1;
-						}
-						output = (output * env) >> 11 & ~1;
-					}
-
-					// Output
-					int l = output * v->volume [0];
-					int r = output * v->volume [1];
-
-					main_out_l += l;
-					main_out_r += r;
-
-					if ( REG(eon) & vbit )
-					{
-						echo_out_l += l;
-						echo_out_r += r;
-					}
-				}
-
-				pmon_input = output;
-				VREG(v_regs,outx) = (uint8_t) (output >> 8);
-			}
-
-			// Soft reset or end of sample
-			if ( REG(flg) & 0x80 || (brr_header & 3) == 1 )
-			{
-				v->env_mode = env_release;
-				env         = 0;
-			}
-
-			if ( m.every_other_sample )
-			{
-				// KOFF
-				if ( m.t_koff & vbit )
-					v->env_mode = env_release;
-
-				// KON
-				if ( m.kon & vbit )
-				{
-					v->kon_delay = 5;
-					v->env_mode  = env_attack;
-					REG(endx) &= ~vbit;
-				}
-			}
-
-			// Envelope
-			if ( !v->kon_delay )
-			{
-				if ( v->env_mode == env_release ) // 97%
-				{
-					env -= 0x8;
-					v->env = env;
-					if ( env <= 0 )
-					{
-						v->env = 0;
-						goto skip_brr; // no BRR decoding for you!
-					}
-				}
-				else // 3%
-				{
-					int rate;
-					int const adsr0 = VREG(v_regs,adsr0);
-					int env_data = VREG(v_regs,adsr1);
-					if ( adsr0 >= 0x80 ) // 97% ADSR
-					{
-						if ( v->env_mode > env_decay ) // 89%
-						{
-							env--;
-							env -= env >> 8;
-							rate = env_data & 0x1F;
-
-							// optimized handling
-							v->hidden_env = env;
-							if ( READ_COUNTER( rate ) )
-								goto exit_env;
-							v->env = env;
-							goto exit_env;
-						}
-						else if ( v->env_mode == env_decay )
-						{
-							env--;
-							env -= env >> 8;
-							rate = (adsr0 >> 3 & 0x0E) + 0x10;
-						}
-						else // env_attack
-						{
-							rate = (adsr0 & 0x0F) * 2 + 1;
-							env += rate < 31 ? 0x20 : 0x400;
-						}
-					}
-					else // GAIN
-					{
-						int mode;
-						env_data = VREG(v_regs,gain);
-						mode = env_data >> 5;
-						if ( mode < 4 ) // direct
-						{
-							env = env_data * 0x10;
-							rate = 31;
-						}
-						else
-						{
-							rate = env_data & 0x1F;
-							if ( mode == 4 ) // 4: linear decrease
-							{
-								env -= 0x20;
-							}
-							else if ( mode < 6 ) // 5: exponential decrease
-							{
-								env--;
-								env -= env >> 8;
-							}
-							else // 6,7: linear increase
-							{
-								env += 0x20;
-								if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
-									env += 0x8 - 0x20; // 7: two-slope linear increase
-							}
-						}
-					}
-
-					// Sustain level
-					if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
-						v->env_mode = env_sustain;
-
-					v->hidden_env = env;
-
-					// unsigned cast because linear decrease going negative also triggers this
-					if ( (unsigned) env > 0x7FF )
-					{
-						env = (env < 0 ? 0 : 0x7FF);
-						if ( v->env_mode == env_attack )
-							v->env_mode = env_decay;
-					}
-
-					if ( !READ_COUNTER( rate ) )
-						v->env = env; // nothing else is controlled by the counter
-				}
-			}
-		exit_env:
-
-			{
-				// Apply pitch
-				int old_pos = v->interp_pos;
-				int interp_pos = (old_pos & 0x3FFF) + pitch;
-				if ( interp_pos > 0x7FFF )
-					interp_pos = 0x7FFF;
-				v->interp_pos = interp_pos;
-
-				// BRR decode if necessary
-				if ( old_pos >= 0x4000 )
-				{
-					// Arrange the four input nybbles in 0xABCD order for easy decoding
-					int nybbles = ram [(v->brr_addr + v->brr_offset) & 0xFFFF] * 0x100 +
-							ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
-
-					// Advance read position
-					int const brr_block_size = 9;
-					int brr_offset = v->brr_offset;
-					if ( (brr_offset += 2) >= brr_block_size )
-					{
-						// Next BRR block
-						int brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
-						assert( brr_offset == brr_block_size );
-						if ( brr_header & 1 )
-						{
-							brr_addr = SAMPLE_PTR( 1 );
-							if ( !v->kon_delay )
-								REG(endx) |= vbit;
-						}
-						v->brr_addr = brr_addr;
-						brr_offset  = 1;
-					}
-					v->brr_offset = brr_offset;
-
-					// Decode
-
-					// 0: >>1  1: <<0  2: <<1 ... 12: <<11  13-15: >>4 <<11
-					static unsigned char const shifts [16 * 2] = {
-						13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
-						 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
-					};
-					int const scale = brr_header >> 4;
-					int const right_shift = shifts [scale];
-					int const left_shift  = shifts [scale + 16];
-
-					// Write to next four samples in circular buffer
-					int* pos = v->buf_pos;
-					int* end;
-
-					// Decode four samples
-					for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
-					{
-						// Extract upper nybble and scale appropriately
-						int s = ((int16_t) nybbles >> right_shift) << left_shift;
-
-						// Apply IIR filter (8 is the most commonly used)
-						int const filter = brr_header & 0x0C;
-						int const p1 = pos [brr_buf_size - 1];
-						int const p2 = pos [brr_buf_size - 2] >> 1;
-						if ( filter >= 8 )
-						{
-							s += p1;
-							s -= p2;
-							if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
-							{
-								s += p2 >> 4;
-								s += (p1 * -3) >> 6;
-							}
-							else // s += p1 * 0.8984375 - p2 * 0.40625
-							{
-								s += (p1 * -13) >> 7;
-								s += (p2 * 3) >> 4;
-							}
-						}
-						else if ( filter ) // s += p1 * 0.46875
-						{
-							s += p1 >> 1;
-							s += (-p1) >> 5;
-						}
-
-						// Adjust and write sample
-						CLAMP16( s );
-						s = (int16_t) (s * 2);
-						pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
-					}
-
-					if ( pos >= &v->buf [brr_buf_size] )
-						pos = v->buf;
-					v->buf_pos = pos;
-				}
-			}
-skip_brr:
-			// Next voice
-			vbit <<= 1;
-			v_regs += 0x10;
-			v++;
-		}
-		while ( vbit < 0x100 );
-
-		// Echo position
-		int echo_offset = m.echo_offset;
-		uint8_t* const echo_ptr = &ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
-		if ( !echo_offset )
-			m.echo_length = (REG(edl) & 0x0F) * 0x800;
-		echo_offset += 4;
-		if ( echo_offset >= m.echo_length )
-			echo_offset = 0;
-		m.echo_offset = echo_offset;
-
-		// FIR
-		int echo_in_l = GET_LE16SA( echo_ptr + 0 );
-		int echo_in_r = GET_LE16SA( echo_ptr + 2 );
-
-		int (*echo_hist_pos) [2] = m.echo_hist_pos;
-		if ( ++echo_hist_pos >= &m.echo_hist [echo_hist_size] )
-			echo_hist_pos = m.echo_hist;
-		m.echo_hist_pos = echo_hist_pos;
-
-		echo_hist_pos [0] [0] = echo_hist_pos [8] [0] = echo_in_l;
-		echo_hist_pos [0] [1] = echo_hist_pos [8] [1] = echo_in_r;
-
-		#define CALC_FIR_( i, in )  ((in) * (int8_t) REG(fir + i * 0x10))
-		echo_in_l = CALC_FIR_( 7, echo_in_l );
-		echo_in_r = CALC_FIR_( 7, echo_in_r );
-
-		#define CALC_FIR( i, ch )   CALC_FIR_( i, echo_hist_pos [i + 1] [ch] )
-		#define DO_FIR( i )\
-			echo_in_l += CALC_FIR( i, 0 );\
-			echo_in_r += CALC_FIR( i, 1 );
-		DO_FIR( 0 );
-		DO_FIR( 1 );
-		DO_FIR( 2 );
-		#if defined (__MWERKS__) && __MWERKS__ < 0x3200
-			__eieio(); // keeps compiler from stupidly "caching" things in memory
-		#endif
-		DO_FIR( 3 );
-		DO_FIR( 4 );
-		DO_FIR( 5 );
-		DO_FIR( 6 );
-
-		// Echo out
-		if ( !(REG(flg) & 0x20) )
-		{
-			int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 14);
-			int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 14);
-
-			// just to help pass more validation tests
-			#if SPC_MORE_ACCURACY
-				l &= ~1;
-				r &= ~1;
-			#endif
-
-			CLAMP16( l );
-			CLAMP16( r );
-
-			SET_LE16A( echo_ptr + 0, l );
-			SET_LE16A( echo_ptr + 2, r );
-		}
-
-		// Sound out
-		int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
-		int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
-
-		CLAMP16( l );
-		CLAMP16( r );
-
-		if ( (REG(flg) & 0x40) )
-		{
-			l = 0;
-			r = 0;
-		}
-
-		sample_t* out = m.out;
-		WRITE_SAMPLES( l, r, out );
-		m.out = out;
-	}
-	while ( --count );
-}
-
-
-//// Setup
-
-void Spc_Dsp::mute_voices( int mask )
-{
-	m.mute_mask = mask;
-	for ( int i = 0; i < voice_count; i++ )
-	{
-		m.voices [i].enabled = (mask >> i & 1) - 1;
-		update_voice_vol( i * 0x10 );
-	}
-}
-
-void Spc_Dsp::init( void* ram_64k )
-{
-	m.ram = (uint8_t*) ram_64k;
-	mute_voices( 0 );
-	disable_surround( false );
-	set_output( 0, 0 );
-	reset();
-
-	#ifndef NDEBUG
-		// be sure this sign-extends
-		assert( (int16_t) 0x8000 == -0x8000 );
-
-		// be sure right shift preserves sign
-		assert( (-1 >> 1) == -1 );
-
-		// check clamp macro
-		int i;
-		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
-		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
-	#endif
-}
-
-void Spc_Dsp::soft_reset_common()
-{
-	require( m.ram ); // init() must have been called already
-
-	m.noise              = 0x4000;
-	m.echo_hist_pos      = m.echo_hist;
-	m.every_other_sample = 1;
-	m.echo_offset        = 0;
-	m.phase              = 0;
-
-	init_counter();
-}
-
-void Spc_Dsp::soft_reset()
-{
-	REG(flg) = 0xE0;
-	soft_reset_common();
-}
-
-void Spc_Dsp::load( uint8_t const regs [register_count] )
-{
-	memcpy( m.regs, regs, sizeof m.regs );
-	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
-
-	// Internal state
-	int i;
-	for ( i = voice_count; --i >= 0; )
-	{
-		voice_t& v = m.voices [i];
-		v.brr_offset = 1;
-		v.buf_pos    = v.buf;
-	}
-	m.new_kon = REG(kon);
-
-	mute_voices( m.mute_mask );
-	soft_reset_common();
-}
-
-void Spc_Dsp::reset() { load( initial_regs ); }
diff --git a/src/console/Spc_Dsp.h b/src/console/Spc_Dsp.h
index 080c1d2978f2..bc1070d6bad1 100644
--- a/src/console/Spc_Dsp.h
+++ b/src/console/Spc_Dsp.h
@@ -13,7 +13,7 @@ public:
 	// Initializes DSP and has it use the 64K RAM provided
 	void init( void* ram_64k );
 
-	// Sets destination for output samples. If out is NULL or out_size is 0,
+	// Sets destination for output samples. If out is nullptr or out_size is 0,
 	// doesn't generate any.
 	typedef short sample_t;
 	void set_output( sample_t* out, int out_size );
diff --git a/src/console/Spc_Emu.cc b/src/console/Spc_Emu.cc
new file mode 100644
index 000000000000..b147c1cc9449
--- /dev/null
+++ b/src/console/Spc_Emu.cc
@@ -0,0 +1,352 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Spc_Emu.h"
+
+#include "blargg_endian.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Copyright (C) 2004-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// TODO: support Spc_Filter's bass
+
+Spc_Emu::Spc_Emu()
+{
+	set_type( gme_spc_type );
+
+	static const char* const names [Snes_Spc::voice_count] = {
+		"DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
+	};
+	set_voice_names( names );
+
+	set_gain( 1.4 );
+}
+
+Spc_Emu::~Spc_Emu() { }
+
+// Track info
+
+long const trailer_offset = 0x10200;
+
+byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }
+
+long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }
+
+static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
+{
+	// header
+	byte const* end = begin + size;
+	if ( size < 8 || memcmp( begin, "xid6", 4 ) )
+	{
+		check( false );
+		return;
+	}
+	long info_size = GET_LE32( begin + 4 );
+	byte const* in = begin + 8;
+	if ( end - in > info_size )
+	{
+		debug_printf( "Extra data after SPC xid6 info\n" );
+		end = in + info_size;
+	}
+
+	int year = 0;
+	char copyright [256 + 5];
+	int copyright_len = 0;
+	int const year_len = 5;
+
+	while ( end - in >= 4 )
+	{
+		// header
+		int id   = in [0];
+		int data = in [3] * 0x100 + in [2];
+		int type = in [1];
+		int len  = type ? data : 0;
+		in += 4;
+		if ( len > end - in )
+		{
+			check( false );
+			break; // block goes past end of data
+		}
+
+		// handle specific block types
+		char* field = 0;
+		switch ( id )
+		{
+			case 0x01: field = out->song;    break;
+			case 0x02: field = out->game;    break;
+			case 0x03: field = out->author;  break;
+			case 0x04: field = out->dumper;  break;
+			case 0x07: field = out->comment; break;
+			case 0x14: year = data;          break;
+
+			//case 0x30: // intro length
+			// Many SPCs have intro length set wrong for looped tracks, making it useless
+			/*
+			case 0x30:
+				check( len == 4 );
+				if ( len >= 4 )
+				{
+					out->intro_length = GET_LE32( in ) / 64;
+					if ( out->length > 0 )
+					{
+						long loop = out->length - out->intro_length;
+						if ( loop >= 2000 )
+							out->loop_length = loop;
+					}
+				}
+				break;
+			*/
+
+			case 0x13:
+				copyright_len = min( len, (int) sizeof copyright - year_len );
+				memcpy( &copyright [year_len], in, copyright_len );
+				break;
+
+			default:
+				if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
+						(id > 0x14 && id < 0x30) || id > 0x36 )
+					debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
+				break;
+		}
+		if ( field )
+		{
+			check( type == 1 );
+			Gme_File::copy_field_( field, (char const*) in, len );
+		}
+
+		// skip to next block
+		in += len;
+
+		// blocks are supposed to be 4-byte aligned with zero-padding...
+		byte const* unaligned = in;
+		while ( (in - begin) & 3 && in < end )
+		{
+			if ( *in++ != 0 )
+			{
+				// ...but some files have no padding
+				in = unaligned;
+				debug_printf( "SPC info tag wasn't properly padded to align\n" );
+				break;
+			}
+		}
+	}
+
+	char* p = &copyright [year_len];
+	if ( year )
+	{
+		*--p = ' ';
+		for ( int n = 4; n--; )
+		{
+			*--p = char (year % 10 + '0');
+			year /= 10;
+		}
+		copyright_len += year_len;
+	}
+	if ( copyright_len )
+		Gme_File::copy_field_( out->copyright, p, copyright_len );
+
+	check( in == end );
+}
+
+static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
+		track_info_t* out )
+{
+	// decode length (can be in text or binary format, sometimes ambiguous ugh)
+	long len_secs = 0;
+	for ( int i = 0; i < 3; i++ )
+	{
+		unsigned n = h.len_secs [i] - '0';
+		if ( n > 9 )
+		{
+			// ignore single-digit text lengths
+			// (except if author field is present and begins at offset 1, ugh)
+			if ( i == 1 && (h.author [0] || !h.author [1]) )
+				len_secs = 0;
+			break;
+		}
+		len_secs *= 10;
+		len_secs += n;
+	}
+	if ( !len_secs || len_secs > 0x1FFF )
+		len_secs = GET_LE16( h.len_secs );
+	if ( len_secs < 0x1FFF )
+		out->length = len_secs * 1000;
+
+	int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
+	Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
+
+	GME_COPY_FIELD( h, out, song );
+	GME_COPY_FIELD( h, out, game );
+	GME_COPY_FIELD( h, out, dumper );
+	GME_COPY_FIELD( h, out, comment );
+
+	if ( xid6_size )
+		get_spc_xid6( xid6, xid6_size, out );
+}
+
+blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
+{
+	get_spc_info( header(), trailer(), trailer_size(), out );
+	return 0;
+}
+
+static blargg_err_t check_spc_header( void const* header )
+{
+	if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Spc_File : Gme_Info_
+{
+	Spc_Emu::header_t header;
+	blargg_vector<byte> xid6;
+
+	Spc_File() { set_type( gme_spc_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		long file_size = in.remain();
+		if ( file_size < Snes_Spc::spc_min_file_size )
+			return gme_wrong_file_type;
+		RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
+		RETURN_ERR( check_spc_header( header.tag ) );
+		long const xid6_offset = 0x10200;
+		long xid6_size = file_size - xid6_offset;
+		if ( xid6_size > 0 )
+		{
+			RETURN_ERR( xid6.resize( xid6_size ) );
+			RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
+			RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
+		}
+		return 0;
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		get_spc_info( header, xid6.begin(), xid6.size(), out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
+static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
+
+static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
+gme_type_t const gme_spc_type = &gme_spc_type_;
+
+
+// Setup
+
+blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
+{
+	RETURN_ERR( apu.init() );
+	enable_accuracy( false );
+	if ( sample_rate != native_sample_rate )
+	{
+		RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
+		resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
+	}
+	return 0;
+}
+
+void Spc_Emu::enable_accuracy_( bool b )
+{
+	Music_Emu::enable_accuracy_( b );
+	filter.enable( b );
+}
+
+void Spc_Emu::mute_voices_( int m )
+{
+	Music_Emu::mute_voices_( m );
+	apu.mute_voices( m );
+}
+
+blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
+{
+	assert( offsetof (header_t,unused2 [46]) == header_size );
+	file_data = in;
+	file_size = size;
+	set_voice_count( Snes_Spc::voice_count );
+	if ( size < Snes_Spc::spc_min_file_size )
+		return gme_wrong_file_type;
+	return check_spc_header( in );
+}
+
+// Emulation
+
+void Spc_Emu::set_tempo_( double t )
+{
+	apu.set_tempo( (int) (t * apu.tempo_unit) );
+}
+
+blargg_err_t Spc_Emu::start_track_( int track )
+{
+	RETURN_ERR( Music_Emu::start_track_( track ) );
+	resampler.clear();
+	filter.clear();
+	RETURN_ERR( apu.load_spc( file_data, file_size ) );
+	filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
+	apu.clear_echo();
+	return 0;
+}
+
+blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
+{
+	RETURN_ERR( apu.play( count, out ) );
+	filter.run( out, count );
+	return 0;
+}
+
+blargg_err_t Spc_Emu::skip_( long count )
+{
+	if ( sample_rate() != native_sample_rate )
+	{
+		count = long (count * resampler.ratio()) & ~1;
+		count -= resampler.skip_input( count );
+	}
+
+	// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
+
+	if ( count > 0 )
+	{
+		RETURN_ERR( apu.skip( count ) );
+		filter.clear();
+	}
+
+	// eliminate pop due to resampler
+	const int resampler_latency = 64;
+	sample_t buf [resampler_latency];
+	return play_( resampler_latency, buf );
+}
+
+blargg_err_t Spc_Emu::play_( long count, sample_t* out )
+{
+	if ( sample_rate() == native_sample_rate )
+		return play_and_filter( count, out );
+
+	long remain = count;
+	while ( remain > 0 )
+	{
+		remain -= resampler.read( &out [count - remain], remain );
+		if ( remain > 0 )
+		{
+			long n = resampler.max_write();
+			RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
+			resampler.write( n );
+		}
+	}
+	check( remain == 0 );
+	return 0;
+}
diff --git a/src/console/Spc_Emu.cxx b/src/console/Spc_Emu.cxx
deleted file mode 100644
index b147c1cc9449..000000000000
--- a/src/console/Spc_Emu.cxx
+++ /dev/null
@@ -1,352 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Spc_Emu.h"
-
-#include "blargg_endian.h"
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// TODO: support Spc_Filter's bass
-
-Spc_Emu::Spc_Emu()
-{
-	set_type( gme_spc_type );
-
-	static const char* const names [Snes_Spc::voice_count] = {
-		"DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
-	};
-	set_voice_names( names );
-
-	set_gain( 1.4 );
-}
-
-Spc_Emu::~Spc_Emu() { }
-
-// Track info
-
-long const trailer_offset = 0x10200;
-
-byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }
-
-long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }
-
-static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
-{
-	// header
-	byte const* end = begin + size;
-	if ( size < 8 || memcmp( begin, "xid6", 4 ) )
-	{
-		check( false );
-		return;
-	}
-	long info_size = GET_LE32( begin + 4 );
-	byte const* in = begin + 8;
-	if ( end - in > info_size )
-	{
-		debug_printf( "Extra data after SPC xid6 info\n" );
-		end = in + info_size;
-	}
-
-	int year = 0;
-	char copyright [256 + 5];
-	int copyright_len = 0;
-	int const year_len = 5;
-
-	while ( end - in >= 4 )
-	{
-		// header
-		int id   = in [0];
-		int data = in [3] * 0x100 + in [2];
-		int type = in [1];
-		int len  = type ? data : 0;
-		in += 4;
-		if ( len > end - in )
-		{
-			check( false );
-			break; // block goes past end of data
-		}
-
-		// handle specific block types
-		char* field = 0;
-		switch ( id )
-		{
-			case 0x01: field = out->song;    break;
-			case 0x02: field = out->game;    break;
-			case 0x03: field = out->author;  break;
-			case 0x04: field = out->dumper;  break;
-			case 0x07: field = out->comment; break;
-			case 0x14: year = data;          break;
-
-			//case 0x30: // intro length
-			// Many SPCs have intro length set wrong for looped tracks, making it useless
-			/*
-			case 0x30:
-				check( len == 4 );
-				if ( len >= 4 )
-				{
-					out->intro_length = GET_LE32( in ) / 64;
-					if ( out->length > 0 )
-					{
-						long loop = out->length - out->intro_length;
-						if ( loop >= 2000 )
-							out->loop_length = loop;
-					}
-				}
-				break;
-			*/
-
-			case 0x13:
-				copyright_len = min( len, (int) sizeof copyright - year_len );
-				memcpy( &copyright [year_len], in, copyright_len );
-				break;
-
-			default:
-				if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
-						(id > 0x14 && id < 0x30) || id > 0x36 )
-					debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
-				break;
-		}
-		if ( field )
-		{
-			check( type == 1 );
-			Gme_File::copy_field_( field, (char const*) in, len );
-		}
-
-		// skip to next block
-		in += len;
-
-		// blocks are supposed to be 4-byte aligned with zero-padding...
-		byte const* unaligned = in;
-		while ( (in - begin) & 3 && in < end )
-		{
-			if ( *in++ != 0 )
-			{
-				// ...but some files have no padding
-				in = unaligned;
-				debug_printf( "SPC info tag wasn't properly padded to align\n" );
-				break;
-			}
-		}
-	}
-
-	char* p = &copyright [year_len];
-	if ( year )
-	{
-		*--p = ' ';
-		for ( int n = 4; n--; )
-		{
-			*--p = char (year % 10 + '0');
-			year /= 10;
-		}
-		copyright_len += year_len;
-	}
-	if ( copyright_len )
-		Gme_File::copy_field_( out->copyright, p, copyright_len );
-
-	check( in == end );
-}
-
-static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
-		track_info_t* out )
-{
-	// decode length (can be in text or binary format, sometimes ambiguous ugh)
-	long len_secs = 0;
-	for ( int i = 0; i < 3; i++ )
-	{
-		unsigned n = h.len_secs [i] - '0';
-		if ( n > 9 )
-		{
-			// ignore single-digit text lengths
-			// (except if author field is present and begins at offset 1, ugh)
-			if ( i == 1 && (h.author [0] || !h.author [1]) )
-				len_secs = 0;
-			break;
-		}
-		len_secs *= 10;
-		len_secs += n;
-	}
-	if ( !len_secs || len_secs > 0x1FFF )
-		len_secs = GET_LE16( h.len_secs );
-	if ( len_secs < 0x1FFF )
-		out->length = len_secs * 1000;
-
-	int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
-	Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
-
-	GME_COPY_FIELD( h, out, song );
-	GME_COPY_FIELD( h, out, game );
-	GME_COPY_FIELD( h, out, dumper );
-	GME_COPY_FIELD( h, out, comment );
-
-	if ( xid6_size )
-		get_spc_xid6( xid6, xid6_size, out );
-}
-
-blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
-{
-	get_spc_info( header(), trailer(), trailer_size(), out );
-	return 0;
-}
-
-static blargg_err_t check_spc_header( void const* header )
-{
-	if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Spc_File : Gme_Info_
-{
-	Spc_Emu::header_t header;
-	blargg_vector<byte> xid6;
-
-	Spc_File() { set_type( gme_spc_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		long file_size = in.remain();
-		if ( file_size < Snes_Spc::spc_min_file_size )
-			return gme_wrong_file_type;
-		RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
-		RETURN_ERR( check_spc_header( header.tag ) );
-		long const xid6_offset = 0x10200;
-		long xid6_size = file_size - xid6_offset;
-		if ( xid6_size > 0 )
-		{
-			RETURN_ERR( xid6.resize( xid6_size ) );
-			RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
-			RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
-		}
-		return 0;
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		get_spc_info( header, xid6.begin(), xid6.size(), out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
-static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
-
-static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
-gme_type_t const gme_spc_type = &gme_spc_type_;
-
-
-// Setup
-
-blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
-{
-	RETURN_ERR( apu.init() );
-	enable_accuracy( false );
-	if ( sample_rate != native_sample_rate )
-	{
-		RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
-		resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
-	}
-	return 0;
-}
-
-void Spc_Emu::enable_accuracy_( bool b )
-{
-	Music_Emu::enable_accuracy_( b );
-	filter.enable( b );
-}
-
-void Spc_Emu::mute_voices_( int m )
-{
-	Music_Emu::mute_voices_( m );
-	apu.mute_voices( m );
-}
-
-blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
-{
-	assert( offsetof (header_t,unused2 [46]) == header_size );
-	file_data = in;
-	file_size = size;
-	set_voice_count( Snes_Spc::voice_count );
-	if ( size < Snes_Spc::spc_min_file_size )
-		return gme_wrong_file_type;
-	return check_spc_header( in );
-}
-
-// Emulation
-
-void Spc_Emu::set_tempo_( double t )
-{
-	apu.set_tempo( (int) (t * apu.tempo_unit) );
-}
-
-blargg_err_t Spc_Emu::start_track_( int track )
-{
-	RETURN_ERR( Music_Emu::start_track_( track ) );
-	resampler.clear();
-	filter.clear();
-	RETURN_ERR( apu.load_spc( file_data, file_size ) );
-	filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
-	apu.clear_echo();
-	return 0;
-}
-
-blargg_err_t Spc_Emu::play_and_filter( long count, sample_t out [] )
-{
-	RETURN_ERR( apu.play( count, out ) );
-	filter.run( out, count );
-	return 0;
-}
-
-blargg_err_t Spc_Emu::skip_( long count )
-{
-	if ( sample_rate() != native_sample_rate )
-	{
-		count = long (count * resampler.ratio()) & ~1;
-		count -= resampler.skip_input( count );
-	}
-
-	// TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
-
-	if ( count > 0 )
-	{
-		RETURN_ERR( apu.skip( count ) );
-		filter.clear();
-	}
-
-	// eliminate pop due to resampler
-	const int resampler_latency = 64;
-	sample_t buf [resampler_latency];
-	return play_( resampler_latency, buf );
-}
-
-blargg_err_t Spc_Emu::play_( long count, sample_t* out )
-{
-	if ( sample_rate() == native_sample_rate )
-		return play_and_filter( count, out );
-
-	long remain = count;
-	while ( remain > 0 )
-	{
-		remain -= resampler.read( &out [count - remain], remain );
-		if ( remain > 0 )
-		{
-			long n = resampler.max_write();
-			RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
-			resampler.write( n );
-		}
-	}
-	check( remain == 0 );
-	return 0;
-}
diff --git a/src/console/Spc_Filter.cc b/src/console/Spc_Filter.cc
new file mode 100644
index 000000000000..af478127af82
--- /dev/null
+++ b/src/console/Spc_Filter.cc
@@ -0,0 +1,83 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Spc_Filter.h"
+
+#include <string.h>
+
+/* Copyright (C) 2007 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); }
+
+SPC_Filter::SPC_Filter()
+{
+	enabled = true;
+	gain    = gain_unit;
+	bass    = bass_norm;
+	clear();
+}
+
+void SPC_Filter::run( short* io, int count )
+{
+	require( (count & 1) == 0 ); // must be even
+
+	int const gain = this->gain;
+	if ( enabled )
+	{
+		int const bass = this->bass;
+		chan_t* c = &ch [2];
+		do
+		{
+			// cache in registers
+			int sum = (--c)->sum;
+			int pp1 = c->pp1;
+			int p1  = c->p1;
+
+			for ( int i = 0; i < count; i += 2 )
+			{
+				// Low-pass filter (two point FIR with coeffs 0.25, 0.75)
+				int f = io [i] + p1;
+				p1 = io [i] * 3;
+
+				// High-pass filter ("leaky integrator")
+				int delta = f - pp1;
+				pp1 = f;
+				int s = sum >> (gain_bits + 2);
+				sum += (delta * gain) - (sum >> bass);
+
+				// Clamp to 16 bits
+				if ( (short) s != s )
+					s = (s >> 31) ^ 0x7FFF;
+
+				io [i] = (short) s;
+			}
+
+			c->p1  = p1;
+			c->pp1 = pp1;
+			c->sum = sum;
+			++io;
+		}
+		while ( c != ch );
+	}
+	else if ( gain != gain_unit )
+	{
+		short* const end = io + count;
+		while ( io < end )
+		{
+			int s = (*io * gain) >> gain_bits;
+			if ( (short) s != s )
+				s = (s >> 31) ^ 0x7FFF;
+			*io++ = (short) s;
+		}
+	}
+}
diff --git a/src/console/Spc_Filter.cxx b/src/console/Spc_Filter.cxx
deleted file mode 100644
index af478127af82..000000000000
--- a/src/console/Spc_Filter.cxx
+++ /dev/null
@@ -1,83 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Spc_Filter.h"
-
-#include <string.h>
-
-/* Copyright (C) 2007 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); }
-
-SPC_Filter::SPC_Filter()
-{
-	enabled = true;
-	gain    = gain_unit;
-	bass    = bass_norm;
-	clear();
-}
-
-void SPC_Filter::run( short* io, int count )
-{
-	require( (count & 1) == 0 ); // must be even
-
-	int const gain = this->gain;
-	if ( enabled )
-	{
-		int const bass = this->bass;
-		chan_t* c = &ch [2];
-		do
-		{
-			// cache in registers
-			int sum = (--c)->sum;
-			int pp1 = c->pp1;
-			int p1  = c->p1;
-
-			for ( int i = 0; i < count; i += 2 )
-			{
-				// Low-pass filter (two point FIR with coeffs 0.25, 0.75)
-				int f = io [i] + p1;
-				p1 = io [i] * 3;
-
-				// High-pass filter ("leaky integrator")
-				int delta = f - pp1;
-				pp1 = f;
-				int s = sum >> (gain_bits + 2);
-				sum += (delta * gain) - (sum >> bass);
-
-				// Clamp to 16 bits
-				if ( (short) s != s )
-					s = (s >> 31) ^ 0x7FFF;
-
-				io [i] = (short) s;
-			}
-
-			c->p1  = p1;
-			c->pp1 = pp1;
-			c->sum = sum;
-			++io;
-		}
-		while ( c != ch );
-	}
-	else if ( gain != gain_unit )
-	{
-		short* const end = io + count;
-		while ( io < end )
-		{
-			int s = (*io * gain) >> gain_bits;
-			if ( (short) s != s )
-				s = (s >> 31) ^ 0x7FFF;
-			*io++ = (short) s;
-		}
-	}
-}
diff --git a/src/console/Track_Emu.cc b/src/console/Track_Emu.cc
new file mode 100644
index 000000000000..d70ea861a37a
--- /dev/null
+++ b/src/console/Track_Emu.cc
@@ -0,0 +1,186 @@
+
+// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
+
+#include "Track_Emu.h"
+
+#include <string.h>
+#include <math.h>
+
+/* Copyright (C) 2005-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include BLARGG_SOURCE_BEGIN
+
+int const stereo = 2; // channels for a stereo signal
+int const fade_block_size = 512;
+int const fade_length = 8000; // msec
+int const silence_max = 6; // seconds
+int const silence_threshold = 0x10;
+
+long Track_Emu::msec_to_samples( long msec ) const
+{
+	long rate = emu->sample_rate() * stereo;
+	return (msec / 1000L) * rate + (msec % 1000L) * rate / 1000;
+}
+
+void Track_Emu::sync( long time )
+{
+	buf_count = 0;
+	silence_count = 0;
+	emu_time = time;
+	out_time = time;
+	silence_time = time;
+	track_ended = time > fade_time + fade_length * stereo * emu->sample_rate();
+}
+
+void Track_Emu::restart_track()
+{
+	emu->start_track( track );
+	sync ( 0 );
+
+	// skip initial silence
+	for ( int n = 40 * stereo * emu->sample_rate() / buf_size; n--; )
+	{
+		fill_buf( true );
+		if ( buf_count || track_ended )
+			break;
+	}
+	sync( 0 );
+}
+
+void Track_Emu::seek( long time )
+{
+	long pos = msec_to_samples( time ) & ~1;
+	if ( pos < out_time )
+		restart_track();
+	emu->skip( pos - emu_time );
+	sync( pos );
+}
+
+long Track_Emu::tell() const
+{
+	long rate = emu->sample_rate() * stereo;
+	return (out_time / rate * 1000) + (out_time % rate * 1000 / rate);
+}
+
+void Track_Emu::start_track( Music_Emu* e, int t, long length, bool ds )
+{
+// to do: remove
+//length = 50 * 1000;
+//ds = true;
+//t = 23;
+
+	emu = e;
+	track = t;
+	detect_silence = ds;
+	fade_factor = pow( 0.005, 1.0 / msec_to_samples( fade_length ) );
+	fade_time = msec_to_samples( length );
+	restart_track();
+}
+
+static bool is_silence( const Music_Emu::sample_t* p, int count )
+{
+	while ( count-- )
+	{
+		if ( (unsigned) (*p++ + silence_threshold / 2) > (unsigned) silence_threshold )
+			return false;
+	}
+	return true;
+}
+
+void Track_Emu::fill_buf( bool check_silence )
+{
+	emu->play( buf_size, buf );
+	emu_time += buf_size;
+	if ( (check_silence || emu_time > fade_time) && is_silence( buf, buf_size ) )
+	{
+		silence_count += buf_size;
+	}
+	else
+	{
+		silence_time = emu_time;
+		buf_count = buf_size;
+	}
+	if ( emu->track_ended() || emu->error_count() )
+		track_ended = true;
+}
+
+inline void Track_Emu::end_track()
+{
+	silence_count = 0;
+	buf_count = 0;
+	track_ended = true;
+}
+
+bool Track_Emu::play( int out_count, Music_Emu::sample_t* out )
+{
+	assert( out_count % 2 == 0 );
+	assert( emu );
+
+	int pos = 0;
+	while ( pos < out_count )
+	{
+		// fill with any remaining silence
+		int count = min( silence_count, out_count - pos );
+		if ( count )
+		{
+			silence_count -= count;
+			memset( &out [pos], 0, count * sizeof *out );
+		}
+		else
+		{
+			// empty internal buffer
+			count = min( buf_count, out_count - pos );
+			if ( !count && track_ended )
+			{
+				memset( &out [pos], 0, (out_count - pos) * sizeof *out );
+				return true;
+			}
+
+			memcpy( &out [pos], &buf [buf_size - buf_count], count * sizeof *out );
+			buf_count -= count;
+		}
+		pos += count;
+
+		// keep internal buffer full and possibly run ahead
+		for ( int n = 6; n--; )
+		{
+			if ( buf_count || track_ended ||
+					emu_time - out_time > silence_max * stereo * emu->sample_rate() )
+				break;
+			fill_buf( detect_silence );
+		}
+	}
+	out_time += out_count;
+
+	if ( detect_silence &&
+		( emu_time - silence_time > silence_max * stereo * emu->sample_rate() && silence_time ) )
+		end_track();
+
+	// fade if track is ending
+	if ( out_time > fade_time )
+	{
+		for ( int i = 0; i < out_count; i += fade_block_size )
+		{
+			double gain = pow( fade_factor, (double) (out_time + i - fade_time) );
+			if ( gain < 0.005 )
+				end_track();
+
+			int count = min( fade_block_size, out_count - i );
+			int igain = (unsigned int)((double)gain * (1 << 15));;
+			for ( int j = 0; j < count; j++ )
+				out [i + j] = (out [i + j] * igain) >> 15;
+		}
+	}
+
+	return !silence_count && !buf_count && track_ended;
+}
+
diff --git a/src/console/Track_Emu.cxx b/src/console/Track_Emu.cxx
deleted file mode 100644
index d70ea861a37a..000000000000
--- a/src/console/Track_Emu.cxx
+++ /dev/null
@@ -1,186 +0,0 @@
-
-// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
-
-#include "Track_Emu.h"
-
-#include <string.h>
-#include <math.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include BLARGG_SOURCE_BEGIN
-
-int const stereo = 2; // channels for a stereo signal
-int const fade_block_size = 512;
-int const fade_length = 8000; // msec
-int const silence_max = 6; // seconds
-int const silence_threshold = 0x10;
-
-long Track_Emu::msec_to_samples( long msec ) const
-{
-	long rate = emu->sample_rate() * stereo;
-	return (msec / 1000L) * rate + (msec % 1000L) * rate / 1000;
-}
-
-void Track_Emu::sync( long time )
-{
-	buf_count = 0;
-	silence_count = 0;
-	emu_time = time;
-	out_time = time;
-	silence_time = time;
-	track_ended = time > fade_time + fade_length * stereo * emu->sample_rate();
-}
-
-void Track_Emu::restart_track()
-{
-	emu->start_track( track );
-	sync ( 0 );
-
-	// skip initial silence
-	for ( int n = 40 * stereo * emu->sample_rate() / buf_size; n--; )
-	{
-		fill_buf( true );
-		if ( buf_count || track_ended )
-			break;
-	}
-	sync( 0 );
-}
-
-void Track_Emu::seek( long time )
-{
-	long pos = msec_to_samples( time ) & ~1;
-	if ( pos < out_time )
-		restart_track();
-	emu->skip( pos - emu_time );
-	sync( pos );
-}
-
-long Track_Emu::tell() const
-{
-	long rate = emu->sample_rate() * stereo;
-	return (out_time / rate * 1000) + (out_time % rate * 1000 / rate);
-}
-
-void Track_Emu::start_track( Music_Emu* e, int t, long length, bool ds )
-{
-// to do: remove
-//length = 50 * 1000;
-//ds = true;
-//t = 23;
-
-	emu = e;
-	track = t;
-	detect_silence = ds;
-	fade_factor = pow( 0.005, 1.0 / msec_to_samples( fade_length ) );
-	fade_time = msec_to_samples( length );
-	restart_track();
-}
-
-static bool is_silence( const Music_Emu::sample_t* p, int count )
-{
-	while ( count-- )
-	{
-		if ( (unsigned) (*p++ + silence_threshold / 2) > (unsigned) silence_threshold )
-			return false;
-	}
-	return true;
-}
-
-void Track_Emu::fill_buf( bool check_silence )
-{
-	emu->play( buf_size, buf );
-	emu_time += buf_size;
-	if ( (check_silence || emu_time > fade_time) && is_silence( buf, buf_size ) )
-	{
-		silence_count += buf_size;
-	}
-	else
-	{
-		silence_time = emu_time;
-		buf_count = buf_size;
-	}
-	if ( emu->track_ended() || emu->error_count() )
-		track_ended = true;
-}
-
-inline void Track_Emu::end_track()
-{
-	silence_count = 0;
-	buf_count = 0;
-	track_ended = true;
-}
-
-bool Track_Emu::play( int out_count, Music_Emu::sample_t* out )
-{
-	assert( out_count % 2 == 0 );
-	assert( emu );
-
-	int pos = 0;
-	while ( pos < out_count )
-	{
-		// fill with any remaining silence
-		int count = min( silence_count, out_count - pos );
-		if ( count )
-		{
-			silence_count -= count;
-			memset( &out [pos], 0, count * sizeof *out );
-		}
-		else
-		{
-			// empty internal buffer
-			count = min( buf_count, out_count - pos );
-			if ( !count && track_ended )
-			{
-				memset( &out [pos], 0, (out_count - pos) * sizeof *out );
-				return true;
-			}
-
-			memcpy( &out [pos], &buf [buf_size - buf_count], count * sizeof *out );
-			buf_count -= count;
-		}
-		pos += count;
-
-		// keep internal buffer full and possibly run ahead
-		for ( int n = 6; n--; )
-		{
-			if ( buf_count || track_ended ||
-					emu_time - out_time > silence_max * stereo * emu->sample_rate() )
-				break;
-			fill_buf( detect_silence );
-		}
-	}
-	out_time += out_count;
-
-	if ( detect_silence &&
-		( emu_time - silence_time > silence_max * stereo * emu->sample_rate() && silence_time ) )
-		end_track();
-
-	// fade if track is ending
-	if ( out_time > fade_time )
-	{
-		for ( int i = 0; i < out_count; i += fade_block_size )
-		{
-			double gain = pow( fade_factor, (double) (out_time + i - fade_time) );
-			if ( gain < 0.005 )
-				end_track();
-
-			int count = min( fade_block_size, out_count - i );
-			int igain = (unsigned int)((double)gain * (1 << 15));;
-			for ( int j = 0; j < count; j++ )
-				out [i + j] = (out [i + j] * igain) >> 15;
-		}
-	}
-
-	return !silence_count && !buf_count && track_ended;
-}
-
diff --git a/src/console/Vfs_File.cc b/src/console/Vfs_File.cc
new file mode 100644
index 000000000000..648d60481e6c
--- /dev/null
+++ b/src/console/Vfs_File.cc
@@ -0,0 +1,57 @@
+#include <stdio.h>
+
+#include "Vfs_File.h"
+
+#include "libaudcore/vfs.h"
+
+void Vfs_File_Reader::reset(VFSFile &file_)
+{
+	close();
+	file = &file_;
+}
+
+Vfs_File_Reader::error_t Vfs_File_Reader::open( const char* path )
+{
+	close();
+	file = owned_file = new VFSFile (path, "r");
+
+	if (! * file)
+	{
+		close();
+		return "Couldn't open file";
+	}
+
+	return 0;
+}
+
+long Vfs_File_Reader::size() const
+{
+	return file->fsize ();
+}
+
+long Vfs_File_Reader::read_avail (void * buf, long size)
+{
+	return (long) file->fread (buf, 1, size);
+}
+
+long Vfs_File_Reader::tell() const
+{
+	return file->ftell ();
+}
+
+Vfs_File_Reader::error_t Vfs_File_Reader::seek( long n )
+{
+	if (file->fseek (n, VFS_SEEK_SET) < 0)
+		return eof_error;
+	return 0;
+}
+
+void Vfs_File_Reader::close()
+{
+	file = 0;
+	if (owned_file)
+	{
+		delete owned_file;
+		owned_file = 0;
+	}
+}
diff --git a/src/console/Vfs_File.cxx b/src/console/Vfs_File.cxx
deleted file mode 100644
index 618c0a777dff..000000000000
--- a/src/console/Vfs_File.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <stdio.h>
-
-#include "Vfs_File.h"
-
-extern "C" {
-#include "libaudcore/vfs.h"
-}
-
-struct reader_private {
-	VFSFile * file, * owned_file;
-};
-
-Vfs_File_Reader::Vfs_File_Reader ()
-{
-	p = new struct reader_private;
-	p->file = 0;
-	p->owned_file = 0;
-}
-
-Vfs_File_Reader::~Vfs_File_Reader ()
-{
-	close ();
-	delete p;
-}
-
-void Vfs_File_Reader::reset (/* VFSFile * */ void * file)
-{
-	close ();
-	p->file = (VFSFile *) file;
-}
-
-Vfs_File_Reader::error_t Vfs_File_Reader::open( const char* path )
-{
-	close();
-	p->file = p->owned_file = vfs_fopen (path, "r");
-	if (! p->file)
-		return "Couldn't open file";
-	return 0;
-}
-
-long Vfs_File_Reader::size() const
-{
-	return vfs_fsize (p->file);
-}
-
-long Vfs_File_Reader::read_avail (void * buf, long size)
-{
-	return (long) vfs_fread (buf, 1, size, p->file);
-}
-
-long Vfs_File_Reader::tell() const
-{
-	return vfs_ftell (p->file);
-}
-
-Vfs_File_Reader::error_t Vfs_File_Reader::seek( long n )
-{
-	if (vfs_fseek (p->file, n, SEEK_SET) < 0)
-		return eof_error;
-	return 0;
-}
-
-void Vfs_File_Reader::close()
-{
-	p->file = 0;
-	if (p->owned_file)
-	{
-		vfs_fclose (p->owned_file);
-		p->owned_file = 0;
-	}
-}
diff --git a/src/console/Vfs_File.h b/src/console/Vfs_File.h
index 267558314446..36e373b67e3d 100644
--- a/src/console/Vfs_File.h
+++ b/src/console/Vfs_File.h
@@ -5,22 +5,24 @@
 
 #include "Data_Reader.h"
 
+class VFSFile;
+
 class Vfs_File_Reader : public File_Reader {
 public:
 	// use already-open file and doesn't close it in close()
-	void reset (/* VFSFile * */ void * file);
+	void reset(VFSFile &file_);
 	error_t open( const char* path );
 	void close();
 
-public:
-	Vfs_File_Reader();
-	~Vfs_File_Reader();
+	~Vfs_File_Reader()
+	    { close(); }
+
 	long size() const;
 	long read_avail( void*, long );
 	long tell() const;
 	error_t seek( long );
 private:
-    struct reader_private * p;
+	VFSFile *file = nullptr, *owned_file = nullptr;
 };
 
 #endif
diff --git a/src/console/Vgm_Emu.cc b/src/console/Vgm_Emu.cc
new file mode 100644
index 000000000000..68028687e554
--- /dev/null
+++ b/src/console/Vgm_Emu.cc
@@ -0,0 +1,416 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Vgm_Emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+#include <math.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
+double const rolloff = 0.990;
+double const oversample_factor = 1.5;
+
+Vgm_Emu::Vgm_Emu()
+{
+	disable_oversampling_ = false;
+	psg_rate   = 0;
+	set_type( gme_vgm_type );
+
+	static int const types [8] = {
+		wave_type | 1, wave_type | 0, wave_type | 2, noise_type | 0
+	};
+	set_voice_types( types );
+
+	set_silence_lookahead( 1 ); // tracks should already be trimmed
+
+	static equalizer_t const eq = { -14.0, 80 };
+	set_equalizer( eq );
+}
+
+Vgm_Emu::~Vgm_Emu() { }
+
+// Track info
+
+static byte const* skip_gd3_str( byte const* in, byte const* end )
+{
+	while ( end - in >= 2 )
+	{
+		in += 2;
+		if ( !(in [-2] | in [-1]) )
+			break;
+	}
+	return in;
+}
+
+static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
+{
+	byte const* mid = skip_gd3_str( in, end );
+	int len = (mid - in) / 2 - 1;
+	if ( len > 0 )
+	{
+		len = min( len, (int) Gme_File::max_field_ );
+		field [len] = 0;
+		for ( int i = 0; i < len; i++ )
+			field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
+	}
+	return mid;
+}
+
+static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
+{
+	return skip_gd3_str( get_gd3_str( in, end, field ), end );
+}
+
+static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
+{
+	in = get_gd3_pair( in, end, out->song );
+	in = get_gd3_pair( in, end, out->game );
+	in = get_gd3_pair( in, end, out->system );
+	in = get_gd3_pair( in, end, out->author );
+	in = get_gd3_str ( in, end, out->copyright );
+	in = get_gd3_pair( in, end, out->dumper );
+	in = get_gd3_str ( in, end, out->comment );
+}
+
+int const gd3_header_size = 12;
+
+static long check_gd3_header( byte const* h, long remain )
+{
+	if ( remain < gd3_header_size ) return 0;
+	if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
+	if ( GET_LE32( h + 4 ) >= 0x200 ) return 0;
+
+	long gd3_size = GET_LE32( h + 8 );
+	if ( gd3_size > remain - gd3_header_size ) return 0;
+
+	return gd3_size;
+}
+
+byte const* Vgm_Emu::gd3_data( int* size ) const
+{
+	if ( size )
+		*size = 0;
+
+	long gd3_offset = GET_LE32( header().gd3_offset ) - 0x2C;
+	if ( gd3_offset < 0 )
+		return 0;
+
+	byte const* gd3 = data + header_size + gd3_offset;
+	long gd3_size = check_gd3_header( gd3, data_end - gd3 );
+	if ( !gd3_size )
+		return 0;
+
+	if ( size )
+		*size = gd3_size + gd3_header_size;
+
+	return gd3;
+}
+
+static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
+{
+	long length = GET_LE32( h.track_duration ) * 10 / 441;
+	if ( length > 0 )
+	{
+		long loop = GET_LE32( h.loop_duration );
+		if ( loop > 0 && GET_LE32( h.loop_offset ) )
+		{
+			out->loop_length = loop * 10 / 441;
+			out->intro_length = length - out->loop_length;
+		}
+		else
+		{
+			out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
+			out->intro_length = length; // make it clear that track is no longer than length
+			out->loop_length = 0;
+		}
+	}
+}
+
+blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
+{
+	get_vgm_length( header(), out );
+
+	int size;
+	byte const* gd3 = gd3_data( &size );
+	if ( gd3 )
+		parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
+
+	return 0;
+}
+
+static blargg_err_t check_vgm_header( Vgm_Emu::header_t const& h )
+{
+	if ( memcmp( h.tag, "Vgm ", 4 ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+struct Vgm_File : Gme_Info_
+{
+	Vgm_Emu::header_t h;
+	blargg_vector<byte> gd3;
+
+	Vgm_File() { set_type( gme_vgm_type ); }
+
+	blargg_err_t load_( Data_Reader& in )
+	{
+		long file_size = in.remain();
+		if ( file_size <= Vgm_Emu::header_size )
+			return gme_wrong_file_type;
+
+		RETURN_ERR( in.read( &h, Vgm_Emu::header_size ) );
+		RETURN_ERR( check_vgm_header( h ) );
+
+		long gd3_offset = GET_LE32( h.gd3_offset ) - 0x2C;
+		long remain = file_size - Vgm_Emu::header_size - gd3_offset;
+		byte gd3_h [gd3_header_size];
+		if ( gd3_offset > 0 && remain >= gd3_header_size )
+		{
+			RETURN_ERR( in.skip( gd3_offset ) );
+			RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
+			long gd3_size = check_gd3_header( gd3_h, remain );
+			if ( gd3_size )
+			{
+				RETURN_ERR( gd3.resize( gd3_size ) );
+				RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
+			}
+		}
+		return 0;
+	}
+
+	blargg_err_t track_info_( track_info_t* out, int ) const
+	{
+		get_vgm_length( h, out );
+		if ( gd3.size() )
+			parse_gd3( gd3.begin(), gd3.end(), out );
+		return 0;
+	}
+};
+
+static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
+static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
+
+static gme_type_t_ const gme_vgm_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 };
+gme_type_t const gme_vgm_type = &gme_vgm_type_;
+
+static gme_type_t_ const gme_vgz_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 };
+gme_type_t const gme_vgz_type = &gme_vgz_type_;
+
+
+// Setup
+
+void Vgm_Emu::set_tempo_( double t )
+{
+	if ( psg_rate )
+	{
+		vgm_rate = (long) (44100 * t + 0.5);
+		blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
+		//debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
+		//debug_printf( "vgm_rate: %ld\n", vgm_rate );
+		// TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
+		//blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
+		//vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
+
+		fm_time_factor = 2 + (long) floor( fm_rate * (1L << fm_time_bits) / vgm_rate + 0.5 );
+	}
+}
+
+blargg_err_t Vgm_Emu::set_sample_rate_( long sample_rate )
+{
+	RETURN_ERR( blip_buf.set_sample_rate( sample_rate, 1000 / 30 ) );
+	return Classic_Emu::set_sample_rate_( sample_rate );
+}
+
+void Vgm_Emu::update_eq( blip_eq_t const& eq )
+{
+	psg.treble_eq( eq );
+	dac_synth.treble_eq( eq );
+}
+
+void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+	if ( i < psg.osc_count )
+		psg.osc_output( i, c, l, r );
+}
+
+void Vgm_Emu::mute_voices_( int mask )
+{
+	Classic_Emu::mute_voices_( mask );
+	dac_synth.output( &blip_buf );
+	if ( uses_fm )
+	{
+		psg.output( (mask & 0x80) ? 0 : &blip_buf );
+		if ( ym2612.enabled() )
+		{
+			dac_synth.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
+			ym2612.mute_voices( mask );
+		}
+
+		if ( ym2413.enabled() )
+		{
+			int m = mask & 0x3F;
+			if ( mask & 0x20 )
+				m |= 0x01E0; // channels 5-8
+			if ( mask & 0x40 )
+				m |= 0x3E00;
+			ym2413.mute_voices( m );
+		}
+	}
+}
+
+blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
+{
+	assert( offsetof (header_t,unused2 [8]) == header_size );
+
+	if ( new_size <= header_size )
+		return gme_wrong_file_type;
+
+	header_t const& h = *(header_t const*) new_data;
+
+	RETURN_ERR( check_vgm_header( h ) );
+
+	check( GET_LE32( h.version ) <= 0x150 );
+
+	// psg rate
+	psg_rate = GET_LE32( h.psg_rate );
+	if ( !psg_rate )
+		psg_rate = 3579545;
+	blip_buf.clock_rate( psg_rate );
+
+	data     = new_data;
+	data_end = new_data + new_size;
+
+	// get loop
+	loop_begin = data_end;
+	if ( GET_LE32( h.loop_offset ) )
+		loop_begin = &data [GET_LE32( h.loop_offset ) + offsetof (header_t,loop_offset)];
+
+	set_voice_count( psg.osc_count );
+
+	RETURN_ERR( setup_fm() );
+
+	static const char* const fm_names [] = {
+		"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
+	};
+	static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
+	set_voice_names( uses_fm ? fm_names : psg_names );
+
+	// do after FM in case output buffer is changed
+	return Classic_Emu::setup_buffer( psg_rate );
+}
+
+blargg_err_t Vgm_Emu::setup_fm()
+{
+	long ym2612_rate = GET_LE32( header().ym2612_rate );
+	long ym2413_rate = GET_LE32( header().ym2413_rate );
+	if ( ym2413_rate && GET_LE32( header().version ) < 0x110 )
+		update_fm_rates( &ym2413_rate, &ym2612_rate );
+
+	uses_fm = false;
+
+	fm_rate = blip_buf.sample_rate() * oversample_factor;
+
+	if ( ym2612_rate )
+	{
+		uses_fm = true;
+		if ( disable_oversampling_ )
+			fm_rate = ym2612_rate / 144.0;
+		Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
+		RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) );
+		ym2612.enable( true );
+		set_voice_count( 8 );
+	}
+
+	if ( !uses_fm && ym2413_rate )
+	{
+		uses_fm = true;
+		if ( disable_oversampling_ )
+			fm_rate = ym2413_rate / 72.0;
+		Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
+		int result = ym2413.set_rate( fm_rate, ym2413_rate );
+		if ( result == 2 )
+			return "YM2413 FM sound isn't supported";
+		CHECK_ALLOC( !result );
+		ym2413.enable( true );
+		set_voice_count( 8 );
+	}
+
+	if ( uses_fm )
+	{
+		RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) );
+		psg.volume( 0.135 * fm_gain * gain() );
+	}
+	else
+	{
+		ym2612.enable( false );
+		ym2413.enable( false );
+		psg.volume( gain() );
+	}
+
+	return 0;
+}
+
+// Emulation
+
+blargg_err_t Vgm_Emu::start_track_( int track )
+{
+	RETURN_ERR( Classic_Emu::start_track_( track ) );
+	psg.reset( GET_LE16( header().noise_feedback ), header().noise_width );
+
+	dac_disabled = -1;
+	pos          = data + header_size;
+	pcm_data     = pos;
+	pcm_pos      = pos;
+	dac_amp      = -1;
+	vgm_time     = 0;
+	if ( GET_LE32( header().version ) >= 0x150 )
+	{
+		long data_offset = GET_LE32( header().data_offset );
+		check( data_offset );
+		if ( data_offset )
+			pos += data_offset + offsetof (header_t,data_offset) - 0x40;
+	}
+
+	if ( uses_fm )
+	{
+		if ( ym2413.enabled() )
+			ym2413.reset();
+
+		if ( ym2612.enabled() )
+			ym2612.reset();
+
+		fm_time_offset = 0;
+		blip_buf.clear();
+		Dual_Resampler::clear();
+	}
+	return 0;
+}
+
+blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
+{
+	time_io = run_commands( msec * vgm_rate / 1000 );
+	psg.end_frame( time_io );
+	return 0;
+}
+
+blargg_err_t Vgm_Emu::play_( long count, sample_t* out )
+{
+	if ( !uses_fm )
+		return Classic_Emu::play_( count, out );
+
+	Dual_Resampler::dual_play( count, out, blip_buf );
+	return 0;
+}
diff --git a/src/console/Vgm_Emu.cxx b/src/console/Vgm_Emu.cxx
deleted file mode 100644
index 68028687e554..000000000000
--- a/src/console/Vgm_Emu.cxx
+++ /dev/null
@@ -1,416 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
-double const rolloff = 0.990;
-double const oversample_factor = 1.5;
-
-Vgm_Emu::Vgm_Emu()
-{
-	disable_oversampling_ = false;
-	psg_rate   = 0;
-	set_type( gme_vgm_type );
-
-	static int const types [8] = {
-		wave_type | 1, wave_type | 0, wave_type | 2, noise_type | 0
-	};
-	set_voice_types( types );
-
-	set_silence_lookahead( 1 ); // tracks should already be trimmed
-
-	static equalizer_t const eq = { -14.0, 80 };
-	set_equalizer( eq );
-}
-
-Vgm_Emu::~Vgm_Emu() { }
-
-// Track info
-
-static byte const* skip_gd3_str( byte const* in, byte const* end )
-{
-	while ( end - in >= 2 )
-	{
-		in += 2;
-		if ( !(in [-2] | in [-1]) )
-			break;
-	}
-	return in;
-}
-
-static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
-{
-	byte const* mid = skip_gd3_str( in, end );
-	int len = (mid - in) / 2 - 1;
-	if ( len > 0 )
-	{
-		len = min( len, (int) Gme_File::max_field_ );
-		field [len] = 0;
-		for ( int i = 0; i < len; i++ )
-			field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
-	}
-	return mid;
-}
-
-static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
-{
-	return skip_gd3_str( get_gd3_str( in, end, field ), end );
-}
-
-static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
-{
-	in = get_gd3_pair( in, end, out->song );
-	in = get_gd3_pair( in, end, out->game );
-	in = get_gd3_pair( in, end, out->system );
-	in = get_gd3_pair( in, end, out->author );
-	in = get_gd3_str ( in, end, out->copyright );
-	in = get_gd3_pair( in, end, out->dumper );
-	in = get_gd3_str ( in, end, out->comment );
-}
-
-int const gd3_header_size = 12;
-
-static long check_gd3_header( byte const* h, long remain )
-{
-	if ( remain < gd3_header_size ) return 0;
-	if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
-	if ( GET_LE32( h + 4 ) >= 0x200 ) return 0;
-
-	long gd3_size = GET_LE32( h + 8 );
-	if ( gd3_size > remain - gd3_header_size ) return 0;
-
-	return gd3_size;
-}
-
-byte const* Vgm_Emu::gd3_data( int* size ) const
-{
-	if ( size )
-		*size = 0;
-
-	long gd3_offset = GET_LE32( header().gd3_offset ) - 0x2C;
-	if ( gd3_offset < 0 )
-		return 0;
-
-	byte const* gd3 = data + header_size + gd3_offset;
-	long gd3_size = check_gd3_header( gd3, data_end - gd3 );
-	if ( !gd3_size )
-		return 0;
-
-	if ( size )
-		*size = gd3_size + gd3_header_size;
-
-	return gd3;
-}
-
-static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
-{
-	long length = GET_LE32( h.track_duration ) * 10 / 441;
-	if ( length > 0 )
-	{
-		long loop = GET_LE32( h.loop_duration );
-		if ( loop > 0 && GET_LE32( h.loop_offset ) )
-		{
-			out->loop_length = loop * 10 / 441;
-			out->intro_length = length - out->loop_length;
-		}
-		else
-		{
-			out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
-			out->intro_length = length; // make it clear that track is no longer than length
-			out->loop_length = 0;
-		}
-	}
-}
-
-blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
-{
-	get_vgm_length( header(), out );
-
-	int size;
-	byte const* gd3 = gd3_data( &size );
-	if ( gd3 )
-		parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
-
-	return 0;
-}
-
-static blargg_err_t check_vgm_header( Vgm_Emu::header_t const& h )
-{
-	if ( memcmp( h.tag, "Vgm ", 4 ) )
-		return gme_wrong_file_type;
-	return 0;
-}
-
-struct Vgm_File : Gme_Info_
-{
-	Vgm_Emu::header_t h;
-	blargg_vector<byte> gd3;
-
-	Vgm_File() { set_type( gme_vgm_type ); }
-
-	blargg_err_t load_( Data_Reader& in )
-	{
-		long file_size = in.remain();
-		if ( file_size <= Vgm_Emu::header_size )
-			return gme_wrong_file_type;
-
-		RETURN_ERR( in.read( &h, Vgm_Emu::header_size ) );
-		RETURN_ERR( check_vgm_header( h ) );
-
-		long gd3_offset = GET_LE32( h.gd3_offset ) - 0x2C;
-		long remain = file_size - Vgm_Emu::header_size - gd3_offset;
-		byte gd3_h [gd3_header_size];
-		if ( gd3_offset > 0 && remain >= gd3_header_size )
-		{
-			RETURN_ERR( in.skip( gd3_offset ) );
-			RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
-			long gd3_size = check_gd3_header( gd3_h, remain );
-			if ( gd3_size )
-			{
-				RETURN_ERR( gd3.resize( gd3_size ) );
-				RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
-			}
-		}
-		return 0;
-	}
-
-	blargg_err_t track_info_( track_info_t* out, int ) const
-	{
-		get_vgm_length( h, out );
-		if ( gd3.size() )
-			parse_gd3( gd3.begin(), gd3.end(), out );
-		return 0;
-	}
-};
-
-static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
-static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
-
-static gme_type_t_ const gme_vgm_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 };
-gme_type_t const gme_vgm_type = &gme_vgm_type_;
-
-static gme_type_t_ const gme_vgz_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 };
-gme_type_t const gme_vgz_type = &gme_vgz_type_;
-
-
-// Setup
-
-void Vgm_Emu::set_tempo_( double t )
-{
-	if ( psg_rate )
-	{
-		vgm_rate = (long) (44100 * t + 0.5);
-		blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
-		//debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
-		//debug_printf( "vgm_rate: %ld\n", vgm_rate );
-		// TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
-		//blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
-		//vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
-
-		fm_time_factor = 2 + (long) floor( fm_rate * (1L << fm_time_bits) / vgm_rate + 0.5 );
-	}
-}
-
-blargg_err_t Vgm_Emu::set_sample_rate_( long sample_rate )
-{
-	RETURN_ERR( blip_buf.set_sample_rate( sample_rate, 1000 / 30 ) );
-	return Classic_Emu::set_sample_rate_( sample_rate );
-}
-
-void Vgm_Emu::update_eq( blip_eq_t const& eq )
-{
-	psg.treble_eq( eq );
-	dac_synth.treble_eq( eq );
-}
-
-void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
-	if ( i < psg.osc_count )
-		psg.osc_output( i, c, l, r );
-}
-
-void Vgm_Emu::mute_voices_( int mask )
-{
-	Classic_Emu::mute_voices_( mask );
-	dac_synth.output( &blip_buf );
-	if ( uses_fm )
-	{
-		psg.output( (mask & 0x80) ? 0 : &blip_buf );
-		if ( ym2612.enabled() )
-		{
-			dac_synth.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
-			ym2612.mute_voices( mask );
-		}
-
-		if ( ym2413.enabled() )
-		{
-			int m = mask & 0x3F;
-			if ( mask & 0x20 )
-				m |= 0x01E0; // channels 5-8
-			if ( mask & 0x40 )
-				m |= 0x3E00;
-			ym2413.mute_voices( m );
-		}
-	}
-}
-
-blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
-{
-	assert( offsetof (header_t,unused2 [8]) == header_size );
-
-	if ( new_size <= header_size )
-		return gme_wrong_file_type;
-
-	header_t const& h = *(header_t const*) new_data;
-
-	RETURN_ERR( check_vgm_header( h ) );
-
-	check( GET_LE32( h.version ) <= 0x150 );
-
-	// psg rate
-	psg_rate = GET_LE32( h.psg_rate );
-	if ( !psg_rate )
-		psg_rate = 3579545;
-	blip_buf.clock_rate( psg_rate );
-
-	data     = new_data;
-	data_end = new_data + new_size;
-
-	// get loop
-	loop_begin = data_end;
-	if ( GET_LE32( h.loop_offset ) )
-		loop_begin = &data [GET_LE32( h.loop_offset ) + offsetof (header_t,loop_offset)];
-
-	set_voice_count( psg.osc_count );
-
-	RETURN_ERR( setup_fm() );
-
-	static const char* const fm_names [] = {
-		"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
-	};
-	static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
-	set_voice_names( uses_fm ? fm_names : psg_names );
-
-	// do after FM in case output buffer is changed
-	return Classic_Emu::setup_buffer( psg_rate );
-}
-
-blargg_err_t Vgm_Emu::setup_fm()
-{
-	long ym2612_rate = GET_LE32( header().ym2612_rate );
-	long ym2413_rate = GET_LE32( header().ym2413_rate );
-	if ( ym2413_rate && GET_LE32( header().version ) < 0x110 )
-		update_fm_rates( &ym2413_rate, &ym2612_rate );
-
-	uses_fm = false;
-
-	fm_rate = blip_buf.sample_rate() * oversample_factor;
-
-	if ( ym2612_rate )
-	{
-		uses_fm = true;
-		if ( disable_oversampling_ )
-			fm_rate = ym2612_rate / 144.0;
-		Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
-		RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) );
-		ym2612.enable( true );
-		set_voice_count( 8 );
-	}
-
-	if ( !uses_fm && ym2413_rate )
-	{
-		uses_fm = true;
-		if ( disable_oversampling_ )
-			fm_rate = ym2413_rate / 72.0;
-		Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
-		int result = ym2413.set_rate( fm_rate, ym2413_rate );
-		if ( result == 2 )
-			return "YM2413 FM sound isn't supported";
-		CHECK_ALLOC( !result );
-		ym2413.enable( true );
-		set_voice_count( 8 );
-	}
-
-	if ( uses_fm )
-	{
-		RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) );
-		psg.volume( 0.135 * fm_gain * gain() );
-	}
-	else
-	{
-		ym2612.enable( false );
-		ym2413.enable( false );
-		psg.volume( gain() );
-	}
-
-	return 0;
-}
-
-// Emulation
-
-blargg_err_t Vgm_Emu::start_track_( int track )
-{
-	RETURN_ERR( Classic_Emu::start_track_( track ) );
-	psg.reset( GET_LE16( header().noise_feedback ), header().noise_width );
-
-	dac_disabled = -1;
-	pos          = data + header_size;
-	pcm_data     = pos;
-	pcm_pos      = pos;
-	dac_amp      = -1;
-	vgm_time     = 0;
-	if ( GET_LE32( header().version ) >= 0x150 )
-	{
-		long data_offset = GET_LE32( header().data_offset );
-		check( data_offset );
-		if ( data_offset )
-			pos += data_offset + offsetof (header_t,data_offset) - 0x40;
-	}
-
-	if ( uses_fm )
-	{
-		if ( ym2413.enabled() )
-			ym2413.reset();
-
-		if ( ym2612.enabled() )
-			ym2612.reset();
-
-		fm_time_offset = 0;
-		blip_buf.clear();
-		Dual_Resampler::clear();
-	}
-	return 0;
-}
-
-blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
-{
-	time_io = run_commands( msec * vgm_rate / 1000 );
-	psg.end_frame( time_io );
-	return 0;
-}
-
-blargg_err_t Vgm_Emu::play_( long count, sample_t* out )
-{
-	if ( !uses_fm )
-		return Classic_Emu::play_( count, out );
-
-	Dual_Resampler::dual_play( count, out, blip_buf );
-	return 0;
-}
diff --git a/src/console/Vgm_Emu_Impl.cc b/src/console/Vgm_Emu_Impl.cc
new file mode 100644
index 000000000000..24bdf29d4cc5
--- /dev/null
+++ b/src/console/Vgm_Emu_Impl.cc
@@ -0,0 +1,314 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Vgm_Emu.h"
+
+#include <math.h>
+#include <string.h>
+#include "blargg_endian.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+enum {
+	cmd_gg_stereo       = 0x4F,
+	cmd_psg             = 0x50,
+	cmd_ym2413          = 0x51,
+	cmd_ym2612_port0    = 0x52,
+	cmd_ym2612_port1    = 0x53,
+	cmd_ym2151          = 0x54,
+	cmd_delay           = 0x61,
+	cmd_delay_735       = 0x62,
+	cmd_delay_882       = 0x63,
+	cmd_byte_delay      = 0x64,
+	cmd_end             = 0x66,
+	cmd_data_block      = 0x67,
+	cmd_short_delay     = 0x70,
+	cmd_pcm_delay       = 0x80,
+	cmd_pcm_seek        = 0xE0,
+
+	pcm_block_type      = 0x00,
+	ym2612_dac_port     = 0x2A
+};
+
+inline int command_len( int command )
+{
+	switch ( command >> 4 )
+	{
+		case 0x03:
+		case 0x04:
+			return 2;
+
+		case 0x05:
+		case 0x0A:
+		case 0x0B:
+			return 3;
+
+		case 0x0C:
+		case 0x0D:
+			return 4;
+
+		case 0x0E:
+		case 0x0F:
+			return 5;
+	}
+
+	check( false );
+	return 1;
+}
+
+template<class Emu>
+inline void Ym_Emu<Emu>::begin_frame( short* p )
+{
+	require( enabled() );
+	out = p;
+	last_time = 0;
+}
+
+template<class Emu>
+inline int Ym_Emu<Emu>::run_until( int time )
+{
+	int count = time - last_time;
+	if ( count > 0 )
+	{
+		if ( last_time < 0 )
+			return false;
+		last_time = time;
+		short* p = out;
+		out += count * Emu::out_chan_count;
+		Emu::run( count, p );
+	}
+	return true;
+}
+
+inline Vgm_Emu_Impl::fm_time_t Vgm_Emu_Impl::to_fm_time( vgm_time_t t ) const
+{
+	return (t * fm_time_factor + fm_time_offset) >> fm_time_bits;
+}
+
+inline blip_time_t Vgm_Emu_Impl::to_blip_time( vgm_time_t t ) const
+{
+	return (t * blip_time_factor) >> blip_time_bits;
+}
+
+void Vgm_Emu_Impl::write_pcm( vgm_time_t vgm_time, int amp )
+{
+	blip_time_t blip_time = to_blip_time( vgm_time );
+	int old = dac_amp;
+	int delta = amp - old;
+	dac_amp = amp;
+	if ( old >= 0 )
+		dac_synth.offset_inline( blip_time, delta, &blip_buf );
+	else
+		dac_amp |= dac_disabled;
+}
+
+blip_time_t Vgm_Emu_Impl::run_commands( vgm_time_t end_time )
+{
+	vgm_time_t vgm_time = this->vgm_time;
+	byte const* pos = this->pos;
+	if ( pos >= data_end )
+	{
+		set_track_ended();
+		if ( pos > data_end )
+			set_warning( "Stream lacked end event" );
+	}
+
+	while ( vgm_time < end_time && pos < data_end )
+	{
+		// TODO: be sure there are enough bytes left in stream for particular command
+		// so we don't read past end
+		switch ( *pos++ )
+		{
+		case cmd_end:
+			pos = loop_begin; // if not looped, loop_begin == data_end
+			break;
+
+		case cmd_delay_735:
+			vgm_time += 735;
+			break;
+
+		case cmd_delay_882:
+			vgm_time += 882;
+			break;
+
+		case cmd_gg_stereo:
+			psg.write_ggstereo( to_blip_time( vgm_time ), *pos++ );
+			break;
+
+		case cmd_psg:
+			psg.write_data( to_blip_time( vgm_time ), *pos++ );
+			break;
+
+		case cmd_delay:
+			vgm_time += pos [1] * 0x100L + pos [0];
+			pos += 2;
+			break;
+
+		case cmd_byte_delay:
+			vgm_time += *pos++;
+			break;
+
+		case cmd_ym2413:
+			if ( ym2413.run_until( to_fm_time( vgm_time ) ) )
+				ym2413.write( pos [0], pos [1] );
+			pos += 2;
+			break;
+
+		case cmd_ym2612_port0:
+			if ( pos [0] == ym2612_dac_port )
+			{
+				write_pcm( vgm_time, pos [1] );
+			}
+			else if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
+			{
+				if ( pos [0] == 0x2B )
+				{
+					dac_disabled = (pos [1] >> 7 & 1) - 1;
+					dac_amp |= dac_disabled;
+				}
+				ym2612.write0( pos [0], pos [1] );
+			}
+			pos += 2;
+			break;
+
+		case cmd_ym2612_port1:
+			if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
+				ym2612.write1( pos [0], pos [1] );
+			pos += 2;
+			break;
+
+		case cmd_data_block: {
+			check( *pos == cmd_end );
+			int type = pos [1];
+			long size = GET_LE32( pos + 2 );
+			pos += 6;
+			if ( type == pcm_block_type )
+				pcm_data = pos;
+			pos += size;
+			break;
+		}
+
+		case cmd_pcm_seek:
+			pcm_pos = pcm_data + pos [3] * 0x1000000L + pos [2] * 0x10000L +
+					pos [1] * 0x100L + pos [0];
+			pos += 4;
+			break;
+
+		default:
+			int cmd = pos [-1];
+			switch ( cmd & 0xF0 )
+			{
+				case cmd_pcm_delay:
+					write_pcm( vgm_time, *pcm_pos++ );
+					vgm_time += cmd & 0x0F;
+					break;
+
+				case cmd_short_delay:
+					vgm_time += (cmd & 0x0F) + 1;
+					break;
+
+				case 0x50:
+					pos += 2;
+					break;
+
+				default:
+					pos += command_len( cmd ) - 1;
+					set_warning( "Unknown stream event" );
+			}
+		}
+	}
+	vgm_time -= end_time;
+	this->pos = pos;
+	this->vgm_time = vgm_time;
+
+	return to_blip_time( end_time );
+}
+
+int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
+{
+	// to do: timing is working mostly by luck
+
+	int min_pairs = sample_count >> 1;
+	int vgm_time = ((long) min_pairs << fm_time_bits) / fm_time_factor - 1;
+	assert( to_fm_time( vgm_time ) <= min_pairs );
+	int pairs = min_pairs;
+	while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
+		vgm_time++;
+	//debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
+
+	if ( ym2612.enabled() )
+	{
+		ym2612.begin_frame( buf );
+		memset( buf, 0, pairs * stereo * sizeof *buf );
+	}
+	else if ( ym2413.enabled() )
+	{
+		ym2413.begin_frame( buf );
+	}
+
+	run_commands( vgm_time );
+	ym2612.run_until( pairs );
+	ym2413.run_until( pairs );
+
+	fm_time_offset = (vgm_time * fm_time_factor + fm_time_offset) -
+			((long) pairs << fm_time_bits);
+
+	psg.end_frame( blip_time );
+
+	return pairs * stereo;
+}
+
+// Update pre-1.10 header FM rates by scanning commands
+void Vgm_Emu_Impl::update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const
+{
+	byte const* p = data + 0x40;
+	while ( p < data_end )
+	{
+		switch ( *p )
+		{
+		case cmd_end:
+			return;
+
+		case cmd_psg:
+		case cmd_byte_delay:
+			p += 2;
+			break;
+
+		case cmd_delay:
+			p += 3;
+			break;
+
+		case cmd_data_block:
+			p += 7 + GET_LE32( p + 3 );
+			break;
+
+		case cmd_ym2413:
+			*ym2612_rate = 0;
+			return;
+
+		case cmd_ym2612_port0:
+		case cmd_ym2612_port1:
+			*ym2612_rate = *ym2413_rate;
+			*ym2413_rate = 0;
+			return;
+
+		case cmd_ym2151:
+			*ym2413_rate = 0;
+			*ym2612_rate = 0;
+			return;
+
+		default:
+			p += command_len( *p );
+		}
+	}
+}
diff --git a/src/console/Vgm_Emu_Impl.cxx b/src/console/Vgm_Emu_Impl.cxx
deleted file mode 100644
index 24bdf29d4cc5..000000000000
--- a/src/console/Vgm_Emu_Impl.cxx
+++ /dev/null
@@ -1,314 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include <math.h>
-#include <string.h>
-#include "blargg_endian.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-enum {
-	cmd_gg_stereo       = 0x4F,
-	cmd_psg             = 0x50,
-	cmd_ym2413          = 0x51,
-	cmd_ym2612_port0    = 0x52,
-	cmd_ym2612_port1    = 0x53,
-	cmd_ym2151          = 0x54,
-	cmd_delay           = 0x61,
-	cmd_delay_735       = 0x62,
-	cmd_delay_882       = 0x63,
-	cmd_byte_delay      = 0x64,
-	cmd_end             = 0x66,
-	cmd_data_block      = 0x67,
-	cmd_short_delay     = 0x70,
-	cmd_pcm_delay       = 0x80,
-	cmd_pcm_seek        = 0xE0,
-
-	pcm_block_type      = 0x00,
-	ym2612_dac_port     = 0x2A
-};
-
-inline int command_len( int command )
-{
-	switch ( command >> 4 )
-	{
-		case 0x03:
-		case 0x04:
-			return 2;
-
-		case 0x05:
-		case 0x0A:
-		case 0x0B:
-			return 3;
-
-		case 0x0C:
-		case 0x0D:
-			return 4;
-
-		case 0x0E:
-		case 0x0F:
-			return 5;
-	}
-
-	check( false );
-	return 1;
-}
-
-template<class Emu>
-inline void Ym_Emu<Emu>::begin_frame( short* p )
-{
-	require( enabled() );
-	out = p;
-	last_time = 0;
-}
-
-template<class Emu>
-inline int Ym_Emu<Emu>::run_until( int time )
-{
-	int count = time - last_time;
-	if ( count > 0 )
-	{
-		if ( last_time < 0 )
-			return false;
-		last_time = time;
-		short* p = out;
-		out += count * Emu::out_chan_count;
-		Emu::run( count, p );
-	}
-	return true;
-}
-
-inline Vgm_Emu_Impl::fm_time_t Vgm_Emu_Impl::to_fm_time( vgm_time_t t ) const
-{
-	return (t * fm_time_factor + fm_time_offset) >> fm_time_bits;
-}
-
-inline blip_time_t Vgm_Emu_Impl::to_blip_time( vgm_time_t t ) const
-{
-	return (t * blip_time_factor) >> blip_time_bits;
-}
-
-void Vgm_Emu_Impl::write_pcm( vgm_time_t vgm_time, int amp )
-{
-	blip_time_t blip_time = to_blip_time( vgm_time );
-	int old = dac_amp;
-	int delta = amp - old;
-	dac_amp = amp;
-	if ( old >= 0 )
-		dac_synth.offset_inline( blip_time, delta, &blip_buf );
-	else
-		dac_amp |= dac_disabled;
-}
-
-blip_time_t Vgm_Emu_Impl::run_commands( vgm_time_t end_time )
-{
-	vgm_time_t vgm_time = this->vgm_time;
-	byte const* pos = this->pos;
-	if ( pos >= data_end )
-	{
-		set_track_ended();
-		if ( pos > data_end )
-			set_warning( "Stream lacked end event" );
-	}
-
-	while ( vgm_time < end_time && pos < data_end )
-	{
-		// TODO: be sure there are enough bytes left in stream for particular command
-		// so we don't read past end
-		switch ( *pos++ )
-		{
-		case cmd_end:
-			pos = loop_begin; // if not looped, loop_begin == data_end
-			break;
-
-		case cmd_delay_735:
-			vgm_time += 735;
-			break;
-
-		case cmd_delay_882:
-			vgm_time += 882;
-			break;
-
-		case cmd_gg_stereo:
-			psg.write_ggstereo( to_blip_time( vgm_time ), *pos++ );
-			break;
-
-		case cmd_psg:
-			psg.write_data( to_blip_time( vgm_time ), *pos++ );
-			break;
-
-		case cmd_delay:
-			vgm_time += pos [1] * 0x100L + pos [0];
-			pos += 2;
-			break;
-
-		case cmd_byte_delay:
-			vgm_time += *pos++;
-			break;
-
-		case cmd_ym2413:
-			if ( ym2413.run_until( to_fm_time( vgm_time ) ) )
-				ym2413.write( pos [0], pos [1] );
-			pos += 2;
-			break;
-
-		case cmd_ym2612_port0:
-			if ( pos [0] == ym2612_dac_port )
-			{
-				write_pcm( vgm_time, pos [1] );
-			}
-			else if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
-			{
-				if ( pos [0] == 0x2B )
-				{
-					dac_disabled = (pos [1] >> 7 & 1) - 1;
-					dac_amp |= dac_disabled;
-				}
-				ym2612.write0( pos [0], pos [1] );
-			}
-			pos += 2;
-			break;
-
-		case cmd_ym2612_port1:
-			if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
-				ym2612.write1( pos [0], pos [1] );
-			pos += 2;
-			break;
-
-		case cmd_data_block: {
-			check( *pos == cmd_end );
-			int type = pos [1];
-			long size = GET_LE32( pos + 2 );
-			pos += 6;
-			if ( type == pcm_block_type )
-				pcm_data = pos;
-			pos += size;
-			break;
-		}
-
-		case cmd_pcm_seek:
-			pcm_pos = pcm_data + pos [3] * 0x1000000L + pos [2] * 0x10000L +
-					pos [1] * 0x100L + pos [0];
-			pos += 4;
-			break;
-
-		default:
-			int cmd = pos [-1];
-			switch ( cmd & 0xF0 )
-			{
-				case cmd_pcm_delay:
-					write_pcm( vgm_time, *pcm_pos++ );
-					vgm_time += cmd & 0x0F;
-					break;
-
-				case cmd_short_delay:
-					vgm_time += (cmd & 0x0F) + 1;
-					break;
-
-				case 0x50:
-					pos += 2;
-					break;
-
-				default:
-					pos += command_len( cmd ) - 1;
-					set_warning( "Unknown stream event" );
-			}
-		}
-	}
-	vgm_time -= end_time;
-	this->pos = pos;
-	this->vgm_time = vgm_time;
-
-	return to_blip_time( end_time );
-}
-
-int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
-	// to do: timing is working mostly by luck
-
-	int min_pairs = sample_count >> 1;
-	int vgm_time = ((long) min_pairs << fm_time_bits) / fm_time_factor - 1;
-	assert( to_fm_time( vgm_time ) <= min_pairs );
-	int pairs = min_pairs;
-	while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
-		vgm_time++;
-	//debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
-
-	if ( ym2612.enabled() )
-	{
-		ym2612.begin_frame( buf );
-		memset( buf, 0, pairs * stereo * sizeof *buf );
-	}
-	else if ( ym2413.enabled() )
-	{
-		ym2413.begin_frame( buf );
-	}
-
-	run_commands( vgm_time );
-	ym2612.run_until( pairs );
-	ym2413.run_until( pairs );
-
-	fm_time_offset = (vgm_time * fm_time_factor + fm_time_offset) -
-			((long) pairs << fm_time_bits);
-
-	psg.end_frame( blip_time );
-
-	return pairs * stereo;
-}
-
-// Update pre-1.10 header FM rates by scanning commands
-void Vgm_Emu_Impl::update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const
-{
-	byte const* p = data + 0x40;
-	while ( p < data_end )
-	{
-		switch ( *p )
-		{
-		case cmd_end:
-			return;
-
-		case cmd_psg:
-		case cmd_byte_delay:
-			p += 2;
-			break;
-
-		case cmd_delay:
-			p += 3;
-			break;
-
-		case cmd_data_block:
-			p += 7 + GET_LE32( p + 3 );
-			break;
-
-		case cmd_ym2413:
-			*ym2612_rate = 0;
-			return;
-
-		case cmd_ym2612_port0:
-		case cmd_ym2612_port1:
-			*ym2612_rate = *ym2413_rate;
-			*ym2413_rate = 0;
-			return;
-
-		case cmd_ym2151:
-			*ym2413_rate = 0;
-			*ym2612_rate = 0;
-			return;
-
-		default:
-			p += command_len( *p );
-		}
-	}
-}
diff --git a/src/console/Vgm_Emu_Impl.h b/src/console/Vgm_Emu_Impl.h
index 3225ea799fca..871b9e10c290 100644
--- a/src/console/Vgm_Emu_Impl.h
+++ b/src/console/Vgm_Emu_Impl.h
@@ -17,7 +17,7 @@ protected:
 	short* out;
 	enum { disabled_time = -1 };
 public:
-	Ym_Emu()                        : last_time( disabled_time ), out( NULL ) { }
+	Ym_Emu()                        : last_time( disabled_time ), out( nullptr ) { }
 	void enable( bool b )           { last_time = b ? 0 : disabled_time; }
 	bool enabled() const            { return last_time != disabled_time; }
 	void begin_frame( short* p );
diff --git a/src/console/Ym2413_Emu.cc b/src/console/Ym2413_Emu.cc
new file mode 100644
index 000000000000..6e3fafe25d97
--- /dev/null
+++ b/src/console/Ym2413_Emu.cc
@@ -0,0 +1,2216 @@
+
+// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
+
+/***********************************************************************************
+
+  emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
+
+  2001 01-08 : Version 0.10 -- 1st version.
+  2001 01-15 : Version 0.20 -- semi-public version.
+  2001 01-16 : Version 0.30 -- 1st public version.
+  2001 01-17 : Version 0.31 -- Fixed bassdrum problem.
+             : Version 0.32 -- LPF implemented.
+  2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method.
+                            -- Fixed the LFO bug.
+  2001 01-24 : Version 0.35 -- Fixed the drum problem,
+                               support undocumented EG behavior.
+  2001 02-02 : Version 0.38 -- Improved the performance.
+                               Fixed the hi-hat and cymbal model.
+                               Fixed the default percussive datas.
+                               Noise reduction.
+                               Fixed the feedback problem.
+  2001 03-03 : Version 0.39 -- Fixed some drum bugs.
+                               Improved the performance.
+  2001 03-04 : Version 0.40 -- Improved the feedback.
+                               Change the default table size.
+                               Clock and Rate can be changed during play.
+  2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone.
+                               Added VRC7 patch (OPLL_reset_patch is changed).
+                               Fixed OPLL_reset() bug.
+                               Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask.
+                               Added OPLL_writeIO.
+  2001 09-28 : Version 0.51 -- Removed the noise table.
+  2002 01-28 : Version 0.52 -- Added Stereo mode.
+  2002 02-07 : Version 0.53 -- Fixed some drum bugs.
+  2002 02-20 : Version 0.54 -- Added the best quality mode.
+  2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close.
+  2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas.
+  2004 04-10 : Version 0.61 -- Added YMF281B tone (defined by Chabin).
+
+  References:
+    fmopl.c        -- 1999,2000 written by Tatsuyuki Satoh (MAME development).
+    fmopl.c(fixed) -- (C) 2002 Jarek Burczynski.
+    s_opl.c        -- 2001 written by Mamiya (NEZplug development).
+    fmgen.cpp      -- 1999,2000 written by cisc.
+    fmpac.ill      -- 2000 created by NARUTO.
+    MSX-Datapack
+    YMU757 data sheet
+    YM2143 data sheet
+
+**************************************************************************************/
+
+
+#ifndef _EMU2413_H_
+#define _EMU2413_H_
+
+typedef signed char     e_int8;
+typedef unsigned char   e_uint8;
+typedef signed short    e_int16;
+typedef unsigned short  e_uint16;
+typedef signed long     e_int32;
+typedef unsigned long   e_uint32;
+
+#ifdef EMU2413_DLL_EXPORTS
+  #define EMU2413_API __declspec(dllexport)
+#elif defined(EMU2413_DLL_IMPORTS)
+  #define EMU2413_API __declspec(dllimport)
+#else
+  #define EMU2413_API
+#endif
+
+#define PI 3.14159265358979323846
+
+enum OPLL_TONE_ENUM {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1, OPLL_281B_TONE=2} ;
+
+/* voice data */
+typedef struct __OPLL_PATCH {
+  e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ;
+} OPLL_PATCH ;
+
+/* slot */
+typedef struct __OPLL_SLOT {
+
+  OPLL_PATCH *patch;
+
+  e_int32 type ;          /* 0 : modulator 1 : carrier */
+
+  /* OUTPUT */
+  e_int32 feedback ;
+  e_int32 output[2] ;   /* Output value of slot */
+
+  /* for Phase Generator (PG) */
+  e_uint16 *sintbl ;    /* Wavetable */
+  e_uint32 phase ;      /* Phase */
+  e_uint32 dphase ;     /* Phase increment amount */
+  e_uint32 pgout ;      /* output */
+
+  /* for Envelope Generator (EG) */
+  e_int32 fnum ;          /* F-Number */
+  e_int32 block ;         /* Block */
+  e_int32 volume ;        /* Current volume */
+  e_int32 sustine ;       /* Sustine 1 = ON, 0 = OFF */
+  e_uint32 tll ;          /* Total Level + Key scale level*/
+  e_uint32 rks ;        /* Key scale offset (Rks) */
+  e_int32 eg_mode ;       /* Current state */
+  e_uint32 eg_phase ;   /* Phase */
+  e_uint32 eg_dphase ;  /* Phase increment amount */
+  e_uint32 egout ;      /* output */
+
+} OPLL_SLOT ;
+
+/* Mask */
+#define OPLL_MASK_CH(x) (1<<(x))
+#define OPLL_MASK_HH (1<<(9))
+#define OPLL_MASK_CYM (1<<(10))
+#define OPLL_MASK_TOM (1<<(11))
+#define OPLL_MASK_SD (1<<(12))
+#define OPLL_MASK_BD (1<<(13))
+#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
+
+/* opll */
+typedef struct OPLL {
+
+  e_uint32 adr ;
+  e_int32 out ;
+
+#ifndef EMU2413_COMPACTION
+  e_uint32 realstep ;
+  e_uint32 oplltime ;
+  e_uint32 opllstep ;
+  e_int32 prev, next ;
+  e_int32 sprev[2],snext[2];
+  e_int32 pan[16];
+#endif
+
+  /* Register */
+  e_uint8 reg[0x40] ;
+  e_int32 slot_on_flag[18] ;
+
+  /* Pitch Modulator */
+  e_uint32 pm_phase ;
+  e_int32 lfo_pm ;
+
+  /* Amp Modulator */
+  e_int32 am_phase ;
+  e_int32 lfo_am ;
+
+  e_uint32 quality;
+
+  /* Noise Generator */
+  e_uint32 noise_seed ;
+
+  /* Channel Data */
+  e_int32 patch_number[9];
+  e_int32 key_status[9] ;
+
+  /* Slot */
+  OPLL_SLOT slot[18] ;
+
+  /* Voice Data */
+  OPLL_PATCH patch[19*2] ;
+  e_int32 patch_update[2] ; /* flag for check patch update */
+
+  e_uint32 mask ;
+
+} OPLL ;
+
+/* Create Object */
+EMU2413_API OPLL *OPLL_new(e_uint32 clk, e_uint32 rate) ;
+EMU2413_API void OPLL_delete(OPLL *) ;
+
+/* Setup */
+EMU2413_API void OPLL_reset(OPLL *) ;
+EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ;
+EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ;
+EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ;
+EMU2413_API void OPLL_set_pan(OPLL *, e_uint32 ch, e_uint32 pan);
+
+/* Port/Register access */
+EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val) ;
+EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val) ;
+
+/* Synthsize */
+EMU2413_API e_int16 OPLL_calc(OPLL *) ;
+EMU2413_API void OPLL_calc_stereo(OPLL *, e_int32 out[2]) ;
+
+/* Misc */
+EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ;
+EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ;
+EMU2413_API void OPLL_forceRefresh(OPLL *) ;
+/* Utility */
+EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ;
+EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ;
+EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ;
+
+/* Channel Mask */
+EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ;
+EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
+
+#define dump2patch OPLL_dump2patch
+
+#endif
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define EMU2413_COMPACTION
+#define INLINE inline
+
+#ifdef EMU2413_COMPACTION
+#define OPLL_TONE_NUM 1
+static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
+  {
+/* YM2413 tone by okazaki at angel.ne.jp */
+0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+  }
+};
+#else
+#define OPLL_TONE_NUM 3
+static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
+  {
+#include "2413tone.h"
+  },
+  {
+#include "vrc7tone.h"
+   },
+  {
+#include "281btone.h"
+  }
+};
+#endif
+
+/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.) */
+#define PG_BITS 9
+#define PG_WIDTH (1<<PG_BITS)
+
+/* Phase increment counter */
+#define DP_BITS 18
+#define DP_WIDTH (1<<DP_BITS)
+#define DP_BASE_BITS (DP_BITS - PG_BITS)
+
+/* Dynamic range (Accuracy of sin table) */
+#define DB_BITS 8
+#define DB_STEP (48.0/(1<<DB_BITS))
+#define DB_MUTE (1<<DB_BITS)
+
+/* Dynamic range of envelope */
+#define EG_STEP 0.375
+#define EG_BITS 7
+#define EG_MUTE (1<<EG_BITS)
+
+/* Dynamic range of total level */
+#define TL_STEP 0.75
+#define TL_BITS 6
+#define TL_MUTE (1<<TL_BITS)
+
+/* Dynamic range of sustine level */
+#define SL_STEP 3.0
+#define SL_BITS 4
+#define SL_MUTE (1<<SL_BITS)
+
+#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
+#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
+#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
+
+#define DB_POS(x) (e_uint32)((x)/DB_STEP)
+#define DB_NEG(x) (e_uint32)(DB_MUTE+DB_MUTE+(x)/DB_STEP)
+
+/* Bits for liner value */
+#define DB2LIN_AMP_BITS 8
+#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
+
+/* Bits for envelope phase incremental counter */
+#define EG_DP_BITS 22
+#define EG_DP_WIDTH (1<<EG_DP_BITS)
+
+/* Bits for Pitch and Amp modulator */
+#define PM_PG_BITS 8
+#define PM_PG_WIDTH (1<<PM_PG_BITS)
+#define PM_DP_BITS 16
+#define PM_DP_WIDTH (1<<PM_DP_BITS)
+#define AM_PG_BITS 8
+#define AM_PG_WIDTH (1<<AM_PG_BITS)
+#define AM_DP_BITS 16
+#define AM_DP_WIDTH (1<<AM_DP_BITS)
+
+/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
+#define PM_AMP_BITS 8
+#define PM_AMP (1<<PM_AMP_BITS)
+
+/* PM speed(Hz) and depth(cent) */
+#define PM_SPEED 6.4
+#define PM_DEPTH 13.75
+
+/* AM speed(Hz) and depth(dB) */
+#define AM_SPEED 3.6413
+#define AM_DEPTH 4.875
+
+/* Cut the lower b bit(s) off. */
+#define HIGHBITS(c,b) ((c)>>(b))
+
+/* Leave the lower b bit(s). */
+#define LOWBITS(c,b) ((c)&((1<<(b))-1))
+
+/* Expand x which is s bits to d bits. */
+#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s)))
+
+/* Expand x which is s bits to d bits and fill expanded bits '1' */
+#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
+
+/* Adjust envelope speed which depends on sampling rate. */
+#define RATE_ADJUST(x) (rate==49716?x:(e_uint32)((double)(x)*clk/72/rate + 0.5))        /* added 0.5 to round the value*/
+
+#define MOD(o,x) (&(o)->slot[(x)<<1])
+#define CAR(o,x) (&(o)->slot[((x)<<1)|1])
+
+#define BIT(s,b) (((s)>>(b))&1)
+
+/* Input clock */
+static e_uint32 clk = 844451141;
+/* Sampling rate */
+static e_uint32 rate = 3354932;
+
+/* WaveTable for each envelope amp */
+static e_uint16 fullsintable[PG_WIDTH];
+static e_uint16 halfsintable[PG_WIDTH];
+
+static e_uint16 *waveform[2] = { fullsintable, halfsintable };
+
+/* LFO Table */
+static e_int32 pmtable[PM_PG_WIDTH];
+static e_int32 amtable[AM_PG_WIDTH];
+
+/* Phase delta for LFO */
+static e_uint32 pm_dphase;
+static e_uint32 am_dphase;
+
+/* dB to Liner table */
+static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2];
+
+/* Liner to Log curve conversion table (for Attack rate). */
+static e_uint16 AR_ADJUST_TABLE[1 << EG_BITS];
+
+/* Empty voice data */
+static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* Basic voice Data */
+static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];
+
+/* Definition of envelope mode */
+enum OPLL_EG_STATE
+{ READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH };
+
+/* Phase incr table for Attack */
+static e_uint32 dphaseARTable[16][16];
+/* Phase incr table for Decay and Release */
+static e_uint32 dphaseDRTable[16][16];
+
+/* KSL + TL Table */
+static e_uint32 tllTable[16][8][1 << TL_BITS][4];
+static e_int32 rksTable[2][8][2];
+
+/* Phase incr table for PG */
+static e_uint32 dphaseTable[512][8][16];
+
+/***************************************************
+
+                  Create tables
+
+****************************************************/
+INLINE static e_int32
+Min (e_int32 i, e_int32 j)
+{
+  if (i < j)
+    return i;
+  else
+    return j;
+}
+
+/* Table for AR to LogCurve. */
+static void
+makeAdjustTable (void)
+{
+  e_int32 i;
+
+  AR_ADJUST_TABLE[0] = (1 << EG_BITS) - 1;
+  for (i = 1; i < (1<<EG_BITS); i++)
+    AR_ADJUST_TABLE[i] = (e_uint16) ((double) (1<<EG_BITS)-1 - ((1<<EG_BITS)-1)*log(i)/log(127));
+}
+
+
+/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
+static void
+makeDB2LinTable (void)
+{
+  e_int32 i;
+
+  for (i = 0; i < DB_MUTE + DB_MUTE; i++)
+  {
+    DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
+    if (i >= DB_MUTE) DB2LIN_TABLE[i] = 0;
+    DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]);
+  }
+}
+
+/* Liner(+0.0 - +1.0) to dB((1<<DB_BITS) - 1 -- 0) */
+static e_int32
+lin2db (double d)
+{
+  if (d == 0)
+    return (DB_MUTE - 1);
+  else
+    return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1);  /* 0 -- 127 */
+}
+
+
+/* Sin Table */
+static void
+makeSinTable (void)
+{
+  e_int32 i;
+
+  for (i = 0; i < PG_WIDTH / 4; i++)
+  {
+    fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
+  }
+
+  for (i = 0; i < PG_WIDTH / 4; i++)
+  {
+    fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
+  }
+
+  for (i = 0; i < PG_WIDTH / 2; i++)
+  {
+    fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
+  }
+
+  for (i = 0; i < PG_WIDTH / 2; i++)
+    halfsintable[i] = fullsintable[i];
+  for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
+    halfsintable[i] = fullsintable[0];
+}
+
+static double saw(double phase)
+{
+  if(phase <= PI/2)
+    return phase * 2 / PI ;
+  else if(phase <= PI*3/2)
+    return 2.0 - ( phase * 2 / PI );
+  else
+    return -4.0 + phase * 2 / PI;
+}
+
+/* Table for Pitch Modulator */
+static void
+makePmTable (void)
+{
+  e_int32 i;
+
+  for (i = 0; i < PM_PG_WIDTH; i++)
+    /* pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200)); */
+    pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * saw (2.0 * PI * i / PM_PG_WIDTH) / 1200));
+}
+
+/* Table for Amp Modulator */
+static void
+makeAmTable (void)
+{
+  e_int32 i;
+
+  for (i = 0; i < AM_PG_WIDTH; i++)
+    /* amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH))); */
+    amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + saw (2.0 * PI * i / PM_PG_WIDTH)));
+}
+
+/* Phase increment counter table */
+static void
+makeDphaseTable (void)
+{
+  e_uint32 fnum, block, ML;
+  e_uint32 mltable[16] =
+    { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
+
+  for (fnum = 0; fnum < 512; fnum++)
+    for (block = 0; block < 8; block++)
+      for (ML = 0; ML < 16; ML++)
+        dphaseTable[fnum][block][ML] = RATE_ADJUST (((fnum * mltable[ML]) << block) >> (20 - DP_BITS));
+}
+
+static void
+makeTllTable (void)
+{
+#define dB2(x) ((x)*2)
+
+  static double kltable[16] = {
+    dB2 (0.000), dB2 (9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
+    dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
+  };
+
+  e_int32 tmp;
+  e_int32 fnum, block, TL, KL;
+
+  for (fnum = 0; fnum < 16; fnum++)
+    for (block = 0; block < 8; block++)
+      for (TL = 0; TL < 64; TL++)
+        for (KL = 0; KL < 4; KL++)
+        {
+          if (KL == 0)
+          {
+            tllTable[fnum][block][TL][KL] = TL2EG (TL);
+          }
+          else
+          {
+            tmp = (e_int32) (kltable[fnum] - dB2 (3.000) * (7 - block));
+            if (tmp <= 0)
+              tllTable[fnum][block][TL][KL] = TL2EG (TL);
+            else
+              tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL);
+          }
+        }
+}
+
+#ifdef USE_SPEC_ENV_SPEED
+static double attacktime[16][4] = {
+  {0, 0, 0, 0},
+  {1730.15, 1400.60, 1153.43, 988.66},
+  {865.08, 700.30, 576.72, 494.33},
+  {432.54, 350.15, 288.36, 247.16},
+  {216.27, 175.07, 144.18, 123.58},
+  {108.13, 87.54, 72.09, 61.79},
+  {54.07, 43.77, 36.04, 30.90},
+  {27.03, 21.88, 18.02, 15.45},
+  {13.52, 10.94, 9.01, 7.72},
+  {6.76, 5.47, 4.51, 3.86},
+  {3.38, 2.74, 2.25, 1.93},
+  {1.69, 1.37, 1.13, 0.97},
+  {0.84, 0.70, 0.60, 0.54},
+  {0.50, 0.42, 0.34, 0.30},
+  {0.28, 0.22, 0.18, 0.14},
+  {0.00, 0.00, 0.00, 0.00}
+};
+
+static double decaytime[16][4] = {
+  {0, 0, 0, 0},
+  {20926.60, 16807.20, 14006.00, 12028.60},
+  {10463.30, 8403.58, 7002.98, 6014.32},
+  {5231.64, 4201.79, 3501.49, 3007.16},
+  {2615.82, 2100.89, 1750.75, 1503.58},
+  {1307.91, 1050.45, 875.37, 751.79},
+  {653.95, 525.22, 437.69, 375.90},
+  {326.98, 262.61, 218.84, 187.95},
+  {163.49, 131.31, 109.42, 93.97},
+  {81.74, 65.65, 54.71, 46.99},
+  {40.87, 32.83, 27.36, 23.49},
+  {20.44, 16.41, 13.68, 11.75},
+  {10.22, 8.21, 6.84, 5.87},
+  {5.11, 4.10, 3.42, 2.94},
+  {2.55, 2.05, 1.71, 1.47},
+  {1.27, 1.27, 1.27, 1.27}
+};
+#endif
+
+/* Rate Table for Attack */
+static void
+makeDphaseARTable (void)
+{
+  e_int32 AR, Rks, RM, RL;
+
+#ifdef USE_SPEC_ENV_SPEED
+  e_uint32 attacktable[16][4];
+
+  for (RM = 0; RM < 16; RM++)
+    for (RL = 0; RL < 4; RL++)
+    {
+      if (RM == 0)
+        attacktable[RM][RL] = 0;
+      else if (RM == 15)
+        attacktable[RM][RL] = EG_DP_WIDTH;
+      else
+        attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
+
+    }
+#endif
+
+  for (AR = 0; AR < 16; AR++)
+    for (Rks = 0; Rks < 16; Rks++)
+    {
+      RM = AR + (Rks >> 2);
+      RL = Rks & 3;
+      if (RM > 15)
+        RM = 15;
+      switch (AR)
+      {
+      case 0:
+        dphaseARTable[AR][Rks] = 0;
+        break;
+      case 15:
+        dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/
+        break;
+      default:
+#ifdef USE_SPEC_ENV_SPEED
+        dphaseARTable[AR][Rks] = RATE_ADJUST (attacktable[RM][RL]);
+#else
+        dphaseARTable[AR][Rks] = RATE_ADJUST ((3 * (RL + 4) << (RM + 1)));
+#endif
+        break;
+      }
+    }
+}
+
+/* Rate Table for Decay and Release */
+static void
+makeDphaseDRTable (void)
+{
+  e_int32 DR, Rks, RM, RL;
+
+#ifdef USE_SPEC_ENV_SPEED
+  e_uint32 decaytable[16][4];
+
+  for (RM = 0; RM < 16; RM++)
+    for (RL = 0; RL < 4; RL++)
+      if (RM == 0)
+        decaytable[RM][RL] = 0;
+      else
+        decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000));
+#endif
+
+  for (DR = 0; DR < 16; DR++)
+    for (Rks = 0; Rks < 16; Rks++)
+    {
+      RM = DR + (Rks >> 2);
+      RL = Rks & 3;
+      if (RM > 15)
+        RM = 15;
+      switch (DR)
+      {
+      case 0:
+        dphaseDRTable[DR][Rks] = 0;
+        break;
+      default:
+#ifdef USE_SPEC_ENV_SPEED
+        dphaseDRTable[DR][Rks] = RATE_ADJUST (decaytable[RM][RL]);
+#else
+        dphaseDRTable[DR][Rks] = RATE_ADJUST ((RL + 4) << (RM - 1));
+#endif
+        break;
+      }
+    }
+}
+
+static void
+makeRksTable (void)
+{
+
+  e_int32 fnum8, block, KR;
+
+  for (fnum8 = 0; fnum8 < 2; fnum8++)
+    for (block = 0; block < 8; block++)
+      for (KR = 0; KR < 2; KR++)
+      {
+        if (KR != 0)
+          rksTable[fnum8][block][KR] = (block << 1) + fnum8;
+        else
+          rksTable[fnum8][block][KR] = block >> 1;
+      }
+}
+
+void
+OPLL_dump2patch (const e_uint8 * dump, OPLL_PATCH * patch)
+{
+  patch[0].AM = (dump[0] >> 7) & 1;
+  patch[1].AM = (dump[1] >> 7) & 1;
+  patch[0].PM = (dump[0] >> 6) & 1;
+  patch[1].PM = (dump[1] >> 6) & 1;
+  patch[0].EG = (dump[0] >> 5) & 1;
+  patch[1].EG = (dump[1] >> 5) & 1;
+  patch[0].KR = (dump[0] >> 4) & 1;
+  patch[1].KR = (dump[1] >> 4) & 1;
+  patch[0].ML = (dump[0]) & 15;
+  patch[1].ML = (dump[1]) & 15;
+  patch[0].KL = (dump[2] >> 6) & 3;
+  patch[1].KL = (dump[3] >> 6) & 3;
+  patch[0].TL = (dump[2]) & 63;
+  patch[0].FB = (dump[3]) & 7;
+  patch[0].WF = (dump[3] >> 3) & 1;
+  patch[1].WF = (dump[3] >> 4) & 1;
+  patch[0].AR = (dump[4] >> 4) & 15;
+  patch[1].AR = (dump[5] >> 4) & 15;
+  patch[0].DR = (dump[4]) & 15;
+  patch[1].DR = (dump[5]) & 15;
+  patch[0].SL = (dump[6] >> 4) & 15;
+  patch[1].SL = (dump[7] >> 4) & 15;
+  patch[0].RR = (dump[6]) & 15;
+  patch[1].RR = (dump[7]) & 15;
+}
+
+void
+OPLL_getDefaultPatch (e_int32 type, e_int32 num, OPLL_PATCH * patch)
+{
+  OPLL_dump2patch (default_inst[type] + num * 16, patch);
+}
+
+static void
+makeDefaultPatch ()
+{
+  e_int32 i, j;
+
+  for (i = 0; i < OPLL_TONE_NUM; i++)
+    for (j = 0; j < 19; j++)
+      OPLL_getDefaultPatch (i, j, &default_patch[i][j * 2]);
+
+}
+
+void
+OPLL_setPatch (OPLL * opll, const e_uint8 * dump)
+{
+  OPLL_PATCH patch[2];
+  int i;
+
+  for (i = 0; i < 19; i++)
+  {
+    OPLL_dump2patch (dump + i * 16, patch);
+    memcpy (&opll->patch[i*2+0], &patch[0], sizeof (OPLL_PATCH));
+    memcpy (&opll->patch[i*2+1], &patch[1], sizeof (OPLL_PATCH));
+  }
+}
+
+void
+OPLL_patch2dump (const OPLL_PATCH * patch, e_uint8 * dump)
+{
+  dump[0] = (e_uint8) ((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);
+  dump[1] = (e_uint8) ((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);
+  dump[2] = (e_uint8) ((patch[0].KL << 6) + patch[0].TL);
+  dump[3] = (e_uint8) ((patch[1].KL << 6) + (patch[1].WF << 4) + (patch[0].WF << 3) + patch[0].FB);
+  dump[4] = (e_uint8) ((patch[0].AR << 4) + patch[0].DR);
+  dump[5] = (e_uint8) ((patch[1].AR << 4) + patch[1].DR);
+  dump[6] = (e_uint8) ((patch[0].SL << 4) + patch[0].RR);
+  dump[7] = (e_uint8) ((patch[1].SL << 4) + patch[1].RR);
+  dump[8] = 0;
+  dump[9] = 0;
+  dump[10] = 0;
+  dump[11] = 0;
+  dump[12] = 0;
+  dump[13] = 0;
+  dump[14] = 0;
+  dump[15] = 0;
+}
+
+/************************************************************
+
+                      Calc Parameters
+
+************************************************************/
+
+INLINE static e_uint32
+calc_eg_dphase (OPLL_SLOT * slot)
+{
+
+  switch (slot->eg_mode)
+  {
+  case ATTACK:
+    return dphaseARTable[slot->patch->AR][slot->rks];
+
+  case DECAY:
+    return dphaseDRTable[slot->patch->DR][slot->rks];
+
+  case SUSHOLD:
+    return 0;
+
+  case SUSTINE:
+    return dphaseDRTable[slot->patch->RR][slot->rks];
+
+  case RELEASE:
+    if (slot->sustine)
+      return dphaseDRTable[5][slot->rks];
+    else if (slot->patch->EG)
+      return dphaseDRTable[slot->patch->RR][slot->rks];
+    else
+      return dphaseDRTable[7][slot->rks];
+
+  case SETTLE:
+    return dphaseDRTable[15][0];
+
+  case FINISH:
+    return 0;
+
+  default:
+    return 0;
+  }
+}
+
+/*************************************************************
+
+                    OPLL internal interfaces
+
+*************************************************************/
+#define SLOT_BD1 12
+#define SLOT_BD2 13
+#define SLOT_HH 14
+#define SLOT_SD 15
+#define SLOT_TOM 16
+#define SLOT_CYM 17
+
+#define UPDATE_PG(S)  (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch->ML]
+#define UPDATE_TLL(S)\
+(((S)->type==0)?\
+((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch->TL][(S)->patch->KL]):\
+((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch->KL]))
+#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch->KR]
+#define UPDATE_WF(S)  (S)->sintbl = waveform[(S)->patch->WF]
+#define UPDATE_EG(S)  (S)->eg_dphase = calc_eg_dphase(S)
+#define UPDATE_ALL(S)\
+  UPDATE_PG(S);\
+  UPDATE_TLL(S);\
+  UPDATE_RKS(S);\
+  UPDATE_WF(S); \
+  UPDATE_EG(S)                  /* EG should be updated last. */
+
+
+/* Slot key on  */
+INLINE static void
+slotOn (OPLL_SLOT * slot)
+{
+  slot->eg_mode = ATTACK;
+  slot->eg_phase = 0;
+  slot->phase = 0;
+  UPDATE_EG(slot);
+}
+
+/* Slot key on without reseting the phase */
+INLINE static void
+slotOn2 (OPLL_SLOT * slot)
+{
+  slot->eg_mode = ATTACK;
+  slot->eg_phase = 0;
+  UPDATE_EG(slot);
+}
+
+/* Slot key off */
+INLINE static void
+slotOff (OPLL_SLOT * slot)
+{
+  if (slot->eg_mode == ATTACK)
+    slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)], EG_BITS, EG_DP_BITS);
+  slot->eg_mode = RELEASE;
+  UPDATE_EG(slot);
+}
+
+/* Channel key on */
+INLINE static void
+keyOn (OPLL * opll, e_int32 i)
+{
+  if (!opll->slot_on_flag[i * 2])
+    slotOn (MOD(opll,i));
+  if (!opll->slot_on_flag[i * 2 + 1])
+    slotOn (CAR(opll,i));
+  opll->key_status[i] = 1;
+}
+
+/* Channel key off */
+INLINE static void
+keyOff (OPLL * opll, e_int32 i)
+{
+  if (opll->slot_on_flag[i * 2 + 1])
+    slotOff (CAR(opll,i));
+  opll->key_status[i] = 0;
+}
+
+INLINE static void
+keyOn_BD (OPLL * opll)
+{
+  keyOn (opll, 6);
+}
+INLINE static void
+keyOn_SD (OPLL * opll)
+{
+  if (!opll->slot_on_flag[SLOT_SD])
+    slotOn (CAR(opll,7));
+}
+INLINE static void
+keyOn_TOM (OPLL * opll)
+{
+  if (!opll->slot_on_flag[SLOT_TOM])
+    slotOn (MOD(opll,8));
+}
+INLINE static void
+keyOn_HH (OPLL * opll)
+{
+  if (!opll->slot_on_flag[SLOT_HH])
+    slotOn2 (MOD(opll,7));
+}
+INLINE static void
+keyOn_CYM (OPLL * opll)
+{
+  if (!opll->slot_on_flag[SLOT_CYM])
+    slotOn2 (CAR(opll,8));
+}
+
+/* Drum key off */
+INLINE static void
+keyOff_BD (OPLL * opll)
+{
+  keyOff (opll, 6);
+}
+INLINE static void
+keyOff_SD (OPLL * opll)
+{
+  if (opll->slot_on_flag[SLOT_SD])
+    slotOff (CAR(opll,7));
+}
+INLINE static void
+keyOff_TOM (OPLL * opll)
+{
+  if (opll->slot_on_flag[SLOT_TOM])
+    slotOff (MOD(opll,8));
+}
+INLINE static void
+keyOff_HH (OPLL * opll)
+{
+  if (opll->slot_on_flag[SLOT_HH])
+    slotOff (MOD(opll,7));
+}
+INLINE static void
+keyOff_CYM (OPLL * opll)
+{
+  if (opll->slot_on_flag[SLOT_CYM])
+    slotOff (CAR(opll,8));
+}
+
+/* Change a voice */
+INLINE static void
+setPatch (OPLL * opll, e_int32 i, e_int32 num)
+{
+  opll->patch_number[i] = num;
+  MOD(opll,i)->patch = &opll->patch[num * 2 + 0];
+  CAR(opll,i)->patch = &opll->patch[num * 2 + 1];
+}
+
+/* Change a rhythm voice */
+INLINE static void
+setSlotPatch (OPLL_SLOT * slot, OPLL_PATCH * patch)
+{
+  slot->patch = patch;
+}
+
+/* Set sustine parameter */
+INLINE static void
+setSustine (OPLL * opll, e_int32 c, e_int32 sustine)
+{
+  CAR(opll,c)->sustine = sustine;
+  if (MOD(opll,c)->type)
+    MOD(opll,c)->sustine = sustine;
+}
+
+/* Volume : 6bit ( Volume register << 2 ) */
+INLINE static void
+setVolume (OPLL * opll, e_int32 c, e_int32 volume)
+{
+  CAR(opll,c)->volume = volume;
+}
+
+INLINE static void
+setSlotVolume (OPLL_SLOT * slot, e_int32 volume)
+{
+  slot->volume = volume;
+}
+
+/* Set F-Number ( fnum : 9bit ) */
+INLINE static void
+setFnumber (OPLL * opll, e_int32 c, e_int32 fnum)
+{
+  CAR(opll,c)->fnum = fnum;
+  MOD(opll,c)->fnum = fnum;
+}
+
+/* Set Block data (block : 3bit ) */
+INLINE static void
+setBlock (OPLL * opll, e_int32 c, e_int32 block)
+{
+  CAR(opll,c)->block = block;
+  MOD(opll,c)->block = block;
+}
+
+/* Change Rhythm Mode */
+INLINE static void
+update_rhythm_mode (OPLL * opll)
+{
+  if (opll->patch_number[6] & 0x10)
+  {
+    if (!(opll->slot_on_flag[SLOT_BD2] | (opll->reg[0x0e] & 32)))
+    {
+      opll->slot[SLOT_BD1].eg_mode = FINISH;
+      opll->slot[SLOT_BD2].eg_mode = FINISH;
+      setPatch (opll, 6, opll->reg[0x36] >> 4);
+    }
+  }
+  else if (opll->reg[0x0e] & 32)
+  {
+    opll->patch_number[6] = 16;
+    opll->slot[SLOT_BD1].eg_mode = FINISH;
+    opll->slot[SLOT_BD2].eg_mode = FINISH;
+    setSlotPatch (&opll->slot[SLOT_BD1], &opll->patch[16 * 2 + 0]);
+    setSlotPatch (&opll->slot[SLOT_BD2], &opll->patch[16 * 2 + 1]);
+  }
+
+  if (opll->patch_number[7] & 0x10)
+  {
+    if (!((opll->slot_on_flag[SLOT_HH] && opll->slot_on_flag[SLOT_SD]) | (opll->reg[0x0e] & 32)))
+    {
+      opll->slot[SLOT_HH].type = 0;
+      opll->slot[SLOT_HH].eg_mode = FINISH;
+      opll->slot[SLOT_SD].eg_mode = FINISH;
+      setPatch (opll, 7, opll->reg[0x37] >> 4);
+    }
+  }
+  else if (opll->reg[0x0e] & 32)
+  {
+    opll->patch_number[7] = 17;
+    opll->slot[SLOT_HH].type = 1;
+    opll->slot[SLOT_HH].eg_mode = FINISH;
+    opll->slot[SLOT_SD].eg_mode = FINISH;
+    setSlotPatch (&opll->slot[SLOT_HH], &opll->patch[17 * 2 + 0]);
+    setSlotPatch (&opll->slot[SLOT_SD], &opll->patch[17 * 2 + 1]);
+  }
+
+  if (opll->patch_number[8] & 0x10)
+  {
+    if (!((opll->slot_on_flag[SLOT_CYM] && opll->slot_on_flag[SLOT_TOM]) | (opll->reg[0x0e] & 32)))
+    {
+      opll->slot[SLOT_TOM].type = 0;
+      opll->slot[SLOT_TOM].eg_mode = FINISH;
+      opll->slot[SLOT_CYM].eg_mode = FINISH;
+      setPatch (opll, 8, opll->reg[0x38] >> 4);
+    }
+  }
+  else if (opll->reg[0x0e] & 32)
+  {
+    opll->patch_number[8] = 18;
+    opll->slot[SLOT_TOM].type = 1;
+    opll->slot[SLOT_TOM].eg_mode = FINISH;
+    opll->slot[SLOT_CYM].eg_mode = FINISH;
+    setSlotPatch (&opll->slot[SLOT_TOM], &opll->patch[18 * 2 + 0]);
+    setSlotPatch (&opll->slot[SLOT_CYM], &opll->patch[18 * 2 + 1]);
+  }
+}
+
+INLINE static void
+update_key_status (OPLL * opll)
+{
+  int ch;
+
+  for (ch = 0; ch < 9; ch++)
+    opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->reg[0x20 + ch]) & 0x10;
+
+  if (opll->reg[0x0e] & 32)
+  {
+    opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e] & 0x10);
+    opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e] & 0x10);
+    opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e] & 0x08);
+    opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e] & 0x01);
+    opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e] & 0x04);
+    opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e] & 0x02);
+  }
+}
+
+void
+OPLL_copyPatch (OPLL * opll, e_int32 num, OPLL_PATCH * patch)
+{
+  memcpy (&opll->patch[num], patch, sizeof (OPLL_PATCH));
+}
+
+/***********************************************************
+
+                      Initializing
+
+***********************************************************/
+
+static void
+OPLL_SLOT_reset (OPLL_SLOT * slot, int type)
+{
+  slot->type = type;
+  slot->sintbl = waveform[0];
+  slot->phase = 0;
+  slot->dphase = 0;
+  slot->output[0] = 0;
+  slot->output[1] = 0;
+  slot->feedback = 0;
+  slot->eg_mode = FINISH;
+  slot->eg_phase = EG_DP_WIDTH;
+  slot->eg_dphase = 0;
+  slot->rks = 0;
+  slot->tll = 0;
+  slot->sustine = 0;
+  slot->fnum = 0;
+  slot->block = 0;
+  slot->volume = 0;
+  slot->pgout = 0;
+  slot->egout = 0;
+  slot->patch = &null_patch;
+}
+
+static void
+internal_refresh (void)
+{
+  makeDphaseTable ();
+  makeDphaseARTable ();
+  makeDphaseDRTable ();
+  pm_dphase = (e_uint32) RATE_ADJUST (PM_SPEED * PM_DP_WIDTH / (clk / 72));
+  am_dphase = (e_uint32) RATE_ADJUST (AM_SPEED * AM_DP_WIDTH / (clk / 72));
+}
+
+static void
+maketables (e_uint32 c, e_uint32 r)
+{
+  if (c != clk)
+  {
+    clk = c;
+    makePmTable ();
+    makeAmTable ();
+    makeDB2LinTable ();
+    makeAdjustTable ();
+    makeTllTable ();
+    makeRksTable ();
+    makeSinTable ();
+    makeDefaultPatch ();
+  }
+
+  if (r != rate)
+  {
+    rate = r;
+    internal_refresh ();
+  }
+}
+
+OPLL *
+OPLL_new (e_uint32 clk, e_uint32 rate)
+{
+  OPLL *opll;
+  e_int32 i;
+
+  maketables (clk, rate);
+
+  opll = (OPLL *) calloc (sizeof (OPLL), 1);
+  if (opll == nullptr)
+    return nullptr;
+
+  for (i = 0; i < 19 * 2; i++)
+    memcpy(&opll->patch[i],&null_patch,sizeof(OPLL_PATCH));
+
+  opll->mask = 0;
+
+  OPLL_reset (opll);
+  OPLL_reset_patch (opll, 0);
+
+  return opll;
+}
+
+
+void
+OPLL_delete (OPLL * opll)
+{
+  free (opll);
+}
+
+
+/* Reset patch datas by system default. */
+void
+OPLL_reset_patch (OPLL * opll, e_int32 type)
+{
+  e_int32 i;
+
+  for (i = 0; i < 19 * 2; i++)
+    OPLL_copyPatch (opll, i, &default_patch[type % OPLL_TONE_NUM][i]);
+}
+
+/* Reset whole of OPLL except patch datas. */
+void
+OPLL_reset (OPLL * opll)
+{
+  e_int32 i;
+
+  if (!opll)
+    return;
+
+  opll->adr = 0;
+  opll->out = 0;
+
+  opll->pm_phase = 0;
+  opll->am_phase = 0;
+
+  opll->noise_seed = 0xffff;
+  opll->mask = 0;
+
+  for (i = 0; i <18; i++)
+    OPLL_SLOT_reset(&opll->slot[i], i%2);
+
+  for (i = 0; i < 9; i++)
+  {
+    opll->key_status[i] = 0;
+    setPatch (opll, i, 0);
+  }
+
+  for (i = 0; i < 0x40; i++)
+    OPLL_writeReg (opll, i, 0);
+
+#ifndef EMU2413_COMPACTION
+  opll->realstep = (e_uint32) ((1 << 31) / rate);
+  opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72));
+  opll->oplltime = 0;
+  for (i = 0; i < 14; i++)
+    opll->pan[i] = 127; /* Maxim: pan is 0..255 */
+  opll->sprev[0] = opll->sprev[1] = 0;
+  opll->snext[0] = opll->snext[1] = 0;
+#endif
+}
+
+/* Force Refresh (When external program changes some parameters). */
+void
+OPLL_forceRefresh (OPLL * opll)
+{
+  e_int32 i;
+
+  if (opll == nullptr)
+    return;
+
+  for (i = 0; i < 9; i++)
+    setPatch(opll,i,opll->patch_number[i]);
+
+  for (i = 0; i < 18; i++)
+  {
+    UPDATE_PG (&opll->slot[i]);
+    UPDATE_RKS (&opll->slot[i]);
+    UPDATE_TLL (&opll->slot[i]);
+    UPDATE_WF (&opll->slot[i]);
+    UPDATE_EG (&opll->slot[i]);
+  }
+}
+
+void
+OPLL_set_rate (OPLL * opll, e_uint32 r)
+{
+  if (opll->quality)
+    rate = 49716;
+  else
+    rate = r;
+  internal_refresh ();
+  rate = r;
+}
+
+void
+OPLL_set_quality (OPLL * opll, e_uint32 q)
+{
+  opll->quality = q;
+  OPLL_set_rate (opll, rate);
+}
+
+/*********************************************************
+
+                 Generate wave data
+
+*********************************************************/
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
+#if ( SLOT_AMP_BITS - PG_BITS ) > 0
+#define wave2_2pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
+#else
+#define wave2_2pi(e)  ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
+#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
+#define wave2_4pi(e)  (e)
+#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
+#define wave2_4pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
+#else
+#define wave2_4pi(e)  ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
+#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
+#define wave2_8pi(e)  (e)
+#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
+#define wave2_8pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
+#else
+#define wave2_8pi(e)  ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Update AM, PM unit */
+static void
+update_ampm (OPLL * opll)
+{
+  opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1);
+  opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1);
+  opll->lfo_am = amtable[HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS)];
+  opll->lfo_pm = pmtable[HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS)];
+}
+
+/* PG */
+INLINE static void
+calc_phase (OPLL_SLOT * slot, e_int32 lfo)
+{
+  if (slot->patch->PM)
+    slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS;
+  else
+    slot->phase += slot->dphase;
+
+  slot->phase &= (DP_WIDTH - 1);
+
+  slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS);
+}
+
+/* Update Noise unit */
+static void
+update_noise (OPLL * opll)
+{
+   if(opll->noise_seed&1) opll->noise_seed ^= 0x8003020;
+   opll->noise_seed >>= 1;
+}
+
+/* EG */
+static void
+calc_envelope (OPLL_SLOT * slot, e_int32 lfo)
+{
+#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
+
+  static e_uint32 SL[16] = {
+    S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
+    S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
+  };
+
+  e_uint32 egout;
+
+  switch (slot->eg_mode)
+  {
+  case ATTACK:
+    egout = AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)];
+    slot->eg_phase += slot->eg_dphase;
+    if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch->AR==15))
+    {
+      egout = 0;
+      slot->eg_phase = 0;
+      slot->eg_mode = DECAY;
+      UPDATE_EG (slot);
+    }
+    break;
+
+  case DECAY:
+    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+    slot->eg_phase += slot->eg_dphase;
+    if (slot->eg_phase >= SL[slot->patch->SL])
+    {
+      if (slot->patch->EG)
+      {
+        slot->eg_phase = SL[slot->patch->SL];
+        slot->eg_mode = SUSHOLD;
+        UPDATE_EG (slot);
+      }
+      else
+      {
+        slot->eg_phase = SL[slot->patch->SL];
+        slot->eg_mode = SUSTINE;
+        UPDATE_EG (slot);
+      }
+    }
+    break;
+
+  case SUSHOLD:
+    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+    if (slot->patch->EG == 0)
+    {
+      slot->eg_mode = SUSTINE;
+      UPDATE_EG (slot);
+    }
+    break;
+
+  case SUSTINE:
+  case RELEASE:
+    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+    slot->eg_phase += slot->eg_dphase;
+    if (egout >= (1 << EG_BITS))
+    {
+      slot->eg_mode = FINISH;
+      egout = (1 << EG_BITS) - 1;
+    }
+    break;
+
+  case SETTLE:
+    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+    slot->eg_phase += slot->eg_dphase;
+    if (egout >= (1 << EG_BITS))
+    {
+      slot->eg_mode = ATTACK;
+      egout = (1 << EG_BITS) - 1;
+      UPDATE_EG(slot);
+    }
+    break;
+
+  case FINISH:
+    egout = (1 << EG_BITS) - 1;
+    break;
+
+  default:
+    egout = (1 << EG_BITS) - 1;
+    break;
+  }
+
+  if (slot->patch->AM)
+    egout = EG2DB (egout + slot->tll) + lfo;
+  else
+    egout = EG2DB (egout + slot->tll);
+
+  if (egout >= DB_MUTE)
+    egout = DB_MUTE - 1;
+
+  slot->egout = egout | 3;
+}
+
+/* CARRIOR */
+INLINE static e_int32
+calc_slot_car (OPLL_SLOT * slot, e_int32 fm)
+{
+  if (slot->egout >= (DB_MUTE - 1))
+  {
+    slot->output[0] = 0;
+  }
+  else
+  {
+    slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
+  }
+
+  slot->output[1] = (slot->output[1] + slot->output[0]) >> 1;
+  return slot->output[1];
+}
+
+/* MODULATOR */
+INLINE static e_int32
+calc_slot_mod (OPLL_SLOT * slot)
+{
+  e_int32 fm;
+
+  slot->output[1] = slot->output[0];
+
+  if (slot->egout >= (DB_MUTE - 1))
+  {
+    slot->output[0] = 0;
+  }
+  else if (slot->patch->FB != 0)
+  {
+    fm = wave2_4pi (slot->feedback) >> (7 - slot->patch->FB);
+    slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
+  }
+  else
+  {
+    slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
+  }
+
+  slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
+
+  return slot->feedback;
+
+}
+
+/* TOM */
+INLINE static e_int32
+calc_slot_tom (OPLL_SLOT * slot)
+{
+  if (slot->egout >= (DB_MUTE - 1))
+    return 0;
+
+  return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
+
+}
+
+/* SNARE */
+INLINE static e_int32
+calc_slot_snare (OPLL_SLOT * slot, e_uint32 noise)
+{
+  if(slot->egout>=(DB_MUTE-1))
+    return 0;
+
+  if(BIT(slot->pgout,7))
+    return DB2LIN_TABLE[(noise?DB_POS(0.0):DB_POS(15.0))+slot->egout];
+  else
+    return DB2LIN_TABLE[(noise?DB_NEG(0.0):DB_NEG(15.0))+slot->egout];
+}
+
+/*
+  TOP-CYM
+ */
+INLINE static e_int32
+calc_slot_cym (OPLL_SLOT * slot, e_uint32 pgout_hh)
+{
+  e_uint32 dbout;
+
+  if (slot->egout >= (DB_MUTE - 1))
+    return 0;
+  else if(
+      /* the same as fmopl.c */
+      ((BIT(pgout_hh,PG_BITS-8)^BIT(pgout_hh,PG_BITS-1))|BIT(pgout_hh,PG_BITS-7)) ^
+      /* different from fmopl.c */
+     (BIT(slot->pgout,PG_BITS-7)&!BIT(slot->pgout,PG_BITS-5))
+    )
+    dbout = DB_NEG(3.0);
+  else
+    dbout = DB_POS(3.0);
+
+  return DB2LIN_TABLE[dbout + slot->egout];
+}
+
+/*
+  HI-HAT
+*/
+INLINE static e_int32
+calc_slot_hat (OPLL_SLOT *slot, e_int32 pgout_cym, e_uint32 noise)
+{
+  e_uint32 dbout;
+
+  if (slot->egout >= (DB_MUTE - 1))
+    return 0;
+  else if(
+      /* the same as fmopl.c */
+      ((BIT(slot->pgout,PG_BITS-8)^BIT(slot->pgout,PG_BITS-1))|BIT(slot->pgout,PG_BITS-7)) ^
+      /* different from fmopl.c */
+      (BIT(pgout_cym,PG_BITS-7)&!BIT(pgout_cym,PG_BITS-5))
+    )
+  {
+    if(noise)
+      dbout = DB_NEG(12.0);
+    else
+      dbout = DB_NEG(24.0);
+  }
+  else
+  {
+    if(noise)
+      dbout = DB_POS(12.0);
+    else
+      dbout = DB_POS(24.0);
+  }
+
+  return DB2LIN_TABLE[dbout + slot->egout];
+}
+
+INLINE static e_int16
+calc (OPLL * opll)
+{
+  e_int32 inst = 0, perc = 0, out = 0;
+  e_int32 i;
+
+  update_ampm (opll);
+  update_noise (opll);
+
+  for (i = 0; i < 18; i++)
+  {
+    calc_phase(&opll->slot[i],opll->lfo_pm);
+    calc_envelope(&opll->slot[i],opll->lfo_am);
+  }
+
+  for (i = 0; i < 6; i++)
+    if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
+      inst += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i)));
+
+  /* CH6 */
+  if (opll->patch_number[6] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
+      inst += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
+      perc += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
+  }
+
+  /* CH7 */
+  if (opll->patch_number[7] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR(opll,7)->eg_mode != FINISH))
+      inst += calc_slot_car (CAR(opll,7), calc_slot_mod(MOD(opll,7)));
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_HH) && (MOD(opll,7)->eg_mode != FINISH))
+      perc += calc_slot_hat (MOD(opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
+    if (!(opll->mask & OPLL_MASK_SD) && (CAR(opll,7)->eg_mode != FINISH))
+      perc -= calc_slot_snare (CAR(opll,7), opll->noise_seed&1);
+  }
+
+  /* CH8 */
+  if (opll->patch_number[8] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH(8)) && (CAR(opll,8)->eg_mode != FINISH))
+      inst += calc_slot_car (CAR(opll,8), calc_slot_mod (MOD(opll,8)));
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_TOM) && (MOD(opll,8)->eg_mode != FINISH))
+      perc += calc_slot_tom (MOD(opll,8));
+    if (!(opll->mask & OPLL_MASK_CYM) && (CAR(opll,8)->eg_mode != FINISH))
+      perc -= calc_slot_cym (CAR(opll,8), MOD(opll,7)->pgout);
+  }
+
+  out = inst + (perc << 1);
+  return (e_int16) out << 3;
+}
+
+#ifdef EMU2413_COMPACTION
+e_int16
+OPLL_calc (OPLL * opll)
+{
+  return calc (opll);
+}
+#else
+e_int16
+OPLL_calc (OPLL * opll)
+{
+  if (!opll->quality)
+    return calc (opll);
+
+  while (opll->realstep > opll->oplltime)
+  {
+    opll->oplltime += opll->opllstep;
+    opll->prev = opll->next;
+    opll->next = calc (opll);
+  }
+
+  opll->oplltime -= opll->realstep;
+  opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime)
+                          + (double) opll->prev * opll->oplltime) / opll->opllstep);
+
+  return (e_int16) opll->out;
+}
+#endif
+
+e_uint32
+OPLL_setMask (OPLL * opll, e_uint32 mask)
+{
+  e_uint32 ret;
+
+  if (opll)
+  {
+    ret = opll->mask;
+    opll->mask = mask;
+    return ret;
+  }
+  else
+    return 0;
+}
+
+e_uint32
+OPLL_toggleMask (OPLL * opll, e_uint32 mask)
+{
+  e_uint32 ret;
+
+  if (opll)
+  {
+    ret = opll->mask;
+    opll->mask ^= mask;
+    return ret;
+  }
+  else
+    return 0;
+}
+
+/****************************************************
+
+                       I/O Ctrl
+
+*****************************************************/
+
+void
+OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
+{
+  e_int32 i, v, ch;
+
+  data = data & 0xff;
+  reg = reg & 0x3f;
+  opll->reg[reg] = (e_uint8) data;
+
+  switch (reg)
+  {
+  case 0x00:
+    opll->patch[0].AM = (data >> 7) & 1;
+    opll->patch[0].PM = (data >> 6) & 1;
+    opll->patch[0].EG = (data >> 5) & 1;
+    opll->patch[0].KR = (data >> 4) & 1;
+    opll->patch[0].ML = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_PG (MOD(opll,i));
+        UPDATE_RKS (MOD(opll,i));
+        UPDATE_EG (MOD(opll,i));
+      }
+    }
+    break;
+
+  case 0x01:
+    opll->patch[1].AM = (data >> 7) & 1;
+    opll->patch[1].PM = (data >> 6) & 1;
+    opll->patch[1].EG = (data >> 5) & 1;
+    opll->patch[1].KR = (data >> 4) & 1;
+    opll->patch[1].ML = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_PG (CAR(opll,i));
+        UPDATE_RKS (CAR(opll,i));
+        UPDATE_EG (CAR(opll,i));
+      }
+    }
+    break;
+
+  case 0x02:
+    opll->patch[0].KL = (data >> 6) & 3;
+    opll->patch[0].TL = (data) & 63;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_TLL(MOD(opll,i));
+      }
+    }
+    break;
+
+  case 0x03:
+    opll->patch[1].KL = (data >> 6) & 3;
+    opll->patch[1].WF = (data >> 4) & 1;
+    opll->patch[0].WF = (data >> 3) & 1;
+    opll->patch[0].FB = (data) & 7;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_WF(MOD(opll,i));
+        UPDATE_WF(CAR(opll,i));
+      }
+    }
+    break;
+
+  case 0x04:
+    opll->patch[0].AR = (data >> 4) & 15;
+    opll->patch[0].DR = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_EG (MOD(opll,i));
+      }
+    }
+    break;
+
+  case 0x05:
+    opll->patch[1].AR = (data >> 4) & 15;
+    opll->patch[1].DR = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_EG(CAR(opll,i));
+      }
+    }
+    break;
+
+  case 0x06:
+    opll->patch[0].SL = (data >> 4) & 15;
+    opll->patch[0].RR = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_EG (MOD(opll,i));
+      }
+    }
+    break;
+
+  case 0x07:
+    opll->patch[1].SL = (data >> 4) & 15;
+    opll->patch[1].RR = (data) & 15;
+    for (i = 0; i < 9; i++)
+    {
+      if (opll->patch_number[i] == 0)
+      {
+        UPDATE_EG (CAR(opll,i));
+      }
+    }
+    break;
+
+  case 0x0e:
+    update_rhythm_mode (opll);
+    if (data & 32)
+    {
+      if (data & 0x10)
+        keyOn_BD (opll);
+      else
+        keyOff_BD (opll);
+      if (data & 0x8)
+        keyOn_SD (opll);
+      else
+        keyOff_SD (opll);
+      if (data & 0x4)
+        keyOn_TOM (opll);
+      else
+        keyOff_TOM (opll);
+      if (data & 0x2)
+        keyOn_CYM (opll);
+      else
+        keyOff_CYM (opll);
+      if (data & 0x1)
+        keyOn_HH (opll);
+      else
+        keyOff_HH (opll);
+    }
+    update_key_status (opll);
+
+    UPDATE_ALL (MOD(opll,6));
+    UPDATE_ALL (CAR(opll,6));
+    UPDATE_ALL (MOD(opll,7));
+    UPDATE_ALL (CAR(opll,7));
+    UPDATE_ALL (MOD(opll,8));
+    UPDATE_ALL (CAR(opll,8));
+
+    break;
+
+  case 0x0f:
+    break;
+
+  case 0x10:
+  case 0x11:
+  case 0x12:
+  case 0x13:
+  case 0x14:
+  case 0x15:
+  case 0x16:
+  case 0x17:
+  case 0x18:
+    ch = reg - 0x10;
+    setFnumber (opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));
+    UPDATE_ALL (MOD(opll,ch));
+    UPDATE_ALL (CAR(opll,ch));
+    break;
+
+  case 0x20:
+  case 0x21:
+  case 0x22:
+  case 0x23:
+  case 0x24:
+  case 0x25:
+  case 0x26:
+  case 0x27:
+  case 0x28:
+    ch = reg - 0x20;
+    setFnumber (opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);
+    setBlock (opll, ch, (data >> 1) & 7);
+    setSustine (opll, ch, (data >> 5) & 1);
+    if (data & 0x10)
+      keyOn (opll, ch);
+    else
+      keyOff (opll, ch);
+    UPDATE_ALL (MOD(opll,ch));
+    UPDATE_ALL (CAR(opll,ch));
+    update_key_status (opll);
+    update_rhythm_mode (opll);
+    break;
+
+  case 0x30:
+  case 0x31:
+  case 0x32:
+  case 0x33:
+  case 0x34:
+  case 0x35:
+  case 0x36:
+  case 0x37:
+  case 0x38:
+    i = (data >> 4) & 15;
+    v = data & 15;
+    if ((opll->reg[0x0e] & 32) && (reg >= 0x36))
+    {
+      switch (reg)
+      {
+      case 0x37:
+        setSlotVolume (MOD(opll,7), i << 2);
+        break;
+      case 0x38:
+        setSlotVolume (MOD(opll,8), i << 2);
+        break;
+      default:
+        break;
+      }
+    }
+    else
+    {
+      setPatch (opll, reg - 0x30, i);
+    }
+    setVolume (opll, reg - 0x30, v << 2);
+    UPDATE_ALL (MOD(opll,reg - 0x30));
+    UPDATE_ALL (CAR(opll,reg - 0x30));
+    break;
+
+  default:
+    break;
+
+  }
+}
+
+void
+OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val)
+{
+  if (adr & 1)
+    OPLL_writeReg (opll, opll->adr, val);
+  else
+    opll->adr = val;
+}
+
+#ifndef EMU2413_COMPACTION
+/* STEREO MODE (OPT) */
+void
+OPLL_set_pan (OPLL * opll, e_uint32 ch, e_uint32 pan)
+{
+  opll->pan[ch & 15] = pan & 255; /* Maxim: pan is 0..255 */
+}
+
+static void
+calc_stereo (OPLL * opll, e_int32 out[2])
+{
+  /* Maxim: changed panning to be 0..255, 127 is centre */
+  e_int32 l=0,r=0;
+//  e_int32 b[4] = { 0, 0, 0, 0 };        /* Ignore, Right, Left, Center */
+//  e_int32 r[4] = { 0, 0, 0, 0 };        /* Ignore, Right, Left, Center */
+  e_int32 i;
+  e_int32 channel;
+
+  update_ampm (opll);
+  update_noise (opll);
+
+  for(i=0;i<18;i++)
+  {
+    calc_phase(&opll->slot[i],opll->lfo_pm);
+    calc_envelope(&opll->slot[i],opll->lfo_am);
+  }
+
+  for (i = 0; i < 6; i++)
+    if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
+    {
+      channel = calc_slot_car (CAR(opll,i), calc_slot_mod (MOD(opll,i)));
+      if ( opll->pan[i] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[i]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[i]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+
+
+  if (opll->patch_number[6] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
+    {
+      channel = calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
+      if ( opll->pan[6] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[6]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[6]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+
+    }
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
+    {
+      channel = calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
+      if ( opll->pan[9] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[9]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[9]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+  }
+
+  if (opll->patch_number[7] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR (opll,7)->eg_mode != FINISH))
+    {
+      channel = calc_slot_car (CAR (opll,7), calc_slot_mod (MOD (opll,7)));
+      if ( opll->pan[7] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[7]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[7]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_HH) && (MOD (opll,7)->eg_mode != FINISH))
+    {
+      channel = calc_slot_hat (MOD (opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
+      if ( opll->pan[10] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[10]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[10]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+    if (!(opll->mask & OPLL_MASK_SD) && (CAR (opll,7)->eg_mode != FINISH))
+    {
+      channel = -calc_slot_snare (CAR (opll,7), opll->noise_seed&1); // this one is negated
+      if ( opll->pan[11] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[11]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[11]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+  }
+
+  if (opll->patch_number[8] <= 15)
+  {
+    if (!(opll->mask & OPLL_MASK_CH (8)) && (CAR (opll,8)->eg_mode != FINISH))
+    {
+      channel = calc_slot_car (CAR (opll,8), calc_slot_mod (MOD (opll,8)));
+      if ( opll->pan[8] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[8]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[8]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+  }
+  else
+  {
+    if (!(opll->mask & OPLL_MASK_TOM) && (MOD (opll,8)->eg_mode != FINISH))
+    {
+      channel = calc_slot_tom (MOD (opll,8));
+      if ( opll->pan[12] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[12]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[12]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+    if (!(opll->mask & OPLL_MASK_CYM) && (CAR (opll,8)->eg_mode != FINISH))
+    {
+      channel = -calc_slot_cym (CAR (opll,8), MOD(opll,7)->pgout); // negated
+      if ( opll->pan[13] == 127 )
+      {
+        l += channel;
+        r += channel;
+      }
+      else
+      {
+        l += channel * (255-opll->pan[13]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
+        r += channel * (    opll->pan[13]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
+      }
+    }
+  }
+/*
+  out[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) <<3;
+  out[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) <<3;
+  */
+  out[0] = l << 3;
+  out[1] = r << 3;
+}
+
+void
+OPLL_calc_stereo (OPLL * opll, e_int32 out[2])
+{
+  if (!opll->quality)
+  {
+    calc_stereo (opll, out);
+    return;
+  }
+
+  while (opll->realstep > opll->oplltime)
+  {
+    opll->oplltime += opll->opllstep;
+    opll->sprev[0] = opll->snext[0];
+    opll->sprev[1] = opll->snext[1];
+    calc_stereo (opll, opll->snext);
+  }
+
+  opll->oplltime -= opll->realstep;
+  out[0] = (e_int16) (((double) opll->snext[0] * (opll->opllstep - opll->oplltime)
+                       + (double) opll->sprev[0] * opll->oplltime) / opll->opllstep);
+  out[1] = (e_int16) (((double) opll->snext[1] * (opll->opllstep - opll->oplltime)
+                       + (double) opll->sprev[1] * opll->oplltime) / opll->opllstep);
+}
+#endif /* EMU2413_COMPACTION */
+
+// Ym2413_Emu
+#include "Ym2413_Emu.h"
+
+#include <assert.h>
+
+static int use_count = 0;
+
+Ym2413_Emu::~Ym2413_Emu()
+{
+	if ( opll )
+	{
+		use_count--;
+		OPLL_delete( opll );
+	}
+}
+
+Ym2413_Emu::Ym2413_Emu()
+{
+	opll = 0;
+}
+
+int Ym2413_Emu::set_rate( double sample_rate, double clock_rate )
+{
+	if ( opll )
+	{
+		OPLL_delete( opll );
+		opll = 0;
+		use_count--;
+	}
+
+	// Only one YM2413 may be used at a time (emu2413 uses lots of global data)
+	assert( use_count == 0 );
+	use_count++;
+
+	opll = OPLL_new ((int) clock_rate, (int) sample_rate);
+	if ( !opll )
+		return 1;
+
+	reset();
+	return 0;
+}
+
+void Ym2413_Emu::reset()
+{
+	OPLL_reset( opll );
+	OPLL_reset_patch( opll, 0 );
+	OPLL_setMask( opll, 0 );
+	OPLL_set_quality( opll, 0 );
+}
+
+void Ym2413_Emu::write( int addr, int data )
+{
+	OPLL_writeReg( opll, addr, data );
+}
+
+void Ym2413_Emu::mute_voices( int mask )
+{
+	OPLL_setMask( opll, mask );
+}
+
+void Ym2413_Emu::run( int pair_count, sample_t* out )
+{
+	while ( pair_count-- )
+	{
+		int s = OPLL_calc( opll );
+		out [0] = s;
+		out [1] = s;
+		out += 2;
+	}
+}
+
diff --git a/src/console/Ym2413_Emu.cxx b/src/console/Ym2413_Emu.cxx
deleted file mode 100644
index 9d8595922453..000000000000
--- a/src/console/Ym2413_Emu.cxx
+++ /dev/null
@@ -1,2224 +0,0 @@
-
-// Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
-
-/***********************************************************************************
-
-  emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
-
-  2001 01-08 : Version 0.10 -- 1st version.
-  2001 01-15 : Version 0.20 -- semi-public version.
-  2001 01-16 : Version 0.30 -- 1st public version.
-  2001 01-17 : Version 0.31 -- Fixed bassdrum problem.
-             : Version 0.32 -- LPF implemented.
-  2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method.
-                            -- Fixed the LFO bug.
-  2001 01-24 : Version 0.35 -- Fixed the drum problem,
-                               support undocumented EG behavior.
-  2001 02-02 : Version 0.38 -- Improved the performance.
-                               Fixed the hi-hat and cymbal model.
-                               Fixed the default percussive datas.
-                               Noise reduction.
-                               Fixed the feedback problem.
-  2001 03-03 : Version 0.39 -- Fixed some drum bugs.
-                               Improved the performance.
-  2001 03-04 : Version 0.40 -- Improved the feedback.
-                               Change the default table size.
-                               Clock and Rate can be changed during play.
-  2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone.
-                               Added VRC7 patch (OPLL_reset_patch is changed).
-                               Fixed OPLL_reset() bug.
-                               Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask.
-                               Added OPLL_writeIO.
-  2001 09-28 : Version 0.51 -- Removed the noise table.
-  2002 01-28 : Version 0.52 -- Added Stereo mode.
-  2002 02-07 : Version 0.53 -- Fixed some drum bugs.
-  2002 02-20 : Version 0.54 -- Added the best quality mode.
-  2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close.
-  2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas.
-  2004 04-10 : Version 0.61 -- Added YMF281B tone (defined by Chabin).
-
-  References:
-    fmopl.c        -- 1999,2000 written by Tatsuyuki Satoh (MAME development).
-    fmopl.c(fixed) -- (C) 2002 Jarek Burczynski.
-    s_opl.c        -- 2001 written by Mamiya (NEZplug development).
-    fmgen.cpp      -- 1999,2000 written by cisc.
-    fmpac.ill      -- 2000 created by NARUTO.
-    MSX-Datapack
-    YMU757 data sheet
-    YM2143 data sheet
-
-**************************************************************************************/
-
-
-#ifndef _EMU2413_H_
-#define _EMU2413_H_
-
-typedef signed char     e_int8;
-typedef unsigned char   e_uint8;
-typedef signed short    e_int16;
-typedef unsigned short  e_uint16;
-typedef signed long     e_int32;
-typedef unsigned long   e_uint32;
-
-#ifdef EMU2413_DLL_EXPORTS
-  #define EMU2413_API __declspec(dllexport)
-#elif defined(EMU2413_DLL_IMPORTS)
-  #define EMU2413_API __declspec(dllimport)
-#else
-  #define EMU2413_API
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PI 3.14159265358979323846
-
-enum OPLL_TONE_ENUM {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1, OPLL_281B_TONE=2} ;
-
-/* voice data */
-typedef struct __OPLL_PATCH {
-  e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ;
-} OPLL_PATCH ;
-
-/* slot */
-typedef struct __OPLL_SLOT {
-
-  OPLL_PATCH *patch;
-
-  e_int32 type ;          /* 0 : modulator 1 : carrier */
-
-  /* OUTPUT */
-  e_int32 feedback ;
-  e_int32 output[2] ;   /* Output value of slot */
-
-  /* for Phase Generator (PG) */
-  e_uint16 *sintbl ;    /* Wavetable */
-  e_uint32 phase ;      /* Phase */
-  e_uint32 dphase ;     /* Phase increment amount */
-  e_uint32 pgout ;      /* output */
-
-  /* for Envelope Generator (EG) */
-  e_int32 fnum ;          /* F-Number */
-  e_int32 block ;         /* Block */
-  e_int32 volume ;        /* Current volume */
-  e_int32 sustine ;       /* Sustine 1 = ON, 0 = OFF */
-  e_uint32 tll ;          /* Total Level + Key scale level*/
-  e_uint32 rks ;        /* Key scale offset (Rks) */
-  e_int32 eg_mode ;       /* Current state */
-  e_uint32 eg_phase ;   /* Phase */
-  e_uint32 eg_dphase ;  /* Phase increment amount */
-  e_uint32 egout ;      /* output */
-
-} OPLL_SLOT ;
-
-/* Mask */
-#define OPLL_MASK_CH(x) (1<<(x))
-#define OPLL_MASK_HH (1<<(9))
-#define OPLL_MASK_CYM (1<<(10))
-#define OPLL_MASK_TOM (1<<(11))
-#define OPLL_MASK_SD (1<<(12))
-#define OPLL_MASK_BD (1<<(13))
-#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
-
-/* opll */
-typedef struct OPLL {
-
-  e_uint32 adr ;
-  e_int32 out ;
-
-#ifndef EMU2413_COMPACTION
-  e_uint32 realstep ;
-  e_uint32 oplltime ;
-  e_uint32 opllstep ;
-  e_int32 prev, next ;
-  e_int32 sprev[2],snext[2];
-  e_int32 pan[16];
-#endif
-
-  /* Register */
-  e_uint8 reg[0x40] ;
-  e_int32 slot_on_flag[18] ;
-
-  /* Pitch Modulator */
-  e_uint32 pm_phase ;
-  e_int32 lfo_pm ;
-
-  /* Amp Modulator */
-  e_int32 am_phase ;
-  e_int32 lfo_am ;
-
-  e_uint32 quality;
-
-  /* Noise Generator */
-  e_uint32 noise_seed ;
-
-  /* Channel Data */
-  e_int32 patch_number[9];
-  e_int32 key_status[9] ;
-
-  /* Slot */
-  OPLL_SLOT slot[18] ;
-
-  /* Voice Data */
-  OPLL_PATCH patch[19*2] ;
-  e_int32 patch_update[2] ; /* flag for check patch update */
-
-  e_uint32 mask ;
-
-} OPLL ;
-
-/* Create Object */
-EMU2413_API OPLL *OPLL_new(e_uint32 clk, e_uint32 rate) ;
-EMU2413_API void OPLL_delete(OPLL *) ;
-
-/* Setup */
-EMU2413_API void OPLL_reset(OPLL *) ;
-EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ;
-EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ;
-EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ;
-EMU2413_API void OPLL_set_pan(OPLL *, e_uint32 ch, e_uint32 pan);
-
-/* Port/Register access */
-EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val) ;
-EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val) ;
-
-/* Synthsize */
-EMU2413_API e_int16 OPLL_calc(OPLL *) ;
-EMU2413_API void OPLL_calc_stereo(OPLL *, e_int32 out[2]) ;
-
-/* Misc */
-EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ;
-EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ;
-EMU2413_API void OPLL_forceRefresh(OPLL *) ;
-/* Utility */
-EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ;
-EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ;
-EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ;
-
-/* Channel Mask */
-EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ;
-EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
-
-#define dump2patch OPLL_dump2patch
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#define EMU2413_COMPACTION
-#define INLINE inline
-
-#ifdef EMU2413_COMPACTION
-#define OPLL_TONE_NUM 1
-static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
-  {
-/* YM2413 tone by okazaki at angel.ne.jp */
-0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-  }
-};
-#else
-#define OPLL_TONE_NUM 3
-static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
-  {
-#include "2413tone.h"
-  },
-  {
-#include "vrc7tone.h"
-   },
-  {
-#include "281btone.h"
-  }
-};
-#endif
-
-/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.) */
-#define PG_BITS 9
-#define PG_WIDTH (1<<PG_BITS)
-
-/* Phase increment counter */
-#define DP_BITS 18
-#define DP_WIDTH (1<<DP_BITS)
-#define DP_BASE_BITS (DP_BITS - PG_BITS)
-
-/* Dynamic range (Accuracy of sin table) */
-#define DB_BITS 8
-#define DB_STEP (48.0/(1<<DB_BITS))
-#define DB_MUTE (1<<DB_BITS)
-
-/* Dynamic range of envelope */
-#define EG_STEP 0.375
-#define EG_BITS 7
-#define EG_MUTE (1<<EG_BITS)
-
-/* Dynamic range of total level */
-#define TL_STEP 0.75
-#define TL_BITS 6
-#define TL_MUTE (1<<TL_BITS)
-
-/* Dynamic range of sustine level */
-#define SL_STEP 3.0
-#define SL_BITS 4
-#define SL_MUTE (1<<SL_BITS)
-
-#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
-#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
-#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
-
-#define DB_POS(x) (e_uint32)((x)/DB_STEP)
-#define DB_NEG(x) (e_uint32)(DB_MUTE+DB_MUTE+(x)/DB_STEP)
-
-/* Bits for liner value */
-#define DB2LIN_AMP_BITS 8
-#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
-
-/* Bits for envelope phase incremental counter */
-#define EG_DP_BITS 22
-#define EG_DP_WIDTH (1<<EG_DP_BITS)
-
-/* Bits for Pitch and Amp modulator */
-#define PM_PG_BITS 8
-#define PM_PG_WIDTH (1<<PM_PG_BITS)
-#define PM_DP_BITS 16
-#define PM_DP_WIDTH (1<<PM_DP_BITS)
-#define AM_PG_BITS 8
-#define AM_PG_WIDTH (1<<AM_PG_BITS)
-#define AM_DP_BITS 16
-#define AM_DP_WIDTH (1<<AM_DP_BITS)
-
-/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
-#define PM_AMP_BITS 8
-#define PM_AMP (1<<PM_AMP_BITS)
-
-/* PM speed(Hz) and depth(cent) */
-#define PM_SPEED 6.4
-#define PM_DEPTH 13.75
-
-/* AM speed(Hz) and depth(dB) */
-#define AM_SPEED 3.6413
-#define AM_DEPTH 4.875
-
-/* Cut the lower b bit(s) off. */
-#define HIGHBITS(c,b) ((c)>>(b))
-
-/* Leave the lower b bit(s). */
-#define LOWBITS(c,b) ((c)&((1<<(b))-1))
-
-/* Expand x which is s bits to d bits. */
-#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s)))
-
-/* Expand x which is s bits to d bits and fill expanded bits '1' */
-#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
-
-/* Adjust envelope speed which depends on sampling rate. */
-#define RATE_ADJUST(x) (rate==49716?x:(e_uint32)((double)(x)*clk/72/rate + 0.5))        /* added 0.5 to round the value*/
-
-#define MOD(o,x) (&(o)->slot[(x)<<1])
-#define CAR(o,x) (&(o)->slot[((x)<<1)|1])
-
-#define BIT(s,b) (((s)>>(b))&1)
-
-/* Input clock */
-static e_uint32 clk = 844451141;
-/* Sampling rate */
-static e_uint32 rate = 3354932;
-
-/* WaveTable for each envelope amp */
-static e_uint16 fullsintable[PG_WIDTH];
-static e_uint16 halfsintable[PG_WIDTH];
-
-static e_uint16 *waveform[2] = { fullsintable, halfsintable };
-
-/* LFO Table */
-static e_int32 pmtable[PM_PG_WIDTH];
-static e_int32 amtable[AM_PG_WIDTH];
-
-/* Phase delta for LFO */
-static e_uint32 pm_dphase;
-static e_uint32 am_dphase;
-
-/* dB to Liner table */
-static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2];
-
-/* Liner to Log curve conversion table (for Attack rate). */
-static e_uint16 AR_ADJUST_TABLE[1 << EG_BITS];
-
-/* Empty voice data */
-static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/* Basic voice Data */
-static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];
-
-/* Definition of envelope mode */
-enum OPLL_EG_STATE
-{ READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH };
-
-/* Phase incr table for Attack */
-static e_uint32 dphaseARTable[16][16];
-/* Phase incr table for Decay and Release */
-static e_uint32 dphaseDRTable[16][16];
-
-/* KSL + TL Table */
-static e_uint32 tllTable[16][8][1 << TL_BITS][4];
-static e_int32 rksTable[2][8][2];
-
-/* Phase incr table for PG */
-static e_uint32 dphaseTable[512][8][16];
-
-/***************************************************
-
-                  Create tables
-
-****************************************************/
-INLINE static e_int32
-Min (e_int32 i, e_int32 j)
-{
-  if (i < j)
-    return i;
-  else
-    return j;
-}
-
-/* Table for AR to LogCurve. */
-static void
-makeAdjustTable (void)
-{
-  e_int32 i;
-
-  AR_ADJUST_TABLE[0] = (1 << EG_BITS) - 1;
-  for (i = 1; i < (1<<EG_BITS); i++)
-    AR_ADJUST_TABLE[i] = (e_uint16) ((double) (1<<EG_BITS)-1 - ((1<<EG_BITS)-1)*log(i)/log(127));
-}
-
-
-/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
-static void
-makeDB2LinTable (void)
-{
-  e_int32 i;
-
-  for (i = 0; i < DB_MUTE + DB_MUTE; i++)
-  {
-    DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
-    if (i >= DB_MUTE) DB2LIN_TABLE[i] = 0;
-    DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]);
-  }
-}
-
-/* Liner(+0.0 - +1.0) to dB((1<<DB_BITS) - 1 -- 0) */
-static e_int32
-lin2db (double d)
-{
-  if (d == 0)
-    return (DB_MUTE - 1);
-  else
-    return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1);  /* 0 -- 127 */
-}
-
-
-/* Sin Table */
-static void
-makeSinTable (void)
-{
-  e_int32 i;
-
-  for (i = 0; i < PG_WIDTH / 4; i++)
-  {
-    fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
-  }
-
-  for (i = 0; i < PG_WIDTH / 4; i++)
-  {
-    fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
-  }
-
-  for (i = 0; i < PG_WIDTH / 2; i++)
-  {
-    fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
-  }
-
-  for (i = 0; i < PG_WIDTH / 2; i++)
-    halfsintable[i] = fullsintable[i];
-  for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
-    halfsintable[i] = fullsintable[0];
-}
-
-static double saw(double phase)
-{
-  if(phase <= PI/2)
-    return phase * 2 / PI ;
-  else if(phase <= PI*3/2)
-    return 2.0 - ( phase * 2 / PI );
-  else
-    return -4.0 + phase * 2 / PI;
-}
-
-/* Table for Pitch Modulator */
-static void
-makePmTable (void)
-{
-  e_int32 i;
-
-  for (i = 0; i < PM_PG_WIDTH; i++)
-    /* pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200)); */
-    pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * saw (2.0 * PI * i / PM_PG_WIDTH) / 1200));
-}
-
-/* Table for Amp Modulator */
-static void
-makeAmTable (void)
-{
-  e_int32 i;
-
-  for (i = 0; i < AM_PG_WIDTH; i++)
-    /* amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH))); */
-    amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + saw (2.0 * PI * i / PM_PG_WIDTH)));
-}
-
-/* Phase increment counter table */
-static void
-makeDphaseTable (void)
-{
-  e_uint32 fnum, block, ML;
-  e_uint32 mltable[16] =
-    { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
-
-  for (fnum = 0; fnum < 512; fnum++)
-    for (block = 0; block < 8; block++)
-      for (ML = 0; ML < 16; ML++)
-        dphaseTable[fnum][block][ML] = RATE_ADJUST (((fnum * mltable[ML]) << block) >> (20 - DP_BITS));
-}
-
-static void
-makeTllTable (void)
-{
-#define dB2(x) ((x)*2)
-
-  static double kltable[16] = {
-    dB2 (0.000), dB2 (9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
-    dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
-  };
-
-  e_int32 tmp;
-  e_int32 fnum, block, TL, KL;
-
-  for (fnum = 0; fnum < 16; fnum++)
-    for (block = 0; block < 8; block++)
-      for (TL = 0; TL < 64; TL++)
-        for (KL = 0; KL < 4; KL++)
-        {
-          if (KL == 0)
-          {
-            tllTable[fnum][block][TL][KL] = TL2EG (TL);
-          }
-          else
-          {
-            tmp = (e_int32) (kltable[fnum] - dB2 (3.000) * (7 - block));
-            if (tmp <= 0)
-              tllTable[fnum][block][TL][KL] = TL2EG (TL);
-            else
-              tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL);
-          }
-        }
-}
-
-#ifdef USE_SPEC_ENV_SPEED
-static double attacktime[16][4] = {
-  {0, 0, 0, 0},
-  {1730.15, 1400.60, 1153.43, 988.66},
-  {865.08, 700.30, 576.72, 494.33},
-  {432.54, 350.15, 288.36, 247.16},
-  {216.27, 175.07, 144.18, 123.58},
-  {108.13, 87.54, 72.09, 61.79},
-  {54.07, 43.77, 36.04, 30.90},
-  {27.03, 21.88, 18.02, 15.45},
-  {13.52, 10.94, 9.01, 7.72},
-  {6.76, 5.47, 4.51, 3.86},
-  {3.38, 2.74, 2.25, 1.93},
-  {1.69, 1.37, 1.13, 0.97},
-  {0.84, 0.70, 0.60, 0.54},
-  {0.50, 0.42, 0.34, 0.30},
-  {0.28, 0.22, 0.18, 0.14},
-  {0.00, 0.00, 0.00, 0.00}
-};
-
-static double decaytime[16][4] = {
-  {0, 0, 0, 0},
-  {20926.60, 16807.20, 14006.00, 12028.60},
-  {10463.30, 8403.58, 7002.98, 6014.32},
-  {5231.64, 4201.79, 3501.49, 3007.16},
-  {2615.82, 2100.89, 1750.75, 1503.58},
-  {1307.91, 1050.45, 875.37, 751.79},
-  {653.95, 525.22, 437.69, 375.90},
-  {326.98, 262.61, 218.84, 187.95},
-  {163.49, 131.31, 109.42, 93.97},
-  {81.74, 65.65, 54.71, 46.99},
-  {40.87, 32.83, 27.36, 23.49},
-  {20.44, 16.41, 13.68, 11.75},
-  {10.22, 8.21, 6.84, 5.87},
-  {5.11, 4.10, 3.42, 2.94},
-  {2.55, 2.05, 1.71, 1.47},
-  {1.27, 1.27, 1.27, 1.27}
-};
-#endif
-
-/* Rate Table for Attack */
-static void
-makeDphaseARTable (void)
-{
-  e_int32 AR, Rks, RM, RL;
-
-#ifdef USE_SPEC_ENV_SPEED
-  e_uint32 attacktable[16][4];
-
-  for (RM = 0; RM < 16; RM++)
-    for (RL = 0; RL < 4; RL++)
-    {
-      if (RM == 0)
-        attacktable[RM][RL] = 0;
-      else if (RM == 15)
-        attacktable[RM][RL] = EG_DP_WIDTH;
-      else
-        attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
-
-    }
-#endif
-
-  for (AR = 0; AR < 16; AR++)
-    for (Rks = 0; Rks < 16; Rks++)
-    {
-      RM = AR + (Rks >> 2);
-      RL = Rks & 3;
-      if (RM > 15)
-        RM = 15;
-      switch (AR)
-      {
-      case 0:
-        dphaseARTable[AR][Rks] = 0;
-        break;
-      case 15:
-        dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/
-        break;
-      default:
-#ifdef USE_SPEC_ENV_SPEED
-        dphaseARTable[AR][Rks] = RATE_ADJUST (attacktable[RM][RL]);
-#else
-        dphaseARTable[AR][Rks] = RATE_ADJUST ((3 * (RL + 4) << (RM + 1)));
-#endif
-        break;
-      }
-    }
-}
-
-/* Rate Table for Decay and Release */
-static void
-makeDphaseDRTable (void)
-{
-  e_int32 DR, Rks, RM, RL;
-
-#ifdef USE_SPEC_ENV_SPEED
-  e_uint32 decaytable[16][4];
-
-  for (RM = 0; RM < 16; RM++)
-    for (RL = 0; RL < 4; RL++)
-      if (RM == 0)
-        decaytable[RM][RL] = 0;
-      else
-        decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000));
-#endif
-
-  for (DR = 0; DR < 16; DR++)
-    for (Rks = 0; Rks < 16; Rks++)
-    {
-      RM = DR + (Rks >> 2);
-      RL = Rks & 3;
-      if (RM > 15)
-        RM = 15;
-      switch (DR)
-      {
-      case 0:
-        dphaseDRTable[DR][Rks] = 0;
-        break;
-      default:
-#ifdef USE_SPEC_ENV_SPEED
-        dphaseDRTable[DR][Rks] = RATE_ADJUST (decaytable[RM][RL]);
-#else
-        dphaseDRTable[DR][Rks] = RATE_ADJUST ((RL + 4) << (RM - 1));
-#endif
-        break;
-      }
-    }
-}
-
-static void
-makeRksTable (void)
-{
-
-  e_int32 fnum8, block, KR;
-
-  for (fnum8 = 0; fnum8 < 2; fnum8++)
-    for (block = 0; block < 8; block++)
-      for (KR = 0; KR < 2; KR++)
-      {
-        if (KR != 0)
-          rksTable[fnum8][block][KR] = (block << 1) + fnum8;
-        else
-          rksTable[fnum8][block][KR] = block >> 1;
-      }
-}
-
-void
-OPLL_dump2patch (const e_uint8 * dump, OPLL_PATCH * patch)
-{
-  patch[0].AM = (dump[0] >> 7) & 1;
-  patch[1].AM = (dump[1] >> 7) & 1;
-  patch[0].PM = (dump[0] >> 6) & 1;
-  patch[1].PM = (dump[1] >> 6) & 1;
-  patch[0].EG = (dump[0] >> 5) & 1;
-  patch[1].EG = (dump[1] >> 5) & 1;
-  patch[0].KR = (dump[0] >> 4) & 1;
-  patch[1].KR = (dump[1] >> 4) & 1;
-  patch[0].ML = (dump[0]) & 15;
-  patch[1].ML = (dump[1]) & 15;
-  patch[0].KL = (dump[2] >> 6) & 3;
-  patch[1].KL = (dump[3] >> 6) & 3;
-  patch[0].TL = (dump[2]) & 63;
-  patch[0].FB = (dump[3]) & 7;
-  patch[0].WF = (dump[3] >> 3) & 1;
-  patch[1].WF = (dump[3] >> 4) & 1;
-  patch[0].AR = (dump[4] >> 4) & 15;
-  patch[1].AR = (dump[5] >> 4) & 15;
-  patch[0].DR = (dump[4]) & 15;
-  patch[1].DR = (dump[5]) & 15;
-  patch[0].SL = (dump[6] >> 4) & 15;
-  patch[1].SL = (dump[7] >> 4) & 15;
-  patch[0].RR = (dump[6]) & 15;
-  patch[1].RR = (dump[7]) & 15;
-}
-
-void
-OPLL_getDefaultPatch (e_int32 type, e_int32 num, OPLL_PATCH * patch)
-{
-  OPLL_dump2patch (default_inst[type] + num * 16, patch);
-}
-
-static void
-makeDefaultPatch ()
-{
-  e_int32 i, j;
-
-  for (i = 0; i < OPLL_TONE_NUM; i++)
-    for (j = 0; j < 19; j++)
-      OPLL_getDefaultPatch (i, j, &default_patch[i][j * 2]);
-
-}
-
-void
-OPLL_setPatch (OPLL * opll, const e_uint8 * dump)
-{
-  OPLL_PATCH patch[2];
-  int i;
-
-  for (i = 0; i < 19; i++)
-  {
-    OPLL_dump2patch (dump + i * 16, patch);
-    memcpy (&opll->patch[i*2+0], &patch[0], sizeof (OPLL_PATCH));
-    memcpy (&opll->patch[i*2+1], &patch[1], sizeof (OPLL_PATCH));
-  }
-}
-
-void
-OPLL_patch2dump (const OPLL_PATCH * patch, e_uint8 * dump)
-{
-  dump[0] = (e_uint8) ((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);
-  dump[1] = (e_uint8) ((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);
-  dump[2] = (e_uint8) ((patch[0].KL << 6) + patch[0].TL);
-  dump[3] = (e_uint8) ((patch[1].KL << 6) + (patch[1].WF << 4) + (patch[0].WF << 3) + patch[0].FB);
-  dump[4] = (e_uint8) ((patch[0].AR << 4) + patch[0].DR);
-  dump[5] = (e_uint8) ((patch[1].AR << 4) + patch[1].DR);
-  dump[6] = (e_uint8) ((patch[0].SL << 4) + patch[0].RR);
-  dump[7] = (e_uint8) ((patch[1].SL << 4) + patch[1].RR);
-  dump[8] = 0;
-  dump[9] = 0;
-  dump[10] = 0;
-  dump[11] = 0;
-  dump[12] = 0;
-  dump[13] = 0;
-  dump[14] = 0;
-  dump[15] = 0;
-}
-
-/************************************************************
-
-                      Calc Parameters
-
-************************************************************/
-
-INLINE static e_uint32
-calc_eg_dphase (OPLL_SLOT * slot)
-{
-
-  switch (slot->eg_mode)
-  {
-  case ATTACK:
-    return dphaseARTable[slot->patch->AR][slot->rks];
-
-  case DECAY:
-    return dphaseDRTable[slot->patch->DR][slot->rks];
-
-  case SUSHOLD:
-    return 0;
-
-  case SUSTINE:
-    return dphaseDRTable[slot->patch->RR][slot->rks];
-
-  case RELEASE:
-    if (slot->sustine)
-      return dphaseDRTable[5][slot->rks];
-    else if (slot->patch->EG)
-      return dphaseDRTable[slot->patch->RR][slot->rks];
-    else
-      return dphaseDRTable[7][slot->rks];
-
-  case SETTLE:
-    return dphaseDRTable[15][0];
-
-  case FINISH:
-    return 0;
-
-  default:
-    return 0;
-  }
-}
-
-/*************************************************************
-
-                    OPLL internal interfaces
-
-*************************************************************/
-#define SLOT_BD1 12
-#define SLOT_BD2 13
-#define SLOT_HH 14
-#define SLOT_SD 15
-#define SLOT_TOM 16
-#define SLOT_CYM 17
-
-#define UPDATE_PG(S)  (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch->ML]
-#define UPDATE_TLL(S)\
-(((S)->type==0)?\
-((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch->TL][(S)->patch->KL]):\
-((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch->KL]))
-#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch->KR]
-#define UPDATE_WF(S)  (S)->sintbl = waveform[(S)->patch->WF]
-#define UPDATE_EG(S)  (S)->eg_dphase = calc_eg_dphase(S)
-#define UPDATE_ALL(S)\
-  UPDATE_PG(S);\
-  UPDATE_TLL(S);\
-  UPDATE_RKS(S);\
-  UPDATE_WF(S); \
-  UPDATE_EG(S)                  /* EG should be updated last. */
-
-
-/* Slot key on  */
-INLINE static void
-slotOn (OPLL_SLOT * slot)
-{
-  slot->eg_mode = ATTACK;
-  slot->eg_phase = 0;
-  slot->phase = 0;
-  UPDATE_EG(slot);
-}
-
-/* Slot key on without reseting the phase */
-INLINE static void
-slotOn2 (OPLL_SLOT * slot)
-{
-  slot->eg_mode = ATTACK;
-  slot->eg_phase = 0;
-  UPDATE_EG(slot);
-}
-
-/* Slot key off */
-INLINE static void
-slotOff (OPLL_SLOT * slot)
-{
-  if (slot->eg_mode == ATTACK)
-    slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)], EG_BITS, EG_DP_BITS);
-  slot->eg_mode = RELEASE;
-  UPDATE_EG(slot);
-}
-
-/* Channel key on */
-INLINE static void
-keyOn (OPLL * opll, e_int32 i)
-{
-  if (!opll->slot_on_flag[i * 2])
-    slotOn (MOD(opll,i));
-  if (!opll->slot_on_flag[i * 2 + 1])
-    slotOn (CAR(opll,i));
-  opll->key_status[i] = 1;
-}
-
-/* Channel key off */
-INLINE static void
-keyOff (OPLL * opll, e_int32 i)
-{
-  if (opll->slot_on_flag[i * 2 + 1])
-    slotOff (CAR(opll,i));
-  opll->key_status[i] = 0;
-}
-
-INLINE static void
-keyOn_BD (OPLL * opll)
-{
-  keyOn (opll, 6);
-}
-INLINE static void
-keyOn_SD (OPLL * opll)
-{
-  if (!opll->slot_on_flag[SLOT_SD])
-    slotOn (CAR(opll,7));
-}
-INLINE static void
-keyOn_TOM (OPLL * opll)
-{
-  if (!opll->slot_on_flag[SLOT_TOM])
-    slotOn (MOD(opll,8));
-}
-INLINE static void
-keyOn_HH (OPLL * opll)
-{
-  if (!opll->slot_on_flag[SLOT_HH])
-    slotOn2 (MOD(opll,7));
-}
-INLINE static void
-keyOn_CYM (OPLL * opll)
-{
-  if (!opll->slot_on_flag[SLOT_CYM])
-    slotOn2 (CAR(opll,8));
-}
-
-/* Drum key off */
-INLINE static void
-keyOff_BD (OPLL * opll)
-{
-  keyOff (opll, 6);
-}
-INLINE static void
-keyOff_SD (OPLL * opll)
-{
-  if (opll->slot_on_flag[SLOT_SD])
-    slotOff (CAR(opll,7));
-}
-INLINE static void
-keyOff_TOM (OPLL * opll)
-{
-  if (opll->slot_on_flag[SLOT_TOM])
-    slotOff (MOD(opll,8));
-}
-INLINE static void
-keyOff_HH (OPLL * opll)
-{
-  if (opll->slot_on_flag[SLOT_HH])
-    slotOff (MOD(opll,7));
-}
-INLINE static void
-keyOff_CYM (OPLL * opll)
-{
-  if (opll->slot_on_flag[SLOT_CYM])
-    slotOff (CAR(opll,8));
-}
-
-/* Change a voice */
-INLINE static void
-setPatch (OPLL * opll, e_int32 i, e_int32 num)
-{
-  opll->patch_number[i] = num;
-  MOD(opll,i)->patch = &opll->patch[num * 2 + 0];
-  CAR(opll,i)->patch = &opll->patch[num * 2 + 1];
-}
-
-/* Change a rhythm voice */
-INLINE static void
-setSlotPatch (OPLL_SLOT * slot, OPLL_PATCH * patch)
-{
-  slot->patch = patch;
-}
-
-/* Set sustine parameter */
-INLINE static void
-setSustine (OPLL * opll, e_int32 c, e_int32 sustine)
-{
-  CAR(opll,c)->sustine = sustine;
-  if (MOD(opll,c)->type)
-    MOD(opll,c)->sustine = sustine;
-}
-
-/* Volume : 6bit ( Volume register << 2 ) */
-INLINE static void
-setVolume (OPLL * opll, e_int32 c, e_int32 volume)
-{
-  CAR(opll,c)->volume = volume;
-}
-
-INLINE static void
-setSlotVolume (OPLL_SLOT * slot, e_int32 volume)
-{
-  slot->volume = volume;
-}
-
-/* Set F-Number ( fnum : 9bit ) */
-INLINE static void
-setFnumber (OPLL * opll, e_int32 c, e_int32 fnum)
-{
-  CAR(opll,c)->fnum = fnum;
-  MOD(opll,c)->fnum = fnum;
-}
-
-/* Set Block data (block : 3bit ) */
-INLINE static void
-setBlock (OPLL * opll, e_int32 c, e_int32 block)
-{
-  CAR(opll,c)->block = block;
-  MOD(opll,c)->block = block;
-}
-
-/* Change Rhythm Mode */
-INLINE static void
-update_rhythm_mode (OPLL * opll)
-{
-  if (opll->patch_number[6] & 0x10)
-  {
-    if (!(opll->slot_on_flag[SLOT_BD2] | (opll->reg[0x0e] & 32)))
-    {
-      opll->slot[SLOT_BD1].eg_mode = FINISH;
-      opll->slot[SLOT_BD2].eg_mode = FINISH;
-      setPatch (opll, 6, opll->reg[0x36] >> 4);
-    }
-  }
-  else if (opll->reg[0x0e] & 32)
-  {
-    opll->patch_number[6] = 16;
-    opll->slot[SLOT_BD1].eg_mode = FINISH;
-    opll->slot[SLOT_BD2].eg_mode = FINISH;
-    setSlotPatch (&opll->slot[SLOT_BD1], &opll->patch[16 * 2 + 0]);
-    setSlotPatch (&opll->slot[SLOT_BD2], &opll->patch[16 * 2 + 1]);
-  }
-
-  if (opll->patch_number[7] & 0x10)
-  {
-    if (!((opll->slot_on_flag[SLOT_HH] && opll->slot_on_flag[SLOT_SD]) | (opll->reg[0x0e] & 32)))
-    {
-      opll->slot[SLOT_HH].type = 0;
-      opll->slot[SLOT_HH].eg_mode = FINISH;
-      opll->slot[SLOT_SD].eg_mode = FINISH;
-      setPatch (opll, 7, opll->reg[0x37] >> 4);
-    }
-  }
-  else if (opll->reg[0x0e] & 32)
-  {
-    opll->patch_number[7] = 17;
-    opll->slot[SLOT_HH].type = 1;
-    opll->slot[SLOT_HH].eg_mode = FINISH;
-    opll->slot[SLOT_SD].eg_mode = FINISH;
-    setSlotPatch (&opll->slot[SLOT_HH], &opll->patch[17 * 2 + 0]);
-    setSlotPatch (&opll->slot[SLOT_SD], &opll->patch[17 * 2 + 1]);
-  }
-
-  if (opll->patch_number[8] & 0x10)
-  {
-    if (!((opll->slot_on_flag[SLOT_CYM] && opll->slot_on_flag[SLOT_TOM]) | (opll->reg[0x0e] & 32)))
-    {
-      opll->slot[SLOT_TOM].type = 0;
-      opll->slot[SLOT_TOM].eg_mode = FINISH;
-      opll->slot[SLOT_CYM].eg_mode = FINISH;
-      setPatch (opll, 8, opll->reg[0x38] >> 4);
-    }
-  }
-  else if (opll->reg[0x0e] & 32)
-  {
-    opll->patch_number[8] = 18;
-    opll->slot[SLOT_TOM].type = 1;
-    opll->slot[SLOT_TOM].eg_mode = FINISH;
-    opll->slot[SLOT_CYM].eg_mode = FINISH;
-    setSlotPatch (&opll->slot[SLOT_TOM], &opll->patch[18 * 2 + 0]);
-    setSlotPatch (&opll->slot[SLOT_CYM], &opll->patch[18 * 2 + 1]);
-  }
-}
-
-INLINE static void
-update_key_status (OPLL * opll)
-{
-  int ch;
-
-  for (ch = 0; ch < 9; ch++)
-    opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->reg[0x20 + ch]) & 0x10;
-
-  if (opll->reg[0x0e] & 32)
-  {
-    opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e] & 0x10);
-    opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e] & 0x10);
-    opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e] & 0x08);
-    opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e] & 0x01);
-    opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e] & 0x04);
-    opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e] & 0x02);
-  }
-}
-
-void
-OPLL_copyPatch (OPLL * opll, e_int32 num, OPLL_PATCH * patch)
-{
-  memcpy (&opll->patch[num], patch, sizeof (OPLL_PATCH));
-}
-
-/***********************************************************
-
-                      Initializing
-
-***********************************************************/
-
-static void
-OPLL_SLOT_reset (OPLL_SLOT * slot, int type)
-{
-  slot->type = type;
-  slot->sintbl = waveform[0];
-  slot->phase = 0;
-  slot->dphase = 0;
-  slot->output[0] = 0;
-  slot->output[1] = 0;
-  slot->feedback = 0;
-  slot->eg_mode = FINISH;
-  slot->eg_phase = EG_DP_WIDTH;
-  slot->eg_dphase = 0;
-  slot->rks = 0;
-  slot->tll = 0;
-  slot->sustine = 0;
-  slot->fnum = 0;
-  slot->block = 0;
-  slot->volume = 0;
-  slot->pgout = 0;
-  slot->egout = 0;
-  slot->patch = &null_patch;
-}
-
-static void
-internal_refresh (void)
-{
-  makeDphaseTable ();
-  makeDphaseARTable ();
-  makeDphaseDRTable ();
-  pm_dphase = (e_uint32) RATE_ADJUST (PM_SPEED * PM_DP_WIDTH / (clk / 72));
-  am_dphase = (e_uint32) RATE_ADJUST (AM_SPEED * AM_DP_WIDTH / (clk / 72));
-}
-
-static void
-maketables (e_uint32 c, e_uint32 r)
-{
-  if (c != clk)
-  {
-    clk = c;
-    makePmTable ();
-    makeAmTable ();
-    makeDB2LinTable ();
-    makeAdjustTable ();
-    makeTllTable ();
-    makeRksTable ();
-    makeSinTable ();
-    makeDefaultPatch ();
-  }
-
-  if (r != rate)
-  {
-    rate = r;
-    internal_refresh ();
-  }
-}
-
-OPLL *
-OPLL_new (e_uint32 clk, e_uint32 rate)
-{
-  OPLL *opll;
-  e_int32 i;
-
-  maketables (clk, rate);
-
-  opll = (OPLL *) calloc (sizeof (OPLL), 1);
-  if (opll == NULL)
-    return NULL;
-
-  for (i = 0; i < 19 * 2; i++)
-    memcpy(&opll->patch[i],&null_patch,sizeof(OPLL_PATCH));
-
-  opll->mask = 0;
-
-  OPLL_reset (opll);
-  OPLL_reset_patch (opll, 0);
-
-  return opll;
-}
-
-
-void
-OPLL_delete (OPLL * opll)
-{
-  free (opll);
-}
-
-
-/* Reset patch datas by system default. */
-void
-OPLL_reset_patch (OPLL * opll, e_int32 type)
-{
-  e_int32 i;
-
-  for (i = 0; i < 19 * 2; i++)
-    OPLL_copyPatch (opll, i, &default_patch[type % OPLL_TONE_NUM][i]);
-}
-
-/* Reset whole of OPLL except patch datas. */
-void
-OPLL_reset (OPLL * opll)
-{
-  e_int32 i;
-
-  if (!opll)
-    return;
-
-  opll->adr = 0;
-  opll->out = 0;
-
-  opll->pm_phase = 0;
-  opll->am_phase = 0;
-
-  opll->noise_seed = 0xffff;
-  opll->mask = 0;
-
-  for (i = 0; i <18; i++)
-    OPLL_SLOT_reset(&opll->slot[i], i%2);
-
-  for (i = 0; i < 9; i++)
-  {
-    opll->key_status[i] = 0;
-    setPatch (opll, i, 0);
-  }
-
-  for (i = 0; i < 0x40; i++)
-    OPLL_writeReg (opll, i, 0);
-
-#ifndef EMU2413_COMPACTION
-  opll->realstep = (e_uint32) ((1 << 31) / rate);
-  opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72));
-  opll->oplltime = 0;
-  for (i = 0; i < 14; i++)
-    opll->pan[i] = 127; /* Maxim: pan is 0..255 */
-  opll->sprev[0] = opll->sprev[1] = 0;
-  opll->snext[0] = opll->snext[1] = 0;
-#endif
-}
-
-/* Force Refresh (When external program changes some parameters). */
-void
-OPLL_forceRefresh (OPLL * opll)
-{
-  e_int32 i;
-
-  if (opll == NULL)
-    return;
-
-  for (i = 0; i < 9; i++)
-    setPatch(opll,i,opll->patch_number[i]);
-
-  for (i = 0; i < 18; i++)
-  {
-    UPDATE_PG (&opll->slot[i]);
-    UPDATE_RKS (&opll->slot[i]);
-    UPDATE_TLL (&opll->slot[i]);
-    UPDATE_WF (&opll->slot[i]);
-    UPDATE_EG (&opll->slot[i]);
-  }
-}
-
-void
-OPLL_set_rate (OPLL * opll, e_uint32 r)
-{
-  if (opll->quality)
-    rate = 49716;
-  else
-    rate = r;
-  internal_refresh ();
-  rate = r;
-}
-
-void
-OPLL_set_quality (OPLL * opll, e_uint32 q)
-{
-  opll->quality = q;
-  OPLL_set_rate (opll, rate);
-}
-
-/*********************************************************
-
-                 Generate wave data
-
-*********************************************************/
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
-#if ( SLOT_AMP_BITS - PG_BITS ) > 0
-#define wave2_2pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
-#else
-#define wave2_2pi(e)  ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
-#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
-#define wave2_4pi(e)  (e)
-#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
-#define wave2_4pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
-#else
-#define wave2_4pi(e)  ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
-#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
-#define wave2_8pi(e)  (e)
-#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
-#define wave2_8pi(e)  ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
-#else
-#define wave2_8pi(e)  ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Update AM, PM unit */
-static void
-update_ampm (OPLL * opll)
-{
-  opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1);
-  opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1);
-  opll->lfo_am = amtable[HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS)];
-  opll->lfo_pm = pmtable[HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS)];
-}
-
-/* PG */
-INLINE static void
-calc_phase (OPLL_SLOT * slot, e_int32 lfo)
-{
-  if (slot->patch->PM)
-    slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS;
-  else
-    slot->phase += slot->dphase;
-
-  slot->phase &= (DP_WIDTH - 1);
-
-  slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS);
-}
-
-/* Update Noise unit */
-static void
-update_noise (OPLL * opll)
-{
-   if(opll->noise_seed&1) opll->noise_seed ^= 0x8003020;
-   opll->noise_seed >>= 1;
-}
-
-/* EG */
-static void
-calc_envelope (OPLL_SLOT * slot, e_int32 lfo)
-{
-#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
-
-  static e_uint32 SL[16] = {
-    S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
-    S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
-  };
-
-  e_uint32 egout;
-
-  switch (slot->eg_mode)
-  {
-  case ATTACK:
-    egout = AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)];
-    slot->eg_phase += slot->eg_dphase;
-    if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch->AR==15))
-    {
-      egout = 0;
-      slot->eg_phase = 0;
-      slot->eg_mode = DECAY;
-      UPDATE_EG (slot);
-    }
-    break;
-
-  case DECAY:
-    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
-    slot->eg_phase += slot->eg_dphase;
-    if (slot->eg_phase >= SL[slot->patch->SL])
-    {
-      if (slot->patch->EG)
-      {
-        slot->eg_phase = SL[slot->patch->SL];
-        slot->eg_mode = SUSHOLD;
-        UPDATE_EG (slot);
-      }
-      else
-      {
-        slot->eg_phase = SL[slot->patch->SL];
-        slot->eg_mode = SUSTINE;
-        UPDATE_EG (slot);
-      }
-    }
-    break;
-
-  case SUSHOLD:
-    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
-    if (slot->patch->EG == 0)
-    {
-      slot->eg_mode = SUSTINE;
-      UPDATE_EG (slot);
-    }
-    break;
-
-  case SUSTINE:
-  case RELEASE:
-    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
-    slot->eg_phase += slot->eg_dphase;
-    if (egout >= (1 << EG_BITS))
-    {
-      slot->eg_mode = FINISH;
-      egout = (1 << EG_BITS) - 1;
-    }
-    break;
-
-  case SETTLE:
-    egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
-    slot->eg_phase += slot->eg_dphase;
-    if (egout >= (1 << EG_BITS))
-    {
-      slot->eg_mode = ATTACK;
-      egout = (1 << EG_BITS) - 1;
-      UPDATE_EG(slot);
-    }
-    break;
-
-  case FINISH:
-    egout = (1 << EG_BITS) - 1;
-    break;
-
-  default:
-    egout = (1 << EG_BITS) - 1;
-    break;
-  }
-
-  if (slot->patch->AM)
-    egout = EG2DB (egout + slot->tll) + lfo;
-  else
-    egout = EG2DB (egout + slot->tll);
-
-  if (egout >= DB_MUTE)
-    egout = DB_MUTE - 1;
-
-  slot->egout = egout | 3;
-}
-
-/* CARRIOR */
-INLINE static e_int32
-calc_slot_car (OPLL_SLOT * slot, e_int32 fm)
-{
-  if (slot->egout >= (DB_MUTE - 1))
-  {
-    slot->output[0] = 0;
-  }
-  else
-  {
-    slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
-  }
-
-  slot->output[1] = (slot->output[1] + slot->output[0]) >> 1;
-  return slot->output[1];
-}
-
-/* MODULATOR */
-INLINE static e_int32
-calc_slot_mod (OPLL_SLOT * slot)
-{
-  e_int32 fm;
-
-  slot->output[1] = slot->output[0];
-
-  if (slot->egout >= (DB_MUTE - 1))
-  {
-    slot->output[0] = 0;
-  }
-  else if (slot->patch->FB != 0)
-  {
-    fm = wave2_4pi (slot->feedback) >> (7 - slot->patch->FB);
-    slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
-  }
-  else
-  {
-    slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
-  }
-
-  slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
-
-  return slot->feedback;
-
-}
-
-/* TOM */
-INLINE static e_int32
-calc_slot_tom (OPLL_SLOT * slot)
-{
-  if (slot->egout >= (DB_MUTE - 1))
-    return 0;
-
-  return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
-
-}
-
-/* SNARE */
-INLINE static e_int32
-calc_slot_snare (OPLL_SLOT * slot, e_uint32 noise)
-{
-  if(slot->egout>=(DB_MUTE-1))
-    return 0;
-
-  if(BIT(slot->pgout,7))
-    return DB2LIN_TABLE[(noise?DB_POS(0.0):DB_POS(15.0))+slot->egout];
-  else
-    return DB2LIN_TABLE[(noise?DB_NEG(0.0):DB_NEG(15.0))+slot->egout];
-}
-
-/*
-  TOP-CYM
- */
-INLINE static e_int32
-calc_slot_cym (OPLL_SLOT * slot, e_uint32 pgout_hh)
-{
-  e_uint32 dbout;
-
-  if (slot->egout >= (DB_MUTE - 1))
-    return 0;
-  else if(
-      /* the same as fmopl.c */
-      ((BIT(pgout_hh,PG_BITS-8)^BIT(pgout_hh,PG_BITS-1))|BIT(pgout_hh,PG_BITS-7)) ^
-      /* different from fmopl.c */
-     (BIT(slot->pgout,PG_BITS-7)&!BIT(slot->pgout,PG_BITS-5))
-    )
-    dbout = DB_NEG(3.0);
-  else
-    dbout = DB_POS(3.0);
-
-  return DB2LIN_TABLE[dbout + slot->egout];
-}
-
-/*
-  HI-HAT
-*/
-INLINE static e_int32
-calc_slot_hat (OPLL_SLOT *slot, e_int32 pgout_cym, e_uint32 noise)
-{
-  e_uint32 dbout;
-
-  if (slot->egout >= (DB_MUTE - 1))
-    return 0;
-  else if(
-      /* the same as fmopl.c */
-      ((BIT(slot->pgout,PG_BITS-8)^BIT(slot->pgout,PG_BITS-1))|BIT(slot->pgout,PG_BITS-7)) ^
-      /* different from fmopl.c */
-      (BIT(pgout_cym,PG_BITS-7)&!BIT(pgout_cym,PG_BITS-5))
-    )
-  {
-    if(noise)
-      dbout = DB_NEG(12.0);
-    else
-      dbout = DB_NEG(24.0);
-  }
-  else
-  {
-    if(noise)
-      dbout = DB_POS(12.0);
-    else
-      dbout = DB_POS(24.0);
-  }
-
-  return DB2LIN_TABLE[dbout + slot->egout];
-}
-
-INLINE static e_int16
-calc (OPLL * opll)
-{
-  e_int32 inst = 0, perc = 0, out = 0;
-  e_int32 i;
-
-  update_ampm (opll);
-  update_noise (opll);
-
-  for (i = 0; i < 18; i++)
-  {
-    calc_phase(&opll->slot[i],opll->lfo_pm);
-    calc_envelope(&opll->slot[i],opll->lfo_am);
-  }
-
-  for (i = 0; i < 6; i++)
-    if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
-      inst += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i)));
-
-  /* CH6 */
-  if (opll->patch_number[6] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
-      inst += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
-      perc += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
-  }
-
-  /* CH7 */
-  if (opll->patch_number[7] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR(opll,7)->eg_mode != FINISH))
-      inst += calc_slot_car (CAR(opll,7), calc_slot_mod(MOD(opll,7)));
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_HH) && (MOD(opll,7)->eg_mode != FINISH))
-      perc += calc_slot_hat (MOD(opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
-    if (!(opll->mask & OPLL_MASK_SD) && (CAR(opll,7)->eg_mode != FINISH))
-      perc -= calc_slot_snare (CAR(opll,7), opll->noise_seed&1);
-  }
-
-  /* CH8 */
-  if (opll->patch_number[8] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH(8)) && (CAR(opll,8)->eg_mode != FINISH))
-      inst += calc_slot_car (CAR(opll,8), calc_slot_mod (MOD(opll,8)));
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_TOM) && (MOD(opll,8)->eg_mode != FINISH))
-      perc += calc_slot_tom (MOD(opll,8));
-    if (!(opll->mask & OPLL_MASK_CYM) && (CAR(opll,8)->eg_mode != FINISH))
-      perc -= calc_slot_cym (CAR(opll,8), MOD(opll,7)->pgout);
-  }
-
-  out = inst + (perc << 1);
-  return (e_int16) out << 3;
-}
-
-#ifdef EMU2413_COMPACTION
-e_int16
-OPLL_calc (OPLL * opll)
-{
-  return calc (opll);
-}
-#else
-e_int16
-OPLL_calc (OPLL * opll)
-{
-  if (!opll->quality)
-    return calc (opll);
-
-  while (opll->realstep > opll->oplltime)
-  {
-    opll->oplltime += opll->opllstep;
-    opll->prev = opll->next;
-    opll->next = calc (opll);
-  }
-
-  opll->oplltime -= opll->realstep;
-  opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime)
-                          + (double) opll->prev * opll->oplltime) / opll->opllstep);
-
-  return (e_int16) opll->out;
-}
-#endif
-
-e_uint32
-OPLL_setMask (OPLL * opll, e_uint32 mask)
-{
-  e_uint32 ret;
-
-  if (opll)
-  {
-    ret = opll->mask;
-    opll->mask = mask;
-    return ret;
-  }
-  else
-    return 0;
-}
-
-e_uint32
-OPLL_toggleMask (OPLL * opll, e_uint32 mask)
-{
-  e_uint32 ret;
-
-  if (opll)
-  {
-    ret = opll->mask;
-    opll->mask ^= mask;
-    return ret;
-  }
-  else
-    return 0;
-}
-
-/****************************************************
-
-                       I/O Ctrl
-
-*****************************************************/
-
-void
-OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
-{
-  e_int32 i, v, ch;
-
-  data = data & 0xff;
-  reg = reg & 0x3f;
-  opll->reg[reg] = (e_uint8) data;
-
-  switch (reg)
-  {
-  case 0x00:
-    opll->patch[0].AM = (data >> 7) & 1;
-    opll->patch[0].PM = (data >> 6) & 1;
-    opll->patch[0].EG = (data >> 5) & 1;
-    opll->patch[0].KR = (data >> 4) & 1;
-    opll->patch[0].ML = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_PG (MOD(opll,i));
-        UPDATE_RKS (MOD(opll,i));
-        UPDATE_EG (MOD(opll,i));
-      }
-    }
-    break;
-
-  case 0x01:
-    opll->patch[1].AM = (data >> 7) & 1;
-    opll->patch[1].PM = (data >> 6) & 1;
-    opll->patch[1].EG = (data >> 5) & 1;
-    opll->patch[1].KR = (data >> 4) & 1;
-    opll->patch[1].ML = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_PG (CAR(opll,i));
-        UPDATE_RKS (CAR(opll,i));
-        UPDATE_EG (CAR(opll,i));
-      }
-    }
-    break;
-
-  case 0x02:
-    opll->patch[0].KL = (data >> 6) & 3;
-    opll->patch[0].TL = (data) & 63;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_TLL(MOD(opll,i));
-      }
-    }
-    break;
-
-  case 0x03:
-    opll->patch[1].KL = (data >> 6) & 3;
-    opll->patch[1].WF = (data >> 4) & 1;
-    opll->patch[0].WF = (data >> 3) & 1;
-    opll->patch[0].FB = (data) & 7;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_WF(MOD(opll,i));
-        UPDATE_WF(CAR(opll,i));
-      }
-    }
-    break;
-
-  case 0x04:
-    opll->patch[0].AR = (data >> 4) & 15;
-    opll->patch[0].DR = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_EG (MOD(opll,i));
-      }
-    }
-    break;
-
-  case 0x05:
-    opll->patch[1].AR = (data >> 4) & 15;
-    opll->patch[1].DR = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_EG(CAR(opll,i));
-      }
-    }
-    break;
-
-  case 0x06:
-    opll->patch[0].SL = (data >> 4) & 15;
-    opll->patch[0].RR = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_EG (MOD(opll,i));
-      }
-    }
-    break;
-
-  case 0x07:
-    opll->patch[1].SL = (data >> 4) & 15;
-    opll->patch[1].RR = (data) & 15;
-    for (i = 0; i < 9; i++)
-    {
-      if (opll->patch_number[i] == 0)
-      {
-        UPDATE_EG (CAR(opll,i));
-      }
-    }
-    break;
-
-  case 0x0e:
-    update_rhythm_mode (opll);
-    if (data & 32)
-    {
-      if (data & 0x10)
-        keyOn_BD (opll);
-      else
-        keyOff_BD (opll);
-      if (data & 0x8)
-        keyOn_SD (opll);
-      else
-        keyOff_SD (opll);
-      if (data & 0x4)
-        keyOn_TOM (opll);
-      else
-        keyOff_TOM (opll);
-      if (data & 0x2)
-        keyOn_CYM (opll);
-      else
-        keyOff_CYM (opll);
-      if (data & 0x1)
-        keyOn_HH (opll);
-      else
-        keyOff_HH (opll);
-    }
-    update_key_status (opll);
-
-    UPDATE_ALL (MOD(opll,6));
-    UPDATE_ALL (CAR(opll,6));
-    UPDATE_ALL (MOD(opll,7));
-    UPDATE_ALL (CAR(opll,7));
-    UPDATE_ALL (MOD(opll,8));
-    UPDATE_ALL (CAR(opll,8));
-
-    break;
-
-  case 0x0f:
-    break;
-
-  case 0x10:
-  case 0x11:
-  case 0x12:
-  case 0x13:
-  case 0x14:
-  case 0x15:
-  case 0x16:
-  case 0x17:
-  case 0x18:
-    ch = reg - 0x10;
-    setFnumber (opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));
-    UPDATE_ALL (MOD(opll,ch));
-    UPDATE_ALL (CAR(opll,ch));
-    break;
-
-  case 0x20:
-  case 0x21:
-  case 0x22:
-  case 0x23:
-  case 0x24:
-  case 0x25:
-  case 0x26:
-  case 0x27:
-  case 0x28:
-    ch = reg - 0x20;
-    setFnumber (opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);
-    setBlock (opll, ch, (data >> 1) & 7);
-    setSustine (opll, ch, (data >> 5) & 1);
-    if (data & 0x10)
-      keyOn (opll, ch);
-    else
-      keyOff (opll, ch);
-    UPDATE_ALL (MOD(opll,ch));
-    UPDATE_ALL (CAR(opll,ch));
-    update_key_status (opll);
-    update_rhythm_mode (opll);
-    break;
-
-  case 0x30:
-  case 0x31:
-  case 0x32:
-  case 0x33:
-  case 0x34:
-  case 0x35:
-  case 0x36:
-  case 0x37:
-  case 0x38:
-    i = (data >> 4) & 15;
-    v = data & 15;
-    if ((opll->reg[0x0e] & 32) && (reg >= 0x36))
-    {
-      switch (reg)
-      {
-      case 0x37:
-        setSlotVolume (MOD(opll,7), i << 2);
-        break;
-      case 0x38:
-        setSlotVolume (MOD(opll,8), i << 2);
-        break;
-      default:
-        break;
-      }
-    }
-    else
-    {
-      setPatch (opll, reg - 0x30, i);
-    }
-    setVolume (opll, reg - 0x30, v << 2);
-    UPDATE_ALL (MOD(opll,reg - 0x30));
-    UPDATE_ALL (CAR(opll,reg - 0x30));
-    break;
-
-  default:
-    break;
-
-  }
-}
-
-void
-OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val)
-{
-  if (adr & 1)
-    OPLL_writeReg (opll, opll->adr, val);
-  else
-    opll->adr = val;
-}
-
-#ifndef EMU2413_COMPACTION
-/* STEREO MODE (OPT) */
-void
-OPLL_set_pan (OPLL * opll, e_uint32 ch, e_uint32 pan)
-{
-  opll->pan[ch & 15] = pan & 255; /* Maxim: pan is 0..255 */
-}
-
-static void
-calc_stereo (OPLL * opll, e_int32 out[2])
-{
-  /* Maxim: changed panning to be 0..255, 127 is centre */
-  e_int32 l=0,r=0;
-//  e_int32 b[4] = { 0, 0, 0, 0 };        /* Ignore, Right, Left, Center */
-//  e_int32 r[4] = { 0, 0, 0, 0 };        /* Ignore, Right, Left, Center */
-  e_int32 i;
-  e_int32 channel;
-
-  update_ampm (opll);
-  update_noise (opll);
-
-  for(i=0;i<18;i++)
-  {
-    calc_phase(&opll->slot[i],opll->lfo_pm);
-    calc_envelope(&opll->slot[i],opll->lfo_am);
-  }
-
-  for (i = 0; i < 6; i++)
-    if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
-    {
-      channel = calc_slot_car (CAR(opll,i), calc_slot_mod (MOD(opll,i)));
-      if ( opll->pan[i] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[i]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[i]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-
-
-  if (opll->patch_number[6] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
-    {
-      channel = calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
-      if ( opll->pan[6] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[6]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[6]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-
-    }
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
-    {
-      channel = calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
-      if ( opll->pan[9] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[9]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[9]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-  }
-
-  if (opll->patch_number[7] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR (opll,7)->eg_mode != FINISH))
-    {
-      channel = calc_slot_car (CAR (opll,7), calc_slot_mod (MOD (opll,7)));
-      if ( opll->pan[7] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[7]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[7]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_HH) && (MOD (opll,7)->eg_mode != FINISH))
-    {
-      channel = calc_slot_hat (MOD (opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
-      if ( opll->pan[10] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[10]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[10]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-    if (!(opll->mask & OPLL_MASK_SD) && (CAR (opll,7)->eg_mode != FINISH))
-    {
-      channel = -calc_slot_snare (CAR (opll,7), opll->noise_seed&1); // this one is negated
-      if ( opll->pan[11] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[11]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[11]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-  }
-
-  if (opll->patch_number[8] <= 15)
-  {
-    if (!(opll->mask & OPLL_MASK_CH (8)) && (CAR (opll,8)->eg_mode != FINISH))
-    {
-      channel = calc_slot_car (CAR (opll,8), calc_slot_mod (MOD (opll,8)));
-      if ( opll->pan[8] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[8]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[8]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-  }
-  else
-  {
-    if (!(opll->mask & OPLL_MASK_TOM) && (MOD (opll,8)->eg_mode != FINISH))
-    {
-      channel = calc_slot_tom (MOD (opll,8));
-      if ( opll->pan[12] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[12]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[12]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-    if (!(opll->mask & OPLL_MASK_CYM) && (CAR (opll,8)->eg_mode != FINISH))
-    {
-      channel = -calc_slot_cym (CAR (opll,8), MOD(opll,7)->pgout); // negated
-      if ( opll->pan[13] == 127 )
-      {
-        l += channel;
-        r += channel;
-      }
-      else
-      {
-        l += channel * (255-opll->pan[13]) / 127; // 0 -> 2, 127 -> 1, 255 -> 0 (nearly)
-        r += channel * (    opll->pan[13]) / 127; // 255 -> 2, 127 -> 1, 0 -> 0 (nearly)
-      }
-    }
-  }
-/*
-  out[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) <<3;
-  out[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) <<3;
-  */
-  out[0] = l << 3;
-  out[1] = r << 3;
-}
-
-void
-OPLL_calc_stereo (OPLL * opll, e_int32 out[2])
-{
-  if (!opll->quality)
-  {
-    calc_stereo (opll, out);
-    return;
-  }
-
-  while (opll->realstep > opll->oplltime)
-  {
-    opll->oplltime += opll->opllstep;
-    opll->sprev[0] = opll->snext[0];
-    opll->sprev[1] = opll->snext[1];
-    calc_stereo (opll, opll->snext);
-  }
-
-  opll->oplltime -= opll->realstep;
-  out[0] = (e_int16) (((double) opll->snext[0] * (opll->opllstep - opll->oplltime)
-                       + (double) opll->sprev[0] * opll->oplltime) / opll->opllstep);
-  out[1] = (e_int16) (((double) opll->snext[1] * (opll->opllstep - opll->oplltime)
-                       + (double) opll->sprev[1] * opll->oplltime) / opll->opllstep);
-}
-#endif /* EMU2413_COMPACTION */
-
-// Ym2413_Emu
-#include "Ym2413_Emu.h"
-
-#include <assert.h>
-
-static int use_count = 0;
-
-Ym2413_Emu::~Ym2413_Emu()
-{
-	if ( opll )
-	{
-		use_count--;
-		OPLL_delete( opll );
-	}
-}
-
-Ym2413_Emu::Ym2413_Emu()
-{
-	opll = 0;
-}
-
-int Ym2413_Emu::set_rate( double sample_rate, double clock_rate )
-{
-	if ( opll )
-	{
-		OPLL_delete( opll );
-		opll = 0;
-		use_count--;
-	}
-
-	// Only one YM2413 may be used at a time (emu2413 uses lots of global data)
-	assert( use_count == 0 );
-	use_count++;
-
-	opll = OPLL_new ((int) clock_rate, (int) sample_rate);
-	if ( !opll )
-		return 1;
-
-	reset();
-	return 0;
-}
-
-void Ym2413_Emu::reset()
-{
-	OPLL_reset( opll );
-	OPLL_reset_patch( opll, 0 );
-	OPLL_setMask( opll, 0 );
-	OPLL_set_quality( opll, 0 );
-}
-
-void Ym2413_Emu::write( int addr, int data )
-{
-	OPLL_writeReg( opll, addr, data );
-}
-
-void Ym2413_Emu::mute_voices( int mask )
-{
-	OPLL_setMask( opll, mask );
-}
-
-void Ym2413_Emu::run( int pair_count, sample_t* out )
-{
-	while ( pair_count-- )
-	{
-		int s = OPLL_calc( opll );
-		out [0] = s;
-		out [1] = s;
-		out += 2;
-	}
-}
-
diff --git a/src/console/Ym2612_Emu.cc b/src/console/Ym2612_Emu.cc
new file mode 100644
index 000000000000..cfacd2fe1234
--- /dev/null
+++ b/src/console/Ym2612_Emu.cc
@@ -0,0 +1,1319 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+// Based on Gens 2.10 ym2612.c
+
+#include "Ym2612_Emu.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <math.h>
+
+/* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */
+/* Copyright (C) 2004-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+// This is mostly the original source in its C style and all.
+//
+// Somewhat optimized and simplified. Uses a template to generate the many
+// variants of Update_Chan. Rewrote header file. In need of full rewrite by
+// someone more familiar with FM sound and the YM2612. Has some inaccuracies
+// compared to the Sega Genesis sound, particularly being mixed at such a
+// high sample accuracy (the Genesis sounds like it has only 8 bit samples).
+// - Shay
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+const int output_bits = 14;
+
+struct slot_t
+{
+	const int *DT;  // parametre detune
+	int MUL;    // parametre "multiple de frequence"
+	int TL;     // Total Level = volume lorsque l'enveloppe est au plus haut
+	int TLL;    // Total Level ajusted
+	int SLL;    // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
+	int KSR_S;  // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
+	int KSR;    // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
+				// sur les differents parametres de l'enveloppe comme l'attaque, le decay ...  comme dans la realite !
+	int SEG;    // Type enveloppe SSG
+	int env_xor;
+	int env_max;
+
+	const int *AR;  // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
+	const int *DR;  // Decay Rate (table pointeur) = Taux pour la regression (DR[KSR])
+	const int *SR;  // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
+	const int *RR;  // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
+	int Fcnt;   // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
+	int Finc;   // frequency step = pas d'incrementation du compteur-frequence
+				// plus le pas est grand, plus la frequence est aïgu (ou haute)
+	int Ecurp;  // Envelope current phase = cette variable permet de savoir dans quelle phase
+				// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
+				// en fonction de la valeur de cette variable, on va appeler une fonction permettant
+				// de mettre à jour l'enveloppe courante.
+	int Ecnt;   // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
+	int Einc;   // Envelope step courant
+	int Ecmp;   // Envelope counter limite pour la prochaine phase
+	int EincA;  // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
+				// cette valeur est egal à AR[KSR]
+	int EincD;  // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
+				// cette valeur est egal à DR[KSR]
+	int EincS;  // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
+				// cette valeur est egal à SR[KSR]
+	int EincR;  // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
+				// cette valeur est egal à RR[KSR]
+	int *OUTp;  // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
+				// d'un autre ou carrement à la sortie de la voie
+	int INd;    // input data of the slot = donnees en entree du slot
+	int ChgEnM; // Change envelop mask.
+	int AMS;    // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
+	int AMSon;  // AMS enable flag = drapeau d'activation de l'AMS
+};
+
+struct channel_t
+{
+	int S0_OUT[4];          // anciennes sorties slot 0 (pour le feed back)
+	int LEFT;               // LEFT enable flag
+	int RIGHT;              // RIGHT enable flag
+	int ALGO;               // Algorythm = determine les connections entre les operateurs
+	int FB;                 // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
+	int FMS;                // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
+	int AMS;                // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
+	int FNUM[4];            // hauteur frequence de la voie (+ 3 pour le mode special)
+	int FOCT[4];            // octave de la voie (+ 3 pour le mode special)
+	int KC[4];              // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
+	slot_t SLOT[4]; // four slot.operators = les 4 slots de la voie
+	int FFlag;              // Frequency step recalculation flag
+};
+
+struct state_t
+{
+	int TimerBase;      // TimerBase calculation
+	int Status;         // YM2612 Status (timer overflow)
+	int TimerA;         // timerA limit = valeur jusqu'à laquelle le timer A doit compter
+	int TimerAL;
+	int TimerAcnt;      // timerA counter = valeur courante du Timer A
+	int TimerB;         // timerB limit = valeur jusqu'à laquelle le timer B doit compter
+	int TimerBL;
+	int TimerBcnt;      // timerB counter = valeur courante du Timer B
+	int Mode;           // Mode actuel des voie 3 et 6 (normal / special)
+	int DAC;            // DAC enabled flag
+	channel_t CHANNEL[Ym2612_Emu::channel_count];   // Les 6 voies du YM2612
+	int REG[2][0x100];  // Sauvegardes des valeurs de tout les registres, c'est facultatif
+						// cela nous rend le debuggage plus facile
+};
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#define ATTACK    0
+#define DECAY     1
+#define SUBSTAIN  2
+#define RELEASE   3
+
+// SIN_LBITS <= 16
+// LFO_HBITS <= 16
+// (SIN_LBITS + SIN_HBITS) <= 26
+// (ENV_LBITS + ENV_HBITS) <= 28
+// (LFO_LBITS + LFO_HBITS) <= 28
+
+#define SIN_HBITS      12                               // Sinus phase counter int part
+#define SIN_LBITS      (26 - SIN_HBITS)                 // Sinus phase counter float part (best setting)
+
+#if (SIN_LBITS > 16)
+#define SIN_LBITS      16                               // Can't be greater than 16 bits
+#endif
+
+#define ENV_HBITS      12                               // Env phase counter int part
+#define ENV_LBITS      (28 - ENV_HBITS)                 // Env phase counter float part (best setting)
+
+#define LFO_HBITS      10                               // LFO phase counter int part
+#define LFO_LBITS      (28 - LFO_HBITS)                 // LFO phase counter float part (best setting)
+
+#define SIN_LENGHT     (1 << SIN_HBITS)
+#define ENV_LENGHT     (1 << ENV_HBITS)
+#define LFO_LENGHT     (1 << LFO_HBITS)
+
+#define TL_LENGHT      (ENV_LENGHT * 3)                 // Env + TL scaling + LFO
+
+#define SIN_MASK       (SIN_LENGHT - 1)
+#define ENV_MASK       (ENV_LENGHT - 1)
+#define LFO_MASK       (LFO_LENGHT - 1)
+
+#define ENV_STEP       (96.0 / ENV_LENGHT)              // ENV_MAX = 96 dB
+
+#define ENV_ATTACK     ((ENV_LENGHT * 0) << ENV_LBITS)
+#define ENV_DECAY      ((ENV_LENGHT * 1) << ENV_LBITS)
+#define ENV_END        ((ENV_LENGHT * 2) << ENV_LBITS)
+
+#define MAX_OUT_BITS   (SIN_HBITS + SIN_LBITS + 2)      // Modulation = -4 <--> +4
+#define MAX_OUT        ((1 << MAX_OUT_BITS) - 1)
+
+#define PG_CUT_OFF     ((int) (78.0 / ENV_STEP))
+#define ENV_CUT_OFF    ((int) (68.0 / ENV_STEP))
+
+#define AR_RATE        399128
+#define DR_RATE        5514396
+
+//#define AR_RATE        426136
+//#define DR_RATE        (AR_RATE * 12)
+
+#define LFO_FMS_LBITS  9    // FIXED (LFO_FMS_BASE gives somethink as 1)
+#define LFO_FMS_BASE   ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
+
+#define S0             0    // Stupid typo of the YM2612
+#define S1             2
+#define S2             1
+#define S3             3
+
+inline void set_seg( slot_t& s, int seg )
+{
+	s.env_xor = 0;
+	s.env_max = INT_MAX;
+	s.SEG = seg;
+	if ( seg & 4 )
+	{
+		s.env_xor = ENV_MASK;
+		s.env_max = ENV_MASK;
+	}
+}
+
+struct tables_t
+{
+	short SIN_TAB [SIN_LENGHT];                 // SINUS TABLE (offset into TL TABLE)
+	int LFOcnt;         // LFO counter = compteur-frequence pour le LFO
+	int LFOinc;         // LFO step counter = pas d'incrementation du compteur-frequence du LFO
+						// plus le pas est grand, plus la frequence est grande
+	unsigned int AR_TAB [128];                  // Attack rate table
+	unsigned int DR_TAB [96];                   // Decay rate table
+	unsigned int DT_TAB [8] [32];               // Detune table
+	unsigned int SL_TAB [16];                   // Substain level table
+	unsigned int NULL_RATE [32];                // Table for nullptr rate
+	int LFO_INC_TAB [8];                        // LFO step table
+
+	short ENV_TAB [2 * ENV_LENGHT + 8];         // ENV CURVE TABLE (attack & decay)
+
+	short LFO_ENV_TAB [LFO_LENGHT];             // LFO AMS TABLE (adjusted for 11.8 dB)
+	short LFO_FREQ_TAB [LFO_LENGHT];            // LFO FMS TABLE
+	int TL_TAB [TL_LENGHT * 2];                 // TOTAL LEVEL TABLE (positif and minus)
+	unsigned int DECAY_TO_ATTACK [ENV_LENGHT];  // Conversion from decay to attack phase
+	unsigned int FINC_TAB [2048];               // Frequency step table
+};
+
+static const unsigned char DT_DEF_TAB [4 * 32] =
+{
+// FD = 0
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// FD = 1
+  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+  2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
+
+// FD = 2
+  1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
+  5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
+
+// FD = 3
+  2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
+  8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
+};
+
+static const unsigned char FKEY_TAB [16] =
+{
+	0, 0, 0, 0,
+	0, 0, 0, 1,
+	2, 3, 3, 3,
+	3, 3, 3, 3
+};
+
+static const unsigned char LFO_AMS_TAB [4] =
+{
+	31, 4, 1, 0
+};
+
+static const unsigned char LFO_FMS_TAB [8] =
+{
+	LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
+	LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
+	LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
+	LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
+};
+
+inline void YM2612_Special_Update() { }
+
+struct Ym2612_Impl
+{
+	enum { channel_count = Ym2612_Emu::channel_count };
+
+	state_t YM2612;
+	int mute_mask;
+	tables_t g;
+
+	void KEY_ON( channel_t&, int );
+	void KEY_OFF( channel_t&, int );
+	int SLOT_SET( int, int );
+	int CHANNEL_SET( int, int );
+	int YM_SET( int, int );
+
+	void set_rate( double sample_rate, double clock_factor );
+	void reset();
+	void write0( int addr, int data );
+	void write1( int addr, int data );
+	void run_timer( int );
+	void run( int pair_count, Ym2612_Emu::sample_t* );
+};
+
+void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl)
+{
+	slot_t *SL = &(ch.SLOT [nsl]);  // on recupere le bon pointeur de slot
+
+	if (SL->Ecurp == RELEASE)       // la touche est-elle rel'chee ?
+	{
+		SL->Fcnt = 0;
+
+		// Fix Ecco 2 splash sound
+
+		SL->Ecnt = (g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
+		SL->ChgEnM = ~0;
+
+//      SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
+//      SL->Ecnt = 0;
+
+		SL->Einc = SL->EincA;
+		SL->Ecmp = ENV_DECAY;
+		SL->Ecurp = ATTACK;
+	}
+}
+
+
+void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl)
+{
+	slot_t *SL = &(ch.SLOT [nsl]);  // on recupere le bon pointeur de slot
+
+	if (SL->Ecurp != RELEASE)       // la touche est-elle appuyee ?
+	{
+		if (SL->Ecnt < ENV_DECAY)   // attack phase ?
+		{
+			SL->Ecnt = (g.ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
+		}
+
+		SL->Einc = SL->EincR;
+		SL->Ecmp = ENV_END;
+		SL->Ecurp = RELEASE;
+	}
+}
+
+
+int Ym2612_Impl::SLOT_SET( int Adr, int data )
+{
+	int nch = Adr & 3;
+	if ( nch == 3 )
+		return 1;
+
+	channel_t& ch = YM2612.CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
+	slot_t& sl = ch.SLOT [(Adr >> 2) & 3];
+
+	switch ( Adr & 0xF0 )
+	{
+		case 0x30:
+			if ( (sl.MUL = (data & 0x0F)) != 0 ) sl.MUL <<= 1;
+			else sl.MUL = 1;
+
+			sl.DT = (int*) g.DT_TAB [(data >> 4) & 7];
+
+			ch.SLOT [0].Finc = -1;
+
+			break;
+
+		case 0x40:
+			sl.TL = data & 0x7F;
+
+			// SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
+			YM2612_Special_Update();
+
+#if ((ENV_HBITS - 7) < 0)
+			sl.TLL = sl.TL >> (7 - ENV_HBITS);
+#else
+			sl.TLL = sl.TL << (ENV_HBITS - 7);
+#endif
+
+			break;
+
+		case 0x50:
+			sl.KSR_S = 3 - (data >> 6);
+
+			ch.SLOT [0].Finc = -1;
+
+			if (data &= 0x1F) sl.AR = (int*) &g.AR_TAB [data << 1];
+			else sl.AR = (int*) &g.NULL_RATE [0];
+
+			sl.EincA = sl.AR [sl.KSR];
+			if (sl.Ecurp == ATTACK) sl.Einc = sl.EincA;
+			break;
+
+		case 0x60:
+			if ( (sl.AMSon = (data & 0x80)) != 0 ) sl.AMS = ch.AMS;
+			else sl.AMS = 31;
+
+			if (data &= 0x1F) sl.DR = (int*) &g.DR_TAB [data << 1];
+			else sl.DR = (int*) &g.NULL_RATE [0];
+
+			sl.EincD = sl.DR [sl.KSR];
+			if (sl.Ecurp == DECAY) sl.Einc = sl.EincD;
+			break;
+
+		case 0x70:
+			if (data &= 0x1F) sl.SR = (int*) &g.DR_TAB [data << 1];
+			else sl.SR = (int*) &g.NULL_RATE [0];
+
+			sl.EincS = sl.SR [sl.KSR];
+			if ((sl.Ecurp == SUBSTAIN) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincS;
+			break;
+
+		case 0x80:
+			sl.SLL = g.SL_TAB [data >> 4];
+
+			sl.RR = (int*) &g.DR_TAB [((data & 0xF) << 2) + 2];
+
+			sl.EincR = sl.RR [sl.KSR];
+			if ((sl.Ecurp == RELEASE) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincR;
+			break;
+
+		case 0x90:
+			// SSG-EG envelope shapes :
+			/*
+			   E  At Al H
+
+			   1  0  0  0  \\\\
+			   1  0  0  1  \___
+			   1  0  1  0  \/\/
+			   1  0  1  1  \
+			   1  1  0  0  ////
+			   1  1  0  1  /
+			   1  1  1  0  /\/\
+			   1  1  1  1  /___
+
+			   E  = SSG-EG enable
+			   At = Start negate
+			   Al = Altern
+			   H  = Hold */
+
+			set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
+			break;
+	}
+
+	return 0;
+}
+
+
+int Ym2612_Impl::CHANNEL_SET( int Adr, int data )
+{
+	int num = Adr & 3;
+	if ( num == 3 )
+		return 1;
+
+	channel_t& ch = YM2612.CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
+
+	switch ( Adr & 0xFC )
+	{
+		case 0xA0:
+			YM2612_Special_Update();
+
+			ch.FNUM [0] = (ch.FNUM [0] & 0x700) + data;
+			ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
+
+			ch.SLOT [0].Finc = -1;
+			break;
+
+		case 0xA4:
+			YM2612_Special_Update();
+
+			ch.FNUM [0] = (ch.FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
+			ch.FOCT [0] = (data & 0x38) >> 3;
+			ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
+
+			ch.SLOT [0].Finc = -1;
+			break;
+
+		case 0xA8:
+			if ( Adr < 0x100 )
+			{
+				num++;
+
+				YM2612_Special_Update();
+
+				YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x700) + data;
+				YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
+						FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
+
+				YM2612.CHANNEL [2].SLOT [0].Finc = -1;
+			}
+			break;
+
+		case 0xAC:
+			if ( Adr < 0x100 )
+			{
+				num++;
+
+				YM2612_Special_Update();
+
+				YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
+				YM2612.CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
+				YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
+						FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
+
+				YM2612.CHANNEL [2].SLOT [0].Finc = -1;
+			}
+			break;
+
+		case 0xB0:
+			if ( ch.ALGO != (data & 7) )
+			{
+				// Fix VectorMan 2 heli sound (level 1)
+				YM2612_Special_Update();
+
+				ch.ALGO = data & 7;
+
+				ch.SLOT [0].ChgEnM = 0;
+				ch.SLOT [1].ChgEnM = 0;
+				ch.SLOT [2].ChgEnM = 0;
+				ch.SLOT [3].ChgEnM = 0;
+			}
+
+			ch.FB = 9 - ((data >> 3) & 7);                              // Real thing ?
+
+//          if (ch.FB = ((data >> 3) & 7)) ch.FB = 9 - ch.FB;       // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
+//          else ch.FB = 31;
+			break;
+
+		case 0xB4: {
+			YM2612_Special_Update();
+
+			ch.LEFT = 0 - ((data >> 7) & 1);
+			ch.RIGHT = 0 - ((data >> 6) & 1);
+
+			ch.AMS = LFO_AMS_TAB [(data >> 4) & 3];
+			ch.FMS = LFO_FMS_TAB [data & 7];
+
+			for ( int i = 0; i < 4; i++ )
+			{
+				slot_t& sl = ch.SLOT [i];
+				sl.AMS = (sl.AMSon ? ch.AMS : 31);
+			}
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+int Ym2612_Impl::YM_SET(int Adr, int data)
+{
+	switch ( Adr )
+	{
+		case 0x22:
+			if (data & 8) // LFO enable
+			{
+				// Cool Spot music 1, LFO modified severals time which
+				// distord the sound, have to check that on a real genesis...
+
+				g.LFOinc = g.LFO_INC_TAB [data & 7];
+			}
+			else
+			{
+				g.LFOinc = g.LFOcnt = 0;
+			}
+			break;
+
+		case 0x24:
+			YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2);
+
+			if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
+			{
+				YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
+			}
+			break;
+
+		case 0x25:
+			YM2612.TimerA = (YM2612.TimerA & 0x3FC) | (data & 3);
+
+			if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
+			{
+				YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
+			}
+			break;
+
+		case 0x26:
+			YM2612.TimerB = data;
+
+			if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12))
+			{
+				YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12);
+			}
+			break;
+
+		case 0x27:
+			// Parametre divers
+			// b7 = CSM MODE
+			// b6 = 3 slot mode
+			// b5 = reset b
+			// b4 = reset a
+			// b3 = timer enable b
+			// b2 = timer enable a
+			// b1 = load b
+			// b0 = load a
+
+			if ((data ^ YM2612.Mode) & 0x40)
+			{
+				// We changed the channel 2 mode, so recalculate phase step
+				// This fix the punch sound in Street of Rage 2
+
+				YM2612_Special_Update();
+
+				YM2612.CHANNEL [2].SLOT [0].Finc = -1;      // recalculate phase step
+			}
+
+//          if ((data & 2) && (YM2612.Status & 2)) YM2612.TimerBcnt = YM2612.TimerBL;
+//          if ((data & 1) && (YM2612.Status & 1)) YM2612.TimerAcnt = YM2612.TimerAL;
+
+//          YM2612.Status &= (~data >> 4);                  // Reset du Status au cas ou c'est demande
+			YM2612.Status &= (~data >> 4) & (data >> 2);    // Reset Status
+
+			YM2612.Mode = data;
+			break;
+
+		case 0x28: {
+			int nch = data & 3;
+			if ( nch == 3 )
+				return 1;
+			if ( data & 4 )
+				nch += 3;
+			channel_t& ch = YM2612.CHANNEL [nch];
+
+			YM2612_Special_Update();
+
+			if (data & 0x10) KEY_ON(ch, S0);    // On appuie sur la touche pour le slot 1
+			else KEY_OFF(ch, S0);               // On rel'che la touche pour le slot 1
+			if (data & 0x20) KEY_ON(ch, S1);    // On appuie sur la touche pour le slot 3
+			else KEY_OFF(ch, S1);               // On rel'che la touche pour le slot 3
+			if (data & 0x40) KEY_ON(ch, S2);    // On appuie sur la touche pour le slot 2
+			else KEY_OFF(ch, S2);               // On rel'che la touche pour le slot 2
+			if (data & 0x80) KEY_ON(ch, S3);    // On appuie sur la touche pour le slot 4
+			else KEY_OFF(ch, S3);               // On rel'che la touche pour le slot 4
+			break;
+		}
+
+		case 0x2B:
+			if (YM2612.DAC ^ (data & 0x80)) YM2612_Special_Update();
+
+			YM2612.DAC = data & 0x80;   // activation/desactivation du DAC
+			break;
+	}
+
+	return 0;
+}
+
+void Ym2612_Impl::set_rate( double sample_rate, double clock_rate )
+{
+	assert( sample_rate );
+	assert( clock_rate > sample_rate );
+
+	int i;
+
+	// 144 = 12 * (prescale * 2) = 12 * 6 * 2
+	// prescale set to 6 by default
+
+	double Frequence = clock_rate / sample_rate / 144.0;
+	if ( fabs( Frequence - 1.0 ) < 0.0000001 )
+		Frequence = 1.0;
+	YM2612.TimerBase = int (Frequence * 4096.0);
+
+	// Tableau TL :
+	// [0     -  4095] = +output  [4095  - ...] = +output overflow (fill with 0)
+	// [12288 - 16383] = -output  [16384 - ...] = -output overflow (fill with 0)
+
+	for(i = 0; i < TL_LENGHT; i++)
+	{
+		if (i >= PG_CUT_OFF)    // YM2612 cut off sound after 78 dB (14 bits output ?)
+		{
+			g.TL_TAB [TL_LENGHT + i] = g.TL_TAB [i] = 0;
+		}
+		else
+		{
+			double x = MAX_OUT;                         // Max output
+			x /= pow( 10.0, (ENV_STEP * i) / 20.0 );    // Decibel -> Voltage
+
+			g.TL_TAB [i] = (int) x;
+			g.TL_TAB [TL_LENGHT + i] = -g.TL_TAB [i];
+		}
+	}
+
+	// Tableau SIN :
+	// g.SIN_TAB [x] [y] = sin(x) * y;
+	// x = phase and y = volume
+
+	g.SIN_TAB [0] = g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
+
+	for(i = 1; i <= SIN_LENGHT / 4; i++)
+	{
+		double x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT));    // Sinus
+		x = 20 * log10(1 / x);                                      // convert to dB
+
+		int j = (int) (x / ENV_STEP);                       // Get TL range
+
+		if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
+
+		g.SIN_TAB [i] = g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
+		g.SIN_TAB [(SIN_LENGHT / 2) + i] = g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
+	}
+
+	// Tableau LFO (LFO wav) :
+
+	for(i = 0; i < LFO_LENGHT; i++)
+	{
+		double x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));    // Sinus
+		x += 1.0;
+		x /= 2.0;                   // positive only
+		x *= 11.8 / ENV_STEP;       // ajusted to MAX enveloppe modulation
+
+		g.LFO_ENV_TAB [i] = (int) x;
+
+		x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));   // Sinus
+		x *= (double) ((1 << (LFO_HBITS - 1)) - 1);
+
+		g.LFO_FREQ_TAB [i] = (int) x;
+
+	}
+
+	// Tableau Enveloppe :
+	// g.ENV_TAB [0] -> g.ENV_TAB [ENV_LENGHT - 1]              = attack curve
+	// g.ENV_TAB [ENV_LENGHT] -> g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
+
+	for(i = 0; i < ENV_LENGHT; i++)
+	{
+		// Attack curve (x^8 - music level 2 Vectorman 2)
+		double x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);
+		x *= ENV_LENGHT;
+
+		g.ENV_TAB [i] = (int) x;
+
+		// Decay curve (just linear)
+		x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);
+		x *= ENV_LENGHT;
+
+		g.ENV_TAB [ENV_LENGHT + i] = (int) x;
+	}
+	for ( i = 0; i < 8; i++ )
+		g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
+
+	g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1;      // for the stopped state
+
+	// Tableau pour la conversion Attack -> Decay and Decay -> Attack
+
+	int j = ENV_LENGHT - 1;
+	for ( i = 0; i < ENV_LENGHT; i++ )
+	{
+		while ( j && g.ENV_TAB [j] < i )
+			j--;
+
+		g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
+	}
+
+	// Tableau pour le Substain Level
+
+	for(i = 0; i < 15; i++)
+	{
+		double x = i * 3;           // 3 and not 6 (Mickey Mania first music for test)
+		x /= ENV_STEP;
+
+		g.SL_TAB [i] = ((int) x << ENV_LBITS) + ENV_DECAY;
+	}
+
+	g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
+
+	// Tableau Frequency Step
+
+	for(i = 0; i < 2048; i++)
+	{
+		double x = (double) (i) * Frequence;
+
+#if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)
+		x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));
+#else
+		x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));
+#endif
+
+		x /= 2.0;   // because MUL = value * 2
+
+		g.FINC_TAB [i] = (unsigned int) x;
+	}
+
+	// Tableaux Attack & Decay Rate
+
+	for(i = 0; i < 4; i++)
+	{
+		g.AR_TAB [i] = 0;
+		g.DR_TAB [i] = 0;
+	}
+
+	for(i = 0; i < 60; i++)
+	{
+		double x = Frequence;
+
+		x *= 1.0 + ((i & 3) * 0.25);                    // bits 0-1 : x1.00, x1.25, x1.50, x1.75
+		x *= (double) (1 << ((i >> 2)));                // bits 2-5 : shift bits (x2^0 - x2^15)
+		x *= (double) (ENV_LENGHT << ENV_LBITS);        // on ajuste pour le tableau g.ENV_TAB
+
+		g.AR_TAB [i + 4] = (unsigned int) (x / AR_RATE);
+		g.DR_TAB [i + 4] = (unsigned int) (x / DR_RATE);
+	}
+
+	for(i = 64; i < 96; i++)
+	{
+		g.AR_TAB [i] = g.AR_TAB [63];
+		g.DR_TAB [i] = g.DR_TAB [63];
+
+		g.NULL_RATE [i - 64] = 0;
+	}
+
+	for ( i = 96; i < 128; i++ )
+		g.AR_TAB [i] = 0;
+
+	// Tableau Detune
+
+	for(i = 0; i < 4; i++)
+	{
+		for (int j = 0; j < 32; j++)
+		{
+#if ((SIN_LBITS + SIN_HBITS - 21) < 0)
+			double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));
+#else
+			double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));
+#endif
+
+			g.DT_TAB [i + 0] [j] = (int)  y;
+			g.DT_TAB [i + 4] [j] = (int) -y;
+		}
+	}
+
+	// Tableau LFO
+	g.LFO_INC_TAB [0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+	g.LFO_INC_TAB [7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
+
+	reset();
+}
+
+const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
+{
+	if ( !impl )
+	{
+		impl = (Ym2612_Impl*) malloc( sizeof *impl );
+		if ( !impl )
+			return "Out of memory";
+		impl->mute_mask = 0;
+	}
+	memset( &impl->YM2612, 0, sizeof impl->YM2612 );
+
+	impl->set_rate( sample_rate, clock_rate );
+
+	return 0;
+}
+
+Ym2612_Emu::~Ym2612_Emu()
+{
+	free( impl );
+}
+
+inline void Ym2612_Impl::write0( int opn_addr, int data )
+{
+	assert( (unsigned) data <= 0xFF );
+
+	if ( opn_addr < 0x30 )
+	{
+		YM2612.REG [0] [opn_addr] = data;
+		YM_SET( opn_addr, data );
+	}
+	else if ( YM2612.REG [0] [opn_addr] != data )
+	{
+		YM2612.REG [0] [opn_addr] = data;
+
+		if ( opn_addr < 0xA0 )
+			SLOT_SET( opn_addr, data );
+		else
+			CHANNEL_SET( opn_addr, data );
+	}
+}
+
+inline void Ym2612_Impl::write1( int opn_addr, int data )
+{
+	assert( (unsigned) data <= 0xFF );
+
+	if ( opn_addr >= 0x30 && YM2612.REG [1] [opn_addr] != data )
+	{
+		YM2612.REG [1] [opn_addr] = data;
+
+		if ( opn_addr < 0xA0 )
+			SLOT_SET( opn_addr + 0x100, data );
+		else
+			CHANNEL_SET( opn_addr + 0x100, data );
+	}
+}
+
+void Ym2612_Emu::reset()
+{
+	impl->reset();
+}
+
+void Ym2612_Impl::reset()
+{
+	g.LFOcnt = 0;
+	YM2612.TimerA = 0;
+	YM2612.TimerAL = 0;
+	YM2612.TimerAcnt = 0;
+	YM2612.TimerB = 0;
+	YM2612.TimerBL = 0;
+	YM2612.TimerBcnt = 0;
+	YM2612.DAC = 0;
+
+	YM2612.Status = 0;
+
+	int i;
+	for ( i = 0; i < channel_count; i++ )
+	{
+		channel_t& ch = YM2612.CHANNEL [i];
+
+		ch.LEFT = ~0;
+		ch.RIGHT = ~0;
+		ch.ALGO = 0;
+		ch.FB = 31;
+		ch.FMS = 0;
+		ch.AMS = 0;
+
+		for ( int j = 0 ;j < 4 ; j++ )
+		{
+			ch.S0_OUT [j] = 0;
+			ch.FNUM [j] = 0;
+			ch.FOCT [j] = 0;
+			ch.KC [j] = 0;
+
+			ch.SLOT [j].Fcnt = 0;
+			ch.SLOT [j].Finc = 0;
+			ch.SLOT [j].Ecnt = ENV_END;     // Put it at the end of Decay phase...
+			ch.SLOT [j].Einc = 0;
+			ch.SLOT [j].Ecmp = 0;
+			ch.SLOT [j].Ecurp = RELEASE;
+
+			ch.SLOT [j].ChgEnM = 0;
+		}
+	}
+
+	for ( i = 0; i < 0x100; i++ )
+	{
+		YM2612.REG [0] [i] = -1;
+		YM2612.REG [1] [i] = -1;
+	}
+
+	for ( i = 0xB6; i >= 0xB4; i-- )
+	{
+		write0( i, 0xC0 );
+		write1( i, 0xC0 );
+	}
+
+	for ( i = 0xB2; i >= 0x22; i-- )
+	{
+		write0( i, 0 );
+		write1( i, 0 );
+	}
+
+	write0( 0x2A, 0x80 );
+}
+
+void Ym2612_Emu::write0( int addr, int data )
+{
+	impl->write0( addr, data );
+}
+
+void Ym2612_Emu::write1( int addr, int data )
+{
+	impl->write1( addr, data );
+}
+
+void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; }
+
+static void update_envelope_( slot_t* sl )
+{
+	switch ( sl->Ecurp )
+	{
+	case 0:
+		// Env_Attack_Next
+
+		// Verified with Gynoug even in HQ (explode SFX)
+		sl->Ecnt = ENV_DECAY;
+
+		sl->Einc = sl->EincD;
+		sl->Ecmp = sl->SLL;
+		sl->Ecurp = DECAY;
+		break;
+
+	case 1:
+		// Env_Decay_Next
+
+		// Verified with Gynoug even in HQ (explode SFX)
+		sl->Ecnt = sl->SLL;
+
+		sl->Einc = sl->EincS;
+		sl->Ecmp = ENV_END;
+		sl->Ecurp = SUBSTAIN;
+		break;
+
+	case 2:
+		// Env_Substain_Next(slot_t *SL)
+		if (sl->SEG & 8)    // SSG envelope type
+		{
+			int release = sl->SEG & 1;
+
+			if ( !release )
+			{
+				// re KEY ON
+
+				// sl->Fcnt = 0;
+				// sl->ChgEnM = ~0;
+
+				sl->Ecnt = 0;
+				sl->Einc = sl->EincA;
+				sl->Ecmp = ENV_DECAY;
+				sl->Ecurp = ATTACK;
+			}
+
+			set_seg( *sl, (sl->SEG << 1) & 4 );
+
+			if ( !release )
+				break;
+		}
+		// fall through
+
+	case 3:
+		// Env_Release_Next
+		sl->Ecnt = ENV_END;
+		sl->Einc = 0;
+		sl->Ecmp = ENV_END + 1;
+		break;
+
+	// default: no op
+	}
+}
+
+inline void update_envelope( slot_t& sl )
+{
+	int ecmp = sl.Ecmp;
+	if ( (sl.Ecnt += sl.Einc) >= ecmp )
+		update_envelope_( &sl );
+}
+
+template<int algo>
+struct ym2612_update_chan {
+	static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
+};
+
+typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
+
+template<int algo>
+void ym2612_update_chan<algo>::func( tables_t& g, channel_t& ch,
+		Ym2612_Emu::sample_t* buf, int length )
+{
+	int not_end = ch.SLOT [S3].Ecnt - ENV_END;
+
+	// algo is a compile-time constant, so all conditions based on it are resolved
+	// during compilation
+
+	// special cases
+	if ( algo == 7 )
+		not_end |= ch.SLOT [S0].Ecnt - ENV_END;
+
+	if ( algo >= 5 )
+		not_end |= ch.SLOT [S2].Ecnt - ENV_END;
+
+	if ( algo >= 4 )
+		not_end |= ch.SLOT [S1].Ecnt - ENV_END;
+
+	int CH_S0_OUT_1 = ch.S0_OUT [1];
+
+	int in0 = ch.SLOT [S0].Fcnt;
+	int in1 = ch.SLOT [S1].Fcnt;
+	int in2 = ch.SLOT [S2].Fcnt;
+	int in3 = ch.SLOT [S3].Fcnt;
+
+	int YM2612_LFOinc = g.LFOinc;
+	int YM2612_LFOcnt = g.LFOcnt + YM2612_LFOinc;
+
+	if ( !not_end )
+		return;
+
+	do
+	{
+		// envelope
+		int const env_LFO = g.LFO_ENV_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK];
+
+		short const* const ENV_TAB = g.ENV_TAB;
+
+	#define CALC_EN( x ) \
+		int temp##x = ENV_TAB [ch.SLOT [S##x].Ecnt >> ENV_LBITS] + ch.SLOT [S##x].TLL;  \
+		int en##x = ((temp##x ^ ch.SLOT [S##x].env_xor) + (env_LFO >> ch.SLOT [S##x].AMS)) &    \
+				((temp##x - ch.SLOT [S##x].env_max) >> 31);
+
+		CALC_EN( 0 )
+		CALC_EN( 1 )
+		CALC_EN( 2 )
+		CALC_EN( 3 )
+
+		int const* const TL_TAB = g.TL_TAB;
+
+	#define SINT( i, o ) (TL_TAB [g.SIN_TAB [(i)] + (o)])
+
+		// feedback
+		int CH_S0_OUT_0 = ch.S0_OUT [0];
+		{
+			int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch.FB);
+			CH_S0_OUT_1 = CH_S0_OUT_0;
+			CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 );
+		}
+
+		int CH_OUTd;
+		if ( algo == 0 )
+		{
+			int temp = in1 + CH_S0_OUT_1;
+			temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
+			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
+			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
+		}
+		else if ( algo == 1 )
+		{
+			int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
+			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
+			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
+		}
+		else if ( algo == 2 )
+		{
+			int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
+			temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
+			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
+		}
+		else if ( algo == 3 )
+		{
+			int temp = in1 + CH_S0_OUT_1;
+			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
+					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
+			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
+		}
+		else if ( algo == 4 )
+		{
+			int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
+			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
+					SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
+			//DO_LIMIT
+		}
+		else if ( algo == 5 )
+		{
+			int temp = CH_S0_OUT_1;
+			CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
+					SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
+					SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
+			//DO_LIMIT
+		}
+		else if ( algo == 6 )
+		{
+			CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
+					SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
+					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
+			//DO_LIMIT
+		}
+		else if ( algo == 7 )
+		{
+			CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
+					SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
+					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
+			//DO_LIMIT
+		}
+
+		CH_OUTd >>= MAX_OUT_BITS - output_bits + 2;
+
+		// update phase
+		unsigned freq_LFO = ((g.LFO_FREQ_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] *
+				ch.FMS) >> (LFO_HBITS - 1 + 1)) + (1L << (LFO_FMS_LBITS - 1));
+		YM2612_LFOcnt += YM2612_LFOinc;
+		in0 += (ch.SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
+		in1 += (ch.SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
+		in2 += (ch.SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
+		in3 += (ch.SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
+
+		int t0 = buf [0] + (CH_OUTd & ch.LEFT);
+		int t1 = buf [1] + (CH_OUTd & ch.RIGHT);
+
+		update_envelope( ch.SLOT [0] );
+		update_envelope( ch.SLOT [1] );
+		update_envelope( ch.SLOT [2] );
+		update_envelope( ch.SLOT [3] );
+
+		ch.S0_OUT [0] = CH_S0_OUT_0;
+		buf [0] = t0;
+		buf [1] = t1;
+		buf += 2;
+	}
+	while ( --length );
+
+	ch.S0_OUT [1] = CH_S0_OUT_1;
+
+	ch.SLOT [S0].Fcnt = in0;
+	ch.SLOT [S1].Fcnt = in1;
+	ch.SLOT [S2].Fcnt = in2;
+	ch.SLOT [S3].Fcnt = in3;
+}
+
+static const ym2612_update_chan_t UPDATE_CHAN [8] = {
+	&ym2612_update_chan<0>::func,
+	&ym2612_update_chan<1>::func,
+	&ym2612_update_chan<2>::func,
+	&ym2612_update_chan<3>::func,
+	&ym2612_update_chan<4>::func,
+	&ym2612_update_chan<5>::func,
+	&ym2612_update_chan<6>::func,
+	&ym2612_update_chan<7>::func
+};
+
+void Ym2612_Impl::run_timer( int length )
+{
+	int const step = 6;
+	int remain = length;
+	do
+	{
+		int n = step;
+		if ( n > remain )
+			n = remain;
+		remain -= n;
+
+		long i = n * YM2612.TimerBase;
+		if (YM2612.Mode & 1)                            // Timer A ON ?
+		{
+	//      if ((YM2612.TimerAcnt -= 14073) <= 0)       // 13879=NTSC (old: 14475=NTSC  14586=PAL)
+			if ((YM2612.TimerAcnt -= i) <= 0)
+			{
+				// timer a overflow
+
+				YM2612.Status |= (YM2612.Mode & 0x04) >> 2;
+				YM2612.TimerAcnt += YM2612.TimerAL;
+
+				if (YM2612.Mode & 0x80)
+				{
+					KEY_ON( YM2612.CHANNEL [2], 0 );
+					KEY_ON( YM2612.CHANNEL [2], 1 );
+					KEY_ON( YM2612.CHANNEL [2], 2 );
+					KEY_ON( YM2612.CHANNEL [2], 3 );
+				}
+			}
+		}
+
+		if (YM2612.Mode & 2)                            // Timer B ON ?
+		{
+	//      if ((YM2612.TimerBcnt -= 14073) <= 0)       // 13879=NTSC (old: 14475=NTSC  14586=PAL)
+			if ((YM2612.TimerBcnt -= i) <= 0)
+			{
+				// timer b overflow
+				YM2612.Status |= (YM2612.Mode & 0x08) >> 2;
+				YM2612.TimerBcnt += YM2612.TimerBL;
+			}
+		}
+	}
+	while ( remain > 0 );
+}
+
+void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
+{
+	if ( pair_count <= 0 )
+		return;
+
+	if ( YM2612.Mode & 3 )
+		run_timer( pair_count );
+
+	// Mise à jour des pas des compteurs-frequences s'ils ont ete modifies
+
+	for ( int chi = 0; chi < channel_count; chi++ )
+	{
+		channel_t& ch = YM2612.CHANNEL [chi];
+		if ( ch.SLOT [0].Finc != -1 )
+			continue;
+
+		int i2 = 0;
+		if ( chi == 2 && (YM2612.Mode & 0x40) )
+			i2 = 2;
+
+		for ( int i = 0; i < 4; i++ )
+		{
+			// static int seq [4] = { 2, 1, 3, 0 };
+			// if ( i2 ) i2 = seq [i];
+
+			slot_t& sl = ch.SLOT [i];
+			int finc = g.FINC_TAB [ch.FNUM [i2]] >> (7 - ch.FOCT [i2]);
+			int ksr = ch.KC [i2] >> sl.KSR_S;   // keycode attenuation
+			sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
+			if (sl.KSR != ksr)          // si le KSR a change alors
+			{                       // les differents taux pour l'enveloppe sont mis à jour
+				sl.KSR = ksr;
+
+				sl.EincA = sl.AR [ksr];
+				sl.EincD = sl.DR [ksr];
+				sl.EincS = sl.SR [ksr];
+				sl.EincR = sl.RR [ksr];
+
+				if (sl.Ecurp == ATTACK)
+				{
+					sl.Einc = sl.EincA;
+				}
+				else if (sl.Ecurp == DECAY)
+				{
+					sl.Einc = sl.EincD;
+				}
+				else if (sl.Ecnt < ENV_END)
+				{
+					if (sl.Ecurp == SUBSTAIN)
+						sl.Einc = sl.EincS;
+					else if (sl.Ecurp == RELEASE)
+						sl.Einc = sl.EincR;
+				}
+			}
+
+			if ( i2 )
+				i2 = (i2 ^ 2) ^ (i2 >> 1);
+		}
+	}
+
+	for ( int i = 0; i < channel_count; i++ )
+	{
+		if ( !(mute_mask & (1 << i)) && (i != 5 || !YM2612.DAC) )
+			UPDATE_CHAN [YM2612.CHANNEL [i].ALGO]( g, YM2612.CHANNEL [i], out, pair_count );
+	}
+
+	g.LFOcnt += g.LFOinc * pair_count;
+}
+
+void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
diff --git a/src/console/Ym2612_Emu.cxx b/src/console/Ym2612_Emu.cxx
deleted file mode 100644
index cfb3588e545e..000000000000
--- a/src/console/Ym2612_Emu.cxx
+++ /dev/null
@@ -1,1319 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-// Based on Gens 2.10 ym2612.c
-
-#include "Ym2612_Emu.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */
-/* Copyright (C) 2004-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// This is mostly the original source in its C style and all.
-//
-// Somewhat optimized and simplified. Uses a template to generate the many
-// variants of Update_Chan. Rewrote header file. In need of full rewrite by
-// someone more familiar with FM sound and the YM2612. Has some inaccuracies
-// compared to the Sega Genesis sound, particularly being mixed at such a
-// high sample accuracy (the Genesis sounds like it has only 8 bit samples).
-// - Shay
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-const int output_bits = 14;
-
-struct slot_t
-{
-	const int *DT;  // parametre detune
-	int MUL;    // parametre "multiple de frequence"
-	int TL;     // Total Level = volume lorsque l'enveloppe est au plus haut
-	int TLL;    // Total Level ajusted
-	int SLL;    // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
-	int KSR_S;  // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
-	int KSR;    // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
-				// sur les differents parametres de l'enveloppe comme l'attaque, le decay ...  comme dans la realite !
-	int SEG;    // Type enveloppe SSG
-	int env_xor;
-	int env_max;
-
-	const int *AR;  // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
-	const int *DR;  // Decay Rate (table pointeur) = Taux pour la regression (DR[KSR])
-	const int *SR;  // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
-	const int *RR;  // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
-	int Fcnt;   // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
-	int Finc;   // frequency step = pas d'incrementation du compteur-frequence
-				// plus le pas est grand, plus la frequence est aïgu (ou haute)
-	int Ecurp;  // Envelope current phase = cette variable permet de savoir dans quelle phase
-				// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
-				// en fonction de la valeur de cette variable, on va appeler une fonction permettant
-				// de mettre à jour l'enveloppe courante.
-	int Ecnt;   // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
-	int Einc;   // Envelope step courant
-	int Ecmp;   // Envelope counter limite pour la prochaine phase
-	int EincA;  // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
-				// cette valeur est egal à AR[KSR]
-	int EincD;  // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
-				// cette valeur est egal à DR[KSR]
-	int EincS;  // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
-				// cette valeur est egal à SR[KSR]
-	int EincR;  // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
-				// cette valeur est egal à RR[KSR]
-	int *OUTp;  // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
-				// d'un autre ou carrement à la sortie de la voie
-	int INd;    // input data of the slot = donnees en entree du slot
-	int ChgEnM; // Change envelop mask.
-	int AMS;    // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
-	int AMSon;  // AMS enable flag = drapeau d'activation de l'AMS
-};
-
-struct channel_t
-{
-	int S0_OUT[4];          // anciennes sorties slot 0 (pour le feed back)
-	int LEFT;               // LEFT enable flag
-	int RIGHT;              // RIGHT enable flag
-	int ALGO;               // Algorythm = determine les connections entre les operateurs
-	int FB;                 // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
-	int FMS;                // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
-	int AMS;                // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
-	int FNUM[4];            // hauteur frequence de la voie (+ 3 pour le mode special)
-	int FOCT[4];            // octave de la voie (+ 3 pour le mode special)
-	int KC[4];              // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
-	slot_t SLOT[4]; // four slot.operators = les 4 slots de la voie
-	int FFlag;              // Frequency step recalculation flag
-};
-
-struct state_t
-{
-	int TimerBase;      // TimerBase calculation
-	int Status;         // YM2612 Status (timer overflow)
-	int TimerA;         // timerA limit = valeur jusqu'à laquelle le timer A doit compter
-	int TimerAL;
-	int TimerAcnt;      // timerA counter = valeur courante du Timer A
-	int TimerB;         // timerB limit = valeur jusqu'à laquelle le timer B doit compter
-	int TimerBL;
-	int TimerBcnt;      // timerB counter = valeur courante du Timer B
-	int Mode;           // Mode actuel des voie 3 et 6 (normal / special)
-	int DAC;            // DAC enabled flag
-	channel_t CHANNEL[Ym2612_Emu::channel_count];   // Les 6 voies du YM2612
-	int REG[2][0x100];  // Sauvegardes des valeurs de tout les registres, c'est facultatif
-						// cela nous rend le debuggage plus facile
-};
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-#define ATTACK    0
-#define DECAY     1
-#define SUBSTAIN  2
-#define RELEASE   3
-
-// SIN_LBITS <= 16
-// LFO_HBITS <= 16
-// (SIN_LBITS + SIN_HBITS) <= 26
-// (ENV_LBITS + ENV_HBITS) <= 28
-// (LFO_LBITS + LFO_HBITS) <= 28
-
-#define SIN_HBITS      12                               // Sinus phase counter int part
-#define SIN_LBITS      (26 - SIN_HBITS)                 // Sinus phase counter float part (best setting)
-
-#if (SIN_LBITS > 16)
-#define SIN_LBITS      16                               // Can't be greater than 16 bits
-#endif
-
-#define ENV_HBITS      12                               // Env phase counter int part
-#define ENV_LBITS      (28 - ENV_HBITS)                 // Env phase counter float part (best setting)
-
-#define LFO_HBITS      10                               // LFO phase counter int part
-#define LFO_LBITS      (28 - LFO_HBITS)                 // LFO phase counter float part (best setting)
-
-#define SIN_LENGHT     (1 << SIN_HBITS)
-#define ENV_LENGHT     (1 << ENV_HBITS)
-#define LFO_LENGHT     (1 << LFO_HBITS)
-
-#define TL_LENGHT      (ENV_LENGHT * 3)                 // Env + TL scaling + LFO
-
-#define SIN_MASK       (SIN_LENGHT - 1)
-#define ENV_MASK       (ENV_LENGHT - 1)
-#define LFO_MASK       (LFO_LENGHT - 1)
-
-#define ENV_STEP       (96.0 / ENV_LENGHT)              // ENV_MAX = 96 dB
-
-#define ENV_ATTACK     ((ENV_LENGHT * 0) << ENV_LBITS)
-#define ENV_DECAY      ((ENV_LENGHT * 1) << ENV_LBITS)
-#define ENV_END        ((ENV_LENGHT * 2) << ENV_LBITS)
-
-#define MAX_OUT_BITS   (SIN_HBITS + SIN_LBITS + 2)      // Modulation = -4 <--> +4
-#define MAX_OUT        ((1 << MAX_OUT_BITS) - 1)
-
-#define PG_CUT_OFF     ((int) (78.0 / ENV_STEP))
-#define ENV_CUT_OFF    ((int) (68.0 / ENV_STEP))
-
-#define AR_RATE        399128
-#define DR_RATE        5514396
-
-//#define AR_RATE        426136
-//#define DR_RATE        (AR_RATE * 12)
-
-#define LFO_FMS_LBITS  9    // FIXED (LFO_FMS_BASE gives somethink as 1)
-#define LFO_FMS_BASE   ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
-
-#define S0             0    // Stupid typo of the YM2612
-#define S1             2
-#define S2             1
-#define S3             3
-
-inline void set_seg( slot_t& s, int seg )
-{
-	s.env_xor = 0;
-	s.env_max = INT_MAX;
-	s.SEG = seg;
-	if ( seg & 4 )
-	{
-		s.env_xor = ENV_MASK;
-		s.env_max = ENV_MASK;
-	}
-}
-
-struct tables_t
-{
-	short SIN_TAB [SIN_LENGHT];                 // SINUS TABLE (offset into TL TABLE)
-	int LFOcnt;         // LFO counter = compteur-frequence pour le LFO
-	int LFOinc;         // LFO step counter = pas d'incrementation du compteur-frequence du LFO
-						// plus le pas est grand, plus la frequence est grande
-	unsigned int AR_TAB [128];                  // Attack rate table
-	unsigned int DR_TAB [96];                   // Decay rate table
-	unsigned int DT_TAB [8] [32];               // Detune table
-	unsigned int SL_TAB [16];                   // Substain level table
-	unsigned int NULL_RATE [32];                // Table for NULL rate
-	int LFO_INC_TAB [8];                        // LFO step table
-
-	short ENV_TAB [2 * ENV_LENGHT + 8];         // ENV CURVE TABLE (attack & decay)
-
-	short LFO_ENV_TAB [LFO_LENGHT];             // LFO AMS TABLE (adjusted for 11.8 dB)
-	short LFO_FREQ_TAB [LFO_LENGHT];            // LFO FMS TABLE
-	int TL_TAB [TL_LENGHT * 2];                 // TOTAL LEVEL TABLE (positif and minus)
-	unsigned int DECAY_TO_ATTACK [ENV_LENGHT];  // Conversion from decay to attack phase
-	unsigned int FINC_TAB [2048];               // Frequency step table
-};
-
-static const unsigned char DT_DEF_TAB [4 * 32] =
-{
-// FD = 0
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// FD = 1
-  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
-  2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
-
-// FD = 2
-  1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
-  5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
-
-// FD = 3
-  2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
-  8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
-};
-
-static const unsigned char FKEY_TAB [16] =
-{
-	0, 0, 0, 0,
-	0, 0, 0, 1,
-	2, 3, 3, 3,
-	3, 3, 3, 3
-};
-
-static const unsigned char LFO_AMS_TAB [4] =
-{
-	31, 4, 1, 0
-};
-
-static const unsigned char LFO_FMS_TAB [8] =
-{
-	LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
-	LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
-	LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
-	LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
-};
-
-inline void YM2612_Special_Update() { }
-
-struct Ym2612_Impl
-{
-	enum { channel_count = Ym2612_Emu::channel_count };
-
-	state_t YM2612;
-	int mute_mask;
-	tables_t g;
-
-	void KEY_ON( channel_t&, int );
-	void KEY_OFF( channel_t&, int );
-	int SLOT_SET( int, int );
-	int CHANNEL_SET( int, int );
-	int YM_SET( int, int );
-
-	void set_rate( double sample_rate, double clock_factor );
-	void reset();
-	void write0( int addr, int data );
-	void write1( int addr, int data );
-	void run_timer( int );
-	void run( int pair_count, Ym2612_Emu::sample_t* );
-};
-
-void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl)
-{
-	slot_t *SL = &(ch.SLOT [nsl]);  // on recupere le bon pointeur de slot
-
-	if (SL->Ecurp == RELEASE)       // la touche est-elle rel'chee ?
-	{
-		SL->Fcnt = 0;
-
-		// Fix Ecco 2 splash sound
-
-		SL->Ecnt = (g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
-		SL->ChgEnM = ~0;
-
-//      SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
-//      SL->Ecnt = 0;
-
-		SL->Einc = SL->EincA;
-		SL->Ecmp = ENV_DECAY;
-		SL->Ecurp = ATTACK;
-	}
-}
-
-
-void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl)
-{
-	slot_t *SL = &(ch.SLOT [nsl]);  // on recupere le bon pointeur de slot
-
-	if (SL->Ecurp != RELEASE)       // la touche est-elle appuyee ?
-	{
-		if (SL->Ecnt < ENV_DECAY)   // attack phase ?
-		{
-			SL->Ecnt = (g.ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
-		}
-
-		SL->Einc = SL->EincR;
-		SL->Ecmp = ENV_END;
-		SL->Ecurp = RELEASE;
-	}
-}
-
-
-int Ym2612_Impl::SLOT_SET( int Adr, int data )
-{
-	int nch = Adr & 3;
-	if ( nch == 3 )
-		return 1;
-
-	channel_t& ch = YM2612.CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
-	slot_t& sl = ch.SLOT [(Adr >> 2) & 3];
-
-	switch ( Adr & 0xF0 )
-	{
-		case 0x30:
-			if ( (sl.MUL = (data & 0x0F)) != 0 ) sl.MUL <<= 1;
-			else sl.MUL = 1;
-
-			sl.DT = (int*) g.DT_TAB [(data >> 4) & 7];
-
-			ch.SLOT [0].Finc = -1;
-
-			break;
-
-		case 0x40:
-			sl.TL = data & 0x7F;
-
-			// SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
-			YM2612_Special_Update();
-
-#if ((ENV_HBITS - 7) < 0)
-			sl.TLL = sl.TL >> (7 - ENV_HBITS);
-#else
-			sl.TLL = sl.TL << (ENV_HBITS - 7);
-#endif
-
-			break;
-
-		case 0x50:
-			sl.KSR_S = 3 - (data >> 6);
-
-			ch.SLOT [0].Finc = -1;
-
-			if (data &= 0x1F) sl.AR = (int*) &g.AR_TAB [data << 1];
-			else sl.AR = (int*) &g.NULL_RATE [0];
-
-			sl.EincA = sl.AR [sl.KSR];
-			if (sl.Ecurp == ATTACK) sl.Einc = sl.EincA;
-			break;
-
-		case 0x60:
-			if ( (sl.AMSon = (data & 0x80)) != 0 ) sl.AMS = ch.AMS;
-			else sl.AMS = 31;
-
-			if (data &= 0x1F) sl.DR = (int*) &g.DR_TAB [data << 1];
-			else sl.DR = (int*) &g.NULL_RATE [0];
-
-			sl.EincD = sl.DR [sl.KSR];
-			if (sl.Ecurp == DECAY) sl.Einc = sl.EincD;
-			break;
-
-		case 0x70:
-			if (data &= 0x1F) sl.SR = (int*) &g.DR_TAB [data << 1];
-			else sl.SR = (int*) &g.NULL_RATE [0];
-
-			sl.EincS = sl.SR [sl.KSR];
-			if ((sl.Ecurp == SUBSTAIN) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincS;
-			break;
-
-		case 0x80:
-			sl.SLL = g.SL_TAB [data >> 4];
-
-			sl.RR = (int*) &g.DR_TAB [((data & 0xF) << 2) + 2];
-
-			sl.EincR = sl.RR [sl.KSR];
-			if ((sl.Ecurp == RELEASE) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincR;
-			break;
-
-		case 0x90:
-			// SSG-EG envelope shapes :
-			/*
-			   E  At Al H
-
-			   1  0  0  0  \\\\
-			   1  0  0  1  \___
-			   1  0  1  0  \/\/
-			   1  0  1  1  \
-			   1  1  0  0  ////
-			   1  1  0  1  /
-			   1  1  1  0  /\/\
-			   1  1  1  1  /___
-
-			   E  = SSG-EG enable
-			   At = Start negate
-			   Al = Altern
-			   H  = Hold */
-
-			set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
-			break;
-	}
-
-	return 0;
-}
-
-
-int Ym2612_Impl::CHANNEL_SET( int Adr, int data )
-{
-	int num = Adr & 3;
-	if ( num == 3 )
-		return 1;
-
-	channel_t& ch = YM2612.CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
-
-	switch ( Adr & 0xFC )
-	{
-		case 0xA0:
-			YM2612_Special_Update();
-
-			ch.FNUM [0] = (ch.FNUM [0] & 0x700) + data;
-			ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
-			ch.SLOT [0].Finc = -1;
-			break;
-
-		case 0xA4:
-			YM2612_Special_Update();
-
-			ch.FNUM [0] = (ch.FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
-			ch.FOCT [0] = (data & 0x38) >> 3;
-			ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
-			ch.SLOT [0].Finc = -1;
-			break;
-
-		case 0xA8:
-			if ( Adr < 0x100 )
-			{
-				num++;
-
-				YM2612_Special_Update();
-
-				YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x700) + data;
-				YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
-						FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
-				YM2612.CHANNEL [2].SLOT [0].Finc = -1;
-			}
-			break;
-
-		case 0xAC:
-			if ( Adr < 0x100 )
-			{
-				num++;
-
-				YM2612_Special_Update();
-
-				YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
-				YM2612.CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
-				YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
-						FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
-				YM2612.CHANNEL [2].SLOT [0].Finc = -1;
-			}
-			break;
-
-		case 0xB0:
-			if ( ch.ALGO != (data & 7) )
-			{
-				// Fix VectorMan 2 heli sound (level 1)
-				YM2612_Special_Update();
-
-				ch.ALGO = data & 7;
-
-				ch.SLOT [0].ChgEnM = 0;
-				ch.SLOT [1].ChgEnM = 0;
-				ch.SLOT [2].ChgEnM = 0;
-				ch.SLOT [3].ChgEnM = 0;
-			}
-
-			ch.FB = 9 - ((data >> 3) & 7);                              // Real thing ?
-
-//          if (ch.FB = ((data >> 3) & 7)) ch.FB = 9 - ch.FB;       // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
-//          else ch.FB = 31;
-			break;
-
-		case 0xB4: {
-			YM2612_Special_Update();
-
-			ch.LEFT = 0 - ((data >> 7) & 1);
-			ch.RIGHT = 0 - ((data >> 6) & 1);
-
-			ch.AMS = LFO_AMS_TAB [(data >> 4) & 3];
-			ch.FMS = LFO_FMS_TAB [data & 7];
-
-			for ( int i = 0; i < 4; i++ )
-			{
-				slot_t& sl = ch.SLOT [i];
-				sl.AMS = (sl.AMSon ? ch.AMS : 31);
-			}
-			break;
-		}
-	}
-
-	return 0;
-}
-
-
-int Ym2612_Impl::YM_SET(int Adr, int data)
-{
-	switch ( Adr )
-	{
-		case 0x22:
-			if (data & 8) // LFO enable
-			{
-				// Cool Spot music 1, LFO modified severals time which
-				// distord the sound, have to check that on a real genesis...
-
-				g.LFOinc = g.LFO_INC_TAB [data & 7];
-			}
-			else
-			{
-				g.LFOinc = g.LFOcnt = 0;
-			}
-			break;
-
-		case 0x24:
-			YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2);
-
-			if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
-			{
-				YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
-			}
-			break;
-
-		case 0x25:
-			YM2612.TimerA = (YM2612.TimerA & 0x3FC) | (data & 3);
-
-			if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
-			{
-				YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
-			}
-			break;
-
-		case 0x26:
-			YM2612.TimerB = data;
-
-			if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12))
-			{
-				YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12);
-			}
-			break;
-
-		case 0x27:
-			// Parametre divers
-			// b7 = CSM MODE
-			// b6 = 3 slot mode
-			// b5 = reset b
-			// b4 = reset a
-			// b3 = timer enable b
-			// b2 = timer enable a
-			// b1 = load b
-			// b0 = load a
-
-			if ((data ^ YM2612.Mode) & 0x40)
-			{
-				// We changed the channel 2 mode, so recalculate phase step
-				// This fix the punch sound in Street of Rage 2
-
-				YM2612_Special_Update();
-
-				YM2612.CHANNEL [2].SLOT [0].Finc = -1;      // recalculate phase step
-			}
-
-//          if ((data & 2) && (YM2612.Status & 2)) YM2612.TimerBcnt = YM2612.TimerBL;
-//          if ((data & 1) && (YM2612.Status & 1)) YM2612.TimerAcnt = YM2612.TimerAL;
-
-//          YM2612.Status &= (~data >> 4);                  // Reset du Status au cas ou c'est demande
-			YM2612.Status &= (~data >> 4) & (data >> 2);    // Reset Status
-
-			YM2612.Mode = data;
-			break;
-
-		case 0x28: {
-			int nch = data & 3;
-			if ( nch == 3 )
-				return 1;
-			if ( data & 4 )
-				nch += 3;
-			channel_t& ch = YM2612.CHANNEL [nch];
-
-			YM2612_Special_Update();
-
-			if (data & 0x10) KEY_ON(ch, S0);    // On appuie sur la touche pour le slot 1
-			else KEY_OFF(ch, S0);               // On rel'che la touche pour le slot 1
-			if (data & 0x20) KEY_ON(ch, S1);    // On appuie sur la touche pour le slot 3
-			else KEY_OFF(ch, S1);               // On rel'che la touche pour le slot 3
-			if (data & 0x40) KEY_ON(ch, S2);    // On appuie sur la touche pour le slot 2
-			else KEY_OFF(ch, S2);               // On rel'che la touche pour le slot 2
-			if (data & 0x80) KEY_ON(ch, S3);    // On appuie sur la touche pour le slot 4
-			else KEY_OFF(ch, S3);               // On rel'che la touche pour le slot 4
-			break;
-		}
-
-		case 0x2B:
-			if (YM2612.DAC ^ (data & 0x80)) YM2612_Special_Update();
-
-			YM2612.DAC = data & 0x80;   // activation/desactivation du DAC
-			break;
-	}
-
-	return 0;
-}
-
-void Ym2612_Impl::set_rate( double sample_rate, double clock_rate )
-{
-	assert( sample_rate );
-	assert( clock_rate > sample_rate );
-
-	int i;
-
-	// 144 = 12 * (prescale * 2) = 12 * 6 * 2
-	// prescale set to 6 by default
-
-	double Frequence = clock_rate / sample_rate / 144.0;
-	if ( fabs( Frequence - 1.0 ) < 0.0000001 )
-		Frequence = 1.0;
-	YM2612.TimerBase = int (Frequence * 4096.0);
-
-	// Tableau TL :
-	// [0     -  4095] = +output  [4095  - ...] = +output overflow (fill with 0)
-	// [12288 - 16383] = -output  [16384 - ...] = -output overflow (fill with 0)
-
-	for(i = 0; i < TL_LENGHT; i++)
-	{
-		if (i >= PG_CUT_OFF)    // YM2612 cut off sound after 78 dB (14 bits output ?)
-		{
-			g.TL_TAB [TL_LENGHT + i] = g.TL_TAB [i] = 0;
-		}
-		else
-		{
-			double x = MAX_OUT;                         // Max output
-			x /= pow( 10.0, (ENV_STEP * i) / 20.0 );    // Decibel -> Voltage
-
-			g.TL_TAB [i] = (int) x;
-			g.TL_TAB [TL_LENGHT + i] = -g.TL_TAB [i];
-		}
-	}
-
-	// Tableau SIN :
-	// g.SIN_TAB [x] [y] = sin(x) * y;
-	// x = phase and y = volume
-
-	g.SIN_TAB [0] = g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
-
-	for(i = 1; i <= SIN_LENGHT / 4; i++)
-	{
-		double x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT));    // Sinus
-		x = 20 * log10(1 / x);                                      // convert to dB
-
-		int j = (int) (x / ENV_STEP);                       // Get TL range
-
-		if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
-
-		g.SIN_TAB [i] = g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
-		g.SIN_TAB [(SIN_LENGHT / 2) + i] = g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
-	}
-
-	// Tableau LFO (LFO wav) :
-
-	for(i = 0; i < LFO_LENGHT; i++)
-	{
-		double x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));    // Sinus
-		x += 1.0;
-		x /= 2.0;                   // positive only
-		x *= 11.8 / ENV_STEP;       // ajusted to MAX enveloppe modulation
-
-		g.LFO_ENV_TAB [i] = (int) x;
-
-		x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT));   // Sinus
-		x *= (double) ((1 << (LFO_HBITS - 1)) - 1);
-
-		g.LFO_FREQ_TAB [i] = (int) x;
-
-	}
-
-	// Tableau Enveloppe :
-	// g.ENV_TAB [0] -> g.ENV_TAB [ENV_LENGHT - 1]              = attack curve
-	// g.ENV_TAB [ENV_LENGHT] -> g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
-
-	for(i = 0; i < ENV_LENGHT; i++)
-	{
-		// Attack curve (x^8 - music level 2 Vectorman 2)
-		double x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);
-		x *= ENV_LENGHT;
-
-		g.ENV_TAB [i] = (int) x;
-
-		// Decay curve (just linear)
-		x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);
-		x *= ENV_LENGHT;
-
-		g.ENV_TAB [ENV_LENGHT + i] = (int) x;
-	}
-	for ( i = 0; i < 8; i++ )
-		g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
-
-	g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1;      // for the stopped state
-
-	// Tableau pour la conversion Attack -> Decay and Decay -> Attack
-
-	int j = ENV_LENGHT - 1;
-	for ( i = 0; i < ENV_LENGHT; i++ )
-	{
-		while ( j && g.ENV_TAB [j] < i )
-			j--;
-
-		g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
-	}
-
-	// Tableau pour le Substain Level
-
-	for(i = 0; i < 15; i++)
-	{
-		double x = i * 3;           // 3 and not 6 (Mickey Mania first music for test)
-		x /= ENV_STEP;
-
-		g.SL_TAB [i] = ((int) x << ENV_LBITS) + ENV_DECAY;
-	}
-
-	g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
-
-	// Tableau Frequency Step
-
-	for(i = 0; i < 2048; i++)
-	{
-		double x = (double) (i) * Frequence;
-
-#if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)
-		x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));
-#else
-		x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));
-#endif
-
-		x /= 2.0;   // because MUL = value * 2
-
-		g.FINC_TAB [i] = (unsigned int) x;
-	}
-
-	// Tableaux Attack & Decay Rate
-
-	for(i = 0; i < 4; i++)
-	{
-		g.AR_TAB [i] = 0;
-		g.DR_TAB [i] = 0;
-	}
-
-	for(i = 0; i < 60; i++)
-	{
-		double x = Frequence;
-
-		x *= 1.0 + ((i & 3) * 0.25);                    // bits 0-1 : x1.00, x1.25, x1.50, x1.75
-		x *= (double) (1 << ((i >> 2)));                // bits 2-5 : shift bits (x2^0 - x2^15)
-		x *= (double) (ENV_LENGHT << ENV_LBITS);        // on ajuste pour le tableau g.ENV_TAB
-
-		g.AR_TAB [i + 4] = (unsigned int) (x / AR_RATE);
-		g.DR_TAB [i + 4] = (unsigned int) (x / DR_RATE);
-	}
-
-	for(i = 64; i < 96; i++)
-	{
-		g.AR_TAB [i] = g.AR_TAB [63];
-		g.DR_TAB [i] = g.DR_TAB [63];
-
-		g.NULL_RATE [i - 64] = 0;
-	}
-
-	for ( i = 96; i < 128; i++ )
-		g.AR_TAB [i] = 0;
-
-	// Tableau Detune
-
-	for(i = 0; i < 4; i++)
-	{
-		for (int j = 0; j < 32; j++)
-		{
-#if ((SIN_LBITS + SIN_HBITS - 21) < 0)
-			double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));
-#else
-			double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));
-#endif
-
-			g.DT_TAB [i + 0] [j] = (int)  y;
-			g.DT_TAB [i + 4] [j] = (int) -y;
-		}
-	}
-
-	// Tableau LFO
-	g.LFO_INC_TAB [0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-	g.LFO_INC_TAB [7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-
-	reset();
-}
-
-const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
-{
-	if ( !impl )
-	{
-		impl = (Ym2612_Impl*) malloc( sizeof *impl );
-		if ( !impl )
-			return "Out of memory";
-		impl->mute_mask = 0;
-	}
-	memset( &impl->YM2612, 0, sizeof impl->YM2612 );
-
-	impl->set_rate( sample_rate, clock_rate );
-
-	return 0;
-}
-
-Ym2612_Emu::~Ym2612_Emu()
-{
-	free( impl );
-}
-
-inline void Ym2612_Impl::write0( int opn_addr, int data )
-{
-	assert( (unsigned) data <= 0xFF );
-
-	if ( opn_addr < 0x30 )
-	{
-		YM2612.REG [0] [opn_addr] = data;
-		YM_SET( opn_addr, data );
-	}
-	else if ( YM2612.REG [0] [opn_addr] != data )
-	{
-		YM2612.REG [0] [opn_addr] = data;
-
-		if ( opn_addr < 0xA0 )
-			SLOT_SET( opn_addr, data );
-		else
-			CHANNEL_SET( opn_addr, data );
-	}
-}
-
-inline void Ym2612_Impl::write1( int opn_addr, int data )
-{
-	assert( (unsigned) data <= 0xFF );
-
-	if ( opn_addr >= 0x30 && YM2612.REG [1] [opn_addr] != data )
-	{
-		YM2612.REG [1] [opn_addr] = data;
-
-		if ( opn_addr < 0xA0 )
-			SLOT_SET( opn_addr + 0x100, data );
-		else
-			CHANNEL_SET( opn_addr + 0x100, data );
-	}
-}
-
-void Ym2612_Emu::reset()
-{
-	impl->reset();
-}
-
-void Ym2612_Impl::reset()
-{
-	g.LFOcnt = 0;
-	YM2612.TimerA = 0;
-	YM2612.TimerAL = 0;
-	YM2612.TimerAcnt = 0;
-	YM2612.TimerB = 0;
-	YM2612.TimerBL = 0;
-	YM2612.TimerBcnt = 0;
-	YM2612.DAC = 0;
-
-	YM2612.Status = 0;
-
-	int i;
-	for ( i = 0; i < channel_count; i++ )
-	{
-		channel_t& ch = YM2612.CHANNEL [i];
-
-		ch.LEFT = ~0;
-		ch.RIGHT = ~0;
-		ch.ALGO = 0;
-		ch.FB = 31;
-		ch.FMS = 0;
-		ch.AMS = 0;
-
-		for ( int j = 0 ;j < 4 ; j++ )
-		{
-			ch.S0_OUT [j] = 0;
-			ch.FNUM [j] = 0;
-			ch.FOCT [j] = 0;
-			ch.KC [j] = 0;
-
-			ch.SLOT [j].Fcnt = 0;
-			ch.SLOT [j].Finc = 0;
-			ch.SLOT [j].Ecnt = ENV_END;     // Put it at the end of Decay phase...
-			ch.SLOT [j].Einc = 0;
-			ch.SLOT [j].Ecmp = 0;
-			ch.SLOT [j].Ecurp = RELEASE;
-
-			ch.SLOT [j].ChgEnM = 0;
-		}
-	}
-
-	for ( i = 0; i < 0x100; i++ )
-	{
-		YM2612.REG [0] [i] = -1;
-		YM2612.REG [1] [i] = -1;
-	}
-
-	for ( i = 0xB6; i >= 0xB4; i-- )
-	{
-		write0( i, 0xC0 );
-		write1( i, 0xC0 );
-	}
-
-	for ( i = 0xB2; i >= 0x22; i-- )
-	{
-		write0( i, 0 );
-		write1( i, 0 );
-	}
-
-	write0( 0x2A, 0x80 );
-}
-
-void Ym2612_Emu::write0( int addr, int data )
-{
-	impl->write0( addr, data );
-}
-
-void Ym2612_Emu::write1( int addr, int data )
-{
-	impl->write1( addr, data );
-}
-
-void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; }
-
-static void update_envelope_( slot_t* sl )
-{
-	switch ( sl->Ecurp )
-	{
-	case 0:
-		// Env_Attack_Next
-
-		// Verified with Gynoug even in HQ (explode SFX)
-		sl->Ecnt = ENV_DECAY;
-
-		sl->Einc = sl->EincD;
-		sl->Ecmp = sl->SLL;
-		sl->Ecurp = DECAY;
-		break;
-
-	case 1:
-		// Env_Decay_Next
-
-		// Verified with Gynoug even in HQ (explode SFX)
-		sl->Ecnt = sl->SLL;
-
-		sl->Einc = sl->EincS;
-		sl->Ecmp = ENV_END;
-		sl->Ecurp = SUBSTAIN;
-		break;
-
-	case 2:
-		// Env_Substain_Next(slot_t *SL)
-		if (sl->SEG & 8)    // SSG envelope type
-		{
-			int release = sl->SEG & 1;
-
-			if ( !release )
-			{
-				// re KEY ON
-
-				// sl->Fcnt = 0;
-				// sl->ChgEnM = ~0;
-
-				sl->Ecnt = 0;
-				sl->Einc = sl->EincA;
-				sl->Ecmp = ENV_DECAY;
-				sl->Ecurp = ATTACK;
-			}
-
-			set_seg( *sl, (sl->SEG << 1) & 4 );
-
-			if ( !release )
-				break;
-		}
-		// fall through
-
-	case 3:
-		// Env_Release_Next
-		sl->Ecnt = ENV_END;
-		sl->Einc = 0;
-		sl->Ecmp = ENV_END + 1;
-		break;
-
-	// default: no op
-	}
-}
-
-inline void update_envelope( slot_t& sl )
-{
-	int ecmp = sl.Ecmp;
-	if ( (sl.Ecnt += sl.Einc) >= ecmp )
-		update_envelope_( &sl );
-}
-
-template<int algo>
-struct ym2612_update_chan {
-	static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-};
-
-typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-
-template<int algo>
-void ym2612_update_chan<algo>::func( tables_t& g, channel_t& ch,
-		Ym2612_Emu::sample_t* buf, int length )
-{
-	int not_end = ch.SLOT [S3].Ecnt - ENV_END;
-
-	// algo is a compile-time constant, so all conditions based on it are resolved
-	// during compilation
-
-	// special cases
-	if ( algo == 7 )
-		not_end |= ch.SLOT [S0].Ecnt - ENV_END;
-
-	if ( algo >= 5 )
-		not_end |= ch.SLOT [S2].Ecnt - ENV_END;
-
-	if ( algo >= 4 )
-		not_end |= ch.SLOT [S1].Ecnt - ENV_END;
-
-	int CH_S0_OUT_1 = ch.S0_OUT [1];
-
-	int in0 = ch.SLOT [S0].Fcnt;
-	int in1 = ch.SLOT [S1].Fcnt;
-	int in2 = ch.SLOT [S2].Fcnt;
-	int in3 = ch.SLOT [S3].Fcnt;
-
-	int YM2612_LFOinc = g.LFOinc;
-	int YM2612_LFOcnt = g.LFOcnt + YM2612_LFOinc;
-
-	if ( !not_end )
-		return;
-
-	do
-	{
-		// envelope
-		int const env_LFO = g.LFO_ENV_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK];
-
-		short const* const ENV_TAB = g.ENV_TAB;
-
-	#define CALC_EN( x ) \
-		int temp##x = ENV_TAB [ch.SLOT [S##x].Ecnt >> ENV_LBITS] + ch.SLOT [S##x].TLL;  \
-		int en##x = ((temp##x ^ ch.SLOT [S##x].env_xor) + (env_LFO >> ch.SLOT [S##x].AMS)) &    \
-				((temp##x - ch.SLOT [S##x].env_max) >> 31);
-
-		CALC_EN( 0 )
-		CALC_EN( 1 )
-		CALC_EN( 2 )
-		CALC_EN( 3 )
-
-		int const* const TL_TAB = g.TL_TAB;
-
-	#define SINT( i, o ) (TL_TAB [g.SIN_TAB [(i)] + (o)])
-
-		// feedback
-		int CH_S0_OUT_0 = ch.S0_OUT [0];
-		{
-			int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch.FB);
-			CH_S0_OUT_1 = CH_S0_OUT_0;
-			CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 );
-		}
-
-		int CH_OUTd;
-		if ( algo == 0 )
-		{
-			int temp = in1 + CH_S0_OUT_1;
-			temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
-			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
-			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
-		}
-		else if ( algo == 1 )
-		{
-			int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
-			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
-			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
-		}
-		else if ( algo == 2 )
-		{
-			int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
-			temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
-			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
-		}
-		else if ( algo == 3 )
-		{
-			int temp = in1 + CH_S0_OUT_1;
-			temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
-					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
-			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
-		}
-		else if ( algo == 4 )
-		{
-			int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
-			CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
-					SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
-			//DO_LIMIT
-		}
-		else if ( algo == 5 )
-		{
-			int temp = CH_S0_OUT_1;
-			CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
-					SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
-					SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
-			//DO_LIMIT
-		}
-		else if ( algo == 6 )
-		{
-			CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
-					SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
-					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
-			//DO_LIMIT
-		}
-		else if ( algo == 7 )
-		{
-			CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
-					SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
-					SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
-			//DO_LIMIT
-		}
-
-		CH_OUTd >>= MAX_OUT_BITS - output_bits + 2;
-
-		// update phase
-		unsigned freq_LFO = ((g.LFO_FREQ_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] *
-				ch.FMS) >> (LFO_HBITS - 1 + 1)) + (1L << (LFO_FMS_LBITS - 1));
-		YM2612_LFOcnt += YM2612_LFOinc;
-		in0 += (ch.SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-		in1 += (ch.SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-		in2 += (ch.SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-		in3 += (ch.SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-
-		int t0 = buf [0] + (CH_OUTd & ch.LEFT);
-		int t1 = buf [1] + (CH_OUTd & ch.RIGHT);
-
-		update_envelope( ch.SLOT [0] );
-		update_envelope( ch.SLOT [1] );
-		update_envelope( ch.SLOT [2] );
-		update_envelope( ch.SLOT [3] );
-
-		ch.S0_OUT [0] = CH_S0_OUT_0;
-		buf [0] = t0;
-		buf [1] = t1;
-		buf += 2;
-	}
-	while ( --length );
-
-	ch.S0_OUT [1] = CH_S0_OUT_1;
-
-	ch.SLOT [S0].Fcnt = in0;
-	ch.SLOT [S1].Fcnt = in1;
-	ch.SLOT [S2].Fcnt = in2;
-	ch.SLOT [S3].Fcnt = in3;
-}
-
-static const ym2612_update_chan_t UPDATE_CHAN [8] = {
-	&ym2612_update_chan<0>::func,
-	&ym2612_update_chan<1>::func,
-	&ym2612_update_chan<2>::func,
-	&ym2612_update_chan<3>::func,
-	&ym2612_update_chan<4>::func,
-	&ym2612_update_chan<5>::func,
-	&ym2612_update_chan<6>::func,
-	&ym2612_update_chan<7>::func
-};
-
-void Ym2612_Impl::run_timer( int length )
-{
-	int const step = 6;
-	int remain = length;
-	do
-	{
-		int n = step;
-		if ( n > remain )
-			n = remain;
-		remain -= n;
-
-		long i = n * YM2612.TimerBase;
-		if (YM2612.Mode & 1)                            // Timer A ON ?
-		{
-	//      if ((YM2612.TimerAcnt -= 14073) <= 0)       // 13879=NTSC (old: 14475=NTSC  14586=PAL)
-			if ((YM2612.TimerAcnt -= i) <= 0)
-			{
-				// timer a overflow
-
-				YM2612.Status |= (YM2612.Mode & 0x04) >> 2;
-				YM2612.TimerAcnt += YM2612.TimerAL;
-
-				if (YM2612.Mode & 0x80)
-				{
-					KEY_ON( YM2612.CHANNEL [2], 0 );
-					KEY_ON( YM2612.CHANNEL [2], 1 );
-					KEY_ON( YM2612.CHANNEL [2], 2 );
-					KEY_ON( YM2612.CHANNEL [2], 3 );
-				}
-			}
-		}
-
-		if (YM2612.Mode & 2)                            // Timer B ON ?
-		{
-	//      if ((YM2612.TimerBcnt -= 14073) <= 0)       // 13879=NTSC (old: 14475=NTSC  14586=PAL)
-			if ((YM2612.TimerBcnt -= i) <= 0)
-			{
-				// timer b overflow
-				YM2612.Status |= (YM2612.Mode & 0x08) >> 2;
-				YM2612.TimerBcnt += YM2612.TimerBL;
-			}
-		}
-	}
-	while ( remain > 0 );
-}
-
-void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
-{
-	if ( pair_count <= 0 )
-		return;
-
-	if ( YM2612.Mode & 3 )
-		run_timer( pair_count );
-
-	// Mise à jour des pas des compteurs-frequences s'ils ont ete modifies
-
-	for ( int chi = 0; chi < channel_count; chi++ )
-	{
-		channel_t& ch = YM2612.CHANNEL [chi];
-		if ( ch.SLOT [0].Finc != -1 )
-			continue;
-
-		int i2 = 0;
-		if ( chi == 2 && (YM2612.Mode & 0x40) )
-			i2 = 2;
-
-		for ( int i = 0; i < 4; i++ )
-		{
-			// static int seq [4] = { 2, 1, 3, 0 };
-			// if ( i2 ) i2 = seq [i];
-
-			slot_t& sl = ch.SLOT [i];
-			int finc = g.FINC_TAB [ch.FNUM [i2]] >> (7 - ch.FOCT [i2]);
-			int ksr = ch.KC [i2] >> sl.KSR_S;   // keycode attenuation
-			sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
-			if (sl.KSR != ksr)          // si le KSR a change alors
-			{                       // les differents taux pour l'enveloppe sont mis à jour
-				sl.KSR = ksr;
-
-				sl.EincA = sl.AR [ksr];
-				sl.EincD = sl.DR [ksr];
-				sl.EincS = sl.SR [ksr];
-				sl.EincR = sl.RR [ksr];
-
-				if (sl.Ecurp == ATTACK)
-				{
-					sl.Einc = sl.EincA;
-				}
-				else if (sl.Ecurp == DECAY)
-				{
-					sl.Einc = sl.EincD;
-				}
-				else if (sl.Ecnt < ENV_END)
-				{
-					if (sl.Ecurp == SUBSTAIN)
-						sl.Einc = sl.EincS;
-					else if (sl.Ecurp == RELEASE)
-						sl.Einc = sl.EincR;
-				}
-			}
-
-			if ( i2 )
-				i2 = (i2 ^ 2) ^ (i2 >> 1);
-		}
-	}
-
-	for ( int i = 0; i < channel_count; i++ )
-	{
-		if ( !(mute_mask & (1 << i)) && (i != 5 || !YM2612.DAC) )
-			UPDATE_CHAN [YM2612.CHANNEL [i].ALGO]( g, YM2612.CHANNEL [i], out, pair_count );
-	}
-
-	g.LFOcnt += g.LFOinc * pair_count;
-}
-
-void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
diff --git a/src/console/Zlib_Inflater.cc b/src/console/Zlib_Inflater.cc
new file mode 100644
index 000000000000..ed64e8d96173
--- /dev/null
+++ b/src/console/Zlib_Inflater.cc
@@ -0,0 +1,175 @@
+// File_Extractor 0.4.0. http://www.slack.net/~ant/
+
+#include "Zlib_Inflater.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+static const char* get_zlib_err( int code )
+{
+	assert( code != Z_OK );
+	if ( code == Z_MEM_ERROR )
+		return "Out of memory";
+
+	const char* str = zError( code );
+	if ( code == Z_DATA_ERROR )
+		str = "Zip data is corrupt";
+	if ( !str )
+		str = "Zip error";
+	return str;
+}
+
+void Zlib_Inflater::end()
+{
+	if ( deflated_ )
+	{
+		deflated_ = false;
+		if ( inflateEnd( &zbuf ) )
+			check( false );
+	}
+	buf.clear();
+
+	static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	memcpy( &zbuf, &empty, sizeof zbuf );
+}
+
+Zlib_Inflater::Zlib_Inflater()
+{
+	deflated_ = false;
+	end(); // initialize things
+}
+
+Zlib_Inflater::~Zlib_Inflater()
+{
+	end();
+}
+
+blargg_err_t Zlib_Inflater::begin( mode_t mode, callback_t callback, void* user_data,
+		long buf_size )
+{
+	end();
+
+	if ( buf_size && buf.resize( buf_size ) )
+		buf_size = 0; // not enough memory for requested size, so use default
+
+	if ( !buf_size )
+		RETURN_ERR( buf.resize( 16 * 1024L ) );
+
+	// Fill buffer with some data, less than normal buffer size since caller might
+	// just be examining beginning of file. 4K is a common disk block size.
+	long count = (buf_size ? buf_size : 4096);
+	RETURN_ERR( callback( user_data, buf.begin(), &count ) );
+	zbuf.avail_in = count;
+	zbuf.next_in  = buf.begin();
+
+	if ( mode == mode_auto )
+	{
+		// examine buffer for gzip header
+		mode = mode_copy;
+		int const min_gzip_size = 2 + 8 + 8;
+		if ( count >= min_gzip_size && buf [0] == 0x1F && buf [1] == 0x8B )
+			mode = mode_ungz;
+	}
+
+	if ( mode != mode_copy )
+	{
+		int wb = MAX_WBITS + 16; // have zlib handle gzip header
+		if ( mode == mode_raw_deflate )
+			wb = -MAX_WBITS;
+
+		int zerr = inflateInit2( &zbuf, wb );
+		if ( zerr )
+			return get_zlib_err( zerr );
+
+		deflated_ = true;
+	}
+	return 0;
+}
+
+
+blargg_err_t Zlib_Inflater::read( void* out, long* count_io,
+		callback_t callback, void* user_data )
+{
+	if ( !*count_io )
+		return 0;
+
+	if ( !deflated_ )
+	{
+		// copy buffered data
+		long first = zbuf.avail_in;
+		if ( first )
+		{
+			if ( first > *count_io )
+				first = *count_io;
+			memcpy( out, zbuf.next_in, first );
+			zbuf.next_in  += first;
+			zbuf.avail_in -= first;
+			if ( !zbuf.avail_in )
+				buf.clear(); // done with buffer
+		}
+
+		// read remaining directly
+		long second = *count_io - first;
+		if ( second )
+		{
+			long actual = second;
+			RETURN_ERR( callback( user_data, (char*) out + first, &actual ) );
+			*count_io -= second - actual;
+		}
+	}
+	else
+	{
+		zbuf.next_out  = (Bytef*) out;
+		zbuf.avail_out = *count_io;
+
+		while ( 1 )
+		{
+			uInt old_avail_in = zbuf.avail_in;
+			int err = inflate( &zbuf, Z_NO_FLUSH );
+			if ( err == Z_STREAM_END )
+			{
+				*count_io -= zbuf.avail_out;
+				end();
+				break; // all data deflated
+			}
+
+			if ( err == Z_BUF_ERROR && !old_avail_in )
+				err = 0; // we just need to provide more input
+
+			if ( err )
+				return get_zlib_err( err );
+
+			if ( !zbuf.avail_out )
+				break; // requested number of bytes deflated
+
+			if ( zbuf.avail_in )
+			{
+				// inflate() should never leave input if there's still space for output
+				assert( false );
+				return "Corrupt zip data";
+			}
+
+			// refill buffer
+			long count = buf.size();
+			RETURN_ERR( callback( user_data, buf.begin(), &count ) );
+			zbuf.next_in  = buf.begin();
+			zbuf.avail_in = count;
+			if ( !zbuf.avail_in )
+				return "Corrupt zip data"; // stream didn't end but there's no more data
+		}
+	}
+	return 0;
+}
diff --git a/src/console/Zlib_Inflater.cxx b/src/console/Zlib_Inflater.cxx
deleted file mode 100644
index ed64e8d96173..000000000000
--- a/src/console/Zlib_Inflater.cxx
+++ /dev/null
@@ -1,175 +0,0 @@
-// File_Extractor 0.4.0. http://www.slack.net/~ant/
-
-#include "Zlib_Inflater.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-static const char* get_zlib_err( int code )
-{
-	assert( code != Z_OK );
-	if ( code == Z_MEM_ERROR )
-		return "Out of memory";
-
-	const char* str = zError( code );
-	if ( code == Z_DATA_ERROR )
-		str = "Zip data is corrupt";
-	if ( !str )
-		str = "Zip error";
-	return str;
-}
-
-void Zlib_Inflater::end()
-{
-	if ( deflated_ )
-	{
-		deflated_ = false;
-		if ( inflateEnd( &zbuf ) )
-			check( false );
-	}
-	buf.clear();
-
-	static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-	memcpy( &zbuf, &empty, sizeof zbuf );
-}
-
-Zlib_Inflater::Zlib_Inflater()
-{
-	deflated_ = false;
-	end(); // initialize things
-}
-
-Zlib_Inflater::~Zlib_Inflater()
-{
-	end();
-}
-
-blargg_err_t Zlib_Inflater::begin( mode_t mode, callback_t callback, void* user_data,
-		long buf_size )
-{
-	end();
-
-	if ( buf_size && buf.resize( buf_size ) )
-		buf_size = 0; // not enough memory for requested size, so use default
-
-	if ( !buf_size )
-		RETURN_ERR( buf.resize( 16 * 1024L ) );
-
-	// Fill buffer with some data, less than normal buffer size since caller might
-	// just be examining beginning of file. 4K is a common disk block size.
-	long count = (buf_size ? buf_size : 4096);
-	RETURN_ERR( callback( user_data, buf.begin(), &count ) );
-	zbuf.avail_in = count;
-	zbuf.next_in  = buf.begin();
-
-	if ( mode == mode_auto )
-	{
-		// examine buffer for gzip header
-		mode = mode_copy;
-		int const min_gzip_size = 2 + 8 + 8;
-		if ( count >= min_gzip_size && buf [0] == 0x1F && buf [1] == 0x8B )
-			mode = mode_ungz;
-	}
-
-	if ( mode != mode_copy )
-	{
-		int wb = MAX_WBITS + 16; // have zlib handle gzip header
-		if ( mode == mode_raw_deflate )
-			wb = -MAX_WBITS;
-
-		int zerr = inflateInit2( &zbuf, wb );
-		if ( zerr )
-			return get_zlib_err( zerr );
-
-		deflated_ = true;
-	}
-	return 0;
-}
-
-
-blargg_err_t Zlib_Inflater::read( void* out, long* count_io,
-		callback_t callback, void* user_data )
-{
-	if ( !*count_io )
-		return 0;
-
-	if ( !deflated_ )
-	{
-		// copy buffered data
-		long first = zbuf.avail_in;
-		if ( first )
-		{
-			if ( first > *count_io )
-				first = *count_io;
-			memcpy( out, zbuf.next_in, first );
-			zbuf.next_in  += first;
-			zbuf.avail_in -= first;
-			if ( !zbuf.avail_in )
-				buf.clear(); // done with buffer
-		}
-
-		// read remaining directly
-		long second = *count_io - first;
-		if ( second )
-		{
-			long actual = second;
-			RETURN_ERR( callback( user_data, (char*) out + first, &actual ) );
-			*count_io -= second - actual;
-		}
-	}
-	else
-	{
-		zbuf.next_out  = (Bytef*) out;
-		zbuf.avail_out = *count_io;
-
-		while ( 1 )
-		{
-			uInt old_avail_in = zbuf.avail_in;
-			int err = inflate( &zbuf, Z_NO_FLUSH );
-			if ( err == Z_STREAM_END )
-			{
-				*count_io -= zbuf.avail_out;
-				end();
-				break; // all data deflated
-			}
-
-			if ( err == Z_BUF_ERROR && !old_avail_in )
-				err = 0; // we just need to provide more input
-
-			if ( err )
-				return get_zlib_err( err );
-
-			if ( !zbuf.avail_out )
-				break; // requested number of bytes deflated
-
-			if ( zbuf.avail_in )
-			{
-				// inflate() should never leave input if there's still space for output
-				assert( false );
-				return "Corrupt zip data";
-			}
-
-			// refill buffer
-			long count = buf.size();
-			RETURN_ERR( callback( user_data, buf.begin(), &count ) );
-			zbuf.next_in  = buf.begin();
-			zbuf.avail_in = count;
-			if ( !zbuf.avail_in )
-				return "Corrupt zip data"; // stream didn't end but there's no more data
-		}
-	}
-	return 0;
-}
diff --git a/src/console/blargg_endian.h b/src/console/blargg_endian.h
index 5ca8b7dd25f1..8c59128a1194 100644
--- a/src/console/blargg_endian.h
+++ b/src/console/blargg_endian.h
@@ -3,7 +3,8 @@
 #ifndef BLARGG_ENDIAN
 #define BLARGG_ENDIAN
 
-#include <glib.h>
+#define WANT_AUD_BSWAP
+#include <libaudcore/audio.h>
 
 #include "blargg_common.h"
 
@@ -19,21 +20,21 @@
 	#define BLARGG_CPU_RISC 1
 #endif
 
-#if G_BYTE_ORDER == G_BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
 	#define BLARGG_BIG_ENDIAN 1
 #else
 	#define BLARGG_LITTLE_ENDIAN 1
 #endif
 
-inline unsigned GET_LE16 (const void * p) { return GUINT16_FROM_LE (* (uint16_t *) p); }
-inline unsigned GET_BE16 (const void * p) { return GUINT16_FROM_BE (* (uint16_t *) p); }
-inline unsigned GET_LE32 (const void * p) { return GUINT32_FROM_LE (* (uint32_t *) p); }
-inline unsigned GET_BE32 (const void * p) { return GUINT32_FROM_BE (* (uint32_t *) p); }
+inline unsigned GET_LE16 (const void * p) { return FROM_LE16 (* (uint16_t *) p); }
+inline unsigned GET_BE16 (const void * p) { return FROM_BE16 (* (uint16_t *) p); }
+inline unsigned GET_LE32 (const void * p) { return FROM_LE32 (* (uint32_t *) p); }
+inline unsigned GET_BE32 (const void * p) { return FROM_BE32 (* (uint32_t *) p); }
 
-inline void SET_LE16 (void * p, uint16_t n) { * (uint16_t *) p = GUINT16_TO_LE (n); }
-inline void SET_BE16 (void * p, uint16_t n) { * (uint16_t *) p = GUINT16_TO_BE (n); }
-inline void SET_LE32 (void * p, uint32_t n) { * (uint32_t *) p = GUINT32_TO_LE (n); }
-inline void SET_BE32 (void * p, uint32_t n) { * (uint32_t *) p = GUINT32_TO_BE (n); }
+inline void SET_LE16 (void * p, uint16_t n) { * (uint16_t *) p = TO_LE16 (n); }
+inline void SET_BE16 (void * p, uint16_t n) { * (uint16_t *) p = TO_BE16 (n); }
+inline void SET_LE32 (void * p, uint32_t n) { * (uint32_t *) p = TO_LE32 (n); }
+inline void SET_BE32 (void * p, uint32_t n) { * (uint32_t *) p = TO_BE32 (n); }
 
 // auto-selecting versions
 
diff --git a/src/console/configure.c b/src/console/configure.c
deleted file mode 100644
index fc99dea66779..000000000000
--- a/src/console/configure.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Audacious: Cross platform multimedia player
- * Copyright (c) 2005-2009 Audacious Team
- *
- * Driver for Game_Music_Emu library. See details at:
- * http://www.slack.net/~ant/libs/
- *
- * Preferences GUI by Giacomo Lozito
- */
-
-#include "configure.h"
-
-#include <audacious/misc.h>
-
-#define CON_CFGID "console"
-
-AudaciousConsoleConfig audcfg;
-
-static const char * const console_defaults[] = {
- "loop_length", "180",
- "resample", "FALSE",
- "resample_rate", "32000",
- "treble", "0",
- "bass", "0",
- "ignore_spc_length", "FALSE",
- "echo", "0",
- "inc_spc_reverb", "FALSE",
- NULL};
-
-bool_t console_cfg_load (void)
-{
-    aud_config_set_defaults (CON_CFGID, console_defaults);
-
-    audcfg.loop_length = aud_get_int (CON_CFGID, "loop_length");
-    audcfg.resample = aud_get_bool (CON_CFGID, "resample");
-    audcfg.resample_rate = aud_get_int (CON_CFGID, "resample_rate");
-    audcfg.treble = aud_get_int (CON_CFGID, "treble");
-    audcfg.bass = aud_get_int (CON_CFGID, "bass");
-    audcfg.ignore_spc_length = aud_get_bool (CON_CFGID, "ignore_spc_length");
-    audcfg.echo = aud_get_int (CON_CFGID, "echo");
-    audcfg.inc_spc_reverb = aud_get_bool (CON_CFGID, "inc_spc_reverb");
-
-    return TRUE;
-}
-
-void console_cfg_save (void)
-{
-    aud_set_int (CON_CFGID, "loop_length", audcfg.loop_length);
-    aud_set_bool (CON_CFGID, "resample", audcfg.resample);
-    aud_set_int (CON_CFGID, "resample_rate", audcfg.resample_rate);
-    aud_set_int (CON_CFGID, "treble", audcfg.treble);
-    aud_set_int (CON_CFGID, "bass", audcfg.bass);
-    aud_set_bool (CON_CFGID, "ignore_spc_length", audcfg.ignore_spc_length);
-    aud_set_int (CON_CFGID, "echo", audcfg.echo);
-    aud_set_bool (CON_CFGID, "inc_spc_reverb", audcfg.inc_spc_reverb);
-}
diff --git a/src/console/configure.cc b/src/console/configure.cc
new file mode 100644
index 000000000000..57ae3d7c72ac
--- /dev/null
+++ b/src/console/configure.cc
@@ -0,0 +1,57 @@
+/*
+ * Audacious: Cross platform multimedia player
+ * Copyright (c) 2005-2009 Audacious Team
+ *
+ * Driver for Game_Music_Emu library. See details at:
+ * http://www.slack.net/~ant/libs/
+ *
+ * Preferences GUI by Giacomo Lozito
+ */
+
+#include "configure.h"
+#include "plugin.h"
+
+#include <libaudcore/runtime.h>
+
+#define CON_CFGID "console"
+
+AudaciousConsoleConfig audcfg;
+
+const char * const ConsolePlugin::defaults[] = {
+ "loop_length", "180",
+ "resample", "FALSE",
+ "resample_rate", "32000",
+ "treble", "0",
+ "bass", "0",
+ "ignore_spc_length", "FALSE",
+ "echo", "0",
+ "inc_spc_reverb", "FALSE",
+ nullptr};
+
+bool ConsolePlugin::init ()
+{
+    aud_config_set_defaults (CON_CFGID, defaults);
+
+    audcfg.loop_length = aud_get_int (CON_CFGID, "loop_length");
+    audcfg.resample = aud_get_bool (CON_CFGID, "resample");
+    audcfg.resample_rate = aud_get_int (CON_CFGID, "resample_rate");
+    audcfg.treble = aud_get_int (CON_CFGID, "treble");
+    audcfg.bass = aud_get_int (CON_CFGID, "bass");
+    audcfg.ignore_spc_length = aud_get_bool (CON_CFGID, "ignore_spc_length");
+    audcfg.echo = aud_get_int (CON_CFGID, "echo");
+    audcfg.inc_spc_reverb = aud_get_bool (CON_CFGID, "inc_spc_reverb");
+
+    return true;
+}
+
+void ConsolePlugin::cleanup ()
+{
+    aud_set_int (CON_CFGID, "loop_length", audcfg.loop_length);
+    aud_set_bool (CON_CFGID, "resample", audcfg.resample);
+    aud_set_int (CON_CFGID, "resample_rate", audcfg.resample_rate);
+    aud_set_int (CON_CFGID, "treble", audcfg.treble);
+    aud_set_int (CON_CFGID, "bass", audcfg.bass);
+    aud_set_bool (CON_CFGID, "ignore_spc_length", audcfg.ignore_spc_length);
+    aud_set_int (CON_CFGID, "echo", audcfg.echo);
+    aud_set_bool (CON_CFGID, "inc_spc_reverb", audcfg.inc_spc_reverb);
+}
diff --git a/src/console/configure.h b/src/console/configure.h
index b8a23170be79..b1c9d8d94e72 100644
--- a/src/console/configure.h
+++ b/src/console/configure.h
@@ -9,31 +9,17 @@
 #ifndef AUD_CONSOLE_CONFIGURE_H
 #define AUD_CONSOLE_CONFIGURE_H 1
 
-#include <libaudcore/core.h>
-
 typedef struct {
 	int loop_length;           /* length of tracks that lack timing information */
-	bool_t resample;          /* whether or not to resample */
+	bool resample;          /* whether or not to resample */
 	int resample_rate;         /* rate to resample at */
 	int treble;                /* -100 to +100 */
 	int bass;                  /* -100 to +100 */
-	bool_t ignore_spc_length; /* if true, ignore length from SPC tags */
+	bool ignore_spc_length; /* if true, ignore length from SPC tags */
 	int echo;                  /* 0 to +100 */
-	bool_t inc_spc_reverb;    /* if true, increases the default reverb */
+	bool inc_spc_reverb;    /* if true, increases the default reverb */
 } AudaciousConsoleConfig;
 
 extern AudaciousConsoleConfig audcfg;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool_t console_cfg_load(void);
-void console_cfg_save(void);
-void console_cfg_ui(void);
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* AUD_CONSOLE_CONFIGURE_H */
diff --git a/src/console/gme.cc b/src/console/gme.cc
new file mode 100644
index 000000000000..f6d01a8e3706
--- /dev/null
+++ b/src/console/gme.cc
@@ -0,0 +1,374 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "Music_Emu.h"
+
+#include "gme_types.h"
+#if !GME_DISABLE_STEREO_DEPTH
+#include "Effects_Buffer.h"
+#endif
+#include "blargg_endian.h"
+#include <string.h>
+#include <ctype.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+BLARGG_EXPORT gme_type_t const* gme_type_list()
+{
+	static gme_type_t const gme_type_list_ [] = {
+#ifdef GME_TYPE_LIST
+	GME_TYPE_LIST,
+#else
+	#ifdef USE_GME_AY
+	            gme_ay_type,
+	#endif
+	#ifdef USE_GME_GBS
+	            gme_gbs_type,
+	#endif
+	#ifdef USE_GME_GYM
+	            gme_gym_type,
+	#endif
+	#ifdef USE_GME_HES
+	            gme_hes_type,
+	#endif
+	#ifdef USE_GME_KSS
+	            gme_kss_type,
+	#endif
+	#ifdef USE_GME_NSF
+	            gme_nsf_type,
+	#endif
+	#ifdef USE_GME_NSFE
+	            gme_nsfe_type,
+	#endif
+	#ifdef USE_GME_SAP
+	            gme_sap_type,
+	#endif
+	#ifdef USE_GME_SPC
+	            gme_spc_type,
+	#endif
+	#ifdef USE_GME_VGM
+	            gme_vgm_type,
+	            gme_vgz_type,
+	#endif
+#endif
+        0
+    };
+
+	return gme_type_list_;
+}
+
+BLARGG_EXPORT const char* gme_identify_header( void const* header )
+{
+	switch ( GET_BE32( header ) )
+	{
+		case BLARGG_4CHAR('Z','X','A','Y'):  return "AY";
+		case BLARGG_4CHAR('G','B','S',0x01): return "GBS";
+		case BLARGG_4CHAR('G','Y','M','X'):  return "GYM";
+		case BLARGG_4CHAR('H','E','S','M'):  return "HES";
+		case BLARGG_4CHAR('K','S','C','C'):
+		case BLARGG_4CHAR('K','S','S','X'):  return "KSS";
+		case BLARGG_4CHAR('N','E','S','M'):  return "NSF";
+		case BLARGG_4CHAR('N','S','F','E'):  return "NSFE";
+		case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
+		case BLARGG_4CHAR('S','N','E','S'):  return "SPC";
+		case BLARGG_4CHAR('V','g','m',' '):  return "VGM";
+	}
+	return "";
+}
+
+static void to_uppercase( const char* in, int len, char* out )
+{
+	for ( int i = 0; i < len; i++ )
+	{
+		if ( !(out [i] = toupper( in [i] )) )
+			return;
+	}
+	*out = 0; // extension too long
+}
+
+BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ )
+{
+	char const* end = strrchr( extension_, '.' );
+	if ( end )
+		extension_ = end + 1;
+
+	char extension [6];
+	to_uppercase( extension_, sizeof extension, extension );
+
+	for ( gme_type_t const* types = gme_type_list(); *types; types++ )
+		if ( !strcmp( extension, (*types)->extension_ ) )
+			return *types;
+	return 0;
+}
+
+BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
+{
+	*type_out = gme_identify_extension( path );
+	// TODO: don't examine header if file has extension?
+	if ( !*type_out )
+	{
+		char header [4];
+		GME_FILE_READER in;
+		RETURN_ERR( in.open( path ) );
+		RETURN_ERR( in.read( header, sizeof header ) );
+		*type_out = gme_identify_extension( gme_identify_header( header ) );
+	}
+	return 0;
+}
+
+BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
+{
+	require( (data || !size) && out );
+	*out = 0;
+
+	gme_type_t file_type = 0;
+	if ( size >= 4 )
+		file_type = gme_identify_extension( gme_identify_header( data ) );
+	if ( !file_type )
+		return gme_wrong_file_type;
+
+	Music_Emu* emu = gme_new_emu( file_type, sample_rate );
+	CHECK_ALLOC( emu );
+
+	gme_err_t err = gme_load_data( emu, data, size );
+
+	if ( err )
+		delete emu;
+	else
+		*out = emu;
+
+	return err;
+}
+
+BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
+{
+	require( path && out );
+	*out = 0;
+
+	GME_FILE_READER in;
+	RETURN_ERR( in.open( path ) );
+
+	char header [4];
+	int header_size = 0;
+
+	gme_type_t file_type = gme_identify_extension( path );
+	if ( !file_type )
+	{
+		header_size = sizeof header;
+		RETURN_ERR( in.read( header, sizeof header ) );
+		file_type = gme_identify_extension( gme_identify_header( header ) );
+	}
+	if ( !file_type )
+		return gme_wrong_file_type;
+
+	Music_Emu* emu = gme_new_emu( file_type, sample_rate );
+	CHECK_ALLOC( emu );
+
+	// optimization: avoids seeking/re-reading header
+	Remaining_Reader rem( header, header_size, &in );
+	gme_err_t err = emu->load( rem );
+	in.close();
+
+	if ( err )
+		delete emu;
+	else
+		*out = emu;
+
+	return err;
+}
+
+BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate )
+{
+	if ( type )
+	{
+		if ( rate == gme_info_only )
+			return type->new_info();
+
+		Music_Emu* me = type->new_emu();
+		if ( me )
+		{
+		#if !GME_DISABLE_STEREO_DEPTH
+			if ( type->flags_ & 1 )
+			{
+				me->effects_buffer = BLARGG_NEW Effects_Buffer;
+				if ( me->effects_buffer )
+					me->set_buffer( me->effects_buffer );
+			}
+
+			if ( !(type->flags_ & 1) || me->effects_buffer )
+		#endif
+			{
+				if ( !me->set_sample_rate( rate ) )
+				{
+					check( me->type() == type );
+					return me;
+				}
+			}
+			delete me;
+		}
+	}
+	return 0;
+}
+
+BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
+
+BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
+{
+	Mem_File_Reader in( data, size );
+	return me->load( in );
+}
+
+BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
+{
+	Callback_Reader in( func, size, data );
+	return me->load( in );
+}
+
+BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; }
+
+BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
+
+BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); }
+
+BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
+
+struct gme_info_t_ : gme_info_t
+{
+	track_info_t info;
+};
+
+BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
+{
+	*out = nullptr;
+
+	gme_info_t_* info = BLARGG_NEW gme_info_t_;
+	CHECK_ALLOC( info );
+
+	gme_err_t err = me->track_info( &info->info, track );
+	if ( err )
+	{
+		gme_free_info( info );
+		return err;
+	}
+
+	#define COPY(name) info->name = info->info.name;
+
+	COPY( length );
+	COPY( intro_length );
+	COPY( loop_length );
+
+	info->i4  = -1;
+	info->i5  = -1;
+	info->i6  = -1;
+	info->i7  = -1;
+	info->i8  = -1;
+	info->i9  = -1;
+	info->i10 = -1;
+	info->i11 = -1;
+	info->i12 = -1;
+	info->i13 = -1;
+	info->i14 = -1;
+	info->i15 = -1;
+
+	info->s7  = "";
+	info->s8  = "";
+	info->s9  = "";
+	info->s10 = "";
+	info->s11 = "";
+	info->s12 = "";
+	info->s13 = "";
+	info->s14 = "";
+	info->s15 = "";
+
+	COPY( system );
+	COPY( game );
+	COPY( song );
+	COPY( author );
+	COPY( copyright );
+	COPY( comment );
+	COPY( dumper );
+
+	#undef COPY
+
+	info->play_length = info->length;
+	if ( info->play_length <= 0 )
+	{
+		info->play_length = info->intro_length + 2 * info->loop_length; // intro + 2 loops
+		if ( info->play_length <= 0 )
+			info->play_length = 150 * 1000; // 2.5 minutes
+	}
+
+	*out = info;
+
+	return 0;
+}
+
+BLARGG_EXPORT void gme_free_info( gme_info_t* info )
+{
+	delete STATIC_CAST(gme_info_t_*,info);
+}
+
+BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth )
+{
+#if !GME_DISABLE_STEREO_DEPTH
+	if ( me->effects_buffer )
+		STATIC_CAST(Effects_Buffer*,me->effects_buffer)->set_depth( depth );
+#endif
+}
+
+BLARGG_EXPORT void*     gme_user_data      ( Music_Emu const* me )                { return me->user_data(); }
+BLARGG_EXPORT void      gme_set_user_data  ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
+BLARGG_EXPORT void      gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
+
+BLARGG_EXPORT gme_err_t gme_start_track    ( Music_Emu* me, int index )           { return me->start_track( index ); }
+BLARGG_EXPORT gme_err_t gme_play           ( Music_Emu* me, int n, short* p )     { return me->play( n, p ); }
+BLARGG_EXPORT void      gme_set_fade       ( Music_Emu* me, int start_msec )      { me->set_fade( start_msec ); }
+BLARGG_EXPORT int       gme_track_ended    ( Music_Emu const* me )                { return me->track_ended(); }
+BLARGG_EXPORT int       gme_tell           ( Music_Emu const* me )                { return me->tell(); }
+BLARGG_EXPORT gme_err_t gme_seek           ( Music_Emu* me, int msec )            { return me->seek( msec ); }
+BLARGG_EXPORT int       gme_voice_count    ( Music_Emu const* me )                { return me->voice_count(); }
+BLARGG_EXPORT void      gme_ignore_silence ( Music_Emu* me, int disable )         { me->ignore_silence( disable != 0 ); }
+BLARGG_EXPORT void      gme_set_tempo      ( Music_Emu* me, double t )            { me->set_tempo( t ); }
+BLARGG_EXPORT void      gme_mute_voice     ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
+BLARGG_EXPORT void      gme_mute_voices    ( Music_Emu* me, int mask )            { me->mute_voices( mask ); }
+BLARGG_EXPORT void      gme_enable_accuracy( Music_Emu* me, int enabled )         { me->enable_accuracy( enabled ); }
+BLARGG_EXPORT void      gme_clear_playlist ( Music_Emu* me )                      { me->clear_playlist(); }
+BLARGG_EXPORT int       gme_type_multitrack( gme_type_t t )                       { return t->track_count != 1; }
+
+BLARGG_EXPORT void      gme_set_equalizer  ( Music_Emu* me, gme_equalizer_t const* eq )
+{
+	Music_Emu::equalizer_t e = me->equalizer();
+	e.treble = eq->treble;
+	e.bass   = eq->bass;
+	me->set_equalizer( e );
+}
+
+BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
+{
+	gme_equalizer_t e = { };
+	e.treble = me->equalizer().treble;
+	e.bass   = me->equalizer().bass;
+	*out = e;
+}
+
+BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i )
+{
+	assert( (unsigned) i < (unsigned) me->voice_count() );
+	return me->voice_names() [i];
+}
+
+BLARGG_EXPORT const char* gme_type_system( gme_type_t type )
+{
+	assert( type );
+	return type->system;
+}
diff --git a/src/console/gme.cxx b/src/console/gme.cxx
deleted file mode 100644
index 8dcc4e7ffb99..000000000000
--- a/src/console/gme.cxx
+++ /dev/null
@@ -1,374 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#include "gme_types.h"
-#if !GME_DISABLE_STEREO_DEPTH
-#include "Effects_Buffer.h"
-#endif
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-BLARGG_EXPORT gme_type_t const* gme_type_list()
-{
-	static gme_type_t const gme_type_list_ [] = {
-#ifdef GME_TYPE_LIST
-	GME_TYPE_LIST,
-#else
-	#ifdef USE_GME_AY
-	            gme_ay_type,
-	#endif
-	#ifdef USE_GME_GBS
-	            gme_gbs_type,
-	#endif
-	#ifdef USE_GME_GYM
-	            gme_gym_type,
-	#endif
-	#ifdef USE_GME_HES
-	            gme_hes_type,
-	#endif
-	#ifdef USE_GME_KSS
-	            gme_kss_type,
-	#endif
-	#ifdef USE_GME_NSF
-	            gme_nsf_type,
-	#endif
-	#ifdef USE_GME_NSFE
-	            gme_nsfe_type,
-	#endif
-	#ifdef USE_GME_SAP
-	            gme_sap_type,
-	#endif
-	#ifdef USE_GME_SPC
-	            gme_spc_type,
-	#endif
-	#ifdef USE_GME_VGM
-	            gme_vgm_type,
-	            gme_vgz_type,
-	#endif
-#endif
-        0
-    };
-
-	return gme_type_list_;
-}
-
-BLARGG_EXPORT const char* gme_identify_header( void const* header )
-{
-	switch ( GET_BE32( header ) )
-	{
-		case BLARGG_4CHAR('Z','X','A','Y'):  return "AY";
-		case BLARGG_4CHAR('G','B','S',0x01): return "GBS";
-		case BLARGG_4CHAR('G','Y','M','X'):  return "GYM";
-		case BLARGG_4CHAR('H','E','S','M'):  return "HES";
-		case BLARGG_4CHAR('K','S','C','C'):
-		case BLARGG_4CHAR('K','S','S','X'):  return "KSS";
-		case BLARGG_4CHAR('N','E','S','M'):  return "NSF";
-		case BLARGG_4CHAR('N','S','F','E'):  return "NSFE";
-		case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
-		case BLARGG_4CHAR('S','N','E','S'):  return "SPC";
-		case BLARGG_4CHAR('V','g','m',' '):  return "VGM";
-	}
-	return "";
-}
-
-static void to_uppercase( const char* in, int len, char* out )
-{
-	for ( int i = 0; i < len; i++ )
-	{
-		if ( !(out [i] = toupper( in [i] )) )
-			return;
-	}
-	*out = 0; // extension too long
-}
-
-BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ )
-{
-	char const* end = strrchr( extension_, '.' );
-	if ( end )
-		extension_ = end + 1;
-
-	char extension [6];
-	to_uppercase( extension_, sizeof extension, extension );
-
-	for ( gme_type_t const* types = gme_type_list(); *types; types++ )
-		if ( !strcmp( extension, (*types)->extension_ ) )
-			return *types;
-	return 0;
-}
-
-BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
-{
-	*type_out = gme_identify_extension( path );
-	// TODO: don't examine header if file has extension?
-	if ( !*type_out )
-	{
-		char header [4];
-		GME_FILE_READER in;
-		RETURN_ERR( in.open( path ) );
-		RETURN_ERR( in.read( header, sizeof header ) );
-		*type_out = gme_identify_extension( gme_identify_header( header ) );
-	}
-	return 0;
-}
-
-BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
-{
-	require( (data || !size) && out );
-	*out = 0;
-
-	gme_type_t file_type = 0;
-	if ( size >= 4 )
-		file_type = gme_identify_extension( gme_identify_header( data ) );
-	if ( !file_type )
-		return gme_wrong_file_type;
-
-	Music_Emu* emu = gme_new_emu( file_type, sample_rate );
-	CHECK_ALLOC( emu );
-
-	gme_err_t err = gme_load_data( emu, data, size );
-
-	if ( err )
-		delete emu;
-	else
-		*out = emu;
-
-	return err;
-}
-
-BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
-{
-	require( path && out );
-	*out = 0;
-
-	GME_FILE_READER in;
-	RETURN_ERR( in.open( path ) );
-
-	char header [4];
-	int header_size = 0;
-
-	gme_type_t file_type = gme_identify_extension( path );
-	if ( !file_type )
-	{
-		header_size = sizeof header;
-		RETURN_ERR( in.read( header, sizeof header ) );
-		file_type = gme_identify_extension( gme_identify_header( header ) );
-	}
-	if ( !file_type )
-		return gme_wrong_file_type;
-
-	Music_Emu* emu = gme_new_emu( file_type, sample_rate );
-	CHECK_ALLOC( emu );
-
-	// optimization: avoids seeking/re-reading header
-	Remaining_Reader rem( header, header_size, &in );
-	gme_err_t err = emu->load( rem );
-	in.close();
-
-	if ( err )
-		delete emu;
-	else
-		*out = emu;
-
-	return err;
-}
-
-BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t type, int rate )
-{
-	if ( type )
-	{
-		if ( rate == gme_info_only )
-			return type->new_info();
-
-		Music_Emu* me = type->new_emu();
-		if ( me )
-		{
-		#if !GME_DISABLE_STEREO_DEPTH
-			if ( type->flags_ & 1 )
-			{
-				me->effects_buffer = BLARGG_NEW Effects_Buffer;
-				if ( me->effects_buffer )
-					me->set_buffer( me->effects_buffer );
-			}
-
-			if ( !(type->flags_ & 1) || me->effects_buffer )
-		#endif
-			{
-				if ( !me->set_sample_rate( rate ) )
-				{
-					check( me->type() == type );
-					return me;
-				}
-			}
-			delete me;
-		}
-	}
-	return 0;
-}
-
-BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
-
-BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
-{
-	Mem_File_Reader in( data, size );
-	return me->load( in );
-}
-
-BLARGG_EXPORT gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
-{
-	Callback_Reader in( func, size, data );
-	return me->load( in );
-}
-
-BLARGG_EXPORT void gme_delete( Music_Emu* me ) { delete me; }
-
-BLARGG_EXPORT gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
-
-BLARGG_EXPORT const char* gme_warning( Music_Emu* me ) { return me->warning(); }
-
-BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
-
-struct gme_info_t_ : gme_info_t
-{
-	track_info_t info;
-};
-
-BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
-{
-	*out = NULL;
-
-	gme_info_t_* info = BLARGG_NEW gme_info_t_;
-	CHECK_ALLOC( info );
-
-	gme_err_t err = me->track_info( &info->info, track );
-	if ( err )
-	{
-		gme_free_info( info );
-		return err;
-	}
-
-	#define COPY(name) info->name = info->info.name;
-
-	COPY( length );
-	COPY( intro_length );
-	COPY( loop_length );
-
-	info->i4  = -1;
-	info->i5  = -1;
-	info->i6  = -1;
-	info->i7  = -1;
-	info->i8  = -1;
-	info->i9  = -1;
-	info->i10 = -1;
-	info->i11 = -1;
-	info->i12 = -1;
-	info->i13 = -1;
-	info->i14 = -1;
-	info->i15 = -1;
-
-	info->s7  = "";
-	info->s8  = "";
-	info->s9  = "";
-	info->s10 = "";
-	info->s11 = "";
-	info->s12 = "";
-	info->s13 = "";
-	info->s14 = "";
-	info->s15 = "";
-
-	COPY( system );
-	COPY( game );
-	COPY( song );
-	COPY( author );
-	COPY( copyright );
-	COPY( comment );
-	COPY( dumper );
-
-	#undef COPY
-
-	info->play_length = info->length;
-	if ( info->play_length <= 0 )
-	{
-		info->play_length = info->intro_length + 2 * info->loop_length; // intro + 2 loops
-		if ( info->play_length <= 0 )
-			info->play_length = 150 * 1000; // 2.5 minutes
-	}
-
-	*out = info;
-
-	return 0;
-}
-
-BLARGG_EXPORT void gme_free_info( gme_info_t* info )
-{
-	delete STATIC_CAST(gme_info_t_*,info);
-}
-
-BLARGG_EXPORT void gme_set_stereo_depth( Music_Emu* me, double depth )
-{
-#if !GME_DISABLE_STEREO_DEPTH
-	if ( me->effects_buffer )
-		STATIC_CAST(Effects_Buffer*,me->effects_buffer)->set_depth( depth );
-#endif
-}
-
-BLARGG_EXPORT void*     gme_user_data      ( Music_Emu const* me )                { return me->user_data(); }
-BLARGG_EXPORT void      gme_set_user_data  ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
-BLARGG_EXPORT void      gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
-
-BLARGG_EXPORT gme_err_t gme_start_track    ( Music_Emu* me, int index )           { return me->start_track( index ); }
-BLARGG_EXPORT gme_err_t gme_play           ( Music_Emu* me, int n, short* p )     { return me->play( n, p ); }
-BLARGG_EXPORT void      gme_set_fade       ( Music_Emu* me, int start_msec )      { me->set_fade( start_msec ); }
-BLARGG_EXPORT int       gme_track_ended    ( Music_Emu const* me )                { return me->track_ended(); }
-BLARGG_EXPORT int       gme_tell           ( Music_Emu const* me )                { return me->tell(); }
-BLARGG_EXPORT gme_err_t gme_seek           ( Music_Emu* me, int msec )            { return me->seek( msec ); }
-BLARGG_EXPORT int       gme_voice_count    ( Music_Emu const* me )                { return me->voice_count(); }
-BLARGG_EXPORT void      gme_ignore_silence ( Music_Emu* me, int disable )         { me->ignore_silence( disable != 0 ); }
-BLARGG_EXPORT void      gme_set_tempo      ( Music_Emu* me, double t )            { me->set_tempo( t ); }
-BLARGG_EXPORT void      gme_mute_voice     ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
-BLARGG_EXPORT void      gme_mute_voices    ( Music_Emu* me, int mask )            { me->mute_voices( mask ); }
-BLARGG_EXPORT void      gme_enable_accuracy( Music_Emu* me, int enabled )         { me->enable_accuracy( enabled ); }
-BLARGG_EXPORT void      gme_clear_playlist ( Music_Emu* me )                      { me->clear_playlist(); }
-BLARGG_EXPORT int       gme_type_multitrack( gme_type_t t )                       { return t->track_count != 1; }
-
-BLARGG_EXPORT void      gme_set_equalizer  ( Music_Emu* me, gme_equalizer_t const* eq )
-{
-	Music_Emu::equalizer_t e = me->equalizer();
-	e.treble = eq->treble;
-	e.bass   = eq->bass;
-	me->set_equalizer( e );
-}
-
-BLARGG_EXPORT void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
-{
-	gme_equalizer_t e = { };
-	e.treble = me->equalizer().treble;
-	e.bass   = me->equalizer().bass;
-	*out = e;
-}
-
-BLARGG_EXPORT const char* gme_voice_name( Music_Emu const* me, int i )
-{
-	assert( (unsigned) i < (unsigned) me->voice_count() );
-	return me->voice_names() [i];
-}
-
-BLARGG_EXPORT const char* gme_type_system( gme_type_t type )
-{
-	assert( type );
-	return type->system;
-}
diff --git a/src/console/gme.h b/src/console/gme.h
index b6648d8f57c3..2d18b21d6098 100644
--- a/src/console/gme.h
+++ b/src/console/gme.h
@@ -4,11 +4,7 @@
 #ifndef GME_H
 #define GME_H
 
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-/* Error string returned by library functions, or NULL if no error (success) */
+/* Error string returned by library functions, or nullptr if no error (success) */
 typedef const char* gme_err_t;
 
 /* First parameter of most gme_ functions is a pointer to the Music_Emu */
@@ -55,7 +51,7 @@ gme_err_t gme_seek( Music_Emu*, int msec );
 sample_rate to open/load. */
 enum { gme_info_only = -1 };
 
-/* Most recent warning string, or NULL if none. Clears current warning after returning.
+/* Most recent warning string, or nullptr if none. Clears current warning after returning.
 Warning is also cleared when loading a file and starting a track. */
 const char* gme_warning( Music_Emu* );
 
@@ -148,7 +144,7 @@ void gme_enable_accuracy( Music_Emu*, int enabled );
 
 /******** Game music types ********/
 
-/* Music file type identifier. Can also hold NULL. */
+/* Music file type identifier. Can also hold nullptr. */
 typedef const struct gme_type_t_* gme_type_t;
 
 /* Emulator type constants for each supported file type */
@@ -168,7 +164,7 @@ extern const gme_type_t
 /* Type of this emulator */
 gme_type_t gme_type( Music_Emu const* );
 
-/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
+/* Pointer to array of all music types, with nullptr entry at end. Allows a player linked
 to this library to support new music types without having to be updated. */
 gme_type_t const* gme_type_list();
 
@@ -199,7 +195,7 @@ gme_type_t gme_identify_extension( const char path_or_extension [] );
 Sets *type_out to type, or 0 if unrecognized or error. */
 gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
 
-/* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need
+/* Create new emulator and set sample rate. Returns nullptr if out of memory. If you only need
 track information, pass gme_info_only for sample_rate. */
 Music_Emu* gme_new_emu( gme_type_t, int sample_rate );
 
@@ -225,14 +221,9 @@ You can use this for whatever you want. */
 void  gme_set_user_data( Music_Emu*, void* new_user_data );
 void* gme_user_data( Music_Emu const* );
 
-/* Register cleanup function to be called when deleting emulator, or NULL to
+/* Register cleanup function to be called when deleting emulator, or nullptr to
 clear it. Passes user_data to cleanup function. */
 typedef void (*gme_user_cleanup_t)( void* user_data );
 void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
 
-
-#ifdef __cplusplus
-	}
-#endif
-
 #endif
diff --git a/src/console/gme_design.txt b/src/console/gme_design.txt
index 579a989fa4a7..ccb9addf075e 100644
--- a/src/console/gme_design.txt
+++ b/src/console/gme_design.txt
@@ -36,7 +36,7 @@ any functions which automatically select it based on a file's extension
 or header contents. For each emulator type there is a global object with
 pointers to functions to create the emulator or a track information
 reader. The emulator type is thus a pointer to this, which conveniently
-allows for a NULL value. The user referencing this emulator type object
+allows for a nullptr value. The user referencing this emulator type object
 is what ultimately links the emulator in (unless new Foo_Emu is used in
 C++, of course).
 
diff --git a/src/console/gme_notes.txt b/src/console/gme_notes.txt
index b3ce1e63a5b4..19ddafabd602 100644
--- a/src/console/gme_notes.txt
+++ b/src/console/gme_notes.txt
@@ -84,7 +84,7 @@ Error handling
 --------------
 Functions which can fail have a return type of gme_err_t, which is a
 pointer to an error string (const char*). If a function is successful it
-returns NULL. Errors that you can easily avoid are checked with debug
+returns nullptr. Errors that you can easily avoid are checked with debug
 assertions; gme_err_t return values are only used for genuine run-time
 errors that can't be easily predicted in advance (out of memory, I/O
 errors, incompatible file data). Your code should check all error
@@ -93,7 +93,7 @@ values.
 To improve usability for C programmers, C++ programmers unfamiliar with
 exceptions, and compatibility with older C++ compilers, the library does
 *not* throw any C++ exceptions and uses malloc() instead of the standard
-operator new. This means that you *must* check for NULL when creating a
+operator new. This means that you *must* check for nullptr when creating a
 library object with the new operator.
 
 When loading a music file in the wrong emulator or trying to load a
@@ -244,7 +244,7 @@ load_file() with the path of a file:
 		// code that reads 'count' bytes into 'out' buffer
 		// and return 0 if no error
 	}
-	
+
 	gme_load_custom( music_emu, my_read, file_size, my_data );
 
 * If you must load the file data into memory yourself, you can have the
@@ -259,11 +259,11 @@ performance reasons, use Remaining_Reader:
 
 	Std_File_Reader in;
 	in.open( file_path );
-	
+
 	char header [4];
 	in.read( &header, sizeof header );
 	...
-	
+
 	Remaining_Reader rem( &header, sizeof header, &in );
 	music_emu->load( rem );
 
diff --git a/src/console/gme_type_list.cc b/src/console/gme_type_list.cc
new file mode 100644
index 000000000000..00a72ad3b0e8
--- /dev/null
+++ b/src/console/gme_type_list.cc
@@ -0,0 +1,38 @@
+// Game_Music_Emu 0.5.1. http://www.slack.net/~ant/
+
+// separate file to avoid linking all emulators if this is not used
+
+#include "gme.h"
+
+/* Copyright (C) 2006 Shay Green. This module 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
+module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+gme_type_t const* gme_type_list()
+{
+	static gme_type_t const gme_type_list_ [] =
+	{
+		gme_ay_type,
+		gme_gbs_type,
+		gme_gym_type,
+		gme_hes_type,
+		gme_kss_type,
+		gme_nsf_type,
+		gme_nsfe_type,
+		gme_sap_type,
+		gme_spc_type,
+		gme_vgm_type,
+		gme_vgz_type,
+		0
+	};
+	return gme_type_list_;
+}
diff --git a/src/console/gme_type_list.cxx b/src/console/gme_type_list.cxx
deleted file mode 100644
index 00a72ad3b0e8..000000000000
--- a/src/console/gme_type_list.cxx
+++ /dev/null
@@ -1,38 +0,0 @@
-// Game_Music_Emu 0.5.1. http://www.slack.net/~ant/
-
-// separate file to avoid linking all emulators if this is not used
-
-#include "gme.h"
-
-/* Copyright (C) 2006 Shay Green. This module 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
-module is distributed in the hope that 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 module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-gme_type_t const* gme_type_list()
-{
-	static gme_type_t const gme_type_list_ [] =
-	{
-		gme_ay_type,
-		gme_gbs_type,
-		gme_gym_type,
-		gme_hes_type,
-		gme_kss_type,
-		gme_nsf_type,
-		gme_nsfe_type,
-		gme_sap_type,
-		gme_spc_type,
-		gme_vgm_type,
-		gme_vgz_type,
-		0
-	};
-	return gme_type_list_;
-}
diff --git a/src/console/plugin.c b/src/console/plugin.c
deleted file mode 100644
index e9611edfaf7c..000000000000
--- a/src/console/plugin.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Audacious: Cross platform multimedia player
- * Copyright (c) 2009 Audacious Team
- *
- * Driver for Game_Music_Emu library. See details at:
- * http://www.slack.net/~ant/libs/
- */
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#include "configure.h"
-
-Tuple * console_probe_for_tuple(const char *filename, VFSFile *fd);
-bool_t console_play(const char *filename, VFSFile *file);
-
-static const char console_about[] =
- N_("Console music decoder engine based on Game_Music_Emu 0.5.2\n"
-    "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n\n"
-    "Audacious plugin by:\n"
-    "William Pitcock <nenolod at dereferenced.org>\n"
-    "Shay Green <gblargg at gmail.com>");
-
-static const char *gme_fmts[] = {
-    "ay", "gbs", "gym",
-    "hes", "kss", "nsf",
-    "nsfe", "sap", "spc",
-    "vgm", "vgz", NULL
-};
-
-static const PreferencesWidget console_widgets[] = {
- {WIDGET_LABEL, N_("<b>Playback</b>")},
- {WIDGET_SPIN_BTN, N_("Bass:"), .data = {.spin_btn = {-100, 100, 1}},
-  .cfg_type = VALUE_INT, .cfg = & audcfg.bass},
- {WIDGET_SPIN_BTN, N_("Treble:"), .data = {.spin_btn = {-100, 100, 1}},
-  .cfg_type = VALUE_INT, .cfg = & audcfg.treble},
- {WIDGET_SPIN_BTN, N_("Echo:"), .data = {.spin_btn = {0, 100, 1}},
-  .cfg_type = VALUE_INT, .cfg = & audcfg.echo},
- {WIDGET_SPIN_BTN, N_("Default song length:"),
-  .data = {.spin_btn = {-100, 100, 1, N_("seconds")}},
-  .cfg_type = VALUE_INT, .cfg = & audcfg.loop_length},
- {WIDGET_LABEL, N_("<b>Resampling</b>")},
- {WIDGET_CHK_BTN, N_("Enable audio resampling"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & audcfg.resample},
- {WIDGET_SPIN_BTN, N_("Resampling rate:"), .child = TRUE,
-  .data = {.spin_btn = {11025, 96000, 100, N_("Hz")}},
-  .cfg_type = VALUE_INT, .cfg = & audcfg.resample_rate},
- {WIDGET_LABEL, N_("<b>SPC</b>")},
- {WIDGET_CHK_BTN, N_("Ignore length from SPC tags"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & audcfg.ignore_spc_length},
- {WIDGET_CHK_BTN, N_("Increase reverb"),
-  .cfg_type = VALUE_BOOLEAN, .cfg = & audcfg.inc_spc_reverb}};
-
-static const PluginPreferences console_prefs = {
- .widgets = console_widgets,
- .n_widgets = ARRAY_LEN (console_widgets)};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Game Console Music Decoder"),
-    .domain = PACKAGE,
-    .about_text = console_about,
-    .init = console_cfg_load,
-    .cleanup = console_cfg_save,
-    .prefs = & console_prefs,
-    .play = console_play,
-    .extensions = gme_fmts,
-    .probe_for_tuple = console_probe_for_tuple,
-    .have_subtune = TRUE
-)
diff --git a/src/console/plugin.cc b/src/console/plugin.cc
new file mode 100644
index 000000000000..c75ee8bae83f
--- /dev/null
+++ b/src/console/plugin.cc
@@ -0,0 +1,56 @@
+/*
+ * Audacious: Cross platform multimedia player
+ * Copyright (c) 2009 Audacious Team
+ *
+ * Driver for Game_Music_Emu library. See details at:
+ * http://www.slack.net/~ant/libs/
+ */
+
+#include "configure.h"
+#include "plugin.h"
+
+EXPORT ConsolePlugin aud_plugin_instance;
+
+const char ConsolePlugin::about[] =
+ N_("Console music decoder engine based on Game_Music_Emu 0.5.2\n"
+    "Supported formats: AY, GBS, GYM, HES, KSS, NSF, NSFE, SAP, SPC, VGM, VGZ\n\n"
+    "Audacious plugin by:\n"
+    "William Pitcock <nenolod at dereferenced.org>\n"
+    "Shay Green <gblargg at gmail.com>");
+
+const char * const ConsolePlugin::exts[] = {
+    "ay", "gbs", "gym",
+    "hes", "kss", "nsf",
+    "nsfe", "sap", "spc",
+    "vgm", "vgz", nullptr
+};
+
+const PreferencesWidget ConsolePlugin::widgets[] = {
+    WidgetLabel (N_("<b>Playback</b>")),
+    WidgetSpin (N_("Bass:"),
+        WidgetInt (audcfg.bass),
+        {-100, 100, 1}),
+    WidgetSpin (N_("Treble:"),
+        WidgetInt (audcfg.treble),
+        {-100, 100, 1}),
+    WidgetSpin (N_("Echo:"),
+        WidgetInt (audcfg.echo),
+        {0, 100, 1}),
+    WidgetSpin (N_("Default song length:"),
+        WidgetInt (audcfg.loop_length),
+        {-100, 100, 1, N_("seconds")}),
+    WidgetLabel (N_("<b>Resampling</b>")),
+    WidgetCheck (N_("Enable audio resampling"),
+        WidgetBool (audcfg.resample)),
+    WidgetSpin (N_("Sample rate:"),
+        WidgetInt (audcfg.resample_rate),
+        {11025, 96000, 100, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetLabel (N_("<b>SPC</b>")),
+    WidgetCheck (N_("Ignore length from SPC tags"),
+        WidgetBool (audcfg.ignore_spc_length)),
+    WidgetCheck (N_("Increase reverb"),
+        WidgetBool (audcfg.inc_spc_reverb))
+};
+
+const PluginPreferences ConsolePlugin::prefs = {{widgets}};
diff --git a/src/console/plugin.h b/src/console/plugin.h
new file mode 100644
index 000000000000..1c24eef841eb
--- /dev/null
+++ b/src/console/plugin.h
@@ -0,0 +1,47 @@
+/*
+ * Audacious: Cross platform multimedia player
+ * Copyright (c) 2009-2014 Audacious Team
+ *
+ * Driver for Game_Music_Emu library. See details at:
+ * http://www.slack.net/~ant/libs/
+ */
+
+#ifndef CONSOLE_PLUGIN_H
+#define CONSOLE_PLUGIN_H
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+class ConsolePlugin : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Game Console Music Decoder"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagSubtunes)
+        .with_exts (exts);
+
+    constexpr ConsolePlugin () : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    void cleanup ();
+
+    bool is_our_file (const char * filename, VFSFile & file)
+        { return false; }
+
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+};
+
+#endif // CONSOLE_PLUGIN_H
diff --git a/src/console/sap_cpu_io.h b/src/console/sap_cpu_io.h
index 3103ecdb6fad..e2acbacf069e 100644
--- a/src/console/sap_cpu_io.h
+++ b/src/console/sap_cpu_io.h
@@ -4,6 +4,7 @@
 #include "blargg_source.h"
 
 #define CPU_WRITE( cpu, addr, data, time )  STATIC_CAST(Sap_Emu&,*cpu).cpu_write( addr, data )
+#define CPU_READ( cpu, addr, time )         STATIC_CAST(Sap_Emu&,*cpu).cpu_read( addr )
 
 void Sap_Emu::cpu_write( sap_addr_t addr, int data )
 {
@@ -12,15 +13,22 @@ void Sap_Emu::cpu_write( sap_addr_t addr, int data )
 		cpu_write_( addr, data );
 }
 
-#ifdef NDEBUG
-	#define CPU_READ( cpu, addr, time )     READ_LOW( addr )
-#else
-	#define CPU_READ( cpu, addr, time )     STATIC_CAST(Sap_Emu&,*cpu).cpu_read( addr )
-
 	int Sap_Emu::cpu_read( sap_addr_t addr )
 	{
-		if ( (addr & 0xF900) == 0xD000 )
+		switch ( (addr & 0xFF1F) )
+		{
+		case 0xD000:
 			debug_printf( "Unmapped read $%04X\n", addr );
+			break;
+		case 0xD014:
+			return info.ntsc ? 0xf : 1;
+		case 0xD40B:
+		case 0xD41B:
+			if ( time() > ( info.ntsc ? 262 : 312 ) * 114 )
+				return 0;
+			return time() / 228;
+		default:
+			break;
+		}
 		return mem.ram [addr];
 	}
-#endif
diff --git a/src/coreaudio/Makefile b/src/coreaudio/Makefile
new file mode 100644
index 000000000000..d1faefd88af4
--- /dev/null
+++ b/src/coreaudio/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = coreaudio${PLUGIN_SUFFIX}
+
+SRCS = coreaudio.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
+
+LD = ${CXX}
+CPPFLAGS += -I../..
+CXXFLAGS += ${PLUGIN_CFLAGS}
+LIBS += -lm -framework CoreAudio
diff --git a/src/coreaudio/coreaudio.cc b/src/coreaudio/coreaudio.cc
new file mode 100644
index 000000000000..e2af9b3c931c
--- /dev/null
+++ b/src/coreaudio/coreaudio.cc
@@ -0,0 +1,470 @@
+/*
+ * CoreAudio Output Plugin for Audacious
+ * Copyright 2014 William Pitcock
+ *
+ * Based on:
+ * SDL Output Plugin for Audacious
+ * Copyright 2010 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 <math.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/preferences.h>
+
+#include <CoreAudio/CoreAudio.h>
+#include <AudioUnit/AudioUnit.h>
+
+class CoreAudioPlugin : public OutputPlugin {
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("CoreAudio output"),
+        PACKAGE,
+        about,
+        & prefs,
+    };
+
+    constexpr CoreAudioPlugin () : OutputPlugin (info, 5) {}
+
+    bool init ();
+    void cleanup ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume vol);
+
+    bool open_audio (int format, int rate_, int chan_);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int len);
+    void drain ();
+
+    int get_delay ();
+    void pause (bool paused);
+    void flush ();
+
+protected:
+    static OSStatus callback (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
+    void check_started ();
+};
+
+EXPORT CoreAudioPlugin aud_plugin_instance;
+
+#define VOLUME_RANGE 40 /* decibels */
+
+#define error(...) do { \
+    aud_ui_show_error (str_printf ("CoreAudio error: " __VA_ARGS__)); \
+} while (0)
+
+struct AudioUnitFormatDescriptionMap {
+    int aud_format;
+    unsigned int mBitsPerChannel;
+    unsigned int mBytesPerChannel;
+    unsigned int mFormatFlags;
+};
+static struct AudioUnitFormatDescriptionMap AUFormatMap[] = {
+    {FMT_S16_LE, 16, sizeof (int16_t), kAudioFormatFlagIsSignedInteger},
+    {FMT_S16_BE, 16, sizeof (int16_t), kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian},
+    {FMT_U16_LE, 16, sizeof (int16_t), 0},
+    {FMT_U16_BE, 16, sizeof (int16_t), kAudioFormatFlagIsBigEndian},
+    {FMT_S24_LE, 24, sizeof (int32_t), kAudioFormatFlagIsSignedInteger},
+    {FMT_S24_BE, 24, sizeof (int32_t), kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian},
+    {FMT_U24_LE, 24, sizeof (int32_t), 0},
+    {FMT_U24_BE, 24, sizeof (int32_t), kAudioFormatFlagIsBigEndian},
+    {FMT_S32_LE, 32, sizeof (int32_t), kAudioFormatFlagIsSignedInteger},
+    {FMT_S32_BE, 32, sizeof (int32_t), kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsBigEndian},
+    {FMT_U32_LE, 32, sizeof (int32_t), 0},
+    {FMT_U32_BE, 32, sizeof (int32_t), kAudioFormatFlagIsBigEndian},
+    {FMT_FLOAT,  32, sizeof (float),   kAudioFormatFlagIsFloat},
+};
+
+static RingBuf <unsigned char> buffer;
+static int vol_left = 0, vol_right = 0;
+static int chan = 0;
+static int rate = 0;
+static int buffer_bytes_per_channel = 0;
+
+static bool prebuffer_flag = false;
+static bool paused_flag = false;
+
+static int block_delay = 0;
+static struct timeval block_time = {0, 0};
+
+static AudioComponent output_comp = nullptr;
+static AudioComponentInstance output_instance = nullptr;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static bool is_exclusive = false;
+
+const char CoreAudioPlugin::about[] =
+    N_("CoreAudio Output Plugin for Audacious\n"
+       "Copyright 2014 William Pitcock\n\n"
+       "Based on SDL Output Plugin for Audacious\n"
+       "Copyright 2010 John Lindgren");
+
+const char * const CoreAudioPlugin::defaults[] = {
+    "vol_left", "100",
+    "vol_right", "100",
+    "exclusive_mode", "FALSE",
+    nullptr};
+
+const PreferencesWidget CoreAudioPlugin::widgets[] = {
+    WidgetCheck (N_("Use exclusive mode"),
+        WidgetBool ("coreaudio", "exclusive_mode")),
+};
+
+const PluginPreferences CoreAudioPlugin::prefs = {
+    {widgets},
+    nullptr,
+    nullptr,
+    nullptr
+};
+
+bool CoreAudioPlugin::init (void)
+{
+    aud_config_set_defaults ("coreaudio", defaults);
+
+    vol_left = aud_get_int ("coreaudio", "vol_left");
+    vol_right = aud_get_int ("coreaudio", "vol_right");
+
+    /* open the default audio device */
+    AudioComponentDescription desc;
+    desc.componentType = kAudioUnitType_Output;
+    desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+    desc.componentFlags = 0;
+    desc.componentFlagsMask = 0;
+    desc.componentManufacturer = 0;
+
+    output_comp = AudioComponentFindNext (NULL, & desc);
+    if (! output_comp)
+    {
+        error ("Failed to open default audio device.\n");
+        return 0;
+    }
+
+    if (AudioComponentInstanceNew (output_comp, & output_instance))
+    {
+        error ("Failed to open default audio device.\n");
+        return 0;
+    }
+
+    AURenderCallbackStruct input;
+    input.inputProc = callback;
+    input.inputProcRefCon = this;
+
+    if (AudioUnitSetProperty (output_instance, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, & input, sizeof input))
+    {
+        error ("Unable to attach an IOProc to the selected audio unit.\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+void CoreAudioPlugin::cleanup (void)
+{
+}
+
+StereoVolume CoreAudioPlugin::get_volume ()
+{
+    return {vol_left, vol_right};
+}
+
+void CoreAudioPlugin::set_volume (StereoVolume vol)
+{
+    int vol_max;
+    float factor;
+
+    vol_left = vol.left;
+    vol_right = vol.right;
+
+    vol_max = aud::max (vol_left, vol_right);
+
+    aud_set_int ("coreaudio", "vol_left", vol_left);
+    aud_set_int ("coreaudio", "vol_right", vol_right);
+
+    factor = (vol_max == 0) ? 0.0 : powf (10, (float) VOLUME_RANGE * (vol_max - 100) / 100 / 20);
+
+    AudioUnitSetParameter (output_instance, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, factor, 0);
+}
+
+OSStatus CoreAudioPlugin::callback (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+    pthread_mutex_lock (& mutex);
+
+    int len = ioData->mBuffers[0].mDataByteSize;
+    unsigned char * buf = (unsigned char *) ioData->mBuffers[0].mData;
+    ioData->mBuffers[0].mNumberChannels = chan;
+
+    int copy = aud::min (len, buffer.len ());
+
+    buffer.move_out (buf, copy);
+    if (copy < len)
+        memset (buf + copy, 0, len - copy);
+
+    /* At this moment, we know that there is a delay of (at least) the block of
+     * data just written.  We save the block size and the current time for
+     * estimating the delay later on. */
+    block_delay = copy / (buffer_bytes_per_channel * chan) * 1000 / rate;
+    gettimeofday (& block_time, nullptr);
+
+    pthread_cond_broadcast (& cond);
+    pthread_mutex_unlock (& mutex);
+
+    return 0;
+}
+
+bool CoreAudioPlugin::open_audio (int format, int rate_, int chan_)
+{
+    struct AudioUnitFormatDescriptionMap * m = nullptr;
+
+    for (struct AudioUnitFormatDescriptionMap it : AUFormatMap)
+    {
+        if (it.aud_format == format)
+        {
+            m = & it;
+            break;
+        }
+    }
+
+    if (! m)
+    {
+        error ("The requested audio format %d is unsupported.\n", format);
+        return 0;
+    }
+
+    AUDDBG ("Opening audio for %d channels, %d Hz.\n", chan, rate);
+
+    chan = chan_;
+    rate = rate_;
+
+    buffer_bytes_per_channel = m->mBytesPerChannel;
+
+    int buffer_size = buffer_bytes_per_channel * chan * (aud_get_int (nullptr, "output_buffer_size") * rate / 1000);
+    buffer.alloc (buffer_size);
+
+    prebuffer_flag = true;
+    paused_flag = false;
+
+    if (AudioUnitInitialize (output_instance))
+    {
+        error ("Unable to initialize audio unit instance\n");
+        return 0;
+    }
+
+    AudioStreamBasicDescription streamFormat;
+    streamFormat.mSampleRate = rate;
+    streamFormat.mFormatID = kAudioFormatLinearPCM;
+    streamFormat.mFormatFlags = m->mFormatFlags;
+    streamFormat.mFramesPerPacket = 1;
+    streamFormat.mChannelsPerFrame = chan;
+    streamFormat.mBitsPerChannel = m->mBitsPerChannel;
+    streamFormat.mBytesPerPacket = chan * buffer_bytes_per_channel;
+    streamFormat.mBytesPerFrame = chan * buffer_bytes_per_channel;
+
+    AUDDBG("Stream format:\n");
+    AUDDBG(" Channels: %d\n", streamFormat.mChannelsPerFrame);
+    AUDDBG(" Sample rate: %f\n", streamFormat.mSampleRate);
+    AUDDBG(" Bits per channel: %d\n", streamFormat.mBitsPerChannel);
+    AUDDBG(" Bytes per frame: %d\n", streamFormat.mBytesPerFrame);
+
+    if (AudioUnitSetProperty (output_instance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(streamFormat)))
+    {
+        error ("Failed to set audio unit input property.\n");
+        buffer.destroy ();
+        return 0;
+    }
+
+    bool exclusive = aud_get_bool ("coreaudio", "exclusive_mode");
+    if (exclusive)
+    {
+        UInt32 hog_mode = 1;
+
+        AudioObjectPropertyAddress prop;
+
+        prop.mSelector = kAudioDevicePropertyHogMode;
+        prop.mScope    = kAudioObjectPropertyScopeGlobal;
+        prop.mElement  = kAudioObjectPropertyElementMaster;
+
+        OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, NULL, sizeof hog_mode, & hog_mode);
+        if (err != noErr)
+        {
+            AUDWARN ("Failed to open device for exclusive mode, continuing anyway... [%d]\n", err);
+            is_exclusive = false;
+        }
+        else
+            is_exclusive = true;
+    }
+
+    if (AudioOutputUnitStart (output_instance))
+    {
+        error ("Unable to start audio unit.\n");
+        buffer.destroy ();
+        return 0;
+    }
+
+    return 1;
+}
+
+void CoreAudioPlugin::close_audio ()
+{
+    AUDDBG ("Closing audio.\n");
+
+    AudioOutputUnitStop (output_instance);
+
+    if (is_exclusive)
+    {
+        UInt32 hog_mode = 0;
+
+        AudioObjectPropertyAddress prop;
+
+        prop.mSelector = kAudioDevicePropertyHogMode;
+        prop.mScope    = kAudioObjectPropertyScopeGlobal;
+        prop.mElement  = kAudioObjectPropertyElementMaster;
+
+        OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, NULL, sizeof hog_mode, & hog_mode);
+        if (err != noErr)
+            AUDWARN ("Failed to release device from exclusive mode, continuing anyway...");
+
+        is_exclusive = false;
+    }
+
+    buffer.destroy ();
+}
+
+void CoreAudioPlugin::check_started ()
+{
+    if (! prebuffer_flag)
+        return;
+
+    AUDDBG ("Starting playback.\n");
+    prebuffer_flag = false;
+    block_delay = 0;
+}
+
+void CoreAudioPlugin::period_wait ()
+{
+    pthread_mutex_lock (& mutex);
+
+    while (! buffer.space ())
+    {
+        if (! paused_flag)
+            check_started ();
+
+        pthread_cond_wait (& cond, & mutex);
+    }
+
+    pthread_mutex_unlock (& mutex);
+}
+
+int CoreAudioPlugin::write_audio (const void * data, int len)
+{
+    pthread_mutex_lock (& mutex);
+
+    len = aud::min (len, buffer.space ());
+    buffer.copy_in ((const unsigned char *) data, len);
+
+    pthread_mutex_unlock (& mutex);
+    return len;
+}
+
+void CoreAudioPlugin::drain ()
+{
+    AUDDBG ("Draining.\n");
+    pthread_mutex_lock (& mutex);
+
+    check_started ();
+
+    while (buffer.len ())
+        pthread_cond_wait (& cond, & mutex);
+
+    pthread_mutex_unlock (& mutex);
+}
+
+int CoreAudioPlugin::get_delay ()
+{
+    auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
+        { return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
+
+    pthread_mutex_lock (& mutex);
+
+    int delay = aud::rescale (buffer.len (), buffer_bytes_per_channel * chan * rate, 1000);
+
+    /* Estimate the additional delay of the last block written. */
+    if (! prebuffer_flag && ! paused_flag && block_delay)
+    {
+        struct timeval cur;
+        gettimeofday (& cur, nullptr);
+
+        delay += aud::max (block_delay - timediff (block_time, cur), (int64_t) 0);
+    }
+
+    pthread_mutex_unlock (& mutex);
+    return delay;
+}
+
+void CoreAudioPlugin::pause (bool pause)
+{
+    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
+    pthread_mutex_lock (& mutex);
+
+    paused_flag = pause;
+
+    if (pause)
+        AudioOutputUnitStop (output_instance);
+    else
+    {
+        if (AudioOutputUnitStart (output_instance))
+        {
+            error ("Unable to restart audio unit after pausing.\n");
+            close_audio ();
+        }
+    }
+
+    pthread_cond_broadcast (& cond); /* wake up period wait */
+    pthread_mutex_unlock (& mutex);
+}
+
+void CoreAudioPlugin::flush ()
+{
+    AUDDBG ("Seek requested; discarding buffer.\n");
+    pthread_mutex_lock (& mutex);
+
+    buffer.discard ();
+
+    prebuffer_flag = true;
+
+    pthread_cond_broadcast (& cond); /* wake up period wait */
+    pthread_mutex_unlock (& mutex);
+}
diff --git a/src/crossfade/Makefile b/src/crossfade/Makefile
index 6a7601269660..ab7243de0c2c 100644
--- a/src/crossfade/Makefile
+++ b/src/crossfade/Makefile
@@ -1,12 +1,12 @@
 PLUGIN = crossfade${PLUGIN_SUFFIX}
 
-SRCS = crossfade.c
+SRCS = crossfade.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/crossfade/crossfade.c b/src/crossfade/crossfade.c
deleted file mode 100644
index 711451103524..000000000000
--- a/src/crossfade/crossfade.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Crossfade Plugin for Audacious
- * Copyright 2010-2012 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 <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-enum
-{
-    STATE_OFF,
-    STATE_PREBUFFER,
-    STATE_RUNNING,
-    STATE_BETWEEN,
-    STATE_STOPPING,
-};
-
-static const char * const crossfade_defaults[] = {
- "length", "3",
- NULL};
-
-static char state = STATE_OFF;
-static int current_channels = 0, current_rate = 0;
-static float * buffer = NULL;
-static int buffer_size = 0, buffer_filled = 0;
-static int prebuffer_filled = 0;
-static float * output = NULL;
-static int output_size = 0;
-
-static void reset (void)
-{
-    state = STATE_OFF;
-    current_channels = 0;
-    current_rate = 0;
-    g_free (buffer);
-    buffer = NULL;
-    buffer_size = 0;
-    buffer_filled = 0;
-    prebuffer_filled = 0;
-    g_free (output);
-    output = NULL;
-    output_size = 0;
-}
-
-static bool_t crossfade_init (void)
-{
-    aud_config_set_defaults ("crossfade", crossfade_defaults);
-    return TRUE;
-}
-
-static void crossfade_cleanup (void)
-{
-    reset ();
-}
-
-static void crossfade_start (int * channels, int * rate)
-{
-    if (state != STATE_BETWEEN)
-        reset ();
-    else if (* channels != current_channels)
-    {
-        aud_interface_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."));
-        reset ();
-    }
-    else if (* rate != current_rate)
-    {
-        aud_interface_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."));
-        reset ();
-    }
-
-    state = STATE_PREBUFFER;
-    current_channels = * channels;
-    current_rate = * rate;
-    prebuffer_filled = 0;
-}
-
-static void do_ramp (float * data, int length, float a, float b)
-{
-    int count;
-
-    for (count = 0; count < length; count ++)
-    {
-        * data = (* data) * (a * (length - count) + b * count) / length;
-        data ++;
-    }
-}
-
-static void mix (float * data, float * new, int length)
-{
-    while (length --)
-        (* data ++) += (* new ++);
-}
-
-static void enlarge_buffer (int length)
-{
-    if (length > buffer_size)
-    {
-        buffer = g_renew (float, buffer, length);
-        buffer_size = length;
-    }
-}
-
-static void add_data (float * data, int length)
-{
-    if (state == STATE_PREBUFFER)
-    {
-        int full = current_channels * current_rate * aud_get_int ("crossfade", "length");
-
-        if (prebuffer_filled < full)
-        {
-            int copy = MIN (length, full - prebuffer_filled);
-            float a = (float) prebuffer_filled / full;
-            float b = (float) (prebuffer_filled + copy) / full;
-
-            if (prebuffer_filled + copy > buffer_filled)
-            {
-                enlarge_buffer (prebuffer_filled + copy);
-                memset (buffer + buffer_filled, 0, sizeof (float) *
-                 (prebuffer_filled + copy - buffer_filled));
-                buffer_filled = prebuffer_filled + copy;
-            }
-
-            do_ramp (data, copy, a, b);
-            mix (buffer + prebuffer_filled, data, copy);
-            prebuffer_filled += copy;
-            data += copy;
-            length -= copy;
-        }
-
-        if (prebuffer_filled < full)
-            return;
-
-        if (prebuffer_filled < buffer_filled)
-        {
-            int copy = MIN (length, buffer_filled - prebuffer_filled);
-
-            mix (buffer + prebuffer_filled, data, copy);
-            prebuffer_filled += copy;
-            data += copy;
-            length -= copy;
-        }
-
-        if (prebuffer_filled < buffer_filled)
-            return;
-
-        state = STATE_RUNNING;
-    }
-
-    if (state != STATE_RUNNING)
-        return;
-
-    enlarge_buffer (buffer_filled + length);
-    memcpy (buffer + buffer_filled, data, sizeof (float) * length);
-    buffer_filled += length;
-}
-
-static void enlarge_output (int length)
-{
-    if (length > output_size)
-    {
-        output = g_renew (float, output, length);
-        output_size = length;
-    }
-}
-
-static void return_data (float * * data, int * length)
-{
-    int full = current_channels * current_rate * aud_get_int ("crossfade", "length");
-    int copy = buffer_filled - full;
-
-    /* only return if we have at least 1/2 second -- this reduces memmove's */
-    if (state != STATE_RUNNING || copy < current_channels * (current_rate / 2))
-    {
-        * data = NULL;
-        * length = 0;
-        return;
-    }
-
-    enlarge_output (copy);
-    memcpy (output, buffer, sizeof (float) * copy);
-    buffer_filled -= copy;
-    memmove (buffer, buffer + copy, sizeof (float) * buffer_filled);
-    * data = output;
-    * length = copy;
-}
-
-static void crossfade_process (float * * data, int * samples)
-{
-    add_data (* data, * samples);
-    return_data (data, samples);
-}
-
-static void crossfade_flush (void)
-{
-    if (state == STATE_PREBUFFER || state == STATE_RUNNING)
-    {
-        state = STATE_RUNNING;
-        buffer_filled = 0;
-    }
-}
-
-static void crossfade_finish (float * * data, int * samples)
-{
-    if (state == STATE_BETWEEN) /* second call, end of last song */
-    {
-        enlarge_output (buffer_filled);
-        memcpy (output, buffer, sizeof (float) * buffer_filled);
-        * data = output;
-        * samples = buffer_filled;
-        buffer_filled = 0;
-        state = STATE_OFF;
-        return;
-    }
-
-    add_data (* data, * samples);
-    return_data (data, samples);
-
-    if (state == STATE_PREBUFFER || state == STATE_RUNNING)
-    {
-        do_ramp (buffer, buffer_filled, 1.0, 0.0);
-        state = STATE_BETWEEN;
-    }
-}
-
-static int crossfade_adjust_delay (int delay)
-{
-    return delay + (int64_t) (buffer_filled / current_channels) * 1000 / current_rate;
-}
-
-static const char crossfade_about[] =
- N_("Crossfade Plugin for Audacious\n"
-    "Copyright 2010-2012 John Lindgren");
-
-static const PreferencesWidget crossfade_widgets[] = {
- {WIDGET_LABEL, N_("<b>Crossfade</b>")},
- {WIDGET_SPIN_BTN, N_("Overlap:"),
-  .cfg_type = VALUE_INT, .csect = "crossfade", .cname = "length",
-  .data = {.spin_btn = {1, 10, 1, N_("seconds")}}}};
-
-static const PluginPreferences crossfade_prefs = {
- .widgets = crossfade_widgets,
- .n_widgets = ARRAY_LEN (crossfade_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Crossfade"),
-    .domain = PACKAGE,
-    .about_text = crossfade_about,
-    .prefs = & crossfade_prefs,
-    .init = crossfade_init,
-    .cleanup = crossfade_cleanup,
-    .start = crossfade_start,
-    .process = crossfade_process,
-    .flush = crossfade_flush,
-    .finish = crossfade_finish,
-    .adjust_delay = crossfade_adjust_delay,
-    .order = 5, /* must be after resample and mixer */
-    .preserves_format = TRUE
-)
diff --git a/src/crossfade/crossfade.cc b/src/crossfade/crossfade.cc
new file mode 100644
index 000000000000..b7b15d7030eb
--- /dev/null
+++ b/src/crossfade/crossfade.cc
@@ -0,0 +1,308 @@
+/*
+ * Crossfade Plugin for Audacious
+ * Copyright 2010-2014 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 <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+enum
+{
+    STATE_OFF,
+    STATE_FADEIN,
+    STATE_RUNNING,
+    STATE_FINISHED,
+    STATE_FLUSHED
+};
+
+static const char * const crossfade_defaults[] = {
+    "automatic", "TRUE",
+    "length", "5",
+    "manual", "TRUE",
+    "manual_length", "0.2",
+    nullptr
+};
+
+static const char crossfade_about[] =
+ N_("Crossfade Plugin for Audacious\n"
+    "Copyright 2010-2014 John Lindgren");
+
+static const PreferencesWidget crossfade_widgets[] = {
+    WidgetLabel (N_("<b>Crossfade</b>")),
+    WidgetCheck (N_("On automatic song change"),
+        WidgetBool ("crossfade", "automatic")),
+    WidgetSpin (N_("Overlap:"),
+        WidgetFloat ("crossfade", "length"),
+        {1, 15, 0.5, N_("seconds")},
+        WIDGET_CHILD),
+    WidgetCheck (N_("On seek or manual song change"),
+        WidgetBool ("crossfade", "manual")),
+    WidgetSpin (N_("Overlap:"),
+        WidgetFloat ("crossfade", "manual_length"),
+        {0.1, 3.0, 0.1, N_("seconds")},
+        WIDGET_CHILD),
+    WidgetLabel (N_("<b>Tip</b>")),
+    WidgetLabel (N_("For better crossfading, enable\n"
+                    "the Silence Removal effect."))
+};
+
+static const PluginPreferences crossfade_prefs = {{crossfade_widgets}};
+
+class Crossfade : public EffectPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Crossfade"),
+        PACKAGE,
+        crossfade_about,
+        & crossfade_prefs
+    };
+
+    /* order #5: must be after resample and mixer */
+    constexpr Crossfade () : EffectPlugin (info, 5, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+    Index<float> & finish (Index<float> & data, bool end_of_playlist);
+    int adjust_delay (int delay);
+};
+
+EXPORT Crossfade aud_plugin_instance;
+
+static char state = STATE_OFF;
+static int current_channels = 0, current_rate = 0;
+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);
+    return true;
+}
+
+void Crossfade::cleanup ()
+{
+    reset ();
+}
+
+static void do_ramp (float * data, int length, float a, float b)
+{
+    for (int i = 0; i < length; i ++)
+    {
+        * data = (* data) * (a * (length - i) + b * i) / length;
+        data ++;
+    }
+}
+
+static void mix (float * data, float * add, int length)
+{
+    while (length --)
+        (* data ++) += (* add ++);
+}
+
+static int buffer_needed_for_state ()
+{
+    double overlap = 0;
+
+    if (state != STATE_FLUSHED && aud_get_bool ("crossfade", "automatic"))
+        overlap = aud_get_double ("crossfade", "length");
+
+    if (state != STATE_FINISHED && aud_get_bool ("crossfade", "manual"))
+        overlap = aud::max (overlap, aud_get_double ("crossfade", "manual_length"));
+
+    return current_channels * (int) (current_rate * overlap);
+}
+
+static void output_data_as_ready (int buffer_needed, bool exact)
+{
+    int copy = buffer.len () - buffer_needed;
+
+    /* if allowed, wait until we have at least 1/2 second ready to output */
+    if (exact ? (copy > 0) : (copy >= current_channels * (current_rate / 2)))
+        output.move_from (buffer, 0, -1, copy, true, true);
+}
+
+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;
+        }
+    }
+
+    if (state == STATE_OFF)
+    {
+        reset ();
+
+        current_channels = channels;
+        current_rate = rate;
+
+        if (aud_get_bool ("crossfade", "manual"))
+        {
+            state = STATE_FLUSHED;
+            buffer.insert (0, buffer_needed_for_state ());
+        }
+        else
+            state = STATE_RUNNING;
+    }
+}
+
+static void run_fadeout ()
+{
+    do_ramp (buffer.begin (), buffer.len (), 1.0, 0.0);
+
+    state = STATE_FADEIN;
+    fadein_point = 0;
+}
+
+static void run_fadein (Index<float> & data)
+{
+    int length = buffer.len ();
+
+    if (fadein_point < length)
+    {
+        int copy = aud::min (data.len (), length - fadein_point);
+        float a = (float) fadein_point / length;
+        float b = (float) (fadein_point + copy) / length;
+
+        do_ramp (data.begin (), copy, a, b);
+        mix (& buffer[fadein_point], data.begin (), copy);
+        data.remove (0, copy);
+
+        fadein_point += copy;
+    }
+
+    if (fadein_point == length)
+        state = STATE_RUNNING;
+}
+
+Index<float> & Crossfade::process (Index<float> & data)
+{
+    if (state == STATE_OFF)
+        return data;
+
+    output.resize (0);
+
+    if (state == STATE_FINISHED || state == STATE_FLUSHED)
+        run_fadeout ();
+
+    if (state == STATE_FADEIN)
+        run_fadein (data);
+
+    if (state == STATE_RUNNING)
+    {
+        buffer.insert (data.begin (), -1, data.len ());
+        output_data_as_ready (buffer_needed_for_state (), false);
+    }
+
+    return output;
+}
+
+bool Crossfade::flush (bool force)
+{
+    if (state == STATE_OFF)
+        return true;
+
+    if (! force && aud_get_bool ("crossfade", "manual"))
+    {
+        state = STATE_FLUSHED;
+        int buffer_needed = buffer_needed_for_state ();
+        if (buffer.len () > buffer_needed)
+            buffer.remove (buffer_needed, -1);
+
+        return false;
+    }
+
+    state = STATE_RUNNING;
+    buffer.resize (0);
+
+    return true;
+}
+
+Index<float> & Crossfade::finish (Index<float> & data, bool end_of_playlist)
+{
+    if (state == STATE_OFF)
+        return data;
+
+    output.resize (0);
+
+    if (state == STATE_FADEIN)
+        run_fadein (data);
+
+    if (state == STATE_RUNNING || state == STATE_FINISHED || state == STATE_FLUSHED)
+    {
+        buffer.insert (data.begin (), -1, data.len ());
+        output_data_as_ready (buffer_needed_for_state (), state != STATE_RUNNING);
+    }
+
+    if (state == STATE_FADEIN || state == STATE_RUNNING)
+    {
+        if (aud_get_bool ("crossfade", "automatic"))
+        {
+            state = STATE_FINISHED;
+            output_data_as_ready (buffer_needed_for_state (), true);
+        }
+        else
+        {
+            state = STATE_OFF;
+            output_data_as_ready (0, true);
+        }
+    }
+
+    if (end_of_playlist && (state == STATE_FINISHED || state == STATE_FLUSHED))
+    {
+        do_ramp (buffer.begin (), buffer.len (), 1.0, 0.0);
+
+        state = STATE_OFF;
+        output_data_as_ready (0, true);
+    }
+
+    return output;
+}
+
+int Crossfade::adjust_delay (int delay)
+{
+    return delay + aud::rescale<int64_t> (buffer.len () / current_channels, current_rate, 1000);
+}
diff --git a/src/crystalizer/Makefile b/src/crystalizer/Makefile
index eea09a4b4a71..3eecf6ec405e 100644
--- a/src/crystalizer/Makefile
+++ b/src/crystalizer/Makefile
@@ -1,11 +1,12 @@
 PLUGIN = crystalizer${PLUGIN_SUFFIX}
 
-SRCS = crystalizer.c
+SRCS = crystalizer.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/crystalizer/crystalizer.c b/src/crystalizer/crystalizer.c
deleted file mode 100644
index d30c28d0ef85..000000000000
--- a/src/crystalizer/crystalizer.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2008 William Pitcock <nenolod at nenolod.net>
- * Copyright (c) 2010-2012 John Lindgren <john.lindgren at tds.net>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice is present in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-static bool_t init (void);
-static void cryst_start (int * channels, int * rate);
-static void cryst_process (float * * data, int * samples);
-static void cryst_flush ();
-static void cryst_finish (float * * data, int * samples);
-
-static const char * const cryst_defaults[] = {
- "intensity", "1",
- NULL};
-
-static const PreferencesWidget cryst_widgets[] = {
- {WIDGET_LABEL, N_("<b>Crystalizer</b>")},
- {WIDGET_SPIN_BTN, N_("Intensity:"),
-  .cfg_type = VALUE_FLOAT, .csect = "crystalizer", .cname = "intensity",
-  .data = {.spin_btn = {0, 10, 0.1}}}};
-
-static const PluginPreferences cryst_prefs = {
- .widgets = cryst_widgets,
- .n_widgets = ARRAY_LEN (cryst_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Crystalizer"),
-    .domain = PACKAGE,
-    .prefs = & cryst_prefs,
-    .init = init,
-    .start = cryst_start,
-    .process = cryst_process,
-    .flush = cryst_flush,
-    .finish = cryst_finish,
-    .preserves_format = TRUE
-)
-
-static int cryst_channels;
-static float * cryst_prev;
-
-static bool_t init (void)
-{
-    aud_config_set_defaults ("crystalizer", cryst_defaults);
-    return TRUE;
-}
-
-static void cryst_start (int * channels, int * rate)
-{
-    cryst_channels = * channels;
-    cryst_prev = realloc (cryst_prev, sizeof (float) * cryst_channels);
-    memset (cryst_prev, 0, sizeof (float) * cryst_channels);
-}
-
-static void cryst_process (float * * data, int * samples)
-{
-    float value = aud_get_double ("crystalizer", "intensity");
-    float * f = * data;
-    float * end = f + (* samples);
-    int channel;
-
-    while (f < end)
-    {
-        for (channel = 0; channel < cryst_channels; channel ++)
-        {
-            float current = * f;
-
-            * f ++ = current + (current - cryst_prev[channel]) * value;
-            cryst_prev[channel] = current;
-        }
-    }
-}
-
-static void cryst_flush ()
-{
-    memset (cryst_prev, 0, sizeof (float) * cryst_channels);
-}
-
-static void cryst_finish (float * * data, int * samples)
-{
-    cryst_process (data, samples);
-}
diff --git a/src/crystalizer/crystalizer.cc b/src/crystalizer/crystalizer.cc
new file mode 100644
index 000000000000..bec4d16034c5
--- /dev/null
+++ b/src/crystalizer/crystalizer.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2008 William Pitcock <nenolod at nenolod.net>
+ * Copyright (c) 2010-2012 John Lindgren <john.lindgren at tds.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice is present in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+static const char * const cryst_defaults[] = {
+ "intensity", "1",
+ nullptr};
+
+static const PreferencesWidget cryst_widgets[] = {
+    WidgetLabel (N_("<b>Crystalizer</b>")),
+    WidgetSpin (N_("Intensity:"),
+        WidgetFloat ("crystalizer", "intensity"),
+        {0, 10, 0.1})
+};
+
+static const PluginPreferences cryst_prefs = {{cryst_widgets}};
+
+class Crystalizer : public EffectPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Crystalizer"),
+        PACKAGE,
+        nullptr,
+        & cryst_prefs
+    };
+
+    constexpr Crystalizer () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+};
+
+EXPORT Crystalizer aud_plugin_instance;
+
+static int cryst_channels;
+static Index<float> cryst_prev;
+
+bool Crystalizer::init ()
+{
+    aud_config_set_defaults ("crystalizer", cryst_defaults);
+    return true;
+}
+
+void Crystalizer::cleanup ()
+{
+    cryst_prev.clear ();
+}
+
+void Crystalizer::start (int & channels, int & rate)
+{
+    cryst_channels = channels;
+    cryst_prev.resize (cryst_channels);
+    cryst_prev.erase (0, cryst_channels);
+}
+
+Index<float> & Crystalizer::process (Index<float> & data)
+{
+    float value = aud_get_double ("crystalizer", "intensity");
+    float * f = data.begin ();
+    float * end = data.end ();
+
+    while (f < end)
+    {
+        for (int channel = 0; channel < cryst_channels; channel ++)
+        {
+            float current = * f;
+            * f ++ = current + (current - cryst_prev[channel]) * value;
+            cryst_prev[channel] = current;
+        }
+    }
+
+    return data;
+}
+
+bool Crystalizer::flush (bool force)
+{
+    cryst_prev.erase (0, cryst_channels);
+    return true;
+}
diff --git a/src/cue/Makefile b/src/cue/Makefile
index 98ce920c694b..85592bf8b956 100644
--- a/src/cue/Makefile
+++ b/src/cue/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = cue${PLUGIN_SUFFIX}
 
-SRCS = cue.c
+SRCS = cue.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
-CPPFLAGS += -I../.. ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${CUE_CFLAGS}
+LD = ${CXX}
+
+CPPFLAGS += -I../.. ${PLUGIN_CPPFLAGS} ${CUE_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += ${GLIB_LIBS} ${CUE_LIBS}
+LIBS += ${CUE_LIBS}
diff --git a/src/cue/cue.c b/src/cue/cue.c
deleted file mode 100644
index 04937aaa9155..000000000000
--- a/src/cue/cue.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Cue Sheet Plugin for Audacious
- * Copyright (c) 2009-2011 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:
- *
- * 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 <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <libcue/libcue.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-typedef struct {
-    int tuple_type;
-    int pti;
-} TuplePTIMap;
-
-TuplePTIMap pti_map[] = {
-    { FIELD_ARTIST, PTI_PERFORMER },
-    { FIELD_TITLE, PTI_TITLE },
-};
-
-static void
-tuple_attach_cdtext(Tuple *tuple, Track *track, int tuple_type, int pti)
-{
-    Cdtext *cdtext;
-    const char *text;
-
-    cdtext = track_get_cdtext(track);
-    if (cdtext == NULL)
-        return;
-
-    text = cdtext_get(pti, cdtext);
-    if (text == NULL)
-        return;
-
-    tuple_set_str (tuple, tuple_type, text);
-}
-
-static bool_t playlist_load_cue (const char * cue_filename, VFSFile * file,
- char * * title, Index * filenames, Index * tuples)
-{
-    void * buffer = NULL;
-    vfs_file_read_all (file, & buffer, NULL);
-    if (! buffer)
-        return FALSE;
-
-    * title = NULL;
-
-    Cd * cd = cue_parse_string (buffer);
-    g_free (buffer);
-    if (cd == NULL)
-        return FALSE;
-
-    int tracks = cd_get_ntrack (cd);
-    if (tracks == 0)
-        return FALSE;
-
-    Track * current = cd_get_track (cd, 1);
-    if (current == NULL)
-        return FALSE;
-
-    char * track_filename = track_get_filename (current);
-    if (track_filename == NULL)
-        return FALSE;
-
-    char * filename = aud_construct_uri (track_filename, cue_filename);
-
-    Tuple * base_tuple = NULL;
-    bool_t base_tuple_scanned = FALSE;
-
-    for (int track = 1; track <= tracks; track ++)
-    {
-        if (current == NULL || filename == NULL)
-            return FALSE;
-
-        if (base_tuple == NULL && ! base_tuple_scanned)
-        {
-            base_tuple_scanned = TRUE;
-            PluginHandle * decoder = aud_file_find_decoder (filename, FALSE);
-            if (decoder != NULL)
-                base_tuple = aud_file_read_tuple (filename, decoder);
-        }
-
-        Track * next = (track + 1 <= tracks) ? cd_get_track (cd, track + 1) : NULL;
-        char * next_filename = (next != NULL) ? aud_construct_uri
-         (track_get_filename (next), cue_filename) : NULL;
-        bool_t last_track = (next_filename == NULL || strcmp (next_filename, filename));
-
-        Tuple * tuple = (base_tuple != NULL) ? tuple_copy (base_tuple) :
-         tuple_new_from_filename (filename);
-        tuple_set_int (tuple, FIELD_TRACK_NUMBER, track);
-
-        int begin = (int64_t) track_get_start (current) * 1000 / 75;
-        tuple_set_int (tuple, FIELD_SEGMENT_START, begin);
-
-        if (last_track)
-        {
-            if (base_tuple != NULL && tuple_get_value_type (base_tuple,
-             FIELD_LENGTH) == TUPLE_INT)
-                tuple_set_int (tuple, FIELD_LENGTH, tuple_get_int
-                 (base_tuple, FIELD_LENGTH) - begin);
-        }
-        else
-        {
-            int length = (int64_t) track_get_length (current) * 1000 / 75;
-            tuple_set_int (tuple, FIELD_LENGTH, length);
-            tuple_set_int (tuple, FIELD_SEGMENT_END, begin + length);
-        }
-
-        for (int i = 0; i < ARRAY_LEN (pti_map); i ++)
-            tuple_attach_cdtext (tuple, current, pti_map[i].tuple_type, pti_map[i].pti);
-
-        index_insert (filenames, -1, str_get (filename));
-        index_insert (tuples, -1, tuple);
-
-        current = next;
-        str_unref (filename);
-        filename = next_filename;
-
-        if (last_track && base_tuple != NULL)
-        {
-            tuple_unref (base_tuple);
-            base_tuple = NULL;
-            base_tuple_scanned = FALSE;
-        }
-    }
-
-    return TRUE;
-}
-
-static const char * const cue_exts[] = {"cue", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
- .name = N_("Cue Sheet Plugin"),
- .domain = PACKAGE,
- .extensions = cue_exts,
- .load = playlist_load_cue
-)
diff --git a/src/cue/cue.cc b/src/cue/cue.cc
new file mode 100644
index 000000000000..79de658c53f5
--- /dev/null
+++ b/src/cue/cue.cc
@@ -0,0 +1,155 @@
+/*
+ * Cue Sheet Plugin for Audacious
+ * Copyright (c) 2009-2011 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:
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+extern "C" {
+#include <libcue/libcue.h>
+}
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/probe.h>
+
+static const char * const cue_exts[] = {"cue"};
+
+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,
+     Index<PlaylistAddItem> & items);
+};
+
+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)
+{
+    Index<char> buffer = file.read_all ();
+    if (! buffer.len ())
+        return false;
+
+    buffer.append (0);  /* null-terminated */
+
+    Cd * cd = cue_parse_string (buffer.begin ());
+    if (cd == nullptr)
+        return false;
+
+    int tracks = cd_get_ntrack (cd);
+    if (tracks == 0)
+        return false;
+
+    Track * current = cd_get_track (cd, 1);
+    if (current == nullptr)
+        return false;
+
+    char * track_filename = track_get_filename (current);
+    if (track_filename == nullptr)
+        return false;
+
+    String filename = String (uri_construct (track_filename, cue_filename));
+
+    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)
+        {
+            base_tuple_scanned = true;
+            PluginHandle * decoder = aud_file_find_decoder (filename, false);
+            if (decoder != nullptr)
+                base_tuple = aud_file_read_tuple (filename, decoder);
+        }
+
+        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));
+
+        Tuple tuple = base_tuple.ref ();
+        tuple.set_filename (filename);
+        tuple.set_int (Tuple::Track, track);
+
+        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
+        {
+            int length = (int64_t) track_get_length (current) * 1000 / 75;
+            tuple.set_int (Tuple::Length, length);
+            tuple.set_int (Tuple::EndTime, begin + length);
+        }
+
+        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 (last_track)
+        {
+            base_tuple = Tuple ();
+            base_tuple_scanned = false;
+        }
+    }
+
+    return true;
+}
diff --git a/src/delete-files/Makefile b/src/delete-files/Makefile
index 4002a85263d4..416a7ae9f3f2 100644
--- a/src/delete-files/Makefile
+++ b/src/delete-files/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = delete-files${PLUGIN_SUFFIX}
 
-SRCS = delete-files.c
+SRCS = delete-files.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${GIO_CFLAGS} ${GTK_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += ${GIO_LIBS} ${GTK_LIBS}
+LIBS += ${GIO_LIBS} ${GTK_LIBS} -laudgui
diff --git a/src/delete-files/delete-files.c b/src/delete-files/delete-files.c
deleted file mode 100644
index 56b0883b90d7..000000000000
--- a/src/delete-files/delete-files.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * delete-files.c
- * Copyright 2013 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <gio/gio.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-static const int menus[] = {AUD_MENU_MAIN, AUD_MENU_PLAYLIST, AUD_MENU_PLAYLIST_REMOVE};
-
-static GtkWidget * dialog = NULL;
-
-static void move_to_trash (const char * filename)
-{
-    GFile * gfile = g_file_new_for_path (filename);
-    GError * gerror = NULL;
-
-    if (! g_file_trash (gfile, NULL, & gerror))
-    {
-        SPRINTF (error, _("Error moving %s to trash: %s."), filename, gerror->message);
-        aud_interface_show_error (error);
-        g_error_free (gerror);
-    }
-
-    g_object_unref ((GObject *) gfile);
-}
-
-static void really_delete (const char * filename)
-{
-    if (g_unlink (filename) < 0)
-    {
-        SPRINTF (error, _("Error deleting %s: %s."), filename, strerror (errno));
-        aud_interface_show_error (error);
-    }
-}
-
-static void confirm_delete (void)
-{
-    Index * files = index_new ();
-
-    int playlist = aud_playlist_get_active ();
-    int entry_count = aud_playlist_entry_count (playlist);
-
-    for (int i = 0; i < entry_count; i ++)
-    {
-        if (aud_playlist_entry_get_selected (playlist, i))
-            index_insert (files, -1, aud_playlist_entry_get_filename (playlist, i));
-    }
-
-    aud_playlist_delete_selected (playlist);
-
-    int file_count = index_count (files);
-
-    for (int i = 0; i < file_count; i ++)
-    {
-        char * uri = index_get (files, i);
-        char * filename = uri_to_filename (uri);
-
-        if (filename)
-        {
-            if (aud_get_bool ("delete_files", "use_trash"))
-                move_to_trash (filename);
-            else
-                really_delete (filename);
-
-            str_unref (filename);
-        }
-        else
-        {
-            SPRINTF (error, _("Error deleting %s: not a local file."), uri);
-            aud_interface_show_error (error);
-        }
-    }
-
-    index_free_full (files, (IndexFreeFunc) str_unref);
-}
-
-static void start_delete (void)
-{
-    if (dialog)
-    {
-        gtk_window_present ((GtkWindow *) dialog);
-        return;
-    }
-
-    const char * message;
-    GtkWidget * button1, * button2;
-
-    if (aud_get_bool ("delete_files", "use_trash"))
-    {
-        message = _("Do you want to move the selected files to the trash?");
-        button1 = audgui_button_new (_("Move to Trash"), "user-trash",
-         (AudguiCallback) confirm_delete, NULL);
-    }
-    else
-    {
-        message = _("Do you want to permanently delete the selected files?");
-        button1 = audgui_button_new (_("Delete"), "edit-delete",
-         (AudguiCallback) confirm_delete, NULL);
-    }
-
-    button2 = audgui_button_new (_("Cancel"), "process-stop", NULL, NULL);
-    dialog = audgui_dialog_new (GTK_MESSAGE_QUESTION, _("Delete Files"),
-     message, button1, button2);
-
-    g_signal_connect (dialog, "destroy", (GCallback) gtk_widget_destroyed, & dialog);
-    gtk_widget_show_all (dialog);
-}
-
-static const char * const delete_files_defaults[] = {
- "use_trash", "TRUE",
- NULL};
-
-static bool_t delete_files_init (void)
-{
-    aud_config_set_defaults ("delete_files", delete_files_defaults);
-
-    for (int i = 0; i < ARRAY_LEN (menus); i ++)
-        aud_plugin_menu_add (menus[i], start_delete, _("Delete Selected Files"), "edit-delete");
-
-    return TRUE;
-}
-
-static void delete_files_cleanup (void)
-{
-    if (dialog)
-        gtk_widget_destroy (dialog);
-
-    for (int i = 0; i < ARRAY_LEN (menus); i ++)
-        aud_plugin_menu_remove (menus[i], start_delete);
-}
-
-static const PreferencesWidget delete_files_widgets[] = {
- {WIDGET_LABEL, N_("<b>Delete Method</b>")},
- {WIDGET_CHK_BTN, N_("Move to trash instead of deleting immediately"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "delete_files", .cname = "use_trash"}};
-
-static const PluginPreferences delete_files_prefs = {
- .widgets = delete_files_widgets,
- .n_widgets = ARRAY_LEN (delete_files_widgets)};
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Delete Files"),
-    .domain = PACKAGE,
-    .init = delete_files_init,
-    .cleanup = delete_files_cleanup,
-    .prefs = & delete_files_prefs,
-)
diff --git a/src/delete-files/delete-files.cc b/src/delete-files/delete-files.cc
new file mode 100644
index 000000000000..92fe939232bd
--- /dev/null
+++ b/src/delete-files/delete-files.cc
@@ -0,0 +1,186 @@
+/*
+ * delete-files.c
+ * Copyright 2013 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+class DeleteFiles : public GeneralPlugin
+{
+public:
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Delete Files"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr DeleteFiles () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT DeleteFiles aud_plugin_instance;
+
+static constexpr AudMenuID menus[] = {
+    AudMenuID::Main,
+    AudMenuID::Playlist,
+    AudMenuID::PlaylistRemove
+};
+
+static GtkWidget * dialog = nullptr;
+
+static void move_to_trash (const char * filename)
+{
+    GFile * gfile = g_file_new_for_path (filename);
+    GError * gerror = nullptr;
+
+    if (! g_file_trash (gfile, nullptr, & gerror))
+    {
+        aud_ui_show_error (str_printf (_("Error moving %s to trash: %s."),
+         filename, gerror->message));
+        g_error_free (gerror);
+    }
+
+    g_object_unref ((GObject *) gfile);
+}
+
+static void really_delete (const char * filename)
+{
+    if (g_unlink (filename) < 0)
+        aud_ui_show_error (str_printf (_("Error deleting %s: %s."), filename, strerror (errno)));
+}
+
+static void confirm_delete (void)
+{
+    Index<String> files;
+
+    int playlist = aud_playlist_get_active ();
+    int entry_count = aud_playlist_entry_count (playlist);
+
+    for (int i = 0; i < entry_count; i ++)
+    {
+        if (aud_playlist_entry_get_selected (playlist, i))
+            files.append (aud_playlist_entry_get_filename (playlist, i));
+    }
+
+    aud_playlist_delete_selected (playlist);
+
+    for (const String & uri : files)
+    {
+        StringBuf filename = uri_to_filename (uri);
+
+        if (filename)
+        {
+            if (aud_get_bool ("delete_files", "use_trash"))
+                move_to_trash (filename);
+            else
+                really_delete (filename);
+        }
+        else
+            aud_ui_show_error (str_printf
+             (_("Error deleting %s: not a local file."), (const char *) uri));
+    }
+}
+
+static void start_delete (void)
+{
+    if (dialog)
+    {
+        gtk_window_present ((GtkWindow *) dialog);
+        return;
+    }
+
+    const char * message;
+    GtkWidget * button1, * button2;
+
+    if (aud_get_bool ("delete_files", "use_trash"))
+    {
+        message = _("Do you want to move the selected files to the trash?");
+        button1 = audgui_button_new (_("Move to Trash"), "user-trash",
+         (AudguiCallback) confirm_delete, nullptr);
+    }
+    else
+    {
+        message = _("Do you want to permanently delete the selected files?");
+        button1 = audgui_button_new (_("Delete"), "edit-delete",
+         (AudguiCallback) confirm_delete, nullptr);
+    }
+
+    button2 = audgui_button_new (_("Cancel"), "process-stop", nullptr, nullptr);
+    dialog = audgui_dialog_new (GTK_MESSAGE_QUESTION, _("Delete Files"),
+     message, button1, button2);
+
+    g_signal_connect (dialog, "destroy", (GCallback) gtk_widget_destroyed, & dialog);
+    gtk_widget_show_all (dialog);
+}
+
+const char * const DeleteFiles::defaults[] = {
+ "use_trash", "TRUE",
+ nullptr};
+
+bool DeleteFiles::init (void)
+{
+#if ! GLIB_CHECK_VERSION (2, 36, 0)
+    g_type_init ();
+#endif
+
+    aud_config_set_defaults ("delete_files", defaults);
+
+    for (AudMenuID menu : menus)
+        aud_plugin_menu_add (menu, start_delete, _("Delete Selected Files"), "edit-delete");
+
+    return TRUE;
+}
+
+void DeleteFiles::cleanup (void)
+{
+    if (dialog)
+        gtk_widget_destroy (dialog);
+
+    for (AudMenuID menu : menus)
+        aud_plugin_menu_remove (menu, start_delete);
+}
+
+const PreferencesWidget DeleteFiles::widgets[] = {
+    WidgetLabel (N_("<b>Delete Method</b>")),
+    WidgetCheck (N_("Move to trash instead of deleting immediately"),
+        WidgetBool ("delete_files", "use_trash"))
+};
+
+const PluginPreferences DeleteFiles::prefs = {{widgets}};
diff --git a/src/echo_plugin/Makefile b/src/echo_plugin/Makefile
index 308de83d3c72..ca1b950c8079 100644
--- a/src/echo_plugin/Makefile
+++ b/src/echo_plugin/Makefile
@@ -1,12 +1,12 @@
 PLUGIN = echo${PLUGIN_SUFFIX}
 
-SRCS = echo.c
+SRCS = echo.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/echo_plugin/echo.c b/src/echo_plugin/echo.c
deleted file mode 100644
index 35e3ef552e79..000000000000
--- a/src/echo_plugin/echo.c
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#define MAX_DELAY 1000
-#define MAX_SRATE 50000
-#define MAX_CHANNELS 2
-#define BYTES_PS sizeof(float)
-#define BUFFER_SAMPLES (MAX_SRATE * MAX_DELAY / 1000)
-#define BUFFER_SHORTS (BUFFER_SAMPLES * MAX_CHANNELS)
-#define BUFFER_BYTES (BUFFER_SHORTS * BYTES_PS)
-
-static const char * const echo_defaults[] = {
- "delay", "500",
- "feedback", "50",
- "volume", "50",
- NULL};
-
-static const PreferencesWidget echo_widgets[] = {
- {WIDGET_LABEL, N_("<b>Echo</b>")},
- {WIDGET_SPIN_BTN, N_("Delay:"),
-  .cfg_type = VALUE_INT, .csect = "echo_plugin", .cname = "delay",
-  .data = {.spin_btn = {0, MAX_DELAY, 10, N_("ms")}}},
- {WIDGET_SPIN_BTN, N_("Feedback:"),
-  .cfg_type = VALUE_INT, .csect = "echo_plugin", .cname = "feedback",
-  .data = {.spin_btn = {0, 100, 1, "%"}}},
- {WIDGET_SPIN_BTN, N_("Volume:"),
-  .cfg_type = VALUE_INT, .csect = "echo_plugin", .cname = "volume",
-  .data = {.spin_btn = {0, 100, 1, "%"}}}};
-
-static const PluginPreferences echo_prefs = {
- .widgets = echo_widgets,
- .n_widgets = ARRAY_LEN (echo_widgets)};
-
-static float *buffer = NULL;
-static int w_ofs;
-
-static bool_t init (void)
-{
-    aud_config_set_defaults ("echo_plugin", echo_defaults);
-    return TRUE;
-}
-
-static void cleanup(void)
-{
-    g_free(buffer);
-    buffer = NULL;
-}
-
-static int echo_channels = 0;
-static int echo_rate = 0;
-
-static void echo_start(int *channels, int *rate)
-{
-    static int old_srate, old_nch;
-
-    if (buffer == NULL)
-        buffer = g_malloc (BUFFER_BYTES);
-
-    echo_channels = *channels;
-    echo_rate = *rate;
-
-    if (echo_channels != old_nch || echo_rate != old_srate)
-    {
-        memset(buffer, 0, BUFFER_BYTES);
-        w_ofs = 0;
-        old_nch = echo_channels;
-        old_srate = echo_rate;
-    }
-}
-
-static void echo_process(float **d, int *samples)
-{
-    int delay = aud_get_int ("echo_plugin", "delay");
-    int feedback = aud_get_int ("echo_plugin", "feedback");
-    int volume = aud_get_int ("echo_plugin", "volume");
-
-    float in, out, buf;
-    int r_ofs;
-    float *data = *d;
-    float *end = *d + *samples;
-
-    r_ofs = w_ofs - (echo_rate * delay / 1000) * echo_channels;
-    if (r_ofs < 0)
-        r_ofs += BUFFER_SHORTS;
-
-    for (; data < end; data++)
-    {
-        in = *data;
-
-        buf = buffer[r_ofs];
-        out = in + buf * volume / 100;
-        buf = in + buf * feedback / 100;
-        buffer[w_ofs] = buf;
-        *data = out;
-
-        if (++r_ofs >= BUFFER_SHORTS)
-            r_ofs -= BUFFER_SHORTS;
-        if (++w_ofs >= BUFFER_SHORTS)
-            w_ofs -= BUFFER_SHORTS;
-    }
-}
-
-static void echo_finish(float **d, int *samples)
-{
-    echo_process(d, samples);
-}
-
-static const char echo_about[] =
- N_("Echo Plugin\n"
-    "By Johan Levin, 1999\n\n"
-    "Surround echo by Carl van Schaik, 1999");
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Echo"),
-    .domain = PACKAGE,
-    .about_text = echo_about,
-    .prefs = & echo_prefs,
-    .init = init,
-    .cleanup = cleanup,
-    .start = echo_start,
-    .process = echo_process,
-    .finish = echo_finish,
-    .preserves_format = TRUE
-)
diff --git a/src/echo_plugin/echo.cc b/src/echo_plugin/echo.cc
new file mode 100644
index 000000000000..967361c790c1
--- /dev/null
+++ b/src/echo_plugin/echo.cc
@@ -0,0 +1,115 @@
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+#define MAX_DELAY 1000
+
+static const char echo_about[] =
+ N_("Echo Plugin\n"
+    "By Johan Levin, 1999\n"
+    "Surround echo by Carl van Schaik, 1999\n"
+    "Updated for Audacious by William Pitcock and John Lindgren, 2010-2014");
+
+static const char * const echo_defaults[] = {
+ "delay", "500",
+ "feedback", "50",
+ "volume", "50",
+ nullptr};
+
+static const PreferencesWidget echo_widgets[] = {
+    WidgetLabel (N_("<b>Echo</b>")),
+    WidgetSpin (N_("Delay:"),
+        WidgetInt ("echo_plugin", "delay"),
+        {0, MAX_DELAY, 10, N_("ms")}),
+    WidgetSpin (N_("Feedback:"),
+        WidgetInt ("echo_plugin", "feedback"),
+        {0, 100, 1, "%"}),
+    WidgetSpin (N_("Volume:"),
+        WidgetInt ("echo_plugin", "volume"),
+        {0, 100, 1, "%"})
+};
+
+static const PluginPreferences echo_prefs = {{echo_widgets}};
+
+class EchoPlugin : public EffectPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Echo"),
+        PACKAGE,
+        echo_about,
+        & echo_prefs
+    };
+
+    constexpr EchoPlugin () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+};
+
+EXPORT EchoPlugin aud_plugin_instance;
+
+static Index<float> buffer;
+static int w_ofs;
+
+bool EchoPlugin::init ()
+{
+    aud_config_set_defaults ("echo_plugin", echo_defaults);
+    return true;
+}
+
+void EchoPlugin::cleanup ()
+{
+    buffer.clear ();
+}
+
+static int echo_channels = 0;
+static int echo_rate = 0;
+
+void EchoPlugin::start (int & channels, int & rate)
+{
+    if (channels != echo_channels || rate != echo_rate)
+    {
+        echo_channels = channels;
+        echo_rate = rate;
+
+        buffer.resize (aud::rescale (MAX_DELAY, 1000, rate) * channels);
+        buffer.erase (0, -1);
+
+        w_ofs = 0;
+    }
+}
+
+Index<float> & EchoPlugin::process (Index<float> & data)
+{
+    int delay = aud_get_int ("echo_plugin", "delay");
+    float feedback = aud_get_int ("echo_plugin", "feedback") / 100.0f;
+    float volume = aud_get_int ("echo_plugin", "volume") / 100.0f;
+
+    int interval = aud::rescale (delay, 1000, echo_rate) * echo_channels;
+    interval = aud::clamp (interval, 0, buffer.len ());  // sanity check
+
+    int r_ofs = w_ofs - interval;
+    if (r_ofs < 0)
+        r_ofs += buffer.len ();
+
+    float * end = data.end ();
+
+    for (float * f = data.begin (); f < end; f++)
+    {
+        float in = * f;
+        float buf = buffer[r_ofs];
+
+        * f = in + buf * volume;
+        buffer[w_ofs] = in + buf * feedback;
+
+        r_ofs = (r_ofs + 1) % buffer.len ();
+        w_ofs = (w_ofs + 1) % buffer.len ();
+    }
+
+    return data;
+}
diff --git a/src/ffaudio/Makefile b/src/ffaudio/Makefile
index 20433de831e3..c127287561d3 100644
--- a/src/ffaudio/Makefile
+++ b/src/ffaudio/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = ffaudio${PLUGIN_SUFFIX}
 
-SRCS = ffaudio-core.c ffaudio-io.c
+SRCS = ffaudio-core.cc ffaudio-io.cc itunes-cover.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${FFMPEG_CFLAGS} -I../.. -std=c99 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE
-LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${FFMPEG_LIBS} -laudtag
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${FFMPEG_CFLAGS} -I../..
+LIBS += ${FFMPEG_LIBS} -laudtag
diff --git a/src/ffaudio/ffaudio-core.c b/src/ffaudio/ffaudio-core.c
deleted file mode 100644
index b3a81abb6458..000000000000
--- a/src/ffaudio/ffaudio-core.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Audacious FFaudio Plugin
- * Copyright © 2009 William Pitcock <nenolod at dereferenced.org>
- *                  Matti Hämäläinen <ccr at tnsp.org>
- * Copyright © 2011 John Lindgren <john.lindgren at tds.net>
- *
- * 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
- */
-
-/*
- * NOTE: Using libav with this code is entirely unsupported.  Do so at your own
- * risk.  Any bugs filed against this plugin on systems using libav will be rejected
- * by us.
- */
-
-#include <glib.h>
-#include <pthread.h>
-
-#undef FFAUDIO_DOUBLECHECK  /* Doublecheck probing result for debugging purposes */
-#undef FFAUDIO_NO_BLACKLIST /* Don't blacklist any recognized codecs/formats */
-
-#include "ffaudio-stdinc.h"
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/debug.h>
-#include <audacious/audtag.h>
-#include <libaudcore/audstrings.h>
-
-static pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;
-static GHashTable * extension_dict = NULL;
-
-typedef struct
-{
-    int stream_idx;
-    AVStream * stream;
-    AVCodecContext * context;
-    AVCodec * codec;
-}
-CodecInfo;
-
-static gint lockmgr (void * * mutexp, enum AVLockOp op)
-{
-    switch (op)
-    {
-    case AV_LOCK_CREATE:
-        * mutexp = g_slice_new (pthread_mutex_t);
-        pthread_mutex_init (* mutexp, NULL);
-        break;
-    case AV_LOCK_OBTAIN:
-        pthread_mutex_lock (* mutexp);
-        break;
-    case AV_LOCK_RELEASE:
-        pthread_mutex_unlock (* mutexp);
-        break;
-    case AV_LOCK_DESTROY:
-        pthread_mutex_destroy (* mutexp);
-        g_slice_free (pthread_mutex_t, * mutexp);
-        break;
-    }
-
-    return 0;
-}
-
-static gboolean ffaudio_init (void)
-{
-    av_register_all();
-    av_lockmgr_register (lockmgr);
-
-    return TRUE;
-}
-
-static void
-ffaudio_cleanup(void)
-{
-    if (extension_dict)
-        g_hash_table_destroy (extension_dict);
-
-    av_lockmgr_register (NULL);
-}
-
-static const gchar * ffaudio_strerror (gint error)
-{
-    static gchar buf[256];
-    return (! av_strerror (error, buf, sizeof buf)) ? buf : "unknown error";
-}
-
-static GHashTable * create_extension_dict (void)
-{
-    GHashTable * dict = g_hash_table_new_full (g_str_hash, g_str_equal,
-     (GDestroyNotify) str_unref, NULL);
-
-    AVInputFormat * f;
-    for (f = av_iformat_next (NULL); f; f = av_iformat_next (f))
-    {
-        if (! f->extensions)
-            continue;
-
-        gchar * exts = g_ascii_strdown (f->extensions, -1);
-
-        gchar * parse, * next;
-        for (parse = exts; parse; parse = next)
-        {
-            next = strchr (parse, ',');
-            if (next)
-            {
-                * next = 0;
-                next ++;
-            }
-
-            g_hash_table_insert (dict, str_get(parse), f);
-        }
-
-        g_free (exts);
-    }
-
-    return dict;
-}
-
-static AVInputFormat * get_format_by_extension (const gchar * name)
-{
-    const gchar * ext0, * sub;
-    uri_parse (name, NULL, & ext0, & sub, NULL);
-
-    if (ext0 == sub)
-        return NULL;
-
-    gchar * ext = g_ascii_strdown (ext0 + 1, sub - ext0 - 1);
-
-    AUDDBG ("Get format by extension: %s\n", name);
-    pthread_mutex_lock (& data_mutex);
-
-    if (! extension_dict)
-        extension_dict = create_extension_dict ();
-
-    AVInputFormat * f = g_hash_table_lookup (extension_dict, ext);
-    pthread_mutex_unlock (& data_mutex);
-
-    if (f)
-        AUDDBG ("Format %s.\n", f->name);
-    else
-        AUDDBG ("Format unknown.\n");
-
-    g_free (ext);
-    return f;
-}
-
-static AVInputFormat * get_format_by_content (const gchar * name, VFSFile * file)
-{
-    AUDDBG ("Get format by content: %s\n", name);
-
-    AVInputFormat * f = NULL;
-
-    guchar buf[16384 + AVPROBE_PADDING_SIZE];
-    gint size = 16;
-    gint filled = 0;
-    gint target = 100;
-    gint score = 0;
-
-    while (1)
-    {
-        if (filled < size)
-            filled += vfs_fread (buf + filled, 1, size - filled, file);
-
-        memset (buf + filled, 0, AVPROBE_PADDING_SIZE);
-        AVProbeData d = {name, buf, filled};
-        score = target;
-
-        f = av_probe_input_format2 (& d, TRUE, & score);
-        if (f)
-            break;
-
-        if (size < 16384 && filled == size)
-            size *= 4;
-        else if (target > 10)
-            target = 10;
-        else
-            break;
-    }
-
-    if (f)
-        AUDDBG ("Format %s, buffer size %d, score %d.\n", f->name, filled, score);
-    else
-        AUDDBG ("Format unknown.\n");
-
-    if (vfs_fseek (file, 0, SEEK_SET) < 0)
-        ; /* ignore errors here */
-
-    return f;
-}
-
-static AVInputFormat * get_format (const gchar * name, VFSFile * file)
-{
-    AVInputFormat * f = get_format_by_extension (name);
-    return f ? f : get_format_by_content (name, file);
-}
-
-static AVFormatContext * open_input_file (const gchar * name, VFSFile * file)
-{
-    AVInputFormat * f = get_format (name, file);
-
-    if (! f)
-    {
-        fprintf (stderr, "ffaudio: Unknown format for %s.\n", name);
-        return NULL;
-    }
-
-    AVFormatContext * c = avformat_alloc_context ();
-    AVIOContext * io = io_context_new (file);
-    c->pb = io;
-
-    gint ret = avformat_open_input (& c, name, f, NULL);
-
-    if (ret < 0)
-    {
-        fprintf (stderr, "ffaudio: avformat_open_input failed for %s: %s.\n", name, ffaudio_strerror (ret));
-        io_context_free (io);
-        return NULL;
-    }
-
-    return c;
-}
-
-static void close_input_file (AVFormatContext * c)
-{
-    AVIOContext * io = c->pb;
-
-#if CHECK_LIBAVFORMAT_VERSION (53, 24, 1)
-    avformat_close_input (&c);
-#else
-    av_close_input_file (c);
-#endif
-
-    io_context_free (io);
-}
-
-static bool_t find_codec (AVFormatContext * c, CodecInfo * cinfo)
-{
-    avformat_find_stream_info (c, NULL);
-
-    for (int i = 0; i < c->nb_streams; i++)
-    {
-        AVStream * stream = c->streams[i];
-
-        if (stream && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
-        {
-            AVCodec * codec = avcodec_find_decoder (stream->codec->codec_id);
-
-            if (codec)
-            {
-                cinfo->stream_idx = i;
-                cinfo->stream = stream;
-                cinfo->context = stream->codec;
-                cinfo->codec = codec;
-
-                return TRUE;
-            }
-        }
-    }
-
-    return FALSE;
-}
-
-static gboolean
-ffaudio_codec_is_seekable(AVCodec *codec)
-{
-    /*
-     * Blacklist certain codecs from seeking, which have problems.  Codecs which have
-     * problems with seeking should have bugs reported to upstream FFmpeg.  --nenolod
-     */
-    switch (codec->id) {
-#ifndef FFAUDIO_NO_BLACKLIST
-#if CHECK_LIBAVCODEC_VERSION(54, 25, 0)
-        case AV_CODEC_ID_MUSEPACK8:
-#else
-        case CODEC_ID_MUSEPACK8:
-#endif
-            AUDDBG("codec is blacklisted from seeking\n");
-            return FALSE;
-#endif
-        default:
-            return TRUE;
-    }
-}
-
-static gboolean ffaudio_probe (const gchar * filename, VFSFile * file)
-{
-    if (! file)
-        return FALSE;
-
-    return get_format (filename, file) ? TRUE : FALSE;
-}
-
-typedef struct {
-    TupleValueType ttype;   /* Tuple field value type */
-    gint field;             /* Tuple field constant */
-    gchar *keys[5];         /* Keys to match (case-insensitive), ended by NULL */
-} ffaudio_meta_t;
-
-static const ffaudio_meta_t metaentries[] = {
- {TUPLE_STRING, FIELD_ARTIST,       {"author", "hor", "artist", NULL}},
- {TUPLE_STRING, FIELD_TITLE,        {"title", "le", NULL}},
- {TUPLE_STRING, FIELD_ALBUM,        {"album", "WM/AlbumTitle", NULL}},
- {TUPLE_STRING, FIELD_PERFORMER,    {"performer", NULL}},
- {TUPLE_STRING, FIELD_COPYRIGHT,    {"copyright", NULL}},
- {TUPLE_STRING, FIELD_GENRE,        {"genre", "WM/Genre", NULL}},
- {TUPLE_STRING, FIELD_COMMENT,      {"comment", NULL}},
- {TUPLE_STRING, FIELD_COMPOSER,     {"composer", NULL}},
- {TUPLE_INT,    FIELD_YEAR,         {"year", "WM/Year", "date", NULL}},
- {TUPLE_INT,    FIELD_TRACK_NUMBER, {"track", "WM/TrackNumber", NULL}},
-};
-
-static void read_metadata_dict (Tuple * tuple, AVDictionary * dict)
-{
-    for (int i = 0; i < ARRAY_LEN (metaentries); i ++)
-    {
-        const ffaudio_meta_t * m = & metaentries[i];
-        AVDictionaryEntry * entry = NULL;
-
-        for (int j = 0; ! entry && m->keys[j]; j ++)
-            entry = av_dict_get (dict, m->keys[j], NULL, 0);
-
-        if (entry && entry->value)
-        {
-            if (m->ttype == TUPLE_STRING)
-                tuple_set_str (tuple, m->field, entry->value);
-            else if (m->ttype == TUPLE_INT)
-                tuple_set_int (tuple, m->field, atoi (entry->value));
-        }
-    }
-}
-
-static Tuple * read_tuple (const gchar * filename, VFSFile * file)
-{
-    Tuple * tuple = NULL;
-    AVFormatContext * ic = open_input_file (filename, file);
-
-    if (ic)
-    {
-        CodecInfo cinfo;
-
-        if (find_codec (ic, & cinfo))
-        {
-            tuple = tuple_new_from_filename (filename);
-
-            tuple_set_int (tuple, FIELD_LENGTH, ic->duration / 1000);
-            tuple_set_int (tuple, FIELD_BITRATE, ic->bit_rate / 1000);
-
-            if (cinfo.codec->long_name)
-                tuple_set_str (tuple, FIELD_CODEC, cinfo.codec->long_name);
-
-            if (ic->metadata)
-                read_metadata_dict (tuple, ic->metadata);
-            if (cinfo.stream->metadata)
-                read_metadata_dict (tuple, cinfo.stream->metadata);
-        }
-
-        close_input_file (ic);
-    }
-
-    return tuple;
-}
-
-static Tuple *
-ffaudio_probe_for_tuple(const gchar *filename, VFSFile *fd)
-{
-    if (! fd)
-        return NULL;
-
-    Tuple * t = read_tuple (filename, fd);
-    if (t == NULL)
-        return NULL;
-
-    if (! vfs_fseek (fd, 0, SEEK_SET))
-        tag_tuple_read (t, fd);
-
-    return t;
-}
-
-static gboolean ffaudio_write_tag (const char * filename, VFSFile * file, const Tuple * tuple)
-{
-    if (! file)
-        return FALSE;
-
-    if (str_has_suffix_nocase (vfs_get_filename (file), ".ape"))
-        return tag_tuple_write(tuple, file, TAG_TYPE_APE);
-
-    return tag_tuple_write(tuple, file, TAG_TYPE_NONE);
-}
-
-static gboolean ffaudio_play (const gchar * filename, VFSFile * file)
-{
-    AUDDBG ("Playing %s.\n", filename);
-    if (! file)
-        return FALSE;
-
-    AVPacket pkt = {.data = NULL};
-    gint errcount;
-    gboolean codec_opened = FALSE;
-    gint out_fmt;
-    gboolean planar;
-    gboolean seekable;
-    gboolean error = FALSE;
-
-    void *buf = NULL;
-    gint bufsize = 0;
-
-    AVFormatContext * ic = open_input_file (filename, file);
-    if (! ic)
-        return FALSE;
-
-    CodecInfo cinfo;
-
-    if (! find_codec (ic, & cinfo))
-    {
-        fprintf (stderr, "ffaudio: No codec found for %s.\n", filename);
-        goto error_exit;
-    }
-
-    AUDDBG("got codec %s for stream index %d, opening\n", cinfo.codec->name, cinfo.stream_idx);
-
-    if (avcodec_open2 (cinfo.context, cinfo.codec, NULL) < 0)
-        goto error_exit;
-
-    codec_opened = TRUE;
-
-    switch (cinfo.context->sample_fmt)
-    {
-        case AV_SAMPLE_FMT_U8: out_fmt = FMT_U8; planar = FALSE; break;
-        case AV_SAMPLE_FMT_S16: out_fmt = FMT_S16_NE; planar = FALSE; break;
-        case AV_SAMPLE_FMT_S32: out_fmt = FMT_S32_NE; planar = FALSE; break;
-        case AV_SAMPLE_FMT_FLT: out_fmt = FMT_FLOAT; planar = FALSE; break;
-
-        case AV_SAMPLE_FMT_U8P: out_fmt = FMT_U8; planar = TRUE; break;
-        case AV_SAMPLE_FMT_S16P: out_fmt = FMT_S16_NE; planar = TRUE; break;
-        case AV_SAMPLE_FMT_S32P: out_fmt = FMT_S32_NE; planar = TRUE; break;
-        case AV_SAMPLE_FMT_FLTP: out_fmt = FMT_FLOAT; planar = TRUE; break;
-
-    default:
-        fprintf (stderr, "ffaudio: Unsupported audio format %d\n", (int) cinfo.context->sample_fmt);
-        goto error_exit;
-    }
-
-    /* Open audio output */
-    AUDDBG("opening audio output\n");
-
-    if (aud_input_open_audio(out_fmt, cinfo.context->sample_rate, cinfo.context->channels) <= 0)
-    {
-        error = TRUE;
-        goto error_exit;
-    }
-
-    AUDDBG("setting parameters\n");
-
-    aud_input_set_bitrate(ic->bit_rate);
-
-    errcount = 0;
-    seekable = ffaudio_codec_is_seekable(cinfo.codec);
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_value = aud_input_check_seek ();
-
-        if (seek_value >= 0 && seekable)
-        {
-            if (av_seek_frame (ic, -1, (gint64) seek_value * AV_TIME_BASE /
-             1000, AVSEEK_FLAG_ANY) < 0)
-            {
-                _ERROR("error while seeking\n");
-            } else
-                errcount = 0;
-
-            seek_value = -1;
-        }
-
-        AVPacket tmp;
-        gint ret;
-
-        /* Read next frame (or more) of data */
-        if ((ret = av_read_frame(ic, &pkt)) < 0)
-        {
-            if (ret == AVERROR_EOF)
-            {
-                AUDDBG("eof reached\n");
-                break;
-            }
-            else
-            {
-                if (++errcount > 4)
-                {
-                    _ERROR("av_read_frame error %d, giving up.\n", ret);
-                    break;
-                } else
-                    continue;
-            }
-        } else
-            errcount = 0;
-
-        /* Ignore any other substreams */
-        if (pkt.stream_index != cinfo.stream_idx)
-        {
-            av_free_packet(&pkt);
-            continue;
-        }
-
-        /* Decode and play packet/frame */
-        memcpy(&tmp, &pkt, sizeof(tmp));
-        while (tmp.size > 0 && ! aud_input_check_stop ())
-        {
-            /* Check for seek request and bail out if we have one */
-            if (seek_value < 0)
-                seek_value = aud_input_check_seek ();
-
-            if (seek_value >= 0)
-                break;
-
-#if CHECK_LIBAVCODEC_VERSION (55, 28, 1)
-            AVFrame * frame = av_frame_alloc ();
-#else
-            AVFrame * frame = avcodec_alloc_frame ();
-#endif
-            int decoded = 0;
-            int len = avcodec_decode_audio4 (cinfo.context, frame, & decoded, & tmp);
-
-            if (len < 0)
-            {
-                fprintf (stderr, "ffaudio: decode_audio() failed, code %d\n", len);
-                break;
-            }
-
-            tmp.size -= len;
-            tmp.data += len;
-
-            if (! decoded)
-                continue;
-
-            gint size = FMT_SIZEOF (out_fmt) * cinfo.context->channels * frame->nb_samples;
-
-            if (planar)
-            {
-                if (bufsize < size)
-                {
-                    buf = g_realloc (buf, size);
-                    bufsize = size;
-                }
-
-                audio_interlace ((const void * *) frame->data, out_fmt,
-                 cinfo.context->channels, buf, frame->nb_samples);
-                aud_input_write_audio (buf, size);
-            }
-            else
-                aud_input_write_audio (frame->data[0], size);
-
-#if CHECK_LIBAVCODEC_VERSION (55, 28, 1)
-            av_frame_free (& frame);
-#else
-            avcodec_free_frame (& frame);
-#endif
-        }
-
-        if (pkt.data)
-            av_free_packet(&pkt);
-    }
-
-error_exit:
-    if (pkt.data)
-        av_free_packet(&pkt);
-    if (codec_opened)
-        avcodec_close(cinfo.context);
-    if (ic != NULL)
-        close_input_file(ic);
-
-    g_free (buf);
-
-    return ! error;
-}
-
-static const char ffaudio_about[] =
- N_("Multi-format audio decoding plugin for Audacious using\n"
-    "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
-    "\n"
-    "Audacious plugin by:\n"
-    "William Pitcock <nenolod at nenolod.net>\n"
-    "Matti Hämäläinen <ccr at tnsp.org>");
-
-static const gchar *ffaudio_fmts[] = {
-    /* musepack, SV7/SV8 */
-    "mpc", "mp+", "mpp",
-
-    /* windows media audio */
-    "wma",
-
-    /* shorten */
-    "shn",
-
-    /* atrac3 */
-    "aa3", "oma",
-
-    /* MPEG 2/4 AC3 */
-    "ac3",
-
-    /* monkey's audio */
-    "ape",
-
-    /* VQF */
-    "vqf",
-
-    /* Apple Lossless */
-    "m4a",
-
-    /* WAV (there are some WAV formats sndfile can't handle) */
-    "wav",
-
-    /* Handle OGG streams (FLAC/Vorbis etc.) */
-    "ogg", "oga",
-
-    /* Opus */
-    "opus",
-
-    /* Speex */
-    "spx",
-
-    /* end of table */
-    NULL
-};
-
-static const char * const ffaudio_mimes[] = {"application/ogg", NULL};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("FFmpeg Plugin"),
-    .domain = PACKAGE,
-    .about_text = ffaudio_about,
-    .init = ffaudio_init,
-    .cleanup = ffaudio_cleanup,
-    .extensions = ffaudio_fmts,
-    .mimes = ffaudio_mimes,
-    .is_our_file_from_vfs = ffaudio_probe,
-    .probe_for_tuple = ffaudio_probe_for_tuple,
-    .play = ffaudio_play,
-    .update_song_tuple = ffaudio_write_tag,
-
-    /* lowest priority fallback */
-    .priority = 10,
-)
diff --git a/src/ffaudio/ffaudio-core.cc b/src/ffaudio/ffaudio-core.cc
new file mode 100644
index 000000000000..b10b2459e21d
--- /dev/null
+++ b/src/ffaudio/ffaudio-core.cc
@@ -0,0 +1,622 @@
+/*
+ * Audacious FFaudio Plugin
+ * Copyright © 2009 William Pitcock <nenolod at dereferenced.org>
+ *                  Matti Hämäläinen <ccr at tnsp.org>
+ * Copyright © 2011 John Lindgren <john.lindgren at tds.net>
+ *
+ * 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
+ */
+
+#include <pthread.h>
+
+#undef FFAUDIO_DOUBLECHECK  /* Doublecheck probing result for debugging purposes */
+#undef FFAUDIO_NO_BLACKLIST /* Don't blacklist any recognized codecs/formats */
+
+#include "ffaudio-stdinc.h"
+
+#include <audacious/audtag.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/multihash.h>
+#include <libaudcore/runtime.h>
+
+class FFaudio : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[], * const mimes[];
+
+    static constexpr PluginInfo info = {
+        N_("FFmpeg Plugin"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagWritesTag)
+        .with_priority (10) /* lowest priority fallback */
+        .with_exts (exts)
+        .with_mimes (mimes);
+
+    constexpr FFaudio () : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    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 write_tuple (const char * filename, VFSFile & file, const Tuple & tuple);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT FFaudio aud_plugin_instance;
+
+typedef struct
+{
+    int stream_idx;
+    AVStream * stream;
+    AVCodecContext * context;
+    AVCodec * codec;
+}
+CodecInfo;
+
+static SimpleHash<String, AVInputFormat *> extension_dict;
+
+static void create_extension_dict ();
+
+static int lockmgr (void * * mutexp, enum AVLockOp op)
+{
+    switch (op)
+    {
+    case AV_LOCK_CREATE:
+        * mutexp = new pthread_mutex_t;
+        pthread_mutex_init ((pthread_mutex_t *) * mutexp, nullptr);
+        break;
+    case AV_LOCK_OBTAIN:
+        pthread_mutex_lock ((pthread_mutex_t *) * mutexp);
+        break;
+    case AV_LOCK_RELEASE:
+        pthread_mutex_unlock ((pthread_mutex_t *) * mutexp);
+        break;
+    case AV_LOCK_DESTROY:
+        pthread_mutex_destroy ((pthread_mutex_t *) * mutexp);
+        delete (pthread_mutex_t *) * mutexp;
+        break;
+    }
+
+    return 0;
+}
+
+static void ffaudio_log_cb (void * avcl, int av_level, const char * fmt, va_list va)
+{
+    audlog::Level level = audlog::Debug;
+    char message [2048];
+
+    switch (av_level)
+    {
+    case AV_LOG_QUIET:
+        return;
+    case AV_LOG_PANIC:
+    case AV_LOG_FATAL:
+    case AV_LOG_ERROR:
+        level = audlog::Error;
+        break;
+    case AV_LOG_WARNING:
+        level = audlog::Warning;
+        break;
+    case AV_LOG_INFO:
+        level = audlog::Info;
+        break;
+    default:
+        break;
+    }
+
+    AVClass * avc = avcl ? * (AVClass * *) avcl : nullptr;
+
+    vsnprintf (message, sizeof message, fmt, va);
+
+    audlog::log (level, __FILE__, __LINE__, avc ? avc->item_name(avcl) : __FUNCTION__,
+                 "<%p> %s", avcl, message);
+}
+
+bool FFaudio::init ()
+{
+    av_register_all();
+    av_lockmgr_register (lockmgr);
+
+    create_extension_dict ();
+
+    av_log_set_callback (ffaudio_log_cb);
+
+    return true;
+}
+
+void FFaudio::cleanup ()
+{
+    extension_dict.clear ();
+
+    av_lockmgr_register (nullptr);
+}
+
+static const char * ffaudio_strerror (int error)
+{
+    static char buf[256];
+    return (! av_strerror (error, buf, sizeof buf)) ? buf : "unknown error";
+}
+
+static void create_extension_dict ()
+{
+    AVInputFormat * f;
+    for (f = av_iformat_next (nullptr); f; f = av_iformat_next (f))
+    {
+        if (! f->extensions)
+            continue;
+
+        StringBuf exts = str_tolower (f->extensions);
+        Index<String> extlist = str_list_to_index (exts, ",");
+
+        for (auto & ext : extlist)
+            extension_dict.add (ext, std::move (f));
+    }
+}
+
+static AVInputFormat * get_format_by_extension (const char * name)
+{
+    StringBuf ext = uri_get_extension (name);
+    if (! ext)
+        return nullptr;
+
+    AUDDBG ("Get format by extension: %s\n", name);
+    AVInputFormat * * f = extension_dict.lookup (String (str_tolower (ext)));
+
+    if (f && * f)
+        AUDDBG ("Format %s.\n", (* f)->name);
+    else
+        AUDDBG ("Format unknown.\n");
+
+    return f ? * f : nullptr;
+}
+
+static AVInputFormat * get_format_by_content (const char * name, VFSFile & file)
+{
+    AUDDBG ("Get format by content: %s\n", name);
+
+    AVInputFormat * f = nullptr;
+
+    unsigned char buf[16384 + AVPROBE_PADDING_SIZE];
+    int size = 16;
+    int filled = 0;
+    int target = 100;
+    int score = 0;
+
+    while (1)
+    {
+        if (filled < size)
+            filled += file.fread (buf + filled, 1, size - filled);
+
+        memset (buf + filled, 0, AVPROBE_PADDING_SIZE);
+        AVProbeData d = {name, buf, filled};
+        score = target;
+
+        f = av_probe_input_format2 (& d, true, & score);
+        if (f)
+            break;
+
+        if (size < 16384 && filled == size)
+            size *= 4;
+        else if (target > 10)
+            target = 10;
+        else
+            break;
+    }
+
+    if (f)
+        AUDDBG ("Format %s, buffer size %d, score %d.\n", f->name, filled, score);
+    else
+        AUDDBG ("Format unknown.\n");
+
+    if (file.fseek (0, VFS_SEEK_SET) < 0)
+        ; /* ignore errors here */
+
+    return f;
+}
+
+static AVInputFormat * get_format (const char * name, VFSFile & file)
+{
+    AVInputFormat * f = get_format_by_extension (name);
+    return f ? f : get_format_by_content (name, file);
+}
+
+static AVFormatContext * open_input_file (const char * name, VFSFile & file)
+{
+    AVInputFormat * f = get_format (name, file);
+
+    if (! f)
+    {
+        AUDERR ("Unknown format for %s.\n", name);
+        return nullptr;
+    }
+
+    AVFormatContext * c = avformat_alloc_context ();
+    AVIOContext * io = io_context_new (file);
+    c->pb = io;
+
+    int ret = avformat_open_input (& c, name, f, nullptr);
+
+    if (ret < 0)
+    {
+        AUDERR ("avformat_open_input failed for %s: %s.\n", name, ffaudio_strerror (ret));
+        io_context_free (io);
+        return nullptr;
+    }
+
+    return c;
+}
+
+static void close_input_file (AVFormatContext * c)
+{
+    AVIOContext * io = c->pb;
+
+#if CHECK_LIBAVFORMAT_VERSION (53, 25, 0, 53, 17, 0)
+    avformat_close_input (&c);
+#else
+    av_close_input_file (c);
+#endif
+
+    io_context_free (io);
+}
+
+static bool find_codec (AVFormatContext * c, CodecInfo * cinfo)
+{
+    avformat_find_stream_info (c, nullptr);
+
+    for (unsigned i = 0; i < c->nb_streams; i++)
+    {
+        AVStream * stream = c->streams[i];
+
+        if (stream && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        {
+            AVCodec * codec = avcodec_find_decoder (stream->codec->codec_id);
+
+            if (codec)
+            {
+                cinfo->stream_idx = i;
+                cinfo->stream = stream;
+                cinfo->context = stream->codec;
+                cinfo->codec = codec;
+
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool FFaudio::is_our_file (const char * filename, VFSFile & file)
+{
+    return (bool) get_format (filename, file);
+}
+
+static const struct {
+    Tuple::ValueType ttype;  /* Tuple field value type */
+    Tuple::Field field;      /* Tuple field constant */
+    const char * keys[5];    /* Keys to match (case-insensitive), ended by nullptr */
+} metaentries[] = {
+    {Tuple::String, Tuple::Artist, {"author", "hor", "artist", nullptr}},
+    {Tuple::String, Tuple::Title, {"title", "le", nullptr}},
+    {Tuple::String, Tuple::Album, {"album", "WM/AlbumTitle", nullptr}},
+    {Tuple::String, Tuple::Performer, {"performer", nullptr}},
+    {Tuple::String, Tuple::Copyright, {"copyright", nullptr}},
+    {Tuple::String, Tuple::Genre, {"genre", "WM/Genre", nullptr}},
+    {Tuple::String, Tuple::Comment, {"comment", nullptr}},
+    {Tuple::String, Tuple::Composer, {"composer", nullptr}},
+    {Tuple::Int, Tuple::Year, {"year", "WM/Year", "date", nullptr}},
+    {Tuple::Int, Tuple::Track, {"track", "WM/TrackNumber", nullptr}},
+};
+
+static void read_metadata_dict (Tuple & tuple, AVDictionary * dict)
+{
+    for (auto & meta : metaentries)
+    {
+        AVDictionaryEntry * entry = nullptr;
+
+        for (int j = 0; ! entry && meta.keys[j]; j ++)
+            entry = av_dict_get (dict, meta.keys[j], nullptr, 0);
+
+        if (entry && entry->value)
+        {
+            if (meta.ttype == Tuple::String)
+                tuple.set_str (meta.field, entry->value);
+            else if (meta.ttype == Tuple::Int)
+                tuple.set_int (meta.field, atoi (entry->value));
+        }
+    }
+}
+
+Tuple FFaudio::read_tuple (const char * filename, VFSFile & file)
+{
+    Tuple tuple;
+    AVFormatContext * ic = open_input_file (filename, file);
+
+    if (ic)
+    {
+        CodecInfo cinfo;
+
+        if (find_codec (ic, & cinfo))
+        {
+            tuple.set_filename (filename);
+
+            tuple.set_int (Tuple::Length, ic->duration / 1000);
+            tuple.set_int (Tuple::Bitrate, ic->bit_rate / 1000);
+
+            if (cinfo.codec->long_name)
+                tuple.set_str (Tuple::Codec, cinfo.codec->long_name);
+
+            if (ic->metadata)
+                read_metadata_dict (tuple, ic->metadata);
+            if (cinfo.stream->metadata)
+                read_metadata_dict (tuple, cinfo.stream->metadata);
+        }
+
+        close_input_file (ic);
+    }
+
+    if (tuple && ! file.fseek (0, VFS_SEEK_SET))
+        audtag::tuple_read (tuple, file);
+
+    return tuple;
+}
+
+bool FFaudio::write_tuple (const char * filename, VFSFile & file, const Tuple & tuple)
+{
+    if (str_has_suffix_nocase (filename, ".ape"))
+        return audtag::tuple_write (tuple, file, audtag::TagType::APE);
+
+    return audtag::tuple_write (tuple, file, audtag::TagType::None);
+}
+
+Index<char> FFaudio::read_image (const char * filename, VFSFile & file)
+{
+    if (str_has_suffix_nocase (filename, ".m4a") || str_has_suffix_nocase (filename, ".mp4"))
+        return read_itunes_cover (filename, file);
+
+    return Index<char> ();
+}
+
+bool FFaudio::play (const char * filename, VFSFile & file)
+{
+    AUDDBG ("Playing %s.\n", filename);
+
+    AVPacket pkt = AVPacket();
+    int errcount;
+    bool codec_opened = false;
+    int out_fmt;
+    bool planar;
+    bool error = false;
+
+    Index<char> buf;
+
+    AVFormatContext * ic = open_input_file (filename, file);
+    if (! ic)
+        return false;
+
+    CodecInfo cinfo;
+
+    if (! find_codec (ic, & cinfo))
+    {
+        AUDERR ("No codec found for %s.\n", filename);
+        goto error_exit;
+    }
+
+    AUDDBG("got codec %s for stream index %d, opening\n", cinfo.codec->name, cinfo.stream_idx);
+
+    if (avcodec_open2 (cinfo.context, cinfo.codec, nullptr) < 0)
+        goto error_exit;
+
+    codec_opened = true;
+
+    switch (cinfo.context->sample_fmt)
+    {
+        case AV_SAMPLE_FMT_U8: out_fmt = FMT_U8; planar = false; break;
+        case AV_SAMPLE_FMT_S16: out_fmt = FMT_S16_NE; planar = false; break;
+        case AV_SAMPLE_FMT_S32: out_fmt = FMT_S32_NE; planar = false; break;
+        case AV_SAMPLE_FMT_FLT: out_fmt = FMT_FLOAT; planar = false; break;
+
+        case AV_SAMPLE_FMT_U8P: out_fmt = FMT_U8; planar = true; break;
+        case AV_SAMPLE_FMT_S16P: out_fmt = FMT_S16_NE; planar = true; break;
+        case AV_SAMPLE_FMT_S32P: out_fmt = FMT_S32_NE; planar = true; break;
+        case AV_SAMPLE_FMT_FLTP: out_fmt = FMT_FLOAT; planar = true; break;
+
+    default:
+        AUDERR ("Unsupported audio format %d\n", (int) cinfo.context->sample_fmt);
+        goto error_exit;
+    }
+
+    /* Open audio output */
+    AUDDBG("opening audio output\n");
+
+    set_stream_bitrate(ic->bit_rate);
+    open_audio(out_fmt, cinfo.context->sample_rate, cinfo.context->channels);
+
+    errcount = 0;
+
+    while (! check_stop ())
+    {
+        int seek_value = check_seek ();
+
+        if (seek_value >= 0)
+        {
+            if (av_seek_frame (ic, -1, (int64_t) seek_value * AV_TIME_BASE /
+             1000, AVSEEK_FLAG_ANY) < 0)
+            {
+                AUDERR ("error while seeking\n");
+            } else
+                errcount = 0;
+
+            seek_value = -1;
+        }
+
+        AVPacket tmp;
+        int ret;
+
+        /* Read next frame (or more) of data */
+        if ((ret = av_read_frame(ic, &pkt)) < 0)
+        {
+            if (ret == (int) AVERROR_EOF)
+            {
+                AUDDBG("eof reached\n");
+                break;
+            }
+            else
+            {
+                if (++errcount > 4)
+                {
+                    AUDERR ("av_read_frame error %d, giving up.\n", ret);
+                    break;
+                } else
+                    continue;
+            }
+        } else
+            errcount = 0;
+
+        /* Ignore any other substreams */
+        if (pkt.stream_index != cinfo.stream_idx)
+        {
+            av_free_packet(&pkt);
+            continue;
+        }
+
+        /* Decode and play packet/frame */
+        memcpy(&tmp, &pkt, sizeof(tmp));
+        while (tmp.size > 0 && ! check_stop ())
+        {
+            /* Check for seek request and bail out if we have one */
+            if (seek_value < 0)
+                seek_value = check_seek ();
+
+            if (seek_value >= 0)
+                break;
+
+#if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
+            AVFrame * frame = av_frame_alloc ();
+#else
+            AVFrame * frame = avcodec_alloc_frame ();
+#endif
+            int decoded = 0;
+            int len = avcodec_decode_audio4 (cinfo.context, frame, & decoded, & tmp);
+
+            if (len < 0)
+            {
+                AUDERR ("decode_audio() failed, code %d\n", len);
+                break;
+            }
+
+            tmp.size -= len;
+            tmp.data += len;
+
+            if (! decoded)
+                continue;
+
+            int size = FMT_SIZEOF (out_fmt) * cinfo.context->channels * frame->nb_samples;
+
+            if (planar)
+            {
+                if (size > buf.len ())
+                    buf.resize (size);
+
+                audio_interlace ((const void * *) frame->data, out_fmt,
+                 cinfo.context->channels, buf.begin (), frame->nb_samples);
+                write_audio (buf.begin (), size);
+            }
+            else
+                write_audio (frame->data[0], size);
+
+#if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
+            av_frame_free (& frame);
+#elif CHECK_LIBAVCODEC_VERSION (54, 59, 100, 54, 28, 0)
+            avcodec_free_frame (& frame);
+#else
+            av_free (frame);
+#endif
+        }
+
+        if (pkt.data)
+            av_free_packet(&pkt);
+    }
+
+error_exit:
+    if (pkt.data)
+        av_free_packet(&pkt);
+    if (codec_opened)
+        avcodec_close(cinfo.context);
+    if (ic != nullptr)
+        close_input_file(ic);
+
+    return ! error;
+}
+
+const char FFaudio::about[] =
+ N_("Multi-format audio decoding plugin for Audacious using\n"
+    "FFmpeg multimedia framework (http://www.ffmpeg.org/)\n"
+    "\n"
+    "Audacious plugin by:\n"
+    "William Pitcock <nenolod at nenolod.net>\n"
+    "Matti Hämäläinen <ccr at tnsp.org>");
+
+const char * const FFaudio::exts[] = {
+    /* musepack, SV7/SV8 */
+    "mpc", "mp+", "mpp",
+
+    /* windows media audio */
+    "wma",
+
+    /* shorten */
+    "shn",
+
+    /* atrac3 */
+    "aa3", "oma",
+
+    /* MPEG 2/4 AC3 */
+    "ac3",
+
+    /* monkey's audio */
+    "ape",
+
+    /* DTS */
+    "dts",
+
+    /* VQF */
+    "vqf",
+
+    /* MPEG-4 */
+    "m4a", "mp4",
+
+    /* WAV (there are some WAV formats sndfile can't handle) */
+    "wav",
+
+    /* Handle OGG streams (FLAC/Vorbis etc.) */
+    "ogg", "oga",
+
+    /* Opus */
+    "opus",
+
+    /* Speex */
+    "spx",
+
+    /* end of table */
+    nullptr
+};
+
+const char * const FFaudio::mimes[] = {"application/ogg", nullptr};
diff --git a/src/ffaudio/ffaudio-io.c b/src/ffaudio/ffaudio-io.c
deleted file mode 100644
index 036209da49f3..000000000000
--- a/src/ffaudio/ffaudio-io.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * ffaudio-io.c
- * Copyright 2011 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
- */
-
-#include <glib.h>
-
-#include "ffaudio-stdinc.h"
-
-#define IOBUF 4096
-
-static gint read_cb (void * file, guchar * buf, gint size)
-{
-    return vfs_fread (buf, 1, size, file);
-}
-
-static gint64 seek_cb (void * file, gint64 offset, gint whence)
-{
-    if (whence == AVSEEK_SIZE)
-        return vfs_fsize (file);
-    if (vfs_fseek (file, offset, whence & ~(gint) AVSEEK_FORCE))
-        return -1;
-    return vfs_ftell (file);
-}
-
-AVIOContext * io_context_new (VFSFile * file)
-{
-    guchar * buf = av_malloc (IOBUF);
-    return avio_alloc_context (buf, IOBUF, 0, file, read_cb, NULL, seek_cb);
-}
-
-void io_context_free (AVIOContext * io)
-{
-    av_free (io->buffer);
-    av_free (io);
-}
diff --git a/src/ffaudio/ffaudio-io.cc b/src/ffaudio/ffaudio-io.cc
new file mode 100644
index 000000000000..b4481c30b4f6
--- /dev/null
+++ b/src/ffaudio/ffaudio-io.cc
@@ -0,0 +1,48 @@
+/*
+ * ffaudio-io.c
+ * Copyright 2011 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
+ */
+
+#define WANT_VFS_STDIO_COMPAT
+#include "ffaudio-stdinc.h"
+
+#define IOBUF 4096
+
+static int read_cb (void * file, unsigned char * buf, int size)
+{
+    return ((VFSFile *) file)->fread (buf, 1, size);
+}
+
+static int64_t seek_cb (void * file, int64_t offset, int whence)
+{
+    if (whence == AVSEEK_SIZE)
+        return ((VFSFile *) file)->fsize ();
+    if (((VFSFile *) file)->fseek (offset, to_vfs_seek_type (whence & ~(int) AVSEEK_FORCE)))
+        return -1;
+    return ((VFSFile *) file)->ftell ();
+}
+
+AVIOContext * io_context_new (VFSFile & file)
+{
+    void * buf = av_malloc (IOBUF);
+    return avio_alloc_context ((unsigned char *) buf, IOBUF, 0, & file, read_cb, nullptr, seek_cb);
+}
+
+void io_context_free (AVIOContext * io)
+{
+    av_free (io->buffer);
+    av_free (io);
+}
diff --git a/src/ffaudio/ffaudio-stdinc.h b/src/ffaudio/ffaudio-stdinc.h
index 4d7df824e0b3..548ec30dd100 100644
--- a/src/ffaudio/ffaudio-stdinc.h
+++ b/src/ffaudio/ffaudio-stdinc.h
@@ -19,18 +19,32 @@
 #ifndef __FFAUDIO_STDINC_H__GUARD
 #define __FFAUDIO_STDINC_H__GUARD
 
-#define _ERROR(...) printf ("ffaudio: " __VA_ARGS__)
+#define __STDC_CONSTANT_MACROS
+#include <libaudcore/plugin.h>
 
-#include <audacious/plugin.h>
+extern "C" {
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
 #include <libavutil/avutil.h>
+}
 
-#define CHECK_LIBAVCODEC_VERSION(a, b, c) (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (a, b, c))
-#define CHECK_LIBAVFORMAT_VERSION(a, b, c) (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT (a, b, c))
-#define CHECK_LIBAVUTIL_VERSION(a, b, c) (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT (a, b, c))
+/* FFmpeg and libav remain mostly compatible but have different version numbers.
+ * The first three numbers are the required FFmpeg version; the last three are for libav. */
+#ifdef HAVE_FFMPEG
+#define CHECK_LIBAVCODEC_VERSION(a, b, c, a2, b2, c2) (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (a, b, c))
+#define CHECK_LIBAVFORMAT_VERSION(a, b, c, a2, b2, c2) (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT (a, b, c))
+#define CHECK_LIBAVUTIL_VERSION(a, b, c, a2, b2, c2) (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT (a, b, c))
+#elif defined HAVE_LIBAV
+#define CHECK_LIBAVCODEC_VERSION(a, b, c, a2, b2, c2) (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT (a2, b2, c2))
+#define CHECK_LIBAVFORMAT_VERSION(a, b, c, a2, b2, c2) (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT (a2, b2, c2))
+#define CHECK_LIBAVUTIL_VERSION(a, b, c, a2, b2, c2) (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT (a2, b2, c2))
+#else
+#error Please define either HAVE_FFMPEG or HAVE_LIBAV
+#endif
 
-AVIOContext * io_context_new (VFSFile * file);
+AVIOContext * io_context_new (VFSFile & file);
 void io_context_free (AVIOContext * context);
 
+Index<char> read_itunes_cover (const char * filename, VFSFile & file);
+
 #endif
diff --git a/src/ffaudio/itunes-cover.cc b/src/ffaudio/itunes-cover.cc
new file mode 100644
index 000000000000..fa51c5883c3e
--- /dev/null
+++ b/src/ffaudio/itunes-cover.cc
@@ -0,0 +1,91 @@
+/*
+ * itunes-cover.c
+ * John Lindgren, 2010
+ *
+ * The author hereby releases this code into the public domain.
+ *
+ * Reference:
+ * http://atomicparsley.sourceforge.net/mpeg-4files.html
+ */
+
+#define __STDC_LIMIT_MACROS
+#include "ffaudio-stdinc.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const struct {
+    const char * id;
+    int skip;
+} hierarchy[] = {
+    {"moov", 0},
+    {"udta", 0},
+    {"meta", 4},
+    {"ilst", 0},
+    {"covr", 0},
+    {"data", 8}
+};
+
+Index<char> read_itunes_cover(const char * filename, VFSFile & file)
+{
+    unsigned char b[8];
+    int bsize;
+
+    Index<char> data;
+
+    /* Check for ftyp frame. */
+
+    if (file.fread (b, 1, 8) != 8)
+        return data;
+    if ((bsize = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) < 8)
+        return data;
+    if (strncmp ((char *) b + 4, "ftyp", 4))
+        return data;
+    if (file.fseek (bsize - 8, VFS_SEEK_CUR))
+        return data;
+
+    int64_t stop = INT64_MAX;
+    int64_t at = bsize;
+
+    /* Descend into frame hierarchy. */
+
+    for (auto & frame : hierarchy)
+    {
+        while (1)
+        {
+            if (file.fread (b, 1, 8) != 8)
+                return data;
+            if ((bsize = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]) < 8 || at + bsize > stop)
+                return data;
+            if (! strncmp ((char *) b + 4, frame.id, 4))
+                break;
+            if (file.fseek (bsize - 8, VFS_SEEK_CUR))
+                return data;
+
+            at += bsize;
+        }
+
+        stop = at + bsize;
+        at += 8;
+
+        /* Skip leading bytes in some frames. */
+
+        if (frame.skip)
+        {
+            if (file.fseek (frame.skip, VFS_SEEK_CUR))
+                return data;
+            at += frame.skip;
+        }
+    }
+
+    /* We're there. */
+
+    data.insert (0, stop - at);
+
+    if (file.fread (data.begin (), 1, stop - at) != stop - at)
+        data.clear ();
+
+    return data;
+}
diff --git a/src/filewriter/Makefile b/src/filewriter/Makefile
index f659f1f85f05..347babaead01 100644
--- a/src/filewriter/Makefile
+++ b/src/filewriter/Makefile
@@ -1,17 +1,19 @@
 PLUGIN = filewriter${PLUGIN_SUFFIX}
 
-SRCS = filewriter.c	\
-       wav.c		\
-       mp3.c		\
-       vorbis.c		\
-       flac.c           \
-       convert.c
+SRCS = filewriter.cc	\
+       wav.cc		\
+       mp3.cc		\
+       vorbis.cc		\
+       flac.cc           \
+       convert.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${GTK_CFLAGS} ${FILEWRITER_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS}
diff --git a/src/filewriter/convert.c b/src/filewriter/convert.c
deleted file mode 100644
index 5a0b212cad0f..000000000000
--- a/src/filewriter/convert.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "convert.h"
-
-gpointer convert_output = NULL;
-static gint nch;
-static gint in_fmt;
-static gint out_fmt;
-
-gboolean convert_init(gint input_fmt, gint output_fmt, gint channels)
-{
-    in_fmt = input_fmt;
-    out_fmt = output_fmt;
-    nch = channels;
-
-    return TRUE;
-}
-
-gint convert_process(gpointer ptr, gint length)
-{
-    gint samples = length / FMT_SIZEOF (in_fmt);
-    gfloat * temp;
-
-    convert_output = g_realloc (convert_output, FMT_SIZEOF (out_fmt) * samples);
-
-    if (in_fmt == out_fmt)
-        memcpy (convert_output, ptr, FMT_SIZEOF (in_fmt) * samples);
-    else if (in_fmt == FMT_FLOAT)
-        audio_to_int (ptr, convert_output, out_fmt, samples);
-    else if (out_fmt == FMT_FLOAT)
-        audio_from_int (ptr, in_fmt, convert_output, samples);
-    else
-    {
-        temp = g_malloc (sizeof (gfloat) * samples);
-        audio_from_int (ptr, in_fmt, temp, samples);
-        audio_to_int (temp, convert_output, out_fmt, samples);
-        g_free (temp);
-    }
-
-    return FMT_SIZEOF (out_fmt) * samples;
-}
-
-void convert_free(void)
-{
-    g_free (convert_output);
-    convert_output = NULL;
-}
diff --git a/src/filewriter/convert.cc b/src/filewriter/convert.cc
new file mode 100644
index 000000000000..2462f308fda6
--- /dev/null
+++ b/src/filewriter/convert.cc
@@ -0,0 +1,43 @@
+#include "convert.h"
+
+#include <string.h>
+
+static int in_fmt;
+static int out_fmt;
+
+static Index<char> convert_output;
+static Index<float> convert_temp;
+
+void convert_init (int input_fmt, int output_fmt)
+{
+    in_fmt = input_fmt;
+    out_fmt = output_fmt;
+}
+
+const Index<char> & convert_process (const void * ptr, int length)
+{
+    int samples = length / FMT_SIZEOF (in_fmt);
+
+    convert_output.resize (FMT_SIZEOF (out_fmt) * samples);
+
+    if (in_fmt == out_fmt)
+        memcpy (convert_output.begin (), ptr, FMT_SIZEOF (in_fmt) * samples);
+    else if (in_fmt == FMT_FLOAT)
+        audio_to_int ((const float *) ptr, convert_output.begin (), out_fmt, samples);
+    else if (out_fmt == FMT_FLOAT)
+        audio_from_int (ptr, in_fmt, (float *) convert_output.begin (), samples);
+    else
+    {
+        convert_temp.resize (samples);
+        audio_from_int (ptr, in_fmt, convert_temp.begin (), samples);
+        audio_to_int (convert_temp.begin (), convert_output.begin (), out_fmt, samples);
+    }
+
+    return convert_output;
+}
+
+void convert_free ()
+{
+    convert_output.clear ();
+    convert_temp.clear ();
+}
diff --git a/src/filewriter/convert.h b/src/filewriter/convert.h
index ba417af6da45..5c1869b88b90 100644
--- a/src/filewriter/convert.h
+++ b/src/filewriter/convert.h
@@ -3,12 +3,8 @@
 
 #include "filewriter.h"
 
-gpointer convert_output;
-
-gboolean convert_init(gint input_fmt, gint output_fmt, gint channels);
-
-gint convert_process(gpointer ptr, gint length);
-
-void convert_free(void);
+void convert_init (int input_fmt, int output_fmt);
+const Index<char> & convert_process (const void * ptr, int length);
+void convert_free ();
 
 #endif
diff --git a/src/filewriter/filewriter.c b/src/filewriter/filewriter.c
deleted file mode 100644
index 5771e3494ac4..000000000000
--- a/src/filewriter/filewriter.c
+++ /dev/null
@@ -1,542 +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 at gmx.net>
- *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
- */
-
-#include <gtk/gtk.h>
-#include <stdlib.h>
-
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "filewriter.h"
-#include "plugins.h"
-#include "convert.h"
-
-struct format_info input;
-
-static GtkWidget * path_hbox, * path_dirbrowser;
-static GtkWidget * fileext_combo, * plugin_button;
-
-enum fileext_t
-{
-    WAV = 0,
-#ifdef FILEWRITER_MP3
-    MP3,
-#endif
-#ifdef FILEWRITER_VORBIS
-    VORBIS,
-#endif
-#ifdef FILEWRITER_FLAC
-    FLAC,
-#endif
-    FILEEXT_MAX
-};
-
-static gint fileext;
-static const gchar *fileext_str[FILEEXT_MAX] =
-{
-    "wav",
-#ifdef FILEWRITER_MP3
-    "mp3",
-#endif
-#ifdef FILEWRITER_VORBIS
-    "ogg",
-#endif
-#ifdef FILEWRITER_FLAC
-    "flac"
-#endif
-};
-
-static FileWriter *plugin;
-
-static gboolean save_original;
-
-static GtkWidget *filenamefrom_hbox, *filenamefrom_label;
-static gboolean filenamefromtags;
-
-static GtkWidget *use_suffix_toggle = NULL;
-static gboolean use_suffix;
-
-static GtkWidget *prependnumber_toggle;
-static gboolean prependnumber;
-
-static gchar *file_path;
-
-VFSFile *output_file = NULL;
-Tuple *tuple = NULL;
-
-static gint64 samples_written;
-
-FileWriter *plugins[FILEEXT_MAX] = {
-    &wav_plugin,
-#ifdef FILEWRITER_MP3
-    &mp3_plugin,
-#endif
-#ifdef FILEWRITER_VORBIS
-    &vorbis_plugin,
-#endif
-#ifdef FILEWRITER_FLAC
-    &flac_plugin,
-#endif
-};
-
-static void set_plugin(void)
-{
-    if (fileext < 0 || fileext >= FILEEXT_MAX)
-        fileext = 0;
-
-    plugin = plugins[fileext];
-}
-
-static gint file_write_output (void * data, gint length)
-{
-    return vfs_fwrite (data, 1, length, output_file);
-}
-
-static const gchar * const filewriter_defaults[] = {
- "fileext", "0", /* WAV */
- "filenamefromtags", "TRUE",
- "prependnumber", "FALSE",
- "save_original", "TRUE",
- "use_suffix", "FALSE",
- NULL};
-
-static gboolean file_init (void)
-{
-    aud_config_set_defaults ("filewriter", 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])
-    {
-        str_unref (file_path);
-        file_path = filename_to_uri (g_get_home_dir ());
-        g_return_val_if_fail (file_path != NULL, FALSE);
-    }
-
-    set_plugin();
-    if (plugin->init)
-        plugin->init(&file_write_output);
-
-    return TRUE;
-}
-
-static void file_cleanup (void)
-{
-    str_unref (file_path);
-    file_path = NULL;
-}
-
-static VFSFile * safe_create (const gchar * filename)
-{
-    if (! vfs_file_test (filename, G_FILE_TEST_EXISTS))
-        return vfs_fopen (filename, "w");
-
-    const gchar * extension = strrchr (filename, '.');
-    gint length = strlen (filename);
-    gchar scratch[length + 3];
-    gint count;
-
-    for (count = 1; count < 100; count ++)
-    {
-        if (extension == NULL)
-            sprintf (scratch, "%s-%d", filename, count);
-        else
-            sprintf (scratch, "%.*s-%d%s", (gint) (extension - filename),
-             filename, count, extension);
-
-        if (! vfs_file_test (scratch, G_FILE_TEST_EXISTS))
-            return vfs_fopen (scratch, "w");
-    }
-
-    return NULL;
-}
-
-static gint file_open(gint fmt, gint rate, gint nch)
-{
-    gchar *filename = NULL, *temp = NULL;
-    gchar * directory;
-    gint pos;
-    gint rv;
-    gint playlist;
-
-    input.format = fmt;
-    input.frequency = rate;
-    input.channels = nch;
-
-    playlist = aud_playlist_get_playing ();
-    if (playlist < 0)
-        return 0;
-
-    pos = aud_playlist_get_position(playlist);
-    tuple = aud_playlist_entry_get_tuple (playlist, pos, FALSE);
-    if (tuple == NULL)
-        return 0;
-
-    if (filenamefromtags)
-    {
-        gchar * utf8 = aud_playlist_entry_get_title (playlist, pos, FALSE);
-        str_replace_char (utf8, '/', ' ');
-
-        gchar buf[3 * strlen (utf8) + 1];
-        str_encode_percent (utf8, -1, buf);
-        str_unref (utf8);
-
-        filename = g_strdup (buf);
-    }
-    else
-    {
-        temp = aud_playlist_entry_get_filename (playlist, pos);
-        gchar * original = strrchr (temp, '/');
-        g_return_val_if_fail (original != NULL, 0);
-        filename = g_strdup (original + 1);
-        str_unref (temp);
-
-        if (!use_suffix)
-            if ((temp = strrchr(filename, '.')) != NULL)
-                *temp = '\0';
-    }
-
-    if (prependnumber)
-    {
-        gint number = tuple_get_int(tuple, FIELD_TRACK_NUMBER);
-        if (!tuple || !number)
-            number = pos + 1;
-
-        temp = g_strdup_printf ("%d%%20%s", number, filename);
-        g_free(filename);
-        filename = temp;
-    }
-
-    if (save_original)
-    {
-        temp = aud_playlist_entry_get_filename (playlist, pos);
-        directory = g_strdup (temp);
-        str_unref (temp);
-        temp = strrchr (directory, '/');
-        g_return_val_if_fail (temp != NULL, 0);
-        temp[1] = 0;
-    }
-    else
-    {
-        g_return_val_if_fail (file_path[0], 0);
-        if (file_path[strlen (file_path) - 1] == '/')
-            directory = g_strdup (file_path);
-        else
-            directory = g_strdup_printf ("%s/", file_path);
-    }
-
-    temp = g_strdup_printf ("%s%s.%s", directory, filename, fileext_str[fileext]);
-    g_free (directory);
-    g_free (filename);
-    filename = temp;
-
-    output_file = safe_create (filename);
-    g_free (filename);
-
-    if (output_file == NULL)
-        return 0;
-
-    convert_init (fmt, plugin->format_required (fmt), nch);
-
-    rv = (plugin->open)();
-
-    samples_written = 0;
-
-    return rv;
-}
-
-static void file_write(void *ptr, gint length)
-{
-    int len = convert_process (ptr, length);
-
-    plugin->write(convert_output, len);
-
-    samples_written += length / FMT_SIZEOF (input.format);
-}
-
-static void file_drain (void)
-{
-}
-
-static void file_close(void)
-{
-    plugin->close();
-    convert_free();
-
-    if (output_file != NULL)
-        vfs_fclose(output_file);
-    output_file = NULL;
-
-    if (tuple)
-    {
-        tuple_unref (tuple);
-        tuple = NULL;
-    }
-}
-
-static void file_flush(gint time)
-{
-    samples_written = time * (gint64) input.channels * input.frequency / 1000;
-}
-
-static void file_pause (gboolean p)
-{
-}
-
-static gint file_get_time (void)
-{
-    return samples_written * 1000 / (input.channels * input.frequency);
-}
-
-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);
-    str_unref (file_path);
-    file_path = str_get (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, gpointer data)
-{
-    fileext = gtk_combo_box_get_active(GTK_COMBO_BOX(fileext_combo));
-    set_plugin();
-    if (plugin->init)
-        plugin->init(&file_write_output);
-
-    gtk_widget_set_sensitive(plugin_button, plugin->configure != NULL);
-}
-
-static void plugin_configure_cb(GtkWidget *button, gpointer data)
-{
-    if (plugin->configure)
-        plugin->configure();
-}
-
-
-static void saveplace_original_cb(GtkWidget *button, gpointer data)
-{
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
-    {
-        gtk_widget_set_sensitive(path_hbox, FALSE);
-        save_original = TRUE;
-    }
-}
-
-static void saveplace_custom_cb(GtkWidget *button, gpointer data)
-{
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
-    {
-        gtk_widget_set_sensitive(path_hbox, TRUE);
-        save_original = FALSE;
-    }
-}
-
-static void filenamefromtags_cb(GtkWidget *button, gpointer 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;
-    }
-}
-
-static void filenamefromfilename_cb(GtkWidget *button, gpointer data)
-{
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
-    {
-        gtk_widget_set_sensitive(use_suffix_toggle, TRUE);
-        filenamefromtags = FALSE;
-    }
-}
-
-static void * file_configure (void)
-{
-        GtkWidget * configure_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-
-        GtkWidget * fileext_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_box_pack_start(GTK_BOX(configure_vbox), fileext_hbox, FALSE, FALSE, 0);
-
-        GtkWidget * fileext_label = gtk_label_new (_("Output file format:"));
-        gtk_box_pack_start(GTK_BOX(fileext_hbox), fileext_label, FALSE, FALSE, 0);
-
-        fileext_combo = gtk_combo_box_text_new ();
-        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "WAV");
-#ifdef FILEWRITER_MP3
-        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "MP3");
-#endif
-#ifdef FILEWRITER_VORBIS
-        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "Vorbis");
-#endif
-#ifdef FILEWRITER_FLAC
-        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "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 != NULL);
-        gtk_box_pack_end(GTK_BOX(fileext_hbox), plugin_button, FALSE, FALSE, 0);
-
-        gtk_box_pack_start(GTK_BOX(configure_vbox), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 0);
-
-        GtkWidget * saveplace_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_add(GTK_CONTAINER(configure_vbox), saveplace_hbox);
-
-        GtkWidget * saveplace1 = gtk_radio_button_new_with_label (NULL,
-         _("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_box_new(GTK_ORIENTATION_HORIZONTAL, 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_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 0);
-
-        filenamefrom_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_add(GTK_CONTAINER(configure_vbox), filenamefrom_hbox);
-
-        filenamefrom_label = gtk_label_new(_("Get filename from:"));
-        gtk_box_pack_start(GTK_BOX(filenamefrom_hbox), filenamefrom_label, FALSE, FALSE, 0);
-
-        GtkWidget * filenamefrom_toggle1 = gtk_radio_button_new_with_label
-         (NULL, _("original file tags"));
-        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 filename"));
-        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(_("Don't strip 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_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 0);
-
-        prependnumber_toggle = gtk_check_button_new_with_label(_("Prepend track number to filename"));
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prependnumber_toggle), prependnumber);
-        gtk_box_pack_start(GTK_BOX(configure_vbox), prependnumber_toggle, FALSE, FALSE, 0);
-
-        g_signal_connect (fileext_combo, "changed", (GCallback) fileext_cb, NULL);
-        g_signal_connect (plugin_button, "clicked", (GCallback) plugin_configure_cb, NULL);
-        g_signal_connect (saveplace1, "toggled", (GCallback) saveplace_original_cb, NULL);
-        g_signal_connect (saveplace2, "toggled", (GCallback) saveplace_custom_cb, NULL);
-        g_signal_connect (filenamefrom_toggle1, "toggled", (GCallback) filenamefromtags_cb, NULL);
-        g_signal_connect (filenamefrom_toggle2, "toggled",
-         (GCallback) filenamefromfilename_cb, NULL);
-
-        return configure_vbox;
-}
-
-static const char file_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 PreferencesWidget file_widgets[] = {
- {WIDGET_CUSTOM, .data = {.populate = file_configure}}};
-
-static const PluginPreferences file_prefs = {
- .widgets = file_widgets,
- .n_widgets = ARRAY_LEN (file_widgets),
- .apply = configure_response_cb};
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("FileWriter Plugin"),
-    .domain = PACKAGE,
-    .about_text = file_about,
-    .init = file_init,
-    .cleanup = file_cleanup,
-    .prefs = & file_prefs,
-    .probe_priority = 0,
-    .open_audio = file_open,
-    .close_audio = file_close,
-    .write_audio = file_write,
-    .drain = file_drain,
-    .output_time = file_get_time,
-    .pause = file_pause,
-    .flush = file_flush,
-    .force_reopen = TRUE
-)
diff --git a/src/filewriter/filewriter.cc b/src/filewriter/filewriter.cc
new file mode 100644
index 000000000000..c2c2a9a5c7e4
--- /dev/null
+++ b/src/filewriter/filewriter.cc
@@ -0,0 +1,507 @@
+/*  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 at gmx.net>
+ *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+#include "filewriter.h"
+#include "plugins.h"
+#include "convert.h"
+
+class FileWriter : public OutputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("FileWriter Plugin"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr FileWriter () : OutputPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    StereoVolume get_volume () { return {0, 0}; }
+    void set_volume (StereoVolume v) {}
+
+    void set_info (const char * filename, const Tuple & tuple);
+    bool open_audio (int fmt, int rate, int nch);
+    void close_audio ();
+
+    void period_wait () {}
+    int write_audio (const void * ptr, int length);
+    void drain () {}
+
+    int get_delay ()
+        { return 0; }
+
+    void pause (bool pause) {}
+    void flush () {}
+};
+
+EXPORT FileWriter aud_plugin_instance;
+
+static String in_filename;
+static Tuple in_tuple;
+
+struct format_info input;
+
+static GtkWidget * path_hbox, * path_dirbrowser;
+static GtkWidget * fileext_combo, * plugin_button;
+
+enum fileext_t
+{
+    WAV = 0,
+#ifdef FILEWRITER_MP3
+    MP3,
+#endif
+#ifdef FILEWRITER_VORBIS
+    VORBIS,
+#endif
+#ifdef FILEWRITER_FLAC
+    FLAC,
+#endif
+    FILEEXT_MAX
+};
+
+static int fileext;
+static const char *fileext_str[FILEEXT_MAX] =
+{
+    "wav",
+#ifdef FILEWRITER_MP3
+    "mp3",
+#endif
+#ifdef FILEWRITER_VORBIS
+    "ogg",
+#endif
+#ifdef FILEWRITER_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] = {
+    &wav_plugin,
+#ifdef FILEWRITER_MP3
+    &mp3_plugin,
+#endif
+#ifdef FILEWRITER_VORBIS
+    &vorbis_plugin,
+#endif
+#ifdef FILEWRITER_FLAC
+    &flac_plugin,
+#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 */
+ "filenamefromtags", "TRUE",
+ "prependnumber", "FALSE",
+ "save_original", "TRUE",
+ "use_suffix", "FALSE",
+ nullptr};
+
+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])
+    {
+        file_path = String (filename_to_uri (g_get_home_dir ()));
+        g_return_val_if_fail (file_path != nullptr, false);
+    }
+
+    set_plugin();
+    if (plugin->init)
+        plugin->init();
+
+    return true;
+}
+
+void FileWriter::cleanup ()
+{
+    file_path = String ();
+}
+
+static VFSFile safe_create (const char * filename)
+{
+    if (! VFSFile::test_file (filename, VFS_EXISTS))
+        return VFSFile (filename, "w");
+
+    const char * extension = strrchr (filename, '.');
+
+    for (int count = 1; count < 100; count ++)
+    {
+        StringBuf scratch = extension ?
+         str_printf ("%.*s-%d%s", (int) (extension - filename), filename, count, extension) :
+         str_printf ("%s-%d", filename, count);
+
+        if (! VFSFile::test_file (scratch, VFS_EXISTS))
+            return VFSFile (scratch, "w");
+    }
+
+    return VFSFile ();
+}
+
+void FileWriter::set_info (const char * filename, const Tuple & tuple)
+{
+    in_filename = String (filename);
+    in_tuple = tuple.ref ();
+}
+
+bool FileWriter::open_audio (int fmt, int rate, int nch)
+{
+    String filename, directory;
+
+    input.format = fmt;
+    input.frequency = rate;
+    input.channels = nch;
+
+    if (filenamefromtags)
+    {
+        String title = in_tuple.get_str (Tuple::FormattedTitle);
+        StringBuf buf = str_encode_percent (title);
+        str_replace_char (buf, '/', '-');
+        filename = String (buf);
+    }
+    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));
+        }
+    }
+
+    if (prependnumber)
+    {
+        int number = in_tuple.get_int (Tuple::Track);
+        if (number >= 0)
+            filename = String (str_printf ("%d%%20%s", number, (const char *) filename));
+    }
+
+    if (save_original)
+    {
+        const char * temp = strrchr (in_filename, '/');
+        g_return_val_if_fail (temp != nullptr, 0);
+        directory = String (str_copy (in_filename, temp + 1 - in_filename));
+    }
+    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, "/"}));
+    }
+
+    filename = String (str_printf ("%s%s.%s", (const char *) directory,
+     (const char *) filename, fileext_str[fileext]));
+
+    output_file = safe_create (filename);
+    if (! output_file)
+        goto err;
+
+    convert_init (fmt, plugin->format_required (fmt));
+
+    if (plugin->open (output_file, input, in_tuple))
+        return true;
+
+err:
+    in_filename = String ();
+    in_tuple = Tuple ();
+    return false;
+}
+
+int FileWriter::write_audio (const void * ptr, int length)
+{
+    auto & buf = convert_process (ptr, length);
+    plugin->write (output_file, buf.begin (), buf.len ());
+
+    return length;
+}
+
+void FileWriter::close_audio ()
+{
+    plugin->close (output_file);
+    convert_free ();
+
+    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)
+{
+    if (plugin->configure)
+        plugin->configure();
+}
+
+
+static void saveplace_original_cb(GtkWidget *button, void * data)
+{
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
+    {
+        gtk_widget_set_sensitive(path_hbox, FALSE);
+        save_original = TRUE;
+    }
+}
+
+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;
+    }
+}
+
+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;
+    }
+}
+
+static void filenamefromfilename_cb(GtkWidget *button, void * data)
+{
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
+    {
+        gtk_widget_set_sensitive(use_suffix_toggle, TRUE);
+        filenamefromtags = FALSE;
+    }
+}
+
+static void * file_configure (void)
+{
+        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);
+
+        GtkWidget * fileext_label = gtk_label_new (_("Output file format:"));
+        gtk_box_pack_start(GTK_BOX(fileext_hbox), fileext_label, FALSE, FALSE, 0);
+
+        fileext_combo = gtk_combo_box_text_new ();
+        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "WAV");
+#ifdef FILEWRITER_MP3
+        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "MP3");
+#endif
+#ifdef FILEWRITER_VORBIS
+        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "Vorbis");
+#endif
+#ifdef FILEWRITER_FLAC
+        gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "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);
+
+        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);
+
+        return configure_vbox;
+}
+
+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.");
+
+const PreferencesWidget FileWriter::widgets[] = {
+    WidgetCustomGTK (file_configure)
+};
+
+const PluginPreferences FileWriter::prefs = {
+    {widgets},
+    nullptr,  // init
+    configure_response_cb
+};
diff --git a/src/filewriter/filewriter.h b/src/filewriter/filewriter.h
index a4186b94e997..4fe437bb3f7b 100644
--- a/src/filewriter/filewriter.h
+++ b/src/filewriter/filewriter.h
@@ -23,35 +23,25 @@
 #ifndef FILEWRITER_H
 #define FILEWRITER_H
 
-#include <gtk/gtk.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
+#define WANT_AUD_BSWAP
+#include <libaudcore/audio.h>
+#include <libaudcore/tuple.h>
+#include <libaudcore/vfs.h>
 
 struct format_info {
-    gint format;
+    int format;
     int frequency;
     int channels;
 };
 
-extern struct format_info input;
-
-extern VFSFile *output_file;
-extern guint64 offset;
-extern Tuple * tuple;
-
-typedef gint (*write_output_callback)(void *ptr, gint length);
-
-typedef struct _FileWriter
+struct FileWriterImpl
 {
-    void (*init)(write_output_callback write_output_func);
-    void (*configure)(void);
-    gint (*open)(void);
-    void (*write)(void *ptr, gint length);
-    void (*close)(void);
-    int (*format_required)(int fmt);
-} FileWriter;
+    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);
+};
 
 #endif
diff --git a/src/filewriter/flac.c b/src/filewriter/flac.c
deleted file mode 100644
index f9eb8a325eb7..000000000000
--- a/src/filewriter/flac.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*  FileWriter FLAC Plugin
- *  Copyright (c) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
- *
- *  Partially derived from Og(g)re - Ogg-Output-Plugin:
- *  Copyright (c) 2002 Lars Siebold <khandha5 at gmx.net>
- *
- *  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.
- */
-
-#include "plugins.h"
-
-#ifdef FILEWRITER_FLAC
-
-#include <FLAC/all.h>
-#include <stdlib.h>
-
-static FLAC__StreamEncoder *flac_encoder;
-static FLAC__StreamMetadata *flac_metadata;
-
-static FLAC__StreamEncoderWriteStatus flac_write_cb(const FLAC__StreamEncoder *encoder,
-    const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, gpointer data)
-{
-    if (vfs_fwrite (buffer, 1, bytes, data) != bytes)
-        return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
-
-    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
-}
-
-static FLAC__StreamEncoderSeekStatus flac_seek_cb(const FLAC__StreamEncoder *encoder,
-    FLAC__uint64 absolute_byte_offset, gpointer data)
-{
-    VFSFile *file = (VFSFile *) data;
-
-    if (vfs_fseek(file, absolute_byte_offset, SEEK_SET) < 0)
-        return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
-
-    return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
-}
-
-static FLAC__StreamEncoderTellStatus flac_tell_cb(const FLAC__StreamEncoder *encoder,
-    FLAC__uint64 *absolute_byte_offset, gpointer data)
-{
-    VFSFile *file = (VFSFile *) data;
-
-    *absolute_byte_offset = vfs_ftell(file);
-
-    return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
-}
-
-static void insert_vorbis_comment (FLAC__StreamMetadata * meta,
- const char * name, const Tuple * tuple, int field)
-{
-    TupleValueType type = tuple_field_get_type (field);
-    if (tuple_get_value_type (tuple, field) != type)
-        return;
-
-    char * temp;
-
-    switch (type)
-    {
-    case TUPLE_INT:;
-        int ival = tuple_get_int (tuple, field);
-        temp = g_strdup_printf ("%s=%d", name, ival);
-        break;
-    case TUPLE_STRING:;
-        char * sval = tuple_get_str (tuple, field);
-        temp = g_strdup_printf ("%s=%s", name, sval);
-        str_unref (sval);
-        break;
-    default:
-        return;
-    }
-
-    FLAC__StreamMetadata_VorbisComment_Entry comment;
-    comment.length = strlen (temp);
-    comment.entry = (unsigned char *) temp;
-
-    FLAC__metadata_object_vorbiscomment_insert_comment (meta,
-     meta->data.vorbis_comment.num_comments, comment, TRUE);
-
-    g_free (temp);
-}
-
-static gint flac_open(void)
-{
-    flac_encoder = FLAC__stream_encoder_new();
-
-    FLAC__stream_encoder_set_channels(flac_encoder, input.channels);
-    FLAC__stream_encoder_set_sample_rate(flac_encoder, input.frequency);
-
-    if (tuple)
-    {
-        flac_metadata = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
-
-        insert_vorbis_comment (flac_metadata, "TITLE", tuple, FIELD_TITLE);
-        insert_vorbis_comment (flac_metadata, "ARTIST", tuple, FIELD_ARTIST);
-        insert_vorbis_comment (flac_metadata, "ALBUM", tuple, FIELD_ALBUM);
-        insert_vorbis_comment (flac_metadata, "GENRE", tuple, FIELD_GENRE);
-        insert_vorbis_comment (flac_metadata, "COMMENT", tuple, FIELD_COMMENT);
-        insert_vorbis_comment (flac_metadata, "DATE", tuple, FIELD_DATE);
-        insert_vorbis_comment (flac_metadata, "YEAR", tuple, FIELD_YEAR);
-        insert_vorbis_comment (flac_metadata, "TRACKNUMBER", tuple, FIELD_TRACK_NUMBER);
-
-        FLAC__stream_encoder_set_metadata(flac_encoder, &flac_metadata, 1);
-    }
-
-    FLAC__stream_encoder_init_stream(flac_encoder, flac_write_cb, flac_seek_cb,
-     flac_tell_cb, NULL, output_file);
-
-    return 1;
-}
-
-static void flac_write(gpointer data, gint length)
-{
-#if 1
-    FLAC__int32 *encbuffer[2];
-    short int *tmpdata = data;
-    int i;
-
-    encbuffer[0] = g_new0(FLAC__int32, length / input.channels);
-    encbuffer[1] = g_new0(FLAC__int32, length / input.channels);
-
-    if (input.channels == 1)
-    {
-        for (i = 0; i < (length / 2); i++)
-        {
-            encbuffer[0][i] = tmpdata[i];
-            encbuffer[1][i] = tmpdata[i];
-        }
-    }
-    else
-    {
-        for (i = 0; i < (length / 4); i++)
-        {
-            encbuffer[0][i] = tmpdata[2 * i];
-            encbuffer[1][i] = tmpdata[2 * i + 1];
-        }
-    }
-
-    FLAC__stream_encoder_process(flac_encoder, (const FLAC__int32 **)encbuffer, length / (input.channels * 2));
-
-    g_free(encbuffer[0]);
-    g_free(encbuffer[1]);
-#else
-    FLAC__int32 *encbuffer;
-    gint16 *tmpdata = data;
-    int i;
-
-    encbuffer = g_new0(FLAC__int32, length);
-
-    for (i=0; i < length; i++) {
-        encbuffer[i] = tmpdata[i];
-    }
-
-    FLAC__stream_encoder_process_interleaved(flac_encoder, encbuffer, length);
-
-    g_free(encbuffer);
-#endif
-}
-
-static void flac_close(void)
-{
-    if (flac_encoder)
-    {
-        FLAC__stream_encoder_finish(flac_encoder);
-        FLAC__stream_encoder_delete(flac_encoder);
-        flac_encoder = NULL;
-    }
-
-    if (flac_metadata)
-    {
-        FLAC__metadata_object_delete(flac_metadata);
-        flac_metadata = NULL;
-    }
-}
-
-static int flac_format_required (int fmt)
-{
-    return FMT_S16_NE;
-}
-
-FileWriter flac_plugin =
-{
-    .init = NULL,
-    .configure = NULL,
-    .open = flac_open,
-    .write = flac_write,
-    .close = flac_close,
-    .format_required = flac_format_required,
-};
-
-#endif
diff --git a/src/filewriter/flac.cc b/src/filewriter/flac.cc
new file mode 100644
index 000000000000..8ea22f4aaad4
--- /dev/null
+++ b/src/filewriter/flac.cc
@@ -0,0 +1,206 @@
+/*  FileWriter FLAC Plugin
+ *  Copyright (c) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
+ *
+ *  Partially derived from Og(g)re - Ogg-Output-Plugin:
+ *  Copyright (c) 2002 Lars Siebold <khandha5 at gmx.net>
+ *
+ *  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.
+ */
+
+#include "plugins.h"
+
+#ifdef FILEWRITER_FLAC
+
+#include <FLAC/all.h>
+
+#include <libaudcore/audstrings.h>
+
+static int channels;
+static FLAC__StreamEncoder *flac_encoder;
+static FLAC__StreamMetadata *flac_metadata;
+
+static FLAC__StreamEncoderWriteStatus flac_write_cb(const FLAC__StreamEncoder *encoder,
+    const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void * data)
+{
+    VFSFile *file = (VFSFile *) data;
+
+    if (file->fwrite (buffer, 1, bytes) != (int64_t) bytes)
+        return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+
+    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+static FLAC__StreamEncoderSeekStatus flac_seek_cb(const FLAC__StreamEncoder *encoder,
+    FLAC__uint64 absolute_byte_offset, void * data)
+{
+    VFSFile *file = (VFSFile *) data;
+
+    if (file->fseek (absolute_byte_offset, VFS_SEEK_SET) < 0)
+        return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
+
+    return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+}
+
+static FLAC__StreamEncoderTellStatus flac_tell_cb(const FLAC__StreamEncoder *encoder,
+    FLAC__uint64 *absolute_byte_offset, void * data)
+{
+    VFSFile *file = (VFSFile *) data;
+
+    *absolute_byte_offset = file->ftell ();
+
+    return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+}
+
+static void insert_vorbis_comment (FLAC__StreamMetadata * meta,
+ const char * name, const Tuple & tuple, Tuple::Field field)
+{
+    Tuple::ValueType type = Tuple::field_get_type (field);
+    if (tuple.get_value_type (field) != type)
+        return;
+
+    StringBuf temp;
+
+    switch (type)
+    {
+    case Tuple::Int:
+    {
+        int ival = tuple.get_int (field);
+        temp.steal (str_printf ("%s=%d", name, ival));
+        break;
+    }
+    case Tuple::String:
+    {
+        String sval = tuple.get_str (field);
+        temp.steal (str_printf ("%s=%s", name, (const char *) sval));
+        break;
+    }
+    default:
+        return;
+    }
+
+    FLAC__StreamMetadata_VorbisComment_Entry comment;
+    comment.length = temp.len ();
+    comment.entry = (unsigned char *) (char *) temp;
+
+    FLAC__metadata_object_vorbiscomment_insert_comment (meta,
+     meta->data.vorbis_comment.num_comments, comment, true);
+}
+
+static bool flac_open (VFSFile & file, const format_info & info, const Tuple & tuple)
+{
+    flac_encoder = FLAC__stream_encoder_new();
+
+    FLAC__stream_encoder_set_channels(flac_encoder, info.channels);
+    FLAC__stream_encoder_set_sample_rate(flac_encoder, info.frequency);
+
+    flac_metadata = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+    insert_vorbis_comment (flac_metadata, "TITLE", tuple, Tuple::Title);
+    insert_vorbis_comment (flac_metadata, "ARTIST", tuple, Tuple::Artist);
+    insert_vorbis_comment (flac_metadata, "ALBUM", tuple, Tuple::Album);
+    insert_vorbis_comment (flac_metadata, "GENRE", tuple, Tuple::Genre);
+    insert_vorbis_comment (flac_metadata, "COMMENT", tuple, Tuple::Comment);
+    insert_vorbis_comment (flac_metadata, "DATE", tuple, Tuple::Date);
+    insert_vorbis_comment (flac_metadata, "YEAR", tuple, Tuple::Year);
+    insert_vorbis_comment (flac_metadata, "TRACKNUMBER", tuple, Tuple::Track);
+
+    FLAC__stream_encoder_set_metadata(flac_encoder, &flac_metadata, 1);
+
+    FLAC__stream_encoder_init_stream(flac_encoder, flac_write_cb, flac_seek_cb,
+     flac_tell_cb, nullptr, &file);
+
+    channels = info.channels;
+    return true;
+}
+
+static void flac_write (VFSFile & file, const void * data, int length)
+{
+#if 1
+    FLAC__int32 *encbuffer[2];
+    int16_t *tmpdata = (int16_t *) data;
+    int i;
+
+    encbuffer[0] = new FLAC__int32[length / channels];
+    encbuffer[1] = new FLAC__int32[length / channels];
+
+    if (channels == 1)
+    {
+        for (i = 0; i < (length / 2); i++)
+        {
+            encbuffer[0][i] = tmpdata[i];
+            encbuffer[1][i] = tmpdata[i];
+        }
+    }
+    else
+    {
+        for (i = 0; i < (length / 4); i++)
+        {
+            encbuffer[0][i] = tmpdata[2 * i];
+            encbuffer[1][i] = tmpdata[2 * i + 1];
+        }
+    }
+
+    FLAC__stream_encoder_process(flac_encoder, (const FLAC__int32 **)encbuffer, length / (channels * 2));
+
+    delete[] encbuffer[0];
+    delete[] encbuffer[1];
+#else
+    FLAC__int32 *encbuffer;
+    int16_t *tmpdata = (int16_t *) data;
+    int i;
+
+    encbuffer = new FLAC__int32[length];
+
+    for (i=0; i < length; i++) {
+        encbuffer[i] = tmpdata[i];
+    }
+
+    FLAC__stream_encoder_process_interleaved(flac_encoder, encbuffer, length);
+
+    delete[] encbuffer;
+#endif
+}
+
+static void flac_close (VFSFile & file)
+{
+    if (flac_encoder)
+    {
+        FLAC__stream_encoder_finish(flac_encoder);
+        FLAC__stream_encoder_delete(flac_encoder);
+        flac_encoder = nullptr;
+    }
+
+    if (flac_metadata)
+    {
+        FLAC__metadata_object_delete(flac_metadata);
+        flac_metadata = nullptr;
+    }
+}
+
+static int flac_format_required (int fmt)
+{
+    return FMT_S16_NE;
+}
+
+FileWriterImpl flac_plugin = {
+    nullptr,  // init
+    nullptr,  // configure
+    flac_open,
+    flac_write,
+    flac_close,
+    flac_format_required,
+};
+
+#endif
diff --git a/src/filewriter/mp3.c b/src/filewriter/mp3.c
deleted file mode 100644
index a6365d046b97..000000000000
--- a/src/filewriter/mp3.c
+++ /dev/null
@@ -1,1238 +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 at gmx.net>
- *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
- */
-
-/* #define AUD_DEBUG 1 */
-
-#include "plugins.h"
-
-#ifdef FILEWRITER_MP3
-
-#include <lame/lame.h>
-
-#include <audacious/debug.h>
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.h>
-
-#define MODES 4
-enum {MODE_AUTO = 4, MODE_JOINT = 1, MODE_STEREO = 0, MODE_MONO = 3};
-static const gint modes[MODES] = {MODE_AUTO, MODE_JOINT, MODE_STEREO, MODE_MONO};
-static const gchar * const mode_names[MODES] = {N_("Auto"), N_("Joint Stereo"),
- N_("Stereo"), N_("Mono")};
-
-static gint (*write_output)(void *ptr, gint length);
-
-static GtkWidget *configure_win = NULL;
-static GtkWidget *alg_quality_spin;
-static GtkWidget *alg_quality_hbox;
-static GtkAdjustment * alg_quality_adj;
-static GtkWidget *vbox, *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;
-static GtkWidget *compression_spin;
-static GtkAdjustment * compression_adj;
-static GtkWidget * mode_hbox, * mode_frame;
-static GtkWidget * samplerate_hbox, * samplerate_label, * samplerate_frame;
-static GtkWidget *misc_frame, *misc_vbox, *enforce_iso_toggle,
-                 *error_protection_toggle;
-static GtkWidget *vbr_vbox, *vbr_toggle, *vbr_options_vbox, *vbr_type_frame,
-                 *vbr_type_hbox, *vbr_type_radio1, *vbr_type_radio2;
-static GtkWidget * abr_frame, * abr_hbox, * abr_label;
-static GtkWidget *vbr_frame, *vbr_options_vbox2;
-static GtkWidget * vbr_options_hbox1, * vbr_min_label;
-static GtkWidget * vbr_options_hbox2, * vbr_max_label, * enforce_min_toggle;
-static GtkWidget *vbr_options_hbox3, *vbr_quality_spin, *vbr_quality_label;
-static GtkAdjustment * vbr_quality_adj;
-static GtkWidget *xing_header_toggle;
-static GtkWidget *tags_vbox, *tags_frames_frame, *tags_frames_hbox,
-                 *tags_copyright_toggle, *tags_original_toggle;
-static GtkWidget *tags_id3_frame, *tags_id3_vbox, *tags_id3_hbox,
-                 *tags_force_id3v2_toggle, *tags_only_v1_toggle, *tags_only_v2_toggle;
-
-static GtkWidget *enc_quality_vbox, *hbox1, *hbox2;
-
-static unsigned long numsamples = 0;
-static int inside;
-
-static gint available_samplerates[] =
-{ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 } ;
-
-static gint available_bitrates[] =
-{ 8, 16, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } ;
-
-typedef struct {
-    gchar *track_name;
-    gchar *album_name;
-    gchar *performer;
-    gchar *genre;
-    gchar *year;
-    gchar *track_number;
-} lameid3_t;
-
-static lameid3_t lameid3;
-
-static lame_global_flags *gfp;
-static unsigned char encbuffer[LAME_MAXMP3BUFFER];
-static int id3v2_size;
-
-static guchar * write_buffer;
-static gint write_buffer_size;
-
-static void free_lameid3(lameid3_t *p)
-{
-    str_unref (p->track_name);
-    str_unref (p->album_name);
-    str_unref (p->performer);
-    str_unref (p->genre);
-    str_unref (p->year);
-    str_unref (p->track_number);
-
-    p->track_name = NULL;
-    p->album_name = NULL;
-    p->performer = NULL;
-    p->genre = NULL;
-    p->year = NULL;
-    p->track_number = NULL;
-}
-
-static void lame_debugf(const char *format, va_list ap)
-{
-    (void) vfprintf(stdout, format, ap);
-}
-
-static const gchar * const mp3_defaults[] = {
- "vbr_on", "0",
- "vbr_type", "0",
- "vbr_min_val", "32",
- "vbr_max_val", "320",
- "enforce_min_val", "0",
- "vbr_quality_val", "4",
- "abr_val", "128",
- "toggle_xing_val", "1",
- "mark_original_val", "1",
- "mark_copyright_val", "0",
- "force_v2_val", "0",
- "only_v1_val", "0",
- "only_v2_val", "0",
- "algo_quality_val", "5",
- "out_samplerate_val", "0",
- "bitrate_val", "128",
- "compression_val", "11",
- "enc_toggle_val", "0",
- "audio_mode_val", "4", /* MODE_AUTO */
- "enforce_iso_val", "0",
- "error_protect_val", "0",
- NULL};
-
-static gint 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 gfloat compression_val;
-static gint enc_toggle_val, audio_mode_val, enforce_iso_val, error_protect_val;
-
-static void mp3_init(write_output_callback write_output_func)
-{
-    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");
-
-    if (write_output_func)
-        write_output=write_output_func;
-}
-
-static gint mp3_open(void)
-{
-    int imp3;
-
-    gfp = lame_init();
-    if (gfp == NULL)
-        return 0;
-
-    /* setup id3 data */
-    id3tag_init(gfp);
-
-    if (tuple) {
-        /* XXX write UTF-8 even though libmp3lame does id3v2.3. --yaz */
-        lameid3.track_name = tuple_get_str (tuple, FIELD_TITLE);
-        id3tag_set_title(gfp, lameid3.track_name);
-
-        lameid3.performer = tuple_get_str (tuple, FIELD_ARTIST);
-        id3tag_set_artist(gfp, lameid3.performer);
-
-        lameid3.album_name = tuple_get_str (tuple, FIELD_ALBUM);
-        id3tag_set_album(gfp, lameid3.album_name);
-
-        lameid3.genre = tuple_get_str (tuple, FIELD_GENRE);
-        id3tag_set_genre(gfp, lameid3.genre);
-
-        lameid3.year = int_to_str (tuple_get_int (tuple, FIELD_YEAR));
-        id3tag_set_year(gfp, lameid3.year);
-
-        lameid3.track_number = int_to_str (tuple_get_int (tuple, FIELD_TRACK_NUMBER));
-        id3tag_set_track(gfp, lameid3.track_number);
-
-        if (force_v2_val) {
-            id3tag_add_v2(gfp);
-        }
-        if (only_v1_val) {
-            id3tag_v1_only(gfp);
-        }
-        if (only_v2_val) {
-            id3tag_v2_only(gfp);
-        }
-    }
-
-    /* input stream description */
-
-    lame_set_in_samplerate(gfp, input.frequency);
-    lame_set_num_channels(gfp, input.channels);
-    /* Maybe implement this? */
-    /* lame_set_scale(lame_global_flags *, float); */
-    lame_set_out_samplerate(gfp, 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) {
-        AUDDBG("set mode to %d\n", audio_mode_val);
-        lame_set_mode(gfp, audio_mode_val);
-    }
-
-    lame_set_errorf(gfp, lame_debugf);
-    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);
-    else if (vbr_on == 0)
-        lame_set_compression_ratio(gfp, 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);
-
-    if (vbr_on != 0) {
-        if (vbr_type == 0)
-            lame_set_VBR(gfp, 2);
-        else
-            lame_set_VBR(gfp, 3);
-        lame_set_VBR_q(gfp, vbr_quality_val);
-        lame_set_VBR_mean_bitrate_kbps(gfp, 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);
-    }
-
-    /* not to write id3 tag automatically. */
-    lame_set_write_id3tag_automatic(gfp, 0);
-
-    if (lame_init_params(gfp) == -1)
-        return 0;
-
-    /* write id3v2 header */
-    imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer));
-
-    if (imp3 > 0) {
-        write_output(encbuffer, imp3);
-        id3v2_size = imp3;
-    }
-    else {
-        id3v2_size = 0;
-    }
-
-    write_buffer = NULL;
-    write_buffer_size = 0;
-
-    return 1;
-}
-
-static void mp3_write(void *ptr, gint length)
-{
-    gint encoded;
-
-    if (write_buffer_size == 0)
-    {
-        write_buffer_size = 8192;
-        write_buffer = g_realloc (write_buffer, write_buffer_size);
-    }
-
-RETRY:
-    if (input.channels == 1)
-        encoded = lame_encode_buffer (gfp, ptr, ptr, length / 2, write_buffer,
-         write_buffer_size);
-    else
-        encoded = lame_encode_buffer_interleaved (gfp, ptr, length / 4,
-         write_buffer, write_buffer_size);
-
-    if (encoded == -1)
-    {
-        write_buffer_size *= 2;
-        write_buffer = g_realloc (write_buffer, write_buffer_size);
-        goto RETRY;
-    }
-
-    if (encoded > 0)
-        write_output (write_buffer, encoded);
-
-    numsamples += length / (2 * input.channels);
-}
-
-static void mp3_close(void)
-{
-    if (output_file) {
-        int imp3, encout;
-
-        /* write remaining mp3 data */
-        encout = lame_encode_flush_nogap(gfp, encbuffer, LAME_MAXMP3BUFFER);
-        write_output(encbuffer, encout);
-
-        /* set gfp->num_samples for valid TLEN tag */
-        lame_set_num_samples(gfp, numsamples);
-
-        /* append v1 tag */
-        imp3 = lame_get_id3v1_tag(gfp, encbuffer, sizeof(encbuffer));
-        if (imp3 > 0)
-            write_output(encbuffer, imp3);
-
-        /* update v2 tag */
-        imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer));
-        if (imp3 > 0) {
-            if (vfs_fseek(output_file, 0, SEEK_SET) != 0) {
-                AUDDBG("can't rewind\n");
-            }
-            else {
-                write_output(encbuffer, imp3);
-            }
-        }
-
-        /* update lame tag */
-        if (id3v2_size) {
-            if (vfs_fseek(output_file, id3v2_size, SEEK_SET) != 0) {
-                AUDDBG("fatal error: can't update LAME-tag frame!\n");
-            }
-            else {
-                imp3 = lame_get_lametag_frame(gfp, encbuffer, sizeof(encbuffer));
-                write_output(encbuffer, imp3);
-            }
-        }
-    }
-
-    g_free (write_buffer);
-
-    lame_close(gfp);
-    AUDDBG("lame_close() done\n");
-
-    free_lameid3(&lameid3);
-    numsamples = 0;
-}
-
-/*****************/
-/* Configuration */
-/*****************/
-
-/* Various Signal-Fuctions */
-
-static void algo_qual(GtkAdjustment * adjustment, gpointer user_data)
-{
-
-    algo_quality_val =
-        gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON
-                                         (alg_quality_spin));
-
-}
-
-static void samplerate_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo) - 1;
-
-    if (i >= 0 && i < ARRAY_LEN (available_samplerates))
-        out_samplerate_val = available_samplerates[i];
-    else
-        out_samplerate_val = 0;
-}
-
-static void bitrate_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo);
-
-    if (i >= 0 && i < ARRAY_LEN (available_bitrates))
-        bitrate_val = available_bitrates[i];
-    else
-        bitrate_val = 128;
-}
-
-static void compression_change(GtkAdjustment * adjustment,
-                               gpointer user_data)
-{
-    compression_val = gtk_spin_button_get_value ((GtkSpinButton *)
-     compression_spin);
-}
-
-static void encoding_toggle(GtkToggleButton * togglebutton,
-                            gpointer user_data)
-{
-
-    enc_toggle_val = GPOINTER_TO_INT(user_data);
-
-}
-
-static void mode_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo);
-
-    if (i >= 0 && i < MODES)
-        audio_mode_val = modes[i];
-    else
-        audio_mode_val = MODE_AUTO;
-}
-
-static void toggle_enforce_iso(GtkToggleButton * togglebutton,
-                               gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_iso_toggle))
-        == TRUE)
-        enforce_iso_val = 1;
-    else
-        enforce_iso_val = 0;
-
-}
-
-static void toggle_error_protect(GtkToggleButton * togglebutton,
-                                 gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active
-        (GTK_TOGGLE_BUTTON(error_protection_toggle)) == TRUE)
-        error_protect_val = 1;
-    else
-        error_protect_val = 0;
-
-}
-
-static void toggle_vbr(GtkToggleButton * togglebutton, gpointer 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;
-
-        if (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);
-        }
-        else if (vbr_type == 1) {
-            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);
-        }
-
-    }
-    else {
-        gtk_widget_set_sensitive(vbr_options_vbox, FALSE);
-        gtk_widget_set_sensitive(enc_quality_frame, TRUE);
-        vbr_on = 0;
-    }
-}
-
-static void vbr_abr_toggle(GtkToggleButton * togglebutton,
-                           gpointer user_data)
-{
-    if (!strcmp(user_data, "VBR")) {
-        gtk_widget_set_sensitive(abr_frame, FALSE);
-        gtk_widget_set_sensitive(vbr_frame, TRUE);
-        vbr_type = 0;
-    }
-    else if (!strcmp(user_data, "ABR")) {
-        gtk_widget_set_sensitive(abr_frame, TRUE);
-        gtk_widget_set_sensitive(vbr_frame, FALSE);
-        vbr_type = 1;
-    }
-}
-
-static void vbr_min_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo);
-
-    if (i >= 0 && i < ARRAY_LEN (available_bitrates))
-        vbr_min_val = available_bitrates[i];
-    else
-        vbr_min_val = 32;
-}
-
-static void vbr_max_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo);
-
-    if (i >= 0 && i < ARRAY_LEN (available_bitrates))
-        vbr_max_val = available_bitrates[i];
-    else
-        vbr_max_val = 320;
-}
-
-static void toggle_enforce_min(GtkToggleButton * togglebutton,
-                               gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_min_toggle))
-        == TRUE)
-        enforce_min_val = 1;
-    else
-        enforce_min_val = 0;
-
-}
-
-static void vbr_qual(GtkAdjustment * adjustment, gpointer user_data)
-{
-
-    vbr_quality_val =
-        gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON
-                                         (vbr_quality_spin));
-
-}
-
-static void abr_changed (GtkComboBox * combo)
-{
-    gint i = gtk_combo_box_get_active (combo);
-
-    if (i >= 0 && i < ARRAY_LEN (available_bitrates))
-        abr_val = available_bitrates[i];
-    else
-        abr_val = 128;
-}
-
-static void toggle_xing(GtkToggleButton * togglebutton, gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xing_header_toggle)) == TRUE)
-        toggle_xing_val = 0;
-    else
-        toggle_xing_val = 1;
-
-}
-
-static void toggle_original(GtkToggleButton * togglebutton,
-                            gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active
-        (GTK_TOGGLE_BUTTON(tags_original_toggle)) == TRUE)
-        mark_original_val = 1;
-    else
-        mark_original_val = 0;
-
-}
-
-static void toggle_copyright(GtkToggleButton * togglebutton,
-                             gpointer user_data)
-{
-
-    if (gtk_toggle_button_get_active
-        (GTK_TOGGLE_BUTTON(tags_copyright_toggle)) == TRUE)
-        mark_copyright_val = 1;
-    else
-        mark_copyright_val = 0;
-
-}
-
-static void force_v2_toggle(GtkToggleButton * togglebutton,
-                            gpointer 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) {
-            inside = 1;
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_only_v1_toggle), FALSE);
-            only_v1_val = 0;
-            inside = 0;
-        }
-    }
-    else
-        force_v2_val = 0;
-
-}
-
-static void id3_only_version(GtkToggleButton * togglebutton,
-                             gpointer user_data)
-{
-    if (!strcmp(user_data, "v1") && inside != 1) {
-        if (gtk_toggle_button_get_active
-            (GTK_TOGGLE_BUTTON(tags_only_v1_toggle)) == TRUE)
-        {
-            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);
-            inside = 0;
-        }
-    }
-    else if (!strcmp(user_data, "v2") && inside != 1) {
-        if (gtk_toggle_button_get_active
-            (GTK_TOGGLE_BUTTON(tags_only_v2_toggle)) == TRUE)
-        {
-            inside = 1;
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_only_v1_toggle), FALSE);
-            only_v1_val = 0;
-            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)
-{
-    if (! configure_win)
-    {
-        configure_win = gtk_dialog_new_with_buttons (_("MP3 Configuration"),
-         NULL, 0, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_OK"), GTK_RESPONSE_OK,
-         NULL);
-
-        g_signal_connect (configure_win, "response", (GCallback) configure_response_cb, NULL);
-        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_box_new(GTK_ORIENTATION_VERTICAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 5);
-
-        quality_hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(alg_quality_hbox),
-                                       10);
-        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);
-        g_signal_connect (alg_quality_adj, "value-changed", (GCallback)
-         algo_qual, NULL);
-
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(alg_quality_spin),
-                                  algo_quality_val);
-
-        /* Output Samplerate */
-
-        samplerate_frame = gtk_frame_new(_("Output Samplerate:"));
-        gtk_container_set_border_width(GTK_CONTAINER(samplerate_frame), 5);
-        gtk_box_pack_start(GTK_BOX(quality_hbox1), samplerate_frame, FALSE,
-                           FALSE, 0);
-
-        samplerate_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(samplerate_hbox), 10);
-        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"));
-        if (! out_samplerate_val)
-            gtk_combo_box_set_active ((GtkComboBox *) combo, 0);
-
-        for (int i = 0; i < ARRAY_LEN (available_samplerates); i ++)
-        {
-            gchar buf[10];
-            str_itoa (available_samplerates[i], buf, sizeof buf);
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, buf);
-
-            if (out_samplerate_val == available_samplerates[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, 1 + i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) samplerate_hbox, combo, FALSE, FALSE, 0);
-        g_signal_connect (combo, "changed", (GCallback) samplerate_changed, NULL);
-
-        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);
-
-        /* 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);
-
-        // vbox sorrounding hbox1 and hbox2
-        enc_quality_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(enc_quality_vbox), 10);
-
-        // pack vbox to frame
-        gtk_container_add(GTK_CONTAINER(enc_quality_frame), enc_quality_vbox);
-
-        // hbox1 for bitrate
-        hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_add(GTK_CONTAINER(enc_quality_vbox), hbox1);
-
-        // radio 1
-        enc_radio1 = gtk_radio_button_new(NULL);
-        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);
-
-        // label 1
-        enc_quality_label1 = gtk_label_new(_("Bitrate (kbps):"));
-        gtk_box_pack_start(GTK_BOX(hbox1), enc_quality_label1, FALSE, FALSE, 0);
-
-        // bitrate menu
-
-        combo = gtk_combo_box_text_new ();
-
-        for (int i = 0; i < ARRAY_LEN (available_bitrates); i ++)
-        {
-            gchar buf[10];
-            str_itoa (available_bitrates[i], buf, sizeof buf);
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, buf);
-
-            if (bitrate_val == available_bitrates[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) hbox1, combo, FALSE, FALSE, 0);
-        g_signal_connect (combo, "changed", (GCallback) bitrate_changed, NULL);
-
-        // hbox2 for compression ratio
-        hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
-
-        // label
-        enc_quality_label2 = gtk_label_new(_("Compression ratio:"));
-        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_spin =
-            gtk_spin_button_new(GTK_ADJUSTMENT(compression_adj), 8, 0);
-        gtk_box_pack_end(GTK_BOX(hbox2), compression_spin, FALSE, FALSE, 0);
-
-        g_signal_connect (compression_adj, "value-changed", (GCallback)
-         compression_change, NULL);
-
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(compression_spin),
-                                  compression_val);
-
-        // radio button signale connect
-        g_signal_connect (enc_radio1, "toggled", (GCallback) encoding_toggle,
-         GINT_TO_POINTER (0));
-        g_signal_connect (enc_radio2, "toggled", (GCallback) encoding_toggle,
-         GINT_TO_POINTER (1));
-
-        /* 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);
-
-        mode_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
-        gtk_container_set_border_width(GTK_CONTAINER(mode_hbox), 10);
-        gtk_container_add(GTK_CONTAINER(mode_frame), mode_hbox);
-
-        combo = gtk_combo_box_text_new ();
-
-        for (int i = 0; i < MODES; i ++)
-        {
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
-             _(mode_names[i]));
-
-            if (audio_mode_val == modes[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) mode_hbox, combo, FALSE, FALSE, 0);
-        g_signal_connect (combo, "changed", (GCallback) mode_changed, NULL);
-
-        /* Misc */
-
-        misc_frame = gtk_frame_new(_("Misc:"));
-        gtk_container_set_border_width(GTK_CONTAINER(misc_frame), 5);
-        gtk_box_pack_start(GTK_BOX(quality_vbox), misc_frame, FALSE, FALSE,
-                           0);
-
-        misc_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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 complience"));
-        gtk_box_pack_start(GTK_BOX(misc_vbox), enforce_iso_toggle, TRUE,
-                           TRUE, 2);
-        g_signal_connect (enforce_iso_toggle, "toggled", (GCallback)
-         toggle_enforce_iso, NULL);
-
-        if (enforce_iso_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (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);
-        g_signal_connect (error_protection_toggle, "toggled", (GCallback)
-         toggle_error_protect, NULL);
-
-        if (error_protect_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (error_protection_toggle), TRUE);
-
-        /* Add the Notebook */
-        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), quality_vbox,
-                                 gtk_label_new(_("Quality")));
-
-        /* VBR/ABR */
-
-        vbr_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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);
-        g_signal_connect (vbr_toggle, "toggled", (GCallback) toggle_vbr, NULL);
-
-        vbr_options_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-        gtk_container_add(GTK_CONTAINER(vbr_vbox), vbr_options_vbox);
-        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);
-
-        vbr_type_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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(NULL, "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);
-
-        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);
-
-        g_signal_connect (vbr_type_radio1, "toggled", (GCallback)
-         vbr_abr_toggle, "VBR");
-        g_signal_connect (vbr_type_radio2, "toggled", (GCallback)
-         vbr_abr_toggle, "ABR");
-
-        /* 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);
-
-        vbr_options_vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox1),
-                                       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);
-
-        combo = gtk_combo_box_text_new ();
-
-        for (int i = 0; i < ARRAY_LEN (available_bitrates); i ++)
-        {
-            gchar buf[10];
-            str_itoa (available_bitrates[i], buf, sizeof buf);
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, buf);
-
-            if (vbr_min_val == available_bitrates[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) vbr_options_hbox1, combo, FALSE, FALSE,
-         0);
-        g_signal_connect (combo, "changed", (GCallback) vbr_min_changed, NULL);
-
-        vbr_options_hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox2),
-                                       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);
-
-        combo = gtk_combo_box_text_new ();
-
-        for (int i = 0; i < ARRAY_LEN (available_bitrates); i ++)
-        {
-            gchar buf[10];
-            str_itoa (available_bitrates[i], buf, sizeof buf);
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, buf);
-
-            if (vbr_max_val == available_bitrates[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) vbr_options_hbox2, combo, FALSE, FALSE,
-         0);
-        g_signal_connect (combo, "changed", (GCallback) vbr_max_changed, NULL);
-
-        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);
-        g_signal_connect (enforce_min_toggle, "toggled", (GCallback)
-         toggle_enforce_min, NULL);
-
-        if (enforce_min_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (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);
-
-        abr_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
-
-        combo = gtk_combo_box_text_new ();
-
-        for (int i = 0; i < ARRAY_LEN (available_bitrates); i ++)
-        {
-            gchar buf[10];
-            str_itoa (available_bitrates[i], buf, sizeof buf);
-            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, buf);
-
-            if (abr_val == available_bitrates[i])
-                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
-        }
-
-        gtk_box_pack_start ((GtkBox *) abr_hbox, combo, FALSE, FALSE,
-         0);
-        g_signal_connect (combo, "changed", (GCallback) abr_changed, NULL);
-
-        /* Quality Level */
-
-        vbr_options_hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox3),
-                                       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);
-
-        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);
-        g_signal_connect (vbr_quality_adj, "value-changed", (GCallback)
-         vbr_qual, NULL);
-
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(vbr_quality_spin),
-                                  vbr_quality_val);
-
-        /* Xing Header */
-
-        xing_header_toggle =
-            gtk_check_button_new_with_label(_("Don't write Xing VBR header"));
-        gtk_box_pack_start(GTK_BOX(vbr_options_vbox), xing_header_toggle,
-                           FALSE, FALSE, 2);
-        g_signal_connect (xing_header_toggle, "toggled", (GCallback)
-         toggle_xing, NULL);
-
-        if (toggle_xing_val == 0)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (xing_header_toggle), TRUE);
-
-        /* Add the Notebook */
-
-        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbr_vbox,
-                                 gtk_label_new(_("VBR/ABR")));
-
-        /* Tags */
-
-        tags_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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);
-
-        tags_frames_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(tags_frames_hbox), 5);
-        gtk_container_add(GTK_CONTAINER(tags_frames_frame),
-                          tags_frames_hbox);
-
-        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);
-        g_signal_connect (tags_copyright_toggle, "toggled", (GCallback)
-         toggle_copyright, NULL);
-
-        if (mark_copyright_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (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);
-        g_signal_connect (tags_original_toggle, "toggled", (GCallback)
-         toggle_original, NULL);
-
-        if (mark_original_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_original_toggle), TRUE);
-
-        /* ID3 Params */
-
-        tags_id3_frame = gtk_frame_new(_("ID3 params:"));
-        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);
-
-        tags_id3_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 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);
-        g_signal_connect (tags_force_id3v2_toggle, "toggled", (GCallback)
-         force_v2_toggle, NULL);
-
-        tags_id3_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
-        g_signal_connect (tags_only_v1_toggle, "toggled", (GCallback)
-         id3_only_version, "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);
-        g_signal_connect (tags_only_v2_toggle, "toggled", (GCallback)
-         id3_only_version, "v2");
-
-        if (force_v2_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_force_id3v2_toggle), TRUE);
-
-        if (only_v1_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_only_v1_toggle), TRUE);
-
-        if (only_v2_val == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
-                                         (tags_only_v2_toggle), TRUE);
-
-        /* Add the Notebook */
-
-        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tags_vbox,
-                                 gtk_label_new(_("Tags")));
-
-        /* Set States */
-
-        if (vbr_on == 1)
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle),
-                                         TRUE);
-        else
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle),
-                                         FALSE);
-
-        /* Show it! */
-
-        gtk_widget_show_all(configure_win);
-    }
-}
-
-static int mp3_format_required (int fmt)
-{
-    return FMT_S16_NE;
-}
-
-FileWriter mp3_plugin =
-{
-    .init = mp3_init,
-    .configure = mp3_configure,
-    .open = mp3_open,
-    .write = mp3_write,
-    .close = mp3_close,
-    .format_required = mp3_format_required,
-};
-
-#endif
diff --git a/src/filewriter/mp3.cc b/src/filewriter/mp3.cc
new file mode 100644
index 000000000000..81f2aab589b3
--- /dev/null
+++ b/src/filewriter/mp3.cc
@@ -0,0 +1,1200 @@
+/*  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 at gmx.net>
+ *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
+ */
+
+/* #define AUD_DEBUG 1 */
+
+#include "plugins.h"
+
+#ifdef FILEWRITER_MP3
+
+#include <string.h>
+#include <lame/lame.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#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 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 *quality_vbox, *quality_hbox1, *alg_quality_frame;
+static GtkWidget *enc_quality_frame, *enc_quality_label1, *enc_quality_label2;
+static GtkWidget * enc_radio1, * enc_radio2;
+static GtkWidget *compression_spin;
+static GtkAdjustment * compression_adj;
+static GtkWidget * mode_hbox, * mode_frame;
+static GtkWidget * samplerate_hbox, * samplerate_label, * samplerate_frame;
+static GtkWidget *misc_frame, *misc_vbox, *enforce_iso_toggle,
+                 *error_protection_toggle;
+static GtkWidget *vbr_vbox, *vbr_toggle, *vbr_options_vbox, *vbr_type_frame,
+                 *vbr_type_hbox, *vbr_type_radio1, *vbr_type_radio2;
+static GtkWidget * abr_frame, * abr_hbox, * abr_label;
+static GtkWidget *vbr_frame, *vbr_options_vbox2;
+static GtkWidget * vbr_options_hbox1, * vbr_min_label;
+static GtkWidget * vbr_options_hbox2, * vbr_max_label, * enforce_min_toggle;
+static GtkWidget *vbr_options_hbox3, *vbr_quality_spin, *vbr_quality_label;
+static GtkAdjustment * vbr_quality_adj;
+static GtkWidget *xing_header_toggle;
+static GtkWidget *tags_vbox, *tags_frames_frame, *tags_frames_hbox,
+                 *tags_copyright_toggle, *tags_original_toggle;
+static GtkWidget *tags_id3_frame, *tags_id3_vbox, *tags_id3_hbox,
+                 *tags_force_id3v2_toggle, *tags_only_v1_toggle, *tags_only_v2_toggle;
+
+static GtkWidget *enc_quality_vbox, *hbox1, *hbox2;
+
+static unsigned long numsamples = 0;
+static int inside;
+
+static int available_samplerates[] =
+{ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 } ;
+
+static int available_bitrates[] =
+{ 8, 16, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } ;
+
+struct lameid3_t {
+    String track_name;
+    String album_name;
+    String performer;
+    String genre;
+    String year;
+    String track_number;
+};
+
+static lameid3_t lameid3;
+
+static lame_global_flags *gfp;
+static unsigned char encbuffer[LAME_MAXMP3BUFFER];
+static int id3v2_size;
+
+static int channels;
+static Index<unsigned char> write_buffer;
+
+static void lame_debugf(const char *format, va_list ap)
+{
+    (void) vprintf(format, ap);
+}
+
+static const char * const mp3_defaults[] = {
+ "vbr_on", "0",
+ "vbr_type", "0",
+ "vbr_min_val", "32",
+ "vbr_max_val", "320",
+ "enforce_min_val", "0",
+ "vbr_quality_val", "4",
+ "abr_val", "128",
+ "toggle_xing_val", "1",
+ "mark_original_val", "1",
+ "mark_copyright_val", "0",
+ "force_v2_val", "0",
+ "only_v1_val", "0",
+ "only_v2_val", "0",
+ "algo_quality_val", "5",
+ "out_samplerate_val", "0",
+ "bitrate_val", "128",
+ "compression_val", "11",
+ "enc_toggle_val", "0",
+ "audio_mode_val", "4", /* MODE_AUTO */
+ "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;
+
+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)
+{
+    int imp3;
+
+    gfp = lame_init();
+    if (gfp == nullptr)
+        return false;
+
+    /* setup id3 data */
+    id3tag_init(gfp);
+
+    /* XXX write UTF-8 even though libmp3lame does id3v2.3. --yaz */
+    lameid3.track_name = tuple.get_str (Tuple::Title);
+    id3tag_set_title(gfp, lameid3.track_name);
+
+    lameid3.performer = tuple.get_str (Tuple::Artist);
+    id3tag_set_artist(gfp, lameid3.performer);
+
+    lameid3.album_name = tuple.get_str (Tuple::Album);
+    id3tag_set_album(gfp, lameid3.album_name);
+
+    lameid3.genre = tuple.get_str (Tuple::Genre);
+    id3tag_set_genre(gfp, lameid3.genre);
+
+    lameid3.year = String (int_to_str (tuple.get_int (Tuple::Year)));
+    id3tag_set_year(gfp, lameid3.year);
+
+    lameid3.track_number = String (int_to_str (tuple.get_int (Tuple::Track)));
+    id3tag_set_track(gfp, lameid3.track_number);
+
+    if (force_v2_val)
+        id3tag_add_v2(gfp);
+    if (only_v1_val)
+        id3tag_v1_only(gfp);
+    if (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);
+
+    /* general control parameters */
+
+    lame_set_bWriteVbrTag(gfp, toggle_xing_val);
+    lame_set_quality(gfp, algo_quality_val);
+    if (audio_mode_val != 4) {
+        AUDDBG("set mode to %d\n", audio_mode_val);
+        lame_set_mode(gfp, (MPEG_mode) audio_mode_val);
+    }
+
+    lame_set_errorf(gfp, lame_debugf);
+    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);
+    else if (vbr_on == 0)
+        lame_set_compression_ratio(gfp, 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);
+
+    if (vbr_on != 0) {
+        if (vbr_type == 0)
+            lame_set_VBR(gfp, (vbr_mode) 2);
+        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_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);
+    }
+
+    /* not to write id3 tag automatically. */
+    lame_set_write_id3tag_automatic(gfp, 0);
+
+    if (lame_init_params(gfp) == -1)
+        return false;
+
+    /* write id3v2 header */
+    imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer));
+
+    if (imp3 > 0) {
+        if (file.fwrite (encbuffer, 1, imp3) != imp3)
+            AUDERR ("write error\n");
+        id3v2_size = imp3;
+    }
+    else {
+        id3v2_size = 0;
+    }
+
+    channels = info.channels;
+    return true;
+}
+
+static void mp3_write (VFSFile & file, const void * data, int length)
+{
+    int encoded;
+
+    if (! write_buffer.len ())
+        write_buffer.resize (8192);
+
+    while (1)
+    {
+        if (channels == 1)
+            encoded = lame_encode_buffer (gfp, (int16_t *) data, (int16_t *) data,
+             length / 2, write_buffer.begin (), write_buffer.len ());
+        else
+            encoded = lame_encode_buffer_interleaved (gfp, (int16_t *) data,
+             length / 4, write_buffer.begin (), write_buffer.len ());
+
+        if (encoded != -1)
+            break;
+
+        write_buffer.resize (write_buffer.len () * 2);
+    }
+
+    if (encoded > 0 && file.fwrite (write_buffer.begin (), 1, encoded) != encoded)
+        AUDERR ("write error\n");
+
+    numsamples += length / (2 * channels);
+}
+
+static void mp3_close (VFSFile & file)
+{
+    int imp3, encout;
+
+    /* write remaining mp3 data */
+    encout = lame_encode_flush_nogap(gfp, encbuffer, LAME_MAXMP3BUFFER);
+    if (file.fwrite (encbuffer, 1, encout) != encout)
+        AUDERR ("write error\n");
+
+    /* set gfp->num_samples for valid TLEN tag */
+    lame_set_num_samples(gfp, numsamples);
+
+    /* append v1 tag */
+    imp3 = lame_get_id3v1_tag(gfp, encbuffer, sizeof(encbuffer));
+    if (imp3 > 0 && file.fwrite (encbuffer, 1, imp3) != imp3)
+        AUDERR ("write error\n");
+
+    /* update v2 tag */
+    imp3 = lame_get_id3v2_tag(gfp, encbuffer, sizeof(encbuffer));
+    if (imp3 > 0) {
+        if (file.fseek (0, VFS_SEEK_SET) != 0)
+            AUDERR ("seek error\n");
+        else if (file.fwrite (encbuffer, 1, imp3) != imp3)
+            AUDERR ("write error\n");
+    }
+
+    /* update lame tag */
+    if (id3v2_size) {
+        if (file.fseek (id3v2_size, VFS_SEEK_SET) != 0)
+            AUDERR ("seek error\n");
+        else {
+            imp3 = lame_get_lametag_frame(gfp, encbuffer, sizeof(encbuffer));
+            if (file.fwrite (encbuffer, 1, imp3) != imp3)
+                AUDERR ("write error\n");
+        }
+    }
+
+    write_buffer.clear ();
+
+    lame_close(gfp);
+    AUDDBG("lame_close() done\n");
+
+    lameid3 = lameid3_t ();
+    numsamples = 0;
+}
+
+/*****************/
+/* Configuration */
+/*****************/
+
+/* Various Signal-Fuctions */
+
+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));
+
+}
+
+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];
+    else
+        out_samplerate_val = 0;
+}
+
+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];
+    else
+        bitrate_val = 128;
+}
+
+static void compression_change(GtkAdjustment * adjustment,
+                               void * user_data)
+{
+    compression_val = gtk_spin_button_get_value ((GtkSpinButton *)
+     compression_spin);
+}
+
+static void encoding_toggle(GtkToggleButton * togglebutton,
+                            void * user_data)
+{
+
+    enc_toggle_val = GPOINTER_TO_INT(user_data);
+
+}
+
+static void mode_changed (GtkComboBox * combo)
+{
+    int i = gtk_combo_box_get_active (combo);
+
+    if (i >= 0 && i < MODES)
+        audio_mode_val = modes[i];
+    else
+        audio_mode_val = MODE_AUTO;
+}
+
+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;
+    else
+        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;
+    else
+        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;
+
+        if (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);
+        }
+        else if (vbr_type == 1) {
+            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);
+        }
+
+    }
+    else {
+        gtk_widget_set_sensitive(vbr_options_vbox, FALSE);
+        gtk_widget_set_sensitive(enc_quality_frame, TRUE);
+        vbr_on = 0;
+    }
+}
+
+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;
+    }
+    else if (!strcmp((char *) user_data, "ABR")) {
+        gtk_widget_set_sensitive(abr_frame, TRUE);
+        gtk_widget_set_sensitive(vbr_frame, FALSE);
+        vbr_type = 1;
+    }
+}
+
+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];
+    else
+        vbr_min_val = 32;
+}
+
+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];
+    else
+        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;
+    else
+        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));
+
+}
+
+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];
+    else
+        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;
+    else
+        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;
+    else
+        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;
+    else
+        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) {
+            inside = 1;
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (tags_only_v1_toggle), FALSE);
+            only_v1_val = 0;
+            inside = 0;
+        }
+    }
+    else
+        force_v2_val = 0;
+
+}
+
+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)
+        {
+            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);
+            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)
+        {
+            inside = 1;
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (tags_only_v1_toggle), FALSE);
+            only_v1_val = 0;
+            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)
+{
+    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);
+        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);
+
+        /* 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_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);
+        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);
+
+        /* 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);
+
+        samplerate_hbox = gtk_hbox_new (FALSE, 5);
+        gtk_container_set_border_width(GTK_CONTAINER(samplerate_hbox), 10);
+        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"));
+        if (! out_samplerate_val)
+            gtk_combo_box_set_active ((GtkComboBox *) combo, 0);
+
+        for (int i = 0; i < aud::n_elems (available_samplerates); i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             int_to_str (available_samplerates[i]));
+
+            if (out_samplerate_val == available_samplerates[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, 1 + i);
+        }
+
+        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);
+
+        /* 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);
+
+        // vbox sorrounding hbox1 and hbox2
+        enc_quality_vbox = gtk_vbox_new (FALSE, 5);
+        gtk_container_set_border_width(GTK_CONTAINER(enc_quality_vbox), 10);
+
+        // pack vbox to frame
+        gtk_container_add(GTK_CONTAINER(enc_quality_frame), enc_quality_vbox);
+
+        // hbox1 for bitrate
+        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);
+
+        // label 1
+        enc_quality_label1 = gtk_label_new(_("Bitrate (kbps):"));
+        gtk_box_pack_start(GTK_BOX(hbox1), enc_quality_label1, FALSE, FALSE, 0);
+
+        // bitrate menu
+
+        combo = gtk_combo_box_text_new ();
+
+        for (int i = 0; i < aud::n_elems (available_bitrates); i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             int_to_str (available_bitrates[i]));
+
+            if (bitrate_val == available_bitrates[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
+        }
+
+        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);
+        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);
+
+        // label
+        enc_quality_label2 = gtk_label_new(_("Compression ratio:"));
+        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_spin =
+            gtk_spin_button_new(GTK_ADJUSTMENT(compression_adj), 8, 0);
+        gtk_box_pack_end(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);
+
+        // radio button signale connect
+        g_signal_connect (enc_radio1, "toggled", (GCallback) encoding_toggle,
+         GINT_TO_POINTER (0));
+        g_signal_connect (enc_radio2, "toggled", (GCallback) encoding_toggle,
+         GINT_TO_POINTER (1));
+
+        /* 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);
+
+        mode_hbox = gtk_hbox_new (FALSE, 10);
+        gtk_container_set_border_width(GTK_CONTAINER(mode_hbox), 10);
+        gtk_container_add(GTK_CONTAINER(mode_frame), mode_hbox);
+
+        combo = gtk_combo_box_text_new ();
+
+        for (int i = 0; i < MODES; i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             _(mode_names[i]));
+
+            if (audio_mode_val == modes[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
+        }
+
+        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);
+
+        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);
+        g_signal_connect (enforce_iso_toggle, "toggled", (GCallback)
+         toggle_enforce_iso, nullptr);
+
+        if (enforce_iso_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (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);
+        g_signal_connect (error_protection_toggle, "toggled", (GCallback)
+         toggle_error_protect, nullptr);
+
+        if (error_protect_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (error_protection_toggle), TRUE);
+
+        /* Add the Notebook */
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), quality_vbox,
+                                 gtk_label_new(_("Quality")));
+
+        /* VBR/ABR */
+
+        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);
+        g_signal_connect (vbr_toggle, "toggled", (GCallback) toggle_vbr, nullptr);
+
+        vbr_options_vbox = gtk_vbox_new (FALSE, 0);
+        gtk_container_add(GTK_CONTAINER(vbr_vbox), vbr_options_vbox);
+        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);
+
+        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);
+
+        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);
+
+        g_signal_connect (vbr_type_radio1, "toggled", (GCallback)
+         vbr_abr_toggle, (void *) "VBR");
+        g_signal_connect (vbr_type_radio2, "toggled", (GCallback)
+         vbr_abr_toggle, (void *) "ABR");
+
+        /* 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);
+
+        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);
+        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);
+
+        combo = gtk_combo_box_text_new ();
+
+        for (int i = 0; i < aud::n_elems (available_bitrates); i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             int_to_str (available_bitrates[i]));
+
+            if (vbr_min_val == available_bitrates[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
+        }
+
+        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);
+        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);
+
+        combo = gtk_combo_box_text_new ();
+
+        for (int i = 0; i < aud::n_elems (available_bitrates); i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             int_to_str (available_bitrates[i]));
+
+            if (vbr_max_val == available_bitrates[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
+        }
+
+        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);
+        g_signal_connect (enforce_min_toggle, "toggled", (GCallback)
+         toggle_enforce_min, nullptr);
+
+        if (enforce_min_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (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);
+
+        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);
+
+        combo = gtk_combo_box_text_new ();
+
+        for (int i = 0; i < aud::n_elems (available_bitrates); i ++)
+        {
+            gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
+             int_to_str (available_bitrates[i]));
+
+            if (abr_val == available_bitrates[i])
+                gtk_combo_box_set_active ((GtkComboBox *) combo, i);
+        }
+
+        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);
+        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);
+
+        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);
+        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);
+
+        /* 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);
+        g_signal_connect (xing_header_toggle, "toggled", (GCallback)
+         toggle_xing, nullptr);
+
+        if (toggle_xing_val == 0)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (xing_header_toggle), TRUE);
+
+        /* Add the Notebook */
+
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbr_vbox,
+                                 gtk_label_new(_("VBR/ABR")));
+
+        /* Tags */
+
+        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);
+
+        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);
+
+        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);
+        g_signal_connect (tags_copyright_toggle, "toggled", (GCallback)
+         toggle_copyright, nullptr);
+
+        if (mark_copyright_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (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);
+        g_signal_connect (tags_original_toggle, "toggled", (GCallback)
+         toggle_original, nullptr);
+
+        if (mark_original_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (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);
+
+        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);
+        g_signal_connect (tags_force_id3v2_toggle, "toggled", (GCallback)
+         force_v2_toggle, nullptr);
+
+        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);
+        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);
+        g_signal_connect (tags_only_v2_toggle, "toggled", (GCallback)
+         id3_only_version, (void *) "v2");
+
+        if (force_v2_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (tags_force_id3v2_toggle), TRUE);
+
+        if (only_v1_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (tags_only_v1_toggle), TRUE);
+
+        if (only_v2_val == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
+                                         (tags_only_v2_toggle), TRUE);
+
+        /* Add the Notebook */
+
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tags_vbox,
+                                 gtk_label_new(_("Tags")));
+
+        /* Set States */
+
+        if (vbr_on == 1)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle),
+                                         TRUE);
+        else
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle),
+                                         FALSE);
+
+        /* Show it! */
+
+        gtk_widget_show_all(configure_win);
+    }
+}
+
+static int mp3_format_required (int fmt)
+{
+    return FMT_S16_NE;
+}
+
+FileWriterImpl mp3_plugin = {
+    mp3_init,
+    mp3_configure,
+    mp3_open,
+    mp3_write,
+    mp3_close,
+    mp3_format_required,
+};
+
+#endif
diff --git a/src/filewriter/plugins.h b/src/filewriter/plugins.h
index fde0734af835..3293295ba278 100644
--- a/src/filewriter/plugins.h
+++ b/src/filewriter/plugins.h
@@ -25,15 +25,15 @@
 
 #include "filewriter.h"
 
-extern FileWriter wav_plugin;
+extern FileWriterImpl wav_plugin;
 #ifdef FILEWRITER_MP3
-extern FileWriter mp3_plugin;
+extern FileWriterImpl mp3_plugin;
 #endif
 #ifdef FILEWRITER_VORBIS
-extern FileWriter vorbis_plugin;
+extern FileWriterImpl vorbis_plugin;
 #endif
 #ifdef FILEWRITER_FLAC
-extern FileWriter flac_plugin;
+extern FileWriterImpl flac_plugin;
 #endif
 
 #endif
diff --git a/src/filewriter/vorbis.c b/src/filewriter/vorbis.c
deleted file mode 100644
index 1891fa7086aa..000000000000
--- a/src/filewriter/vorbis.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*  FileWriter Vorbis Plugin
- *  Copyright (c) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
- *
- *  Partially derived from Og(g)re - Ogg-Output-Plugin:
- *  Copyright (c) 2002 Lars Siebold <khandha5 at gmx.net>
- *
- *  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.
- */
-
-#include "plugins.h"
-
-#ifdef FILEWRITER_VORBIS
-
-#include <vorbis/vorbisenc.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.h>
-
-static gint (*write_output)(void *ptr, gint length);
-
-static ogg_stream_state os;
-static ogg_page og;
-static ogg_packet op;
-
-static vorbis_dsp_state vd;
-static vorbis_block vb;
-static vorbis_info vi;
-static vorbis_comment vc;
-
-static const gchar * const vorbis_defaults[] = {
- "base_quality", "0.5",
- NULL};
-
-static gdouble v_base_quality;
-
-static void vorbis_init(write_output_callback write_output_func)
-{
-    aud_config_set_defaults ("filewriter_vorbis", vorbis_defaults);
-
-    v_base_quality = aud_get_double ("filewriter_vorbis", "base_quality");
-
-    if (write_output_func)
-        write_output=write_output_func;
-}
-
-static void add_string_from_tuple (vorbis_comment * vc, const char * name,
- const Tuple * tuple, gint field)
-{
-    gchar * val = tuple_get_str (tuple, field);
-    if (! val)
-        return;
-
-    vorbis_comment_add_tag (vc, name, val);
-    str_unref (val);
-}
-
-static gint vorbis_open(void)
-{
-    ogg_packet header;
-    ogg_packet header_comm;
-    ogg_packet header_code;
-
-    vorbis_init(NULL);
-
-    vorbis_info_init(&vi);
-    vorbis_comment_init(&vc);
-
-    if (tuple)
-    {
-        gchar tmpstr[32];
-        gint scrint;
-
-        add_string_from_tuple (& vc, "title", tuple, FIELD_TITLE);
-        add_string_from_tuple (& vc, "artist", tuple, FIELD_ARTIST);
-        add_string_from_tuple (& vc, "album", tuple, FIELD_ALBUM);
-        add_string_from_tuple (& vc, "genre", tuple, FIELD_GENRE);
-        add_string_from_tuple (& vc, "date", tuple, FIELD_DATE);
-        add_string_from_tuple (& vc, "comment", tuple, FIELD_COMMENT);
-
-        if ((scrint = tuple_get_int(tuple, FIELD_TRACK_NUMBER)))
-        {
-            str_itoa (scrint, tmpstr, sizeof tmpstr);
-            vorbis_comment_add_tag(&vc, "tracknumber", tmpstr);
-        }
-
-        if ((scrint = tuple_get_int(tuple, FIELD_YEAR)))
-        {
-            str_itoa (scrint, tmpstr, sizeof tmpstr);
-            vorbis_comment_add_tag(&vc, "year", tmpstr);
-        }
-    }
-
-    if (vorbis_encode_init_vbr (& vi, input.channels, input.frequency,
-     v_base_quality))
-    {
-        vorbis_info_clear(&vi);
-        return 0;
-    }
-
-    vorbis_analysis_init(&vd, &vi);
-    vorbis_block_init(&vd, &vb);
-
-    srand(time(NULL));
-    ogg_stream_init(&os, rand());
-
-    vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
-
-    ogg_stream_packetin(&os, &header);
-    ogg_stream_packetin(&os, &header_comm);
-    ogg_stream_packetin(&os, &header_code);
-
-    while (ogg_stream_flush (& os, & og))
-    {
-        write_output(og.header, og.header_len);
-        write_output(og.body, og.body_len);
-    }
-
-    return 1;
-}
-
-static void vorbis_write_real (void * data, gint length)
-{
-    int samples = length / sizeof (float);
-    int channel, result;
-    float * end = (float *) data + samples;
-    float * * buffer = vorbis_analysis_buffer (& vd, samples / input.channels);
-    float * from, * to;
-
-    for (channel = 0; channel < input.channels; channel ++)
-    {
-        to = buffer[channel];
-
-        for (from = (float *) data + channel; from < end; from += input.channels)
-            * to ++ = * from;
-    }
-
-    vorbis_analysis_wrote (& vd, samples / input.channels);
-
-    while(vorbis_analysis_blockout(&vd, &vb) == 1)
-    {
-        vorbis_analysis(&vb, &op);
-        vorbis_bitrate_addblock(&vb);
-
-        while (vorbis_bitrate_flushpacket(&vd, &op))
-        {
-            ogg_stream_packetin(&os, &op);
-
-            while ((result = ogg_stream_pageout(&os, &og)))
-            {
-                write_output(og.header, og.header_len);
-                write_output(og.body, og.body_len);
-            }
-        }
-    }
-}
-
-static void vorbis_write (void * data, gint length)
-{
-    if (length > 0) /* don't signal end of file yet */
-        vorbis_write_real (data, length);
-}
-
-static void vorbis_close(void)
-{
-    vorbis_write_real (NULL, 0); /* signal end of file */
-
-    while (ogg_stream_flush (& os, & og))
-    {
-        write_output (og.header, og.header_len);
-        write_output (og.body, og.body_len);
-    }
-
-    ogg_stream_clear(&os);
-
-    vorbis_block_clear(&vb);
-    vorbis_dsp_clear(&vd);
-    vorbis_info_clear(&vi);
-}
-
-/* configuration stuff */
-static GtkWidget *configure_win = NULL;
-static GtkWidget *quality_frame, *quality_vbox, *quality_hbox1, *quality_spin, *quality_label;
-static GtkAdjustment * quality_adj;
-
-static void quality_change(GtkAdjustment *adjustment, gpointer user_data)
-{
-    v_base_quality = gtk_spin_button_get_value ((GtkSpinButton *) quality_spin) / 10;
-    aud_set_double ("filewriter_vorbis", "base_quality", v_base_quality);
-}
-
-static void vorbis_configure(void)
-{
-    if (! configure_win)
-    {
-        configure_win = gtk_dialog_new_with_buttons
-         (_("Vorbis Encoder Configuration"), NULL, 0, _("_Close"),
-         GTK_RESPONSE_CLOSE, NULL);
-
-        g_signal_connect (configure_win, "response", (GCallback) gtk_widget_destroy, NULL);
-        g_signal_connect (configure_win, "destroy", (GCallback)
-         gtk_widget_destroyed, & configure_win);
-
-        GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) configure_win);
-
-        /* 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);
-
-        quality_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 10);
-        gtk_container_add(GTK_CONTAINER(quality_frame), quality_vbox);
-
-        /* quality option: vbr level */
-        quality_hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
-        gtk_container_set_border_width(GTK_CONTAINER(quality_hbox1), 10);
-        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);
-
-        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);
-        g_signal_connect(G_OBJECT(quality_adj), "value-changed", G_CALLBACK(quality_change), NULL);
-
-        gtk_spin_button_set_value(GTK_SPIN_BUTTON(quality_spin), (v_base_quality * 10));
-    }
-
-    gtk_widget_show_all(configure_win);
-}
-
-static int vorbis_format_required (int fmt)
-{
-    return FMT_FLOAT;
-}
-
-FileWriter vorbis_plugin =
-{
-    .init = vorbis_init,
-    .configure = vorbis_configure,
-    .open = vorbis_open,
-    .write = vorbis_write,
-    .close = vorbis_close,
-    .format_required = vorbis_format_required,
-};
-
-#endif
diff --git a/src/filewriter/vorbis.cc b/src/filewriter/vorbis.cc
new file mode 100644
index 000000000000..c97ac3d445b1
--- /dev/null
+++ b/src/filewriter/vorbis.cc
@@ -0,0 +1,248 @@
+/*  FileWriter Vorbis Plugin
+ *  Copyright (c) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
+ *
+ *  Partially derived from Og(g)re - Ogg-Output-Plugin:
+ *  Copyright (c) 2002 Lars Siebold <khandha5 at gmx.net>
+ *
+ *  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.
+ */
+
+#include "plugins.h"
+
+#ifdef FILEWRITER_VORBIS
+
+#include <stdlib.h>
+#include <vorbis/vorbisenc.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+
+static ogg_stream_state os;
+static ogg_page og;
+static ogg_packet op;
+
+static vorbis_dsp_state vd;
+static vorbis_block vb;
+static vorbis_info vi;
+static vorbis_comment vc;
+
+static const char * const vorbis_defaults[] = {
+ "base_quality", "0.5",
+ nullptr};
+
+static double v_base_quality;
+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,
+ const Tuple & tuple, Tuple::Field field)
+{
+    String val = tuple.get_str (field);
+    if (val)
+        vorbis_comment_add_tag (vc, name, val);
+}
+
+static bool vorbis_open (VFSFile & file, const format_info & info, const Tuple & tuple)
+{
+    ogg_packet header;
+    ogg_packet header_comm;
+    ogg_packet header_code;
+
+    vorbis_init();
+
+    vorbis_info_init(&vi);
+    vorbis_comment_init(&vc);
+
+    int scrint;
+
+    add_string_from_tuple (& vc, "title", tuple, Tuple::Title);
+    add_string_from_tuple (& vc, "artist", tuple, Tuple::Artist);
+    add_string_from_tuple (& vc, "album", tuple, Tuple::Album);
+    add_string_from_tuple (& vc, "genre", tuple, Tuple::Genre);
+    add_string_from_tuple (& vc, "date", tuple, Tuple::Date);
+    add_string_from_tuple (& vc, "comment", tuple, Tuple::Comment);
+
+    if ((scrint = tuple.get_int (Tuple::Track)) > 0)
+        vorbis_comment_add_tag(&vc, "tracknumber", int_to_str (scrint));
+
+    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))
+    {
+        vorbis_info_clear(&vi);
+        return false;
+    }
+
+    vorbis_analysis_init(&vd, &vi);
+    vorbis_block_init(&vd, &vb);
+
+    ogg_stream_init(&os, rand());
+
+    vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);
+
+    ogg_stream_packetin(&os, &header);
+    ogg_stream_packetin(&os, &header_comm);
+    ogg_stream_packetin(&os, &header_code);
+
+    while (ogg_stream_flush (& os, & og))
+    {
+        if (file.fwrite (og.header, 1, og.header_len) != og.header_len ||
+         file.fwrite (og.body, 1, og.body_len) != og.body_len)
+            AUDERR ("write error\n");
+    }
+
+    channels = info.channels;
+    return true;
+}
+
+static void vorbis_write_real (VFSFile & file, const void * data, int length)
+{
+    int samples = length / sizeof (float);
+    int channel;
+    float * end = (float *) data + samples;
+    float * * buffer = vorbis_analysis_buffer (& vd, samples / channels);
+    float * from, * to;
+
+    for (channel = 0; channel < channels; channel ++)
+    {
+        to = buffer[channel];
+
+        for (from = (float *) data + channel; from < end; from += channels)
+            * to ++ = * from;
+    }
+
+    vorbis_analysis_wrote (& vd, samples / channels);
+
+    while(vorbis_analysis_blockout(&vd, &vb) == 1)
+    {
+        vorbis_analysis(&vb, &op);
+        vorbis_bitrate_addblock(&vb);
+
+        while (vorbis_bitrate_flushpacket(&vd, &op))
+        {
+            ogg_stream_packetin(&os, &op);
+
+            while (ogg_stream_pageout(&os, &og))
+            {
+                if (file.fwrite (og.header, 1, og.header_len) != og.header_len ||
+                 file.fwrite (og.body, 1, og.body_len) != og.body_len)
+                    AUDERR ("write error\n");
+            }
+        }
+    }
+}
+
+static void vorbis_write (VFSFile & file, const void * data, int length)
+{
+    if (length > 0) /* don't signal end of file yet */
+        vorbis_write_real (file, data, length);
+}
+
+static void vorbis_close (VFSFile & file)
+{
+    vorbis_write_real (file, nullptr, 0); /* signal end of file */
+
+    while (ogg_stream_flush (& os, & og))
+    {
+        if (file.fwrite (og.header, 1, og.header_len) != og.header_len ||
+         file.fwrite (og.body, 1, og.body_len) != og.body_len)
+            AUDERR ("write error\n");
+    }
+
+    ogg_stream_clear(&os);
+
+    vorbis_block_clear(&vb);
+    vorbis_dsp_clear(&vd);
+    vorbis_info_clear(&vi);
+}
+
+/* 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);
+}
+
+static void vorbis_configure(void)
+{
+    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);
+
+        /* 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);
+
+        quality_vbox = gtk_vbox_new (FALSE, 5);
+        gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 10);
+        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);
+        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);
+
+        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);
+        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_widget_show_all(configure_win);
+}
+
+static int vorbis_format_required (int fmt)
+{
+    return FMT_FLOAT;
+}
+
+FileWriterImpl vorbis_plugin = {
+    vorbis_init,
+    vorbis_configure,
+    vorbis_open,
+    vorbis_write,
+    vorbis_close,
+    vorbis_format_required,
+};
+
+#endif
diff --git a/src/filewriter/wav.c b/src/filewriter/wav.c
deleted file mode 100644
index fe51fc52bc06..000000000000
--- a/src/filewriter/wav.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*  FileWriter-Plugin
- *  (C) copyright 2012 Michał Lipski
- *  (C) copyright 2007 merging of Disk Writer and Out-Lame by Michael Färber
- *
- *  Original Out-Lame-Plugin:
- *  (C) copyright 2002 Lars Siebold <khandha5 at gmx.net>
- *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
- */
-
-#include "plugins.h"
-
-#pragma pack(push) /* must be byte-aligned */
-#pragma pack(1)
-struct wavhead
-{
-    guint32 main_chunk;
-    guint32 length;
-    guint32 chunk_type;
-    guint32 sub_chunk;
-    guint32 sc_len;
-    guint16 format;
-    guint16 modus;
-    guint32 sample_fq;
-    guint32 byte_p_sec;
-    guint16 byte_p_spl;
-    guint16 bit_p_spl;
-    guint32 data_chunk;
-    guint32 data_length;
-};
-#pragma pack(pop)
-
-static struct wavhead header;
-
-static guint64 written;
-
-static gint wav_open(void)
-{
-    memcpy(&header.main_chunk, "RIFF", 4);
-    header.length = GUINT32_TO_LE(0);
-    memcpy(&header.chunk_type, "WAVE", 4);
-    memcpy(&header.sub_chunk, "fmt ", 4);
-    header.sc_len = GUINT32_TO_LE(16);
-    if (input.format == FMT_FLOAT)
-        header.format = GUINT16_TO_LE(3);
-    else
-        header.format = GUINT16_TO_LE(1);
-    header.modus = GUINT16_TO_LE(input.channels);
-    header.sample_fq = GUINT32_TO_LE(input.frequency);
-    if (input.format == FMT_S16_LE)
-        header.bit_p_spl = GUINT16_TO_LE(16);
-    else if (input.format == FMT_S24_LE)
-        header.bit_p_spl = GUINT16_TO_LE(24);
-    else
-        header.bit_p_spl = GUINT16_TO_LE(32);
-    header.byte_p_sec = GUINT32_TO_LE(input.frequency * header.modus * (GUINT16_FROM_LE(header.bit_p_spl) / 8));
-    header.byte_p_spl = GUINT16_TO_LE((GUINT16_FROM_LE(header.bit_p_spl) / (8 / input.channels)));
-    memcpy(&header.data_chunk, "data", 4);
-    header.data_length = GUINT32_TO_LE(0);
-
-    if (vfs_fwrite (& header, 1, sizeof header, output_file) != sizeof header)
-        return 0;
-
-    written = 0;
-
-    return 1;
-}
-
-static void pack24 (void * * data, int * len)
-{
-    int samples = (* len) / sizeof (int32_t);
-    char * new = g_malloc (samples * 3);
-    int32_t * data32 = * data;
-    int32_t * end = data32 + samples;
-
-    * data = new;
-    * len = samples * 3;
-
-    while (data32 < end)
-    {
-        memcpy (new, data32 ++, 3);
-        new += 3;
-    }
-}
-
-static void wav_write (void * data, gint len)
-{
-    if (input.format == FMT_S24_LE)
-        pack24 (& data, & len);
-
-    written += len;
-    if (vfs_fwrite (data, 1, len, output_file) != len)
-        fprintf (stderr, "Error while writing to .wav output file.\n");
-
-    if (input.format == FMT_S24_LE)
-        g_free (data);
-}
-
-static void wav_close(void)
-{
-    if (output_file)
-    {
-        header.length = GUINT32_TO_LE(written + sizeof (struct wavhead) - 8);
-        header.data_length = GUINT32_TO_LE(written);
-
-        if (vfs_fseek (output_file, 0, SEEK_SET) || vfs_fwrite (& header, 1,
-         sizeof header, output_file) != sizeof header)
-            fprintf (stderr, "Error while writing to .wav output file.\n");
-    }
-}
-
-static int wav_format_required (int fmt)
-{
-    switch (fmt)
-    {
-        case FMT_S16_LE:
-        case FMT_S24_LE:
-        case FMT_S32_LE:
-        case FMT_FLOAT:
-            return fmt;
-        default:
-            return FMT_S16_LE;
-    }
-}
-
-FileWriter wav_plugin =
-{
-    .init = NULL,
-    .configure = NULL,
-    .open = wav_open,
-    .write = wav_write,
-    .close = wav_close,
-    .format_required = wav_format_required,
-};
diff --git a/src/filewriter/wav.cc b/src/filewriter/wav.cc
new file mode 100644
index 000000000000..ab914fdc159c
--- /dev/null
+++ b/src/filewriter/wav.cc
@@ -0,0 +1,152 @@
+/*  FileWriter-Plugin
+ *  (C) copyright 2012 Michał Lipski
+ *  (C) copyright 2007 merging of Disk Writer and Out-Lame by Michael Färber
+ *
+ *  Original Out-Lame-Plugin:
+ *  (C) copyright 2002 Lars Siebold <khandha5 at gmx.net>
+ *  (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz at 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.
+ */
+
+#include "plugins.h"
+
+#include <string.h>
+#include <libaudcore/runtime.h>
+
+#pragma pack(push) /* must be byte-aligned */
+#pragma pack(1)
+struct wavhead
+{
+    uint32_t main_chunk;
+    uint32_t length;
+    uint32_t chunk_type;
+    uint32_t sub_chunk;
+    uint32_t sc_len;
+    uint16_t format;
+    uint16_t modus;
+    uint32_t sample_fq;
+    uint32_t byte_p_sec;
+    uint16_t byte_p_spl;
+    uint16_t bit_p_spl;
+    uint32_t data_chunk;
+    uint32_t data_length;
+};
+#pragma pack(pop)
+
+static struct wavhead header;
+
+static int format;
+static Index<char> packbuf;
+
+static uint64_t written;
+
+
+static bool wav_open (VFSFile & file, const format_info & info, const Tuple &)
+{
+    memcpy(&header.main_chunk, "RIFF", 4);
+    header.length = TO_LE32(0);
+    memcpy(&header.chunk_type, "WAVE", 4);
+    memcpy(&header.sub_chunk, "fmt ", 4);
+    header.sc_len = TO_LE32(16);
+    if (info.format == FMT_FLOAT)
+        header.format = TO_LE16(3);
+    else
+        header.format = TO_LE16(1);
+    header.modus = TO_LE16(info.channels);
+    header.sample_fq = TO_LE32(info.frequency);
+    if (info.format == FMT_S16_LE)
+        header.bit_p_spl = TO_LE16(16);
+    else if (info.format == FMT_S24_LE)
+        header.bit_p_spl = TO_LE16(24);
+    else
+        header.bit_p_spl = TO_LE16(32);
+    header.byte_p_sec = TO_LE32(info.frequency * header.modus * (FROM_LE16(header.bit_p_spl) / 8));
+    header.byte_p_spl = TO_LE16((FROM_LE16(header.bit_p_spl) / (8 / info.channels)));
+    memcpy(&header.data_chunk, "data", 4);
+    header.data_length = TO_LE32(0);
+
+    if (file.fwrite (& header, 1, sizeof header) != sizeof header)
+        return false;
+
+    format = info.format;
+    written = 0;
+
+    return true;
+}
+
+static void pack24 (const void * * data, int * len)
+{
+    int samples = (* len) / sizeof (int32_t);
+    auto data32 = (const int32_t *) * data;
+    auto end = data32 + samples;
+
+    packbuf.resize (samples * 3);
+    char * buf = packbuf.begin ();
+
+    * data = buf;
+    * len = samples * 3;
+
+    while (data32 < end)
+    {
+        memcpy (buf, data32 ++, 3);
+        buf += 3;
+    }
+}
+
+static void wav_write (VFSFile & file, const void * data, int len)
+{
+    if (format == FMT_S24_LE)
+        pack24 (& data, & len);
+
+    written += len;
+    if (file.fwrite (data, 1, len) != len)
+        AUDERR ("Error while writing to .wav output file.\n");
+}
+
+static void wav_close (VFSFile & file)
+{
+    header.length = TO_LE32(written + sizeof (struct wavhead) - 8);
+    header.data_length = TO_LE32(written);
+
+    if (file.fseek (0, VFS_SEEK_SET) ||
+     file.fwrite (& header, 1, sizeof header) != sizeof header)
+        AUDERR ("Error while writing to .wav output file.\n");
+
+    packbuf.clear ();
+}
+
+static int wav_format_required (int fmt)
+{
+    switch (fmt)
+    {
+        case FMT_S16_LE:
+        case FMT_S24_LE:
+        case FMT_S32_LE:
+        case FMT_FLOAT:
+            return fmt;
+        default:
+            return FMT_S16_LE;
+    }
+}
+
+FileWriterImpl wav_plugin = {
+    nullptr,  // init
+    nullptr,  // configure
+    wav_open,
+    wav_write,
+    wav_close,
+    wav_format_required,
+};
diff --git a/src/flacng/Makefile b/src/flacng/Makefile
index b47566644396..fb53a2bb2bb6 100644
--- a/src/flacng/Makefile
+++ b/src/flacng/Makefile
@@ -1,15 +1,17 @@
 PLUGIN = flacng${PLUGIN_SUFFIX}
 
-SRCS = plugin.c \
-       tools.c \
-       seekable_stream_callbacks.c	\
-       metadata.c
+SRCS = plugin.cc \
+       tools.cc \
+       seekable_stream_callbacks.cc	\
+       metadata.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${LIBFLAC_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${LIBFLAC_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${LIBFLAC_CFLAGS} -I../..
+LIBS += ${LIBFLAC_LIBS}
diff --git a/src/flacng/flacng.h b/src/flacng/flacng.h
index 955eefeb6573..1f1d9aa987cb 100644
--- a/src/flacng/flacng.h
+++ b/src/flacng/flacng.h
@@ -22,13 +22,36 @@
 
 #include <FLAC/all.h>
 
-#include <libaudcore/audio.h>
-#include <libaudcore/tuple.h>
-#include <libaudcore/vfs.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
 
-#define FLACNG_ERROR(...) do { \
-    printf("flacng: " __VA_ARGS__); \
-} while (0)
+class FLACng : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char *const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("FLAC Decoder"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo(FlagWritesTag)
+        .with_priority(1)
+        .with_exts(exts);
+
+    constexpr FLACng() : InputPlugin(info, iinfo) {}
+
+    bool init();
+    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 write_tuple(const char *filename, VFSFile &file, const Tuple &tuple);
+    bool play(const char *filename, VFSFile &file);
+};
 
 #define BUFFER_SIZE_SAMP (FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS)
 #define BUFFER_SIZE_BYTE (BUFFER_SIZE_SAMP * (FLAC__MAX_BITS_PER_SAMPLE/8))
@@ -36,22 +59,35 @@
 #define SAMPLE_SIZE(a) (a == 8 ? 1 : (a == 16 ? 2 : 4))
 #define SAMPLE_FMT(a) (a == 8 ? FMT_S8 : (a == 16 ? FMT_S16_NE : (a == 24 ? FMT_S24_NE : FMT_S32_NE)))
 
-typedef struct callback_info {
-    unsigned bits_per_sample;
-    unsigned sample_rate;
-    unsigned channels;
-    unsigned long total_samples;
-    int32_t* output_buffer;
-    int32_t* write_pointer;
-    unsigned buffer_used;
-    VFSFile* fd;
-    int bitrate;
-} callback_info;
+struct callback_info
+{
+    unsigned bits_per_sample = 0;
+    unsigned sample_rate = 0;
+    unsigned channels = 0;
+    unsigned long total_samples = 0;
+    Index<int32_t> output_buffer;
+    int32_t *write_pointer = nullptr;
+    unsigned buffer_used = 0;
+    VFSFile *fd = nullptr;
+    int bitrate = 0;
+
+    void alloc()
+    {
+        output_buffer.resize(BUFFER_SIZE_SAMP);
+        reset();
+    }
+
+    void reset()
+    {
+        buffer_used = 0;
+        write_pointer = output_buffer.begin();
+    }
+};
 
 /* metadata.c */
-bool_t flac_update_song_tuple(const char *filename, VFSFile *fd, const Tuple *tuple);
-bool_t flac_get_image(const char *filename, VFSFile *fd, void **data, int64_t *length);
-Tuple *flac_probe_for_tuple(const char *filename, VFSFile *fd);
+bool flac_update_song_tuple(const char *filename, VFSFile &fd, const Tuple &tuple);
+Index<char> flac_get_image(const char *filename, VFSFile &fd);
+Tuple flac_probe_for_tuple(const char *filename, VFSFile &fd);
 
 /* seekable_stream_callbacks.c */
 FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
@@ -64,9 +100,6 @@ void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderError
 void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
 
 /* tools.c */
-callback_info* init_callback_info(void);
-void clean_callback_info(callback_info* info);
-void reset_info(callback_info* info);
-bool_t read_metadata(FLAC__StreamDecoder* decoder, callback_info* info);
+bool read_metadata(FLAC__StreamDecoder* decoder, callback_info* info);
 
 #endif
diff --git a/src/flacng/metadata.c b/src/flacng/metadata.c
deleted file mode 100644
index d1dd23c2ca18..000000000000
--- a/src/flacng/metadata.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * A FLAC decoder plugin for the Audacious Media Player
- * Copyright (C) 2005 Ralf Ertzinger
- * Copyright (C) 2010 John Lindgren
- * Copyright (C) 2010 Michał Lipski <tallica at o2.pl>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <libaudcore/audstrings.h>
-
-#include "flacng.h"
-
-static size_t read_cb(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
-{
-    size_t read;
-
-    if (handle == NULL)
-    {
-        FLACNG_ERROR("Trying to read data from an uninitialized file!\n");
-        return -1;
-    }
-
-    read = vfs_fread(ptr, size, nmemb, handle);
-
-    switch (read)
-    {
-        case -1:
-            FLACNG_ERROR("Error while reading from stream!\n");
-            return -1;
-
-        case 0:
-            AUDDBG("Stream reached EOF\n");
-            return 0;
-
-        default:
-            return read;
-    }
-}
-
-static size_t write_cb(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
-{
-    return vfs_fwrite(ptr, size, nmemb, handle);
-}
-
-static int seek_cb(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
-{
-    if (vfs_fseek(handle, offset, whence) != 0)
-    {
-        FLACNG_ERROR("Could not seek to %ld!\n", (long)offset);
-        return -1;
-    }
-
-    return 0;
-}
-
-static FLAC__int64 tell_cb(FLAC__IOHandle handle)
-{
-    uint64_t offset;
-
-    if ((offset = vfs_ftell(handle)) == -1)
-    {
-        FLACNG_ERROR("Could not tell current position!\n");
-        return -1;
-    }
-
-    AUDDBG ("Current position: %d\n", (int) offset);
-    return offset;
-}
-
-static int eof_cb(FLAC__IOHandle handle)
-{
-    return vfs_feof(handle);
-}
-
-static FLAC__IOCallbacks io_callbacks = {
-    read_cb,
-    write_cb,
-    seek_cb,
-    tell_cb,
-    eof_cb,
-    NULL
-};
-
-static void insert_str_tuple_to_vc (FLAC__StreamMetadata * vc_block,
- const Tuple * tuple, int tuple_name, char * field_name)
-{
-    FLAC__StreamMetadata_VorbisComment_Entry entry;
-    char *val = tuple_get_str(tuple, tuple_name);
-
-    if (val == NULL)
-        return;
-
-    SPRINTF (str, "%s=%s", field_name, val);
-    entry.entry = (FLAC__byte *) str;
-    entry.length = strlen(str);
-    FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,
-        vc_block->data.vorbis_comment.num_comments, entry, true);
-    str_unref(val);
-}
-
-static void insert_int_tuple_to_vc (FLAC__StreamMetadata * vc_block,
- const Tuple * tuple, int tuple_name, char * field_name)
-{
-    FLAC__StreamMetadata_VorbisComment_Entry entry;
-    int val = tuple_get_int(tuple, tuple_name);
-
-    if (val <= 0)
-        return;
-
-    SPRINTF (str, "%s=%d", field_name, val);
-    entry.entry = (FLAC__byte *) str;
-    entry.length = strlen(str);
-    FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,
-        vc_block->data.vorbis_comment.num_comments, entry, true);
-}
-
-bool_t flac_update_song_tuple(const char *filename, VFSFile *fd, const Tuple *tuple)
-{
-    AUDDBG("Update song tuple.\n");
-
-    FLAC__Metadata_Iterator *iter;
-    FLAC__Metadata_Chain *chain;
-    FLAC__StreamMetadata *vc_block;
-    FLAC__Metadata_ChainStatus status;
-
-    chain = FLAC__metadata_chain_new();
-
-    if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks))
-        goto ERR;
-
-    iter = FLAC__metadata_iterator_new();
-
-    FLAC__metadata_iterator_init(iter, chain);
-
-    while (FLAC__metadata_iterator_next(iter))
-        if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
-        {
-            FLAC__metadata_iterator_delete_block(iter, true);
-            break;
-        }
-
-    vc_block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
-
-    insert_str_tuple_to_vc(vc_block, tuple, FIELD_TITLE, "TITLE");
-    insert_str_tuple_to_vc(vc_block, tuple, FIELD_ARTIST, "ARTIST");
-    insert_str_tuple_to_vc(vc_block, tuple, FIELD_ALBUM, "ALBUM");
-    insert_str_tuple_to_vc(vc_block, tuple, FIELD_GENRE, "GENRE");
-    insert_str_tuple_to_vc(vc_block, tuple, FIELD_COMMENT, "COMMENT");
-
-    insert_int_tuple_to_vc(vc_block, tuple, FIELD_YEAR, "DATE");
-    insert_int_tuple_to_vc(vc_block, tuple, FIELD_TRACK_NUMBER, "TRACKNUMBER");
-
-    FLAC__metadata_iterator_insert_block_after(iter, vc_block);
-
-    FLAC__metadata_iterator_delete(iter);
-    FLAC__metadata_chain_sort_padding(chain);
-
-    if (!FLAC__metadata_chain_write_with_callbacks(chain, TRUE, fd, io_callbacks))
-        goto ERR;
-
-    FLAC__metadata_chain_delete(chain);
-    return TRUE;
-
-ERR:
-    status = FLAC__metadata_chain_status(chain);
-    FLAC__metadata_chain_delete(chain);
-
-    FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
-    return FALSE;
-}
-
-bool_t flac_get_image(const char *filename, VFSFile *fd, void **data, int64_t *length)
-{
-    AUDDBG("Probe for song image.\n");
-
-    FLAC__Metadata_Iterator *iter;
-    FLAC__Metadata_Chain *chain;
-    FLAC__StreamMetadata *metadata = NULL;
-    FLAC__Metadata_ChainStatus status;
-    bool_t has_image = FALSE;
-
-    chain = FLAC__metadata_chain_new();
-
-    if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks))
-        goto ERR;
-
-    iter = FLAC__metadata_iterator_new();
-
-    FLAC__metadata_iterator_init(iter, chain);
-
-    while (FLAC__metadata_iterator_next(iter))
-        if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_PICTURE)
-            break;
-
-    if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_PICTURE)
-    {
-        metadata = FLAC__metadata_iterator_get_block(iter);
-
-        if (metadata->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
-        {
-            AUDDBG("FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER found.");
-
-            * data = g_malloc (metadata->data.picture.data_length);
-            * length = metadata->data.picture.data_length;
-            memcpy (* data, metadata->data.picture.data, * length);
-            has_image = TRUE;
-        }
-    }
-
-    FLAC__metadata_iterator_delete(iter);
-    FLAC__metadata_chain_delete(chain);
-
-    return has_image;
-
-ERR:
-    status = FLAC__metadata_chain_status(chain);
-    FLAC__metadata_chain_delete(chain);
-
-    FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
-    return FALSE;
-}
-
-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, int field, int unit_field, const char *text)
-{
-    int value, unit;
-
-    parse_gain_text(text, &value, &unit);
-
-    if (tuple_get_value_type(tuple, unit_field) == TUPLE_INT)
-        value = value * (int64_t) tuple_get_int(tuple, unit_field) / unit;
-    else
-        tuple_set_int(tuple, unit_field, unit);
-
-    tuple_set_int(tuple, field, value);
-}
-
-static void add_text (Tuple * tuple, int field, const char * value)
-{
-    char * cur = tuple_get_str (tuple, field);
-    if (cur)
-    {
-        SPRINTF (both, "%s, %s", cur, value);
-        tuple_set_str (tuple, field, both);
-    }
-    else
-        tuple_set_str (tuple, field, value);
-
-    str_unref(cur);
-}
-
-static void parse_comment (Tuple * tuple, const char * key, const char * value)
-{
-    AUDDBG ("Found key %s <%s>\n", key, value);
-
-    const struct {
-        const char * key;
-        int field;
-    } tfields[] = {
-     {"ARTIST", FIELD_ARTIST},
-     {"ALBUM", FIELD_ALBUM},
-     {"TITLE", FIELD_TITLE},
-     {"COMMENT", FIELD_COMMENT},
-     {"GENRE", FIELD_GENRE}};
-
-    for (int i = 0; i < ARRAY_LEN (tfields); i ++)
-    {
-        if (! g_ascii_strcasecmp (key, tfields[i].key))
-        {
-            add_text (tuple, tfields[i].field, value);
-            return;
-        }
-    }
-
-    if (! g_ascii_strcasecmp (key, "TRACKNUMBER"))
-        tuple_set_int(tuple, FIELD_TRACK_NUMBER, atoi(value));
-    else if (! g_ascii_strcasecmp (key, "DATE"))
-        tuple_set_int(tuple, FIELD_YEAR, atoi(value));
-    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_TRACK_GAIN"))
-        set_gain_info(tuple, FIELD_GAIN_TRACK_GAIN, FIELD_GAIN_GAIN_UNIT, value);
-    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_TRACK_PEAK"))
-        set_gain_info(tuple, FIELD_GAIN_TRACK_PEAK, FIELD_GAIN_PEAK_UNIT, value);
-    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_ALBUM_GAIN"))
-        set_gain_info(tuple, FIELD_GAIN_ALBUM_GAIN, FIELD_GAIN_GAIN_UNIT, value);
-    else if (! g_ascii_strcasecmp (key, "REPLAYGAIN_ALBUM_PEAK"))
-        set_gain_info(tuple, FIELD_GAIN_ALBUM_PEAK, FIELD_GAIN_PEAK_UNIT, value);
-}
-
-Tuple *flac_probe_for_tuple(const char *filename, VFSFile *fd)
-{
-    AUDDBG("Probe for tuple.\n");
-
-    Tuple *tuple = NULL;
-    FLAC__Metadata_Iterator *iter;
-    FLAC__Metadata_Chain *chain;
-    FLAC__StreamMetadata *metadata = NULL;
-    FLAC__Metadata_ChainStatus status;
-    FLAC__StreamMetadata_VorbisComment_Entry *entry;
-    char *key;
-    char *value;
-
-    tuple = tuple_new_from_filename(filename);
-
-    tuple_set_str(tuple, FIELD_CODEC, "Free Lossless Audio Codec (FLAC)");
-    tuple_set_str(tuple, FIELD_QUALITY, _("lossless"));
-
-    chain = FLAC__metadata_chain_new();
-
-    if (!FLAC__metadata_chain_read_with_callbacks(chain, fd, io_callbacks))
-        goto ERR;
-
-    iter = FLAC__metadata_iterator_new();
-
-    FLAC__metadata_iterator_init(iter, chain);
-
-    do
-    {
-        switch (FLAC__metadata_iterator_get_block_type(iter))
-        {
-            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
-
-                if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
-                {
-                    metadata = FLAC__metadata_iterator_get_block(iter);
-
-                    AUDDBG("Vorbis comment contains %d fields\n", metadata->data.vorbis_comment.num_comments);
-                    AUDDBG("Vendor string: %s\n", metadata->data.vorbis_comment.vendor_string.entry);
-
-                    entry = metadata->data.vorbis_comment.comments;
-
-                    for (int i = 0; i < metadata->data.vorbis_comment.num_comments; i++, entry++)
-                    {
-                        if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false)
-                            AUDDBG("Could not parse comment\n");
-                        else
-                        {
-                            parse_comment(tuple, key, value);
-                            g_free(key);
-                            g_free(value);
-                        }
-                    }
-                }
-                break;
-
-            case FLAC__METADATA_TYPE_STREAMINFO:
-                metadata = FLAC__metadata_iterator_get_block(iter);
-
-                /* Calculate the stream length (milliseconds) */
-                if (metadata->data.stream_info.sample_rate == 0)
-                {
-                    FLACNG_ERROR("Invalid sample rate for stream!\n");
-                    tuple_set_int(tuple, FIELD_LENGTH, -1);
-                }
-                else
-                {
-                    tuple_set_int(tuple, FIELD_LENGTH,
-                        (metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate) * 1000);
-                    AUDDBG("Stream length: %d seconds\n", tuple_get_int(tuple, FIELD_LENGTH));
-                }
-
-                int64_t size = vfs_fsize(fd);
-
-                if (size == -1 || metadata->data.stream_info.total_samples == 0)
-                    tuple_set_int(tuple, FIELD_BITRATE, 0);
-                else
-                {
-                    int bitrate = 8 * size *
-                        (int64_t) metadata->data.stream_info.sample_rate / metadata->data.stream_info.total_samples;
-
-                    tuple_set_int(tuple, FIELD_BITRATE, (bitrate + 500) / 1000);
-                }
-                break;
-
-            default:
-                ;
-        }
-    } while (FLAC__metadata_iterator_next(iter));
-
-    FLAC__metadata_iterator_delete(iter);
-    FLAC__metadata_chain_delete(chain);
-
-    return tuple;
-
-ERR:
-    status = FLAC__metadata_chain_status(chain);
-    FLAC__metadata_chain_delete(chain);
-
-    FLACNG_ERROR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
-    return tuple;
-}
diff --git a/src/flacng/metadata.cc b/src/flacng/metadata.cc
new file mode 100644
index 000000000000..837f844ba6f7
--- /dev/null
+++ b/src/flacng/metadata.cc
@@ -0,0 +1,438 @@
+/*
+ * A FLAC decoder plugin for the Audacious Media Player
+ * Copyright (C) 2005 Ralf Ertzinger
+ * Copyright (C) 2010 John Lindgren
+ * Copyright (C) 2010 Michał Lipski <tallica at o2.pl>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WANT_VFS_STDIO_COMPAT
+#include <libaudcore/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/audstrings.h>
+
+#include "flacng.h"
+
+static size_t read_cb(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
+{
+    int64_t read;
+
+    if (handle == nullptr)
+    {
+        AUDERR("Trying to read data from an uninitialized file!\n");
+        return -1;
+    }
+
+    read = ((VFSFile *) handle)->fread (ptr, size, nmemb);
+
+    switch (read)
+    {
+        case -1:
+            AUDERR("Error while reading from stream!\n");
+            return -1;
+
+        case 0:
+            AUDDBG("Stream reached EOF\n");
+            return 0;
+
+        default:
+            return read;
+    }
+}
+
+static size_t write_cb(const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
+{
+    return ((VFSFile *) handle)->fwrite (ptr, size, nmemb);
+}
+
+static int seek_cb(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
+{
+    if (((VFSFile *) handle)->fseek (offset, to_vfs_seek_type (whence)) != 0)
+    {
+        AUDERR("Could not seek to %ld!\n", (long)offset);
+        return -1;
+    }
+
+    return 0;
+}
+
+static FLAC__int64 tell_cb(FLAC__IOHandle handle)
+{
+    int64_t offset;
+
+    if ((offset = ((VFSFile *) handle)->ftell ()) < 0)
+    {
+        AUDERR("Could not tell current position!\n");
+        return -1;
+    }
+
+    AUDDBG ("Current position: %d\n", (int) offset);
+    return offset;
+}
+
+static int eof_cb(FLAC__IOHandle handle)
+{
+    return ((VFSFile *) handle)->feof ();
+}
+
+static FLAC__IOCallbacks io_callbacks = {
+    read_cb,
+    write_cb,
+    seek_cb,
+    tell_cb,
+    eof_cb,
+    nullptr
+};
+
+static void insert_str_tuple_to_vc (FLAC__StreamMetadata * vc_block,
+ const Tuple & tuple, Tuple::Field field, const char * field_name)
+{
+    FLAC__StreamMetadata_VorbisComment_Entry entry;
+    String val = tuple.get_str (field);
+
+    if (! val)
+        return;
+
+    StringBuf str = str_printf ("%s=%s", field_name, (const char *) val);
+    entry.entry = (FLAC__byte *) (char *) str;
+    entry.length = strlen(str);
+    FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,
+        vc_block->data.vorbis_comment.num_comments, entry, true);
+}
+
+static void insert_int_tuple_to_vc (FLAC__StreamMetadata * vc_block,
+ const Tuple & tuple, Tuple::Field field, const char * field_name)
+{
+    FLAC__StreamMetadata_VorbisComment_Entry entry;
+    int val = tuple.get_int (field);
+
+    if (val <= 0)
+        return;
+
+    StringBuf str = str_printf ("%s=%d", field_name, val);
+    entry.entry = (FLAC__byte *) (char *) str;
+    entry.length = strlen(str);
+    FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,
+        vc_block->data.vorbis_comment.num_comments, entry, true);
+}
+
+bool FLACng::write_tuple(const char *filename, VFSFile &file, const Tuple &tuple)
+{
+    AUDDBG("Update song tuple.\n");
+
+    FLAC__Metadata_Iterator *iter;
+    FLAC__Metadata_Chain *chain;
+    FLAC__StreamMetadata *vc_block;
+    FLAC__Metadata_ChainStatus status;
+
+    chain = FLAC__metadata_chain_new();
+
+    if (!FLAC__metadata_chain_read_with_callbacks(chain, &file, io_callbacks))
+        goto ERR;
+
+    iter = FLAC__metadata_iterator_new();
+
+    FLAC__metadata_iterator_init(iter, chain);
+
+    while (FLAC__metadata_iterator_next(iter))
+        if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+        {
+            FLAC__metadata_iterator_delete_block(iter, true);
+            break;
+        }
+
+    vc_block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+    insert_str_tuple_to_vc(vc_block, tuple, Tuple::Title, "TITLE");
+    insert_str_tuple_to_vc(vc_block, tuple, Tuple::Artist, "ARTIST");
+    insert_str_tuple_to_vc(vc_block, tuple, Tuple::Album, "ALBUM");
+    insert_str_tuple_to_vc(vc_block, tuple, Tuple::Genre, "GENRE");
+    insert_str_tuple_to_vc(vc_block, tuple, Tuple::Comment, "COMMENT");
+
+    insert_int_tuple_to_vc(vc_block, tuple, Tuple::Year, "DATE");
+    insert_int_tuple_to_vc(vc_block, tuple, Tuple::Track, "TRACKNUMBER");
+
+    FLAC__metadata_iterator_insert_block_after(iter, vc_block);
+
+    FLAC__metadata_iterator_delete(iter);
+    FLAC__metadata_chain_sort_padding(chain);
+
+    if (!FLAC__metadata_chain_write_with_callbacks(chain, true, &file, io_callbacks))
+        goto ERR;
+
+    FLAC__metadata_chain_delete(chain);
+    return true;
+
+ERR:
+    status = FLAC__metadata_chain_status(chain);
+    FLAC__metadata_chain_delete(chain);
+
+    AUDERR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
+    return false;
+}
+
+Index<char> FLACng::read_image(const char *filename, VFSFile &file)
+{
+    AUDDBG("Probe for song image.\n");
+
+    FLAC__Metadata_Iterator *iter;
+    FLAC__Metadata_Chain *chain;
+    FLAC__StreamMetadata *metadata = nullptr;
+    FLAC__Metadata_ChainStatus status;
+
+    Index<char> data;
+
+    chain = FLAC__metadata_chain_new();
+
+    if (!FLAC__metadata_chain_read_with_callbacks(chain, &file, io_callbacks))
+        goto ERR;
+
+    iter = FLAC__metadata_iterator_new();
+
+    FLAC__metadata_iterator_init(iter, chain);
+
+    while (FLAC__metadata_iterator_next(iter))
+        if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_PICTURE)
+            break;
+
+    if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_PICTURE)
+    {
+        metadata = FLAC__metadata_iterator_get_block(iter);
+
+        if (metadata->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER)
+        {
+            AUDDBG("FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER found.");
+            data.insert ((const char *) metadata->data.picture.data, 0,
+             metadata->data.picture.data_length);
+        }
+    }
+
+    FLAC__metadata_iterator_delete(iter);
+    FLAC__metadata_chain_delete(chain);
+
+    return data;
+
+ERR:
+    status = FLAC__metadata_chain_status(chain);
+    FLAC__metadata_chain_delete(chain);
+
+    AUDERR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
+    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);
+    if (cur)
+        tuple.set_str (field, str_concat ({cur, ", ", value}));
+    else
+        tuple.set_str (field, value);
+}
+
+static void parse_comment (Tuple & tuple, const char * key, const char * value)
+{
+    AUDDBG ("Found key %s <%s>\n", key, value);
+
+    static const struct {
+        const char * key;
+        Tuple::Field field;
+    } tfields[] = {
+        {"ARTIST", Tuple::Artist},
+        {"ALBUM", Tuple::Album},
+        {"TITLE", Tuple::Title},
+        {"COMMENT", Tuple::Comment},
+        {"GENRE", Tuple::Genre}
+    };
+
+    for (auto & tfield : tfields)
+    {
+        if (!strcmp_nocase(key, tfield.key))
+        {
+            add_text (tuple, tfield.field, value);
+            return;
+        }
+    }
+
+    if (!strcmp_nocase(key, "TRACKNUMBER"))
+        tuple.set_int(Tuple::Track, atoi(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);
+    else if (!strcmp_nocase(key, "REPLAYGAIN_TRACK_PEAK"))
+        set_gain_info(tuple, Tuple::TrackPeak, Tuple::PeakDivisor, value);
+    else if (!strcmp_nocase(key, "REPLAYGAIN_ALBUM_GAIN"))
+        set_gain_info(tuple, Tuple::AlbumGain, Tuple::GainDivisor, value);
+    else if (!strcmp_nocase(key, "REPLAYGAIN_ALBUM_PEAK"))
+        set_gain_info(tuple, Tuple::AlbumPeak, Tuple::PeakDivisor, value);
+}
+
+Tuple FLACng::read_tuple(const char *filename, VFSFile &file)
+{
+    AUDDBG("Probe for tuple.\n");
+
+    Tuple tuple;
+    FLAC__Metadata_Iterator *iter;
+    FLAC__Metadata_Chain *chain;
+    FLAC__StreamMetadata *metadata = nullptr;
+    FLAC__Metadata_ChainStatus status;
+    FLAC__StreamMetadata_VorbisComment_Entry *entry;
+    char *key;
+    char *value;
+
+    tuple.set_filename (filename);
+
+    tuple.set_str (Tuple::Codec, "Free Lossless Audio Codec (FLAC)");
+    tuple.set_str (Tuple::Quality, _("lossless"));
+
+    chain = FLAC__metadata_chain_new();
+
+    if (!FLAC__metadata_chain_read_with_callbacks(chain, &file, io_callbacks))
+        goto ERR;
+
+    iter = FLAC__metadata_iterator_new();
+
+    FLAC__metadata_iterator_init(iter, chain);
+
+    do
+    {
+        switch (FLAC__metadata_iterator_get_block_type(iter))
+        {
+            case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+
+                if (FLAC__metadata_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+                {
+                    metadata = FLAC__metadata_iterator_get_block(iter);
+
+                    AUDDBG("Vorbis comment contains %d fields\n", metadata->data.vorbis_comment.num_comments);
+                    AUDDBG("Vendor string: %s\n", metadata->data.vorbis_comment.vendor_string.entry);
+
+                    entry = metadata->data.vorbis_comment.comments;
+
+                    for (unsigned i = 0; i < metadata->data.vorbis_comment.num_comments; i++, entry++)
+                    {
+                        if (FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(*entry, &key, &value) == false)
+                            AUDDBG("Could not parse comment\n");
+                        else
+                        {
+                            parse_comment(tuple, key, value);
+                            free(key);
+                            free(value);
+                        }
+                    }
+                }
+                break;
+
+            case FLAC__METADATA_TYPE_STREAMINFO:
+            {
+                metadata = FLAC__metadata_iterator_get_block(iter);
+
+                /* Calculate the stream length (milliseconds) */
+                if (metadata->data.stream_info.sample_rate == 0)
+                {
+                    AUDERR("Invalid sample rate for stream!\n");
+                    tuple.set_int (Tuple::Length, -1);
+                }
+                else
+                {
+                    tuple.set_int (Tuple::Length,
+                        (metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate) * 1000);
+                    AUDDBG("Stream length: %d seconds\n", tuple.get_int (Tuple::Length));
+                }
+
+                int64_t size = file.fsize ();
+
+                if (size < 0 || metadata->data.stream_info.total_samples == 0)
+                    tuple.set_int (Tuple::Bitrate, 0);
+                else
+                {
+                    int bitrate = 8 * size *
+                        (int64_t) metadata->data.stream_info.sample_rate / metadata->data.stream_info.total_samples;
+
+                    tuple.set_int (Tuple::Bitrate, (bitrate + 500) / 1000);
+                }
+                break;
+            }
+
+            default:
+                ;
+        }
+    } while (FLAC__metadata_iterator_next(iter));
+
+    FLAC__metadata_iterator_delete(iter);
+    FLAC__metadata_chain_delete(chain);
+
+    return tuple;
+
+ERR:
+    status = FLAC__metadata_chain_status(chain);
+    FLAC__metadata_chain_delete(chain);
+
+    AUDERR("An error occured: %s\n", FLAC__Metadata_ChainStatusString[status]);
+    return tuple;
+}
diff --git a/src/flacng/plugin.c b/src/flacng/plugin.c
deleted file mode 100644
index 8a4a928ef2c7..000000000000
--- a/src/flacng/plugin.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- *  A FLAC decoder plugin for the Audacious Media Player
- *  Copyright (C) 2005 Ralf Ertzinger
- *  Copyright (C) 2010-2012 Michał Lipski
- *
- *  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.
- */
-
-#include <string.h>
-#include <glib.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-
-#include "flacng.h"
-
-static FLAC__StreamDecoder *decoder;
-static callback_info *info;
-
-static bool_t flac_init (void)
-{
-    FLAC__StreamDecoderInitStatus ret;
-
-    /* Callback structure and decoder for main decoding loop */
-
-    if ((info = init_callback_info()) == NULL)
-    {
-        FLACNG_ERROR("Could not initialize the main callback structure!\n");
-        return FALSE;
-    }
-
-    if ((decoder = FLAC__stream_decoder_new()) == NULL)
-    {
-        FLACNG_ERROR("Could not create the main FLAC decoder instance!\n");
-        return FALSE;
-    }
-
-    if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream(
-        decoder,
-        read_callback,
-        seek_callback,
-        tell_callback,
-        length_callback,
-        eof_callback,
-        write_callback,
-        metadata_callback,
-        error_callback,
-        info)))
-    {
-        FLACNG_ERROR("Could not initialize the main FLAC decoder: %s(%d)\n",
-            FLAC__StreamDecoderInitStatusString[ret], ret);
-        return FALSE;
-    }
-
-    AUDDBG("Plugin initialized.\n");
-    return TRUE;
-}
-
-static void flac_cleanup(void)
-{
-    FLAC__stream_decoder_delete(decoder);
-    clean_callback_info(info);
-}
-
-bool_t flac_is_our_fd(const char *filename, VFSFile *fd)
-{
-    AUDDBG("Probe for FLAC.\n");
-
-    if (!fd)
-        return FALSE;
-
-    char buf[4];
-    if (vfs_fread (buf, 1, sizeof buf, fd) != sizeof buf)
-        return FALSE;
-
-    return ! strncmp (buf, "fLaC", sizeof buf);
-}
-
-static void squeeze_audio(int32_t* src, void* dst, unsigned count, unsigned res)
-{
-    int i;
-    int32_t* rp = src;
-    int8_t*  wp = dst;
-    int16_t* wp2 = dst;
-    int32_t* wp4 = dst;
-
-    switch (res)
-    {
-        case 8:
-            for (i = 0; i < count; i++, wp++, rp++)
-                *wp = *rp & 0xff;
-            break;
-
-        case 16:
-            for (i = 0; i < count; i++, wp2++, rp++)
-                *wp2 = *rp & 0xffff;
-            break;
-
-        case 24:
-        case 32:
-            for (i = 0; i < count; i++, wp4++, rp++)
-                *wp4 = *rp;
-            break;
-
-        default:
-            FLACNG_ERROR("Can not convert to %u bps\n", res);
-    }
-}
-
-static bool_t flac_play (const char * filename, VFSFile * file)
-{
-    if (!file)
-        return FALSE;
-
-    void * play_buffer = NULL;
-    bool_t error = FALSE;
-
-    info->fd = file;
-
-    if (read_metadata(decoder, info) == FALSE)
-    {
-        FLACNG_ERROR("Could not prepare file for playing!\n");
-        error = TRUE;
-        goto ERR_NO_CLOSE;
-    }
-
-    play_buffer = g_malloc (BUFFER_SIZE_BYTE);
-
-    if (! aud_input_open_audio (SAMPLE_FMT (info->bits_per_sample),
-        info->sample_rate, info->channels))
-    {
-        error = TRUE;
-        goto ERR_NO_CLOSE;
-    }
-
-    aud_input_set_bitrate(info->bitrate);
-
-    while (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_END_OF_STREAM)
-    {
-        if (aud_input_check_stop ())
-            break;
-
-        int seek_value = aud_input_check_seek ();
-        if (seek_value >= 0)
-            FLAC__stream_decoder_seek_absolute (decoder, (int64_t)
-             seek_value * info->sample_rate / 1000);
-
-        /* Try to decode a single frame of audio */
-        if (FLAC__stream_decoder_process_single(decoder) == FALSE)
-        {
-            FLACNG_ERROR("Error while decoding!\n");
-            error = TRUE;
-            break;
-        }
-
-        squeeze_audio(info->output_buffer, play_buffer, info->buffer_used, info->bits_per_sample);
-        aud_input_write_audio(play_buffer, info->buffer_used * SAMPLE_SIZE(info->bits_per_sample));
-
-        reset_info(info);
-    }
-
-ERR_NO_CLOSE:
-    g_free (play_buffer);
-    reset_info(info);
-
-    if (FLAC__stream_decoder_flush(decoder) == FALSE)
-        FLACNG_ERROR("Could not flush decoder state!\n");
-
-    return ! error;
-}
-
-static const char flac_about[] =
- N_("Original code by\n"
-    "Ralf Ertzinger <ralf at skytale.net>\n\n"
-    "http://www.skytale.net/projects/bmp-flac2/");
-
-static const char *flac_fmts[] = { "flac", "fla", NULL };
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("FLAC Decoder"),
-    .domain = PACKAGE,
-    .about_text = flac_about,
-    .init = flac_init,
-    .cleanup = flac_cleanup,
-    .play = flac_play,
-    .probe_for_tuple = flac_probe_for_tuple,
-    .is_our_file_from_vfs = flac_is_our_fd,
-    .extensions = flac_fmts,
-    .update_song_tuple = flac_update_song_tuple,
-    .get_song_image = flac_get_image,
-    .priority = 1
-)
diff --git a/src/flacng/plugin.cc b/src/flacng/plugin.cc
new file mode 100644
index 000000000000..444e2b4a4ee8
--- /dev/null
+++ b/src/flacng/plugin.cc
@@ -0,0 +1,173 @@
+/*
+ *  A FLAC decoder plugin for the Audacious Media Player
+ *  Copyright (C) 2005 Ralf Ertzinger
+ *  Copyright (C) 2010-2012 Michał Lipski
+ *
+ *  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.
+ */
+
+#include <string.h>
+
+#include <libaudcore/runtime.h>
+
+#include "flacng.h"
+
+EXPORT FLACng aud_plugin_instance;
+
+static FLAC__StreamDecoder *decoder;
+static callback_info *cinfo;
+
+bool FLACng::init()
+{
+    FLAC__StreamDecoderInitStatus ret;
+
+    /* Callback structure and decoder for main decoding loop */
+
+    cinfo = new callback_info;
+
+    if ((decoder = FLAC__stream_decoder_new()) == nullptr)
+    {
+        AUDERR("Could not create the main FLAC decoder instance!\n");
+        return false;
+    }
+
+    if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream(
+        decoder,
+        read_callback,
+        seek_callback,
+        tell_callback,
+        length_callback,
+        eof_callback,
+        write_callback,
+        metadata_callback,
+        error_callback,
+        cinfo)))
+    {
+        AUDERR("Could not initialize the main FLAC decoder: %s(%d)\n",
+            FLAC__StreamDecoderInitStatusString[ret], ret);
+        return false;
+    }
+
+    AUDDBG("Plugin initialized.\n");
+    return true;
+}
+
+void FLACng::cleanup()
+{
+    FLAC__stream_decoder_delete(decoder);
+    delete cinfo;
+}
+
+bool FLACng::is_our_file(const char *filename, VFSFile &file)
+{
+    AUDDBG("Probe for FLAC.\n");
+
+    char buf[4];
+    if (file.fread (buf, 1, sizeof buf) != sizeof buf)
+        return false;
+
+    return ! strncmp (buf, "fLaC", sizeof buf);
+}
+
+static void squeeze_audio(int32_t* src, void* dst, unsigned count, unsigned res)
+{
+    int32_t* rp = src;
+    int8_t*  wp = (int8_t*) dst;
+    int16_t* wp2 = (int16_t*) dst;
+    int32_t* wp4 = (int32_t*) dst;
+
+    switch (res)
+    {
+        case 8:
+            for (unsigned i = 0; i < count; i++, wp++, rp++)
+                *wp = *rp & 0xff;
+            break;
+
+        case 16:
+            for (unsigned i = 0; i < count; i++, wp2++, rp++)
+                *wp2 = *rp & 0xffff;
+            break;
+
+        case 24:
+        case 32:
+            for (unsigned i = 0; i < count; i++, wp4++, rp++)
+                *wp4 = *rp;
+            break;
+
+        default:
+            AUDERR("Can not convert to %u bps\n", res);
+    }
+}
+
+bool FLACng::play(const char *filename, VFSFile &file)
+{
+    Index<char> play_buffer;
+    bool error = false;
+
+    cinfo->fd = &file;
+
+    if (read_metadata(decoder, cinfo) == false)
+    {
+        AUDERR("Could not prepare file for playing!\n");
+        error = true;
+        goto ERR_NO_CLOSE;
+    }
+
+    play_buffer.resize(BUFFER_SIZE_BYTE);
+
+    set_stream_bitrate(cinfo->bitrate);
+    open_audio(SAMPLE_FMT(cinfo->bits_per_sample), cinfo->sample_rate, cinfo->channels);
+
+    while (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_END_OF_STREAM)
+    {
+        if (check_stop ())
+            break;
+
+        int seek_value = check_seek ();
+        if (seek_value >= 0)
+            FLAC__stream_decoder_seek_absolute (decoder, (int64_t)
+             seek_value * cinfo->sample_rate / 1000);
+
+        /* Try to decode a single frame of audio */
+        if (FLAC__stream_decoder_process_single(decoder) == false)
+        {
+            AUDERR("Error while decoding!\n");
+            error = true;
+            break;
+        }
+
+        squeeze_audio(cinfo->output_buffer.begin(), play_buffer.begin(),
+         cinfo->buffer_used, cinfo->bits_per_sample);
+        write_audio(play_buffer.begin(), cinfo->buffer_used *
+         SAMPLE_SIZE(cinfo->bits_per_sample));
+
+        cinfo->reset();
+    }
+
+ERR_NO_CLOSE:
+    cinfo->reset();
+
+    if (FLAC__stream_decoder_flush(decoder) == false)
+        AUDERR("Could not flush decoder state!\n");
+
+    return ! error;
+}
+
+const char FLACng::about[] =
+ N_("Original code by\n"
+    "Ralf Ertzinger <ralf at skytale.net>\n\n"
+    "http://www.skytale.net/projects/bmp-flac2/");
+
+const char *const FLACng::exts[] = { "flac", "fla", nullptr };
diff --git a/src/flacng/seekable_stream_callbacks.c b/src/flacng/seekable_stream_callbacks.c
deleted file mode 100644
index 4a93e9fbb5f2..000000000000
--- a/src/flacng/seekable_stream_callbacks.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *  A FLAC decoder plugin for the Audacious Media Player
- *  Copyright (C) 2005 Ralf Ertzinger
- *  Copyright (C) 2010-2012 Michał Lipski
- *
- *  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.
- */
-
-#include <string.h>
-#include <FLAC/all.h>
-
-#include <audacious/debug.h>
-
-#include "flacng.h"
-
-FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
-{
-    callback_info* info = (callback_info*) client_data;
-    size_t read;
-
-    if (info->fd == NULL)
-    {
-        FLACNG_ERROR("Trying to read data from an uninitialized file!\n");
-        return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-    }
-
-    if (*bytes == 0)
-        return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-
-    read = vfs_fread(buffer, 1, *bytes, info->fd);
-    *bytes = read;
-
-    switch (read)
-    {
-        case -1:
-            FLACNG_ERROR("Error while reading from stream!\n");
-            return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
-
-        case 0:
-            AUDDBG("Stream reached EOF\n");
-            return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
-
-        default:
-            return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-    }
-}
-
-FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 offset, void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-
-    if (vfs_fseek(info->fd, offset, SEEK_SET) != 0)
-    {
-        FLACNG_ERROR("Could not seek to %ld!\n", (long)offset);
-        return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
-    }
-
-    return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *offset, void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-
-    if ((*offset = vfs_ftell(info->fd)) == -1)
-    {
-        FLACNG_ERROR("Could not tell current position!\n");
-        return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
-    }
-
-    AUDDBG ("Current position: %d\n", (int) * offset);
-
-    return FLAC__STREAM_DECODER_TELL_STATUS_OK;
-}
-
-FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-    return vfs_feof(info->fd);
-}
-
-FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *length, void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-
-    if ((*length = vfs_fsize(info->fd)) == -1)
-    {
-        /*
-         * Could not get the stream size. This is not necessarily an
-         * error, maybe the stream has no fixed size (think streaming
-         * audio)
-         */
-        AUDDBG("Stream length is unknown.\n");
-        *length = 0;
-        return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
-    }
-
-    AUDDBG ("Stream length is %d bytes\n", (int) * length);
-
-    return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-
-    if (info->channels != frame->header.channels ||
-        info->sample_rate != frame->header.sample_rate)
-    {
-        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
-    }
-
-    for (long sample = 0; sample < frame->header.blocksize; sample++)
-    {
-        for (short channel = 0; channel < frame->header.channels; channel++)
-        {
-            *(info->write_pointer++) = buffer[channel][sample];
-            info->buffer_used += 1;
-        }
-    }
-
-    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
-}
-
-void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
-{
-    FLACNG_ERROR("FLAC decoder error callback was called: %d\n", status);
-}
-
-void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
-{
-    callback_info *info = (callback_info*) client_data;
-    int64_t size;
-
-    if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
-    {
-        info->total_samples = metadata->data.stream_info.total_samples;
-        AUDDBG("total_total_samples=%ld\n", (long) metadata->data.stream_info.total_samples);
-
-        info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
-        AUDDBG("bits_per_sample=%d\n", metadata->data.stream_info.bits_per_sample);
-
-        info->channels = metadata->data.stream_info.channels;
-        AUDDBG("channels=%d\n", metadata->data.stream_info.channels);
-
-        info->sample_rate = metadata->data.stream_info.sample_rate;
-        AUDDBG("sample_rate=%d\n", metadata->data.stream_info.sample_rate);
-
-        size = vfs_fsize(info->fd);
-
-        if (size == -1 || info->total_samples == 0)
-            info->bitrate = 0;
-        else
-            info->bitrate = 8 * size * (int64_t) info->sample_rate / info->total_samples;
-
-        AUDDBG("bitrate=%d\n", info->bitrate);
-    }
-}
diff --git a/src/flacng/seekable_stream_callbacks.cc b/src/flacng/seekable_stream_callbacks.cc
new file mode 100644
index 000000000000..8b3e7aaa505b
--- /dev/null
+++ b/src/flacng/seekable_stream_callbacks.cc
@@ -0,0 +1,173 @@
+/*
+ *  A FLAC decoder plugin for the Audacious Media Player
+ *  Copyright (C) 2005 Ralf Ertzinger
+ *  Copyright (C) 2010-2012 Michał Lipski
+ *
+ *  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.
+ */
+
+#include <string.h>
+#include <FLAC/all.h>
+
+#include <libaudcore/runtime.h>
+
+#include "flacng.h"
+
+FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
+{
+    callback_info* info = (callback_info*) client_data;
+    int64_t read;
+
+    if (*bytes == 0)
+        return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+
+    read = info->fd->fread (buffer, 1, *bytes);
+    *bytes = read;
+
+    switch (read)
+    {
+        case -1:
+            AUDERR("Error while reading from stream!\n");
+            return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+
+        case 0:
+            AUDDBG("Stream reached EOF\n");
+            return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+
+        default:
+            return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+    }
+}
+
+FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 offset, void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+
+    if (info->fd->fseek (offset, VFS_SEEK_SET) != 0)
+    {
+        AUDERR("Could not seek to %ld!\n", (long)offset);
+        return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+    }
+
+    return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *offset, void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+
+    int64_t result = info->fd->ftell ();
+    if (result < 0)
+    {
+        AUDERR("Could not tell current position!\n");
+        return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+    }
+
+    *offset = result;
+
+    AUDDBG ("Current position: %d\n", (int) * offset);
+
+    return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+    return info->fd->feof ();
+}
+
+FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *length, void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+
+    int64_t result = info->fd->fsize ();
+    if (result < 0)
+    {
+        /*
+         * Could not get the stream size. This is not necessarily an
+         * error, maybe the stream has no fixed size (think streaming
+         * audio)
+         */
+        AUDDBG("Stream length is unknown.\n");
+        *length = 0;
+        return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+    }
+
+    *length = result;
+
+    AUDDBG ("Stream length is %d bytes\n", (int) * length);
+
+    return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+
+    if (info->channels != frame->header.channels ||
+        info->sample_rate != frame->header.sample_rate)
+    {
+        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+    }
+
+    if (!info->output_buffer.len())
+        info->alloc();
+
+    for (unsigned sample = 0; sample < frame->header.blocksize; sample++)
+    {
+        for (unsigned channel = 0; channel < frame->header.channels; channel++)
+        {
+            *(info->write_pointer++) = buffer[channel][sample];
+            info->buffer_used += 1;
+        }
+    }
+
+    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+    AUDERR("FLAC decoder error callback was called: %d\n", status);
+}
+
+void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+    callback_info *info = (callback_info*) client_data;
+    int64_t size;
+
+    if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
+    {
+        info->total_samples = metadata->data.stream_info.total_samples;
+        AUDDBG("total_total_samples=%ld\n", (long) metadata->data.stream_info.total_samples);
+
+        info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
+        AUDDBG("bits_per_sample=%d\n", metadata->data.stream_info.bits_per_sample);
+
+        info->channels = metadata->data.stream_info.channels;
+        AUDDBG("channels=%d\n", metadata->data.stream_info.channels);
+
+        info->sample_rate = metadata->data.stream_info.sample_rate;
+        AUDDBG("sample_rate=%d\n", metadata->data.stream_info.sample_rate);
+
+        size = info->fd->fsize ();
+
+        if (size == -1 || info->total_samples == 0)
+            info->bitrate = 0;
+        else
+            info->bitrate = 8 * size * (int64_t) info->sample_rate / info->total_samples;
+
+        AUDDBG("bitrate=%d\n", info->bitrate);
+    }
+}
diff --git a/src/flacng/tools.c b/src/flacng/tools.c
deleted file mode 100644
index 02db04bc3d18..000000000000
--- a/src/flacng/tools.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  A FLAC decoder plugin for the Audacious Media Player
- *  Copyright (C) 2005 Ralf Ertzinger
- *  Copyright (C) 2010 John Lindgren
- *  Copyright (C) 2010-2012 Michał Lipski
- *
- *  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.
- */
-
-#include <string.h>
-#include <glib.h>
-
-#include <audacious/debug.h>
-
-#include "flacng.h"
-
-callback_info *init_callback_info(void)
-{
-    callback_info *info;
-
-    info = g_new0 (callback_info, 1);
-    info->output_buffer = g_malloc (BUFFER_SIZE_BYTE);
-
-    reset_info(info);
-
-    AUDDBG("Playback buffer allocated for %d samples, %d bytes\n", BUFFER_SIZE_SAMP, BUFFER_SIZE_BYTE);
-
-    return info;
-}
-
-void clean_callback_info(callback_info *info)
-{
-    g_free (info->output_buffer);
-    g_free (info);
-}
-
-void reset_info(callback_info *info)
-{
-    info->buffer_used = 0;
-    info->write_pointer = info->output_buffer;
-}
-
-bool_t read_metadata(FLAC__StreamDecoder *decoder, callback_info *info)
-{
-    FLAC__StreamDecoderState ret;
-
-    reset_info(info);
-
-    /* Reset the decoder */
-    if (FLAC__stream_decoder_reset(decoder) == false)
-    {
-        FLACNG_ERROR("Could not reset the decoder!\n");
-        return FALSE;
-    }
-
-    /* Try to decode the metadata */
-    if (FLAC__stream_decoder_process_until_end_of_metadata(decoder) == false)
-    {
-        ret = FLAC__stream_decoder_get_state(decoder);
-        AUDDBG("Could not read the metadata: %s(%d)!\n",
-            FLAC__StreamDecoderStateString[ret], ret);
-        reset_info(info);
-        return FALSE;
-    }
-
-    return TRUE;
-}
diff --git a/src/flacng/tools.cc b/src/flacng/tools.cc
new file mode 100644
index 000000000000..e5c1a23acfc9
--- /dev/null
+++ b/src/flacng/tools.cc
@@ -0,0 +1,52 @@
+/*
+ *  A FLAC decoder plugin for the Audacious Media Player
+ *  Copyright (C) 2005 Ralf Ertzinger
+ *  Copyright (C) 2010 John Lindgren
+ *  Copyright (C) 2010-2012 Michał Lipski
+ *
+ *  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.
+ */
+
+#include <string.h>
+
+#include <libaudcore/runtime.h>
+
+#include "flacng.h"
+
+bool read_metadata(FLAC__StreamDecoder *decoder, callback_info *info)
+{
+    FLAC__StreamDecoderState ret;
+
+    info->reset();
+
+    /* Reset the decoder */
+    if (FLAC__stream_decoder_reset(decoder) == false)
+    {
+        AUDERR("Could not reset the decoder!\n");
+        return false;
+    }
+
+    /* Try to decode the metadata */
+    if (FLAC__stream_decoder_process_until_end_of_metadata(decoder) == false)
+    {
+        ret = FLAC__stream_decoder_get_state(decoder);
+        AUDDBG("Could not read the metadata: %s(%d)!\n",
+            FLAC__StreamDecoderStateString[ret], ret);
+        info->reset();
+        return false;
+    }
+
+    return true;
+}
diff --git a/src/gio/Makefile b/src/gio/Makefile
index 6d0ebb9c0362..f491c09e5729 100644
--- a/src/gio/Makefile
+++ b/src/gio/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = gio${PLUGIN_SUFFIX}
 
-SRCS = gio.c
+SRCS = gio.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${TRANSPORT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${GIO_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
 LIBS += ${GIO_LIBS}
diff --git a/src/gio/gio.c b/src/gio/gio.c
deleted file mode 100644
index 94273252d07a..000000000000
--- a/src/gio/gio.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * GIO Transport Plugin for Audacious
- * Copyright 2009-2012 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <gio/gio.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-typedef struct {
-    GFile * file;
-    GIOStream * iostream;
-    GInputStream * istream;
-    GOutputStream * ostream;
-    GSeekable * seekable;
-} FileData;
-
-#define gio_error(...) do { \
-    SPRINTF (gio_error_buf, __VA_ARGS__); \
-    aud_interface_show_error (gio_error_buf); \
-} while (0)
-
-#define CHECK_ERROR(op, name) do { \
-    if (error) { \
-        gio_error ("Cannot %s %s: %s.", op, name, error->message); \
-        g_error_free (error); \
-        goto FAILED; \
-    } \
-} while (0)
-
-static void * gio_fopen (const char * filename, const char * mode)
-{
-    GError * error = 0;
-
-    FileData * data = g_new0 (FileData, 1);
-
-    data->file = g_file_new_for_uri (filename);
-
-    switch (mode[0])
-    {
-    case 'r':
-        if (strchr (mode, '+'))
-        {
-            data->iostream = (GIOStream *) g_file_open_readwrite (data->file, 0, & error);
-            CHECK_ERROR ("open", filename);
-            data->istream = g_io_stream_get_input_stream (data->iostream);
-            data->ostream = g_io_stream_get_output_stream (data->iostream);
-            data->seekable = (GSeekable *) data->iostream;
-        }
-        else
-        {
-            data->istream = (GInputStream *) g_file_read (data->file, 0, & error);
-            CHECK_ERROR ("open", filename);
-            data->seekable = (GSeekable *) data->istream;
-        }
-        break;
-    case 'w':
-        if (strchr (mode, '+'))
-        {
-            data->iostream = (GIOStream *) g_file_replace_readwrite (data->file, 0, 0, 0, 0, & error);
-            CHECK_ERROR ("open", filename);
-            data->istream = g_io_stream_get_input_stream (data->iostream);
-            data->ostream = g_io_stream_get_output_stream (data->iostream);
-            data->seekable = (GSeekable *) data->iostream;
-        }
-        else
-        {
-            data->ostream = (GOutputStream *) g_file_replace (data->file, 0, 0, 0, 0, & error);
-            CHECK_ERROR ("open", filename);
-            data->seekable = (GSeekable *) data->ostream;
-        }
-        break;
-    case 'a':
-        if (strchr (mode, '+'))
-        {
-            gio_error ("Cannot open %s: GIO does not support read-and-append mode.", filename);
-            goto FAILED;
-        }
-        else
-        {
-            data->ostream = (GOutputStream *) g_file_append_to (data->file, 0, 0, & error);
-            CHECK_ERROR ("open", filename);
-            data->seekable = (GSeekable *) data->ostream;
-        }
-        break;
-    default:
-        gio_error ("Cannot open %s: invalid mode.", filename);
-        goto FAILED;
-    }
-
-    return data;
-
-FAILED:
-    g_free (data);
-    return 0;
-}
-
-static int gio_fclose (VFSFile * file)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-
-    if (data->iostream)
-    {
-        g_io_stream_close (data->iostream, 0, & error);
-        g_object_unref (data->iostream);
-        CHECK_ERROR ("close", vfs_get_filename (file));
-    }
-    else if (data->istream)
-    {
-        g_input_stream_close (data->istream, 0, & error);
-        g_object_unref (data->istream);
-        CHECK_ERROR ("close", vfs_get_filename (file));
-    }
-    else if (data->ostream)
-    {
-        g_output_stream_close (data->ostream, 0, & error);
-        g_object_unref (data->ostream);
-        CHECK_ERROR ("close", vfs_get_filename (file));
-    }
-
-    if (data->file)
-        g_object_unref (data->file);
-
-    return 0;
-
-FAILED:
-    if (data->file)
-        g_object_unref (data->file);
-
-    return -1;
-}
-
-static int64_t gio_fread (void * buf, int64_t size, int64_t nitems, VFSFile * file)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-
-    if (! data->istream)
-    {
-        gio_error ("Cannot read from %s: not open for reading.", vfs_get_filename (file));
-        return 0;
-    }
-
-    int64_t readed = g_input_stream_read (data->istream, buf, size * nitems, 0, & error);
-    CHECK_ERROR ("read from", vfs_get_filename (file));
-
-    return (size > 0) ? readed / size : 0;
-
-FAILED:
-    return 0;
-}
-
-static int64_t gio_fwrite (const void * buf, int64_t size, int64_t nitems, VFSFile * file)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-
-    if (! data->ostream)
-    {
-        gio_error ("Cannot write to %s: not open for writing.", vfs_get_filename (file));
-        return 0;
-    }
-
-    int64_t written = g_output_stream_write (data->ostream, buf, size * nitems, 0, & error);
-    CHECK_ERROR ("write to", vfs_get_filename (file));
-
-    return (size > 0) ? written / size : 0;
-
-FAILED:
-    return 0;
-}
-
-static int gio_fseek (VFSFile * file, int64_t offset, int whence)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-    GSeekType gwhence;
-
-    switch (whence)
-    {
-    case SEEK_SET:
-        gwhence = G_SEEK_SET;
-        break;
-    case SEEK_CUR:
-        gwhence = G_SEEK_CUR;
-        break;
-    case SEEK_END:
-        gwhence = G_SEEK_END;
-        break;
-    default:
-        gio_error ("Cannot seek within %s: invalid whence.", vfs_get_filename (file));
-        return -1;
-    }
-
-    g_seekable_seek (data->seekable, offset, gwhence, NULL, & error);
-    CHECK_ERROR ("seek within", vfs_get_filename (file));
-
-    return 0;
-
-FAILED:
-    return -1;
-}
-
-static int64_t gio_ftell (VFSFile * file)
-{
-    FileData * data = vfs_get_handle (file);
-    return g_seekable_tell (data->seekable);
-}
-
-static int gio_getc (VFSFile * file)
-{
-    unsigned char c;
-    return (gio_fread (& c, 1, 1, file) == 1) ? c : -1;
-}
-
-static int gio_ungetc (int c, VFSFile * file)
-{
-    return (! gio_fseek (file, -1, SEEK_CUR)) ? c : -1;
-}
-
-static bool_t gio_feof (VFSFile * file)
-{
-    int test = gio_getc (file);
-
-    if (test < 0)
-        return TRUE;
-
-    gio_ungetc (test, file);
-    return FALSE;
-}
-
-static int gio_ftruncate (VFSFile * file, int64_t length)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-
-    g_seekable_truncate (data->seekable, length, NULL, & error);
-    CHECK_ERROR ("truncate", vfs_get_filename (file));
-
-    return 0;
-
-FAILED:
-    return -1;
-}
-
-static int64_t gio_fsize (VFSFile * file)
-{
-    FileData * data = vfs_get_handle (file);
-    GError * error = 0;
-
-    /* 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 (data->seekable))
-        return -1;
-
-    GFileInfo * info = g_file_query_info (data->file,
-     G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, 0, & error);
-    CHECK_ERROR ("get size of", vfs_get_filename (file));
-
-    int64_t size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
-
-    g_object_unref (info);
-    return size;
-
-FAILED:
-    return -1;
-}
-
-static const char gio_about[] =
- N_("GIO Plugin for Audacious\n"
-    "Copyright 2009-2012 John Lindgren");
-
-static const char * const gio_schemes[] = {"ftp", "sftp", "smb", 0};
-
-static VFSConstructor constructor = {
-    .vfs_fopen_impl = gio_fopen,
-    .vfs_fclose_impl = gio_fclose,
-    .vfs_fread_impl = gio_fread,
-    .vfs_fwrite_impl = gio_fwrite,
-    .vfs_fseek_impl = gio_fseek,
-    .vfs_ftell_impl = gio_ftell,
-    .vfs_feof_impl = gio_feof,
-    .vfs_ftruncate_impl = gio_ftruncate,
-    .vfs_fsize_impl = gio_fsize
-};
-
-AUD_TRANSPORT_PLUGIN
-(
-    .name = N_("GIO Plugin"),
-    .domain = PACKAGE,
-    .about_text = gio_about,
-    .schemes = gio_schemes,
-    .vtable = & constructor
-)
diff --git a/src/gio/gio.cc b/src/gio/gio.cc
new file mode 100644
index 000000000000..0d3d3fd2655a
--- /dev/null
+++ b/src/gio/gio.cc
@@ -0,0 +1,388 @@
+/*
+ * GIO Transport Plugin for Audacious
+ * Copyright 2009-2012 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gio/gio.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+
+static const char gio_about[] =
+ N_("GIO Plugin for Audacious\n"
+    "Copyright 2009-2012 John Lindgren");
+
+static const char * const gio_schemes[] = {"ftp", "sftp", "smb"};
+
+class GIOTransport : public TransportPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("GIO Plugin"), PACKAGE, gio_about};
+
+    constexpr GIOTransport () : TransportPlugin (info, gio_schemes) {}
+
+    VFSImpl * fopen (const char * path, const char * mode, String & error);
+};
+
+EXPORT GIOTransport aud_plugin_instance;
+
+class GIOFile : public VFSImpl
+{
+public:
+    GIOFile (const char * filename, const char * mode);
+    ~GIOFile ();
+
+    // exception
+    struct OpenError {
+        String error;
+    };
+
+protected:
+    int64_t fread (void * ptr, int64_t size, int64_t nmemb);
+    int64_t fwrite (const void * buf, int64_t size, int64_t nitems);
+
+    int fseek (int64_t offset, VFSSeekType whence);
+    int64_t ftell ();
+
+    int getc ();
+    int ungetc (int c);
+
+    bool feof ();
+
+    int ftruncate (int64_t length);
+    int64_t fsize ();
+
+    int fflush ();
+
+private:
+    String m_filename;
+    GFile * m_file = nullptr;
+    GIOStream * m_iostream = nullptr;
+    GInputStream * m_istream = nullptr;
+    GOutputStream * m_ostream = nullptr;
+    GSeekable * m_seekable = nullptr;
+};
+
+#define CHECK_ERROR(op, name) do { \
+    if (error) { \
+        AUDERR ("Cannot %s %s: %s.\n", op, (const char *) name, error->message); \
+        g_error_free (error); \
+        goto FAILED; \
+    } \
+} while (0)
+
+#define CHECK_AND_SAVE_ERROR(op, name) do { \
+    if (error) { \
+        AUDERR ("Cannot %s %s: %s.\n", op, (const char *) name, error->message); \
+        errorstr = String (error->message); \
+        g_error_free (error); \
+        goto FAILED; \
+    } \
+} while (0)
+
+GIOFile::GIOFile (const char * filename, const char * mode) :
+    m_filename (filename)
+{
+    GError * error = nullptr;
+    String errorstr;
+
+    m_file = g_file_new_for_uri (filename);
+
+    switch (mode[0])
+    {
+    case 'r':
+        if (strchr (mode, '+'))
+        {
+            m_iostream = (GIOStream *) g_file_open_readwrite (m_file, 0, & error);
+            CHECK_AND_SAVE_ERROR ("open", filename);
+            m_istream = g_io_stream_get_input_stream (m_iostream);
+            m_ostream = g_io_stream_get_output_stream (m_iostream);
+            m_seekable = (GSeekable *) m_iostream;
+        }
+        else
+        {
+            m_istream = (GInputStream *) g_file_read (m_file, 0, & error);
+            CHECK_AND_SAVE_ERROR ("open", filename);
+            m_seekable = (GSeekable *) m_istream;
+        }
+        break;
+    case 'w':
+        if (strchr (mode, '+'))
+        {
+            m_iostream = (GIOStream *) g_file_replace_readwrite (m_file,
+             0, 0, (GFileCreateFlags) 0, 0, & error);
+            CHECK_AND_SAVE_ERROR ("open", filename);
+            m_istream = g_io_stream_get_input_stream (m_iostream);
+            m_ostream = g_io_stream_get_output_stream (m_iostream);
+            m_seekable = (GSeekable *) m_iostream;
+        }
+        else
+        {
+            m_ostream = (GOutputStream *) g_file_replace (m_file, 0, 0,
+             (GFileCreateFlags) 0, 0, & error);
+            CHECK_AND_SAVE_ERROR ("open", filename);
+            m_seekable = (GSeekable *) m_ostream;
+        }
+        break;
+    case 'a':
+        if (strchr (mode, '+'))
+        {
+            AUDERR ("Cannot open %s: GIO does not support read-and-append mode.\n", filename);
+            errorstr = String (_("Read-and-append mode not supported"));
+            goto FAILED;
+        }
+        else
+        {
+            m_ostream = (GOutputStream *) g_file_append_to (m_file,
+             (GFileCreateFlags) 0, 0, & error);
+            CHECK_AND_SAVE_ERROR ("open", filename);
+            m_seekable = (GSeekable *) m_ostream;
+        }
+        break;
+    default:
+        AUDERR ("Cannot open %s: invalid mode.\n", filename);
+        errorstr = String (_("Invalid open mode"));
+        goto FAILED;
+    }
+
+    return;
+
+FAILED:
+    g_object_unref (m_file);
+    throw OpenError {errorstr};
+}
+
+GIOFile::~GIOFile ()
+{
+    GError * error = 0;
+
+    if (m_iostream)
+    {
+        g_io_stream_close (m_iostream, 0, & error);
+        g_object_unref (m_iostream);
+        CHECK_ERROR ("close", m_filename);
+    }
+    else if (m_istream)
+    {
+        g_input_stream_close (m_istream, 0, & error);
+        g_object_unref (m_istream);
+        CHECK_ERROR ("close", m_filename);
+    }
+    else if (m_ostream)
+    {
+        g_output_stream_close (m_ostream, 0, & error);
+        g_object_unref (m_ostream);
+        CHECK_ERROR ("close", m_filename);
+    }
+
+FAILED:
+    g_object_unref (m_file);
+}
+
+VFSImpl * GIOTransport::fopen (const char * filename, const char * mode, String & error)
+{
+#if ! GLIB_CHECK_VERSION (2, 36, 0)
+    g_type_init ();
+#endif
+
+    try { return new GIOFile (filename, mode); }
+    catch (GIOFile::OpenError & ex)
+    {
+        error = std::move (ex.error);
+        return nullptr;
+    }
+}
+
+int64_t GIOFile::fread (void * buf, int64_t size, int64_t nitems)
+{
+    GError * error = 0;
+
+    if (! m_istream)
+    {
+        AUDERR ("Cannot read from %s: not open for reading.\n", (const char *) m_filename);
+        return 0;
+    }
+
+    int64_t total = 0;
+    int64_t remain = size * nitems;
+
+    while (remain > 0)
+    {
+        int64_t part = g_input_stream_read (m_istream, buf, remain, 0, & error);
+        CHECK_ERROR ("read from", m_filename);
+
+        if (part <= 0)
+            break;
+
+        buf = (char *) buf + part;
+        total += part;
+        remain -= part;
+    }
+
+FAILED:
+    return (size > 0) ? total / size : 0;
+}
+
+int64_t GIOFile::fwrite (const void * buf, int64_t size, int64_t nitems)
+{
+    GError * error = 0;
+
+    if (! m_ostream)
+    {
+        AUDERR ("Cannot write to %s: not open for writing.\n", (const char *) m_filename);
+        return 0;
+    }
+
+    int64_t total = 0;
+    int64_t remain = size * nitems;
+
+    while (remain > 0)
+    {
+        int64_t part = g_output_stream_write (m_ostream, buf, remain, 0, & error);
+        CHECK_ERROR ("write to", m_filename);
+
+        if (part <= 0)
+            break;
+
+        buf = (const char *) buf + part;
+        total += part;
+        remain -= part;
+    }
+
+FAILED:
+    return (size > 0) ? total / size : 0;
+}
+
+int GIOFile::fseek (int64_t offset, VFSSeekType whence)
+{
+    GError * error = 0;
+    GSeekType gwhence;
+
+    switch (whence)
+    {
+    case VFS_SEEK_SET:
+        gwhence = G_SEEK_SET;
+        break;
+    case VFS_SEEK_CUR:
+        gwhence = G_SEEK_CUR;
+        break;
+    case VFS_SEEK_END:
+        gwhence = G_SEEK_END;
+        break;
+    default:
+        AUDERR ("Cannot seek within %s: invalid whence.\n", (const char *) m_filename);
+        return -1;
+    }
+
+    g_seekable_seek (m_seekable, offset, gwhence, nullptr, & error);
+    CHECK_ERROR ("seek within", m_filename);
+
+    return 0;
+
+FAILED:
+    return -1;
+}
+
+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;
+}
+
+int GIOFile::ftruncate (int64_t length)
+{
+    GError * error = 0;
+
+    g_seekable_truncate (m_seekable, length, nullptr, & error);
+    CHECK_ERROR ("truncate", m_filename);
+
+    return 0;
+
+FAILED:
+    return -1;
+}
+
+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);
+
+    size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+
+    g_object_unref (info);
+    return size;
+
+FAILED:
+    return -1;
+}
+
+int GIOFile::fflush ()
+{
+    int result;
+    GError * error = nullptr;
+
+    if (! m_ostream)
+        return 0;  /* no-op */
+
+    result = g_output_stream_flush (m_ostream, nullptr, & error);
+    CHECK_ERROR ("flush", m_filename);
+
+    return result;
+
+FAILED:
+    return -1;
+}
diff --git a/src/gl-spectrum-qt/Makefile b/src/gl-spectrum-qt/Makefile
new file mode 100644
index 000000000000..c4abd2be6f88
--- /dev/null
+++ b/src/gl-spectrum-qt/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = gl-spectrum-qt${PLUGIN_SUFFIX}
+
+SRCS = gl-spectrum.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${VISUALIZATION_PLUGIN_DIR}
+
+LD = ${CXX}
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${QTOPENGL_CFLAGS} ${GL_CFLAGS}
+LIBS += -lm ${QTOPENGL_LIBS} ${GL_LIBS}
diff --git a/src/gl-spectrum-qt/gl-spectrum.cc b/src/gl-spectrum-qt/gl-spectrum.cc
new file mode 100644
index 000000000000..f081f25a6fff
--- /dev/null
+++ b/src/gl-spectrum-qt/gl-spectrum.cc
@@ -0,0 +1,292 @@
+/*
+ * OpenGL Spectrum Analyzer for Audacious
+ * Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini
+ * Copyright 2014 William Pitcock
+ *
+ * Based on the XMMS plugin:
+ * Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and
+ *                     4Front Technologies
+ *
+ * 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.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#include <QGLWidget>
+#include <QGLFunctions>
+
+#define NUM_BANDS 32
+#define DB_RANGE 40
+
+#define BAR_SPACING (3.2f / NUM_BANDS)
+#define BAR_WIDTH (0.8f * BAR_SPACING)
+
+static const char gl_about[] =
+ N_("OpenGL Spectrum Analyzer for Audacious\n"
+    "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n"
+    "Copyright 2014 William Pitcock\n\n"
+    "Based on the XMMS plugin:\n"
+    "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, "
+    "and 4Front Technologies\n\n"
+    "License: GPLv2+");
+
+class GLSpectrumQt : public VisPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("OpenGL Spectrum Analyzer (Qt)"),
+        PACKAGE,
+        gl_about
+    };
+
+    constexpr GLSpectrumQt () : VisPlugin (info, Visualizer::Freq) {}
+
+    bool init ();
+
+    void * get_qt_widget ();
+
+    void clear ();
+    void render_freq (const float * freq);
+};
+
+EXPORT GLSpectrumQt aud_plugin_instance;
+
+static float logscale[NUM_BANDS + 1];
+static float colors[NUM_BANDS][NUM_BANDS][3];
+
+static int s_pos = 0;
+static float s_angle = 25, s_anglespeed = 0.05f;
+static float s_bars[NUM_BANDS][NUM_BANDS];
+
+class GLSpectrumWidget : public QGLWidget, protected QGLFunctions
+{
+public:
+    GLSpectrumWidget (QWidget *parent = nullptr);
+    ~GLSpectrumWidget ();
+
+private:
+    void paintGL ();
+    void resizeGL (int w, int h);
+};
+
+GLSpectrumWidget * s_widget = nullptr;
+
+bool GLSpectrumQt::init ()
+{
+    for (int i = 0; i <= NUM_BANDS; i ++)
+        logscale[i] = powf (256, (float) i / NUM_BANDS) - 0.5f;
+
+    for (int y = 0; y < NUM_BANDS; y ++)
+    {
+        float yf = (float) y / (NUM_BANDS - 1);
+
+        for (int x = 0; x < NUM_BANDS; x ++)
+        {
+            float xf = (float) x / (NUM_BANDS - 1);
+
+            colors[x][y][0] = (1 - xf) * (1 - yf);
+            colors[x][y][1] = xf;
+            colors[x][y][2] = yf;
+        }
+    }
+
+    return true;
+}
+
+/* stolen from the skins plugin */
+/* convert linear frequency graph to logarithmic one */
+static void make_log_graph (const float * freq, float * graph)
+{
+    for (int i = 0; i < NUM_BANDS; i ++)
+    {
+        /* sum up values in freq array between logscale[i] and logscale[i + 1],
+           including fractional parts */
+        int a = ceilf (logscale[i]);
+        int b = floorf (logscale[i + 1]);
+        float sum = 0;
+
+        if (b < a)
+            sum += freq[b] * (logscale[i + 1] - logscale[i]);
+        else
+        {
+            if (a > 0)
+                sum += freq[a - 1] * (a - logscale[i]);
+            for (; a < b; a ++)
+                sum += freq[a];
+            if (b < 256)
+                sum += freq[b] * (logscale[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) NUM_BANDS / 12;
+
+        /* convert to dB */
+        float val = 20 * log10f (sum);
+
+        /* scale (-DB_RANGE, 0.0) to (0.0, 1.0) */
+        val = 1 + val / DB_RANGE;
+
+        graph[i] = aud::clamp (val, 0.0f, 1.0f);
+    }
+}
+
+void GLSpectrumQt::render_freq (const float * freq)
+{
+    make_log_graph (freq, s_bars[s_pos]);
+    s_pos = (s_pos + 1) % NUM_BANDS;
+
+    s_angle += s_anglespeed;
+    if (s_angle > 45 || s_angle < -45)
+        s_anglespeed = -s_anglespeed;
+
+    if (s_widget)
+        s_widget->updateGL ();
+}
+
+void GLSpectrumQt::clear ()
+{
+#ifdef XXX_NOTYET
+    memset (s_bars, 0, sizeof s_bars);
+
+    if (s_widget)
+        s_widget->updateGL ();
+#endif
+}
+
+static void draw_rectangle (float x1, float y1, float z1, float x2, float y2,
+ float z2, float r, float g, float b)
+{
+    glColor3f (r, g, b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y2, z1);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x2, y2, z2);
+    glVertex3f (x1, y2, z2);
+    glEnd ();
+
+    glColor3f (0.65f * r, 0.65f * g, 0.65f * b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y1, z1);
+    glVertex3f (x1, y2, z1);
+    glVertex3f (x1, y2, z2);
+    glVertex3f (x1, y1, z2);
+    glEnd ();
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x2, y1, z1);
+    glVertex3f (x2, y1, z2);
+    glVertex3f (x2, y2, z2);
+    glEnd ();
+
+    glColor3f (0.8f * r, 0.8f * g, 0.8f * b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y1, z1);
+    glVertex3f (x2, y1, z1);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x1, y2, z1);
+    glEnd ();
+}
+
+static void draw_bar (float x, float z, float h, float r, float g, float b)
+{
+    draw_rectangle (x, 0, z, x + BAR_WIDTH, h, z + BAR_WIDTH,
+     r * (0.2f + 0.8f * h), g * (0.2f + 0.8f * h), b * (0.2f + 0.8f * h));
+}
+
+static void draw_bars ()
+{
+    glPushMatrix ();
+    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 ++)
+    {
+        float z = -1.6f + (NUM_BANDS - i) * BAR_SPACING;
+
+        for (int j = 0; j < NUM_BANDS; j ++)
+        {
+            draw_bar (1.6f - BAR_SPACING * j, z,
+             s_bars[(s_pos + i) % NUM_BANDS][j] * 1.6,
+             colors[i][j][0], colors[i][j][1], colors[i][j][2]);
+        }
+    }
+
+    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+    glPopMatrix ();
+}
+
+GLSpectrumWidget::GLSpectrumWidget (QWidget * parent) : QGLWidget (parent)
+{
+    setObjectName ("GLSpectrumWidget");
+}
+
+GLSpectrumWidget::~GLSpectrumWidget ()
+{
+    s_widget = nullptr;
+}
+
+void GLSpectrumWidget::paintGL ()
+{
+    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);
+}
+
+void GLSpectrumWidget::resizeGL (int w, int h)
+{
+    glViewport (0, 0, w, h);
+}
+
+void * GLSpectrumQt::get_qt_widget ()
+{
+    if (s_widget)
+        return s_widget;
+
+    s_widget = new GLSpectrumWidget;
+    return s_widget;
+}
diff --git a/src/gl-spectrum/Makefile b/src/gl-spectrum/Makefile
index e2dd330a4ec0..423054de7c8e 100644
--- a/src/gl-spectrum/Makefile
+++ b/src/gl-spectrum/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = gl-spectrum${PLUGIN_SUFFIX}
 
-SRCS = gl-spectrum.c
+SRCS = gl-spectrum.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${VISUALIZATION_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GTK_CFLAGS}
 LIBS += -lm ${GTK_LIBS} ${GL_LIBS}
diff --git a/src/gl-spectrum/gl-spectrum.c b/src/gl-spectrum/gl-spectrum.c
deleted file mode 100644
index 10fb22efd943..000000000000
--- a/src/gl-spectrum/gl-spectrum.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * OpenGL Spectrum Analyzer for Audacious
- * Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini
- *
- * Based on the XMMS plugin:
- * Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and
- *                     4Front Technologies
- *
- * 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.
- */
-
-#include <math.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include <GL/gl.h>
-
-#ifdef GDK_WINDOWING_X11
-#include <GL/glx.h>
-#include <gdk/gdkx.h>
-#endif
-
-#ifdef GDK_WINDOWING_WIN32
-#include <gdk/gdkwin32.h>
-#endif
-
-#define NUM_BANDS 32
-#define DB_RANGE 40
-
-#define BAR_SPACING (3.2f / NUM_BANDS)
-#define BAR_WIDTH (0.8f * BAR_SPACING)
-
-static float logscale[NUM_BANDS + 1];
-static float colors[NUM_BANDS][NUM_BANDS][3];
-
-#ifdef GDK_WINDOWING_X11
-static Display * s_display;
-static Window s_xwindow;
-static GLXContext s_context;
-#endif
-
-#ifdef GDK_WINDOWING_WIN32
-static HWND s_hwnd;
-static HDC s_hdc;
-static HGLRC s_glrc;
-#endif
-
-static GtkWidget * s_widget = NULL;
-
-static int s_pos = 0;
-static float s_angle = 25, s_anglespeed = 0.05f;
-static float s_bars[NUM_BANDS][NUM_BANDS];
-
-static bool_t init (void)
-{
-    for (int i = 0; i <= NUM_BANDS; i ++)
-        logscale[i] = powf (256, (float) i / NUM_BANDS) - 0.5f;
-
-    for (int y = 0; y < NUM_BANDS; y ++)
-    {
-        float yf = (float) y / (NUM_BANDS - 1);
-
-        for (int x = 0; x < NUM_BANDS; x ++)
-        {
-            float xf = (float) x / (NUM_BANDS - 1);
-
-            colors[x][y][0] = (1 - xf) * (1 - yf);
-            colors[x][y][1] = xf;
-            colors[x][y][2] = yf;
-        }
-    }
-
-    return TRUE;
-}
-
-/* stolen from the skins plugin */
-/* convert linear frequency graph to logarithmic one */
-static void make_log_graph (const float * freq, float * graph)
-{
-    for (int i = 0; i < NUM_BANDS; i ++)
-    {
-        /* sum up values in freq array between logscale[i] and logscale[i + 1],
-           including fractional parts */
-        int a = ceilf (logscale[i]);
-        int b = floorf (logscale[i + 1]);
-        float sum = 0;
-
-        if (b < a)
-            sum += freq[b] * (logscale[i + 1] - logscale[i]);
-        else
-        {
-            if (a > 0)
-                sum += freq[a - 1] * (a - logscale[i]);
-            for (; a < b; a ++)
-                sum += freq[a];
-            if (b < 256)
-                sum += freq[b] * (logscale[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) NUM_BANDS / 12;
-
-        /* convert to dB */
-        float val = 20 * log10f (sum);
-
-        /* scale (-DB_RANGE, 0.0) to (0.0, 1.0) */
-        val = 1 + val / DB_RANGE;
-
-        graph[i] = CLAMP (val, 0, 1);
-    }
-}
-
-static void render_freq (const float * freq)
-{
-    make_log_graph (freq, s_bars[s_pos]);
-    s_pos = (s_pos + 1) % NUM_BANDS;
-
-    s_angle += s_anglespeed;
-    if (s_angle > 45 || s_angle < -45)
-        s_anglespeed = -s_anglespeed;
-
-    if (s_widget)
-        gtk_widget_queue_draw (s_widget);
-}
-
-static void clear (void)
-{
-    memset (s_bars, 0, sizeof s_bars);
-
-    if (s_widget)
-        gtk_widget_queue_draw (s_widget);
-}
-
-static void draw_rectangle (float x1, float y1, float z1, float x2, float y2,
- float z2, float r, float g, float b)
-{
-    glColor3f (r, g, b);
-
-    glBegin (GL_POLYGON);
-    glVertex3f (x1, y2, z1);
-    glVertex3f (x2, y2, z1);
-    glVertex3f (x2, y2, z2);
-    glVertex3f (x1, y2, z2);
-    glEnd ();
-
-    glColor3f (0.65f * r, 0.65f * g, 0.65f * b);
-
-    glBegin (GL_POLYGON);
-    glVertex3f (x1, y1, z1);
-    glVertex3f (x1, y2, z1);
-    glVertex3f (x1, y2, z2);
-    glVertex3f (x1, y1, z2);
-    glEnd ();
-
-    glBegin (GL_POLYGON);
-    glVertex3f (x2, y2, z1);
-    glVertex3f (x2, y1, z1);
-    glVertex3f (x2, y1, z2);
-    glVertex3f (x2, y2, z2);
-    glEnd ();
-
-    glColor3f (0.8f * r, 0.8f * g, 0.8f * b);
-
-    glBegin (GL_POLYGON);
-    glVertex3f (x1, y1, z1);
-    glVertex3f (x2, y1, z1);
-    glVertex3f (x2, y2, z1);
-    glVertex3f (x1, y2, z1);
-    glEnd ();
-}
-
-static void draw_bar (float x, float z, float h, float r, float g, float b)
-{
-    draw_rectangle (x, 0, z, x + BAR_WIDTH, h, z + BAR_WIDTH,
-     r * (0.2f + 0.8f * h), g * (0.2f + 0.8f * h), b * (0.2f + 0.8f * h));
-}
-
-static void draw_bars (void)
-{
-    glPushMatrix ();
-    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 ++)
-    {
-        float z = -1.6f + (NUM_BANDS - i) * BAR_SPACING;
-
-        for (int j = 0; j < NUM_BANDS; j ++)
-        {
-            draw_bar (1.6f - BAR_SPACING * j, z,
-             s_bars[(s_pos + i) % NUM_BANDS][j] * 1.6,
-             colors[i][j][0], colors[i][j][1], colors[i][j][2]);
-        }
-    }
-
-    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-    glPopMatrix ();
-}
-
-static bool_t draw_cb (GtkWidget * widget, cairo_t * cr)
-{
-#ifdef GDK_WINDOWING_X11
-    if (! s_context)
-        return FALSE;
-#endif
-
-#ifdef GDK_WINDOWING_WIN32
-    if (! s_glrc)
-        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
-
-#ifdef GDK_WINDOWING_WIN32
-    SwapBuffers (s_hdc);
-#endif
-
-    return TRUE;
-}
-
-static void widget_realized (void)
-{
-    GdkWindow * window = gtk_widget_get_window (s_widget);
-
-#ifdef GDK_WINDOWING_X11
-    GdkScreen * screen = gdk_window_get_screen (window);
-    int nscreen = GDK_SCREEN_XNUMBER (screen);
-
-    s_display = GDK_SCREEN_XDISPLAY (screen);
-    s_xwindow = GDK_WINDOW_XID (window);
-
-    /* Create s_context */
-    int attribs[] = {
-     GLX_RGBA,
-     GLX_RED_SIZE, 1,
-     GLX_GREEN_SIZE, 1,
-     GLX_BLUE_SIZE, 1,
-     GLX_ALPHA_SIZE, 1,
-     GLX_DOUBLEBUFFER,
-     GLX_DEPTH_SIZE, 1,
-     None
-    };
-
-    XVisualInfo * xvinfo = glXChooseVisual (s_display, nscreen, attribs);
-    g_return_if_fail (xvinfo);
-
-    /* Fix up visual/colormap */
-    GdkVisual * visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
-    g_return_if_fail (visual);
-
-    gtk_widget_set_visual (s_widget, visual);
-
-    s_context = glXCreateContext (s_display, xvinfo, 0, True);
-    g_return_if_fail (s_context);
-
-    XFree (xvinfo);
-
-    glXMakeCurrent (s_display, s_xwindow, s_context);
-#endif
-
-#ifdef GDK_WINDOWING_WIN32
-    s_hwnd = GDK_WINDOW_HWND (window);
-    s_hdc = GetDC (s_hwnd);
-
-    PIXELFORMATDESCRIPTOR desc = {
-     sizeof (PIXELFORMATDESCRIPTOR),
-     1,                                 // version number (?)
-     PFD_DRAW_TO_WINDOW |               // format must support window
-     PFD_SUPPORT_OPENGL |               // format must support OpenGL
-     PFD_DOUBLEBUFFER,                  // must support double buffering
-     PFD_TYPE_RGBA,                     // request an RGBA format
-     24,                                // select a 8:8:8 bit color depth
-     0, 0, 0, 0, 0, 0,                  // color bits ignored (?)
-     0,                                 // no alpha buffer
-     0,                                 // shift bit ignored (?)
-     0,                                 // no accumulation buffer
-     0, 0, 0, 0,                        // accumulation bits ignored (?)
-     16,                                // 16-bit z-buffer (depth buffer)
-     0,                                 // no stencil buffer
-     0,                                 // no auxiliary buffer (?)
-     PFD_MAIN_PLANE,                    // main drawing layer
-     0,                                 // reserved (?)
-     0, 0, 0                            // layer masks ignored (?)
-    };
-
-    int format = ChoosePixelFormat (s_hdc, & desc);
-    g_return_if_fail (format != 0);
-
-    SetPixelFormat (s_hdc, format, & desc);
-
-    s_glrc = wglCreateContext (s_hdc);
-    g_return_if_fail (s_glrc);
-
-    wglMakeCurrent (s_hdc, s_glrc);
-#endif
-}
-
-static void widget_destroyed (void)
-{
-    s_widget = NULL;
-
-#ifdef GDK_WINDOWING_X11
-    if (s_context)
-    {
-        glXDestroyContext (s_display, s_context);
-        s_context = NULL;
-    }
-
-    s_display = NULL;
-#endif
-
-#ifdef GDK_WINDOWING_WIN32
-    if (s_glrc)
-    {
-        wglMakeCurrent (s_hdc, NULL);
-        wglDeleteContext (s_glrc);
-        s_glrc = NULL;
-    }
-
-    if (s_hdc)
-    {
-        ReleaseDC (s_hwnd, s_hdc);
-        s_hdc = NULL;
-    }
-
-    s_hwnd = NULL;
-#endif
-}
-
-static /* GtkWidget * */ void * get_widget (void)
-{
-    if (s_widget)
-        return s_widget;
-
-    s_widget = gtk_drawing_area_new ();
-
-    g_signal_connect (s_widget, "draw", (GCallback) draw_cb, NULL);
-    g_signal_connect (s_widget, "realize", (GCallback) widget_realized, NULL);
-    g_signal_connect (s_widget, "destroy", (GCallback) widget_destroyed, NULL);
-
-    /* Disable GTK double buffering */
-    gtk_widget_set_double_buffered (s_widget, FALSE);
-
-    return s_widget;
-}
-
-static const char about_text[] =
- N_("OpenGL Spectrum Analyzer for Audacious\n"
-    "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n\n"
-    "Based on the XMMS plugin:\n"
-    "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, "
-    "and 4Front Technologies\n\n"
-    "License: GPLv2+");
-
-AUD_VIS_PLUGIN
-(
-    .name = N_("OpenGL Spectrum Analyzer"),
-    .domain = PACKAGE,
-    .about_text = about_text,
-    .init = init,
-    .render_freq = render_freq,
-    .clear = clear,
-    .get_widget = get_widget,
-)
diff --git a/src/gl-spectrum/gl-spectrum.cc b/src/gl-spectrum/gl-spectrum.cc
new file mode 100644
index 000000000000..8ce3ca13ea10
--- /dev/null
+++ b/src/gl-spectrum/gl-spectrum.cc
@@ -0,0 +1,426 @@
+/*
+ * OpenGL Spectrum Analyzer for Audacious
+ * Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini
+ *
+ * Based on the XMMS plugin:
+ * Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, and
+ *                     4Front Technologies
+ *
+ * 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.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include <GL/gl.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+#include <gdk/gdkwin32.h>
+#endif
+
+#define NUM_BANDS 32
+#define DB_RANGE 40
+
+#define BAR_SPACING (3.2f / NUM_BANDS)
+#define BAR_WIDTH (0.8f * BAR_SPACING)
+
+static const char gl_about[] =
+ N_("OpenGL Spectrum Analyzer for Audacious\n"
+    "Copyright 2013 Christophe Budé, John Lindgren, and Carlo Bramini\n\n"
+    "Based on the XMMS plugin:\n"
+    "Copyright 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson, "
+    "and 4Front Technologies\n\n"
+    "License: GPLv2+");
+
+class GLSpectrum : public VisPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("OpenGL Spectrum Analyzer"),
+        PACKAGE,
+        gl_about
+    };
+
+    constexpr GLSpectrum () : VisPlugin (info, Visualizer::Freq) {}
+
+    bool init ();
+
+    void * get_gtk_widget ();
+
+    void clear ();
+    void render_freq (const float * freq);
+};
+
+EXPORT GLSpectrum aud_plugin_instance;
+
+static float logscale[NUM_BANDS + 1];
+static float colors[NUM_BANDS][NUM_BANDS][3];
+
+#ifdef GDK_WINDOWING_X11
+static Display * s_display;
+static Window s_xwindow;
+static GLXContext s_context;
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+static HWND s_hwnd;
+static HDC s_hdc;
+static HGLRC s_glrc;
+#endif
+
+static GtkWidget * s_widget = nullptr;
+
+static int s_pos = 0;
+static float s_angle = 25, s_anglespeed = 0.05f;
+static float s_bars[NUM_BANDS][NUM_BANDS];
+
+bool GLSpectrum::init ()
+{
+    for (int i = 0; i <= NUM_BANDS; i ++)
+        logscale[i] = powf (256, (float) i / NUM_BANDS) - 0.5f;
+
+    for (int y = 0; y < NUM_BANDS; y ++)
+    {
+        float yf = (float) y / (NUM_BANDS - 1);
+
+        for (int x = 0; x < NUM_BANDS; x ++)
+        {
+            float xf = (float) x / (NUM_BANDS - 1);
+
+            colors[x][y][0] = (1 - xf) * (1 - yf);
+            colors[x][y][1] = xf;
+            colors[x][y][2] = yf;
+        }
+    }
+
+    return true;
+}
+
+/* stolen from the skins plugin */
+/* convert linear frequency graph to logarithmic one */
+static void make_log_graph (const float * freq, float * graph)
+{
+    for (int i = 0; i < NUM_BANDS; i ++)
+    {
+        /* sum up values in freq array between logscale[i] and logscale[i + 1],
+           including fractional parts */
+        int a = ceilf (logscale[i]);
+        int b = floorf (logscale[i + 1]);
+        float sum = 0;
+
+        if (b < a)
+            sum += freq[b] * (logscale[i + 1] - logscale[i]);
+        else
+        {
+            if (a > 0)
+                sum += freq[a - 1] * (a - logscale[i]);
+            for (; a < b; a ++)
+                sum += freq[a];
+            if (b < 256)
+                sum += freq[b] * (logscale[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) NUM_BANDS / 12;
+
+        /* convert to dB */
+        float val = 20 * log10f (sum);
+
+        /* scale (-DB_RANGE, 0.0) to (0.0, 1.0) */
+        val = 1 + val / DB_RANGE;
+
+        graph[i] = aud::clamp (val, 0.0f, 1.0f);
+    }
+}
+
+void GLSpectrum::render_freq (const float * freq)
+{
+    make_log_graph (freq, s_bars[s_pos]);
+    s_pos = (s_pos + 1) % NUM_BANDS;
+
+    s_angle += s_anglespeed;
+    if (s_angle > 45 || s_angle < -45)
+        s_anglespeed = -s_anglespeed;
+
+    if (s_widget)
+        gtk_widget_queue_draw (s_widget);
+}
+
+void GLSpectrum::clear ()
+{
+    memset (s_bars, 0, sizeof s_bars);
+
+    if (s_widget)
+        gtk_widget_queue_draw (s_widget);
+}
+
+static void draw_rectangle (float x1, float y1, float z1, float x2, float y2,
+ float z2, float r, float g, float b)
+{
+    glColor3f (r, g, b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y2, z1);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x2, y2, z2);
+    glVertex3f (x1, y2, z2);
+    glEnd ();
+
+    glColor3f (0.65f * r, 0.65f * g, 0.65f * b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y1, z1);
+    glVertex3f (x1, y2, z1);
+    glVertex3f (x1, y2, z2);
+    glVertex3f (x1, y1, z2);
+    glEnd ();
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x2, y1, z1);
+    glVertex3f (x2, y1, z2);
+    glVertex3f (x2, y2, z2);
+    glEnd ();
+
+    glColor3f (0.8f * r, 0.8f * g, 0.8f * b);
+
+    glBegin (GL_POLYGON);
+    glVertex3f (x1, y1, z1);
+    glVertex3f (x2, y1, z1);
+    glVertex3f (x2, y2, z1);
+    glVertex3f (x1, y2, z1);
+    glEnd ();
+}
+
+static void draw_bar (float x, float z, float h, float r, float g, float b)
+{
+    draw_rectangle (x, 0, z, x + BAR_WIDTH, h, z + BAR_WIDTH,
+     r * (0.2f + 0.8f * h), g * (0.2f + 0.8f * h), b * (0.2f + 0.8f * h));
+}
+
+static void draw_bars ()
+{
+    glPushMatrix ();
+    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 ++)
+    {
+        float z = -1.6f + (NUM_BANDS - i) * BAR_SPACING;
+
+        for (int j = 0; j < NUM_BANDS; j ++)
+        {
+            draw_bar (1.6f - BAR_SPACING * j, z,
+             s_bars[(s_pos + i) % NUM_BANDS][j] * 1.6,
+             colors[i][j][0], colors[i][j][1], colors[i][j][2]);
+        }
+    }
+
+    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+    glPopMatrix ();
+}
+
+static gboolean draw_cb (GtkWidget * widget)
+{
+#ifdef GDK_WINDOWING_X11
+    if (! s_context)
+        return false;
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+    if (! s_glrc)
+        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
+
+#ifdef GDK_WINDOWING_WIN32
+    SwapBuffers (s_hdc);
+#endif
+
+    return true;
+}
+
+static void widget_realized ()
+{
+    GdkWindow * window = gtk_widget_get_window (s_widget);
+
+#ifdef GDK_WINDOWING_X11
+    GdkScreen * screen = gdk_window_get_screen (window);
+    int nscreen = GDK_SCREEN_XNUMBER (screen);
+
+    s_display = GDK_SCREEN_XDISPLAY (screen);
+    s_xwindow = GDK_WINDOW_XID (window);
+
+    /* Create s_context */
+    int attribs[] = {
+     GLX_RGBA,
+     GLX_RED_SIZE, 1,
+     GLX_GREEN_SIZE, 1,
+     GLX_BLUE_SIZE, 1,
+     GLX_ALPHA_SIZE, 1,
+     GLX_DOUBLEBUFFER,
+     GLX_DEPTH_SIZE, 1,
+     None
+    };
+
+    XVisualInfo * xvinfo = glXChooseVisual (s_display, nscreen, attribs);
+    g_return_if_fail (xvinfo);
+
+    /* Fix up visual/colormap */
+    GdkVisual * visual = gdk_x11_screen_lookup_visual (screen, xvinfo->visualid);
+    g_return_if_fail (visual);
+
+    gtk_widget_set_visual (s_widget, visual);
+
+    s_context = glXCreateContext (s_display, xvinfo, 0, true);
+    g_return_if_fail (s_context);
+
+    XFree (xvinfo);
+
+    glXMakeCurrent (s_display, s_xwindow, s_context);
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+    s_hwnd = (HWND) GDK_WINDOW_HWND (window);
+    s_hdc = GetDC (s_hwnd);
+
+    PIXELFORMATDESCRIPTOR desc = {
+     sizeof (PIXELFORMATDESCRIPTOR),
+     1,                                 // version number (?)
+     PFD_DRAW_TO_WINDOW |               // format must support window
+     PFD_SUPPORT_OPENGL |               // format must support OpenGL
+     PFD_DOUBLEBUFFER,                  // must support double buffering
+     PFD_TYPE_RGBA,                     // request an RGBA format
+     24,                                // select a 8:8:8 bit color depth
+     0, 0, 0, 0, 0, 0,                  // color bits ignored (?)
+     0,                                 // no alpha buffer
+     0,                                 // shift bit ignored (?)
+     0,                                 // no accumulation buffer
+     0, 0, 0, 0,                        // accumulation bits ignored (?)
+     16,                                // 16-bit z-buffer (depth buffer)
+     0,                                 // no stencil buffer
+     0,                                 // no auxiliary buffer (?)
+     PFD_MAIN_PLANE,                    // main drawing layer
+     0,                                 // reserved (?)
+     0, 0, 0                            // layer masks ignored (?)
+    };
+
+    int format = ChoosePixelFormat (s_hdc, & desc);
+    g_return_if_fail (format != 0);
+
+    SetPixelFormat (s_hdc, format, & desc);
+
+    s_glrc = wglCreateContext (s_hdc);
+    g_return_if_fail (s_glrc);
+
+    wglMakeCurrent (s_hdc, s_glrc);
+#endif
+}
+
+static void widget_destroyed ()
+{
+    s_widget = nullptr;
+
+#ifdef GDK_WINDOWING_X11
+    if (s_context)
+    {
+        glXDestroyContext (s_display, s_context);
+        s_context = nullptr;
+    }
+
+    s_display = nullptr;
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+    if (s_glrc)
+    {
+        wglMakeCurrent (s_hdc, nullptr);
+        wglDeleteContext (s_glrc);
+        s_glrc = nullptr;
+    }
+
+    if (s_hdc)
+    {
+        ReleaseDC (s_hwnd, s_hdc);
+        s_hdc = nullptr;
+    }
+
+    s_hwnd = nullptr;
+#endif
+}
+
+void * GLSpectrum::get_gtk_widget ()
+{
+    if (s_widget)
+        return s_widget;
+
+    s_widget = gtk_drawing_area_new ();
+
+    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);
+
+    /* Disable GTK double buffering */
+    gtk_widget_set_double_buffered (s_widget, false);
+
+    return s_widget;
+}
diff --git a/src/gnomeshortcuts/Makefile b/src/gnomeshortcuts/Makefile
index 13b8e1d36b62..b8ef5dfab14b 100644
--- a/src/gnomeshortcuts/Makefile
+++ b/src/gnomeshortcuts/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = gnomeshortcuts${PLUGIN_SUFFIX}
 
-SRCS = gnomeshortcuts.c
+SRCS = gnomeshortcuts.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${DBUS_CFLAGS} -I../.. -I..
 LIBS += ${GLIB_LIBS} ${DBUS_LIBS} ${GTK_LIBS}
diff --git a/src/gnomeshortcuts/gnomeshortcuts.c b/src/gnomeshortcuts/gnomeshortcuts.c
deleted file mode 100644
index e415645ff211..000000000000
--- a/src/gnomeshortcuts/gnomeshortcuts.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- *  This file is part of audacious-gnome-shortcut plugin for audacious
- *
- *  Copyright (c) 2007-2008    Sascha Hlusiak <contact at saschahlusiak.de>
- *  Name: plugin.c
- *  Description: plugin.c
- *
- *  audacious-gnome-shortcut 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.
- *
- *  audacious-gnome-shortcut is distributed in the hope that 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-gnome-shortcut; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <string.h>
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-bindings.h>
-#include <glib-object.h>
-
-#include <audacious/drct.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-
-static gboolean init (void);
-static void cleanup (void);
-void gnome_remote_init();
-void gnome_remote_uninit();
-
-static gboolean loaded = FALSE;
-static DBusGProxy *media_player_keys_proxy = NULL;
-
-static const char about[] =
- N_("Gnome Shortcut Plugin\n"
-    "Lets you control the player with Gnome's shortcuts.\n\n"
-    "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>");
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Gnome Shortcuts"),
-    .domain = PACKAGE,
-    .about_text = about,
-    .init = init,
-    .cleanup = cleanup
-)
-
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-
-
-static void
-hotkey_marshal_VOID__STRING_STRING (GClosure     *closure,
-                                    GValue       *return_value,
-                                    guint         n_param_values,
-                                    const GValue *param_values,
-                                    gpointer      invocation_hint,
-                                    gpointer      marshal_data)
-{
-    typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer data1,
-                                                      gpointer arg_1,
-                                                      gpointer arg_2);
-    register GMarshalFunc_VOID__STRING_STRING callback;
-    register GCClosure *cc = (GCClosure*) closure;
-    register gpointer data1;
-
-    g_return_if_fail (n_param_values == 3);
-
-    if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-        data1 = closure->data;
-    } else {
-        data1 = g_value_peek_pointer (param_values + 0);
-    }
-    callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
-
-    callback (data1,
-     g_marshal_value_peek_string (param_values + 1),
-     g_marshal_value_peek_string (param_values + 2));
-}
-
-static void
-on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const gchar *key)
-{
-    if (strcmp ("Audacious", application) == 0) {
-        gint current_volume /* , old_volume */ ;
-        static gint volume_static = 0;
-        gboolean mute;
-
-        /* get current volume */
-        aud_drct_get_volume_main (&current_volume);
-        /* old_volume = current_volume; */
-        if (current_volume)
-        {
-            /* volume is not mute */
-            mute = FALSE;
-        } else {
-            /* volume is mute */
-            mute = TRUE;
-        }
-
-        /* mute the playback */
-        if (strcmp ("Mute", key) == 0)
-        {
-            if (!mute)
-            {
-                volume_static = current_volume;
-                aud_drct_set_volume_main (0);
-                mute = TRUE;
-            } else {
-                aud_drct_set_volume_main (volume_static);
-                mute = FALSE;
-            }
-            return;
-        }
-
-        /* decreace volume */
-/*      if ((keycode == plugin_cfg.vol_down) && (state == plugin_cfg.vol_down_mask))
-        {
-            if (mute)
-            {
-                current_volume = old_volume;
-                old_volume = 0;
-                mute = FALSE;
-            }
-
-            if ((current_volume -= plugin_cfg.vol_decrement) < 0)
-            {
-                current_volume = 0;
-            }
-
-            if (current_volume != old_volume)
-            {
-                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
-                 current_volume);
-            }
-
-            old_volume = current_volume;
-            return TRUE;
-        }*/
-
-        /* increase volume */
-/*      if ((keycode == plugin_cfg.vol_up) && (state == plugin_cfg.vol_up_mask))
-        {
-            if (mute)
-            {
-                current_volume = old_volume;
-                old_volume = 0;
-                mute = FALSE;
-            }
-
-            if ((current_volume += plugin_cfg.vol_increment) > 100)
-            {
-                current_volume = 100;
-            }
-
-            if (current_volume != old_volume)
-            {
-                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
-                 current_volume);
-            }
-
-            old_volume = current_volume;
-            return TRUE;
-        }*/
-
-        /* play or pause */
-        if (strcmp ("Play", key) == 0 || strcmp ("Pause", key) == 0)
-        {
-            aud_drct_play_pause ();
-            return;
-        }
-
-        /* stop */
-        if (strcmp ("Stop", key) == 0)
-        {
-            aud_drct_stop ();
-            return;
-        }
-
-        /* prev track */
-        if (strcmp ("Previous", key) == 0)
-        {
-            aud_drct_pl_prev ();
-            return;
-        }
-
-        /* next track */
-        if (strcmp ("Next", key) == 0)
-        {
-            aud_drct_pl_next ();
-            return;
-        }
-    }
-}
-
-void gnome_remote_uninit ()
-{
-    GError *error = NULL;
-    if (media_player_keys_proxy == NULL) return;
-
-    dbus_g_proxy_disconnect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
-     G_CALLBACK (on_media_player_key_pressed), NULL);
-
-    dbus_g_proxy_call (media_player_keys_proxy,
-     "ReleaseMediaPlayerKeys", &error,
-     G_TYPE_STRING, "Audacious",
-     G_TYPE_INVALID, G_TYPE_INVALID);
-    if (error != NULL) {
-        g_warning ("Could not release media player keys: %s", error->message);
-        g_error_free (error);
-    }
-    g_object_unref(media_player_keys_proxy);
-    media_player_keys_proxy = NULL;
-}
-
-void gnome_remote_init ()
-{
-    DBusGConnection *bus;
-    GError *error = NULL;
-    dbus_g_thread_init();
-
-    bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-    if ((bus == NULL) && error) {
-        g_warning ("Error connecting to DBus: %s", error->message);
-        g_error_free (error);
-    } else {
-        media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
-         "org.gnome.SettingsDaemon",
-         "/org/gnome/SettingsDaemon/MediaKeys",
-         "org.gnome.SettingsDaemon.MediaKeys");
-        if (media_player_keys_proxy == NULL) return;
-
-        dbus_g_proxy_call (media_player_keys_proxy,
-         "GrabMediaPlayerKeys", &error,
-         G_TYPE_STRING, "Audacious",
-         G_TYPE_UINT, 0,
-         G_TYPE_INVALID,
-         G_TYPE_INVALID);
-        if (error != NULL) {
-            g_error_free (error);
-            error = NULL;
-            g_object_unref(media_player_keys_proxy);
-            media_player_keys_proxy = NULL;
-             media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
-             "org.gnome.SettingsDaemon",
-             "/org/gnome/SettingsDaemon",
-             "org.gnome.SettingsDaemon");
-            if (media_player_keys_proxy == NULL) return;
-
-            dbus_g_proxy_call (media_player_keys_proxy,
-             "GrabMediaPlayerKeys", &error,
-             G_TYPE_STRING, "Audacious",
-             G_TYPE_UINT, 0,
-             G_TYPE_INVALID,
-             G_TYPE_INVALID);
-            if (error != NULL) {
-                g_warning ("Could not grab media player keys: %s", error->message);
-                g_error_free (error);
-                g_object_unref(media_player_keys_proxy);
-                media_player_keys_proxy = NULL;
-                return;
-            }
-        }
-
-        dbus_g_object_register_marshaller (hotkey_marshal_VOID__STRING_STRING,
-         G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-
-        dbus_g_proxy_add_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
-         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-
-        dbus_g_proxy_connect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
-         G_CALLBACK (on_media_player_key_pressed), NULL, NULL);
-    }
-}
-
-static gboolean init (void)
-{
-    gnome_remote_init();
-    loaded = TRUE;
-    return TRUE;
-}
-
-static void cleanup (void)
-{
-    if (!loaded) return;
-    gnome_remote_uninit();
-    loaded = FALSE;
-}
diff --git a/src/gnomeshortcuts/gnomeshortcuts.cc b/src/gnomeshortcuts/gnomeshortcuts.cc
new file mode 100644
index 000000000000..6749e5f6b000
--- /dev/null
+++ b/src/gnomeshortcuts/gnomeshortcuts.cc
@@ -0,0 +1,289 @@
+/*
+ *  This file is part of audacious-gnome-shortcut plugin for audacious
+ *
+ *  Copyright (c) 2007-2008    Sascha Hlusiak <contact at saschahlusiak.de>
+ *  Name: plugin.c
+ *  Description: plugin.c
+ *
+ *  audacious-gnome-shortcut 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.
+ *
+ *  audacious-gnome-shortcut is distributed in the hope that 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-gnome-shortcut; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <glib-object.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/i18n.h>
+
+class GNOMEShortcuts : public GeneralPlugin
+{
+public:
+    static const char about[];
+
+    static constexpr PluginInfo info = {
+        N_("GNOME Shortcuts"),
+        PACKAGE,
+        about
+    };
+
+    constexpr GNOMEShortcuts () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT GNOMEShortcuts aud_plugin_instance;
+
+static DBusGProxy *media_player_keys_proxy = nullptr;
+
+const char GNOMEShortcuts::about[] =
+ N_("GNOME Shortcut Plugin\n"
+    "Lets you control the player with GNOME's shortcuts.\n\n"
+    "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>");
+
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+
+
+static void
+hotkey_marshal_VOID__STRING_STRING (GClosure     *closure,
+                                    GValue       *return_value,
+                                    unsigned         n_param_values,
+                                    const GValue *param_values,
+                                    void *      invocation_hint,
+                                    void *      marshal_data)
+{
+    typedef void (*GMarshalFunc_VOID__STRING_STRING) (void * data1,
+                                                      void * arg_1,
+                                                      void * arg_2);
+    GMarshalFunc_VOID__STRING_STRING callback;
+    GCClosure *cc = (GCClosure*) closure;
+    void * data1;
+
+    g_return_if_fail (n_param_values == 3);
+
+    if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+        data1 = closure->data;
+    } else {
+        data1 = g_value_peek_pointer (param_values + 0);
+    }
+    callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+    callback (data1,
+     g_marshal_value_peek_string (param_values + 1),
+     g_marshal_value_peek_string (param_values + 2));
+}
+
+static void
+on_media_player_key_pressed (DBusGProxy *proxy, const char *application, const char *key)
+{
+    if (strcmp ("Audacious", application) == 0) {
+        int current_volume /* , old_volume */ ;
+        static int volume_static = 0;
+        bool mute;
+
+        /* get current volume */
+        current_volume = aud_drct_get_volume_main ();
+        /* old_volume = current_volume; */
+        if (current_volume)
+        {
+            /* volume is not mute */
+            mute = false;
+        } else {
+            /* volume is mute */
+            mute = true;
+        }
+
+        /* mute the playback */
+        if (strcmp ("Mute", key) == 0)
+        {
+            if (!mute)
+            {
+                volume_static = current_volume;
+                aud_drct_set_volume_main (0);
+                mute = true;
+            } else {
+                aud_drct_set_volume_main (volume_static);
+                mute = false;
+            }
+            return;
+        }
+
+        /* decreace volume */
+/*      if ((keycode == plugin_cfg.vol_down) && (state == plugin_cfg.vol_down_mask))
+        {
+            if (mute)
+            {
+                current_volume = old_volume;
+                old_volume = 0;
+                mute = false;
+            }
+
+            if ((current_volume -= plugin_cfg.vol_decrement) < 0)
+            {
+                current_volume = 0;
+            }
+
+            if (current_volume != old_volume)
+            {
+                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
+                 current_volume);
+            }
+
+            old_volume = current_volume;
+            return true;
+        }*/
+
+        /* increase volume */
+/*      if ((keycode == plugin_cfg.vol_up) && (state == plugin_cfg.vol_up_mask))
+        {
+            if (mute)
+            {
+                current_volume = old_volume;
+                old_volume = 0;
+                mute = false;
+            }
+
+            if ((current_volume += plugin_cfg.vol_increment) > 100)
+            {
+                current_volume = 100;
+            }
+
+            if (current_volume != old_volume)
+            {
+                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
+                 current_volume);
+            }
+
+            old_volume = current_volume;
+            return true;
+        }*/
+
+        /* play or pause */
+        if (strcmp ("Play", key) == 0 || strcmp ("Pause", key) == 0)
+        {
+            aud_drct_play_pause ();
+            return;
+        }
+
+        /* stop */
+        if (strcmp ("Stop", key) == 0)
+        {
+            aud_drct_stop ();
+            return;
+        }
+
+        /* prev track */
+        if (strcmp ("Previous", key) == 0)
+        {
+            aud_drct_pl_prev ();
+            return;
+        }
+
+        /* next track */
+        if (strcmp ("Next", key) == 0)
+        {
+            aud_drct_pl_next ();
+            return;
+        }
+    }
+}
+
+void GNOMEShortcuts::cleanup ()
+{
+    GError *error = nullptr;
+    if (media_player_keys_proxy == nullptr) return;
+
+    dbus_g_proxy_disconnect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+     G_CALLBACK (on_media_player_key_pressed), nullptr);
+
+    dbus_g_proxy_call (media_player_keys_proxy,
+     "ReleaseMediaPlayerKeys", &error,
+     G_TYPE_STRING, "Audacious",
+     G_TYPE_INVALID, G_TYPE_INVALID);
+    if (error != nullptr) {
+        g_warning ("Could not release media player keys: %s", error->message);
+        g_error_free (error);
+    }
+    g_object_unref(media_player_keys_proxy);
+    media_player_keys_proxy = nullptr;
+}
+
+bool GNOMEShortcuts::init ()
+{
+    DBusGConnection *bus;
+    GError *error = nullptr;
+    dbus_g_thread_init();
+
+    bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    if ((bus == nullptr) && error) {
+        g_warning ("Error connecting to DBus: %s", error->message);
+        g_error_free (error);
+        return false;
+    } else {
+        media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
+         "org.gnome.SettingsDaemon",
+         "/org/gnome/SettingsDaemon/MediaKeys",
+         "org.gnome.SettingsDaemon.MediaKeys");
+        if (media_player_keys_proxy == nullptr)
+            return false;
+
+        dbus_g_proxy_call (media_player_keys_proxy,
+         "GrabMediaPlayerKeys", &error,
+         G_TYPE_STRING, "Audacious",
+         G_TYPE_UINT, 0,
+         G_TYPE_INVALID,
+         G_TYPE_INVALID);
+        if (error != nullptr) {
+            g_error_free (error);
+            error = nullptr;
+            g_object_unref(media_player_keys_proxy);
+            media_player_keys_proxy = nullptr;
+             media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
+             "org.gnome.SettingsDaemon",
+             "/org/gnome/SettingsDaemon",
+             "org.gnome.SettingsDaemon");
+            if (media_player_keys_proxy == nullptr)
+                return false;
+
+            dbus_g_proxy_call (media_player_keys_proxy,
+             "GrabMediaPlayerKeys", &error,
+             G_TYPE_STRING, "Audacious",
+             G_TYPE_UINT, 0,
+             G_TYPE_INVALID,
+             G_TYPE_INVALID);
+            if (error != nullptr) {
+                g_warning ("Could not grab media player keys: %s", error->message);
+                g_error_free (error);
+                g_object_unref(media_player_keys_proxy);
+                media_player_keys_proxy = nullptr;
+                return false;
+            }
+        }
+
+        dbus_g_object_register_marshaller (hotkey_marshal_VOID__STRING_STRING,
+         G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+        dbus_g_proxy_add_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+        dbus_g_proxy_connect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+         G_CALLBACK (on_media_player_key_pressed), nullptr, nullptr);
+
+        return true;
+    }
+}
diff --git a/src/gtkui/Makefile b/src/gtkui/Makefile
index ecdf78e42400..cdfe244bc1bd 100644
--- a/src/gtkui/Makefile
+++ b/src/gtkui/Makefile
@@ -1,21 +1,23 @@
 PLUGIN = gtkui${PLUGIN_SUFFIX}
 
-SRCS = columns.c \
-       layout.c \
-       menus.c \
-       ui_infoarea.c \
-       ui_gtk.c \
-       ui_playlist_widget.c \
-       ui_playlist_notebook.c \
-       ui_statusbar.c \
-       playlist_util.c \
-       settings.c
+SRCS = columns.cc \
+       layout.cc \
+       menus.cc \
+       ui_infoarea.cc \
+       ui_gtk.cc \
+       ui_playlist_widget.cc \
+       ui_playlist_notebook.cc \
+       ui_statusbar.cc \
+       playlist_util.cc \
+       settings.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GTK_CFLAGS}
-LIBS += -lm ${GTK_LIBS}
+LIBS += -lm ${GTK_LIBS} -laudgui
diff --git a/src/gtkui/columns.c b/src/gtkui/columns.c
deleted file mode 100644
index 4f9d773cae84..000000000000
--- a/src/gtkui/columns.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * columns.c
- * Copyright 2011 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 <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <libaudcore/index.h>
-#include <libaudcore/audstrings.h>
-#include <libaudgui/libaudgui-gtk.h>
-#include <libaudgui/list.h>
-
-#include "ui_playlist_notebook.h"
-#include "ui_playlist_widget.h"
-
-const char * const pw_col_names[PW_COLS] = {N_("Entry number"), N_("Title"),
- N_("Artist"), N_("Year"), N_("Album"), N_("Track"), N_("Genre"),
- N_("Queue position"), N_("Length"), N_("File path"), N_("File name"),
- N_("Custom title"), N_("Bitrate")};
-
-int pw_num_cols;
-int pw_cols[PW_COLS];
-
-static const char * const pw_col_keys[PW_COLS] = {"number", "title", "artist",
- "year", "album", "track", "genre", "queued", "length", "path", "filename",
- "custom", "bitrate"};
-
-void pw_col_init (void)
-{
-    pw_num_cols = 0;
-
-    char * columns = aud_get_str ("gtkui", "playlist_columns");
-    Index * index = str_list_to_index (columns, " ");
-
-    int count = index_count (index);
-    if (count > PW_COLS)
-        count = PW_COLS;
-
-    for (int c = 0; c < count; c ++)
-    {
-        char * column = index_get (index, c);
-
-        int i = 0;
-        while (i < PW_COLS && strcmp (column, pw_col_keys[i]))
-            i ++;
-
-        if (i == PW_COLS)
-            break;
-
-        pw_cols[pw_num_cols ++] = i;
-    }
-
-    index_free_full (index, (IndexFreeFunc) str_unref);
-    str_unref (columns);
-}
-
-typedef struct {
-    int column;
-    bool_t selected;
-} Column;
-
-static GtkWidget * chosen_list = NULL, * avail_list = NULL;
-static Index * chosen = NULL, * avail = NULL;
-
-static void apply_changes (void)
-{
-    int cols = index_count (chosen);
-    g_return_if_fail (cols <= PW_COLS);
-
-    ui_playlist_notebook_empty ();
-
-    for (pw_num_cols = 0; pw_num_cols < cols; pw_num_cols ++)
-        pw_cols[pw_num_cols] = ((Column *) index_get (chosen, pw_num_cols))->column;
-
-    aud_set_str ("gtkui", "column_widths", "");
-    aud_set_str ("gtkui", "column_expand", "");
-
-    ui_playlist_notebook_populate ();
-}
-
-static void get_value (void * user, int row, int column, GValue * value)
-{
-    g_return_if_fail (row >= 0 && row < index_count (user));
-    Column * c = index_get (user, row);
-    g_value_set_string (value, _(pw_col_names[c->column]));
-}
-
-static bool_t get_selected (void * user, int row)
-{
-    g_return_val_if_fail (row >= 0 && row < index_count (user), FALSE);
-    return ((Column *) index_get (user, row))->selected;
-}
-
-static void set_selected (void * user, int row, bool_t selected)
-{
-    g_return_if_fail (row >= 0 && row < index_count (user));
-    ((Column *) index_get (user, row))->selected = selected;
-}
-
-static void select_all (void * user, bool_t selected)
-{
-    int rows = index_count (user);
-    for (int row = 0; row < rows; row ++)
-        ((Column *) index_get (user, row))->selected = selected;
-}
-
-static void shift_rows (void * user, int row, int before)
-{
-    int rows = index_count (user);
-    g_return_if_fail (row >= 0 && row < rows);
-    g_return_if_fail (before >= 0 && before <= rows);
-
-    if (before == row)
-        return;
-
-    Index * move = index_new ();
-    Index * others = index_new ();
-
-    int begin, end;
-    if (before < row)
-    {
-        begin = before;
-        end = row + 1;
-        while (end < rows && ((Column *) index_get (user, end))->selected)
-            end ++;
-    }
-    else
-    {
-        begin = row;
-        while (begin > 0 && ((Column *) index_get (user, begin - 1))->selected)
-            begin --;
-        end = before;
-    }
-
-    for (int i = begin; i < end; i ++)
-    {
-        Column * c = index_get (user, i);
-        index_insert (c->selected ? move : others, -1, c);
-    }
-
-    if (before < row)
-    {
-        index_copy_insert (others, 0, move, -1, -1);
-        index_free (others);
-    }
-    else
-    {
-        index_copy_insert (move, 0, others, -1, -1);
-        index_free (move);
-        move = others;
-    }
-
-    index_copy_set (move, 0, user, begin, end - begin);
-    index_free (move);
-
-    GtkWidget * list = (user == chosen) ? chosen_list : avail_list;
-    audgui_list_update_rows (list, begin, end - begin);
-    audgui_list_update_selection (list, begin, end - begin);
-
-    apply_changes ();
-}
-
-static const AudguiListCallbacks callbacks = {
- .get_value = get_value,
- .get_selected = get_selected,
- .set_selected = set_selected,
- .select_all = select_all,
- .shift_rows = shift_rows};
-
-static void transfer (Index * source)
-{
-    Index * dest;
-    GtkWidget * source_list, * dest_list;
-    if (source == chosen)
-    {
-        dest = avail;
-        source_list = chosen_list;
-        dest_list = avail_list;
-    }
-    else
-    {
-        dest = chosen;
-        source_list = avail_list;
-        dest_list = chosen_list;
-    }
-
-    int source_rows = index_count (source);
-    int dest_rows = index_count (dest);
-
-    for (int row = 0; row < source_rows; )
-    {
-        Column * c = index_get (source, row);
-        if (! c->selected)
-        {
-            row ++;
-            continue;
-        }
-
-        index_delete (source, row, 1);
-        audgui_list_delete_rows (source_list, row, 1);
-        source_rows --;
-        index_insert (dest, -1, c);
-        audgui_list_insert_rows (dest_list, dest_rows, 1);
-        dest_rows ++;
-    }
-
-    apply_changes ();
-}
-
-static void destroy_cb (void)
-{
-    chosen_list = NULL;
-    avail_list = NULL;
-
-    int rows = index_count (chosen);
-    for (int row = 0; row < rows; row ++)
-        g_slice_free (Column, index_get (chosen, row));
-    index_free (chosen);
-    chosen = NULL;
-
-    rows = index_count (avail);
-    for (int row = 0; row < rows; row ++)
-        g_slice_free (Column, index_get (avail, row));
-    index_free (avail);
-    avail = NULL;
-}
-
-void * pw_col_create_chooser (void)
-{
-    chosen = index_new ();
-    avail = index_new ();
-
-    bool_t added[PW_COLS];
-    memset (added, 0, sizeof added);
-
-    for (int i = 0; i < pw_num_cols; i ++)
-    {
-        if (added[pw_cols[i]])
-            continue;
-        added[pw_cols[i]] = TRUE;
-        Column * column = g_slice_new (Column);
-        column->column = pw_cols[i];
-        column->selected = 0;
-        index_insert (chosen, -1, column);
-    }
-
-    for (int i = 0; i < PW_COLS; i ++)
-    {
-        if (added[i])
-            continue;
-        Column * column = g_slice_new (Column);
-        column->column = i;
-        column->selected = 0;
-        index_insert (avail, -1, column);
-    }
-
-    GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_widget_set_size_request (hbox, -1, 160);
-
-    GtkWidget * scroll = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scroll,
-     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scroll,
-     GTK_SHADOW_IN);
-    gtk_box_pack_start ((GtkBox *) hbox, scroll, TRUE, TRUE, 0);
-
-    avail_list = audgui_list_new (& callbacks, avail, index_count (avail));
-    audgui_list_add_column (avail_list, _("Available columns"), 0, G_TYPE_STRING, -1);
-    gtk_container_add ((GtkContainer *) scroll, avail_list);
-
-    GtkWidget * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-    gtk_box_pack_start ((GtkBox *) hbox, vbox, FALSE, FALSE, 0);
-
-    GtkWidget * button = gtk_button_new ();
-    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
-     ("go-next", GTK_ICON_SIZE_BUTTON));
-    gtk_box_pack_start ((GtkBox *) vbox, button, TRUE, FALSE, 0);
-    g_signal_connect_swapped (button, "clicked", (GCallback) transfer, avail);
-
-    button = gtk_button_new ();
-    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
-     ("go-previous", GTK_ICON_SIZE_BUTTON));
-    gtk_box_pack_start ((GtkBox *) vbox, button, TRUE, FALSE, 0);
-    g_signal_connect_swapped (button, "clicked", (GCallback) transfer, chosen);
-
-    scroll = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scroll,
-     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scroll,
-     GTK_SHADOW_IN);
-    gtk_box_pack_start ((GtkBox *) hbox, scroll, TRUE, TRUE, 0);
-
-    chosen_list = audgui_list_new (& callbacks, chosen, index_count (chosen));
-    audgui_list_add_column (chosen_list, _("Displayed columns"), 0, G_TYPE_STRING, -1);
-    gtk_container_add ((GtkContainer *) scroll, chosen_list);
-
-    g_signal_connect (hbox, "destroy", (GCallback) destroy_cb, NULL);
-
-    return hbox;
-}
-
-void pw_col_save (void)
-{
-    Index * index = index_new ();
-
-    for (int i = 0; i < pw_num_cols; i ++)
-        index_insert (index, -1, (void *) pw_col_keys[pw_cols[i]]);
-
-    char * columns = index_to_str_list (index, " ");
-    aud_set_str ("gtkui", "playlist_columns", columns);
-    str_unref (columns);
-
-    index_free (index);
-}
diff --git a/src/gtkui/columns.cc b/src/gtkui/columns.cc
new file mode 100644
index 000000000000..1ba300f9685c
--- /dev/null
+++ b/src/gtkui/columns.cc
@@ -0,0 +1,350 @@
+/*
+ * columns.c
+ * Copyright 2011 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 <gtk/gtk.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/index.h>
+#include <libaudcore/audstrings.h>
+#include <libaudgui/libaudgui-gtk.h>
+#include <libaudgui/list.h>
+
+#include "ui_playlist_notebook.h"
+#include "ui_playlist_widget.h"
+
+const char * const pw_col_names[PW_COLS] = {
+    N_("Entry number"),
+    N_("Title"),
+    N_("Artist"),
+    N_("Year"),
+    N_("Album"),
+    N_("Album artist"),
+    N_("Track"),
+    N_("Genre"),
+    N_("Queue position"),
+    N_("Length"),
+    N_("File path"),
+    N_("File name"),
+    N_("Custom title"),
+    N_("Bitrate")
+};
+
+int pw_num_cols;
+int pw_cols[PW_COLS];
+int pw_col_widths[PW_COLS];
+
+static const char * const pw_col_keys[PW_COLS] = {
+    "number",
+    "title",
+    "artist",
+    "year",
+    "album",
+    "album-artist",
+    "track",
+    "genre",
+    "queued",
+    "length",
+    "path",
+    "filename",
+    "custom",
+    "bitrate"
+};
+
+static const int pw_default_widths[PW_COLS] = {
+    10,   // entry number
+    275,  // title
+    175,  // artist
+    10,   // year
+    175,  // album
+    175,  // album artist
+    10,   // track
+    100,  // genre
+    10,   // queue position
+    10,   // length
+    275,  // path
+    275,  // filename
+    275,  // custom title
+    10    // bitrate
+};
+
+void pw_col_init ()
+{
+    pw_num_cols = 0;
+
+    String columns = aud_get_str ("gtkui", "playlist_columns");
+    Index<String> index = str_list_to_index (columns, " ");
+
+    int count = index.len ();
+    if (count > PW_COLS)
+        count = PW_COLS;
+
+    for (int c = 0; c < count; c ++)
+    {
+        const String & column = index[c];
+
+        int i = 0;
+        while (i < PW_COLS && strcmp (column, pw_col_keys[i]))
+            i ++;
+
+        if (i == PW_COLS)
+            break;
+
+        pw_cols[pw_num_cols ++] = i;
+    }
+
+    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);
+}
+
+struct Column {
+    int column;
+    bool selected;
+};
+
+static GtkWidget * chosen_list = nullptr, * avail_list = nullptr;
+static Index<Column> chosen, avail;
+
+static void apply_changes ()
+{
+    int cols = chosen.len ();
+    g_return_if_fail (cols <= PW_COLS);
+
+    ui_playlist_notebook_empty ();
+
+    for (pw_num_cols = 0; pw_num_cols < cols; pw_num_cols ++)
+        pw_cols[pw_num_cols] = chosen[pw_num_cols].column;
+
+    ui_playlist_notebook_populate ();
+}
+
+static void get_value (void * user, int row, int column, GValue * value)
+{
+    auto & index = * (Index<Column> *) user;
+    g_return_if_fail (row >= 0 && row < index.len ());
+    g_value_set_string (value, _(pw_col_names[index[row].column]));
+}
+
+static bool get_selected (void * user, int row)
+{
+    auto & index = * (Index<Column> *) user;
+    g_return_val_if_fail (row >= 0 && row < index.len (), false);
+    return index[row].selected;
+}
+
+static void set_selected (void * user, int row, bool selected)
+{
+    auto & index = * (Index<Column> *) user;
+    g_return_if_fail (row >= 0 && row < index.len ());
+    index[row].selected = selected;
+}
+
+static void select_all (void * user, bool selected)
+{
+    auto & index = * (Index<Column> *) user;
+    for (Column & col : index)
+        col.selected = selected;
+}
+
+static void shift_rows (void * user, int row, int before)
+{
+    auto & index = * (Index<Column> *) user;
+    int rows = index.len ();
+    g_return_if_fail (row >= 0 && row < rows);
+    g_return_if_fail (before >= 0 && before <= rows);
+
+    if (before == row)
+        return;
+
+    Index<Column> move;
+    Index<Column> others;
+
+    int begin, end;
+    if (before < row)
+    {
+        begin = before;
+        end = row + 1;
+        while (end < rows && index[end].selected)
+            end ++;
+    }
+    else
+    {
+        begin = row;
+        while (begin > 0 && index[begin - 1].selected)
+            begin --;
+        end = before;
+    }
+
+    for (int i = begin; i < end; i ++)
+    {
+        if (index[i].selected)
+            move.append (index[i]);
+        else
+            others.append (index[i]);
+    }
+
+    if (before < row)
+        move.move_from (others, 0, -1, -1, true, true);
+    else
+        move.move_from (others, 0, 0, -1, true, true);
+
+    index.move_from (move, 0, begin, end - begin, false, true);
+
+    GtkWidget * list = (& index == & chosen) ? chosen_list : avail_list;
+    audgui_list_update_rows (list, begin, end - begin);
+    audgui_list_update_selection (list, begin, end - begin);
+
+    apply_changes ();
+}
+
+static const AudguiListCallbacks callbacks = {
+    get_value,
+    get_selected,
+    set_selected,
+    select_all,
+    nullptr,  // activate_row
+    nullptr,  // right_click
+    shift_rows
+};
+
+static void transfer (Index<Column> * source)
+{
+    Index<Column> * dest;
+    GtkWidget * source_list, * dest_list;
+    if (source == & chosen)
+    {
+        dest = & avail;
+        source_list = chosen_list;
+        dest_list = avail_list;
+    }
+    else
+    {
+        dest = & chosen;
+        source_list = avail_list;
+        dest_list = chosen_list;
+    }
+
+    int source_rows = source->len ();
+    int dest_rows = dest->len ();
+
+    for (int row = 0; row < source_rows; )
+    {
+        Column c = (* source)[row];
+        if (! c.selected)
+        {
+            row ++;
+            continue;
+        }
+
+        source->remove (row, 1);
+        audgui_list_delete_rows (source_list, row, 1);
+        source_rows --;
+        dest->append (c);
+        audgui_list_insert_rows (dest_list, dest_rows, 1);
+        dest_rows ++;
+    }
+
+    apply_changes ();
+}
+
+static void destroy_cb ()
+{
+    chosen_list = nullptr;
+    avail_list = nullptr;
+
+    chosen.clear ();
+    avail.clear ();
+}
+
+void * pw_col_create_chooser ()
+{
+    bool added[PW_COLS] = {};
+
+    for (int i = 0; i < pw_num_cols; i ++)
+    {
+        if (! added[pw_cols[i]])
+        {
+            added[pw_cols[i]] = true;
+            chosen.append (pw_cols[i], false);
+        }
+    }
+
+    for (int i = 0; i < PW_COLS; i ++)
+    {
+        if (! added[i])
+            avail.append (i, false);
+    }
+
+    GtkWidget * hbox = gtk_hbox_new (false, 6);
+    gtk_widget_set_size_request (hbox, -1, 160);
+
+    GtkWidget * scroll = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scroll,
+     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scroll,
+     GTK_SHADOW_IN);
+    gtk_box_pack_start ((GtkBox *) hbox, scroll, true, true, 0);
+
+    avail_list = audgui_list_new (& callbacks, & avail, avail.len ());
+    audgui_list_add_column (avail_list, _("Available columns"), 0, G_TYPE_STRING, -1);
+    gtk_container_add ((GtkContainer *) scroll, avail_list);
+
+    GtkWidget * vbox = gtk_vbox_new (false, 6);
+    gtk_box_pack_start ((GtkBox *) hbox, vbox, false, false, 0);
+
+    GtkWidget * button = gtk_button_new ();
+    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
+     ("go-next", GTK_ICON_SIZE_BUTTON));
+    gtk_box_pack_start ((GtkBox *) vbox, button, true, false, 0);
+    g_signal_connect_swapped (button, "clicked", (GCallback) transfer, & avail);
+
+    button = gtk_button_new ();
+    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
+     ("go-previous", GTK_ICON_SIZE_BUTTON));
+    gtk_box_pack_start ((GtkBox *) vbox, button, true, false, 0);
+    g_signal_connect_swapped (button, "clicked", (GCallback) transfer, & chosen);
+
+    scroll = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scroll,
+     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scroll,
+     GTK_SHADOW_IN);
+    gtk_box_pack_start ((GtkBox *) hbox, scroll, true, true, 0);
+
+    chosen_list = audgui_list_new (& callbacks, & chosen, chosen.len ());
+    audgui_list_add_column (chosen_list, _("Displayed columns"), 0, G_TYPE_STRING, -1);
+    gtk_container_add ((GtkContainer *) scroll, chosen_list);
+
+    g_signal_connect (hbox, "destroy", (GCallback) destroy_cb, nullptr);
+
+    return hbox;
+}
+
+void pw_col_save ()
+{
+    Index<String> index;
+    for (int i = 0; i < pw_num_cols; i ++)
+        index.append (String (pw_col_keys[pw_cols[i]]));
+
+    aud_set_str ("gtkui", "playlist_columns", index_to_str_list (index, " "));
+    aud_set_str ("gtkui", "column_widths", int_array_to_str (pw_col_widths, PW_COLS));
+}
diff --git a/src/gtkui/gtkui.h b/src/gtkui/gtkui.h
index a3d392f58d71..08d40edb4cbd 100644
--- a/src/gtkui/gtkui.h
+++ b/src/gtkui/gtkui.h
@@ -21,9 +21,9 @@
 #define GTKUI_H
 
 #include <stdint.h>
-
 #include <gtk/gtk.h>
-#include <audacious/types.h>
+
+struct PluginPreferences;
 
 /* menus.c */
 GtkWidget * make_menu_bar (GtkAccelGroup * accel);
@@ -36,16 +36,17 @@ extern int menu_tab_playlist_id;
 extern const PluginPreferences gtkui_prefs;
 
 /* ui_gtk.c */
-void set_ab_repeat_a (void);
-void set_ab_repeat_b (void);
-void clear_ab_repeat (void);
-void show_hide_menu (void);
-void show_hide_infoarea (void);
-void show_hide_infoarea_vis (void);
-void show_hide_statusbar (void);
+void set_ab_repeat_a ();
+void set_ab_repeat_b ();
+void clear_ab_repeat ();
+void show_hide_menu ();
+void show_hide_infoarea ();
+void show_hide_infoarea_vis ();
+void show_hide_statusbar ();
 void popup_menu_rclick (unsigned button, uint32_t time);
 void popup_menu_tab (unsigned button, uint32_t time, int playlist);
-void activate_search_tool (void);
-void update_step_size (void);
+void activate_search_tool ();
+void activate_playlist_manager ();
+void update_step_size ();
 
 #endif
diff --git a/src/gtkui/layout.c b/src/gtkui/layout.c
deleted file mode 100644
index d9a6c8b16378..000000000000
--- a/src/gtkui/layout.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * layout.c
- * Copyright 2011 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 <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugins.h>
-
-#include "layout.h"
-
-#define DEFAULT_WIDTH 300
-#define DEFAULT_HEIGHT 200
-
-enum {DOCK_LEFT, DOCK_RIGHT, DOCK_TOP, DOCK_BOTTOM, DOCKS};
-
-#define IS_VERTICAL(d) ((d) & 2)
-#define IS_AFTER(d) ((d) & 1)
-
-#define NULL_ON_DESTROY(w) g_signal_connect ((w), "destroy", (GCallback) \
- gtk_widget_destroyed, & (w))
-
-typedef struct {
-    char * name;
-    GtkWidget * widget, * vbox, * paned, * window;
-    int dock, x, y, w, h;
-} Item;
-
-static GList * items = NULL;
-
-static GtkWidget * layout = NULL;
-static GtkWidget * center = NULL;
-static GtkWidget * docks[DOCKS] = {NULL, NULL, NULL, NULL};
-static GtkWidget * menu = NULL;
-
-GtkWidget * layout_new (void)
-{
-    g_return_val_if_fail (! layout, NULL);
-    layout = gtk_alignment_new (0, 0, 1, 1);
-    gtk_alignment_set_padding ((GtkAlignment *) layout, 3, 3, 3, 3);
-    NULL_ON_DESTROY (layout);
-    return layout;
-}
-
-void layout_add_center (GtkWidget * widget)
-{
-    g_return_if_fail (layout && ! center && widget);
-    center = widget;
-    gtk_container_add ((GtkContainer *) layout, center);
-    NULL_ON_DESTROY (center);
-}
-
-static void layout_move (GtkWidget * widget, int dock);
-
-static void layout_dock_left (GtkWidget * widget)
-{
-    layout_move (widget, DOCK_LEFT);
-}
-
-static void layout_dock_right (GtkWidget * widget)
-{
-    layout_move (widget, DOCK_RIGHT);
-}
-
-static void layout_dock_top (GtkWidget * widget)
-{
-    layout_move (widget, DOCK_TOP);
-}
-
-static void layout_dock_bottom (GtkWidget * widget)
-{
-    layout_move (widget, DOCK_BOTTOM);
-}
-
-static void layout_undock (GtkWidget * widget)
-{
-    layout_move (widget, -1);
-}
-
-static void layout_disable (GtkWidget * widget)
-{
-    PluginHandle * plugin = aud_plugin_by_widget (widget);
-    g_return_if_fail (plugin);
-    aud_plugin_enable (plugin, FALSE);
-}
-
-static bool_t menu_cb (GtkWidget * widget, GdkEventButton * event)
-{
-    g_return_val_if_fail (widget && event, FALSE);
-
-    if (event->type != GDK_BUTTON_PRESS || event->button != 3)
-        return FALSE;
-
-    if (menu)
-        gtk_widget_destroy (menu);
-
-    menu = gtk_menu_new ();
-    g_signal_connect (menu, "destroy", (GCallback) gtk_widget_destroyed, & menu);
-
-    const char * names[6] = {N_("Dock at Left"), N_("Dock at Right"),
-     N_("Dock at Top"), N_("Dock at Bottom"), N_("Undock"), N_("Disable")};
-    void (* const funcs[6]) (GtkWidget * widget) = {layout_dock_left,
-     layout_dock_right, layout_dock_top, layout_dock_bottom, layout_undock,
-     layout_disable};
-
-    for (int i = 0; i < 6; i ++)
-    {
-        GtkWidget * item = gtk_menu_item_new_with_label (_(names[i]));
-        gtk_menu_shell_append ((GtkMenuShell *) menu, item);
-        g_signal_connect_swapped (item, "activate", (GCallback) funcs[i], widget);
-    }
-
-    gtk_widget_show_all (menu);
-    gtk_menu_popup ((GtkMenu *) menu, NULL, NULL, NULL, NULL, event->button, event->time);
-
-    return TRUE;
-}
-
-static GtkWidget * vbox_new (GtkWidget * widget, const char * name)
-{
-    g_return_val_if_fail (widget && name, NULL);
-
-    GtkWidget * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
-
-    GtkWidget * ebox = gtk_event_box_new ();
-    gtk_box_pack_start ((GtkBox *) vbox, ebox, FALSE, FALSE, 0);
-    g_signal_connect_swapped (ebox, "button-press-event", (GCallback) menu_cb,
-     widget);
-
-    GtkWidget * label = gtk_label_new (NULL);
-    char * markup = g_markup_printf_escaped ("<small><b>%s</b></small>", name);
-    gtk_label_set_markup ((GtkLabel *) label, markup);
-    g_free (markup);
-    gtk_misc_set_alignment ((GtkMisc *) label, 0, 0);
-    gtk_container_add ((GtkContainer *) ebox, label);
-
-    gtk_box_pack_start ((GtkBox *) vbox, widget, TRUE, TRUE, 0);
-
-    gtk_widget_show_all (vbox);
-
-    return vbox;
-}
-
-typedef struct {
-    GtkWidget * paned;
-    GtkWidget * widget;
-    bool_t vertical;
-    int w, h;
-} RestoreSizeData;
-
-static bool_t restore_size_cb (RestoreSizeData * d)
-{
-    GtkAllocation rect;
-    gtk_widget_get_allocation (d->widget, & rect);
-    int pos = gtk_paned_get_position ((GtkPaned *) d->paned);
-    pos -= d->vertical ? d->h - rect.height : d->w - rect.width;
-    gtk_paned_set_position ((GtkPaned *) d->paned, pos);
-
-    g_slice_free (RestoreSizeData, d);
-    return FALSE;
-}
-
-static GtkWidget * paned_new (bool_t vertical, bool_t after, int w, int h)
-{
-    GtkWidget * paned = gtk_paned_new (vertical ? GTK_ORIENTATION_VERTICAL :
-     GTK_ORIENTATION_HORIZONTAL);
-
-    GtkWidget * mine = gtk_alignment_new (0, 0, 1, 1);
-    GtkWidget * next = gtk_alignment_new (0, 0, 1, 1);
-    gtk_paned_pack1 ((GtkPaned *) paned, after ? next : mine, after, FALSE);
-    gtk_paned_pack2 ((GtkPaned *) paned, after ? mine : next, ! after, FALSE);
-
-    g_object_set_data ((GObject *) paned, "mine", mine);
-    g_object_set_data ((GObject *) paned, "next", next);
-
-    gtk_widget_show_all (paned);
-
-    if (vertical ? h : w)
-    {
-        if (after)
-        {
-            /* hack to set the size of the second pane */
-            RestoreSizeData * d = g_slice_new (RestoreSizeData);
-            d->paned = paned;
-            d->widget = mine;
-            d->vertical = vertical;
-            d->w = w;
-            d->h = h;
-            g_idle_add ((GSourceFunc) restore_size_cb, d);
-        }
-        else
-            gtk_paned_set_position ((GtkPaned *) paned, vertical ? h : w);
-    }
-
-    return paned;
-}
-
-static Item * item_new (const char * name)
-{
-    Item * item = g_slice_new (Item);
-    item->name = str_get (name);
-    item->widget = item->vbox = item->paned = item->window = NULL;
-    item->dock = item->x = item->y = -1;
-    item->w = DEFAULT_WIDTH;
-    item->h = DEFAULT_HEIGHT;
-
-    if (! strcmp (name, _("Search Tool")))
-    {
-        item->dock = DOCK_LEFT;
-        item->w = 200;
-    }
-
-    items = g_list_append (items, item);
-    return item;
-}
-
-static int item_by_widget (Item * item, GtkWidget * widget)
-{
-    return (item->widget != widget);
-}
-
-static int item_by_name (Item * item, const char * name)
-{
-    return strcmp (item->name, name);
-}
-
-static bool_t delete_cb (GtkWidget * widget)
-{
-    layout_disable (widget);
-    return TRUE;
-}
-
-static bool_t escape_cb (GtkWidget * widget, GdkEventKey * event)
-{
-    if (event->keyval == GDK_KEY_Escape)
-    {
-        layout_disable (widget);
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-static GtkWidget * dock_get_parent (int dock)
-{
-    g_return_val_if_fail (dock >= 0 && dock < DOCKS, NULL);
-
-    for (int scan = dock; scan --; )
-    {
-        if (docks[scan])
-            return g_object_get_data ((GObject *) docks[scan], "next");
-    }
-
-    return layout;
-}
-
-static Item * item_get_prev (Item * item)
-{
-    GList * this = g_list_find (items, item);
-    g_return_val_if_fail (this, NULL);
-
-    for (GList * node = this->prev; node; node = node->prev)
-    {
-        Item * test = node->data;
-        if (test->widget && test->dock == item->dock)
-            return test;
-    }
-
-    return NULL;
-}
-
-static Item * item_get_next (Item * item)
-{
-    GList * this = g_list_find (items, item);
-    g_return_val_if_fail (this, NULL);
-
-    for (GList * node = this->next; node; node = node->next)
-    {
-        Item * test = node->data;
-        if (test->widget && test->dock == item->dock)
-            return test;
-    }
-
-    return NULL;
-}
-
-static GtkWidget * item_get_parent (Item * item)
-{
-    Item * prev = item_get_prev (item);
-    return prev ? g_object_get_data ((GObject *) prev->paned, "next") :
-     g_object_get_data ((GObject *) docks[item->dock], "mine");
-}
-
-static void item_add (Item * item)
-{
-    g_return_if_fail (item->name && item->widget && item->vbox && ! item->paned
-     && ! item->window && item->dock < DOCKS);
-
-    if (item->dock < 0)
-    {
-        item->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-        NULL_ON_DESTROY (item->window);
-
-        gtk_window_set_title ((GtkWindow *) item->window, item->name);
-        gtk_container_set_border_width ((GtkContainer *) item->window, 2);
-        gtk_window_set_has_resize_grip ((GtkWindow *) item->window, FALSE);
-
-        g_signal_connect_swapped (item->window, "delete-event", (GCallback)
-         delete_cb, item->widget);
-        g_signal_connect_swapped (item->window, "key-press-event", (GCallback)
-         escape_cb, item->widget);
-
-        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_container_add ((GtkContainer *) item->window, item->vbox);
-        gtk_widget_show_all (item->window);
-    }
-    else
-    {
-        /* Screwy logic to figure out where we need to add a GtkPaned and which
-         * widget goes in which pane of it. */
-        bool_t swap = FALSE;
-        Item * where = item;
-        GtkWidget * parent, * paned;
-
-        if (docks[item->dock])
-        {
-            if (! item_get_next (item))
-            {
-                swap = TRUE;
-                where = item_get_prev (item);
-                g_return_if_fail (where && ! where->paned);
-            }
-
-            parent = item_get_parent (where);
-            g_return_if_fail (parent);
-
-            paned = paned_new (! IS_VERTICAL (where->dock), FALSE, where->w,
-             where->h);
-            where->paned = paned;
-            NULL_ON_DESTROY (where->paned);
-        }
-        else
-        {
-            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);
-            docks[item->dock] = paned;
-            NULL_ON_DESTROY (docks[item->dock]);
-        }
-
-        GtkWidget * mine = g_object_get_data ((GObject *) paned, "mine");
-        GtkWidget * next = g_object_get_data ((GObject *) paned, "next");
-        GtkWidget * child = gtk_bin_get_child ((GtkBin *) parent);
-        g_return_if_fail (mine && next && child);
-
-        g_object_ref (child);
-        gtk_container_remove ((GtkContainer *) parent, child);
-        gtk_container_add ((GtkContainer *) parent, paned);
-        gtk_container_add ((GtkContainer *) (swap ? next : mine), item->vbox);
-        gtk_container_add ((GtkContainer *) (swap ? mine : next), child);
-        g_object_unref (child);
-    }
-}
-
-static void item_remove (Item * item)
-{
-    g_return_if_fail (item->widget && item->vbox);
-
-    if (item->dock < 0)
-    {
-        g_return_if_fail (item->window);
-        gtk_container_remove ((GtkContainer *) item->window, item->vbox);
-        gtk_widget_destroy (item->window);
-    }
-    else
-    {
-        /* Screwy logic to figure out which GtkPaned we need to remove and which
-         * pane of it has the widget we need to keep. */
-        bool_t swap = FALSE;
-        Item * where = item;
-        GtkWidget * parent, * paned;
-
-        Item * prev = item_get_prev (item);
-        if (item->paned || prev)
-        {
-            if (! item->paned)
-            {
-                swap = TRUE;
-                where = item_get_prev (item);
-                g_return_if_fail (where && where->paned);
-            }
-
-            parent = item_get_parent (where);
-            g_return_if_fail (parent);
-
-            paned = where->paned;
-        }
-        else
-        {
-            parent = dock_get_parent (item->dock);
-            g_return_if_fail (parent);
-
-            paned = docks[item->dock];
-        }
-
-        GtkWidget * mine = g_object_get_data ((GObject *) paned, "mine");
-        GtkWidget * next = g_object_get_data ((GObject *) paned, "next");
-        GtkWidget * child = gtk_bin_get_child ((GtkBin *) (swap ? mine : next));
-        g_return_if_fail (mine && next && child);
-
-        g_object_ref (child);
-        gtk_container_remove ((GtkContainer *) (swap ? next : mine), item->vbox);
-        gtk_container_remove ((GtkContainer *) (swap ? mine : next), child);
-        gtk_container_remove ((GtkContainer *) parent, paned);
-        gtk_container_add ((GtkContainer *) parent, child);
-        g_object_unref (child);
-    }
-}
-
-static void size_changed_cb (GtkWidget * widget, GdkRectangle * rect, Item * item)
-{
-    item->w = rect->width;
-    item->h = rect->height;
-
-    if (item->dock < 0)
-    {
-        g_return_if_fail (item->window);
-        gtk_window_get_position ((GtkWindow *) item->window, & item->x, & item->y);
-    }
-}
-
-void layout_add (GtkWidget * widget, const char * name)
-{
-    g_return_if_fail (layout && center && widget && name && strlen (name) <= 256
-     && ! strchr (name, '\n'));
-
-    GList * node = g_list_find_custom (items, name, (GCompareFunc) item_by_name);
-    Item * item = node ? node->data : NULL;
-
-    if (item)
-    {
-        g_return_if_fail (! item->widget && ! item->vbox && ! item->window);
-        if (item->dock >= DOCKS)
-            item->dock = -1;
-    }
-    else
-        item = item_new (name);
-
-    item->widget = widget;
-    NULL_ON_DESTROY (item->widget);
-    item->vbox = vbox_new (widget, name);
-    NULL_ON_DESTROY (item->vbox);
-
-    g_signal_connect (item->vbox, "size-allocate", (GCallback) size_changed_cb, item);
-
-    item_add (item);
-}
-
-static void layout_move (GtkWidget * widget, int dock)
-{
-    g_return_if_fail (layout && center && widget && dock < DOCKS);
-
-    GList * node = g_list_find_custom (items, widget, (GCompareFunc) item_by_widget);
-    g_return_if_fail (node && node->data);
-    Item * item = node->data;
-
-    g_return_if_fail (item->vbox);
-    g_object_ref (item->vbox);
-
-    item_remove (item);
-    items = g_list_remove_link (items, node);
-    item->dock = dock;
-    items = g_list_concat (items, node);
-    item_add (item);
-
-    g_object_unref (item->vbox);
-}
-
-void layout_remove (GtkWidget * widget)
-{
-    g_return_if_fail (layout && center && widget);
-
-    /* menu may hold pointers to this widget */
-    if (menu)
-        gtk_widget_destroy (menu);
-
-    GList * node = g_list_find_custom (items, widget, (GCompareFunc) item_by_widget);
-    g_return_if_fail (node && node->data);
-    Item * item = node->data;
-
-    item_remove (item);
-    g_return_if_fail (! item->widget && ! item->vbox && ! item->window);
-}
-
-void layout_save (void)
-{
-    int i = 0;
-
-    for (GList * node = items; node; node = node->next)
-    {
-        Item * item = node->data;
-        g_return_if_fail (item && item->name);
-
-        char key[16], value[64];
-
-        snprintf (key, sizeof key, "item%d_name", i);
-        aud_set_str ("gtkui-layout", key, item->name);
-
-        snprintf (key, sizeof key, "item%d_pos", i);
-        snprintf (value, sizeof value, "%d,%d,%d,%d,%d", item->dock, item->x,
-         item->y, item->w, item->h);
-        aud_set_str ("gtkui-layout", key, value);
-
-        i ++;
-    }
-
-    aud_set_int ("gtkui-layout", "item_count", i);
-}
-
-void layout_load (void)
-{
-    g_return_if_fail (! items);
-
-    int count = aud_get_int ("gtkui-layout", "item_count");
-
-    for (int i = 0; i < count; i ++)
-    {
-        char key[16];
-
-        snprintf (key, sizeof key, "item%d_name", i);
-        char * name = aud_get_str ("gtkui-layout", key);
-        Item * item = item_new (name);
-        str_unref (name);
-
-        snprintf (key, sizeof key, "item%d_pos", i);
-        char * pos = aud_get_str ("gtkui-layout", key);
-        sscanf (pos, "%d,%d,%d,%d,%d", & item->dock, & item->x, & item->y, & item->w, & item->h);
-        str_unref (pos);
-    }
-}
-
-void layout_cleanup (void)
-{
-    for (GList * node = items; node; node = node->next)
-    {
-        Item * item = node->data;
-        g_return_if_fail (item && ! item->widget && ! item->vbox && ! item->window);
-        str_unref (item->name);
-        g_slice_free (Item, item);
-    }
-
-    g_list_free (items);
-    items = NULL;
-}
diff --git a/src/gtkui/layout.cc b/src/gtkui/layout.cc
new file mode 100644
index 000000000000..3619ea236d4c
--- /dev/null
+++ b/src/gtkui/layout.cc
@@ -0,0 +1,616 @@
+/*
+ * layout.c
+ * Copyright 2011 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 <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugins.h>
+
+#include "layout.h"
+
+#define DEFAULT_WIDTH 300
+#define DEFAULT_HEIGHT 200
+
+enum {
+    DOCK_LEFT,
+    DOCK_RIGHT,
+    DOCK_TOP,
+    DOCK_BOTTOM,
+    DOCKS
+};
+
+#define IS_VERTICAL(d) ((d) & 2)
+#define IS_AFTER(d) ((d) & 1)
+
+#define NULL_ON_DESTROY(w) g_signal_connect ((w), "destroy", (GCallback) \
+ gtk_widget_destroyed, & (w))
+
+typedef struct {
+    String name;
+    PluginHandle * plugin;
+    GtkWidget * widget, * vbox, * paned, * window;
+    int dock, x, y, w, h;
+} Item;
+
+static GList * items = nullptr;
+
+static GtkWidget * layout = nullptr;
+static GtkWidget * center = nullptr;
+static GtkWidget * docks[DOCKS] = {nullptr, nullptr, nullptr, nullptr};
+static GtkWidget * menu = nullptr;
+
+static Item * item_new (const char * name)
+{
+    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;
+
+    if (! strcmp (name, _("Search Tool")))
+    {
+        item->dock = DOCK_LEFT;
+        item->w = 200;
+    }
+
+    items = g_list_append (items, item);
+    return item;
+}
+
+static int item_by_plugin (Item * item, PluginHandle * plugin)
+{
+    return (item->plugin != plugin);
+}
+
+static int item_by_widget (Item * item, GtkWidget * widget)
+{
+    return (item->widget != widget);
+}
+
+static int item_by_name (Item * item, const char * name)
+{
+    return strcmp (item->name, name);
+}
+
+GtkWidget * layout_new ()
+{
+    g_return_val_if_fail (! layout, nullptr);
+    layout = gtk_alignment_new (0, 0, 1, 1);
+    gtk_alignment_set_padding ((GtkAlignment *) layout, 3, 3, 3, 3);
+    NULL_ON_DESTROY (layout);
+    return layout;
+}
+
+void layout_add_center (GtkWidget * widget)
+{
+    g_return_if_fail (layout && ! center && widget);
+    center = widget;
+    gtk_container_add ((GtkContainer *) layout, center);
+    NULL_ON_DESTROY (center);
+}
+
+static void layout_move (GtkWidget * widget, int dock);
+
+static void layout_dock_left (GtkWidget * widget)
+{
+    layout_move (widget, DOCK_LEFT);
+}
+
+static void layout_dock_right (GtkWidget * widget)
+{
+    layout_move (widget, DOCK_RIGHT);
+}
+
+static void layout_dock_top (GtkWidget * widget)
+{
+    layout_move (widget, DOCK_TOP);
+}
+
+static void layout_dock_bottom (GtkWidget * widget)
+{
+    layout_move (widget, DOCK_BOTTOM);
+}
+
+static void layout_undock (GtkWidget * widget)
+{
+    layout_move (widget, -1);
+}
+
+static void layout_disable (GtkWidget * widget)
+{
+    g_return_if_fail (layout && center && widget);
+
+    GList * node = g_list_find_custom (items, widget, (GCompareFunc) item_by_widget);
+    g_return_if_fail (node);
+
+    Item * item = (Item *) node->data;
+    g_return_if_fail (item->plugin);
+
+    aud_plugin_enable (item->plugin, false);
+}
+
+static gboolean menu_cb (GtkWidget * widget, GdkEventButton * event)
+{
+    g_return_val_if_fail (widget && event, false);
+
+    if (event->type != GDK_BUTTON_PRESS || event->button != 3)
+        return false;
+
+    if (menu)
+        gtk_widget_destroy (menu);
+
+    menu = gtk_menu_new ();
+    g_signal_connect (menu, "destroy", (GCallback) gtk_widget_destroyed, & menu);
+
+    const char * names[6] = {N_("Dock at Left"), N_("Dock at Right"),
+     N_("Dock at Top"), N_("Dock at Bottom"), N_("Undock"), N_("Disable")};
+    void (* const funcs[6]) (GtkWidget * widget) = {layout_dock_left,
+     layout_dock_right, layout_dock_top, layout_dock_bottom, layout_undock,
+     layout_disable};
+
+    for (int i = 0; i < 6; i ++)
+    {
+        GtkWidget * item = gtk_menu_item_new_with_label (_(names[i]));
+        gtk_menu_shell_append ((GtkMenuShell *) menu, item);
+        g_signal_connect_swapped (item, "activate", (GCallback) funcs[i], widget);
+    }
+
+    gtk_widget_show_all (menu);
+    gtk_menu_popup ((GtkMenu *) menu, nullptr, nullptr, nullptr, nullptr, event->button, event->time);
+
+    return true;
+}
+
+static GtkWidget * vbox_new (GtkWidget * widget, const char * name)
+{
+    g_return_val_if_fail (widget && name, nullptr);
+
+    GtkWidget * vbox = gtk_vbox_new (false, 2);
+
+    GtkWidget * ebox = gtk_event_box_new ();
+    gtk_box_pack_start ((GtkBox *) vbox, ebox, false, false, 0);
+    g_signal_connect_swapped (ebox, "button-press-event", (GCallback) menu_cb,
+     widget);
+
+    GtkWidget * label = gtk_label_new (nullptr);
+    char * markup = g_markup_printf_escaped ("<small><b>%s</b></small>", name);
+    gtk_label_set_markup ((GtkLabel *) label, markup);
+    g_free (markup);
+    gtk_misc_set_alignment ((GtkMisc *) label, 0, 0);
+    gtk_container_add ((GtkContainer *) ebox, label);
+
+    gtk_box_pack_start ((GtkBox *) vbox, widget, true, true, 0);
+
+    gtk_widget_show_all (vbox);
+
+    return vbox;
+}
+
+typedef struct {
+    GtkWidget * paned;
+    GtkWidget * widget;
+    bool vertical;
+    int w, h;
+} RestoreSizeData;
+
+static gboolean restore_size_cb (RestoreSizeData * d)
+{
+    GtkAllocation rect;
+    gtk_widget_get_allocation (d->widget, & rect);
+    int pos = gtk_paned_get_position ((GtkPaned *) d->paned);
+    pos -= d->vertical ? d->h - rect.height : d->w - rect.width;
+    gtk_paned_set_position ((GtkPaned *) d->paned, pos);
+
+    g_slice_free (RestoreSizeData, d);
+    return false;
+}
+
+static GtkWidget * paned_new (bool vertical, bool after, int w, int h)
+{
+    GtkWidget * paned = vertical ? gtk_vpaned_new () : gtk_hpaned_new ();
+
+    GtkWidget * mine = gtk_alignment_new (0, 0, 1, 1);
+    GtkWidget * next = gtk_alignment_new (0, 0, 1, 1);
+    gtk_paned_pack1 ((GtkPaned *) paned, after ? next : mine, after, false);
+    gtk_paned_pack2 ((GtkPaned *) paned, after ? mine : next, ! after, false);
+
+    g_object_set_data ((GObject *) paned, "mine", mine);
+    g_object_set_data ((GObject *) paned, "next", next);
+
+    gtk_widget_show_all (paned);
+
+    if (vertical ? h : w)
+    {
+        if (after)
+        {
+            /* hack to set the size of the second pane */
+            RestoreSizeData * d = g_slice_new (RestoreSizeData);
+            d->paned = paned;
+            d->widget = mine;
+            d->vertical = vertical;
+            d->w = w;
+            d->h = h;
+            g_idle_add ((GSourceFunc) restore_size_cb, d);
+        }
+        else
+            gtk_paned_set_position ((GtkPaned *) paned, vertical ? h : w);
+    }
+
+    return paned;
+}
+
+static gboolean delete_cb (GtkWidget * widget)
+{
+    layout_disable (widget);
+    return true;
+}
+
+static gboolean escape_cb (GtkWidget * widget, GdkEventKey * event)
+{
+    if (event->keyval == GDK_KEY_Escape)
+    {
+        layout_disable (widget);
+        return true;
+    }
+
+    return false;
+}
+
+static GtkWidget * dock_get_parent (int dock)
+{
+    g_return_val_if_fail (dock >= 0 && dock < DOCKS, nullptr);
+
+    for (int scan = dock; scan --; )
+    {
+        if (docks[scan])
+            return (GtkWidget *) g_object_get_data ((GObject *) docks[scan], "next");
+    }
+
+    return layout;
+}
+
+static Item * item_get_prev (Item * item)
+{
+    GList * node = g_list_find (items, item);
+    g_return_val_if_fail (node, nullptr);
+
+    while ((node = node->prev))
+    {
+        Item * test = (Item *) node->data;
+        if (test->widget && test->dock == item->dock)
+            return test;
+    }
+
+    return nullptr;
+}
+
+static Item * item_get_next (Item * item)
+{
+    GList * node = g_list_find (items, item);
+    g_return_val_if_fail (node, nullptr);
+
+    while ((node = node->next))
+    {
+        Item * test = (Item *) node->data;
+        if (test->widget && test->dock == item->dock)
+            return test;
+    }
+
+    return nullptr;
+}
+
+static GtkWidget * item_get_parent (Item * item)
+{
+    Item * prev = item_get_prev (item);
+
+    if (prev)
+        return (GtkWidget *) g_object_get_data ((GObject *) prev->paned, "next");
+    else
+        return (GtkWidget *) g_object_get_data ((GObject *) docks[item->dock], "mine");
+}
+
+static void item_add (Item * item)
+{
+    g_return_if_fail (item->name && item->widget && item->vbox && ! item->paned
+     && ! item->window && item->dock < DOCKS);
+
+    if (item->dock < 0)
+    {
+        item->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+        NULL_ON_DESTROY (item->window);
+
+        gtk_window_set_title ((GtkWindow *) item->window, item->name);
+        gtk_container_set_border_width ((GtkContainer *) item->window, 2);
+
+        g_signal_connect_swapped (item->window, "delete-event", (GCallback)
+         delete_cb, item->widget);
+        g_signal_connect_swapped (item->window, "key-press-event", (GCallback)
+         escape_cb, item->widget);
+
+        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_container_add ((GtkContainer *) item->window, item->vbox);
+        gtk_widget_show_all (item->window);
+    }
+    else
+    {
+        /* Screwy logic to figure out where we need to add a GtkPaned and which
+         * widget goes in which pane of it. */
+        bool swap = false;
+        Item * where = item;
+        GtkWidget * parent, * paned;
+
+        if (docks[item->dock])
+        {
+            if (! item_get_next (item))
+            {
+                swap = true;
+                where = item_get_prev (item);
+                g_return_if_fail (where && ! where->paned);
+            }
+
+            parent = item_get_parent (where);
+            g_return_if_fail (parent);
+
+            paned = paned_new (! IS_VERTICAL (where->dock), false, where->w,
+             where->h);
+            where->paned = paned;
+            NULL_ON_DESTROY (where->paned);
+        }
+        else
+        {
+            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);
+            docks[item->dock] = paned;
+            NULL_ON_DESTROY (docks[item->dock]);
+        }
+
+        GtkWidget * mine = (GtkWidget *) g_object_get_data ((GObject *) paned, "mine");
+        GtkWidget * next = (GtkWidget *) g_object_get_data ((GObject *) paned, "next");
+        GtkWidget * child = gtk_bin_get_child ((GtkBin *) parent);
+        g_return_if_fail (mine && next && child);
+
+        g_object_ref (child);
+        gtk_container_remove ((GtkContainer *) parent, child);
+        gtk_container_add ((GtkContainer *) parent, paned);
+        gtk_container_add ((GtkContainer *) (swap ? next : mine), item->vbox);
+        gtk_container_add ((GtkContainer *) (swap ? mine : next), child);
+        g_object_unref (child);
+    }
+}
+
+static void item_remove (Item * item)
+{
+    g_return_if_fail (item->widget && item->vbox);
+
+    if (item->dock < 0)
+    {
+        g_return_if_fail (item->window);
+        gtk_container_remove ((GtkContainer *) item->window, item->vbox);
+        gtk_widget_destroy (item->window);
+    }
+    else
+    {
+        /* Screwy logic to figure out which GtkPaned we need to remove and which
+         * pane of it has the widget we need to keep. */
+        bool swap = false;
+        Item * where = item;
+        GtkWidget * parent, * paned;
+
+        Item * prev = item_get_prev (item);
+        if (item->paned || prev)
+        {
+            if (! item->paned)
+            {
+                swap = true;
+                where = item_get_prev (item);
+                g_return_if_fail (where && where->paned);
+            }
+
+            parent = item_get_parent (where);
+            g_return_if_fail (parent);
+
+            paned = where->paned;
+        }
+        else
+        {
+            parent = dock_get_parent (item->dock);
+            g_return_if_fail (parent);
+
+            paned = docks[item->dock];
+        }
+
+        GtkWidget * mine = (GtkWidget *) g_object_get_data ((GObject *) paned, "mine");
+        GtkWidget * next = (GtkWidget *) g_object_get_data ((GObject *) paned, "next");
+        GtkWidget * child = gtk_bin_get_child ((GtkBin *) (swap ? mine : next));
+        g_return_if_fail (mine && next && child);
+
+        g_object_ref (child);
+        gtk_container_remove ((GtkContainer *) (swap ? next : mine), item->vbox);
+        gtk_container_remove ((GtkContainer *) (swap ? mine : next), child);
+        gtk_container_remove ((GtkContainer *) parent, paned);
+        gtk_container_add ((GtkContainer *) parent, child);
+        g_object_unref (child);
+    }
+}
+
+static void size_changed_cb (GtkWidget * widget, GdkRectangle * rect, Item * item)
+{
+    item->w = rect->width;
+    item->h = rect->height;
+
+    if (item->dock < 0)
+    {
+        g_return_if_fail (item->window);
+        gtk_window_get_position ((GtkWindow *) item->window, & item->x, & item->y);
+    }
+}
+
+void layout_add (PluginHandle * plugin, GtkWidget * widget)
+{
+    g_return_if_fail (layout && center && plugin && widget);
+
+    const char * name = aud_plugin_get_name (plugin);
+    g_return_if_fail (name);
+
+    GList * node = g_list_find_custom (items, name, (GCompareFunc) item_by_name);
+    Item * item = node ? (Item *) node->data : nullptr;
+
+    if (item)
+    {
+        g_return_if_fail (! item->widget && ! item->vbox && ! item->window);
+        if (item->dock >= DOCKS)
+            item->dock = -1;
+    }
+    else
+        item = item_new (name);
+
+    item->plugin = plugin;
+    item->widget = widget;
+    NULL_ON_DESTROY (item->widget);
+    item->vbox = vbox_new (widget, name);
+    NULL_ON_DESTROY (item->vbox);
+
+    g_signal_connect (item->vbox, "size-allocate", (GCallback) size_changed_cb, item);
+
+    item_add (item);
+}
+
+static void layout_move (GtkWidget * widget, int dock)
+{
+    g_return_if_fail (layout && center && widget && dock < DOCKS);
+
+    GList * node = g_list_find_custom (items, widget, (GCompareFunc) item_by_widget);
+    g_return_if_fail (node);
+    Item * item = (Item *) node->data;
+
+    g_return_if_fail (item->vbox);
+    g_object_ref (item->vbox);
+
+    item_remove (item);
+    items = g_list_remove_link (items, node);
+    item->dock = dock;
+    items = g_list_concat (items, node);
+    item_add (item);
+
+    g_object_unref (item->vbox);
+}
+
+void layout_remove (PluginHandle * plugin)
+{
+    g_return_if_fail (layout && center && plugin);
+
+    GList * node = g_list_find_custom (items, plugin, (GCompareFunc) item_by_plugin);
+    if (! node)
+        return;
+
+    /* menu may hold pointers to this widget */
+    if (menu)
+        gtk_widget_destroy (menu);
+
+    item_remove ((Item *) node->data);
+}
+
+void layout_focus (PluginHandle * plugin)
+{
+    g_return_if_fail (layout && center && plugin);
+
+    GList * node = g_list_find_custom (items, plugin, (GCompareFunc) item_by_plugin);
+    if (! node)
+        return;
+
+    Item * item = (Item *) node->data;
+    g_return_if_fail (item);
+
+    if (item->window)
+        gtk_window_present ((GtkWindow *) item->window);
+
+    aud_plugin_send_message (plugin, "grab focus", nullptr, 0);
+}
+
+void layout_save ()
+{
+    int i = 0;
+
+    for (GList * node = items; node; node = node->next)
+    {
+        Item * item = (Item *) node->data;
+        g_return_if_fail (item && item->name);
+
+        char key[16], value[64];
+
+        snprintf (key, sizeof key, "item%d_name", i);
+        aud_set_str ("gtkui-layout", key, item->name);
+
+        snprintf (key, sizeof key, "item%d_pos", i);
+        snprintf (value, sizeof value, "%d,%d,%d,%d,%d", item->dock, item->x,
+         item->y, item->w, item->h);
+        aud_set_str ("gtkui-layout", key, value);
+
+        i ++;
+    }
+
+    aud_set_int ("gtkui-layout", "item_count", i);
+}
+
+void layout_load ()
+{
+    g_return_if_fail (! items);
+
+    int count = aud_get_int ("gtkui-layout", "item_count");
+
+    for (int i = 0; i < count; i ++)
+    {
+        char key[16];
+
+        snprintf (key, sizeof key, "item%d_name", i);
+        String name = aud_get_str ("gtkui-layout", key);
+        Item * item = item_new (name);
+
+        snprintf (key, sizeof key, "item%d_pos", i);
+        String pos = aud_get_str ("gtkui-layout", key);
+        sscanf (pos, "%d,%d,%d,%d,%d", & item->dock, & item->x, & item->y, & item->w, & item->h);
+    }
+}
+
+void layout_cleanup ()
+{
+    for (GList * node = items; node; node = node->next)
+    {
+        Item * item = (Item *) node->data;
+        g_return_if_fail (! item->widget && ! item->vbox && ! item->window);
+        delete item;
+    }
+
+    g_list_free (items);
+    items = nullptr;
+}
diff --git a/src/gtkui/layout.h b/src/gtkui/layout.h
index eb6494583c93..e2a8b67743de 100644
--- a/src/gtkui/layout.h
+++ b/src/gtkui/layout.h
@@ -22,13 +22,14 @@
 
 #include <gtk/gtk.h>
 
-void layout_load (void);
-void layout_save (void);
-void layout_cleanup (void);
+void layout_load ();
+void layout_save ();
+void layout_cleanup ();
 
-GtkWidget * layout_new (void);
-void layout_add_center (GtkWidget * add);
-void layout_add (GtkWidget * add, const char * name);
-void layout_remove (GtkWidget * rem);
+GtkWidget * layout_new ();
+void layout_add_center (GtkWidget * widget);
+void layout_add (PluginHandle * plugin, GtkWidget * widget);
+void layout_remove (PluginHandle * plugin);
+void layout_focus (PluginHandle * plugin);
 
 #endif
diff --git a/src/gtkui/menus.c b/src/gtkui/menus.c
deleted file mode 100644
index 75eb36a9118f..000000000000
--- a/src/gtkui/menus.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * menus.c
- * Copyright 2011-2014 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 <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/menu.h>
-
-#include "gtkui.h"
-#include "playlist_util.h"
-#include "ui_playlist_notebook.h"
-#include "ui_playlist_widget.h"
-
-#define SHIFT GDK_SHIFT_MASK
-#define CTRL GDK_CONTROL_MASK
-#define ALT GDK_MOD1_MASK
-
-int menu_tab_playlist_id = -1; /* should really be stored in the menu somehow */
-
-static void open_files (void) {audgui_run_filebrowser (TRUE); }
-static void open_url (void) {audgui_show_add_url_window (TRUE); }
-static void add_files (void) {audgui_run_filebrowser (FALSE); }
-static void add_url (void) {audgui_show_add_url_window (FALSE); }
-
-static void configure_effects (void) {aud_show_prefs_for_plugin_type (PLUGIN_TYPE_EFFECT); }
-static void configure_visualizations (void) {aud_show_prefs_for_plugin_type (PLUGIN_TYPE_VIS); }
-
-static void pl_sort_track (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_TRACK); }
-static void pl_sort_title (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_TITLE); }
-static void pl_sort_artist (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_ARTIST); }
-static void pl_sort_album (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_ALBUM); }
-static void pl_sort_date (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_DATE); }
-static void pl_sort_length (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_LENGTH); }
-static void pl_sort_path (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_PATH); }
-static void pl_sort_custom (void) {aud_playlist_sort_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_FORMATTED_TITLE); }
-static void pl_reverse (void) {aud_playlist_reverse (aud_playlist_get_active ()); }
-static void pl_random (void) {aud_playlist_randomize (aud_playlist_get_active ()); }
-
-static void pl_sort_selected_track (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_TRACK); }
-static void pl_sort_selected_title (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_TITLE); }
-static void pl_sort_selected_artist (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_ARTIST); }
-static void pl_sort_selected_album (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_ALBUM); }
-static void pl_sort_selected_date (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_DATE); }
-static void pl_sort_selected_length (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_LENGTH); }
-static void pl_sort_selected_path (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_PATH); }
-static void pl_sort_selected_custom (void) {aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_FORMATTED_TITLE); }
-static void pl_reverse_selected (void) {aud_playlist_reverse_selected (aud_playlist_get_active ()); }
-static void pl_random_selected (void) {aud_playlist_randomize_selected (aud_playlist_get_active ()); }
-
-static void pl_new (void)
-{
-    aud_playlist_insert (-1);
-    aud_playlist_set_active (aud_playlist_count () - 1);
-}
-
-static void pl_play (void) {aud_drct_play_playlist (aud_playlist_get_active ()); }
-static void pl_refresh (void) {aud_playlist_rescan (aud_playlist_get_active ()); }
-static void pl_remove_failed (void) {aud_playlist_remove_failed (aud_playlist_get_active ()); }
-static void pl_remove_dupes_by_title (void) {aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_TITLE); }
-static void pl_remove_dupes_by_filename (void) {aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_FILENAME); }
-static void pl_remove_dupes_by_path (void) {aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), PLAYLIST_SORT_PATH); }
-static void pl_rename (void) {start_rename_playlist (aud_playlist_get_active ()); }
-static void pl_close (void) {audgui_confirm_playlist_delete (aud_playlist_get_active ()); }
-static void pl_refresh_sel (void) {aud_playlist_rescan_selected (aud_playlist_get_active ()); }
-static void pl_select_all (void) {aud_playlist_select_all (aud_playlist_get_active (), TRUE); }
-
-static void pl_tab_play (void)
-{
-    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
-    if (playlist >= 0)
-        aud_drct_play_playlist (playlist);
-}
-
-static void pl_tab_rename (void)
-{
-    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
-    if (playlist >= 0)
-        start_rename_playlist (playlist);
-}
-
-static void pl_tab_close (void)
-{
-    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
-    if (playlist >= 0)
-        audgui_confirm_playlist_delete (playlist);
-}
-
-static GtkWidget * get_services_main (void) {return aud_get_plugin_menu (AUD_MENU_MAIN); }
-static GtkWidget * get_services_pl (void) {return aud_get_plugin_menu (AUD_MENU_PLAYLIST); }
-
-static void volume_up (void)
-{
-    int vol = 0;
-    aud_drct_get_volume_main (& vol);
-    aud_drct_set_volume_main (vol + 5);
-}
-
-static void volume_down (void)
-{
-    int vol = 0;
-    aud_drct_get_volume_main (& vol);
-    aud_drct_set_volume_main (vol - 5);
-}
-
-static const AudguiMenuItem file_items[] = {
- {N_("_Open Files ..."), "document-open", 'o', CTRL, .func = open_files},
- {N_("Open _URL ..."), "folder-remote", 'l', CTRL, .func = open_url},
- {N_("_Add Files ..."), "list-add", 'o', SHIFT | CTRL, .func = add_files},
- {N_("Add U_RL ..."), "folder-remote", 'l', SHIFT | CTRL, .func = add_url},
- {.sep = TRUE},
- {N_("Search _Library"), "edit-find", 'y', CTRL, .func = activate_search_tool},
- {.sep = TRUE},
- {N_("A_bout ..."), "help-about", .func = audgui_show_about_window},
- {N_("_Settings ..."), "preferences-system", .func = aud_show_prefs_window},
- {N_("_Quit"), "application-exit", 'q', CTRL, .func = aud_drct_quit}};
-
-static const AudguiMenuItem playback_items[] = {
- {N_("_Play"), "media-playback-start", GDK_KEY_Return, CTRL, .func = aud_drct_play},
- {N_("Paus_e"), "media-playback-pause", ',', CTRL, .func = aud_drct_pause},
- {N_("_Stop"), "media-playback-stop", '.', CTRL, .func = aud_drct_stop},
- {N_("Pre_vious"), "media-skip-backward", GDK_KEY_Up, ALT, .func = aud_drct_pl_prev},
- {N_("_Next"), "media-skip-forward", GDK_KEY_Down, ALT, .func = aud_drct_pl_next},
- {.sep = TRUE},
- {N_("_Repeat"), NULL, 'r', CTRL, .cname = "repeat", .hook = "set repeat"},
- {N_("S_huffle"), NULL, 's', CTRL, .cname = "shuffle", .hook = "set shuffle"},
- {N_("N_o Playlist Advance"), NULL, 'n', CTRL,
-  .cname = "no_playlist_advance", .hook = "set no_playlist_advance"},
- {N_("Stop A_fter This Song"), NULL, 'm', CTRL,
-  .cname = "stop_after_current_song", .hook = "set stop_after_current_song"},
- {.sep = TRUE},
- {N_("Song _Info ..."), "dialog-information", 'i', CTRL, .func = audgui_infowin_show_current},
- {N_("Jump to _Time ..."), "go-jump", 'k', CTRL, .func = audgui_jump_to_time},
- {N_("_Jump to Song ..."), "go-jump", 'j', CTRL, .func = audgui_jump_to_track},
- {.sep = TRUE},
- {N_("Set Repeat Point _A"), NULL, '1', CTRL, .func = set_ab_repeat_a},
- {N_("Set Repeat Point _B"), NULL, '2', CTRL, .func = set_ab_repeat_b},
- {N_("_Clear Repeat Points"), NULL, '3', CTRL, .func = clear_ab_repeat}};
-
-static const AudguiMenuItem dupe_items[] = {
- {N_("By _Title"), .func = pl_remove_dupes_by_title},
- {N_("By _Filename"), .func = pl_remove_dupes_by_filename},
- {N_("By File _Path"), .func = pl_remove_dupes_by_path}};
-
-static const AudguiMenuItem sort_items[] = {
- {N_("By Track _Number"), .func = pl_sort_track},
- {N_("By _Title"), .func = pl_sort_title},
- {N_("By _Artist"), .func = pl_sort_artist},
- {N_("By Al_bum"), .func = pl_sort_album},
- {N_("By Release _Date"), .func = pl_sort_date},
- {N_("By _Length"), .func = pl_sort_length},
- {N_("By _File Path"), .func = pl_sort_path},
- {N_("By _Custom Title"), .func = pl_sort_custom},
- {.sep = TRUE},
- {N_("R_everse Order"), "view-sort-descending", .func = pl_reverse},
- {N_("_Random Order"), .func = pl_random}};
-
- static const AudguiMenuItem sort_selected_items[] = {
- {N_("By Track _Number"), .func = pl_sort_selected_track},
- {N_("By _Title"), .func = pl_sort_selected_title},
- {N_("By _Artist"), .func = pl_sort_selected_artist},
- {N_("By Al_bum"), .func = pl_sort_selected_album},
- {N_("By Release _Date"), .func = pl_sort_selected_date},
- {N_("By _Length"), .func = pl_sort_selected_length},
- {N_("By _File Path"), .func = pl_sort_selected_path},
- {N_("By _Custom Title"), .func = pl_sort_selected_custom},
- {.sep = TRUE},
- {N_("R_everse Order"), "view-sort-descending", .func = pl_reverse_selected},
- {N_("_Random Order"), .func = pl_random_selected}};
-
-static const AudguiMenuItem playlist_items[] = {
- {N_("_Play This Playlist"), "media-playback-start", GDK_KEY_Return, SHIFT, .func = pl_play},
- {N_("_Refresh"), "view-refresh", GDK_KEY_F5, .func = pl_refresh},
- {.sep = TRUE},
- {N_("_Sort"), "view-sort-ascending", .items = sort_items, ARRAY_LEN (sort_items)},
- {N_("Sort Se_lected"), "view-sort-ascending", .items = sort_selected_items, ARRAY_LEN (sort_selected_items)},
- {N_("Remove _Duplicates"), "edit-copy", .items = dupe_items, ARRAY_LEN (dupe_items)},
- {N_("Remove _Unavailable Files"), "dialog-warning", .func = pl_remove_failed},
- {.sep = TRUE},
- {N_("_New"), "document-new", 't', CTRL, .func = pl_new},
- {N_("Ren_ame ..."), "insert-text", GDK_KEY_F2, .func = pl_rename},
- {N_("Remo_ve"), "edit-delete", 'w', CTRL, .func = pl_close},
- {.sep = TRUE},
- {N_("_Import ..."), "document-open", .func = audgui_import_playlist},
- {N_("_Export ..."), "document-save", .func = audgui_export_playlist},
- {.sep = TRUE},
- {N_("Playlist _Manager ..."), "audio-x-generic", 'p', CTRL, .func = audgui_playlist_manager},
- {N_("_Queue Manager ..."), NULL, 'u', CTRL, .func = audgui_queue_manager_show}};
-
-static const AudguiMenuItem output_items[] = {
- {N_("Volume _Up"), "audio-volume-high", '+', CTRL, .func = volume_up},
- {N_("Volume _Down"), "audio-volume-low", '-', CTRL, .func = volume_down},
- {.sep = TRUE},
- {N_("_Equalizer"), "multimedia-volume-control", 'e', CTRL, .func = audgui_show_equalizer_window},
- {.sep = TRUE},
- {N_("E_ffects ..."), .func = configure_effects}};
-
-static const AudguiMenuItem view_items[] = {
- {N_("Show _Menu Bar"), NULL, 'm', SHIFT | CTRL,
-  .csect = "gtkui", "menu_visible", .func = show_hide_menu},
- {N_("Show I_nfo Bar"), NULL, 'i', SHIFT | CTRL,
-  .csect = "gtkui", "infoarea_visible", .func = show_hide_infoarea},
- {N_("Show Info Bar Vis_ualization"),
-  .csect = "gtkui", "infoarea_show_vis", .func = show_hide_infoarea_vis},
- {N_("Show _Status Bar"), NULL, 's', SHIFT | CTRL,
-  .csect = "gtkui", "statusbar_visible", .func = show_hide_statusbar},
- {.sep = TRUE},
- {N_("Show _Remaining Time"), NULL, 'r', SHIFT | CTRL,
-  .csect = "gtkui", "show_remaining_time"},
- {.sep = TRUE},
- {N_("_Visualizations ..."), .func = configure_visualizations}};
-
-static const AudguiMenuItem main_items[] = {
- {N_("_File"), .items = file_items, ARRAY_LEN (file_items)},
- {N_("_Playback"), .items = playback_items, ARRAY_LEN (playback_items)},
- {N_("P_laylist"), .items = playlist_items, ARRAY_LEN (playlist_items)},
- {N_("_Services"), .get_sub = get_services_main},
- {N_("_Output"), .items = output_items, ARRAY_LEN (output_items)},
- {N_("_View"), .items = view_items, ARRAY_LEN (view_items)}};
-
-static const AudguiMenuItem rclick_items[] = {
- {N_("Song _Info ..."), "dialog-information", 'i', ALT, .func = playlist_song_info},
- {N_("_Queue/Unqueue"), NULL, 'q', ALT, .func = playlist_queue_toggle},
- {N_("_Refresh"), "view-refresh", GDK_KEY_F6, .func = pl_refresh_sel},
- {.sep = TRUE},
- {N_("Cu_t"), "edit-cut", .func = playlist_cut},
- {N_("_Copy"), "edit-copy", .func = playlist_copy},
- {N_("_Paste"), "edit-paste", .func = playlist_paste},
- {N_("Select _All"), "edit-select-all", .func = pl_select_all},
- {.sep = TRUE},
- {N_("_Services"), .get_sub = get_services_pl}};
-
-static const AudguiMenuItem tab_items[] = {
- {N_("_Play"), "media-playback-start", .func = pl_tab_play},
- {N_("_Rename ..."), "insert-text", .func = pl_tab_rename},
- {N_("Remo_ve"), "edit-delete", .func = pl_tab_close}};
-
-
-GtkWidget * make_menu_bar (GtkAccelGroup * accel)
-{
-    GtkWidget * bar = gtk_menu_bar_new ();
-    audgui_menu_init (bar, main_items, ARRAY_LEN (main_items), accel);
-    return bar;
-}
-
-GtkWidget * make_menu_main (GtkAccelGroup * accel)
-{
-    GtkWidget * shell = gtk_menu_new ();
-    audgui_menu_init (shell, main_items, ARRAY_LEN (main_items), accel);
-    return shell;
-}
-
-GtkWidget * make_menu_rclick (GtkAccelGroup * accel)
-{
-    GtkWidget * shell = gtk_menu_new ();
-    audgui_menu_init (shell, rclick_items, ARRAY_LEN (rclick_items), accel);
-    return shell;
-}
-
-GtkWidget * make_menu_tab (GtkAccelGroup * accel)
-{
-    GtkWidget * shell = gtk_menu_new ();
-    audgui_menu_init (shell, tab_items, ARRAY_LEN (tab_items), accel);
-    return shell;
-}
diff --git a/src/gtkui/menus.cc b/src/gtkui/menus.cc
new file mode 100644
index 000000000000..553158c16237
--- /dev/null
+++ b/src/gtkui/menus.cc
@@ -0,0 +1,293 @@
+/*
+ * menus.c
+ * Copyright 2011-2014 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 <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/drct.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>
+#include <libaudgui/menu.h>
+
+#include "gtkui.h"
+#include "playlist_util.h"
+#include "ui_playlist_notebook.h"
+#include "ui_playlist_widget.h"
+
+#define SHIFT GDK_SHIFT_MASK
+#define CTRL GDK_CONTROL_MASK
+#define ALT GDK_MOD1_MASK
+
+#define SHIFT_CTRL (GdkModifierType) (SHIFT | CTRL)
+#define NONE       0, (GdkModifierType) 0
+
+int menu_tab_playlist_id = -1; /* should really be stored in the menu somehow */
+
+static void open_files () { audgui_run_filebrowser (true); }
+static void open_url () { audgui_show_add_url_window (true); }
+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_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); }
+static void pl_sort_title () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Title); }
+static void pl_sort_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Artist); }
+static void pl_sort_album () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Album); }
+static void pl_sort_album_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::AlbumArtist); }
+static void pl_sort_date () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Date); }
+static void pl_sort_genre () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Genre); }
+static void pl_sort_length () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Length); }
+static void pl_sort_path () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+static void pl_sort_custom () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::FormattedTitle); }
+static void pl_reverse () { aud_playlist_reverse (aud_playlist_get_active ()); }
+static void pl_random () { aud_playlist_randomize (aud_playlist_get_active ()); }
+
+static void pl_sort_selected_track () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Track); }
+static void pl_sort_selected_title () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Title); }
+static void pl_sort_selected_artist () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Artist); }
+static void pl_sort_selected_album () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Album); }
+static void pl_sort_selected_album_artist () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::AlbumArtist); }
+static void pl_sort_selected_date () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Date); }
+static void pl_sort_selected_genre () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Genre); }
+static void pl_sort_selected_length () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Length); }
+static void pl_sort_selected_path () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+static void pl_sort_selected_custom () { aud_playlist_sort_selected_by_scheme (aud_playlist_get_active (), Playlist::FormattedTitle); }
+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 ()); }
+static void pl_remove_dupes_by_title () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Title); }
+static void pl_remove_dupes_by_filename () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Filename); }
+static void pl_remove_dupes_by_path () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+static void pl_rename () { start_rename_playlist (aud_playlist_get_active ()); }
+static void pl_close () { audgui_confirm_playlist_delete (aud_playlist_get_active ()); }
+static void pl_refresh_sel () { aud_playlist_rescan_selected (aud_playlist_get_active ()); }
+static void pl_select_all () { aud_playlist_select_all (aud_playlist_get_active (), true); }
+
+static void pl_tab_play ()
+{
+    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
+    if (playlist >= 0)
+        aud_playlist_play (playlist);
+}
+
+static void pl_tab_rename ()
+{
+    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
+    if (playlist >= 0)
+        start_rename_playlist (playlist);
+}
+
+static void pl_tab_close ()
+{
+    int playlist = aud_playlist_by_unique_id (menu_tab_playlist_id);
+    if (playlist >= 0)
+        audgui_confirm_playlist_delete (playlist);
+}
+
+static GtkWidget * get_services_main () { return audgui_get_plugin_menu (AudMenuID::Main); }
+static GtkWidget * get_services_pl () { return audgui_get_plugin_menu (AudMenuID::Playlist); }
+
+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 const AudguiMenuItem file_items[] = {
+    MenuCommand (N_("_Open Files ..."), "document-open", 'o', CTRL, open_files),
+    MenuCommand (N_("Open _URL ..."), "folder-remote", 'l', CTRL, open_url),
+    MenuCommand (N_("_Add Files ..."), "list-add", 'o', SHIFT_CTRL, add_files),
+    MenuCommand (N_("Add U_RL ..."), "folder-remote", 'l', SHIFT_CTRL, add_url),
+    MenuSep (),
+    MenuCommand (N_("Search _Library"), "edit-find", 'y', CTRL, activate_search_tool),
+    MenuSep (),
+    MenuCommand (N_("A_bout ..."), "help-about", NONE, audgui_show_about_window),
+    MenuCommand (N_("_Settings ..."), "preferences-system", NONE, audgui_show_prefs_window),
+    MenuCommand (N_("_Quit"), "application-exit", 'q', CTRL, aud_quit)
+};
+
+static const AudguiMenuItem playback_items[] = {
+    MenuCommand (N_("_Play"), "media-playback-start", GDK_KEY_Return, CTRL, aud_drct_play),
+    MenuCommand (N_("Paus_e"), "media-playback-pause", ',', CTRL, aud_drct_pause),
+    MenuCommand (N_("_Stop"), "media-playback-stop", '.', CTRL, aud_drct_stop),
+    MenuCommand (N_("Pre_vious"), "media-skip-backward", GDK_KEY_Up, ALT, aud_drct_pl_prev),
+    MenuCommand (N_("_Next"), "media-skip-forward", GDK_KEY_Down, ALT, aud_drct_pl_next),
+    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_("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 (),
+    MenuCommand (N_("Song _Info ..."), "dialog-information", 'i', CTRL, audgui_infowin_show_current),
+    MenuCommand (N_("Jump to _Time ..."), "go-jump", 'k', CTRL, audgui_jump_to_time),
+    MenuCommand (N_("_Jump to Song ..."), "go-jump", 'j', CTRL, audgui_jump_to_track),
+    MenuSep (),
+    MenuCommand (N_("Set Repeat Point _A"), nullptr, '1', CTRL, set_ab_repeat_a),
+    MenuCommand (N_("Set Repeat Point _B"), nullptr, '2', CTRL, set_ab_repeat_b),
+    MenuCommand (N_("_Clear Repeat Points"), nullptr, '3', CTRL, clear_ab_repeat)
+};
+
+static const AudguiMenuItem dupe_items[] = {
+    MenuCommand (N_("By _Title"), nullptr, NONE, pl_remove_dupes_by_title),
+    MenuCommand (N_("By _File Name"), nullptr, NONE, pl_remove_dupes_by_filename),
+    MenuCommand (N_("By File _Path"), nullptr, NONE, pl_remove_dupes_by_path)
+};
+
+static const AudguiMenuItem sort_items[] = {
+    MenuCommand (N_("By Track _Number"), nullptr, NONE, pl_sort_track),
+    MenuCommand (N_("By _Title"), nullptr, NONE, pl_sort_title),
+    MenuCommand (N_("By _Artist"), nullptr, NONE, pl_sort_artist),
+    MenuCommand (N_("By Al_bum"), nullptr, NONE, pl_sort_album),
+    MenuCommand (N_("By Albu_m Artist"), nullptr, NONE, pl_sort_album_artist),
+    MenuCommand (N_("By Release _Date"), nullptr, NONE, pl_sort_date),
+    MenuCommand (N_("By _Genre"), nullptr, NONE, pl_sort_genre),
+    MenuCommand (N_("By _Length"), nullptr, NONE, pl_sort_length),
+    MenuCommand (N_("By _File Path"), nullptr, NONE, pl_sort_path),
+    MenuCommand (N_("By _Custom Title"), nullptr, NONE, pl_sort_custom),
+    MenuSep (),
+    MenuCommand (N_("R_everse Order"), "view-sort-descending", NONE, pl_reverse),
+    MenuCommand (N_("_Random Order"), nullptr, NONE, pl_random)
+};
+
+static const AudguiMenuItem sort_selected_items[] = {
+    MenuCommand (N_("By Track _Number"), nullptr, NONE, pl_sort_selected_track),
+    MenuCommand (N_("By _Title"), nullptr, NONE, pl_sort_selected_title),
+    MenuCommand (N_("By _Artist"), nullptr, NONE, pl_sort_selected_artist),
+    MenuCommand (N_("By Al_bum"), nullptr, NONE, pl_sort_selected_album),
+    MenuCommand (N_("By Albu_m Artist"), nullptr, NONE, pl_sort_selected_album_artist),
+    MenuCommand (N_("By Release _Date"), nullptr, NONE, pl_sort_selected_date),
+    MenuCommand (N_("By _Genre"), nullptr, NONE, pl_sort_selected_genre),
+    MenuCommand (N_("By _Length"), nullptr, NONE, pl_sort_selected_length),
+    MenuCommand (N_("By _File Path"), nullptr, NONE, pl_sort_selected_path),
+    MenuCommand (N_("By _Custom Title"), nullptr, NONE, pl_sort_selected_custom),
+    MenuSep (),
+    MenuCommand (N_("R_everse Order"), "view-sort-descending", NONE, pl_reverse_selected),
+    MenuCommand (N_("_Random Order"), nullptr, NONE, pl_random_selected)
+};
+
+static const AudguiMenuItem playlist_items[] = {
+    MenuCommand (N_("_Play/Resume"), "media-playback-start", GDK_KEY_Return, SHIFT, pl_play),
+    MenuCommand (N_("_Refresh"), "view-refresh", GDK_KEY_F5, (GdkModifierType) 0, pl_refresh),
+    MenuSep (),
+    MenuSub (N_("_Sort"), "view-sort-ascending", {sort_items}),
+    MenuSub (N_("Sort Se_lected"), "view-sort-ascending", {sort_selected_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_("Ren_ame ..."), "insert-text", GDK_KEY_F2, (GdkModifierType) 0, pl_rename),
+    MenuCommand (N_("Remo_ve"), "edit-delete", 'w', CTRL, pl_close),
+    MenuSep (),
+    MenuCommand (N_("_Import ..."), "document-open", NONE, audgui_import_playlist),
+    MenuCommand (N_("_Export ..."), "document-save", NONE, audgui_export_playlist),
+    MenuSep (),
+    MenuCommand (N_("Playlist _Manager ..."), "audio-x-generic", 'p', CTRL, activate_playlist_manager),
+    MenuCommand (N_("_Queue Manager ..."), nullptr, 'u', CTRL, audgui_queue_manager_show)
+};
+
+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),
+    MenuSep (),
+    MenuCommand (N_("E_ffects ..."), nullptr, NONE, configure_effects)
+};
+
+static const AudguiMenuItem view_items[] = {
+    MenuToggle (N_("Show _Menu Bar"), nullptr, 'm', SHIFT_CTRL, "gtkui", "menu_visible", show_hide_menu),
+    MenuToggle (N_("Show I_nfo Bar"), nullptr, 'i', SHIFT_CTRL, "gtkui", "infoarea_visible", show_hide_infoarea),
+    MenuToggle (N_("Show Info Bar Vis_ualization"), nullptr, NONE, "gtkui", "infoarea_show_vis", show_hide_infoarea_vis),
+    MenuToggle (N_("Show _Status Bar"), nullptr, 's', SHIFT_CTRL, "gtkui", "statusbar_visible", show_hide_statusbar),
+    MenuSep (),
+    MenuToggle (N_("Show _Remaining Time"), nullptr, 'r', SHIFT_CTRL, "gtkui", "show_remaining_time"),
+    MenuSep (),
+    MenuCommand (N_("_Visualizations ..."), nullptr, NONE, configure_visualizations)
+};
+
+static const AudguiMenuItem main_items[] = {
+    MenuSub (N_("_File"), nullptr, {file_items}),
+    MenuSub (N_("_Playback"), nullptr, {playback_items}),
+    MenuSub (N_("P_laylist"), nullptr, {playlist_items}),
+    MenuSub (N_("_Services"), nullptr, get_services_main),
+    MenuSub (N_("_Output"), nullptr, {output_items}),
+    MenuSub (N_("_View"), nullptr, {view_items})
+};
+
+static const AudguiMenuItem rclick_items[] = {
+    MenuCommand (N_("Song _Info ..."), "dialog-information", 'i', ALT, playlist_song_info),
+    MenuCommand (N_("_Queue/Unqueue"), nullptr, 'q', ALT, playlist_queue_toggle),
+    MenuSep (),
+    MenuCommand (N_("_Open Containing Folder"), "folder", NONE, playlist_open_folder),
+    MenuCommand (N_("_Refresh"), "view-refresh", GDK_KEY_F6, (GdkModifierType) 0, pl_refresh_sel),
+    MenuSep (),
+    MenuCommand (N_("Cu_t"), "edit-cut", NONE, playlist_cut),
+    MenuCommand (N_("_Copy"), "edit-copy", NONE, playlist_copy),
+    MenuCommand (N_("_Paste"), "edit-paste", NONE, playlist_paste),
+    MenuCommand (N_("Select _All"), "edit-select-all", NONE, pl_select_all),
+    MenuSep (),
+    MenuSub (N_("_Services"), nullptr, get_services_pl)
+};
+
+static const AudguiMenuItem tab_items[] = {
+    MenuCommand (N_("_Play"), "media-playback-start", NONE, pl_tab_play),
+    MenuCommand (N_("_Rename ..."), "insert-text", NONE, pl_tab_rename),
+    MenuCommand (N_("Remo_ve"), "edit-delete", NONE, pl_tab_close)
+};
+
+GtkWidget * make_menu_bar (GtkAccelGroup * accel)
+{
+    GtkWidget * bar = gtk_menu_bar_new ();
+    audgui_menu_init (bar, {main_items}, accel);
+    return bar;
+}
+
+GtkWidget * make_menu_main (GtkAccelGroup * accel)
+{
+    GtkWidget * shell = gtk_menu_new ();
+    audgui_menu_init (shell, {main_items}, accel);
+    return shell;
+}
+
+GtkWidget * make_menu_rclick (GtkAccelGroup * accel)
+{
+    GtkWidget * shell = gtk_menu_new ();
+    audgui_menu_init (shell, {rclick_items}, accel);
+    return shell;
+}
+
+GtkWidget * make_menu_tab (GtkAccelGroup * accel)
+{
+    GtkWidget * shell = gtk_menu_new ();
+    audgui_menu_init (shell, {tab_items}, accel);
+    return shell;
+}
diff --git a/src/gtkui/playlist_util.c b/src/gtkui/playlist_util.c
deleted file mode 100644
index c63a9252fa07..000000000000
--- a/src/gtkui/playlist_util.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * playlist_util.c
- * Copyright 2010-2011 Michał Lipski and 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 <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/playlist.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/list.h>
-
-#include "playlist_util.h"
-#include "ui_playlist_notebook.h"
-
-GtkWidget * playlist_get_treeview (int playlist)
-{
-    GtkWidget *page = gtk_notebook_get_nth_page(UI_PLAYLIST_NOTEBOOK, playlist);
-
-    if (!page)
-        return NULL;
-
-    return g_object_get_data ((GObject *) page, "treeview");
-}
-
-int playlist_count_selected_in_range (int list, int top, int length)
-{
-    int selected = 0;
-    int count;
-
-    for (count = 0; count < length; count ++)
-    {
-        if (aud_playlist_entry_get_selected (list, top + count))
-            selected ++;
-    }
-
-    return selected;
-}
-
-void playlist_song_info (void)
-{
-    int list = aud_playlist_get_active ();
-    int focus = aud_playlist_get_focus (list);
-
-    if (focus < 0)
-        return;
-
-    audgui_infowin_show (list, focus);
-}
-
-void playlist_queue_toggle (void)
-{
-    int list = aud_playlist_get_active ();
-    int focus = aud_playlist_get_focus (list);
-
-    if (focus < 0)
-        return;
-
-    int at = aud_playlist_queue_find_entry (list, focus);
-
-    if (at < 0)
-        aud_playlist_queue_insert (list, -1, focus);
-    else
-        aud_playlist_queue_delete (list, at, 1);
-}
-
-void playlist_delete_selected (void)
-{
-    int list = aud_playlist_get_active ();
-    aud_playlist_delete_selected (list);
-    aud_playlist_entry_set_selected (list, aud_playlist_get_focus (list), TRUE);
-}
-
-void playlist_copy (void)
-{
-    char * text = audgui_urilist_create_from_selected (aud_playlist_get_active ());
-    if (! text)
-        return;
-
-    gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), text, -1);
-    g_free (text);
-}
-
-void playlist_cut (void)
-{
-    playlist_copy ();
-    playlist_delete_selected ();
-}
-
-void playlist_paste (void)
-{
-    char * text = gtk_clipboard_wait_for_text (gtk_clipboard_get
-     (GDK_SELECTION_CLIPBOARD));
-    if (! text)
-        return;
-
-    int list = aud_playlist_get_active ();
-    audgui_urilist_insert (list, aud_playlist_get_focus (list), text);
-    g_free (text);
-}
-
-void playlist_shift (int offset)
-{
-    int list = aud_playlist_get_active ();
-    int focus = aud_playlist_get_focus (list);
-
-    if (focus < 0 || ! aud_playlist_entry_get_selected (list, focus))
-        return;
-
-    aud_playlist_shift (list, focus, offset);
-}
diff --git a/src/gtkui/playlist_util.cc b/src/gtkui/playlist_util.cc
new file mode 100644
index 000000000000..6ecf2161c7d4
--- /dev/null
+++ b/src/gtkui/playlist_util.cc
@@ -0,0 +1,150 @@
+/*
+ * playlist_util.c
+ * Copyright 2010-2011 Michał Lipski and 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 <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/playlist.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/list.h>
+
+#include "playlist_util.h"
+#include "ui_playlist_notebook.h"
+
+GtkWidget * playlist_get_treeview (int playlist)
+{
+    GtkWidget * page = gtk_notebook_get_nth_page (UI_PLAYLIST_NOTEBOOK, playlist);
+
+    if (!page)
+        return nullptr;
+
+    return (GtkWidget *) g_object_get_data ((GObject *) page, "treeview");
+}
+
+int playlist_count_selected_in_range (int list, int top, int length)
+{
+    int selected = 0;
+
+    for (int count = 0; count < length; count ++)
+    {
+        if (aud_playlist_entry_get_selected (list, top + count))
+            selected ++;
+    }
+
+    return selected;
+}
+
+void playlist_song_info ()
+{
+    int list = aud_playlist_get_active ();
+    int focus = aud_playlist_get_focus (list);
+
+    if (focus < 0)
+        return;
+
+    audgui_infowin_show (list, focus);
+}
+
+void playlist_open_folder ()
+{
+    int list = aud_playlist_get_active ();
+    int focus = aud_playlist_get_focus (list);
+
+    if (focus < 0)
+        return;
+
+    StringBuf filename = uri_to_filename (aud_playlist_entry_get_filename (list, focus));
+    if (! filename)
+        return;
+
+    char * dirname = g_path_get_dirname (filename);
+    StringBuf uri = filename_to_uri (dirname);
+    g_free (dirname);
+
+    GdkScreen * screen = gdk_screen_get_default ();
+    gtk_show_uri (screen, uri, GDK_CURRENT_TIME, nullptr);
+}
+
+void playlist_queue_toggle ()
+{
+    int list = aud_playlist_get_active ();
+    int focus = aud_playlist_get_focus (list);
+
+    if (focus < 0)
+        return;
+
+    /* make sure focused row is selected */
+    if (! aud_playlist_entry_get_selected (list, focus))
+    {
+        aud_playlist_select_all (list, false);
+        aud_playlist_entry_set_selected (list, focus, true);
+    }
+
+    int at = aud_playlist_queue_find_entry (list, focus);
+
+    if (at < 0)
+        aud_playlist_queue_insert_selected (list, -1);
+    else
+        aud_playlist_queue_delete_selected (list);
+}
+
+void playlist_delete_selected ()
+{
+    int list = aud_playlist_get_active ();
+    aud_playlist_delete_selected (list);
+    aud_playlist_entry_set_selected (list, aud_playlist_get_focus (list), true);
+}
+
+void playlist_copy ()
+{
+    Index<char> text = audgui_urilist_create_from_selected (aud_playlist_get_active ());
+    if (! text.len ())
+        return;
+
+    gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), text.begin (), text.len ());
+}
+
+void playlist_cut ()
+{
+    playlist_copy ();
+    playlist_delete_selected ();
+}
+
+void playlist_paste ()
+{
+    char * text = gtk_clipboard_wait_for_text (gtk_clipboard_get
+     (GDK_SELECTION_CLIPBOARD));
+    if (! text)
+        return;
+
+    int list = aud_playlist_get_active ();
+    audgui_urilist_insert (list, aud_playlist_get_focus (list), text);
+    g_free (text);
+}
+
+void playlist_shift (int offset)
+{
+    int list = aud_playlist_get_active ();
+    int focus = aud_playlist_get_focus (list);
+
+    if (focus < 0 || ! aud_playlist_entry_get_selected (list, focus))
+        return;
+
+    aud_playlist_shift (list, focus, offset);
+}
diff --git a/src/gtkui/playlist_util.h b/src/gtkui/playlist_util.h
index 3786152f6e75..b13b1f59fec5 100644
--- a/src/gtkui/playlist_util.h
+++ b/src/gtkui/playlist_util.h
@@ -23,12 +23,13 @@
 GtkWidget * playlist_get_treeview (int playlist);
 
 int playlist_count_selected_in_range (int list, int top, int length);
-void playlist_song_info (void);
-void playlist_queue_toggle (void);
-void playlist_delete_selected (void);
-void playlist_copy (void);
-void playlist_cut (void);
-void playlist_paste (void);
+void playlist_song_info ();
+void playlist_open_folder ();
+void playlist_queue_toggle ();
+void playlist_delete_selected ();
+void playlist_copy ();
+void playlist_cut ();
+void playlist_paste ();
 void playlist_shift (int offset);
 
 #endif
diff --git a/src/gtkui/settings.c b/src/gtkui/settings.c
deleted file mode 100644
index eb47f6d41aee..000000000000
--- a/src/gtkui/settings.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * settings.c
- * Copyright 2013 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 "gtkui.h"
-
-#include <audacious/i18n.h>
-#include <audacious/preferences.h>
-
-#include "ui_playlist_notebook.h"
-#include "ui_playlist_widget.h"
-
-static void redisplay_playlists (void)
-{
-    ui_playlist_notebook_empty ();
-    ui_playlist_notebook_populate ();
-}
-
-static PreferencesWidget gtkui_widgets[] = {
-    {WIDGET_LABEL, N_("<b>Playlist Tabs</b>")},
-    {WIDGET_CHK_BTN, N_("Always show tabs"),
-     .cfg_type = VALUE_BOOLEAN, .csect = "gtkui", .cname = "playlist_tabs_visible",
-     .callback = show_hide_playlist_tabs},
-    {WIDGET_CHK_BTN, N_("Show entry counts"),
-     .cfg_type = VALUE_BOOLEAN, .csect = "gtkui", .cname = "entry_count_visible",
-     .callback = redisplay_playlists},
-    {WIDGET_CHK_BTN, N_("Show close buttons"),
-     .cfg_type = VALUE_BOOLEAN, .csect = "gtkui", .cname = "close_button_visible",
-     .callback = redisplay_playlists},
-    {WIDGET_LABEL, N_("<b>Playlist Columns</b>")},
-    {WIDGET_CUSTOM, .data.populate = pw_col_create_chooser},
-    {WIDGET_CHK_BTN, N_("Show column headers"),
-     .cfg_type = VALUE_BOOLEAN, .csect = "gtkui", .cname = "playlist_headers",
-     .callback = redisplay_playlists},
-    {WIDGET_LABEL, N_("<b>Miscellaneous</b>")},
-    {WIDGET_SPIN_BTN, N_("Arrow keys seek by:"),
-     .cfg_type = VALUE_FLOAT, .csect = "gtkui", .cname = "step_size",
-     .callback= update_step_size, .data.spin_btn = {0.1, 60, 0.1, N_("seconds")}},
-    {WIDGET_CHK_BTN, N_("Scroll on song change"),
-     .cfg_type = VALUE_BOOLEAN, .csect = "gtkui", .cname = "autoscroll"}
-};
-
-const PluginPreferences gtkui_prefs = {
-    .widgets = gtkui_widgets,
-    .n_widgets = ARRAY_LEN (gtkui_widgets)
-};
-
diff --git a/src/gtkui/settings.cc b/src/gtkui/settings.cc
new file mode 100644
index 000000000000..e459eccc8085
--- /dev/null
+++ b/src/gtkui/settings.cc
@@ -0,0 +1,54 @@
+/*
+ * settings.c
+ * Copyright 2013 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 "gtkui.h"
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/preferences.h>
+
+#include "ui_playlist_notebook.h"
+#include "ui_playlist_widget.h"
+
+static void redisplay_playlists ()
+{
+    ui_playlist_notebook_empty ();
+    ui_playlist_notebook_populate ();
+}
+
+static const PreferencesWidget gtkui_widgets[] = {
+    WidgetLabel (N_("<b>Playlist Tabs</b>")),
+    WidgetCheck (N_("Always show tabs"),
+        WidgetBool ("gtkui", "playlist_tabs_visible", show_hide_playlist_tabs)),
+    WidgetCheck (N_("Show entry counts"),
+        WidgetBool ("gtkui", "entry_count_visible", redisplay_playlists)),
+    WidgetCheck (N_("Show close buttons"),
+        WidgetBool ("gtkui", "close_button_visible", redisplay_playlists)),
+    WidgetLabel (N_("<b>Playlist Columns</b>")),
+    WidgetCustomGTK (pw_col_create_chooser),
+    WidgetCheck (N_("Show column headers"),
+        WidgetBool ("gtkui", "playlist_headers", redisplay_playlists)),
+    WidgetLabel (N_("<b>Miscellaneous</b>")),
+    WidgetSpin (N_("Arrow keys seek by:"),
+        WidgetFloat ("gtkui", "step_size", update_step_size),
+        {0.1, 60, 0.1, N_("seconds")}),
+    WidgetCheck (N_("Scroll on song change"),
+        WidgetBool ("gtkui", "autoscroll"))
+};
+
+const PluginPreferences gtkui_prefs = {{gtkui_widgets}};
diff --git a/src/gtkui/ui_gtk.c b/src/gtkui/ui_gtk.c
deleted file mode 100644
index ac2f39662070..000000000000
--- a/src/gtkui/ui_gtk.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
- * ui_gtk.c
- * Copyright 2009-2012 William Pitcock, Tomasz Moń, Michał Lipski, and 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 <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <audacious/plugins.h>
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-
-#include "gtkui.h"
-#include "layout.h"
-#include "ui_playlist_notebook.h"
-#include "ui_playlist_widget.h"
-#include "ui_infoarea.h"
-#include "ui_statusbar.h"
-#include "playlist_util.h"
-
-static const char * const gtkui_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",
- "show_remaining_time", "FALSE",
- "step_size", "5",
-
- "player_x", "-1000",
- "player_y", "-1000",
- "player_width", "760",
- "player_height", "460",
-
- NULL
-};
-
-static PluginHandle * search_tool;
-
-static GtkWidget *volume;
-static bool_t volume_slider_is_moving = FALSE;
-static unsigned update_volume_timeout_source = 0;
-static gulong volume_change_handler_id;
-
-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;
-static GtkWidget * slider, * label_time;
-static GtkWidget * menu_main, * menu_rclick, * menu_tab;
-
-static bool_t 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 bool_t init (void);
-static void cleanup (void);
-static void ui_show (bool_t show);
-
-AUD_IFACE_PLUGIN
-(
-    .name = N_("GTK Interface"),
-    .domain = PACKAGE,
-    .prefs = & gtkui_prefs,
-    .init = init,
-    .cleanup = cleanup,
-    .show = ui_show,
-    .run_gtk_plugin = (void (*) (void *, const char *)) layout_add,
-    .stop_gtk_plugin = (void (*) (void *)) layout_remove,
-)
-
-static void save_window_size (void)
-{
-    int x, y, w, h;
-    gtk_window_get_position ((GtkWindow *) window, & x, & y);
-    gtk_window_get_size ((GtkWindow *) window, & w, & h);
-
-    aud_set_int ("gtkui", "player_x", x);
-    aud_set_int ("gtkui", "player_y", y);
-    aud_set_int ("gtkui", "player_width", w);
-    aud_set_int ("gtkui", "player_height", h);
-}
-
-static void restore_window_size (void)
-{
-    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");
-
-    gtk_window_set_default_size ((GtkWindow *) window, w, h);
-
-    if (x > -1000 && y > -1000)
-        gtk_window_move ((GtkWindow *) window, x, y);
-}
-
-static bool_t window_delete()
-{
-    bool_t handle = FALSE;
-
-    hook_call("window close", &handle);
-
-    if (handle)
-        return TRUE;
-
-    aud_drct_quit ();
-    return TRUE;
-}
-
-static void button_open_pressed (void)
-{
-    audgui_run_filebrowser (TRUE);
-}
-
-static void button_add_pressed (void)
-{
-    audgui_run_filebrowser (FALSE);
-}
-
-void set_ab_repeat_a (void)
-{
-    if (! aud_drct_get_playing ())
-        return;
-
-    int a, b;
-    aud_drct_get_ab_repeat (& a, & b);
-    a = aud_drct_get_time ();
-    aud_drct_set_ab_repeat (a, b);
-}
-
-void set_ab_repeat_b (void)
-{
-    if (! aud_drct_get_playing ())
-        return;
-
-    int a, b;
-    aud_drct_get_ab_repeat (& a, & b);
-    b = aud_drct_get_time ();
-    aud_drct_set_ab_repeat (a, b);
-}
-
-void clear_ab_repeat (void)
-{
-    aud_drct_set_ab_repeat (-1, -1);
-}
-
-static bool_t title_change_cb (void)
-{
-    if (delayed_title_change_source)
-    {
-        g_source_remove (delayed_title_change_source);
-        delayed_title_change_source = 0;
-    }
-
-    if (aud_drct_get_playing ())
-    {
-        if (aud_drct_get_ready ())
-        {
-            char * title = aud_drct_get_title ();
-            SPRINTF (title_s, _("%s - Audacious"), title);
-            gtk_window_set_title ((GtkWindow *) window, title_s);
-            str_unref (title);
-        }
-        else
-            gtk_window_set_title ((GtkWindow *) window, _("Buffering ..."));
-    }
-    else
-        gtk_window_set_title ((GtkWindow *) window, _("Audacious"));
-
-    return FALSE;
-}
-
-static void ui_show (bool_t show)
-{
-    if (show)
-    {
-        if (! gtk_widget_get_visible (window))
-            restore_window_size ();
-
-        gtk_window_present ((GtkWindow *) window);
-    }
-    else
-    {
-        if (gtk_widget_get_visible (window))
-            save_window_size ();
-
-        gtk_widget_hide (window);
-    }
-
-    show_hide_infoarea_vis ();
-}
-
-static void append_str (char * buf, int bufsize, const char * str)
-{
-    snprintf (buf + strlen (buf), bufsize - strlen (buf), "%s", str);
-}
-
-static void append_time_str (char * buf, int bufsize, int time)
-{
-    audgui_format_time (buf + strlen (buf), bufsize - strlen (buf), time);
-}
-
-static void set_time_label (int time, int len)
-{
-    char s[128] = "<b>";
-
-    if (len && aud_get_bool ("gtkui", "show_remaining_time"))
-        append_time_str (s, sizeof s, len - time);
-    else
-        append_time_str (s, sizeof s, time);
-
-    if (len)
-    {
-        append_str (s, sizeof s, " / ");
-        append_time_str (s, sizeof s, len);
-
-        int a, b;
-        aud_drct_get_ab_repeat (& a, & b);
-
-        if (a >= 0)
-        {
-            append_str (s, sizeof s, " A=");
-            append_time_str (s, sizeof s, a);
-        }
-
-        if (b >= 0)
-        {
-            append_str (s, sizeof s, " B=");
-            append_time_str (s, sizeof s, b);
-        }
-    }
-
-    append_str (s, sizeof s, "</b>");
-
-    /* only update label if necessary */
-    if (strcmp (gtk_label_get_label ((GtkLabel *) label_time), s))
-        gtk_label_set_markup ((GtkLabel *) label_time, s);
-}
-
-static void set_slider (int time)
-{
-    gtk_range_set_value ((GtkRange *) slider, time);
-}
-
-static bool_t time_counter_cb (void)
-{
-    if (slider_is_moving)
-        return TRUE;
-
-    slider_seek_time = -1;  // delayed reset to avoid seeking twice
-
-    int time = aud_drct_get_time ();
-    int length = aud_drct_get_length ();
-
-    if (length > 0)
-        set_slider (time);
-
-    set_time_label (time, length);
-
-    return TRUE;
-}
-
-static void do_seek (int time)
-{
-    int length = aud_drct_get_length ();
-    time = 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, NULL);
-    }
-}
-
-static bool_t ui_slider_change_value_cb (GtkRange * range,
- GtkScrollType scroll, double value)
-{
-    int length = aud_drct_get_length ();
-    int time = CLAMP ((int) value, 0, length);
-
-    set_time_label (time, length);
-
-    if (slider_is_moving)
-        slider_seek_time = time;
-    else if (time != slider_seek_time)  // avoid seeking twice
-        do_seek (time);
-
-    return FALSE;
-}
-
-static bool_t ui_slider_button_press_cb(GtkWidget * widget, GdkEventButton * event, void * user_data)
-{
-    slider_is_moving = TRUE;
-    return FALSE;
-}
-
-static bool_t ui_slider_button_release_cb(GtkWidget * widget, GdkEventButton * event, void * user_data)
-{
-    if (slider_seek_time != -1)
-        do_seek (slider_seek_time);
-
-    slider_is_moving = FALSE;
-    return FALSE;
-}
-
-static bool_t ui_volume_value_changed_cb(GtkButton * button, double volume, void * user_data)
-{
-    aud_drct_set_volume((int) volume, (int) volume);
-
-    return TRUE;
-}
-
-static void ui_volume_pressed_cb(GtkButton *button, void * user_data)
-{
-    volume_slider_is_moving = TRUE;
-}
-
-static void ui_volume_released_cb(GtkButton *button, void * user_data)
-{
-    volume_slider_is_moving = FALSE;
-}
-
-static bool_t ui_volume_slider_update(void * data)
-{
-    int volume;
-
-    if (volume_slider_is_moving || data == NULL)
-        return TRUE;
-
-    aud_drct_get_volume_main(&volume);
-
-    if (volume == (int) gtk_scale_button_get_value(GTK_SCALE_BUTTON(data)))
-        return TRUE;
-
-    g_signal_handler_block(data, volume_change_handler_id);
-    gtk_scale_button_set_value(GTK_SCALE_BUTTON(data), volume);
-    g_signal_handler_unblock(data, volume_change_handler_id);
-
-    return TRUE;
-}
-
-static void set_slider_length (int length)
-{
-    if (length > 0)
-    {
-        gtk_range_set_range ((GtkRange *) slider, 0, length);
-        gtk_widget_show (slider);
-    }
-    else
-        gtk_widget_hide (slider);
-}
-
-void update_step_size (void)
-{
-    double step_size = aud_get_double ("gtkui", "step_size");
-    gtk_range_set_increments ((GtkRange *) slider, step_size * 1000, step_size * 1000);
-}
-
-static void pause_cb (void)
-{
-    gtk_tool_button_set_icon_name ((GtkToolButton *) button_play,
-     aud_drct_get_paused () ? "media-playback-start" : "media-playback-pause");
-}
-
-static void ui_playback_begin (void)
-{
-    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, NULL);
-}
-
-static void ui_playback_ready (void)
-{
-    title_change_cb ();
-    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, NULL);
-
-    gtk_widget_show (label_time);
-}
-
-static void ui_playback_stop (void)
-{
-    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,
-     NULL);
-
-    gtk_tool_button_set_icon_name ((GtkToolButton *) button_play, "media-playback-start");
-    gtk_widget_set_sensitive ((GtkWidget *) button_stop, FALSE);
-    gtk_widget_hide (slider);
-    gtk_widget_hide (label_time);
-}
-
-static GtkToolItem * toolbar_button_add (GtkWidget * toolbar,
- void (* callback) (void), const char * icon)
-{
-    GtkToolItem * item = gtk_tool_button_new (NULL, NULL);
-    gtk_tool_button_set_icon_name ((GtkToolButton *) item, icon);
-    gtk_toolbar_insert ((GtkToolbar *) toolbar, item, -1);
-    g_signal_connect (item, "clicked", callback, NULL);
-    return item;
-}
-
-static GtkToolItem * toggle_button_new (const char * icon,
- void (* toggled) (GtkToggleToolButton * button))
-{
-    GtkToolItem * item = gtk_toggle_tool_button_new ();
-    gtk_tool_button_set_icon_name ((GtkToolButton *) item, icon);
-    g_signal_connect (item, "toggled", (GCallback) toggled, NULL);
-    return item;
-}
-
-static GtkWidget *markup_label_new(const char * str)
-{
-    GtkWidget *label = gtk_label_new(str);
-    g_object_set(G_OBJECT(label), "use-markup", TRUE, NULL);
-    return label;
-}
-
-static void window_mapped_cb (GtkWidget * widget, void * unused)
-{
-    gtk_widget_grab_focus (playlist_get_treeview (aud_playlist_get_active ()));
-}
-
-static bool_t window_keypress_cb (GtkWidget * widget, GdkEventKey * event, void * unused)
-{
-    switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))
-    {
-      case 0:;
-        GtkWidget * focused = gtk_window_get_focus ((GtkWindow *) window);
-
-        /* escape key returns focus to playlist */
-        if (event->keyval == GDK_KEY_Escape)
-        {
-            if (! focused || ! gtk_widget_is_ancestor (focused, (GtkWidget *) UI_PLAYLIST_NOTEBOOK))
-                gtk_widget_grab_focus (playlist_get_treeview (aud_playlist_get_active ()));
-
-            return FALSE;
-        }
-
-        /* single-key shortcuts; must not interfere with text entry */
-        if (focused && GTK_IS_ENTRY (focused))
-            return FALSE;
-
-        switch (event->keyval)
-        {
-        case 'z':
-            aud_drct_pl_prev ();
-            return TRUE;
-        case 'x':
-            aud_drct_play ();
-            return TRUE;
-        case 'c':
-        case ' ':
-            aud_drct_pause ();
-            return TRUE;
-        case 'v':
-            aud_drct_stop ();
-            return TRUE;
-        case 'b':
-            aud_drct_pl_next ();
-            return TRUE;
-        case GDK_KEY_Left:
-            if (aud_drct_get_playing ())
-                do_seek (aud_drct_get_time () - aud_get_double ("gtkui", "step_size") * 1000);
-            return TRUE;
-        case GDK_KEY_Right:
-            if (aud_drct_get_playing ())
-                do_seek (aud_drct_get_time () + aud_get_double ("gtkui", "step_size") * 1000);
-            return TRUE;
-        }
-
-        return FALSE;
-
-      case GDK_CONTROL_MASK:
-        switch (event->keyval)
-        {
-          case GDK_KEY_ISO_Left_Tab:
-          case GDK_KEY_Tab:
-            aud_playlist_set_active ((aud_playlist_get_active () + 1) %
-             aud_playlist_count ());
-            break;
-
-          default:
-            return FALSE;
-        }
-        break;
-      case (GDK_CONTROL_MASK | GDK_SHIFT_MASK):
-        switch (event->keyval)
-        {
-          case GDK_KEY_ISO_Left_Tab:
-          case GDK_KEY_Tab:
-            aud_playlist_set_active (aud_playlist_get_active () ?
-             aud_playlist_get_active () - 1 : aud_playlist_count () - 1);
-            break;
-          default:
-            return FALSE;
-        }
-        break;
-      case GDK_MOD1_MASK:
-        switch (event->keyval)
-        {
-          case GDK_KEY_Left:
-            if (aud_drct_get_playing ())
-                do_seek (aud_drct_get_time () - aud_get_double ("gtkui", "step_size") * 1000);
-            break;
-          case GDK_KEY_Right:
-            if (aud_drct_get_playing ())
-                do_seek (aud_drct_get_time () + aud_get_double ("gtkui", "step_size") * 1000);
-            break;
-          default:
-            return FALSE;
-        }
-      default:
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static bool_t playlist_keypress_cb (GtkWidget * widget, GdkEventKey * event, void * unused)
-{
-    switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))
-    {
-    case 0:
-        switch (event->keyval)
-        {
-        case GDK_KEY_Escape:
-            ui_playlist_notebook_position (GINT_TO_POINTER (aud_playlist_get_active ()), NULL);
-            return TRUE;
-        case GDK_KEY_Delete:
-            playlist_delete_selected ();
-            return TRUE;
-        case GDK_KEY_Menu:
-            popup_menu_rclick (0, event->time);
-            return TRUE;
-        }
-
-        break;
-    case GDK_CONTROL_MASK:
-        switch (event->keyval)
-        {
-        case 'x':
-            playlist_cut ();
-            return TRUE;
-        case 'c':
-            playlist_copy ();
-            return TRUE;
-        case 'v':
-            playlist_paste ();
-            return TRUE;
-        case 'a':
-            aud_playlist_select_all (aud_playlist_get_active (), TRUE);
-            return TRUE;
-        }
-
-        break;
-    }
-
-    return FALSE;
-}
-
-static void update_toggles (void * data, void * user)
-{
-    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_repeat,
-     aud_get_bool (NULL, "repeat"));
-    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_shuffle,
-     aud_get_bool (NULL, "shuffle"));
-}
-
-static void toggle_repeat (GtkToggleToolButton * button)
-{
-    aud_set_bool (NULL, "repeat", gtk_toggle_tool_button_get_active (button));
-}
-
-static void toggle_shuffle (GtkToggleToolButton * button)
-{
-    aud_set_bool (NULL, "shuffle", gtk_toggle_tool_button_get_active (button));
-}
-
-static void toggle_search_tool (GtkToggleToolButton * button)
-{
-    aud_plugin_enable (search_tool, gtk_toggle_tool_button_get_active (button));
-}
-
-static bool_t search_tool_toggled (PluginHandle * plugin, void * unused)
-{
-    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) search_button,
-     aud_plugin_get_enabled (plugin));
-    return TRUE;
-}
-
-static void config_save (void)
-{
-    if (gtk_widget_get_visible (window))
-        save_window_size ();
-
-    layout_save ();
-    pw_col_save ();
-}
-
-static void ui_hooks_associate(void)
-{
-    hook_associate ("title change", (HookFunction) title_change_cb, NULL);
-    hook_associate ("playback begin", (HookFunction) ui_playback_begin, NULL);
-    hook_associate ("playback ready", (HookFunction) ui_playback_ready, NULL);
-    hook_associate ("playback pause", (HookFunction) pause_cb, NULL);
-    hook_associate ("playback unpause", (HookFunction) pause_cb, NULL);
-    hook_associate ("playback stop", (HookFunction) ui_playback_stop, NULL);
-    hook_associate ("playlist update", ui_playlist_notebook_update, NULL);
-    hook_associate ("playlist activate", ui_playlist_notebook_activate, NULL);
-    hook_associate ("playlist set playing", ui_playlist_notebook_set_playing, NULL);
-    hook_associate ("playlist position", ui_playlist_notebook_position, NULL);
-    hook_associate ("set shuffle", update_toggles, NULL);
-    hook_associate ("set repeat", update_toggles, NULL);
-    hook_associate ("config save", (HookFunction) config_save, NULL);
-}
-
-static void ui_hooks_disassociate(void)
-{
-    hook_dissociate ("title change", (HookFunction) title_change_cb);
-    hook_dissociate ("playback begin", (HookFunction) ui_playback_begin);
-    hook_dissociate ("playback ready", (HookFunction) ui_playback_ready);
-    hook_dissociate ("playback pause", (HookFunction) pause_cb);
-    hook_dissociate ("playback unpause", (HookFunction) pause_cb);
-    hook_dissociate ("playback stop", (HookFunction) ui_playback_stop);
-    hook_dissociate("playlist update", ui_playlist_notebook_update);
-    hook_dissociate ("playlist activate", ui_playlist_notebook_activate);
-    hook_dissociate ("playlist set playing", ui_playlist_notebook_set_playing);
-    hook_dissociate ("playlist position", ui_playlist_notebook_position);
-    hook_dissociate ("set shuffle", update_toggles);
-    hook_dissociate ("set repeat", update_toggles);
-    hook_dissociate ("config save", (HookFunction) config_save);
-}
-
-static bool_t init (void)
-{
-    search_tool = aud_plugin_lookup_basename ("search-tool");
-
-    aud_config_set_defaults ("gtkui", gtkui_defaults);
-
-    pw_col_init ();
-
-    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_has_resize_grip ((GtkWindow *) window, FALSE);
-
-    g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(window_delete), NULL);
-
-    accel = gtk_accel_group_new ();
-    gtk_window_add_accel_group ((GtkWindow *) window, accel);
-
-    vbox_outer = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-    gtk_container_add ((GtkContainer *) window, vbox_outer);
-
-    menu_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-    gtk_box_pack_start ((GtkBox *) vbox_outer, menu_box, FALSE, FALSE, 0);
-
-    toolbar = gtk_toolbar_new ();
-    gtk_toolbar_set_style ((GtkToolbar *) toolbar, GTK_TOOLBAR_ICONS);
-    GtkStyleContext * context = gtk_widget_get_style_context (toolbar);
-    gtk_style_context_add_class (context, GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
-    gtk_box_pack_start ((GtkBox *) vbox_outer, toolbar, FALSE, FALSE, 0);
-
-    /* search button */
-    if (search_tool)
-    {
-        search_button = toggle_button_new ("edit-find", toggle_search_tool);
-        gtk_toolbar_insert ((GtkToolbar *) toolbar, search_button, -1);
-        gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) search_button,
-         aud_plugin_get_enabled (search_tool));
-        aud_plugin_add_watch (search_tool, search_tool_toggled, NULL);
-    }
-
-    /* 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");
-
-    /* time slider and label */
-    GtkToolItem * boxitem1 = gtk_tool_item_new ();
-    gtk_tool_item_set_expand (boxitem1, TRUE);
-    gtk_toolbar_insert ((GtkToolbar *) toolbar, boxitem1, -1);
-
-    GtkWidget * box1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-    gtk_container_add ((GtkContainer *) boxitem1, box1);
-
-    slider = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, NULL);
-    gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
-    gtk_widget_set_size_request(slider, 120, -1);
-    gtk_widget_set_valign (slider, GTK_ALIGN_CENTER);
-    gtk_widget_set_can_focus(slider, FALSE);
-    gtk_box_pack_start ((GtkBox *) box1, slider, TRUE, TRUE, 6);
-
-    update_step_size ();
-
-    label_time = markup_label_new(NULL);
-    gtk_box_pack_end ((GtkBox *) box1, label_time, FALSE, FALSE, 6);
-
-    gtk_widget_set_no_show_all (slider, TRUE);
-    gtk_widget_set_no_show_all (label_time, TRUE);
-
-    /* repeat and shuffle buttons */
-    button_repeat = toggle_button_new ("media-playlist-repeat", toggle_repeat);
-    gtk_toolbar_insert ((GtkToolbar *) toolbar, button_repeat, -1);
-    button_shuffle = toggle_button_new ("media-playlist-shuffle", toggle_shuffle);
-    gtk_toolbar_insert ((GtkToolbar *) toolbar, button_shuffle, -1);
-
-    /* volume button */
-    GtkToolItem * boxitem2 = gtk_tool_item_new ();
-    gtk_toolbar_insert ((GtkToolbar *) toolbar, boxitem2, -1);
-
-    GtkWidget * box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-    gtk_container_add ((GtkContainer *) boxitem2, box2);
-
-    volume = gtk_volume_button_new();
-    g_object_set ((GObject *) volume, "size", GTK_ICON_SIZE_LARGE_TOOLBAR, NULL);
-    gtk_button_set_relief(GTK_BUTTON(volume), GTK_RELIEF_NONE);
-    gtk_scale_button_set_adjustment(GTK_SCALE_BUTTON(volume), GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 100, 1, 5, 0)));
-    gtk_widget_set_can_focus(volume, FALSE);
-
-    int lvol = 0, rvol = 0;
-    aud_drct_get_volume(&lvol, &rvol);
-    gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume), (lvol + rvol) / 2);
-
-    gtk_box_pack_start ((GtkBox *) box2, volume, FALSE, FALSE, 0);
-
-    /* main UI layout */
-    layout_load ();
-
-    GtkWidget * layout = layout_new ();
-    gtk_box_pack_start ((GtkBox *) vbox_outer, layout, TRUE, TRUE, 0);
-
-    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-    layout_add_center (vbox);
-
-    ui_playlist_notebook_new ();
-    gtk_box_pack_start ((GtkBox *) vbox, (GtkWidget *) UI_PLAYLIST_NOTEBOOK, TRUE, TRUE, 0);
-
-    /* optional UI elements */
-    show_hide_menu ();
-    show_hide_infoarea ();
-    show_hide_statusbar ();
-
-    AUDDBG("hooks associate\n");
-    ui_hooks_associate();
-
-    AUDDBG("playlist associate\n");
-    ui_playlist_notebook_populate();
-
-    g_signal_connect(slider, "change-value", G_CALLBACK(ui_slider_change_value_cb), NULL);
-    g_signal_connect(slider, "button-press-event", G_CALLBACK(ui_slider_button_press_cb), NULL);
-    g_signal_connect(slider, "button-release-event", G_CALLBACK(ui_slider_button_release_cb), NULL);
-
-    volume_change_handler_id = g_signal_connect(volume, "value-changed", G_CALLBACK(ui_volume_value_changed_cb), NULL);
-    g_signal_connect(volume, "pressed", G_CALLBACK(ui_volume_pressed_cb), NULL);
-    g_signal_connect(volume, "released", G_CALLBACK(ui_volume_released_cb), NULL);
-    update_volume_timeout_source = g_timeout_add(250, (GSourceFunc) ui_volume_slider_update, volume);
-
-    g_signal_connect (window, "map-event", (GCallback) window_mapped_cb, NULL);
-    g_signal_connect (window, "key-press-event", (GCallback) window_keypress_cb, NULL);
-    g_signal_connect (UI_PLAYLIST_NOTEBOOK, "key-press-event", (GCallback) playlist_keypress_cb, NULL);
-
-    if (aud_drct_get_playing ())
-    {
-        ui_playback_begin ();
-        if (aud_drct_get_ready ())
-            ui_playback_ready ();
-    }
-    else
-        ui_playback_stop ();
-
-    title_change_cb ();
-
-    gtk_widget_show_all (vbox_outer);
-
-    update_toggles (NULL, NULL);
-
-    menu_rclick = make_menu_rclick (accel);
-    menu_tab = make_menu_tab (accel);
-
-    return TRUE;
-}
-
-static void cleanup (void)
-{
-    if (menu_main)
-        gtk_widget_destroy (menu_main);
-
-    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;
-    }
-
-    ui_hooks_disassociate();
-
-    if (search_tool)
-        aud_plugin_remove_watch (search_tool, search_tool_toggled, NULL);
-
-    gtk_widget_destroy (window);
-    layout_cleanup ();
-}
-
-static void menu_position_cb (GtkMenu * menu, int * x, int * y, int * push, void * button)
-{
-    int xorig, yorig, xwin, ywin;
-
-    gdk_window_get_origin (gtk_widget_get_window (window), & xorig, & yorig);
-    gtk_widget_translate_coordinates (button, window, 0, 0, & xwin, & ywin);
-
-    * x = xorig + xwin;
-    * y = yorig + ywin + gtk_widget_get_allocated_height (button);
-    * push = TRUE;
-}
-
-static void menu_button_cb (void)
-{
-    if (gtk_toggle_tool_button_get_active ((GtkToggleToolButton *) menu_button))
-        gtk_menu_popup ((GtkMenu *) menu_main, NULL, NULL, menu_position_cb,
-         menu_button, 0, gtk_get_current_event_time ());
-    else
-        gtk_widget_hide (menu_main);
-}
-
-static void menu_hide_cb (void)
-{
-    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) menu_button, FALSE);
-}
-
-void show_hide_menu (void)
-{
-    if (aud_get_bool ("gtkui", "menu_visible"))
-    {
-        /* remove menu button from toolbar and show menu bar */
-        if (menu_main)
-            gtk_widget_destroy (menu_main);
-        if (menu_button)
-            gtk_widget_destroy ((GtkWidget *) menu_button);
-
-        if (! menu)
-        {
-            menu = make_menu_bar (accel);
-            g_signal_connect (menu, "destroy", (GCallback) gtk_widget_destroyed,
-             & menu);
-            gtk_widget_show (menu);
-            gtk_box_pack_start ((GtkBox *) menu_box, menu, TRUE, TRUE, 0);
-        }
-    }
-    else
-    {
-        /* hide menu bar and add menu item to toolbar */
-        if (menu)
-            gtk_widget_destroy (menu);
-
-        if (! menu_main)
-        {
-            menu_main = make_menu_main (accel);
-            g_signal_connect (menu_main, "destroy", (GCallback)
-             gtk_widget_destroyed, & menu_main);
-            g_signal_connect (menu_main, "hide", (GCallback) menu_hide_cb, NULL);
-        }
-
-        if (! menu_button)
-        {
-            menu_button = gtk_toggle_tool_button_new ();
-            gtk_tool_button_set_icon_name ((GtkToolButton *) menu_button, "audacious");
-            g_signal_connect (menu_button, "destroy", (GCallback)
-             gtk_widget_destroyed, & menu_button);
-            gtk_widget_show ((GtkWidget *) menu_button);
-            gtk_toolbar_insert ((GtkToolbar *) toolbar, menu_button, 0);
-            g_signal_connect (menu_button, "toggled", (GCallback) menu_button_cb, NULL);
-        }
-    }
-}
-
-void show_hide_infoarea (void)
-{
-    bool_t show = aud_get_bool ("gtkui", "infoarea_visible");
-
-    if (show && ! infoarea)
-    {
-        infoarea = ui_infoarea_new ();
-        g_signal_connect (infoarea, "destroy", (GCallback) gtk_widget_destroyed, & infoarea);
-        gtk_box_pack_end ((GtkBox *) vbox, infoarea, FALSE, FALSE, 0);
-        gtk_widget_show_all (infoarea);
-
-        show_hide_infoarea_vis ();
-    }
-
-    if (! show && infoarea)
-    {
-        gtk_widget_destroy (infoarea);
-        infoarea = NULL;
-    }
-}
-
-void show_hide_infoarea_vis (void)
-{
-    /* only turn on visualization if interface is shown */
-    ui_infoarea_show_vis (gtk_widget_get_visible (window) && aud_get_bool
-     ("gtkui", "infoarea_show_vis"));
-}
-
-void show_hide_statusbar (void)
-{
-    bool_t show = aud_get_bool ("gtkui", "statusbar_visible");
-
-    if (show && ! statusbar)
-    {
-        statusbar = ui_statusbar_new ();
-        g_signal_connect (statusbar, "destroy", (GCallback) gtk_widget_destroyed, & statusbar);
-        gtk_box_pack_end ((GtkBox *) vbox_outer, statusbar, FALSE, FALSE, 0);
-        gtk_widget_show_all (statusbar);
-    }
-
-    if (! show && statusbar)
-    {
-        gtk_widget_destroy (statusbar);
-        statusbar = NULL;
-    }
-}
-
-void popup_menu_rclick (unsigned button, uint32_t time)
-{
-    gtk_menu_popup ((GtkMenu *) menu_rclick, NULL, NULL, NULL, NULL, button,
-     time);
-}
-
-void popup_menu_tab (unsigned button, uint32_t time, int playlist)
-{
-    menu_tab_playlist_id = aud_playlist_get_unique_id (playlist);
-    gtk_menu_popup ((GtkMenu *) menu_tab, NULL, NULL, NULL, NULL, button, time);
-}
-
-void activate_search_tool (void)
-{
-    if (! search_tool)
-        return;
-
-    if (! aud_plugin_get_enabled (search_tool))
-        aud_plugin_enable (search_tool, TRUE);
-
-    aud_plugin_send_message (search_tool, "grab focus", NULL, 0);
-}
diff --git a/src/gtkui/ui_gtk.cc b/src/gtkui/ui_gtk.cc
new file mode 100644
index 000000000000..b70d005f8aaa
--- /dev/null
+++ b/src/gtkui/ui_gtk.cc
@@ -0,0 +1,1120 @@
+/*
+ * ui_gtk.c
+ * Copyright 2009-2012 William Pitcock, Tomasz Moń, Michał Lipski, and 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 <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.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 "gtkui.h"
+#include "layout.h"
+#include "ui_playlist_notebook.h"
+#include "ui_playlist_widget.h"
+#include "ui_infoarea.h"
+#include "ui_statusbar.h"
+#include "playlist_util.h"
+
+static const char * const gtkui_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",
+    "show_remaining_time", "FALSE",
+    "step_size", "5",
+
+    "player_x", "-1000",
+    "player_y", "-1000",
+    "player_width", "760",
+    "player_height", "460",
+
+    nullptr
+};
+
+class GtkUI : public IfacePlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("GTK Interface"),
+        PACKAGE,
+        nullptr,
+        & gtkui_prefs
+    };
+
+    constexpr GtkUI () : IfacePlugin (info) {}
+
+    bool init ();
+    void cleanup ();
+    void show (bool show);
+
+    void run ()
+        { gtk_main (); }
+    void quit ()
+        { gtk_main_quit (); }
+
+    void show_about_window ()
+        { audgui_show_about_window (); }
+    void hide_about_window ()
+        { audgui_hide_about_window (); }
+    void show_filebrowser (bool open)
+        { audgui_run_filebrowser (open); }
+    void hide_filebrowser ()
+        { audgui_hide_filebrowser (); }
+    void show_jump_to_song ()
+        { audgui_jump_to_track (); }
+    void hide_jump_to_song ()
+        { audgui_jump_to_track_hide (); }
+    void show_prefs_window ()
+        { audgui_show_prefs_window (); }
+    void hide_prefs_window ()
+        { audgui_hide_prefs_window (); }
+    void plugin_menu_add (AudMenuID id, void func (), const char * name, const char * icon)
+        { audgui_plugin_menu_add (id, func, name, icon); }
+    void plugin_menu_remove (AudMenuID id, void func ())
+        { audgui_plugin_menu_remove (id, func); }
+};
+
+EXPORT GtkUI aud_plugin_instance;
+
+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;
+
+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;
+static GtkWidget * slider, * label_time;
+static GtkWidget * menu_main, * menu_rclick, * menu_tab;
+
+static gboolean 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 void save_window_size ()
+{
+    int x, y, w, h;
+    gtk_window_get_position ((GtkWindow *) window, & x, & y);
+    gtk_window_get_size ((GtkWindow *) window, & w, & h);
+
+    aud_set_int ("gtkui", "player_x", x);
+    aud_set_int ("gtkui", "player_y", y);
+    aud_set_int ("gtkui", "player_width", w);
+    aud_set_int ("gtkui", "player_height", h);
+}
+
+static void restore_window_size ()
+{
+    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");
+
+    gtk_window_set_default_size ((GtkWindow *) window, w, h);
+
+    if (x > -1000 && y > -1000)
+        gtk_window_move ((GtkWindow *) window, x, y);
+}
+
+static gboolean window_delete ()
+{
+    bool handle = false;
+
+    hook_call ("window close", & handle);
+
+    if (handle)
+        return true;
+
+    aud_quit ();
+    return true;
+}
+
+static void button_open_pressed ()
+{
+    audgui_run_filebrowser (true);
+}
+
+static void button_add_pressed ()
+{
+    audgui_run_filebrowser (false);
+}
+
+void set_ab_repeat_a ()
+{
+    if (! aud_drct_get_playing ())
+        return;
+
+    int a, b;
+    aud_drct_get_ab_repeat (a, b);
+    a = aud_drct_get_time ();
+    aud_drct_set_ab_repeat (a, b);
+}
+
+void set_ab_repeat_b ()
+{
+    if (! aud_drct_get_playing ())
+        return;
+
+    int a, b;
+    aud_drct_get_ab_repeat (a, b);
+    b = aud_drct_get_time ();
+    aud_drct_set_ab_repeat (a, b);
+}
+
+void clear_ab_repeat ()
+{
+    aud_drct_set_ab_repeat (-1, -1);
+}
+
+static gboolean title_change_cb ()
+{
+    if (delayed_title_change_source)
+    {
+        g_source_remove (delayed_title_change_source);
+        delayed_title_change_source = 0;
+    }
+
+    if (aud_drct_get_playing ())
+    {
+        if (aud_drct_get_ready ())
+        {
+            String title = aud_drct_get_title ();
+            gtk_window_set_title ((GtkWindow *) window,
+             str_printf (_("%s - Audacious"), (const char *) title));
+        }
+        else
+            gtk_window_set_title ((GtkWindow *) window, _("Buffering ..."));
+    }
+    else
+        gtk_window_set_title ((GtkWindow *) window, _("Audacious"));
+
+    return false;
+}
+
+void GtkUI::show (bool show)
+{
+    if (show)
+    {
+        if (! gtk_widget_get_visible (window))
+            restore_window_size ();
+
+        gtk_window_present ((GtkWindow *) window);
+    }
+    else
+    {
+        if (gtk_widget_get_visible (window))
+            save_window_size ();
+
+        gtk_widget_hide (window);
+    }
+
+    show_hide_infoarea_vis ();
+}
+
+static void append_str (char * buf, int bufsize, const char * str)
+{
+    snprintf (buf + strlen (buf), bufsize - strlen (buf), "%s", str);
+}
+
+static void set_time_label (int time, int len)
+{
+    char s[128] = "<b>";
+
+    if (len && 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)
+    {
+        append_str (s, sizeof s, " / ");
+        append_str (s, sizeof s, str_format_time (len));
+
+        int a, b;
+        aud_drct_get_ab_repeat (a, b);
+
+        if (a >= 0)
+        {
+            append_str (s, sizeof s, " A=");
+            append_str (s, sizeof s, str_format_time (a));
+        }
+
+        if (b >= 0)
+        {
+            append_str (s, sizeof s, " B=");
+            append_str (s, sizeof s, str_format_time (b));
+        }
+    }
+
+    append_str (s, sizeof s, "</b>");
+
+    /* only update label if necessary */
+    if (strcmp (gtk_label_get_label ((GtkLabel *) label_time), s))
+        gtk_label_set_markup ((GtkLabel *) label_time, s);
+}
+
+static void set_slider (int time)
+{
+    gtk_range_set_value ((GtkRange *) slider, time);
+}
+
+static gboolean time_counter_cb ()
+{
+    if (slider_is_moving)
+        return true;
+
+    slider_seek_time = -1;  // delayed reset to avoid seeking twice
+
+    int time = aud_drct_get_time ();
+    int length = aud_drct_get_length ();
+
+    if (length > 0)
+        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);
+    }
+}
+
+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);
+
+    if (slider_is_moving)
+        slider_seek_time = time;
+    else if (time != slider_seek_time)  // avoid seeking twice
+        do_seek (time);
+
+    return false;
+}
+
+static gboolean ui_slider_button_press_cb (GtkWidget * widget, GdkEventButton * event)
+{
+    gboolean primary_warps = false;
+    g_object_get (gtk_widget_get_settings (widget),
+     "gtk-primary-button-warps-slider", & primary_warps, nullptr);
+
+    if (event->button == 1 && ! primary_warps)
+        event->button = 2;
+
+    slider_is_moving = true;
+    return false;
+}
+
+static gboolean ui_slider_button_release_cb (GtkWidget * widget, GdkEventButton * event)
+{
+    gboolean primary_warps = false;
+    g_object_get (gtk_widget_get_settings (widget),
+     "gtk-primary-button-warps-slider", & primary_warps, nullptr);
+
+    if (event->button == 1 && ! primary_warps)
+        event->button = 2;
+
+    if (slider_seek_time != -1)
+        do_seek (slider_seek_time);
+
+    slider_is_moving = false;
+    return false;
+}
+
+static gboolean ui_volume_value_changed_cb (GtkButton * button, double volume)
+{
+    aud_drct_set_volume_main (volume);
+    return true;
+}
+
+static void ui_volume_pressed_cb (GtkButton * button)
+{
+    volume_slider_is_moving = true;
+}
+
+static void ui_volume_released_cb (GtkButton * button)
+{
+    volume_slider_is_moving = false;
+}
+
+static gboolean ui_volume_slider_update (void * button)
+{
+    if (volume_slider_is_moving || ! button)
+        return true;
+
+    int volume = aud_drct_get_volume_main ();
+
+    if (volume == (int) gtk_scale_button_get_value ((GtkScaleButton *) button))
+        return true;
+
+    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)
+{
+    if (length > 0)
+    {
+        gtk_range_set_range ((GtkRange *) slider, 0, length);
+        gtk_widget_show (slider);
+    }
+    else
+        gtk_widget_hide (slider);
+}
+
+void update_step_size ()
+{
+    double step_size = aud_get_double ("gtkui", "step_size");
+    gtk_range_set_increments ((GtkRange *) slider, step_size * 1000, step_size * 1000);
+}
+
+static void pause_cb ()
+{
+    gtk_tool_button_set_icon_name ((GtkToolButton *) button_play,
+     aud_drct_get_paused () ? "media-playback-start" : "media-playback-pause");
+}
+
+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);
+}
+
+static void ui_playback_ready ()
+{
+    title_change_cb ();
+    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);
+
+    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);
+
+    gtk_tool_button_set_icon_name ((GtkToolButton *) button_play, "media-playback-start");
+    gtk_widget_set_sensitive ((GtkWidget *) button_stop, false);
+    gtk_widget_hide (slider);
+    gtk_widget_hide (label_time);
+}
+
+static GtkToolItem * toolbar_button_add (GtkWidget * toolbar,
+ void (* callback) (), const char * icon)
+{
+    GtkToolItem * item = gtk_tool_button_new (nullptr, nullptr);
+    gtk_tool_button_set_icon_name ((GtkToolButton *) item, icon);
+    gtk_toolbar_insert ((GtkToolbar *) toolbar, item, -1);
+    g_signal_connect (item, "clicked", callback, nullptr);
+    return item;
+}
+
+static GtkToolItem * toggle_button_new (const char * icon,
+ void (* toggled) (GtkToggleToolButton * button))
+{
+    GtkToolItem * item = gtk_toggle_tool_button_new ();
+    gtk_tool_button_set_icon_name ((GtkToolButton *) item, icon);
+    g_signal_connect (item, "toggled", (GCallback) toggled, nullptr);
+    return item;
+}
+
+static GtkWidget * markup_label_new (const char * str)
+{
+    GtkWidget * label = gtk_label_new (str);
+    gtk_label_set_use_markup ((GtkLabel *) label, true);
+    return label;
+}
+
+static void window_mapped_cb (GtkWidget * widget)
+{
+    gtk_widget_grab_focus (playlist_get_treeview (aud_playlist_get_active ()));
+}
+
+static gboolean window_keypress_cb (GtkWidget * widget, GdkEventKey * event)
+{
+    switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))
+    {
+      case 0:
+      {
+        GtkWidget * focused = gtk_window_get_focus ((GtkWindow *) window);
+
+        /* escape key returns focus to playlist */
+        if (event->keyval == GDK_KEY_Escape)
+        {
+            if (! focused || ! gtk_widget_is_ancestor (focused, (GtkWidget *) UI_PLAYLIST_NOTEBOOK))
+                gtk_widget_grab_focus (playlist_get_treeview (aud_playlist_get_active ()));
+
+            return false;
+        }
+
+        /* single-key shortcuts; must not interfere with text entry */
+        if (focused && GTK_IS_ENTRY (focused))
+            return false;
+
+        switch (event->keyval)
+        {
+        case 'z':
+            aud_drct_pl_prev ();
+            return true;
+        case 'x':
+            aud_drct_play ();
+            return true;
+        case 'c':
+        case ' ':
+            aud_drct_pause ();
+            return true;
+        case 'v':
+            aud_drct_stop ();
+            return true;
+        case 'b':
+            aud_drct_pl_next ();
+            return true;
+        case GDK_KEY_Left:
+            if (aud_drct_get_playing ())
+                do_seek (aud_drct_get_time () - aud_get_double ("gtkui", "step_size") * 1000);
+            return true;
+        case GDK_KEY_Right:
+            if (aud_drct_get_playing ())
+                do_seek (aud_drct_get_time () + aud_get_double ("gtkui", "step_size") * 1000);
+            return true;
+        }
+
+        return false;
+      }
+
+      case GDK_CONTROL_MASK:
+        switch (event->keyval)
+        {
+          case GDK_KEY_ISO_Left_Tab:
+          case GDK_KEY_Tab:
+            aud_playlist_set_active ((aud_playlist_get_active () + 1) %
+             aud_playlist_count ());
+            break;
+
+          default:
+            return false;
+        }
+        break;
+      case (GDK_CONTROL_MASK | GDK_SHIFT_MASK):
+        switch (event->keyval)
+        {
+          case GDK_KEY_ISO_Left_Tab:
+          case GDK_KEY_Tab:
+            aud_playlist_set_active (aud_playlist_get_active () ?
+             aud_playlist_get_active () - 1 : aud_playlist_count () - 1);
+            break;
+          default:
+            return false;
+        }
+        break;
+      case GDK_MOD1_MASK:
+        switch (event->keyval)
+        {
+          case GDK_KEY_Left:
+            if (aud_drct_get_playing ())
+                do_seek (aud_drct_get_time () - aud_get_double ("gtkui", "step_size") * 1000);
+            break;
+          case GDK_KEY_Right:
+            if (aud_drct_get_playing ())
+                do_seek (aud_drct_get_time () + aud_get_double ("gtkui", "step_size") * 1000);
+            break;
+          default:
+            return false;
+        }
+      default:
+        return false;
+    }
+
+    return true;
+}
+
+static gboolean playlist_keypress_cb (GtkWidget * widget, GdkEventKey * event)
+{
+    switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))
+    {
+    case 0:
+        switch (event->keyval)
+        {
+        case GDK_KEY_Escape:
+            ui_playlist_notebook_position (aud::to_ptr (aud_playlist_get_active ()), nullptr);
+            return true;
+        case GDK_KEY_Delete:
+            playlist_delete_selected ();
+            return true;
+        case GDK_KEY_Menu:
+            popup_menu_rclick (0, event->time);
+            return true;
+        }
+
+        break;
+    case GDK_CONTROL_MASK:
+        switch (event->keyval)
+        {
+        case 'x':
+            playlist_cut ();
+            return true;
+        case 'c':
+            playlist_copy ();
+            return true;
+        case 'v':
+            playlist_paste ();
+            return true;
+        case 'a':
+            aud_playlist_select_all (aud_playlist_get_active (), true);
+            return true;
+        }
+
+        break;
+    }
+
+    return false;
+}
+
+static void update_toggles (void * data, void * user)
+{
+    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_repeat,
+     aud_get_bool (nullptr, "repeat"));
+    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_shuffle,
+     aud_get_bool (nullptr, "shuffle"));
+}
+
+static void toggle_repeat (GtkToggleToolButton * button)
+{
+    aud_set_bool (nullptr, "repeat", gtk_toggle_tool_button_get_active (button));
+}
+
+static void toggle_shuffle (GtkToggleToolButton * button)
+{
+    aud_set_bool (nullptr, "shuffle", gtk_toggle_tool_button_get_active (button));
+}
+
+static void toggle_search_tool (GtkToggleToolButton * button)
+{
+    aud_plugin_enable (search_tool, gtk_toggle_tool_button_get_active (button));
+}
+
+static bool search_tool_toggled (PluginHandle * plugin, void *)
+{
+    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) search_button,
+     aud_plugin_get_enabled (plugin));
+    return true;
+}
+
+static void config_save ()
+{
+    if (gtk_widget_get_visible (window))
+        save_window_size ();
+
+    layout_save ();
+    pw_col_save ();
+}
+
+static void ui_hooks_associate ()
+{
+    hook_associate ("title change", (HookFunction) title_change_cb, 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);
+    hook_associate ("playback unpause", (HookFunction) pause_cb, nullptr);
+    hook_associate ("playback stop", (HookFunction) ui_playback_stop, nullptr);
+    hook_associate ("playlist update", ui_playlist_notebook_update, nullptr);
+    hook_associate ("playlist activate", ui_playlist_notebook_activate, nullptr);
+    hook_associate ("playlist set playing", ui_playlist_notebook_set_playing, nullptr);
+    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 ("config save", (HookFunction) config_save, nullptr);
+}
+
+static void ui_hooks_disassociate ()
+{
+    hook_dissociate ("title change", (HookFunction) title_change_cb);
+    hook_dissociate ("playback begin", (HookFunction) ui_playback_begin);
+    hook_dissociate ("playback ready", (HookFunction) ui_playback_ready);
+    hook_dissociate ("playback pause", (HookFunction) pause_cb);
+    hook_dissociate ("playback unpause", (HookFunction) pause_cb);
+    hook_dissociate ("playback stop", (HookFunction) ui_playback_stop);
+    hook_dissociate ("playlist update", ui_playlist_notebook_update);
+    hook_dissociate ("playlist activate", ui_playlist_notebook_activate);
+    hook_dissociate ("playlist set playing", ui_playlist_notebook_set_playing);
+    hook_dissociate ("playlist position", ui_playlist_notebook_position);
+    hook_dissociate ("set shuffle", update_toggles);
+    hook_dissociate ("set repeat", update_toggles);
+    hook_dissociate ("config save", (HookFunction) config_save);
+}
+
+static void add_dock_plugin (PluginHandle * plugin, void *)
+{
+    GtkWidget * widget = (GtkWidget *) aud_plugin_get_gtk_widget (plugin);
+    if (widget)
+        layout_add (plugin, widget);
+}
+
+static void remove_dock_plugin (PluginHandle * plugin, void *)
+{
+    layout_remove (plugin);
+}
+
+static void add_dock_plugins ()
+{
+    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);
+}
+
+static void remove_dock_plugins ()
+{
+    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);
+}
+
+bool GtkUI::init ()
+{
+    if (aud_get_mainloop_type () != MainloopType::GLib)
+        return false;
+
+    audgui_init ();
+
+    search_tool = aud_plugin_lookup_basename ("search-tool");
+
+    aud_config_set_defaults ("gtkui", gtkui_defaults);
+
+    pw_col_init ();
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+    accel = gtk_accel_group_new ();
+    gtk_window_add_accel_group ((GtkWindow *) window, accel);
+
+    vbox_outer = gtk_vbox_new (false, 0);
+    gtk_container_add ((GtkContainer *) window, vbox_outer);
+
+    menu_box = gtk_hbox_new (false, 0);
+    gtk_box_pack_start ((GtkBox *) vbox_outer, menu_box, false, false, 0);
+
+    toolbar = gtk_toolbar_new ();
+    gtk_toolbar_set_style ((GtkToolbar *) toolbar, GTK_TOOLBAR_ICONS);
+    gtk_box_pack_start ((GtkBox *) vbox_outer, toolbar, false, false, 0);
+
+    /* search button */
+    if (search_tool)
+    {
+        search_button = toggle_button_new ("edit-find", toggle_search_tool);
+        gtk_toolbar_insert ((GtkToolbar *) toolbar, search_button, -1);
+        gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) search_button,
+         aud_plugin_get_enabled (search_tool));
+        aud_plugin_add_watch (search_tool, search_tool_toggled, nullptr);
+    }
+
+    /* 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");
+
+    /* time slider and label */
+    GtkToolItem * boxitem1 = gtk_tool_item_new ();
+    gtk_tool_item_set_expand (boxitem1, true);
+    gtk_toolbar_insert ((GtkToolbar *) toolbar, boxitem1, -1);
+
+    GtkWidget * box1 = gtk_hbox_new (false, 0);
+    gtk_container_add ((GtkContainer *) boxitem1, box1);
+
+    slider = gtk_hscale_new (nullptr);
+    gtk_scale_set_draw_value ((GtkScale *) slider, false);
+    gtk_widget_set_size_request (slider, 120, -1);
+    gtk_widget_set_can_focus (slider, false);
+    gtk_box_pack_start ((GtkBox *) box1, slider, true, true, 6);
+
+    update_step_size ();
+
+    label_time = markup_label_new (nullptr);
+    gtk_box_pack_end ((GtkBox *) box1, label_time, false, false, 6);
+
+    gtk_widget_set_no_show_all (slider, true);
+    gtk_widget_set_no_show_all (label_time, true);
+
+    /* repeat and shuffle buttons */
+    button_repeat = toggle_button_new ("media-playlist-repeat", toggle_repeat);
+    gtk_toolbar_insert ((GtkToolbar *) toolbar, button_repeat, -1);
+    button_shuffle = toggle_button_new ("media-playlist-shuffle", toggle_shuffle);
+    gtk_toolbar_insert ((GtkToolbar *) toolbar, button_shuffle, -1);
+
+    /* volume button */
+    GtkToolItem * boxitem2 = gtk_tool_item_new ();
+    gtk_toolbar_insert ((GtkToolbar *) toolbar, boxitem2, -1);
+
+    GtkWidget * box2 = gtk_hbox_new (false, 0);
+    gtk_container_add ((GtkContainer *) boxitem2, box2);
+
+    volume = gtk_volume_button_new ();
+    g_object_set ((GObject *) volume, "size", GTK_ICON_SIZE_LARGE_TOOLBAR, nullptr);
+    gtk_button_set_relief ((GtkButton *) volume, GTK_RELIEF_NONE);
+    gtk_scale_button_set_adjustment ((GtkScaleButton *) volume,
+     (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 5, 0));
+    gtk_widget_set_can_focus (volume, false);
+
+    gtk_scale_button_set_value ((GtkScaleButton *) volume, aud_drct_get_volume_main ());
+
+    gtk_box_pack_start ((GtkBox *) box2, volume, false, false, 0);
+
+    /* main UI layout */
+    layout_load ();
+
+    GtkWidget * layout = layout_new ();
+    gtk_box_pack_start ((GtkBox *) vbox_outer, layout, true, true, 0);
+
+    vbox = gtk_vbox_new (false, 6);
+    layout_add_center (vbox);
+
+    ui_playlist_notebook_new ();
+    gtk_box_pack_start ((GtkBox *) vbox, (GtkWidget *) UI_PLAYLIST_NOTEBOOK, true, true, 0);
+
+    /* optional UI elements */
+    show_hide_menu ();
+    show_hide_infoarea ();
+    show_hide_statusbar ();
+
+    AUDDBG ("hooks associate\n");
+    ui_hooks_associate ();
+
+    AUDDBG ("playlist associate\n");
+    ui_playlist_notebook_populate ();
+
+    g_signal_connect (slider, "change-value", (GCallback) ui_slider_change_value_cb , nullptr);
+    g_signal_connect (slider, "button-press-event", (GCallback) ui_slider_button_press_cb, nullptr);
+    g_signal_connect (slider, "button-release-event", (GCallback) ui_slider_button_release_cb, nullptr);
+
+    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);
+
+    g_signal_connect (window, "map-event", (GCallback) window_mapped_cb, nullptr);
+    g_signal_connect (window, "delete-event", (GCallback) window_delete, nullptr);
+    g_signal_connect (window, "key-press-event", (GCallback) window_keypress_cb, nullptr);
+    g_signal_connect (UI_PLAYLIST_NOTEBOOK, "key-press-event", (GCallback) playlist_keypress_cb, nullptr);
+
+    if (aud_drct_get_playing ())
+    {
+        ui_playback_begin ();
+        if (aud_drct_get_ready ())
+            ui_playback_ready ();
+    }
+    else
+        ui_playback_stop ();
+
+    title_change_cb ();
+
+    gtk_widget_show_all (vbox_outer);
+
+    update_toggles (nullptr, nullptr);
+
+    menu_rclick = make_menu_rclick (accel);
+    menu_tab = make_menu_tab (accel);
+
+    add_dock_plugins ();
+
+    return true;
+}
+
+void GtkUI::cleanup ()
+{
+    remove_dock_plugins ();
+
+    if (menu_main)
+        gtk_widget_destroy (menu_main);
+
+    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;
+    }
+
+    ui_hooks_disassociate ();
+
+    if (search_tool)
+        aud_plugin_remove_watch (search_tool, search_tool_toggled, nullptr);
+
+    gtk_widget_destroy (window);
+    layout_cleanup ();
+
+    audgui_cleanup ();
+}
+
+static void menu_position_cb (GtkMenu * menu, int * x, int * y, int * push, void * button)
+{
+    GtkAllocation alloc;
+    int xorig, yorig, xwin, ywin;
+
+    gtk_widget_get_allocation ((GtkWidget *) button, & alloc);
+    gdk_window_get_origin (gtk_widget_get_window (window), & xorig, & yorig);
+    gtk_widget_translate_coordinates ((GtkWidget *) button, window, 0, 0, & xwin, & ywin);
+
+    * x = xorig + xwin;
+    * y = yorig + ywin + alloc.height;
+    * push = true;
+}
+
+static void menu_button_cb ()
+{
+    if (gtk_toggle_tool_button_get_active ((GtkToggleToolButton *) menu_button))
+        gtk_menu_popup ((GtkMenu *) menu_main, nullptr, nullptr, menu_position_cb,
+         menu_button, 0, gtk_get_current_event_time ());
+    else
+        gtk_widget_hide (menu_main);
+}
+
+static void menu_hide_cb ()
+{
+    gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) menu_button, false);
+}
+
+void show_hide_menu ()
+{
+    if (aud_get_bool ("gtkui", "menu_visible"))
+    {
+        /* remove menu button from toolbar and show menu bar */
+        if (menu_main)
+            gtk_widget_destroy (menu_main);
+        if (menu_button)
+            gtk_widget_destroy ((GtkWidget *) menu_button);
+
+        if (! menu)
+        {
+            menu = make_menu_bar (accel);
+            g_signal_connect (menu, "destroy", (GCallback) gtk_widget_destroyed,
+             & menu);
+            gtk_widget_show (menu);
+            gtk_box_pack_start ((GtkBox *) menu_box, menu, true, true, 0);
+        }
+    }
+    else
+    {
+        /* hide menu bar and add menu item to toolbar */
+        if (menu)
+            gtk_widget_destroy (menu);
+
+        if (! menu_main)
+        {
+            menu_main = make_menu_main (accel);
+            g_signal_connect (menu_main, "destroy", (GCallback)
+             gtk_widget_destroyed, & menu_main);
+            g_signal_connect (menu_main, "hide", (GCallback) menu_hide_cb, nullptr);
+        }
+
+        if (! menu_button)
+        {
+            menu_button = gtk_toggle_tool_button_new ();
+            gtk_tool_button_set_icon_name ((GtkToolButton *) menu_button, "audacious");
+            g_signal_connect (menu_button, "destroy", (GCallback)
+             gtk_widget_destroyed, & menu_button);
+            gtk_widget_show ((GtkWidget *) menu_button);
+            gtk_toolbar_insert ((GtkToolbar *) toolbar, menu_button, 0);
+            g_signal_connect (menu_button, "toggled", (GCallback) menu_button_cb, nullptr);
+        }
+    }
+}
+
+void show_hide_infoarea ()
+{
+    bool show = aud_get_bool ("gtkui", "infoarea_visible");
+
+    if (show && ! infoarea)
+    {
+        infoarea = ui_infoarea_new ();
+        g_signal_connect (infoarea, "destroy", (GCallback) gtk_widget_destroyed, & infoarea);
+        gtk_box_pack_end ((GtkBox *) vbox, infoarea, false, false, 0);
+        gtk_widget_show_all (infoarea);
+
+        show_hide_infoarea_vis ();
+    }
+
+    if (! show && infoarea)
+    {
+        gtk_widget_destroy (infoarea);
+        infoarea = nullptr;
+    }
+}
+
+void show_hide_infoarea_vis ()
+{
+    /* only turn on visualization if interface is shown */
+    ui_infoarea_show_vis (gtk_widget_get_visible (window) && aud_get_bool
+     ("gtkui", "infoarea_show_vis"));
+}
+
+void show_hide_statusbar ()
+{
+    bool show = aud_get_bool ("gtkui", "statusbar_visible");
+
+    if (show && ! statusbar)
+    {
+        statusbar = ui_statusbar_new ();
+        g_signal_connect (statusbar, "destroy", (GCallback) gtk_widget_destroyed, & statusbar);
+        gtk_box_pack_end ((GtkBox *) vbox_outer, statusbar, false, false, 0);
+        gtk_widget_show_all (statusbar);
+    }
+
+    if (! show && statusbar)
+    {
+        gtk_widget_destroy (statusbar);
+        statusbar = nullptr;
+    }
+}
+
+void popup_menu_rclick (unsigned button, uint32_t time)
+{
+    gtk_menu_popup ((GtkMenu *) menu_rclick, nullptr, nullptr, nullptr, nullptr, button,
+     time);
+}
+
+void popup_menu_tab (unsigned button, uint32_t time, int playlist)
+{
+    menu_tab_playlist_id = aud_playlist_get_unique_id (playlist);
+    gtk_menu_popup ((GtkMenu *) menu_tab, nullptr, nullptr, nullptr, nullptr, button, time);
+}
+
+void activate_search_tool ()
+{
+    if (! search_tool)
+        return;
+
+    aud_plugin_enable (search_tool, true);
+    layout_focus (search_tool);
+}
+
+void activate_playlist_manager ()
+{
+    PluginHandle * manager = aud_plugin_lookup_basename ("playlist-manager");
+    if (! manager)
+        return;
+
+    aud_plugin_enable (manager, true);
+    layout_focus (manager);
+}
diff --git a/src/gtkui/ui_infoarea.c b/src/gtkui/ui_infoarea.c
deleted file mode 100644
index e92876f722ea..000000000000
--- a/src/gtkui/ui_infoarea.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * ui_infoarea.c
- * Copyright 2010-2012 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:
- *
- * 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 <math.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#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 */
-
-typedef struct {
-    GtkWidget * box, * main;
-
-    char * title, * artist, * album; /* pooled */
-    char * last_title, * last_artist, * last_album; /* pooled */
-    float alpha, last_alpha;
-
-    bool_t stopped;
-    int fade_timeout;
-
-    GdkPixbuf * pb, * last_pb;
-} UIInfoArea;
-
-static struct {
-    GtkWidget * widget;
-    char bars[VIS_BANDS];
-    char delay[VIS_BANDS];
-} vis;
-
-/****************************************************************************/
-
-static UIInfoArea * area = NULL;
-
-static void vis_render_cb (const float * freq)
-{
-    /* xscale[i] = pow (256, i / VIS_BANDS) - 0.5; */
-    const float xscale[VIS_BANDS + 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 < VIS_BANDS; i ++)
-    {
-        int a = ceilf (xscale[i]);
-        int b = floorf (xscale[i + 1]);
-        float n = 0;
-
-        if (b < a)
-            n += freq[b] * (xscale[i + 1] - xscale[i]);
-        else
-        {
-            if (a > 0)
-                n += freq[a - 1] * (a - xscale[i]);
-            for (; a < b; a ++)
-                n += freq[a];
-            if (b < 256)
-                n += freq[b] * (xscale[i + 1] - b);
-        }
-
-        /* 40 dB range */
-        int x = 40 + 20 * log10f (n);
-        x = CLAMP (x, 0, 40);
-
-        vis.bars[i] -= MAX (0, VIS_FALLOFF - vis.delay[i]);
-
-        if (vis.delay[i])
-            vis.delay[i] --;
-
-        if (x > vis.bars[i])
-        {
-            vis.bars[i] = x;
-            vis.delay[i] = VIS_DELAY;
-        }
-    }
-
-    if (vis.widget)
-        gtk_widget_queue_draw (vis.widget);
-}
-
-static void vis_clear_cb (void)
-{
-    memset (vis.bars, 0, sizeof vis.bars);
-    memset (vis.delay, 0, sizeof vis.delay);
-
-    if (vis.widget)
-        gtk_widget_queue_draw (vis.widget);
-}
-
-/****************************************************************************/
-
-static void clear (GtkWidget * widget, cairo_t * cr)
-{
-    GtkAllocation alloc;
-    gtk_widget_get_allocation (widget, & alloc);
-
-    cairo_pattern_t * gradient = cairo_pattern_create_linear (0, 0, 0, alloc.height);
-    cairo_pattern_add_color_stop_rgb (gradient, 0, 0.25, 0.25, 0.25);
-    cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.15, 0.15, 0.15);
-    cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.1, 0.1, 0.1);
-    cairo_pattern_add_color_stop_rgb (gradient, 1, 0, 0, 0);
-
-    cairo_set_source (cr, gradient);
-    cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
-    cairo_fill (cr);
-
-    cairo_pattern_destroy (gradient);
-}
-
-static void draw_text (GtkWidget * widget, cairo_t * cr, int x, int y, int
- width, float r, float g, float b, float a, const char * font,
- const char * text)
-{
-    cairo_move_to(cr, x, y);
-    cairo_set_operator(cr, CAIRO_OPERATOR_ATOP);
-    cairo_set_source_rgba(cr, r, g, b, a);
-
-    PangoFontDescription * desc = pango_font_description_from_string (font);
-    PangoLayout * pl = gtk_widget_create_pango_layout (widget, NULL);
-    pango_layout_set_text (pl, text, -1);
-    pango_layout_set_font_description(pl, desc);
-    pango_font_description_free(desc);
-    pango_layout_set_width (pl, width * PANGO_SCALE);
-    pango_layout_set_ellipsize (pl, PANGO_ELLIPSIZE_END);
-
-    pango_cairo_show_layout(cr, pl);
-
-    g_object_unref(pl);
-}
-
-/****************************************************************************/
-
-static void rgb_to_hsv (float r, float g, float b, float * h, float * s,
- float * v)
-{
-    float max, min;
-
-    max = r;
-    if (g > max)
-        max = g;
-    if (b > max)
-        max = b;
-
-    min = r;
-    if (g < min)
-        min = g;
-    if (b < min)
-        min = b;
-
-    * v = max;
-
-    if (max == min)
-    {
-        * h = 0;
-        * s = 0;
-        return;
-    }
-
-    if (r == max)
-        * h = 1 + (g - b) / (max - min);
-    else if (g == max)
-        * h = 3 + (b - r) / (max - min);
-    else
-        * h = 5 + (r - g) / (max - min);
-
-    * s = (max - min) / max;
-}
-
-static void hsv_to_rgb (float h, float s, float v, float * r, float * g,
- float * b)
-{
-    for (; h >= 2; h -= 2)
-    {
-        float * p = r;
-        r = g;
-        g = b;
-        b = p;
-    }
-
-    if (h < 1)
-    {
-        * r = 1;
-        * g = 0;
-        * b = 1 - h;
-    }
-    else
-    {
-        * r = 1;
-        * g = h - 1;
-        * b = 0;
-    }
-
-    * r = v * (1 - s * (1 - * r));
-    * g = v * (1 - s * (1 - * g));
-    * b = v * (1 - s * (1 - * b));
-}
-
-static void get_color (int i, float * r, float * g, float * b)
-{
-    static GdkRGBA c;
-    static bool_t valid = FALSE;
-
-    if (! valid)
-    {
-        /* we want a color that matches the current theme
-         * selected color of a GtkEntry should be reasonable */
-        GtkStyleContext * style = gtk_style_context_new ();
-        GtkWidgetPath * path = gtk_widget_path_new ();
-        gtk_widget_path_append_type (path, GTK_TYPE_ENTRY);
-        gtk_style_context_set_path (style, path);
-        gtk_widget_path_free (path);
-        gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED, & c);
-        g_object_unref (style);
-        valid = TRUE;
-    }
-
-    float h, s, v;
-    rgb_to_hsv (c.red, c.green, c.blue, & 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);
-
-    hsv_to_rgb (h, s, v, r, g, b);
-}
-
-static bool_t draw_vis_cb (GtkWidget * widget, cairo_t * cr)
-{
-    clear (widget, cr);
-
-    for (int i = 0; i < VIS_BANDS; i++)
-    {
-        int x = SPACING + 8 * i;
-        int t = VIS_CENTER - vis.bars[i];
-        int m = MIN (VIS_CENTER + vis.bars[i], HEIGHT);
-
-        float r, g, b;
-        get_color (i, & r, & g, & b);
-
-        cairo_set_source_rgb (cr, r, g, b);
-        cairo_rectangle (cr, x, t, 6, VIS_CENTER - t);
-        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_fill (cr);
-    }
-
-    return TRUE;
-}
-
-static void draw_album_art (cairo_t * cr)
-{
-    g_return_if_fail (area);
-
-    if (area->pb != NULL)
-    {
-        gdk_cairo_set_source_pixbuf (cr, area->pb, SPACING, SPACING);
-        cairo_paint_with_alpha (cr, area->alpha);
-    }
-
-    if (area->last_pb != NULL)
-    {
-        gdk_cairo_set_source_pixbuf (cr, area->last_pb, SPACING, SPACING);
-        cairo_paint_with_alpha (cr, area->last_alpha);
-    }
-}
-
-static void draw_title (cairo_t * cr)
-{
-    g_return_if_fail (area);
-
-    GtkAllocation alloc;
-    gtk_widget_get_allocation (area->main, & alloc);
-
-    int x = ICON_SIZE + SPACING * 2;
-    int width = alloc.width - x;
-
-    if (area->title != NULL)
-        draw_text (area->main, cr, x, SPACING, width, 1, 1, 1, area->alpha,
-         "18", area->title);
-    if (area->last_title != NULL)
-        draw_text (area->main, cr, x, SPACING, width, 1, 1, 1, area->last_alpha,
-         "18", area->last_title);
-    if (area->artist != NULL)
-        draw_text (area->main, cr, x, SPACING + ICON_SIZE / 2, width, 1, 1, 1,
-         area->alpha, "9", area->artist);
-    if (area->last_artist != NULL)
-        draw_text (area->main, cr, x, SPACING + ICON_SIZE / 2, width, 1, 1, 1,
-         area->last_alpha, "9", area->last_artist);
-    if (area->album != NULL)
-        draw_text (area->main, cr, x, SPACING + ICON_SIZE * 3 / 4, width, 0.7,
-         0.7, 0.7, area->alpha, "9", area->album);
-    if (area->last_album != NULL)
-        draw_text (area->main, cr, x, SPACING + ICON_SIZE * 3 / 4, width, 0.7,
-         0.7, 0.7, area->last_alpha, "9", area->last_album);
-}
-
-static bool_t draw_cb (GtkWidget * widget, cairo_t * cr)
-{
-    g_return_val_if_fail (area, FALSE);
-
-    clear (widget, cr);
-
-    draw_album_art (cr);
-    draw_title (cr);
-
-    return TRUE;
-}
-
-static bool_t ui_infoarea_do_fade (void)
-{
-    g_return_val_if_fail (area, FALSE);
-    bool_t ret = FALSE;
-
-    if (aud_drct_get_playing () && area->alpha < 1)
-    {
-        area->alpha += 0.1;
-        ret = TRUE;
-    }
-
-    if (area->last_alpha > 0)
-    {
-        area->last_alpha -= 0.1;
-        ret = TRUE;
-    }
-
-    gtk_widget_queue_draw (area->main);
-
-    if (! ret)
-        area->fade_timeout = 0;
-
-    return ret;
-}
-
-static void ui_infoarea_set_title (void)
-{
-    g_return_if_fail (area);
-
-    if (! aud_drct_get_playing ())
-        return;
-
-    int playlist = aud_playlist_get_playing ();
-    int entry = aud_playlist_get_position (playlist);
-
-    char * title, * artist, * album;
-    aud_playlist_entry_describe (playlist, entry, & title, & artist, & album, TRUE);
-
-    if (! g_strcmp0 (title, area->title) && ! g_strcmp0 (artist, area->artist)
-     && ! g_strcmp0 (album, area->album))
-    {
-        str_unref (title);
-        str_unref (artist);
-        str_unref (album);
-        return;
-    }
-
-    str_unref (area->title);
-    str_unref (area->artist);
-    str_unref (area->album);
-    area->title = title;
-    area->artist = artist;
-    area->album = album;
-
-    gtk_widget_queue_draw (area->main);
-}
-
-static void set_album_art (void)
-{
-    g_return_if_fail (area);
-
-    if (area->pb)
-        g_object_unref (area->pb);
-
-    area->pb = audgui_pixbuf_request_current ();
-    if (! area->pb)
-        area->pb = audgui_pixbuf_fallback ();
-    if (area->pb)
-        audgui_pixbuf_scale_within (& area->pb, ICON_SIZE);
-}
-
-static void album_art_ready (void)
-{
-    g_return_if_fail (area);
-
-    if (! aud_drct_get_playing ())
-        return;
-
-    set_album_art ();
-    gtk_widget_queue_draw (area->main);
-}
-
-static void infoarea_next (void)
-{
-    g_return_if_fail (area);
-
-    if (area->last_pb)
-        g_object_unref (area->last_pb);
-    area->last_pb = area->pb;
-    area->pb = NULL;
-
-    str_unref (area->last_title);
-    area->last_title = area->title;
-    area->title = NULL;
-
-    str_unref (area->last_artist);
-    area->last_artist = area->artist;
-    area->artist = NULL;
-
-    str_unref (area->last_album);
-    area->last_album = area->album;
-    area->album = NULL;
-
-    area->last_alpha = area->alpha;
-    area->alpha = 0;
-
-    gtk_widget_queue_draw (area->main);
-}
-
-static void ui_infoarea_playback_start (void)
-{
-    g_return_if_fail (area);
-
-    if (! area->stopped) /* moved to the next song without stopping? */
-        infoarea_next ();
-    area->stopped = FALSE;
-
-    ui_infoarea_set_title ();
-    set_album_art ();
-
-    if (! area->fade_timeout)
-        area->fade_timeout = g_timeout_add (30, (GSourceFunc)
-         ui_infoarea_do_fade, area);
-}
-
-static void ui_infoarea_playback_stop (void)
-{
-    g_return_if_fail (area);
-
-    infoarea_next ();
-    area->stopped = TRUE;
-
-    if (! area->fade_timeout)
-        area->fade_timeout = g_timeout_add (30, (GSourceFunc)
-         ui_infoarea_do_fade, area);
-}
-
-static void realize_cb (GtkWidget * widget)
-{
-    /* using a native window avoids redrawing parent widgets */
-    gdk_window_ensure_native (gtk_widget_get_window (widget));
-}
-
-void ui_infoarea_show_vis (bool_t show)
-{
-    if (! area)
-        return;
-
-    if (show)
-    {
-        if (vis.widget)
-            return;
-
-        vis.widget = gtk_drawing_area_new ();
-
-        /* note: "realize" signal must be connected before adding to box */
-        g_signal_connect (vis.widget, "realize", (GCallback) realize_cb, NULL);
-
-        gtk_widget_set_size_request (vis.widget, VIS_WIDTH + 2 * SPACING, HEIGHT);
-        gtk_box_pack_start ((GtkBox *) area->box, vis.widget, FALSE, FALSE, 0);
-
-        g_signal_connect (vis.widget, "draw", (GCallback) draw_vis_cb, NULL);
-        gtk_widget_show (vis.widget);
-
-        aud_vis_func_add (AUD_VIS_TYPE_CLEAR, (VisFunc) vis_clear_cb);
-        aud_vis_func_add (AUD_VIS_TYPE_FREQ, (VisFunc) vis_render_cb);
-    }
-    else
-    {
-        if (! vis.widget)
-            return;
-
-        aud_vis_func_remove ((VisFunc) vis_clear_cb);
-        aud_vis_func_remove ((VisFunc) vis_render_cb);
-
-        gtk_widget_destroy (vis.widget);
-
-        memset (& vis, 0, sizeof vis);
-    }
-}
-
-static void destroy_cb (GtkWidget * widget)
-{
-    g_return_if_fail (area);
-
-    ui_infoarea_show_vis (FALSE);
-
-    hook_dissociate ("playlist update", (HookFunction) ui_infoarea_set_title);
-    hook_dissociate ("playback begin", (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;
-    }
-
-    str_unref (area->title);
-    str_unref (area->artist);
-    str_unref (area->album);
-    str_unref (area->last_title);
-    str_unref (area->last_artist);
-    str_unref (area->last_album);
-
-    if (area->pb)
-        g_object_unref (area->pb);
-    if (area->last_pb)
-        g_object_unref (area->last_pb);
-
-    g_slice_free (UIInfoArea, area);
-    area = NULL;
-}
-
-GtkWidget * ui_infoarea_new (void)
-{
-    g_return_val_if_fail (! area, NULL);
-    area = g_slice_new0 (UIInfoArea);
-
-    area->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
-    area->main = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (area->main, ICON_SIZE + 2 * SPACING, HEIGHT);
-    gtk_box_pack_start ((GtkBox *) area->box, area->main, TRUE, TRUE, 0);
-
-    g_signal_connect (area->main, "draw", (GCallback) draw_cb, NULL);
-
-    hook_associate ("playlist update", (HookFunction) ui_infoarea_set_title, NULL);
-    hook_associate ("playback begin", (HookFunction) ui_infoarea_playback_start, NULL);
-    hook_associate ("playback stop", (HookFunction) ui_infoarea_playback_stop, NULL);
-    hook_associate ("current art ready", (HookFunction) album_art_ready, NULL);
-
-    g_signal_connect (area->box, "destroy", (GCallback) destroy_cb, NULL);
-
-    if (aud_drct_get_playing ())
-    {
-        ui_infoarea_playback_start ();
-
-        /* 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 (NULL);
-    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
-    gtk_container_add ((GtkContainer *) frame, area->box);
-    return frame;
-}
diff --git a/src/gtkui/ui_infoarea.cc b/src/gtkui/ui_infoarea.cc
new file mode 100644
index 000000000000..d3c9bc880d28
--- /dev/null
+++ b/src/gtkui/ui_infoarea.cc
@@ -0,0 +1,566 @@
+/*
+ * ui_infoarea.c
+ * Copyright 2010-2012 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:
+ *
+ * 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 <math.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/interface.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+#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 */
+
+typedef struct {
+    GtkWidget * box, * main;
+
+    String title, artist, album;
+    String last_title, last_artist, last_album;
+    float alpha, last_alpha;
+
+    bool stopped;
+    int fade_timeout;
+
+    GdkPixbuf * pb, * last_pb;
+} UIInfoArea;
+
+class InfoAreaVis : public Visualizer
+{
+public:
+    constexpr InfoAreaVis () :
+        Visualizer (Freq) {}
+
+    GtkWidget * widget = nullptr;
+    char bars[VIS_BANDS] {};
+    char delay[VIS_BANDS] {};
+
+    void clear ();
+    void render_freq (const float * freq);
+};
+
+static InfoAreaVis vis;
+
+/****************************************************************************/
+
+static UIInfoArea * area = nullptr;
+
+void InfoAreaVis::render_freq (const float * freq)
+{
+    /* xscale[i] = pow (256, i / VIS_BANDS) - 0.5; */
+    const float xscale[VIS_BANDS + 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 < VIS_BANDS; i ++)
+    {
+        int a = ceilf (xscale[i]);
+        int b = floorf (xscale[i + 1]);
+        float n = 0;
+
+        if (b < a)
+            n += freq[b] * (xscale[i + 1] - xscale[i]);
+        else
+        {
+            if (a > 0)
+                n += freq[a - 1] * (a - xscale[i]);
+            for (; a < b; a ++)
+                n += freq[a];
+            if (b < 256)
+                n += freq[b] * (xscale[i + 1] - b);
+        }
+
+        /* 40 dB range */
+        int x = 40 + 20 * log10f (n);
+        x = aud::clamp (x, 0, 40);
+
+        bars[i] -= aud::max (0, VIS_FALLOFF - delay[i]);
+
+        if (delay[i])
+            delay[i] --;
+
+        if (x > bars[i])
+        {
+            bars[i] = x;
+            delay[i] = VIS_DELAY;
+        }
+    }
+
+    if (widget)
+        gtk_widget_queue_draw (widget);
+}
+
+void InfoAreaVis::clear ()
+{
+    memset (bars, 0, sizeof bars);
+    memset (delay, 0, sizeof delay);
+
+    if (widget)
+        gtk_widget_queue_draw (widget);
+}
+
+/****************************************************************************/
+
+static void clear (GtkWidget * widget, cairo_t * cr)
+{
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (widget, & alloc);
+
+    cairo_pattern_t * gradient = cairo_pattern_create_linear (0, 0, 0, alloc.height);
+    cairo_pattern_add_color_stop_rgb (gradient, 0, 0.25, 0.25, 0.25);
+    cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.15, 0.15, 0.15);
+    cairo_pattern_add_color_stop_rgb (gradient, 0.5, 0.1, 0.1, 0.1);
+    cairo_pattern_add_color_stop_rgb (gradient, 1, 0, 0, 0);
+
+    cairo_set_source (cr, gradient);
+    cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
+    cairo_fill (cr);
+
+    cairo_pattern_destroy (gradient);
+}
+
+static void draw_text (GtkWidget * widget, cairo_t * cr, int x, int y, int
+ width, float r, float g, float b, float a, const char * font,
+ const char * text)
+{
+    cairo_move_to (cr, x, y);
+    cairo_set_source_rgba (cr, r, g, b, a);
+
+    PangoFontDescription * desc = pango_font_description_from_string (font);
+    PangoLayout * pl = gtk_widget_create_pango_layout (widget, nullptr);
+    pango_layout_set_text (pl, text, -1);
+    pango_layout_set_font_description (pl, desc);
+    pango_font_description_free (desc);
+    pango_layout_set_width (pl, width * PANGO_SCALE);
+    pango_layout_set_ellipsize (pl, PANGO_ELLIPSIZE_END);
+
+    pango_cairo_show_layout (cr, pl);
+
+    g_object_unref (pl);
+}
+
+/****************************************************************************/
+
+static void rgb_to_hsv (float r, float g, float b, float * h, float * s,
+ float * v)
+{
+    float max, min;
+
+    max = r;
+    if (g > max)
+        max = g;
+    if (b > max)
+        max = b;
+
+    min = r;
+    if (g < min)
+        min = g;
+    if (b < min)
+        min = b;
+
+    * v = max;
+
+    if (max == min)
+    {
+        * h = 0;
+        * s = 0;
+        return;
+    }
+
+    if (r == max)
+        * h = 1 + (g - b) / (max - min);
+    else if (g == max)
+        * h = 3 + (b - r) / (max - min);
+    else
+        * h = 5 + (r - g) / (max - min);
+
+    * s = (max - min) / max;
+}
+
+static void hsv_to_rgb (float h, float s, float v, float * r, float * g,
+ float * b)
+{
+    for (; h >= 2; h -= 2)
+    {
+        float * p = r;
+        r = g;
+        g = b;
+        b = p;
+    }
+
+    if (h < 1)
+    {
+        * r = 1;
+        * g = 0;
+        * b = 1 - h;
+    }
+    else
+    {
+        * r = 1;
+        * g = h - 1;
+        * b = 0;
+    }
+
+    * r = v * (1 - s * (1 - * r));
+    * g = v * (1 - s * (1 - * g));
+    * b = v * (1 - s * (1 - * b));
+}
+
+static void get_color (GtkWidget * widget, int i, float * r, float * g, float * b)
+{
+    GdkColor * c = (gtk_widget_get_style (widget))->base + GTK_STATE_SELECTED;
+    float h, s, v;
+
+    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);
+
+    hsv_to_rgb (h, s, v, r, g, b);
+}
+
+static int expose_vis_cb (GtkWidget * widget, GdkEventExpose * event)
+{
+    cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+    clear (widget, cr);
+
+    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);
+
+        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_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_fill (cr);
+    }
+
+    cairo_destroy (cr);
+    return true;
+}
+
+static void draw_album_art (cairo_t * cr)
+{
+    g_return_if_fail (area);
+
+    if (area->pb)
+    {
+        gdk_cairo_set_source_pixbuf (cr, area->pb, SPACING, SPACING);
+        cairo_paint_with_alpha (cr, area->alpha);
+    }
+
+    if (area->last_pb)
+    {
+        gdk_cairo_set_source_pixbuf (cr, area->last_pb, SPACING, SPACING);
+        cairo_paint_with_alpha (cr, area->last_alpha);
+    }
+}
+
+static void draw_title (cairo_t * cr)
+{
+    g_return_if_fail (area);
+
+    GtkAllocation alloc;
+    gtk_widget_get_allocation (area->main, & alloc);
+
+    int x = ICON_SIZE + SPACING * 2;
+    int width = alloc.width - x;
+
+    if (area->title)
+        draw_text (area->main, cr, x, SPACING, width, 1, 1, 1, area->alpha,
+         "18", area->title);
+    if (area->last_title)
+        draw_text (area->main, cr, x, SPACING, width, 1, 1, 1, area->last_alpha,
+         "18", area->last_title);
+    if (area->artist)
+        draw_text (area->main, cr, x, SPACING + ICON_SIZE / 2, width, 1, 1, 1,
+         area->alpha, "9", area->artist);
+    if (area->last_artist)
+        draw_text (area->main, cr, x, SPACING + ICON_SIZE / 2, width, 1, 1, 1,
+         area->last_alpha, "9", area->last_artist);
+    if (area->album)
+        draw_text (area->main, cr, x, SPACING + ICON_SIZE * 3 / 4, width, 0.7,
+         0.7, 0.7, area->alpha, "9", area->album);
+    if (area->last_album)
+        draw_text (area->main, cr, x, SPACING + ICON_SIZE * 3 / 4, width, 0.7,
+         0.7, 0.7, area->last_alpha, "9", area->last_album);
+}
+
+static int expose_cb (GtkWidget * widget, GdkEventExpose * event)
+{
+    cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
+
+    clear (widget, cr);
+
+    draw_album_art (cr);
+    draw_title (cr);
+
+    cairo_destroy (cr);
+    return true;
+}
+
+static gboolean ui_infoarea_do_fade ()
+{
+    g_return_val_if_fail (area, false);
+    gboolean ret = false;
+
+    if (aud_drct_get_playing () && area->alpha < 1)
+    {
+        area->alpha += 0.1;
+        ret = true;
+    }
+
+    if (area->last_alpha > 0)
+    {
+        area->last_alpha -= 0.1;
+        ret = true;
+    }
+
+    gtk_widget_queue_draw (area->main);
+
+    if (! ret)
+        area->fade_timeout = 0;
+
+    return ret;
+}
+
+static void ui_infoarea_set_title ()
+{
+    g_return_if_fail (area);
+
+    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);
+
+    if (! g_strcmp0 (title, area->title) && ! g_strcmp0 (artist, area->artist)
+     && ! g_strcmp0 (album, area->album))
+        return;
+
+    area->title = std::move (title);
+    area->artist = std::move (artist);
+    area->album = std::move (album);
+
+    gtk_widget_queue_draw (area->main);
+}
+
+static void set_album_art ()
+{
+    g_return_if_fail (area);
+
+    if (area->pb)
+        g_object_unref (area->pb);
+
+    area->pb = audgui_pixbuf_request_current ();
+    if (! area->pb)
+        area->pb = audgui_pixbuf_fallback ();
+    if (area->pb)
+        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);
+
+    if (area->last_pb)
+        g_object_unref (area->last_pb);
+    area->last_pb = area->pb;
+    area->pb = nullptr;
+
+    area->last_title = std::move (area->title);
+    area->last_artist = std::move (area->artist);
+    area->last_album = std::move (area->album);
+
+    area->last_alpha = area->alpha;
+    area->alpha = 0;
+
+    gtk_widget_queue_draw (area->main);
+}
+
+static void ui_infoarea_playback_start ()
+{
+    g_return_if_fail (area);
+
+    if (! area->stopped) /* moved to the next song without stopping? */
+        infoarea_next ();
+    area->stopped = false;
+
+    ui_infoarea_set_title ();
+    set_album_art ();
+
+    if (! area->fade_timeout)
+        area->fade_timeout = g_timeout_add (30, (GSourceFunc)
+         ui_infoarea_do_fade, area);
+}
+
+static void ui_infoarea_playback_stop ()
+{
+    g_return_if_fail (area);
+
+    infoarea_next ();
+    area->stopped = true;
+
+    if (! area->fade_timeout)
+        area->fade_timeout = g_timeout_add (30, (GSourceFunc)
+         ui_infoarea_do_fade, area);
+}
+
+static void realize_cb (GtkWidget * widget)
+{
+    /* using a native window avoids redrawing parent widgets */
+    gdk_window_ensure_native (gtk_widget_get_window (widget));
+}
+
+void ui_infoarea_show_vis (bool show)
+{
+    if (! area)
+        return;
+
+    if (show)
+    {
+        if (vis.widget)
+            return;
+
+        vis.widget = gtk_drawing_area_new ();
+
+        /* note: "realize" signal must be connected before adding to box */
+        g_signal_connect (vis.widget, "realize", (GCallback) realize_cb, nullptr);
+
+        gtk_widget_set_size_request (vis.widget, VIS_WIDTH + 2 * SPACING, HEIGHT);
+        gtk_box_pack_start ((GtkBox *) area->box, vis.widget, false, false, 0);
+
+        g_signal_connect (vis.widget, "expose-event", (GCallback) expose_vis_cb, nullptr);
+        gtk_widget_show (vis.widget);
+
+        aud_visualizer_add (& vis);
+    }
+    else
+    {
+        if (! vis.widget)
+            return;
+
+        aud_visualizer_remove (& vis);
+
+        gtk_widget_destroy (vis.widget);
+        vis.widget = nullptr;
+
+        vis.clear ();
+    }
+}
+
+static void destroy_cb (GtkWidget * widget)
+{
+    g_return_if_fail (area);
+
+    ui_infoarea_show_vis (false);
+
+    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;
+    }
+
+    if (area->pb)
+        g_object_unref (area->pb);
+    if (area->last_pb)
+        g_object_unref (area->last_pb);
+
+    delete area;
+    area = nullptr;
+}
+
+GtkWidget * ui_infoarea_new ()
+{
+    g_return_val_if_fail (! area, nullptr);
+    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_box_pack_start ((GtkBox *) area->box, area->main, true, true, 0);
+
+    g_signal_connect (area->main, "expose-event", (GCallback) expose_cb, nullptr);
+
+    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 ();
+
+        /* 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);
+    gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
+    gtk_container_add ((GtkContainer *) frame, area->box);
+    return frame;
+}
diff --git a/src/gtkui/ui_infoarea.h b/src/gtkui/ui_infoarea.h
index 55874716d1e1..2377455741bd 100644
--- a/src/gtkui/ui_infoarea.h
+++ b/src/gtkui/ui_infoarea.h
@@ -22,7 +22,7 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * ui_infoarea_new (void);
-void ui_infoarea_show_vis (bool_t show);
+GtkWidget * ui_infoarea_new ();
+void ui_infoarea_show_vis (bool show);
 
 #endif
diff --git a/src/gtkui/ui_playlist_notebook.c b/src/gtkui/ui_playlist_notebook.c
deleted file mode 100644
index f0bd92aa18e3..000000000000
--- a/src/gtkui/ui_playlist_notebook.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * ui_playlist_notebook.c
- * Copyright 2010-2012 Michał Lipski and 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 <stdlib.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/list.h>
-#include <libaudgui/libaudgui.h>
-
-#include "gtkui.h"
-#include "ui_playlist_notebook.h"
-#include "ui_playlist_widget.h"
-#include "playlist_util.h"
-
-static GtkWidget * notebook = NULL;
-static int highlighted = -1;
-
-static int switch_handler = 0;
-static int reorder_handler = 0;
-
-static void add_button_cb (GtkButton * button, void * unused)
-{
-    aud_playlist_insert (-1);
-    aud_playlist_set_active (aud_playlist_count () - 1);
-}
-
-static void make_add_button (GtkWidget * notebook)
-{
-    GtkWidget * button = gtk_button_new ();
-    gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE);
-    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
-     ("list-add", GTK_ICON_SIZE_MENU));
-    gtk_widget_set_can_focus (button, FALSE);
-
-    g_signal_connect (button, "clicked", (GCallback) add_button_cb, NULL);
-    gtk_widget_show_all (button);
-
-    gtk_notebook_set_action_widget ((GtkNotebook *) notebook, button, GTK_PACK_END);
-}
-
-static void close_button_cb (GtkWidget * button, void * id)
-{
-    audgui_confirm_playlist_delete (aud_playlist_by_unique_id (GPOINTER_TO_INT (id)));
-}
-
-static GtkWidget * make_close_button (GtkWidget * ebox, int list)
-{
-    GtkWidget * button = gtk_button_new ();
-    GtkWidget * image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_MENU);
-    gtk_button_set_image ((GtkButton *) button, image);
-    gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE);
-    gtk_button_set_focus_on_click ((GtkButton *) button, FALSE);
-    gtk_widget_set_name (button, "gtkui-tab-close-button");
-
-    g_signal_connect (button, "clicked", (GCallback) close_button_cb,
-     GINT_TO_POINTER (aud_playlist_get_unique_id (list)));
-
-    GtkCssProvider * provider = gtk_css_provider_new ();
-    gtk_css_provider_load_from_data (provider,
-     "#gtkui-tab-close-button {"
-     " -GtkButton-default-border: 0;"
-     " -GtkButton-default-outside-border: 0;"
-     " -GtkButton-inner-border: 0;"
-     " -GtkWidget-focus-padding: 0;"
-     " -GtkWidget-focus-line-width: 0;"
-     " margin: 0;"
-     " padding: 0; }",
-     -1, NULL);
-
-    gtk_style_context_add_provider (gtk_widget_get_style_context (button),
-     GTK_STYLE_PROVIDER (provider),
-     GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-    g_object_unref (provider);
-
-    gtk_widget_show (button);
-
-    return button;
-}
-
-GtkNotebook *ui_playlist_get_notebook(void)
-{
-    return GTK_NOTEBOOK(notebook);
-}
-
-static void save_column_widths ()
-{
-    int current = gtk_notebook_get_current_page ((GtkNotebook *) notebook);
-    GtkWidget * treeview = playlist_get_treeview (current);
-
-    char * widths, * expand;
-    ui_playlist_widget_get_column_widths (treeview, & widths, & expand);
-
-    aud_set_str ("gtkui", "column_widths", widths);
-    aud_set_str ("gtkui", "column_expand", expand);
-
-    str_unref (widths);
-    str_unref (expand);
-}
-
-static void apply_column_widths (GtkWidget * treeview)
-{
-    char * widths = aud_get_str ("gtkui", "column_widths");
-    char * expand = aud_get_str ("gtkui", "column_expand");
-
-    if (widths && widths[0] && expand && expand[0])
-        ui_playlist_widget_set_column_widths (treeview, widths, expand);
-
-    str_unref (widths);
-    str_unref (expand);
-}
-
-static void tab_title_reset(GtkWidget *ebox)
-{
-    GtkWidget *label = g_object_get_data(G_OBJECT(ebox), "label");
-    GtkWidget *entry = g_object_get_data(G_OBJECT(ebox), "entry");
-    gtk_widget_hide(entry);
-    gtk_widget_show(label);
-}
-
-static void tab_title_save(GtkEntry *entry, void * ebox)
-{
-    int id = GPOINTER_TO_INT (g_object_get_data ((GObject *) ebox, "playlist-id"));
-    GtkWidget *label = g_object_get_data(G_OBJECT(ebox), "label");
-
-    aud_playlist_set_title (aud_playlist_by_unique_id (id), gtk_entry_get_text (entry));
-    gtk_widget_hide(GTK_WIDGET(entry));
-    gtk_widget_show(label);
-}
-
-static bool_t tab_key_press_cb(GtkWidget *widget, GdkEventKey *event, void * user_data)
-{
-    if (event->keyval == GDK_KEY_Escape)
-        tab_title_reset(widget);
-
-    return FALSE;
-}
-
-static bool_t tab_button_press_cb(GtkWidget *ebox, GdkEventButton *event, void * user_data)
-{
-    int id = GPOINTER_TO_INT (g_object_get_data ((GObject *) ebox, "playlist-id"));
-    int playlist = aud_playlist_by_unique_id (id);
-
-    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
-        aud_drct_play_playlist (playlist);
-
-    if (event->type == GDK_BUTTON_PRESS && event->button == 2)
-        audgui_confirm_playlist_delete (playlist);
-
-    if (event->type == GDK_BUTTON_PRESS && event->button == 3)
-        popup_menu_tab (event->button, event->time, playlist);
-
-    return FALSE;
-}
-
-static bool_t scroll_cb (GtkWidget * widget, GdkEventScroll * event)
-{
-    switch (event->direction)
-    {
-    case GDK_SCROLL_UP:
-    case GDK_SCROLL_LEFT:
-        aud_playlist_set_active (aud_playlist_get_active () - 1);
-        return TRUE;
-
-    case GDK_SCROLL_DOWN:
-    case GDK_SCROLL_RIGHT:
-        aud_playlist_set_active (aud_playlist_get_active () + 1);
-        return TRUE;
-
-    default:
-        return FALSE;
-    }
-}
-
-static void tab_changed (GtkNotebook * notebook, GtkWidget * page, int
- page_num, void * unused)
-{
-    save_column_widths ();
-    apply_column_widths (playlist_get_treeview (page_num));
-
-    aud_playlist_set_active (page_num);
-}
-
-static void tab_reordered(GtkNotebook *notebook, GtkWidget *child, unsigned page_num, void * user_data)
-{
-    GtkWidget * widget = g_object_get_data ((GObject *) child, "treeview");
-    g_return_if_fail (widget);
-    aud_playlist_reorder (ui_playlist_widget_get_playlist (widget), page_num, 1);
-}
-
-static GtkLabel *get_tab_label(int playlist)
-{
-    GtkWidget *page = gtk_notebook_get_nth_page(UI_PLAYLIST_NOTEBOOK, playlist);
-    GtkWidget *ebox = gtk_notebook_get_tab_label(UI_PLAYLIST_NOTEBOOK, page);
-    return GTK_LABEL(g_object_get_data(G_OBJECT(ebox), "label"));
-}
-
-static void set_tab_label (int list, GtkLabel * label)
-{
-    char * title = aud_playlist_get_title (list);
-
-    if (aud_get_bool ("gtkui", "entry_count_visible"))
-    {
-        char * temp = str_printf ("%s (%d)", title, aud_playlist_entry_count (list));
-        str_unref (title);
-        title = temp;
-    }
-
-    if (list == aud_playlist_get_playing ())
-    {
-        char * markup = g_markup_printf_escaped ("<b>%s</b>", title);
-        gtk_label_set_markup (label, markup);
-        g_free (markup);
-    }
-    else
-        gtk_label_set_text (label, title);
-
-    str_unref (title);
-}
-
-void start_rename_playlist (int playlist)
-{
-    if (! gtk_notebook_get_show_tabs ((GtkNotebook *) notebook))
-    {
-        audgui_show_playlist_rename (playlist);
-        return;
-    }
-
-    GtkWidget * page = gtk_notebook_get_nth_page (UI_PLAYLIST_NOTEBOOK, playlist);
-    GtkWidget * ebox = gtk_notebook_get_tab_label (UI_PLAYLIST_NOTEBOOK, page);
-
-    GtkWidget *label = g_object_get_data(G_OBJECT(ebox), "label");
-    GtkWidget *entry = g_object_get_data(G_OBJECT(ebox), "entry");
-    gtk_widget_hide(label);
-
-    char * title = aud_playlist_get_title (playlist);
-    gtk_entry_set_text ((GtkEntry *) entry, title);
-    str_unref (title);
-    gtk_widget_grab_focus(entry);
-    gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
-    gtk_widget_show(entry);
-}
-
-void ui_playlist_notebook_create_tab(int playlist)
-{
-    GtkWidget *scrollwin, *treeview;
-    GtkWidget *label, *entry, *ebox, *hbox;
-    GtkAdjustment *vscroll;
-    int position = aud_playlist_get_position (playlist);
-
-    scrollwin = gtk_scrolled_window_new(NULL, NULL);
-    vscroll = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrollwin));
-
-    treeview = ui_playlist_widget_new(playlist);
-    apply_column_widths (treeview);
-
-    g_object_set_data(G_OBJECT(scrollwin), "treeview", treeview);
-
-    gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-    gtk_widget_show_all(scrollwin);
-
-    ebox = gtk_event_box_new();
-    gtk_event_box_set_visible_window ((GtkEventBox *) ebox, FALSE);
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
-
-    label = gtk_label_new ("");
-    set_tab_label (playlist, (GtkLabel *) label);
-    gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
-    entry = gtk_entry_new();
-    gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
-    gtk_container_add(GTK_CONTAINER(ebox), hbox);
-    gtk_widget_show_all(ebox);
-    gtk_widget_hide(entry);
-
-    GtkWidget * button = NULL;
-
-    if (aud_get_bool ("gtkui", "close_button_visible"))
-    {
-        button = make_close_button (ebox, playlist);
-        gtk_box_pack_end ((GtkBox *) hbox, button, FALSE, FALSE, 0);
-    }
-
-    g_object_set_data(G_OBJECT(ebox), "label", label);
-    g_object_set_data(G_OBJECT(ebox), "entry", entry);
-    g_object_set_data(G_OBJECT(ebox), "page", scrollwin);
-
-    gtk_notebook_insert_page (UI_PLAYLIST_NOTEBOOK, scrollwin, ebox, playlist);
-    gtk_notebook_set_tab_reorderable(UI_PLAYLIST_NOTEBOOK, scrollwin, TRUE);
-
-    int id = aud_playlist_get_unique_id (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));
-
-    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);
-        audgui_list_set_focus (treeview, position);
-    }
-
-    g_signal_connect(ebox, "button-press-event", G_CALLBACK(tab_button_press_cb), NULL);
-    g_signal_connect(ebox, "key-press-event", G_CALLBACK(tab_key_press_cb), NULL);
-    g_signal_connect(entry, "activate", G_CALLBACK(tab_title_save), ebox);
-    g_signal_connect_swapped (vscroll, "value-changed",
-     G_CALLBACK(ui_playlist_widget_scroll), treeview);
-
-    /* we have to connect to "scroll-event" on the notebook, the tabs, AND the
-     * close buttons (sigh) */
-    gtk_widget_add_events (ebox, GDK_SCROLL_MASK);
-    g_signal_connect (ebox, "scroll-event", (GCallback) scroll_cb, NULL);
-
-    if (button)
-    {
-        gtk_widget_add_events (button, GDK_SCROLL_MASK);
-        g_signal_connect (button, "scroll-event", (GCallback) scroll_cb, NULL);
-    }
-}
-
-void ui_playlist_notebook_populate(void)
-{
-    int playlists = aud_playlist_count();
-    int count;
-
-    for (count = 0; count < playlists; count++)
-        ui_playlist_notebook_create_tab(count);
-
-    gtk_notebook_set_current_page (UI_PLAYLIST_NOTEBOOK, aud_playlist_get_active ());
-    highlighted = aud_playlist_get_unique_id (aud_playlist_get_playing ());
-
-    if (! switch_handler)
-        switch_handler = g_signal_connect (notebook, "switch-page", (GCallback)
-         tab_changed, NULL);
-    if (! reorder_handler)
-        reorder_handler = g_signal_connect (notebook, "page-reordered",
-         (GCallback) tab_reordered, NULL);
-
-    gtk_widget_grab_focus (playlist_get_treeview (aud_playlist_get_active ()));
-}
-
-void ui_playlist_notebook_empty (void)
-{
-    if (switch_handler)
-        g_signal_handler_disconnect (notebook, switch_handler);
-    switch_handler = 0;
-    if (reorder_handler)
-        g_signal_handler_disconnect (notebook, reorder_handler);
-    reorder_handler = 0;
-
-    int n_pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
-    while (n_pages)
-        gtk_notebook_remove_page ((GtkNotebook *) notebook, -- n_pages);
-}
-
-static void add_remove_pages (void)
-{
-    g_signal_handlers_block_by_func (notebook, (void *) tab_changed, NULL);
-    g_signal_handlers_block_by_func (notebook, (void *) tab_reordered, NULL);
-
-    save_column_widths ();
-
-    int lists = aud_playlist_count ();
-    int pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
-
-    /* scan through existing treeviews */
-    for (int i = 0; i < pages; )
-    {
-        GtkWidget * page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, i);
-        GtkWidget * tree = g_object_get_data ((GObject *) page, "treeview");
-        int tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
-
-        /* do we have an orphaned treeview? */
-        if (aud_playlist_by_unique_id (tree_id) < 0)
-        {
-            gtk_notebook_remove_page ((GtkNotebook *) notebook, i);
-            pages --;
-            continue;
-        }
-
-        /* do we have the right treeview? */
-        int list_id = aud_playlist_get_unique_id (i);
-
-        if (tree_id == list_id)
-        {
-            ui_playlist_widget_set_playlist (tree, i);
-            i ++;
-            continue;
-        }
-
-        /* look for the right treeview */
-        int found = FALSE;
-
-        for (int j = i + 1; j < pages; j ++)
-        {
-            page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, j);
-            tree = g_object_get_data ((GObject *) page, "treeview");
-            tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
-
-            /* found it? move it to the right place */
-            if (tree_id == list_id)
-            {
-                gtk_notebook_reorder_child ((GtkNotebook *) notebook, page, i);
-                found = TRUE;
-                break;
-            }
-        }
-
-        /* didn't find it? create it */
-        if (! found)
-        {
-            ui_playlist_notebook_create_tab (i);
-            pages ++;
-            continue;
-        }
-    }
-
-    /* create new treeviews */
-    while (pages < lists)
-    {
-        ui_playlist_notebook_create_tab (pages);
-        pages ++;
-    }
-
-    int active = aud_playlist_get_active ();
-    apply_column_widths (playlist_get_treeview (active));
-    gtk_notebook_set_current_page ((GtkNotebook *) notebook, active);
-
-    show_hide_playlist_tabs ();
-
-    g_signal_handlers_unblock_by_func (notebook, (void *) tab_changed, NULL);
-    g_signal_handlers_unblock_by_func (notebook, (void *) tab_reordered, NULL);
-}
-
-void ui_playlist_notebook_update (void * data, void * user)
-{
-    int global_level = GPOINTER_TO_INT (data);
-
-    if (global_level == PLAYLIST_UPDATE_STRUCTURE)
-        add_remove_pages ();
-
-    int lists = aud_playlist_count ();
-
-    for (int list = 0; list < lists; list ++)
-    {
-        if (global_level >= PLAYLIST_UPDATE_METADATA)
-            set_tab_label (list, get_tab_label (list));
-
-        GtkWidget * treeview = playlist_get_treeview (list);
-
-        int at, count;
-        int level = aud_playlist_updated_range (list, & at, & count);
-
-        if (level)
-            ui_playlist_widget_update (treeview, level, at, count);
-
-        audgui_list_set_highlight (treeview, aud_playlist_get_position (list));
-    }
-
-    gtk_notebook_set_current_page ((GtkNotebook *) notebook, aud_playlist_get_active ());
-}
-
-void ui_playlist_notebook_position (void * data, void * user)
-{
-    int list = GPOINTER_TO_INT (data);
-    int row = aud_playlist_get_position (list);
-
-    if (aud_get_bool ("gtkui", "autoscroll"))
-    {
-        aud_playlist_select_all (list, FALSE);
-        aud_playlist_entry_set_selected (list, row, TRUE);
-        aud_playlist_set_focus (list, row);
-    }
-
-    if (! aud_playlist_update_pending ())
-        audgui_list_set_highlight (playlist_get_treeview (list), row);
-}
-
-void ui_playlist_notebook_activate (void * data, void * user)
-{
-    if (! aud_playlist_update_pending ())
-        gtk_notebook_set_current_page ((GtkNotebook *) notebook, aud_playlist_get_active ());
-}
-
-void ui_playlist_notebook_set_playing (void * data, void * user)
-{
-    int new = aud_playlist_get_unique_id (aud_playlist_get_playing ());
-
-    if (highlighted == new)
-        return;
-
-    int pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
-
-    for (int i = 0; i < pages; i ++)
-    {
-        GtkWidget * page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, i);
-        GtkWidget * tree = g_object_get_data ((GObject *) page, "treeview");
-        int tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
-
-        if (tree_id == highlighted || tree_id == new)
-            set_tab_label (i, get_tab_label (i));
-    }
-
-    highlighted = new;
-}
-
-static void destroy_cb (void)
-{
-    hook_dissociate ("config save", (HookFunction) save_column_widths);
-
-    notebook = NULL;
-    switch_handler = 0;
-    reorder_handler = 0;
-}
-
-GtkWidget * ui_playlist_notebook_new (void)
-{
-    notebook = gtk_notebook_new ();
-    gtk_notebook_set_scrollable ((GtkNotebook *) notebook, TRUE);
-    make_add_button (notebook);
-
-    show_hide_playlist_tabs ();
-
-    hook_associate ("config save", (HookFunction) save_column_widths, NULL);
-
-    gtk_widget_add_events (notebook, GDK_SCROLL_MASK);
-    g_signal_connect (notebook, "scroll-event", (GCallback) scroll_cb, NULL);
-    g_signal_connect (notebook, "destroy", (GCallback) destroy_cb, NULL);
-
-    return notebook;
-}
-
-void show_hide_playlist_tabs (void)
-{
-    gtk_notebook_set_show_tabs ((GtkNotebook *) notebook, aud_get_bool ("gtkui",
-     "playlist_tabs_visible") || aud_playlist_count () > 1);
-}
diff --git a/src/gtkui/ui_playlist_notebook.cc b/src/gtkui/ui_playlist_notebook.cc
new file mode 100644
index 000000000000..dc919cbafaac
--- /dev/null
+++ b/src/gtkui/ui_playlist_notebook.cc
@@ -0,0 +1,573 @@
+/*
+ * ui_playlist_notebook.c
+ * Copyright 2010-2012 Michał Lipski and 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 <stdlib.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudgui/list.h>
+#include <libaudgui/libaudgui.h>
+
+#include "gtkui.h"
+#include "ui_playlist_notebook.h"
+#include "ui_playlist_widget.h"
+#include "playlist_util.h"
+
+static GtkWidget * notebook = nullptr;
+static int highlighted = -1;
+
+static int switch_handler = 0;
+static int reorder_handler = 0;
+
+void apply_column_widths (GtkWidget * treeview)
+{
+    /* skip righthand column since it expands with the window */
+    for (int i = 0; i < pw_num_cols - 1; i ++)
+    {
+        GtkTreeViewColumn * col = gtk_tree_view_get_column ((GtkTreeView *) treeview, i);
+        gtk_tree_view_column_set_fixed_width (col, pw_col_widths[pw_cols[i]]);
+    }
+}
+
+static void size_allocate_cb (GtkWidget * treeview)
+{
+    int current = gtk_notebook_get_current_page ((GtkNotebook *) notebook);
+
+    if (current < 0 || treeview != playlist_get_treeview (current))
+        return;
+
+    bool changed = false;
+
+    /* skip righthand column since it expands with the window */
+    for (int i = 0; i < pw_num_cols - 1; i ++)
+    {
+        GtkTreeViewColumn * col = gtk_tree_view_get_column ((GtkTreeView *) treeview, i);
+        int width = gtk_tree_view_column_get_width (col);
+
+        if (width != pw_col_widths[pw_cols[i]])
+        {
+            pw_col_widths[pw_cols[i]] = width;
+            changed = true;
+        }
+    }
+
+    if (changed)
+    {
+        int count = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
+
+        for (int i = 0; i < count; i ++)
+        {
+            if (i != current)
+                apply_column_widths (playlist_get_treeview (i));
+        }
+    }
+}
+
+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 ();
+    gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE);
+    gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name
+     ("list-add", GTK_ICON_SIZE_MENU));
+    gtk_widget_set_can_focus (button, false);
+
+    g_signal_connect (button, "clicked", (GCallback) add_button_cb, nullptr);
+    gtk_widget_show_all (button);
+
+    gtk_notebook_set_action_widget ((GtkNotebook *) notebook, button, GTK_PACK_END);
+}
+
+static void close_button_cb (GtkWidget * button, void * id)
+{
+    audgui_confirm_playlist_delete (aud_playlist_by_unique_id (GPOINTER_TO_INT (id)));
+}
+
+static void close_button_style_set (GtkWidget * button)
+{
+    int w, h;
+    gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
+     GTK_ICON_SIZE_MENU, & w, & h);
+    gtk_widget_set_size_request (button, w + 2, h + 2);
+}
+
+static GtkWidget * make_close_button (GtkWidget * ebox, int list)
+{
+    GtkWidget * button = gtk_button_new ();
+    GtkWidget * image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_MENU);
+    gtk_button_set_image ((GtkButton *) button, image);
+    gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE);
+    gtk_button_set_focus_on_click ((GtkButton *) button, false);
+    gtk_widget_set_name (button, "gtkui-tab-close-button");
+
+    g_signal_connect (button, "clicked", (GCallback) close_button_cb,
+     GINT_TO_POINTER (aud_playlist_get_unique_id (list)));
+
+    gtk_rc_parse_string (
+     "style \"gtkui-tab-close-button-style\" {"
+     " GtkButton::default-border = {0, 0, 0, 0}"
+     " GtkButton::default-outside-border = {0, 0, 0, 0}"
+     " GtkButton::inner-border = {0, 0, 0, 0}"
+     " GtkWidget::focus-padding = 0"
+     " GtkWidget::focus-line-width = 0"
+     " xthickness = 0"
+     " ythickness = 0 }"
+     "widget \"*.gtkui-tab-close-button\" style \"gtkui-tab-close-button-style\""
+    );
+
+    g_signal_connect (button, "style-set", (GCallback) close_button_style_set, nullptr);
+
+    gtk_widget_show (button);
+
+    return button;
+}
+
+GtkNotebook * ui_playlist_get_notebook ()
+{
+    return (GtkNotebook *) notebook;
+}
+
+static void tab_title_reset (GtkWidget * ebox)
+{
+    GtkWidget * label = (GtkWidget *) g_object_get_data ((GObject *) ebox, "label");
+    GtkWidget * entry = (GtkWidget *) g_object_get_data ((GObject *) ebox, "entry");
+    gtk_widget_hide (entry);
+    gtk_widget_show (label);
+}
+
+static void tab_title_save (GtkEntry * entry, void * ebox)
+{
+    int id = GPOINTER_TO_INT (g_object_get_data ((GObject *) ebox, "playlist-id"));
+    GtkWidget * label = (GtkWidget *) g_object_get_data ((GObject *) ebox, "label");
+
+    aud_playlist_set_title (aud_playlist_by_unique_id (id), gtk_entry_get_text (entry));
+    gtk_widget_hide ((GtkWidget *) entry);
+    gtk_widget_show (label);
+}
+
+static gboolean tab_key_press_cb (GtkWidget * widget, GdkEventKey * event)
+{
+    if (event->keyval == GDK_KEY_Escape)
+        tab_title_reset (widget);
+
+    return false;
+}
+
+static gboolean tab_button_press_cb (GtkWidget * ebox, GdkEventButton * event)
+{
+    int id = GPOINTER_TO_INT (g_object_get_data ((GObject *) ebox, "playlist-id"));
+    int playlist = aud_playlist_by_unique_id (id);
+
+    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+        aud_playlist_play (playlist);
+
+    if (event->type == GDK_BUTTON_PRESS && event->button == 2)
+        audgui_confirm_playlist_delete (playlist);
+
+    if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+        popup_menu_tab (event->button, event->time, playlist);
+
+    return false;
+}
+
+static gboolean scroll_cb (GtkWidget * widget, GdkEventScroll * event)
+{
+    switch (event->direction)
+    {
+    case GDK_SCROLL_UP:
+    case GDK_SCROLL_LEFT:
+        aud_playlist_set_active (aud_playlist_get_active () - 1);
+        return true;
+
+    case GDK_SCROLL_DOWN:
+    case GDK_SCROLL_RIGHT:
+        aud_playlist_set_active (aud_playlist_get_active () + 1);
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+static gboolean scroll_ignore_cb ()
+{
+    return true;
+}
+
+static void tab_changed (GtkNotebook * notebook, GtkWidget * page, unsigned page_num)
+{
+    aud_playlist_set_active (page_num);
+}
+
+static void tab_reordered (GtkNotebook * notebook, GtkWidget * child, unsigned page_num)
+{
+    GtkWidget * widget = (GtkWidget *) g_object_get_data ((GObject *) child, "treeview");
+    g_return_if_fail (widget);
+    aud_playlist_reorder (ui_playlist_widget_get_playlist (widget), page_num, 1);
+}
+
+static GtkLabel * get_tab_label (int playlist)
+{
+    GtkWidget * page = gtk_notebook_get_nth_page (UI_PLAYLIST_NOTEBOOK, playlist);
+    GtkWidget * ebox = gtk_notebook_get_tab_label (UI_PLAYLIST_NOTEBOOK, page);
+    return (GtkLabel *) g_object_get_data ((GObject *) ebox, "label");
+}
+
+static void set_tab_label (int list, GtkLabel * label)
+{
+    String title0 = aud_playlist_get_title (list);
+    StringBuf title = aud_get_bool ("gtkui", "entry_count_visible") ?
+     str_printf ("%s (%d)", (const char *) title0, aud_playlist_entry_count (list)) :
+     str_copy (title0);
+
+    if (list == aud_playlist_get_playing ())
+    {
+        char * markup = g_markup_printf_escaped ("<b>%s</b>", (const char *) title);
+        gtk_label_set_markup (label, markup);
+        g_free (markup);
+    }
+    else
+        gtk_label_set_text (label, title);
+}
+
+void start_rename_playlist (int playlist)
+{
+    if (! gtk_notebook_get_show_tabs ((GtkNotebook *) notebook))
+    {
+        audgui_show_playlist_rename (playlist);
+        return;
+    }
+
+    GtkWidget * page = gtk_notebook_get_nth_page (UI_PLAYLIST_NOTEBOOK, playlist);
+    GtkWidget * ebox = gtk_notebook_get_tab_label (UI_PLAYLIST_NOTEBOOK, page);
+
+    GtkWidget * label = (GtkWidget *) g_object_get_data ((GObject *) ebox, "label");
+    GtkWidget * entry = (GtkWidget *) g_object_get_data ((GObject *) ebox, "entry");
+    gtk_widget_hide (label);
+
+    gtk_entry_set_text ((GtkEntry *) entry, aud_playlist_get_title (playlist));
+
+    gtk_widget_grab_focus (entry);
+    gtk_editable_select_region ((GtkEditable *) entry, 0, -1);
+    gtk_widget_show (entry);
+}
+
+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);
+
+    /* do not allow scroll events to propagate up to the notebook */
+    g_signal_connect_after (scrollwin, "scroll-event", (GCallback) scroll_ignore_cb, nullptr);
+
+    GtkWidget * treeview = ui_playlist_widget_new (playlist);
+
+    apply_column_widths (treeview);
+    g_signal_connect (treeview, "size-allocate", (GCallback) size_allocate_cb, nullptr);
+
+    g_object_set_data ((GObject *) scrollwin, "treeview", treeview);
+
+    gtk_container_add ((GtkContainer *) scrollwin, treeview);
+    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrollwin,
+     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_widget_show_all (scrollwin);
+
+    GtkWidget * ebox = gtk_event_box_new ();
+    gtk_event_box_set_visible_window ((GtkEventBox *) ebox, false);
+
+    GtkWidget * hbox = gtk_hbox_new (false, 2);
+
+    GtkWidget * label = gtk_label_new ("");
+    set_tab_label (playlist, (GtkLabel *) label);
+    gtk_box_pack_start ((GtkBox *) hbox, label, false, false, 0);
+
+    GtkWidget * entry = gtk_entry_new ();
+    gtk_box_pack_start ((GtkBox *) hbox, entry, false, false, 0);
+    gtk_container_add ((GtkContainer *) ebox, hbox);
+    gtk_widget_show_all (ebox);
+    gtk_widget_hide (entry);
+
+    GtkWidget * button = nullptr;
+
+    if (aud_get_bool ("gtkui", "close_button_visible"))
+    {
+        button = make_close_button (ebox, playlist);
+        gtk_box_pack_end ((GtkBox *) hbox, button, false, false, 0);
+    }
+
+    g_object_set_data ((GObject *) ebox, "label", label);
+    g_object_set_data ((GObject *) ebox, "entry", entry);
+    g_object_set_data ((GObject *) ebox, "page", scrollwin);
+
+    gtk_notebook_insert_page (UI_PLAYLIST_NOTEBOOK, scrollwin, ebox, playlist);
+    gtk_notebook_set_tab_reorderable (UI_PLAYLIST_NOTEBOOK, scrollwin, true);
+
+    int id = aud_playlist_get_unique_id (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));
+
+    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);
+        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);
+    g_signal_connect (entry, "activate", (GCallback) tab_title_save, ebox);
+    g_signal_connect_swapped (vscroll, "value-changed",
+     (GCallback) ui_playlist_widget_scroll, treeview);
+
+    /* we have to connect to "scroll-event" on the notebook, the tabs, AND the
+     * close buttons (sigh) */
+    gtk_widget_add_events (ebox, GDK_SCROLL_MASK);
+    g_signal_connect (ebox, "scroll-event", (GCallback) scroll_cb, nullptr);
+
+    if (button)
+    {
+        gtk_widget_add_events (button, GDK_SCROLL_MASK);
+        g_signal_connect (button, "scroll-event", (GCallback) scroll_cb, nullptr);
+    }
+}
+
+void ui_playlist_notebook_populate ()
+{
+    int playlist = aud_playlist_get_active ();
+
+    for (int count = 0; count < aud_playlist_count (); count ++)
+        ui_playlist_notebook_create_tab (count);
+
+    gtk_notebook_set_current_page (UI_PLAYLIST_NOTEBOOK, playlist);
+    highlighted = aud_playlist_get_unique_id (aud_playlist_get_playing ());
+
+    if (! switch_handler)
+        switch_handler = g_signal_connect (notebook, "switch-page", (GCallback)
+         tab_changed, nullptr);
+    if (! reorder_handler)
+        reorder_handler = g_signal_connect (notebook, "page-reordered",
+         (GCallback) tab_reordered, nullptr);
+
+    gtk_widget_grab_focus (playlist_get_treeview (playlist));
+}
+
+void ui_playlist_notebook_empty ()
+{
+    if (switch_handler)
+        g_signal_handler_disconnect (notebook, switch_handler);
+    switch_handler = 0;
+    if (reorder_handler)
+        g_signal_handler_disconnect (notebook, reorder_handler);
+    reorder_handler = 0;
+
+    int n_pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
+    while (n_pages)
+        gtk_notebook_remove_page ((GtkNotebook *) notebook, -- n_pages);
+}
+
+static void add_remove_pages ()
+{
+    g_signal_handlers_block_by_func (notebook, (void *) tab_changed, nullptr);
+    g_signal_handlers_block_by_func (notebook, (void *) tab_reordered, nullptr);
+
+    int lists = aud_playlist_count ();
+    int pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
+
+    /* scan through existing treeviews */
+    for (int i = 0; i < pages; )
+    {
+        GtkWidget * page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, i);
+        GtkWidget * tree = (GtkWidget *) g_object_get_data ((GObject *) page, "treeview");
+        int tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
+
+        /* do we have an orphaned treeview? */
+        if (aud_playlist_by_unique_id (tree_id) < 0)
+        {
+            gtk_notebook_remove_page ((GtkNotebook *) notebook, i);
+            pages --;
+            continue;
+        }
+
+        /* do we have the right treeview? */
+        int list_id = aud_playlist_get_unique_id (i);
+
+        if (tree_id == list_id)
+        {
+            ui_playlist_widget_set_playlist (tree, i);
+            i ++;
+            continue;
+        }
+
+        /* look for the right treeview */
+        int found = false;
+
+        for (int j = i + 1; j < pages; j ++)
+        {
+            page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, j);
+            tree = (GtkWidget *) g_object_get_data ((GObject *) page, "treeview");
+            tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
+
+            /* found it? move it to the right place */
+            if (tree_id == list_id)
+            {
+                gtk_notebook_reorder_child ((GtkNotebook *) notebook, page, i);
+                found = true;
+                break;
+            }
+        }
+
+        /* didn't find it? create it */
+        if (! found)
+        {
+            ui_playlist_notebook_create_tab (i);
+            pages ++;
+            continue;
+        }
+    }
+
+    /* create new treeviews */
+    while (pages < lists)
+    {
+        ui_playlist_notebook_create_tab (pages);
+        pages ++;
+    }
+
+    gtk_notebook_set_current_page ((GtkNotebook *) notebook, aud_playlist_get_active ());
+
+    show_hide_playlist_tabs ();
+
+    g_signal_handlers_unblock_by_func (notebook, (void *) tab_changed, nullptr);
+    g_signal_handlers_unblock_by_func (notebook, (void *) tab_reordered, nullptr);
+}
+
+void ui_playlist_notebook_update (void * data, void * user)
+{
+    auto global_level = aud::from_ptr<Playlist::UpdateLevel> (data);
+    if (global_level == Playlist::Structure)
+        add_remove_pages ();
+
+    int lists = aud_playlist_count ();
+
+    for (int list = 0; list < lists; list ++)
+    {
+        if (global_level >= Playlist::Metadata)
+            set_tab_label (list, get_tab_label (list));
+
+        GtkWidget * treeview = playlist_get_treeview (list);
+
+        auto update = aud_playlist_update_detail (list);
+        if (update.level)
+            ui_playlist_widget_update (treeview, update);
+
+        audgui_list_set_highlight (treeview, aud_playlist_get_position (list));
+    }
+
+    gtk_notebook_set_current_page ((GtkNotebook *) notebook, aud_playlist_get_active ());
+}
+
+void ui_playlist_notebook_position (void * data, void * user)
+{
+    int list = aud::from_ptr<int> (data);
+    int row = aud_playlist_get_position (list);
+
+    if (aud_get_bool ("gtkui", "autoscroll"))
+    {
+        aud_playlist_select_all (list, false);
+        aud_playlist_entry_set_selected (list, row, true);
+        aud_playlist_set_focus (list, row);
+    }
+
+    if (! aud_playlist_update_pending ())
+        audgui_list_set_highlight (playlist_get_treeview (list), row);
+}
+
+void ui_playlist_notebook_activate (void * data, void * user)
+{
+    if (! aud_playlist_update_pending ())
+        gtk_notebook_set_current_page ((GtkNotebook *) notebook, aud_playlist_get_active ());
+}
+
+void ui_playlist_notebook_set_playing (void * data, void * user)
+{
+    int id = aud_playlist_get_unique_id (aud_playlist_get_playing ());
+
+    // if the previous playing playlist was deleted, ignore it
+    if (aud_playlist_by_unique_id (highlighted) < 0)
+        highlighted = -1;
+
+    if (highlighted == id)
+        return;
+
+    int pages = gtk_notebook_get_n_pages ((GtkNotebook *) notebook);
+
+    for (int i = 0; i < pages; i ++)
+    {
+        GtkWidget * page = gtk_notebook_get_nth_page ((GtkNotebook *) notebook, i);
+        GtkWidget * tree = (GtkWidget *) g_object_get_data ((GObject *) page, "treeview");
+        int tree_id = GPOINTER_TO_INT (g_object_get_data ((GObject *) tree, "playlist-id"));
+
+        if (tree_id == highlighted || tree_id == id)
+            set_tab_label (i, get_tab_label (i));
+    }
+
+    highlighted = id;
+}
+
+static void destroy_cb ()
+{
+    notebook = nullptr;
+    switch_handler = 0;
+    reorder_handler = 0;
+}
+
+GtkWidget * ui_playlist_notebook_new ()
+{
+    notebook = gtk_notebook_new ();
+    gtk_notebook_set_scrollable ((GtkNotebook *) notebook, true);
+    make_add_button (notebook);
+
+    show_hide_playlist_tabs ();
+
+    gtk_widget_add_events (notebook, GDK_SCROLL_MASK);
+    g_signal_connect (notebook, "scroll-event", (GCallback) scroll_cb, nullptr);
+    g_signal_connect (notebook, "destroy", (GCallback) destroy_cb, nullptr);
+
+    return notebook;
+}
+
+void show_hide_playlist_tabs ()
+{
+    gtk_notebook_set_show_tabs ((GtkNotebook *) notebook, aud_get_bool ("gtkui",
+     "playlist_tabs_visible") || aud_playlist_count () > 1);
+}
diff --git a/src/gtkui/ui_playlist_notebook.h b/src/gtkui/ui_playlist_notebook.h
index 1bd5ae2f676e..1deb65128a8f 100644
--- a/src/gtkui/ui_playlist_notebook.h
+++ b/src/gtkui/ui_playlist_notebook.h
@@ -22,19 +22,20 @@
 
 #include <gtk/gtk.h>
 
-#define UI_PLAYLIST_NOTEBOOK ui_playlist_get_notebook()
+#define UI_PLAYLIST_NOTEBOOK ui_playlist_get_notebook ()
 
-GtkNotebook *ui_playlist_get_notebook(void);
-GtkWidget *ui_playlist_notebook_new();
-void ui_playlist_notebook_create_tab(int playlist);
-void ui_playlist_notebook_populate(void);
-void ui_playlist_notebook_empty (void);
+GtkNotebook * ui_playlist_get_notebook ();
+GtkWidget * ui_playlist_notebook_new ();
+
+void ui_playlist_notebook_create_tab (int playlist);
+void ui_playlist_notebook_populate ();
+void ui_playlist_notebook_empty ();
 void ui_playlist_notebook_update (void * data, void * user);
 void ui_playlist_notebook_activate (void * data, void * user);
 void ui_playlist_notebook_set_playing (void * data, void * user);
 void ui_playlist_notebook_position (void * data, void * user);
 
 void start_rename_playlist (int playlist);
-void show_hide_playlist_tabs (void);
+void show_hide_playlist_tabs ();
 
 #endif
diff --git a/src/gtkui/ui_playlist_widget.c b/src/gtkui/ui_playlist_widget.c
deleted file mode 100644
index 685e740208c3..000000000000
--- a/src/gtkui/ui_playlist_widget.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * ui_playlist_widget.c
- * Copyright 2011-2012 John Lindgren, William Pitcock, and Michał Lipski
- *
- * 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 <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudcore/audstrings.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-#include <libaudgui/list.h>
-
-#include "gtkui.h"
-#include "playlist_util.h"
-#include "ui_playlist_widget.h"
-
-static const GType pw_col_types[PW_COLS] = {G_TYPE_INT, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING};
-static const bool_t pw_col_widths[PW_COLS] = {7, -1, -1, 4, -1, 2, -1, 3, 7,
- -1, -1, -1, 3};
-static const bool_t pw_col_label[PW_COLS] = {FALSE, TRUE, TRUE, TRUE, TRUE,
- FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE};
-
-typedef struct {
-    int list;
-    GList * queue;
-    int popup_source, popup_pos;
-    bool_t popup_shown;
-} PlaylistWidgetData;
-
-static void set_int_from_tuple (GValue * value, const Tuple * tuple, int field)
-{
-    int i = tuple ? tuple_get_int (tuple, field) : 0;
-    if (i > 0)
-        g_value_take_string (value, g_strdup_printf ("%d", i));
-    else
-        g_value_set_string (value, "");
-}
-
-static void set_string_from_tuple (GValue * value, const Tuple * tuple,
- int field)
-{
-    char *str = tuple ? tuple_get_str (tuple, field) : NULL;
-    g_value_set_string (value, str);
-    str_unref(str);
-}
-
-static void set_queued (GValue * value, int list, int row)
-{
-    int q = aud_playlist_queue_find_entry (list, row);
-    if (q < 0)
-        g_value_set_string (value, "");
-    else
-        g_value_take_string (value, g_strdup_printf ("#%d", 1 + q));
-}
-
-static void set_length (GValue * value, int list, int row)
-{
-    int len = aud_playlist_entry_get_length (list, row, TRUE);
-    if (len)
-    {
-        char s[16];
-        audgui_format_time (s, sizeof s, len);
-        g_value_set_string (value, s);
-    }
-    else
-        g_value_set_string (value, "");
-}
-
-static void get_value (void * user, int row, int column, GValue * value)
-{
-    PlaylistWidgetData * data = user;
-    g_return_if_fail (column >= 0 && column < pw_num_cols);
-    g_return_if_fail (row >= 0 && row < aud_playlist_entry_count (data->list));
-
-    column = pw_cols[column];
-
-    char * title = NULL, * artist = NULL, * album = NULL;
-    Tuple * tuple = NULL;
-
-    if (column == PW_COL_TITLE || column == PW_COL_ARTIST || column ==
-     PW_COL_ALBUM)
-        aud_playlist_entry_describe (data->list, row, & title, & artist,
-         & album, TRUE);
-    else if (column == PW_COL_YEAR || column == PW_COL_TRACK || column ==
-     PW_COL_GENRE || column == PW_COL_FILENAME || column == PW_COL_PATH ||
-     column == PW_COL_BITRATE)
-        tuple = aud_playlist_entry_get_tuple (data->list, row, TRUE);
-
-    switch (column)
-    {
-    case PW_COL_NUMBER:
-        g_value_set_int (value, 1 + row);
-        break;
-    case PW_COL_TITLE:
-        g_value_set_string (value, title);
-        break;
-    case PW_COL_ARTIST:
-        g_value_set_string (value, artist);
-        break;
-    case PW_COL_YEAR:
-        set_int_from_tuple (value, tuple, FIELD_YEAR);
-        break;
-    case PW_COL_ALBUM:
-        g_value_set_string (value, album);
-        break;
-    case PW_COL_TRACK:
-        set_int_from_tuple (value, tuple, FIELD_TRACK_NUMBER);
-        break;
-    case PW_COL_GENRE:
-        set_string_from_tuple (value, tuple, FIELD_GENRE);
-        break;
-    case PW_COL_QUEUED:
-        set_queued (value, data->list, row);
-        break;
-    case PW_COL_LENGTH:
-        set_length (value, data->list, row);
-        break;
-    case PW_COL_FILENAME:
-        set_string_from_tuple (value, tuple, FIELD_FILE_NAME);
-        break;
-    case PW_COL_PATH:
-        set_string_from_tuple (value, tuple, FIELD_FILE_PATH);
-        break;
-    case PW_COL_CUSTOM:;
-        char * custom = aud_playlist_entry_get_title (data->list, row, TRUE);
-        g_value_set_string (value, custom);
-        str_unref (custom);
-        break;
-    case PW_COL_BITRATE:
-        set_int_from_tuple (value, tuple, FIELD_BITRATE);
-        break;
-    }
-
-    str_unref (title);
-    str_unref (artist);
-    str_unref (album);
-    if (tuple)
-        tuple_unref (tuple);
-}
-
-static bool_t get_selected (void * user, int row)
-{
-    return aud_playlist_entry_get_selected (((PlaylistWidgetData *) user)->list,
-     row);
-}
-
-static void set_selected (void * user, int row, bool_t selected)
-{
-    aud_playlist_entry_set_selected (((PlaylistWidgetData *) user)->list, row,
-     selected);
-}
-
-static void select_all (void * user, bool_t selected)
-{
-    aud_playlist_select_all (((PlaylistWidgetData *) user)->list, selected);
-}
-
-static void focus_change (void * user, int row)
-{
-    aud_playlist_set_focus (((PlaylistWidgetData *) user)->list, row);
-}
-
-static void activate_row (void * user, int row)
-{
-    int list = ((PlaylistWidgetData *) user)->list;
-    aud_playlist_set_position (list, row);
-    aud_drct_play_playlist (list);
-}
-
-static void right_click (void * user, GdkEventButton * event)
-{
-    popup_menu_rclick (event->button, event->time);
-}
-
-static void shift_rows (void * user, int row, int before)
-{
-    int list = ((PlaylistWidgetData *) user)->list;
-
-    /* Adjust the shift amount so that the selected entry closest to the
-     * destination ends up at the destination. */
-    if (before > row)
-        before -= playlist_count_selected_in_range (list, row, before - row);
-    else
-        before += playlist_count_selected_in_range (list, before, row - before);
-
-    aud_playlist_shift (list, row, before - row);
-}
-
-static bool_t 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;
-    }
-
-    data->popup_pos = -1;
-}
-
-static void popup_trigger (PlaylistWidgetData * data, int pos)
-{
-    popup_hide (data);
-
-    data->popup_pos = pos;
-    data->popup_source = g_timeout_add (aud_get_int (NULL, "filepopup_delay") *
-     100, (GSourceFunc) popup_show, data);
-}
-
-static void mouse_motion (void * user, GdkEventMotion * event, int row)
-{
-    PlaylistWidgetData * data = (PlaylistWidgetData *) user;
-
-    if (row < 0)
-    {
-        popup_hide (data);
-        return;
-    }
-
-    if (aud_get_bool (NULL, "show_filepopup_for_tuple") && data->popup_pos != row)
-        popup_trigger (data, row);
-}
-
-static void mouse_leave (void * user, GdkEventMotion * event, int row)
-{
-    popup_hide ((PlaylistWidgetData *) user);
-}
-
-static void get_data (void * user, void * * data, int * length)
-{
-    char * text = audgui_urilist_create_from_selected
-     (((PlaylistWidgetData *) user)->list);
-    g_return_if_fail (text);
-    * data = text;
-    * length = strlen (text);
-}
-
-static void receive_data (void * user, int row, const void * data, int length)
-{
-    SNCOPY (text, data, length);
-    audgui_urilist_insert (((PlaylistWidgetData *) user)->list, row, text);
-}
-
-static const AudguiListCallbacks callbacks = {
- .get_value = get_value,
- .get_selected = get_selected,
- .set_selected = set_selected,
- .select_all = select_all,
- .focus_change = focus_change,
- .activate_row = activate_row,
- .right_click = right_click,
- .shift_rows = shift_rows,
- .mouse_motion = mouse_motion,
- .mouse_leave = mouse_leave,
- .data_type = "text/uri-list",
- .get_data = get_data,
- .receive_data = receive_data};
-
-static bool_t search_cb (GtkTreeModel * model, int column, const char * search,
- GtkTreeIter * iter, void * user)
-{
-    GtkTreePath * path = gtk_tree_model_get_path (model, iter);
-    g_return_val_if_fail (path, TRUE);
-    int row = gtk_tree_path_get_indices (path)[0];
-    g_return_val_if_fail (row >= 0, TRUE);
-    gtk_tree_path_free (path);
-
-    Index * keys = str_list_to_index (search, " ");
-    int n_keys = index_count (keys);
-
-    bool_t matched = FALSE;
-
-    if (n_keys)
-    {
-        char * s[3] = {NULL, NULL, NULL};
-        aud_playlist_entry_describe (((PlaylistWidgetData *) user)->list, row,
-         & s[0], & s[1], & s[2], FALSE);
-
-        for (int i = 0; i < ARRAY_LEN (s); i ++)
-        {
-            if (! s[i])
-                continue;
-
-            for (int j = 0; j < n_keys;)
-            {
-                if (strstr_nocase_utf8 (s[i], index_get (keys, j)))
-                {
-                    index_delete_full (keys, j, 1, (IndexFreeFunc) str_unref);
-                    n_keys --;
-                }
-                else
-                    j ++;
-            }
-
-            str_unref (s[i]);
-        }
-
-        matched = ! n_keys;
-    }
-
-    index_free_full (keys, (IndexFreeFunc) str_unref);
-
-    return ! matched;
-}
-
-static void destroy_cb (PlaylistWidgetData * data)
-{
-    g_list_free (data->queue);
-    g_slice_free (PlaylistWidgetData, data);
-}
-
-GtkWidget * ui_playlist_widget_new (int playlist)
-{
-    PlaylistWidgetData * data = g_slice_new (PlaylistWidgetData);
-    data->list = playlist;
-    data->queue = NULL;
-    data->popup_source = 0;
-    data->popup_pos = -1;
-    data->popup_shown = FALSE;
-
-    GtkWidget * list = audgui_list_new (& callbacks, data,
-     aud_playlist_entry_count (playlist));
-
-    gtk_tree_view_set_headers_visible ((GtkTreeView *) list,
-     aud_get_bool ("gtkui", "playlist_headers"));
-    gtk_tree_view_set_search_equal_func ((GtkTreeView *) list, search_cb, data,
-     NULL);
-    g_signal_connect_swapped (list, "destroy", (GCallback) destroy_cb, data);
-
-    /* Disable type-to-search because it blocks CTRL-V, causing URI's to be
-     * pasted into the search box rather than added to the playlist.  The search
-     * box can still be brought up with CTRL-F. */
-    gtk_tree_view_set_enable_search ((GtkTreeView *) list, FALSE);
-
-    for (int i = 0; i < pw_num_cols; i ++)
-    {
-        int n = pw_cols[i];
-        audgui_list_add_column (list, pw_col_label[n] ? _(pw_col_names[n]) :
-         NULL, i, pw_col_types[n], pw_col_widths[n]);
-    }
-
-    return list;
-}
-
-int ui_playlist_widget_get_playlist (GtkWidget * widget)
-{
-    PlaylistWidgetData * data = audgui_list_get_user (widget);
-    g_return_val_if_fail (data, -1);
-    return data->list;
-}
-
-void ui_playlist_widget_set_playlist (GtkWidget * widget, int list)
-{
-    PlaylistWidgetData * data = audgui_list_get_user (widget);
-    g_return_if_fail (data);
-    data->list = list;
-}
-
-static void update_queue (GtkWidget * widget, PlaylistWidgetData * data)
-{
-    for (GList * node = data->queue; node; node = node->next)
-        audgui_list_update_rows (widget, GPOINTER_TO_INT (node->data), 1);
-
-    g_list_free (data->queue);
-    data->queue = NULL;
-
-    for (int i = aud_playlist_queue_count (data->list); i --; )
-        data->queue = g_list_prepend (data->queue, GINT_TO_POINTER
-         (aud_playlist_queue_get_entry (data->list, i)));
-
-    for (GList * node = data->queue; node; node = node->next)
-        audgui_list_update_rows (widget, GPOINTER_TO_INT (node->data), 1);
-}
-
-void ui_playlist_widget_update (GtkWidget * widget, int type, int at,
- int count)
-{
-    PlaylistWidgetData * data = audgui_list_get_user (widget);
-    g_return_if_fail (data);
-
-    if (type == PLAYLIST_UPDATE_STRUCTURE)
-    {
-        int old_entries = audgui_list_row_count (widget);
-        int entries = aud_playlist_entry_count (data->list);
-
-        audgui_list_delete_rows (widget, at, old_entries - (entries - count));
-        audgui_list_insert_rows (widget, at, count);
-
-        /* scroll to end of playlist if entries were added there
-           (but not if a newly added entry is playing) */
-        if (entries > old_entries && at + count == entries &&
-         aud_playlist_get_focus (data->list) < old_entries)
-            aud_playlist_set_focus (data->list, entries - 1);
-
-        ui_playlist_widget_scroll (widget);
-    }
-    else if (type == PLAYLIST_UPDATE_METADATA)
-        audgui_list_update_rows (widget, at, count);
-
-    audgui_list_update_selection (widget, at, count);
-    audgui_list_set_focus (widget, aud_playlist_get_focus (data->list));
-    update_queue (widget, data);
-}
-
-void ui_playlist_widget_scroll (GtkWidget * widget)
-{
-    PlaylistWidgetData * data = audgui_list_get_user (widget);
-    g_return_if_fail (data);
-
-    int row = -1;
-
-    if (gtk_widget_get_realized (widget))
-    {
-        int x, y;
-        audgui_get_mouse_coords (widget, & x, & y);
-        row = audgui_list_row_at_point (widget, x, y);
-    }
-
-    /* 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))
-        popup_trigger (data, row);
-    else
-        popup_hide (data);
-}
-
-void ui_playlist_widget_get_column_widths (GtkWidget * widget, char * * widths,
- char * * expand)
-{
-    int w[pw_num_cols], ex[pw_num_cols];
-
-    for (int i = 0; i < pw_num_cols; i ++)
-    {
-        GtkTreeViewColumn * col = gtk_tree_view_get_column ((GtkTreeView *) widget, i);
-        w[i] = gtk_tree_view_column_get_fixed_width (col);
-        ex[i] = gtk_tree_view_column_get_expand (col);
-    }
-
-    * widths = int_array_to_str (w, pw_num_cols);
-    * expand = int_array_to_str (ex, pw_num_cols);
-}
-
-void ui_playlist_widget_set_column_widths (GtkWidget * widget,
- const char * widths, const char * expand)
-{
-    int w[pw_num_cols], ex[pw_num_cols];
-
-    if (! str_to_int_array (widths, w, pw_num_cols) ||
-     ! str_to_int_array (expand, ex, pw_num_cols))
-        return;
-
-    for (int i = 0; i < pw_num_cols; i ++)
-    {
-        GtkTreeViewColumn * col = gtk_tree_view_get_column ((GtkTreeView *) widget, i);
-        gtk_tree_view_column_set_fixed_width (col, w[i]);
-        gtk_tree_view_column_set_expand (col, ex[i]);
-     }
-}
diff --git a/src/gtkui/ui_playlist_widget.cc b/src/gtkui/ui_playlist_widget.cc
new file mode 100644
index 000000000000..a95e2ea088fb
--- /dev/null
+++ b/src/gtkui/ui_playlist_widget.cc
@@ -0,0 +1,488 @@
+/*
+ * ui_playlist_widget.c
+ * Copyright 2011-2012 John Lindgren, William Pitcock, and Michał Lipski
+ *
+ * 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 <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/tuple.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+#include <libaudgui/list.h>
+
+#include "gtkui.h"
+#include "playlist_util.h"
+#include "ui_playlist_widget.h"
+
+static const GType pw_col_types[PW_COLS] =
+{
+    G_TYPE_INT,     // entry number
+    G_TYPE_STRING,  // title
+    G_TYPE_STRING,  // artist
+    G_TYPE_STRING,  // year
+    G_TYPE_STRING,  // album
+    G_TYPE_STRING,  // album artist
+    G_TYPE_STRING,  // track
+    G_TYPE_STRING,  // genre
+    G_TYPE_STRING,  // queue position
+    G_TYPE_STRING,  // length
+    G_TYPE_STRING,  // path
+    G_TYPE_STRING,  // file name
+    G_TYPE_STRING,  // custom title
+    G_TYPE_STRING   // bitrate
+};
+
+static const int pw_col_min_widths[PW_COLS] = {
+    7,   // entry number
+    10,  // title
+    10,  // artist
+    4,   // year
+    10,  // album
+    10,  // album artist
+    2,   // track
+    10,  // genre
+    3,   // queue position
+    7,   // length
+    10,  // path
+    10,  // file name
+    10,  // custom title
+    3    // bitrate
+};
+
+static const bool pw_col_label[PW_COLS] = {
+    false,  // entry number
+    true,   // title
+    true,   // artist
+    true,   // year
+    true,   // album
+    true,   // album artist
+    false,  // track
+    true,   // genre
+    false,  // queue position
+    false,  // length
+    true,   // path
+    true,   // file name
+    true,   // custom title
+    false   // bitrate
+};
+
+typedef struct {
+    int list;
+    int popup_source, popup_pos;
+    bool popup_shown;
+} PlaylistWidgetData;
+
+static void set_int_from_tuple (GValue * value, const Tuple & tuple, Tuple::Field field)
+{
+    int i = tuple ? tuple.get_int (field) : 0;
+    if (i > 0)
+        g_value_take_string (value, g_strdup_printf ("%d", i));
+    else
+        g_value_set_string (value, "");
+}
+
+static void set_string_from_tuple (GValue * value, const Tuple & tuple, Tuple::Field field)
+{
+    String str = tuple ? tuple.get_str (field) : String ();
+    g_value_set_string (value, str);
+}
+
+static void set_queued (GValue * value, int list, int row)
+{
+    int q = aud_playlist_queue_find_entry (list, row);
+    if (q < 0)
+        g_value_set_string (value, "");
+    else
+        g_value_take_string (value, g_strdup_printf ("#%d", 1 + q));
+}
+
+static void set_length (GValue * value, const Tuple & tuple)
+{
+    int len = tuple.get_int (Tuple::Length);
+    if (len >= 0)
+        g_value_set_string (value, str_format_time (len));
+    else
+        g_value_set_string (value, "");
+}
+
+static void get_value (void * user, int row, int column, GValue * value)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) user;
+    g_return_if_fail (column >= 0 && column < pw_num_cols);
+    g_return_if_fail (row >= 0 && row < aud_playlist_entry_count (data->list));
+
+    column = pw_cols[column];
+
+    Tuple tuple;
+
+    switch (column)
+    {
+    case PW_COL_TITLE:
+    case PW_COL_ARTIST:
+    case PW_COL_ALBUM:
+    case PW_COL_YEAR:
+    case PW_COL_ALBUM_ARTIST:
+    case PW_COL_TRACK:
+    case PW_COL_GENRE:
+    case PW_COL_LENGTH:
+    case PW_COL_FILENAME:
+    case PW_COL_PATH:
+    case PW_COL_CUSTOM:
+    case PW_COL_BITRATE:
+        tuple = aud_playlist_entry_get_tuple (data->list, row, Playlist::Guess);
+        break;
+    }
+
+    switch (column)
+    {
+    case PW_COL_NUMBER:
+        g_value_set_int (value, 1 + row);
+        break;
+    case PW_COL_TITLE:
+        set_string_from_tuple (value, tuple, Tuple::Title);
+        break;
+    case PW_COL_ARTIST:
+        set_string_from_tuple (value, tuple, Tuple::Artist);
+        break;
+    case PW_COL_YEAR:
+        set_int_from_tuple (value, tuple, Tuple::Year);
+        break;
+    case PW_COL_ALBUM:
+        set_string_from_tuple (value, tuple, Tuple::Album);
+        break;
+    case PW_COL_ALBUM_ARTIST:
+        set_string_from_tuple (value, tuple, Tuple::AlbumArtist);
+        break;
+    case PW_COL_TRACK:
+        set_int_from_tuple (value, tuple, Tuple::Track);
+        break;
+    case PW_COL_GENRE:
+        set_string_from_tuple (value, tuple, Tuple::Genre);
+        break;
+    case PW_COL_QUEUED:
+        set_queued (value, data->list, row);
+        break;
+    case PW_COL_LENGTH:
+        set_length (value, tuple);
+        break;
+    case PW_COL_FILENAME:
+        set_string_from_tuple (value, tuple, Tuple::Basename);
+        break;
+    case PW_COL_PATH:
+        set_string_from_tuple (value, tuple, Tuple::Path);
+        break;
+    case PW_COL_CUSTOM:
+        set_string_from_tuple (value, tuple, Tuple::FormattedTitle);
+        break;
+    case PW_COL_BITRATE:
+        set_int_from_tuple (value, tuple, Tuple::Bitrate);
+        break;
+    }
+}
+
+static bool get_selected (void * user, int 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);
+}
+
+static void select_all (void * user, bool selected)
+{
+    aud_playlist_select_all (((PlaylistWidgetData *) user)->list, selected);
+}
+
+static void focus_change (void * user, int row)
+{
+    aud_playlist_set_focus (((PlaylistWidgetData *) user)->list, row);
+}
+
+static void activate_row (void * user, int row)
+{
+    int list = ((PlaylistWidgetData *) user)->list;
+    aud_playlist_set_position (list, row);
+    aud_playlist_play (list);
+}
+
+static void right_click (void * user, GdkEventButton * event)
+{
+    popup_menu_rclick (event->button, event->time);
+}
+
+static void shift_rows (void * user, int row, int before)
+{
+    int list = ((PlaylistWidgetData *) user)->list;
+
+    /* Adjust the shift amount so that the selected entry closest to the
+     * destination ends up at the destination. */
+    if (before > row)
+        before -= playlist_count_selected_in_range (list, row, before - row);
+    else
+        before += playlist_count_selected_in_range (list, before, row - 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;
+    }
+
+    data->popup_pos = -1;
+}
+
+static void popup_trigger (PlaylistWidgetData * data, int pos)
+{
+    popup_hide (data);
+
+    data->popup_pos = pos;
+    data->popup_source = g_timeout_add (aud_get_int (nullptr, "filepopup_delay") *
+     100, (GSourceFunc) popup_show, data);
+}
+
+static void mouse_motion (void * user, GdkEventMotion * event, int row)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) user;
+
+    if (row < 0)
+    {
+        popup_hide (data);
+        return;
+    }
+
+    if (aud_get_bool (nullptr, "show_filepopup_for_tuple") && data->popup_pos != row)
+        popup_trigger (data, row);
+}
+
+static void mouse_leave (void * user, GdkEventMotion * event, int row)
+{
+    popup_hide ((PlaylistWidgetData *) user);
+}
+
+static Index<char> get_data (void * user)
+{
+    int playlist = ((PlaylistWidgetData *) user)->list;
+    return audgui_urilist_create_from_selected (playlist);
+}
+
+static void receive_data (void * user, int row, const char * data, int length)
+{
+    int playlist = ((PlaylistWidgetData *) user)->list;
+    audgui_urilist_insert (playlist, row, str_copy (data, length));
+}
+
+static const AudguiListCallbacks callbacks = {
+    get_value,
+    get_selected,
+    set_selected,
+    select_all,
+    activate_row,
+    right_click,
+    shift_rows,
+    "text/uri-list",
+    get_data,
+    receive_data,
+    mouse_motion,
+    mouse_leave,
+    focus_change
+};
+
+static gboolean search_cb (GtkTreeModel * model, int column, const char * search,
+ GtkTreeIter * iter, void * user)
+{
+    GtkTreePath * path = gtk_tree_model_get_path (model, iter);
+    g_return_val_if_fail (path, true);
+    int row = gtk_tree_path_get_indices (path)[0];
+    g_return_val_if_fail (row >= 0, true);
+    gtk_tree_path_free (path);
+
+    Index<String> keys = str_list_to_index (search, " ");
+
+    bool matched = false;
+
+    if (keys.len ())
+    {
+        int list = ((PlaylistWidgetData *) user)->list;
+        Tuple tuple = aud_playlist_entry_get_tuple (list, row);
+
+        String strings[3] = {
+            tuple.get_str (Tuple::Title),
+            tuple.get_str (Tuple::Artist),
+            tuple.get_str (Tuple::Album)
+        };
+
+        for (const String & s : strings)
+        {
+            if (! s)
+                continue;
+
+            auto is_match = [&] (const String & key)
+                { return (bool) strstr_nocase_utf8 (s, key); };
+
+            keys.remove_if (is_match);
+        }
+
+        matched = ! keys.len ();
+    }
+
+    return ! matched;
+}
+
+static void destroy_cb (PlaylistWidgetData * data)
+{
+    delete data;
+}
+
+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));
+
+    gtk_tree_view_set_headers_visible ((GtkTreeView *) list,
+     aud_get_bool ("gtkui", "playlist_headers"));
+    gtk_tree_view_set_search_equal_func ((GtkTreeView *) list, search_cb, data,
+     nullptr);
+    g_signal_connect_swapped (list, "destroy", (GCallback) destroy_cb, data);
+
+    /* Disable type-to-search because it blocks CTRL-V, causing URI's to be
+     * pasted into the search box rather than added to the playlist.  The search
+     * box can still be brought up with CTRL-F. */
+    gtk_tree_view_set_enable_search ((GtkTreeView *) list, false);
+
+    for (int i = 0; i < pw_num_cols; i ++)
+    {
+        int n = pw_cols[i];
+        audgui_list_add_column (list, pw_col_label[n] ? _(pw_col_names[n]) :
+         nullptr, i, pw_col_types[n], pw_col_min_widths[n]);
+    }
+
+    return list;
+}
+
+int ui_playlist_widget_get_playlist (GtkWidget * widget)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) audgui_list_get_user (widget);
+    g_return_val_if_fail (data, -1);
+    return data->list;
+}
+
+void ui_playlist_widget_set_playlist (GtkWidget * widget, int list)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) audgui_list_get_user (widget);
+    g_return_if_fail (data);
+    data->list = list;
+}
+
+void ui_playlist_widget_update (GtkWidget * widget, const Playlist::Update & update)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) audgui_list_get_user (widget);
+    g_return_if_fail (data);
+
+    int entries = aud_playlist_entry_count (data->list);
+    int changed = entries - update.before - update.after;
+
+    if (update.level == Playlist::Structure)
+    {
+        int old_entries = audgui_list_row_count (widget);
+        int removed = old_entries - update.before - update.after;
+
+        audgui_list_delete_rows (widget, update.before, removed);
+        audgui_list_insert_rows (widget, update.before, changed);
+
+        /* scroll to end of playlist if entries were added there
+           (but not if a newly added entry is playing) */
+        if (entries > old_entries && ! update.after &&
+         aud_playlist_get_focus (data->list) < old_entries)
+            aud_playlist_set_focus (data->list, entries - 1);
+
+        ui_playlist_widget_scroll (widget);
+    }
+    else if (update.level == Playlist::Metadata || update.queue_changed)
+        audgui_list_update_rows (widget, update.before, changed);
+
+    if (update.queue_changed)
+    {
+        for (int i = aud_playlist_queue_count (data->list); i --; )
+        {
+            int entry = aud_playlist_queue_get_entry (data->list, i);
+            if (entry < update.before || entry >= entries - update.after)
+                audgui_list_update_rows (widget, entry, 1);
+        }
+    }
+
+    audgui_list_update_selection (widget, update.before, changed);
+    audgui_list_set_focus (widget, aud_playlist_get_focus (data->list));
+}
+
+void ui_playlist_widget_scroll (GtkWidget * widget)
+{
+    PlaylistWidgetData * data = (PlaylistWidgetData *) audgui_list_get_user (widget);
+    g_return_if_fail (data);
+
+    int row = -1;
+
+    if (gtk_widget_get_realized (widget))
+    {
+        int x, y;
+        audgui_get_mouse_coords (widget, & x, & y);
+        row = audgui_list_row_at_point (widget, x, y);
+    }
+
+    /* 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))
+        popup_trigger (data, row);
+    else
+        popup_hide (data);
+}
diff --git a/src/gtkui/ui_playlist_widget.h b/src/gtkui/ui_playlist_widget.h
index 4ff48a9a03a8..9503d841dc30 100644
--- a/src/gtkui/ui_playlist_widget.h
+++ b/src/gtkui/ui_playlist_widget.h
@@ -21,31 +21,41 @@
 #define UI_PLAYLIST_WIDGET_H
 
 #include <gtk/gtk.h>
+#include <libaudcore/playlist.h>
 
 GtkWidget * ui_playlist_widget_new (int playlist);
 int ui_playlist_widget_get_playlist (GtkWidget * widget);
 void ui_playlist_widget_set_playlist (GtkWidget * widget, int playlist);
-void ui_playlist_widget_update (GtkWidget * widget, int type, int at,
- int count);
+void ui_playlist_widget_update (GtkWidget * widget, const Playlist::Update & update);
 void ui_playlist_widget_scroll (GtkWidget * widget);
 
-void ui_playlist_widget_get_column_widths (GtkWidget * widget, char * * widths,
- char * * expand);
-void ui_playlist_widget_set_column_widths (GtkWidget * widget,
- const char * widths, const char * expand);
-
-enum {PW_COL_NUMBER, PW_COL_TITLE, PW_COL_ARTIST, PW_COL_YEAR, PW_COL_ALBUM,
- PW_COL_TRACK, PW_COL_GENRE, PW_COL_QUEUED, PW_COL_LENGTH, PW_COL_PATH,
- PW_COL_FILENAME, PW_COL_CUSTOM, PW_COL_BITRATE, PW_COLS};
+enum {
+    PW_COL_NUMBER,
+    PW_COL_TITLE,
+    PW_COL_ARTIST,
+    PW_COL_YEAR,
+    PW_COL_ALBUM,
+    PW_COL_ALBUM_ARTIST,
+    PW_COL_TRACK,
+    PW_COL_GENRE,
+    PW_COL_QUEUED,
+    PW_COL_LENGTH,
+    PW_COL_PATH,
+    PW_COL_FILENAME,
+    PW_COL_CUSTOM,
+    PW_COL_BITRATE,
+    PW_COLS
+};
 
 extern const char * const pw_col_names[PW_COLS];
 
 extern int pw_num_cols;
 extern int pw_cols[PW_COLS];
+extern int pw_col_widths[PW_COLS];
 
-void pw_col_init (void);
-void * pw_col_create_chooser (void);
-void pw_col_save (void);
-void pw_col_cleanup (void);
+void pw_col_init ();
+void * pw_col_create_chooser ();
+void pw_col_save ();
+void pw_col_cleanup ();
 
 #endif
diff --git a/src/gtkui/ui_statusbar.c b/src/gtkui/ui_statusbar.c
deleted file mode 100644
index 747884dcb20e..000000000000
--- a/src/gtkui/ui_statusbar.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * ui_statusbar.c
- * Copyright 2010-2011 William Pitcock, Michał Lipski, and 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 <glib.h>
-#include <audacious/i18n.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <audacious/drct.h>
-#include <audacious/playlist.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-
-#include "ui_statusbar.h"
-
-#define APPEND(b, ...) snprintf (b + strlen (b), sizeof b - strlen (b), __VA_ARGS__)
-
-static void ui_statusbar_update_playlist_length (void * unused, GtkWidget * label)
-{
-    int playlist = aud_playlist_get_active ();
-
-    char s1[16], s2[16];
-    audgui_format_time (s1, sizeof s1, aud_playlist_get_selected_length (playlist));
-    audgui_format_time (s2, sizeof s2, aud_playlist_get_total_length (playlist));
-
-    SCONCAT3 (buf, s1, " / ", s2);
-    gtk_label_set_text ((GtkLabel *) label, buf);
-}
-
-static void ui_statusbar_info_change (void * unused, GtkWidget * label)
-{
-    /* may be called asynchronously */
-    if (! aud_drct_get_playing ())
-        return;
-
-    int playlist = aud_playlist_get_playing ();
-    Tuple * tuple = aud_playlist_entry_get_tuple (playlist,
-     aud_playlist_get_position (playlist), FALSE);
-    char * codec = tuple ? tuple_get_str (tuple, FIELD_CODEC) : NULL;
-    if (tuple)
-        tuple_unref (tuple);
-
-    int bitrate, samplerate, channels;
-    aud_drct_get_info (& bitrate, & samplerate, & channels);
-
-    char buf[256];
-    buf[0] = 0;
-
-    if (codec)
-    {
-        APPEND (buf, "%s", codec);
-        if (channels > 0 || samplerate > 0 || bitrate > 0)
-            APPEND (buf, ", ");
-    }
-
-    str_unref (codec);
-
-    if (channels > 0)
-    {
-        if (channels == 1)
-            APPEND (buf, _("mono"));
-        else if (channels == 2)
-            APPEND (buf, _("stereo"));
-        else
-            APPEND (buf, ngettext ("%d channel", "%d channels", channels),
-             channels);
-
-        if (samplerate > 0 || bitrate > 0)
-            APPEND (buf, ", ");
-    }
-
-    if (samplerate > 0)
-    {
-        APPEND (buf, "%d kHz", samplerate / 1000);
-        if (bitrate > 0)
-            APPEND (buf, ", ");
-    }
-
-    if (bitrate > 0)
-        APPEND (buf, _("%d kbps"), bitrate / 1000);
-
-    gtk_label_set_text ((GtkLabel *) label, buf);
-}
-
-static void ui_statusbar_playback_stop (void * unused, GtkWidget * label)
-{
-    gtk_label_set_text ((GtkLabel *) label, NULL);
-}
-
-static void ui_statusbar_destroy_cb (GtkWidget * widget, void * data)
-{
-    hook_dissociate ("playback ready", (HookFunction) ui_statusbar_info_change);
-    hook_dissociate ("info change", (HookFunction) ui_statusbar_info_change);
-    hook_dissociate ("playback stop", (HookFunction) ui_statusbar_playback_stop);
-    hook_dissociate ("playlist activate", (HookFunction) ui_statusbar_update_playlist_length);
-    hook_dissociate ("playlist update", (HookFunction) ui_statusbar_update_playlist_length);
-}
-
-GtkWidget * ui_statusbar_new (void)
-{
-    GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
-    GtkWidget * status = gtk_widget_new (GTK_TYPE_LABEL, "xalign", 0.0, NULL);
-    GtkWidget * length = gtk_widget_new (GTK_TYPE_LABEL, "xalign", 1.0, NULL);
-
-    gtk_label_set_ellipsize ((GtkLabel *) status, PANGO_ELLIPSIZE_END);
-    gtk_box_pack_start ((GtkBox *) hbox, status, TRUE, TRUE, 5);
-    gtk_box_pack_start ((GtkBox *) hbox, length, FALSE, FALSE, 5);
-
-    ui_statusbar_update_playlist_length (NULL, length);
-
-    hook_associate ("playback ready", (HookFunction) ui_statusbar_info_change, status);
-    hook_associate ("info change", (HookFunction) ui_statusbar_info_change, status);
-    hook_associate ("playback stop", (HookFunction) ui_statusbar_playback_stop, status);
-    hook_associate ("playlist activate", (HookFunction) ui_statusbar_update_playlist_length, length);
-    hook_associate ("playlist update", (HookFunction) ui_statusbar_update_playlist_length, length);
-
-    g_signal_connect (hbox, "destroy", (GCallback) ui_statusbar_destroy_cb, NULL);
-
-    if (aud_drct_get_playing () && aud_drct_get_ready ())
-        ui_statusbar_info_change (NULL, status);
-
-    return hbox;
-}
diff --git a/src/gtkui/ui_statusbar.cc b/src/gtkui/ui_statusbar.cc
new file mode 100644
index 000000000000..a888eed4ff26
--- /dev/null
+++ b/src/gtkui/ui_statusbar.cc
@@ -0,0 +1,163 @@
+/*
+ * ui_statusbar.c
+ * Copyright 2010-2011 William Pitcock, Michał Lipski, and 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 <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/runtime.h>
+
+#include "ui_statusbar.h"
+
+static QueuedFunc clear_timeout;
+
+static void ui_statusbar_update_playlist_length (void *, void * label)
+{
+    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));
+    gtk_label_set_text ((GtkLabel *) label, str_concat ({s1, " / ", s2}));
+}
+
+static void ui_statusbar_info_change (void *, void * label)
+{
+    if (clear_timeout.running ())
+        return;
+
+    Tuple tuple = aud_drct_get_tuple ();
+    String codec = tuple.get_str (Tuple::Codec);
+
+    int bitrate, samplerate, channels;
+    aud_drct_get_info (bitrate, samplerate, channels);
+
+    StringBuf buf;
+
+    if (codec)
+    {
+        buf.insert (-1, codec);
+        if (channels > 0 || samplerate > 0 || bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (channels > 0)
+    {
+        if (channels == 1)
+            buf.insert (-1, _("mono"));
+        else if (channels == 2)
+            buf.insert (-1, _("stereo"));
+        else
+            buf.combine (str_printf (ngettext ("%d channel", "%d channels", channels), channels));
+
+        if (samplerate > 0 || bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (samplerate > 0)
+    {
+        buf.combine (str_printf ("%d kHz", samplerate / 1000));
+        if (bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (bitrate > 0)
+        buf.combine (str_printf (_("%d kbps"), bitrate / 1000));
+
+    gtk_label_set_text ((GtkLabel *) label, buf);
+}
+
+static void ui_statusbar_playback_stop (void *, void * label)
+{
+    if (clear_timeout.running ())
+        return;
+
+    gtk_label_set_text ((GtkLabel *) label, nullptr);
+}
+
+static void clear_message (void * label)
+{
+    clear_timeout.stop ();
+
+    if (aud_drct_get_ready ())
+        ui_statusbar_info_change (nullptr, label);
+    else
+        gtk_label_set_text ((GtkLabel *) label, nullptr);
+}
+
+static void no_advance_toggled (void *, void * label)
+{
+    if (aud_get_bool (nullptr, "no_playlist_advance"))
+        gtk_label_set_text ((GtkLabel *) label, _("Single mode."));
+    else
+        gtk_label_set_text ((GtkLabel *) label, _("Playlist mode."));
+
+    clear_timeout.start (1000, clear_message, label);
+}
+
+static void stop_after_song_toggled (void *, void * label)
+{
+    if (aud_get_bool (nullptr, "stop_after_current_song"))
+        gtk_label_set_text ((GtkLabel *) label, _("Stopping after song."));
+
+    clear_timeout.start (1000, clear_message, label);
+}
+
+static void ui_statusbar_destroy_cb ()
+{
+    clear_timeout.stop ();
+
+    hook_dissociate ("playback ready", ui_statusbar_info_change);
+    hook_dissociate ("info change", ui_statusbar_info_change);
+    hook_dissociate ("tuple change", ui_statusbar_info_change);
+    hook_dissociate ("playback stop", ui_statusbar_playback_stop);
+    hook_dissociate ("set no_playlist_advance", no_advance_toggled);
+    hook_dissociate ("set stop_after_current_song", stop_after_song_toggled);
+    hook_dissociate ("playlist activate", ui_statusbar_update_playlist_length);
+    hook_dissociate ("playlist update", ui_statusbar_update_playlist_length);
+}
+
+GtkWidget * ui_statusbar_new ()
+{
+    GtkWidget * hbox = gtk_hbox_new (false, 3);
+    GtkWidget * status = gtk_widget_new (GTK_TYPE_LABEL, "xalign", 0.0, nullptr);
+    GtkWidget * length = gtk_widget_new (GTK_TYPE_LABEL, "xalign", 1.0, nullptr);
+
+    gtk_label_set_ellipsize ((GtkLabel *) status, PANGO_ELLIPSIZE_END);
+    gtk_box_pack_start ((GtkBox *) hbox, status, true, true, 5);
+    gtk_box_pack_start ((GtkBox *) hbox, length, false, false, 5);
+
+    ui_statusbar_update_playlist_length (nullptr, length);
+
+    hook_associate ("playback ready", ui_statusbar_info_change, status);
+    hook_associate ("info change", ui_statusbar_info_change, status);
+    hook_associate ("tuple change", ui_statusbar_info_change, status);
+    hook_associate ("playback stop", ui_statusbar_playback_stop, status);
+    hook_associate ("set no_playlist_advance", no_advance_toggled, status);
+    hook_associate ("set stop_after_current_song", stop_after_song_toggled, status);
+    hook_associate ("playlist activate", ui_statusbar_update_playlist_length, length);
+    hook_associate ("playlist update", ui_statusbar_update_playlist_length, length);
+
+    g_signal_connect (hbox, "destroy", (GCallback) ui_statusbar_destroy_cb, nullptr);
+
+    if (aud_drct_get_ready ())
+        ui_statusbar_info_change (nullptr, status);
+
+    return hbox;
+}
diff --git a/src/gtkui/ui_statusbar.h b/src/gtkui/ui_statusbar.h
index b3217fac266b..1f92d0f3d8fd 100644
--- a/src/gtkui/ui_statusbar.h
+++ b/src/gtkui/ui_statusbar.h
@@ -22,6 +22,6 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * ui_statusbar_new (void);
+GtkWidget * ui_statusbar_new ();
 
 #endif
diff --git a/src/hotkey/Makefile b/src/hotkey/Makefile
index e977d8145a98..3765d51bd717 100644
--- a/src/hotkey/Makefile
+++ b/src/hotkey/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = hotkey${PLUGIN_SUFFIX}
 
-SRCS = plugin.c gui.c grab.c
+SRCS = plugin.cc gui.cc grab.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -I..
-LIBS += ${GLIB_LIBS} ${GTK_LIBS} -lX11
+LIBS += ${GLIB_LIBS} ${GTK_LIBS} -lX11 -laudgui
diff --git a/src/hotkey/grab.c b/src/hotkey/grab.c
deleted file mode 100644
index b7b4e9e3434d..000000000000
--- a/src/hotkey/grab.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- *  This file is part of audacious-hotkey plugin for audacious
- *
- *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
- *  Name: grab.c
- *  Description: grab.c
- *
- *  Part of this code is from itouch-ctrl plugin.
- *  Authors of itouch-ctrl are listed below:
- *
- *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
- *
- *  Part of this code are from xmms-itouch plugin.
- *  Authors of xmms-itouch are listed below:
- *
- *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
- *                         Bryn Davies <curious at ihug.com.au>
- *                         Jonathan A. Davis <davis at jdhouse.org>
- *                         Jeremy Tan <nsx at nsx.homeip.net>
- *
- *  audacious-hotkey 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.
- *
- *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-
-#include "grab.h"
-#include "plugin.h"
-
-
-static gint grabbed = 0;
-static unsigned int numlock_mask = 0;
-static unsigned int scrolllock_mask = 0;
-static unsigned int capslock_mask = 0;
-
-
-/* Taken from xbindkeys */
-static void get_offending_modifiers (Display * dpy)
-{
-    int i;
-    XModifierKeymap *modmap;
-    KeyCode nlock, slock;
-
-    static int mask_table[8] = {
-        ShiftMask, LockMask, ControlMask, Mod1Mask,
-        Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
-    };
-
-    nlock = XKeysymToKeycode (dpy, XK_Num_Lock);
-    slock = XKeysymToKeycode (dpy, XK_Scroll_Lock);
-
-    /*
-    * Find out the masks for the NumLock and ScrollLock modifiers,
-    * so that we can bind the grabs for when they are enabled too.
-    */
-    modmap = XGetModifierMapping (dpy);
-
-    if (modmap != NULL && modmap->max_keypermod > 0)
-    {
-        for (i = 0; i < 8 * modmap->max_keypermod; i++)
-        {
-            if (modmap->modifiermap[i] == nlock && nlock != 0)
-                numlock_mask = mask_table[i / modmap->max_keypermod];
-            else if (modmap->modifiermap[i] == slock && slock != 0)
-                scrolllock_mask = mask_table[i / modmap->max_keypermod];
-        }
-    }
-
-    capslock_mask = LockMask;
-
-    if (modmap)
-        XFreeModifiermap (modmap);
-}
-
-
-static int x11_error_handler (Display *dpy, XErrorEvent *error)
-{
-    return 0;
-}
-
-/* grab required keys */
-static void grab_key(const HotkeyConfiguration *hotkey, Display *xdisplay, Window x_root_window)
-{
-    unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
-
-    if (hotkey->key == 0) return;
-
-    if (hotkey->type == TYPE_KEY)
-    {
-        XGrabKey (xdisplay, hotkey->key, modifier, x_root_window,
-            False, GrabModeAsync, GrabModeAsync);
-
-        if (modifier == AnyModifier)
-            return;
-
-        if (numlock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (capslock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (scrolllock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (numlock_mask && capslock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (numlock_mask && scrolllock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (capslock_mask && scrolllock_mask)
-            XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask,
-                x_root_window,
-                False, GrabModeAsync, GrabModeAsync);
-
-        if (numlock_mask && capslock_mask && scrolllock_mask)
-            XGrabKey (xdisplay, hotkey->key,
-                modifier | numlock_mask | capslock_mask | scrolllock_mask,
-                x_root_window, False, GrabModeAsync,
-                GrabModeAsync);
-    }
-    if (hotkey->type == TYPE_MOUSE)
-    {
-        XGrabButton (xdisplay, hotkey->key, modifier, x_root_window,
-            False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (modifier == AnyModifier)
-            return;
-
-        if (numlock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (capslock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (scrolllock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (numlock_mask && capslock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (numlock_mask && scrolllock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (capslock_mask && scrolllock_mask)
-            XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask,
-                x_root_window,
-                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
-
-        if (numlock_mask && capslock_mask && scrolllock_mask)
-            XGrabButton (xdisplay, hotkey->key,
-                modifier | numlock_mask | capslock_mask | scrolllock_mask,
-                x_root_window, False, ButtonPressMask, GrabModeAsync,
-                GrabModeAsync, None, None);
-    }
-}
-
-void grab_keys ( )
-{
-    Display* xdisplay;
-    int screen;
-    PluginConfig* plugin_cfg = get_config();
-    HotkeyConfiguration *hotkey;
-
-    XErrorHandler old_handler = 0;
-     xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-
-    if (grabbed) return;
-
-
-    XSync(xdisplay, False);
-    old_handler = XSetErrorHandler (x11_error_handler);
-
-    get_offending_modifiers(xdisplay);
-    hotkey = &(plugin_cfg->first);
-    while (hotkey)
-    {
-        for (screen=0;screen<ScreenCount(xdisplay);screen++)
-        {
-            grab_key(hotkey, xdisplay, RootWindow(xdisplay, screen));
-        }
-        hotkey = hotkey->next;
-    }
-
-    XSync(xdisplay, False);
-    XSetErrorHandler (old_handler);
-
-    grabbed = 1;
-}
-
-
-
-/* grab required keys */
-static void ungrab_key(HotkeyConfiguration *hotkey, Display* xdisplay, Window x_root_window)
-{
-    unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
-
-    if (hotkey->key == 0) return;
-
-    if (hotkey->type == TYPE_KEY)
-    {
-        XUngrabKey (xdisplay, hotkey->key, modifier, x_root_window);
-
-        if (modifier == AnyModifier)
-            return;
-
-        if (numlock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window);
-
-        if (capslock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window);
-
-        if (scrolllock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window);
-
-        if (numlock_mask && capslock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window);
-
-        if (numlock_mask && scrolllock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window);
-
-        if (capslock_mask && scrolllock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window);
-
-        if (numlock_mask && capslock_mask && scrolllock_mask)
-            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
-    }
-    if (hotkey->type == TYPE_MOUSE)
-    {
-        XUngrabButton (xdisplay, hotkey->key, modifier, x_root_window);
-
-        if (modifier == AnyModifier)
-            return;
-
-        if (numlock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window);
-
-        if (capslock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window);
-
-        if (scrolllock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window);
-
-        if (numlock_mask && capslock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window);
-
-        if (numlock_mask && scrolllock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window);
-
-        if (capslock_mask && scrolllock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window);
-
-        if (numlock_mask && capslock_mask && scrolllock_mask)
-            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
-    }
-}
-
-void ungrab_keys ( )
-{
-    Display* xdisplay;
-    int screen;
-    PluginConfig* plugin_cfg = get_config();
-    HotkeyConfiguration *hotkey;
-
-    XErrorHandler old_handler = 0;
-     xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-
-    if (!grabbed) return;
-    if (!xdisplay) return;
-
-    XSync(xdisplay, False);
-    old_handler = XSetErrorHandler (x11_error_handler);
-
-    get_offending_modifiers(xdisplay);
-
-    hotkey = &(plugin_cfg->first);
-    while (hotkey)
-    {
-        for (screen=0;screen<ScreenCount(xdisplay);screen++)
-        {
-            ungrab_key(hotkey, xdisplay, RootWindow(xdisplay, screen));
-        }
-        hotkey = hotkey->next;
-    }
-
-    XSync(xdisplay, False);
-    XSetErrorHandler (old_handler);
-
-    grabbed = 0;
-}
-
-
-static GdkFilterReturn
-gdk_filter(GdkXEvent *xevent,
-       GdkEvent *event,
-       gpointer data)
-{
-    HotkeyConfiguration *hotkey;
-    hotkey = &(get_config()->first);
-    switch (((XEvent*)xevent)->type)
-    {
-    case KeyPress:
-        {
-            XKeyEvent *keyevent = (XKeyEvent*)xevent;
-            while (hotkey)
-            {
-                if ((hotkey->key == keyevent->keycode) &&
-                    (hotkey->mask == (keyevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) &&
-                    (hotkey->type == TYPE_KEY))
-                {
-                    if (handle_keyevent(hotkey->event))
-                        return GDK_FILTER_REMOVE;
-                    break;
-                }
-
-                hotkey = hotkey->next;
-            }
-            break;
-        }
-    case ButtonPress:
-        {
-            XButtonEvent *buttonevent = (XButtonEvent*)xevent;
-            while (hotkey)
-            {
-                if ((hotkey->key == buttonevent->button) &&
-                    (hotkey->mask == (buttonevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) &&
-                    (hotkey->type == TYPE_MOUSE))
-                {
-                    if (handle_keyevent(hotkey->event))
-                        return GDK_FILTER_REMOVE;
-                    break;
-                }
-
-                hotkey = hotkey->next;
-            }
-
-            break;
-        }
-    }
-
-    return GDK_FILTER_CONTINUE;
-}
-
-gboolean setup_filter()
-{
-    gdk_window_add_filter (gdk_screen_get_root_window
-     (gdk_screen_get_default ()), gdk_filter, NULL);
-
-    return TRUE;
-}
-
-void release_filter()
-{
-    gdk_window_remove_filter (gdk_screen_get_root_window
-     (gdk_screen_get_default ()), gdk_filter, NULL);
-}
diff --git a/src/hotkey/grab.cc b/src/hotkey/grab.cc
new file mode 100644
index 000000000000..252051f0e699
--- /dev/null
+++ b/src/hotkey/grab.cc
@@ -0,0 +1,388 @@
+/*
+ *  This file is part of audacious-hotkey plugin for audacious
+ *
+ *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
+ *  Name: grab.c
+ *  Description: grab.c
+ *
+ *  Part of this code is from itouch-ctrl plugin.
+ *  Authors of itouch-ctrl are listed below:
+ *
+ *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
+ *
+ *  Part of this code are from xmms-itouch plugin.
+ *  Authors of xmms-itouch are listed below:
+ *
+ *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
+ *                         Bryn Davies <curious at ihug.com.au>
+ *                         Jonathan A. Davis <davis at jdhouse.org>
+ *                         Jeremy Tan <nsx at nsx.homeip.net>
+ *
+ *  audacious-hotkey 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.
+ *
+ *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "grab.h"
+#include "plugin.h"
+
+
+static int grabbed = 0;
+static unsigned int numlock_mask = 0;
+static unsigned int scrolllock_mask = 0;
+static unsigned int capslock_mask = 0;
+
+
+/* Taken from xbindkeys */
+static void get_offending_modifiers (Display * dpy)
+{
+    int i;
+    XModifierKeymap *modmap;
+    KeyCode nlock, slock;
+
+    static int mask_table[8] = {
+        ShiftMask, LockMask, ControlMask, Mod1Mask,
+        Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+    };
+
+    nlock = XKeysymToKeycode (dpy, XK_Num_Lock);
+    slock = XKeysymToKeycode (dpy, XK_Scroll_Lock);
+
+    /*
+    * Find out the masks for the NumLock and ScrollLock modifiers,
+    * so that we can bind the grabs for when they are enabled too.
+    */
+    modmap = XGetModifierMapping (dpy);
+
+    if (modmap != nullptr && modmap->max_keypermod > 0)
+    {
+        for (i = 0; i < 8 * modmap->max_keypermod; i++)
+        {
+            if (modmap->modifiermap[i] == nlock && nlock != 0)
+                numlock_mask = mask_table[i / modmap->max_keypermod];
+            else if (modmap->modifiermap[i] == slock && slock != 0)
+                scrolllock_mask = mask_table[i / modmap->max_keypermod];
+        }
+    }
+
+    capslock_mask = LockMask;
+
+    if (modmap)
+        XFreeModifiermap (modmap);
+}
+
+
+static int x11_error_handler (Display *dpy, XErrorEvent *error)
+{
+    return 0;
+}
+
+/* grab required keys */
+static void grab_key(const HotkeyConfiguration *hotkey, Display *xdisplay, Window x_root_window)
+{
+    unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
+
+    if (hotkey->key == 0) return;
+
+    if (hotkey->type == TYPE_KEY)
+    {
+        XGrabKey (xdisplay, hotkey->key, modifier, x_root_window,
+            False, GrabModeAsync, GrabModeAsync);
+
+        if (modifier == AnyModifier)
+            return;
+
+        if (numlock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (capslock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (scrolllock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (numlock_mask && capslock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (numlock_mask && scrolllock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (capslock_mask && scrolllock_mask)
+            XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask,
+                x_root_window,
+                False, GrabModeAsync, GrabModeAsync);
+
+        if (numlock_mask && capslock_mask && scrolllock_mask)
+            XGrabKey (xdisplay, hotkey->key,
+                modifier | numlock_mask | capslock_mask | scrolllock_mask,
+                x_root_window, False, GrabModeAsync,
+                GrabModeAsync);
+    }
+    if (hotkey->type == TYPE_MOUSE)
+    {
+        XGrabButton (xdisplay, hotkey->key, modifier, x_root_window,
+            False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (modifier == AnyModifier)
+            return;
+
+        if (numlock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (capslock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (scrolllock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (numlock_mask && capslock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (numlock_mask && scrolllock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (capslock_mask && scrolllock_mask)
+            XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask,
+                x_root_window,
+                False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
+
+        if (numlock_mask && capslock_mask && scrolllock_mask)
+            XGrabButton (xdisplay, hotkey->key,
+                modifier | numlock_mask | capslock_mask | scrolllock_mask,
+                x_root_window, False, ButtonPressMask, GrabModeAsync,
+                GrabModeAsync, None, None);
+    }
+}
+
+void grab_keys ( )
+{
+    Display* xdisplay;
+    int screen;
+    PluginConfig* plugin_cfg = get_config();
+    HotkeyConfiguration *hotkey;
+
+    XErrorHandler old_handler = 0;
+     xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+
+    if (grabbed) return;
+
+
+    XSync(xdisplay, False);
+    old_handler = XSetErrorHandler (x11_error_handler);
+
+    get_offending_modifiers(xdisplay);
+    hotkey = &(plugin_cfg->first);
+    while (hotkey)
+    {
+        for (screen=0;screen<ScreenCount(xdisplay);screen++)
+        {
+            grab_key(hotkey, xdisplay, RootWindow(xdisplay, screen));
+        }
+        hotkey = hotkey->next;
+    }
+
+    XSync(xdisplay, False);
+    XSetErrorHandler (old_handler);
+
+    grabbed = 1;
+}
+
+
+
+/* grab required keys */
+static void ungrab_key(HotkeyConfiguration *hotkey, Display* xdisplay, Window x_root_window)
+{
+    unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
+
+    if (hotkey->key == 0) return;
+
+    if (hotkey->type == TYPE_KEY)
+    {
+        XUngrabKey (xdisplay, hotkey->key, modifier, x_root_window);
+
+        if (modifier == AnyModifier)
+            return;
+
+        if (numlock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window);
+
+        if (capslock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window);
+
+        if (scrolllock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window);
+
+        if (numlock_mask && capslock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window);
+
+        if (numlock_mask && scrolllock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window);
+
+        if (capslock_mask && scrolllock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window);
+
+        if (numlock_mask && capslock_mask && scrolllock_mask)
+            XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
+    }
+    if (hotkey->type == TYPE_MOUSE)
+    {
+        XUngrabButton (xdisplay, hotkey->key, modifier, x_root_window);
+
+        if (modifier == AnyModifier)
+            return;
+
+        if (numlock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window);
+
+        if (capslock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window);
+
+        if (scrolllock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window);
+
+        if (numlock_mask && capslock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window);
+
+        if (numlock_mask && scrolllock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window);
+
+        if (capslock_mask && scrolllock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window);
+
+        if (numlock_mask && capslock_mask && scrolllock_mask)
+            XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
+    }
+}
+
+void ungrab_keys ( )
+{
+    Display* xdisplay;
+    int screen;
+    PluginConfig* plugin_cfg = get_config();
+    HotkeyConfiguration *hotkey;
+
+    XErrorHandler old_handler = 0;
+     xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+
+    if (!grabbed) return;
+    if (!xdisplay) return;
+
+    XSync(xdisplay, False);
+    old_handler = XSetErrorHandler (x11_error_handler);
+
+    get_offending_modifiers(xdisplay);
+
+    hotkey = &(plugin_cfg->first);
+    while (hotkey)
+    {
+        for (screen=0;screen<ScreenCount(xdisplay);screen++)
+        {
+            ungrab_key(hotkey, xdisplay, RootWindow(xdisplay, screen));
+        }
+        hotkey = hotkey->next;
+    }
+
+    XSync(xdisplay, False);
+    XSetErrorHandler (old_handler);
+
+    grabbed = 0;
+}
+
+
+static GdkFilterReturn
+gdk_filter(GdkXEvent *xevent,
+       GdkEvent *event,
+       void * data)
+{
+    HotkeyConfiguration *hotkey;
+    hotkey = &(get_config()->first);
+    switch (((XEvent*)xevent)->type)
+    {
+    case KeyPress:
+        {
+            XKeyEvent *keyevent = (XKeyEvent*)xevent;
+            while (hotkey)
+            {
+                if ((hotkey->key == keyevent->keycode) &&
+                    (hotkey->mask == (keyevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) &&
+                    (hotkey->type == TYPE_KEY))
+                {
+                    if (handle_keyevent(hotkey->event))
+                        return GDK_FILTER_REMOVE;
+                    break;
+                }
+
+                hotkey = hotkey->next;
+            }
+            break;
+        }
+    case ButtonPress:
+        {
+            XButtonEvent *buttonevent = (XButtonEvent*)xevent;
+            while (hotkey)
+            {
+                if ((hotkey->key == buttonevent->button) &&
+                    (hotkey->mask == (buttonevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) &&
+                    (hotkey->type == TYPE_MOUSE))
+                {
+                    if (handle_keyevent(hotkey->event))
+                        return GDK_FILTER_REMOVE;
+                    break;
+                }
+
+                hotkey = hotkey->next;
+            }
+
+            break;
+        }
+    }
+
+    return GDK_FILTER_CONTINUE;
+}
+
+gboolean setup_filter()
+{
+    gdk_window_add_filter (gdk_screen_get_root_window
+     (gdk_screen_get_default ()), gdk_filter, nullptr);
+
+    return TRUE;
+}
+
+void release_filter()
+{
+    gdk_window_remove_filter (gdk_screen_get_root_window
+     (gdk_screen_get_default ()), gdk_filter, nullptr);
+}
diff --git a/src/hotkey/gui.c b/src/hotkey/gui.c
deleted file mode 100644
index acf133160984..000000000000
--- a/src/hotkey/gui.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- *  This file is part of audacious-hotkey plugin for audacious
- *
- *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
- *  Name: gui.c
- *  Description: gui.c
- *
- *  Part of this code is from itouch-ctrl plugin.
- *  Authors of itouch-ctrl are listed below:
- *
- *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
- *
- *  Part of this code are from xmms-itouch plugin.
- *  Authors of xmms-itouch are listed below:
- *
- *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
- *                         Bryn Davies <curious at ihug.com.au>
- *                         Jonathan A. Davis <davis at jdhouse.org>
- *                         Jeremy Tan <nsx at nsx.homeip.net>
- *
- *  audacious-hotkey 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.
- *
- *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <gdk/gdkkeysyms-compat.h>
-
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include <X11/XKBlib.h>
-
-#include "plugin.h"
-#include "gui.h"
-#include "grab.h"
-
-typedef struct _KeyControls {
-    GtkWidget *keytext;
-    GtkWidget *grid;
-    GtkWidget *button;
-    GtkWidget *combobox;
-
-    HotkeyConfiguration hotkey;
-    struct _KeyControls *next, *prev, *first;
-} KeyControls;
-
-
-static void clear_keyboard (GtkWidget *widget, gpointer data);
-static void add_callback (GtkWidget *widget, gpointer data);
-static void cancel_callback (GtkWidget *widget, gpointer data);
-static void destroy_callback (GtkWidget *widget, gpointer data);
-static void ok_callback (GtkWidget *widget, gpointer data);
-
-
-static gchar* event_desc[EVENT_MAX] = {
-    [EVENT_PREV_TRACK] = N_("Previous track"),
-    [EVENT_PLAY] = N_("Play"),
-    [EVENT_PAUSE] = N_("Pause/Resume"),
-    [EVENT_STOP] = N_("Stop"),
-    [EVENT_NEXT_TRACK] = N_("Next track"),
-    [EVENT_FORWARD] = N_("Forward 5 seconds"),
-    [EVENT_BACKWARD] = N_("Rewind 5 seconds"),
-    [EVENT_MUTE] = N_("Mute"),
-    [EVENT_VOL_UP] = N_("Volume up"),
-    [EVENT_VOL_DOWN] = N_("Volume down"),
-    [EVENT_JUMP_TO_FILE] = N_("Jump to file"),
-    [EVENT_TOGGLE_WIN] = N_("Toggle player window(s)"),
-    [EVENT_SHOW_AOSD] = N_("Show On-Screen-Display"),
-    [EVENT_TOGGLE_REPEAT] = N_("Toggle repeat"),
-    [EVENT_TOGGLE_SHUFFLE] = N_("Toggle shuffle"),
-    [EVENT_TOGGLE_STOP] = N_("Toggle stop after current"),
-    [EVENT_RAISE] = N_("Raise player window(s)")
-};
-
-
-static void set_keytext (GtkWidget *entry, gint key, gint mask, gint type)
-{
-    gchar *text = NULL;
-
-    if (key == 0 && mask == 0)
-    {
-        text = g_strdup(_("(none)"));
-    } else {
-        static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" };
-        static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
-        gchar *strings[9];
-        gchar *keytext = NULL;
-        int i, j;
-        if (type == TYPE_KEY)
-        {
-            KeySym keysym;
-            keysym = XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0, 0);
-            if (keysym == 0 || keysym == NoSymbol)
-            {
-                keytext = g_strdup_printf("#%d", key);
-            } else {
-                keytext = g_strdup(XKeysymToString(keysym));
-            }
-        }
-        if (type == TYPE_MOUSE)
-        {
-            keytext = g_strdup_printf("Button%d", key);
-        }
-
-        for (i = 0, j=0; j<7; j++)
-        {
-            if (mask & modifiers[j])
-                 strings[i++] = modifier_string[j];
-        }
-        if (key != 0) strings[i++] = keytext;
-        strings[i] = NULL;
-
-        text = g_strjoinv(" + ", strings);
-        g_free(keytext);
-    }
-
-    gtk_entry_set_text(GTK_ENTRY(entry), text);
-    gtk_editable_set_position(GTK_EDITABLE(entry), -1);
-    if (text) g_free(text);
-}
-
-static gboolean
-on_entry_key_press_event(GtkWidget * widget,
-                         GdkEventKey * event,
-                         gpointer user_data)
-{
-    KeyControls *controls = (KeyControls*) user_data;
-    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_ISO_Left_Tab)
-    {
-        set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
-        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;
-
-    if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R))))
-            mod |= ControlMask;
-
-    if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R))))
-            mod |= Mod1Mask;
-
-    if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R))))
-            mod |= ShiftMask;
-
-    if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift))))
-            mod |= Mod5Mask;
-
-    if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R))))
-            mod |= Mod4Mask;
-
-    if (!is_mod) {
-        controls->hotkey.key = event->hardware_keycode;
-        controls->hotkey.mask = mod;
-        controls->hotkey.type = TYPE_KEY;
-        if (controls->next == NULL)
-            add_callback (NULL, (gpointer) controls);
-        else gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext));
-    }
-
-    set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY);
-    return TRUE;
-}
-
-static gboolean
-on_entry_key_release_event(GtkWidget * widget,
-                           GdkEventKey * event,
-                           gpointer user_data)
-{
-    KeyControls *controls = (KeyControls*) user_data;
-    if (!gtk_widget_is_focus(widget)) return FALSE;
-    set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
-
-    return TRUE;
-}
-
-static gboolean
-on_entry_button_press_event(GtkWidget * widget,
-                            GdkEventButton * event,
-                            gpointer user_data)
-{
-    KeyControls *controls = (KeyControls*) user_data;
-    int mod;
-
-    if (!gtk_widget_is_focus(widget)) return FALSE;
-
-    mod = 0;
-    if (event->state & GDK_CONTROL_MASK)
-            mod |= ControlMask;
-
-    if (event->state & GDK_MOD1_MASK)
-            mod |= Mod1Mask;
-
-    if (event->state & GDK_SHIFT_MASK)
-            mod |= ShiftMask;
-
-    if (event->state & GDK_MOD5_MASK)
-            mod |= Mod5Mask;
-
-    if (event->state & GDK_MOD4_MASK)
-            mod |= Mod4Mask;
-
-    if ((event->button <= 3) && (mod == 0))
-    {
-        GtkWidget* dialog;
-        GtkResponseType response;
-        dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)),
-            GTK_DIALOG_MODAL,
-            GTK_MESSAGE_WARNING,
-            GTK_BUTTONS_YES_NO,
-            _("It is not recommended to bind the primary mouse buttons without modificators.\n\n"
-              "Do you want to continue?"));
-        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;
-    }
-
-    controls->hotkey.key = event->button;
-    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 == NULL)
-        add_callback (NULL, (gpointer) controls);
-
-    return TRUE;
-}
-
-static gboolean
-on_entry_scroll_event(GtkWidget * widget,
-                            GdkEventScroll * event,
-                            gpointer user_data)
-{
-    KeyControls *controls = (KeyControls*) user_data;
-    int mod;
-
-    if (!gtk_widget_is_focus(widget)) return FALSE;
-
-    mod = 0;
-    if (event->state & GDK_CONTROL_MASK)
-            mod |= ControlMask;
-
-    if (event->state & GDK_MOD1_MASK)
-            mod |= Mod1Mask;
-
-    if (event->state & GDK_SHIFT_MASK)
-            mod |= ShiftMask;
-
-    if (event->state & GDK_MOD5_MASK)
-            mod |= Mod5Mask;
-
-    if (event->state & GDK_MOD4_MASK)
-            mod |= Mod4Mask;
-
-    if (event->direction == GDK_SCROLL_UP)
-        controls->hotkey.key = 4;
-    else if (event->direction == GDK_SCROLL_DOWN)
-        controls->hotkey.key = 5;
-    else if (event->direction == GDK_SCROLL_LEFT)
-        controls->hotkey.key = 6;
-    else if (event->direction == GDK_SCROLL_RIGHT)
-        controls->hotkey.key = 7;
-    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 == NULL)
-        add_callback (NULL, (gpointer) controls);
-    return TRUE;
-}
-
-KeyControls* add_event_controls(KeyControls* list,
-                GtkWidget *grid,
-                int row,
-                HotkeyConfiguration *hotkey)
-{
-    KeyControls *controls;
-    int i;
-
-    controls = (KeyControls*) g_malloc(sizeof(KeyControls));
-    controls->next = NULL;
-    controls->prev = list;
-    controls->first = list->first;
-    controls->grid = grid;
-    list->next = controls;
-
-    if (hotkey)
-    {
-        controls->hotkey.key = hotkey->key;
-        controls->hotkey.mask = hotkey->mask;
-        controls->hotkey.type = hotkey->type;
-        controls->hotkey.event = hotkey->event;
-        if (controls->hotkey.key == 0)
-            controls->hotkey.mask = 0;
-    } else {
-        controls->hotkey.key = 0;
-        controls->hotkey.mask = 0;
-        controls->hotkey.type = TYPE_KEY;
-        controls->hotkey.event = 0;
-    }
-
-    controls->combobox = gtk_combo_box_text_new();
-    gtk_widget_set_hexpand(controls->combobox, TRUE);
-    for (i=0;i<EVENT_MAX;i++)
-    {
-        gtk_combo_box_text_append_text((GtkComboBoxText *) controls->combobox, _(event_desc[i]));
-    }
-    gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), controls->hotkey.event);
-    gtk_grid_attach (GTK_GRID (grid), controls->combobox, 0, row, 1, 1);
-
-
-    controls->keytext = gtk_entry_new ();
-    gtk_widget_set_hexpand (controls->keytext, TRUE);
-    gtk_grid_attach (GTK_GRID (grid), controls->keytext, 1, row, 1, 1);
-    gtk_editable_set_editable(GTK_EDITABLE(controls->keytext), FALSE);
-
-
-    set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
-    g_signal_connect((gpointer)controls->keytext, "key_press_event",
-                         G_CALLBACK(on_entry_key_press_event), controls);
-    g_signal_connect((gpointer)controls->keytext, "key_release_event",
-                         G_CALLBACK(on_entry_key_release_event), controls);
-    g_signal_connect((gpointer)controls->keytext, "button_press_event",
-                         G_CALLBACK(on_entry_button_press_event), controls);
-    g_signal_connect((gpointer)controls->keytext, "scroll_event",
-                         G_CALLBACK(on_entry_scroll_event), controls);
-
-
-    controls->button = gtk_button_new();
-    gtk_button_set_image (GTK_BUTTON (controls->button),
-     gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_BUTTON));
-    gtk_grid_attach (GTK_GRID (grid), controls->button, 2, row, 1, 1);
-    g_signal_connect (G_OBJECT (controls->button), "clicked",
-            G_CALLBACK (clear_keyboard), controls);
-
-    gtk_widget_grab_focus(GTK_WIDGET(controls->keytext));
-    return controls;
-}
-
-void show_configure ()
-{
-    KeyControls *first_controls, *current_controls;
-    GtkWidget *window;
-    GtkWidget *main_vbox, *hbox;
-    GtkWidget *alignment;
-    GtkWidget *frame;
-    GtkWidget *label;
-    GtkWidget *image;
-    GtkWidget *grid;
-    GtkWidget *button_box, *button;
-    PluginConfig* plugin_cfg;
-    HotkeyConfiguration *hotkey, temphotkey;
-    int i;
-
-    load_config ( );
-
-    plugin_cfg = get_config();
-
-    ungrab_keys();
-
-    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_title (GTK_WINDOW (window), _("Global Hotkey Plugin Configuration"));
-    gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG);
-    gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
-    gtk_container_set_border_width (GTK_CONTAINER (window), 5);
-
-    main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
-    gtk_container_add (GTK_CONTAINER (window), main_vbox);
-
-    alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
-    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_box_new (GTK_ORIENTATION_HORIZONTAL, 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);
-    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_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-
-    label = gtk_label_new (NULL);
-    gtk_label_set_markup (GTK_LABEL (label), _("Hotkeys:"));
-    frame = gtk_frame_new (NULL);
-    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-    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_grid_new ();
-    gtk_grid_set_column_spacing (GTK_GRID (grid), 2);
-    gtk_container_add (GTK_CONTAINER (alignment), grid);
-
-    label = gtk_label_new (NULL);
-    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
-    gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
-    gtk_label_set_markup (GTK_LABEL (label),
-            _("<b>Action:</b>"));
-    gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-
-    label = gtk_label_new (NULL);
-    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
-    gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
-    gtk_label_set_markup (GTK_LABEL (label),
-            _("<b>Key Binding:</b>"));
-    gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
-
-
-    hotkey = &(plugin_cfg->first);
-    i = 1;
-    first_controls = (KeyControls*) g_malloc(sizeof(KeyControls));
-    first_controls->next = NULL;
-    first_controls->prev = NULL;
-    first_controls->grid = grid;
-    first_controls->button = NULL;
-    first_controls->combobox = NULL;
-    first_controls->keytext = NULL;
-    first_controls->first = first_controls;
-    first_controls->hotkey.key = 0;
-    first_controls->hotkey.mask = 0;
-    first_controls->hotkey.event = 0;
-    first_controls->hotkey.type = TYPE_KEY;
-    current_controls = first_controls;
-    if (hotkey -> key != 0)
-    {
-        while (hotkey)
-        {
-            current_controls = add_event_controls(current_controls, grid, i, hotkey);
-            hotkey = hotkey->next;
-            i++;
-        }
-    }
-    temphotkey.key = 0;
-    temphotkey.mask = 0;
-    temphotkey.type = TYPE_KEY;
-    if (current_controls != first_controls)
-        temphotkey.event = current_controls->hotkey.event+1;
-    else temphotkey.event = 0;
-    if (temphotkey.event >= EVENT_MAX) temphotkey.event = 0;
-    add_event_controls(current_controls, grid, i, &temphotkey);
-
-
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-    gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
-
-    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
-    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);
-
-    button = audgui_button_new (_("_Add"), "list-add", NULL, NULL);
-    gtk_container_add (GTK_CONTAINER (button_box), button);
-    g_signal_connect (G_OBJECT (button), "clicked",
-            G_CALLBACK (add_callback), first_controls);
-
-    button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
-    gtk_box_pack_start (GTK_BOX (hbox), button_box, TRUE, TRUE, 0);
-    gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END);
-    gtk_box_set_spacing (GTK_BOX (button_box), 4);
-
-    button = audgui_button_new (_("_Cancel"), "process-stop", NULL, NULL);
-    gtk_container_add (GTK_CONTAINER (button_box), button);
-    g_signal_connect (G_OBJECT (button), "clicked",
-            G_CALLBACK (cancel_callback), NULL);
-
-    button = audgui_button_new (_("_Set"), "system-run", NULL, NULL);
-    gtk_container_add (GTK_CONTAINER (button_box), button);
-    g_signal_connect (G_OBJECT (button), "clicked",
-            G_CALLBACK (ok_callback), first_controls);
-
-    g_signal_connect (G_OBJECT (window), "destroy",
-        G_CALLBACK (destroy_callback), first_controls);
-
-    gtk_widget_show_all (GTK_WIDGET (window));
-}
-
-static void clear_keyboard (GtkWidget *widget, gpointer data)
-{
-    KeyControls *controls= (KeyControls*)data;
-
-    if ((controls->next == NULL) && (controls->prev->keytext == NULL))
-    {
-        controls->hotkey.key = 0;
-        controls->hotkey.mask = 0;
-        controls->hotkey.type = TYPE_KEY;
-        set_keytext(controls->keytext, 0, 0, TYPE_KEY);
-        gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), 0);
-        return;
-    }
-
-    if (controls->prev)
-    {
-        KeyControls* c;
-        GtkWidget* grid;
-        int row;
-
-        gtk_widget_destroy(GTK_WIDGET(controls->button));
-        gtk_widget_destroy(GTK_WIDGET(controls->keytext));
-        gtk_widget_destroy(GTK_WIDGET(controls->combobox));
-
-        row=0;
-        c = controls->first;
-        while (c) {
-            if (c == controls) break;
-            row++;
-            c = c->next;
-        }
-        c = controls->next;
-        controls->prev->next = controls->next;
-        if (controls->next)
-            controls->next->prev = controls->prev;
-        g_free(controls);
-        if (c) grid = c->grid; else grid = NULL;
-        while (c)
-        {
-            g_object_ref(c->combobox);
-            g_object_ref(c->keytext);
-            g_object_ref(c->button);
-
-            gtk_container_remove( GTK_CONTAINER(c->grid) , c->combobox);
-            gtk_container_remove( GTK_CONTAINER(c->grid) , c->keytext);
-            gtk_container_remove( GTK_CONTAINER(c->grid) , c->button);
-
-            gtk_grid_attach (GTK_GRID (c->grid), c->combobox, 0, row, 1, 1);
-            gtk_grid_attach (GTK_GRID (c->grid), c->keytext, 1, row, 1, 1);
-            gtk_grid_attach (GTK_GRID (c->grid), c->button, 2, row, 1, 1);
-
-            g_object_unref(c->combobox);
-            g_object_unref(c->keytext);
-            g_object_unref(c->button);
-
-            c = c->next;
-            row++;
-        }
-        if (grid)
-            gtk_widget_show_all (GTK_WIDGET (grid));
-
-        return;
-    }
-}
-
-void add_callback (GtkWidget *widget, gpointer data)
-{
-    KeyControls* controls = (KeyControls*)data;
-    HotkeyConfiguration temphotkey;
-    int count;
-    if (controls == NULL) return;
-    if ((controls->next == NULL)&&(controls->hotkey.event+1 == EVENT_MAX)) return;
-    controls = controls->first;
-    if (controls == NULL) return;
-    count = 1;
-    while (controls->next) {
-        controls = controls->next;
-        count = count + 1;
-    }
-    temphotkey.key = 0;
-    temphotkey.mask = 0;
-    temphotkey.type = TYPE_KEY;
-    temphotkey.event = controls->hotkey.event+1;
-    if (temphotkey.event >= EVENT_MAX) temphotkey.event = 0;
-    add_event_controls(controls, controls->grid, count, &temphotkey);
-    gtk_widget_show_all (GTK_WIDGET (controls->grid));
-}
-
-void destroy_callback (GtkWidget *widget, gpointer data)
-{
-    KeyControls* controls = (KeyControls*)data;
-    if (is_loaded())
-    {
-        grab_keys ();
-    }
-    while (controls) {
-        KeyControls *old;
-        old = controls;
-        controls = controls->next;
-        g_free(old);
-    }
-}
-
-void cancel_callback (GtkWidget *widget, gpointer data)
-{
-    gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget)));
-}
-
-void ok_callback (GtkWidget *widget, gpointer data)
-{
-    KeyControls *controls = (KeyControls*)data;
-    PluginConfig* plugin_cfg = get_config();
-    HotkeyConfiguration *hotkey;
-
-    hotkey = &(plugin_cfg->first);
-    hotkey = hotkey->next;
-    while (hotkey)
-    {
-        HotkeyConfiguration * old;
-        old = hotkey;
-        hotkey = hotkey->next;
-        g_free(old);
-    }
-    plugin_cfg->first.next = NULL;
-    plugin_cfg->first.key = 0;
-    plugin_cfg->first.event = 0;
-    plugin_cfg->first.mask = 0;
-
-    hotkey = &(plugin_cfg->first);
-    while (controls)
-    {
-        if (controls->hotkey.key) {
-            if (hotkey->key) {
-                hotkey->next = g_new(HotkeyConfiguration, 1);
-                hotkey = hotkey->next;
-                hotkey->next = NULL;
-            }
-            hotkey->key = controls->hotkey.key;
-            hotkey->mask = controls->hotkey.mask;
-            hotkey->event = gtk_combo_box_get_active( GTK_COMBO_BOX(controls->combobox) );
-            hotkey->type = controls->hotkey.type;
-        }
-        controls = controls->next;
-    }
-
-    save_config ( );
-
-    gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget)));
-}
diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc
new file mode 100644
index 000000000000..4f7c413de572
--- /dev/null
+++ b/src/hotkey/gui.cc
@@ -0,0 +1,631 @@
+/*
+ *  This file is part of audacious-hotkey plugin for audacious
+ *
+ *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
+ *  Name: gui.c
+ *  Description: gui.c
+ *
+ *  Part of this code is from itouch-ctrl plugin.
+ *  Authors of itouch-ctrl are listed below:
+ *
+ *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
+ *
+ *  Part of this code are from xmms-itouch plugin.
+ *  Authors of xmms-itouch are listed below:
+ *
+ *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
+ *                         Bryn Davies <curious at ihug.com.au>
+ *                         Jonathan A. Davis <davis at jdhouse.org>
+ *                         Jeremy Tan <nsx at nsx.homeip.net>
+ *
+ *  audacious-hotkey 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.
+ *
+ *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/preferences.h>
+
+#include <libaudgui/libaudgui-gtk.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms-compat.h>
+
+#include <X11/XKBlib.h>
+
+#include "plugin.h"
+#include "gui.h"
+#include "grab.h"
+
+typedef struct _KeyControls {
+    GtkWidget *keytext;
+    GtkWidget *grid;
+    GtkWidget *button;
+    GtkWidget *combobox;
+
+    HotkeyConfiguration hotkey;
+    struct _KeyControls *next, *prev, *first;
+} KeyControls;
+
+static KeyControls *first_controls;
+
+
+static void clear_keyboard (GtkWidget *widget, void * data);
+static void add_callback (GtkWidget *widget, void * data);
+static void destroy_callback ();
+static void ok_callback ();
+
+
+static const char * event_desc[EVENT_MAX] = {
+    [EVENT_PREV_TRACK] = N_("Previous track"),
+    [EVENT_PLAY] = N_("Play"),
+    [EVENT_PAUSE] = N_("Pause/Resume"),
+    [EVENT_STOP] = N_("Stop"),
+    [EVENT_NEXT_TRACK] = N_("Next track"),
+    [EVENT_FORWARD] = N_("Forward 5 seconds"),
+    [EVENT_BACKWARD] = N_("Rewind 5 seconds"),
+    [EVENT_MUTE] = N_("Mute"),
+    [EVENT_VOL_UP] = N_("Volume up"),
+    [EVENT_VOL_DOWN] = N_("Volume down"),
+    [EVENT_JUMP_TO_FILE] = N_("Jump to file"),
+    [EVENT_TOGGLE_WIN] = N_("Toggle player window(s)"),
+    [EVENT_SHOW_AOSD] = N_("Show On-Screen-Display"),
+    [EVENT_TOGGLE_REPEAT] = N_("Toggle repeat"),
+    [EVENT_TOGGLE_SHUFFLE] = N_("Toggle shuffle"),
+    [EVENT_TOGGLE_STOP] = N_("Toggle stop after current"),
+    [EVENT_RAISE] = N_("Raise player window(s)")
+};
+
+
+static void set_keytext (GtkWidget *entry, int key, int mask, int type)
+{
+    char *text = nullptr;
+
+    if (key == 0 && mask == 0)
+    {
+        text = g_strdup(_("(none)"));
+    } else {
+        static const char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" };
+        static const unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
+        const char *strings[9];
+        char *keytext = nullptr;
+        int i, j;
+        if (type == TYPE_KEY)
+        {
+            KeySym keysym;
+            keysym = XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0, 0);
+            if (keysym == 0 || keysym == NoSymbol)
+            {
+                keytext = g_strdup_printf("#%d", key);
+            } else {
+                keytext = g_strdup(XKeysymToString(keysym));
+            }
+        }
+        if (type == TYPE_MOUSE)
+        {
+            keytext = g_strdup_printf("Button%d", key);
+        }
+
+        for (i = 0, j=0; j<7; j++)
+        {
+            if (mask & modifiers[j])
+                 strings[i++] = modifier_string[j];
+        }
+        if (key != 0) strings[i++] = keytext;
+        strings[i] = nullptr;
+
+        text = g_strjoinv(" + ", (char **)strings);
+        g_free(keytext);
+    }
+
+    gtk_entry_set_text(GTK_ENTRY(entry), text);
+    gtk_editable_set_position(GTK_EDITABLE(entry), -1);
+    if (text) g_free(text);
+}
+
+static gboolean
+on_entry_key_press_event(GtkWidget * widget,
+                         GdkEventKey * event,
+                         void * user_data)
+{
+    KeyControls *controls = (KeyControls*) user_data;
+    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_ISO_Left_Tab)
+    {
+        set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
+        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;
+
+    if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R))))
+            mod |= ControlMask;
+
+    if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R))))
+            mod |= Mod1Mask;
+
+    if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R))))
+            mod |= ShiftMask;
+
+    if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift))))
+            mod |= Mod5Mask;
+
+    if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R))))
+            mod |= Mod4Mask;
+
+    if (!is_mod) {
+        controls->hotkey.key = event->hardware_keycode;
+        controls->hotkey.mask = mod;
+        controls->hotkey.type = TYPE_KEY;
+        if (controls->next == nullptr)
+            add_callback (nullptr, (void *) controls);
+        else gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext));
+    }
+
+    set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY);
+    return TRUE;
+}
+
+static gboolean
+on_entry_key_release_event(GtkWidget * widget,
+                           GdkEventKey * event,
+                           void * user_data)
+{
+    KeyControls *controls = (KeyControls*) user_data;
+    if (!gtk_widget_is_focus(widget)) return FALSE;
+    set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
+
+    return TRUE;
+}
+
+static gboolean
+on_entry_button_press_event(GtkWidget * widget,
+                            GdkEventButton * event,
+                            void * user_data)
+{
+    KeyControls *controls = (KeyControls*) user_data;
+    int mod;
+
+    if (!gtk_widget_is_focus(widget)) return FALSE;
+
+    mod = 0;
+    if (event->state & GDK_CONTROL_MASK)
+            mod |= ControlMask;
+
+    if (event->state & GDK_MOD1_MASK)
+            mod |= Mod1Mask;
+
+    if (event->state & GDK_SHIFT_MASK)
+            mod |= ShiftMask;
+
+    if (event->state & GDK_MOD5_MASK)
+            mod |= Mod5Mask;
+
+    if (event->state & GDK_MOD4_MASK)
+            mod |= Mod4Mask;
+
+    if ((event->button <= 3) && (mod == 0))
+    {
+        GtkWidget* dialog;
+        int response;
+        dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)),
+            GTK_DIALOG_MODAL,
+            GTK_MESSAGE_WARNING,
+            GTK_BUTTONS_YES_NO,
+            _("It is not recommended to bind the primary mouse buttons without modificators.\n\n"
+              "Do you want to continue?"));
+        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;
+    }
+
+    controls->hotkey.key = event->button;
+    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;
+}
+
+static gboolean
+on_entry_scroll_event(GtkWidget * widget,
+                            GdkEventScroll * event,
+                            void * user_data)
+{
+    KeyControls *controls = (KeyControls*) user_data;
+    int mod;
+
+    if (!gtk_widget_is_focus(widget)) return FALSE;
+
+    mod = 0;
+    if (event->state & GDK_CONTROL_MASK)
+            mod |= ControlMask;
+
+    if (event->state & GDK_MOD1_MASK)
+            mod |= Mod1Mask;
+
+    if (event->state & GDK_SHIFT_MASK)
+            mod |= ShiftMask;
+
+    if (event->state & GDK_MOD5_MASK)
+            mod |= Mod5Mask;
+
+    if (event->state & GDK_MOD4_MASK)
+            mod |= Mod4Mask;
+
+    if (event->direction == GDK_SCROLL_UP)
+        controls->hotkey.key = 4;
+    else if (event->direction == GDK_SCROLL_DOWN)
+        controls->hotkey.key = 5;
+    else if (event->direction == GDK_SCROLL_LEFT)
+        controls->hotkey.key = 6;
+    else if (event->direction == GDK_SCROLL_RIGHT)
+        controls->hotkey.key = 7;
+    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;
+}
+
+KeyControls* add_event_controls(KeyControls* list,
+                GtkWidget *grid,
+                int row,
+                HotkeyConfiguration *hotkey)
+{
+    KeyControls *controls;
+    int i;
+
+    controls = (KeyControls*) g_malloc(sizeof(KeyControls));
+    controls->next = nullptr;
+    controls->prev = list;
+    controls->first = list->first;
+    controls->grid = grid;
+    list->next = controls;
+
+    if (hotkey)
+    {
+        controls->hotkey.key = hotkey->key;
+        controls->hotkey.mask = hotkey->mask;
+        controls->hotkey.type = hotkey->type;
+        controls->hotkey.event = hotkey->event;
+        if (controls->hotkey.key == 0)
+            controls->hotkey.mask = 0;
+    } else {
+        controls->hotkey.key = 0;
+        controls->hotkey.mask = 0;
+        controls->hotkey.type = TYPE_KEY;
+        controls->hotkey.event = (EVENT) 0;
+    }
+
+    controls->combobox = gtk_combo_box_text_new();
+    for (i=0;i<EVENT_MAX;i++)
+    {
+        gtk_combo_box_text_append_text((GtkComboBoxText *) controls->combobox, _(event_desc[i]));
+    }
+    gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), controls->hotkey.event);
+    gtk_table_attach_defaults (GTK_TABLE (grid), controls->combobox, 0, 1, row, row + 1);
+
+
+    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);
+
+
+    set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
+    g_signal_connect((void *)controls->keytext, "key_press_event",
+                         G_CALLBACK(on_entry_key_press_event), controls);
+    g_signal_connect((void *)controls->keytext, "key_release_event",
+                         G_CALLBACK(on_entry_key_release_event), controls);
+    g_signal_connect((void *)controls->keytext, "button_press_event",
+                         G_CALLBACK(on_entry_button_press_event), controls);
+    g_signal_connect((void *)controls->keytext, "scroll_event",
+                         G_CALLBACK(on_entry_scroll_event), controls);
+
+
+    controls->button = gtk_button_new();
+    gtk_button_set_image (GTK_BUTTON (controls->button),
+     gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_BUTTON));
+    gtk_table_attach_defaults (GTK_TABLE (grid), controls->button, 2, 3, row, row + 1);
+    g_signal_connect (G_OBJECT (controls->button), "clicked",
+            G_CALLBACK (clear_keyboard), controls);
+
+    gtk_widget_grab_focus(GTK_WIDGET(controls->keytext));
+    return controls;
+}
+
+void *make_config_widget ()
+{
+    KeyControls *current_controls;
+    GtkWidget *main_vbox, *hbox;
+    GtkWidget *alignment;
+    GtkWidget *frame;
+    GtkWidget *label;
+    GtkWidget *image;
+    GtkWidget *grid;
+    GtkWidget *button_box, *button;
+    PluginConfig* plugin_cfg;
+    HotkeyConfiguration *hotkey, temphotkey;
+    int i;
+
+    load_config ( );
+
+    plugin_cfg = get_config();
+
+    ungrab_keys();
+
+    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_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0);
+    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);
+    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_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_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);
+    gtk_table_set_col_spacings (GTK_TABLE (grid), 2);
+    gtk_container_add (GTK_CONTAINER (alignment), grid);
+
+    label = gtk_label_new (nullptr);
+    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
+    gtk_label_set_markup (GTK_LABEL (label),
+            _("<b>Action:</b>"));
+    gtk_table_attach_defaults (GTK_TABLE (grid), label, 0, 1, 0, 1);
+
+    label = gtk_label_new (nullptr);
+    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
+    gtk_label_set_markup (GTK_LABEL (label),
+            _("<b>Key Binding:</b>"));
+    gtk_table_attach_defaults (GTK_TABLE (grid), label, 1, 2, 0, 1);
+
+
+    hotkey = &(plugin_cfg->first);
+    i = 1;
+    first_controls = (KeyControls*) g_malloc(sizeof(KeyControls));
+    first_controls->next = nullptr;
+    first_controls->prev = nullptr;
+    first_controls->grid = grid;
+    first_controls->button = nullptr;
+    first_controls->combobox = nullptr;
+    first_controls->keytext = nullptr;
+    first_controls->first = first_controls;
+    first_controls->hotkey.key = 0;
+    first_controls->hotkey.mask = 0;
+    first_controls->hotkey.event = (EVENT) 0;
+    first_controls->hotkey.type = TYPE_KEY;
+    current_controls = first_controls;
+    if (hotkey -> key != 0)
+    {
+        while (hotkey)
+        {
+            current_controls = add_event_controls(current_controls, grid, i, hotkey);
+            hotkey = hotkey->next;
+            i++;
+        }
+    }
+    temphotkey.key = 0;
+    temphotkey.mask = 0;
+    temphotkey.type = TYPE_KEY;
+    if (current_controls != first_controls)
+        temphotkey.event = (EVENT) (current_controls->hotkey.event + 1);
+    else
+        temphotkey.event = (EVENT) 0;
+    if (temphotkey.event >= EVENT_MAX)
+        temphotkey.event = (EVENT) 0;
+    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);
+
+    button_box = gtk_hbutton_box_new ();
+    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);
+
+    button = audgui_button_new (_("_Add"), "list-add", nullptr, nullptr);
+    gtk_container_add (GTK_CONTAINER (button_box), button);
+    g_signal_connect (G_OBJECT (button), "clicked",
+            G_CALLBACK (add_callback), first_controls);
+
+    return main_vbox;
+}
+
+static void clear_keyboard (GtkWidget *widget, void * data)
+{
+    KeyControls *controls= (KeyControls*)data;
+
+    if ((controls->next == nullptr) && (controls->prev->keytext == nullptr))
+    {
+        controls->hotkey.key = 0;
+        controls->hotkey.mask = 0;
+        controls->hotkey.type = TYPE_KEY;
+        set_keytext(controls->keytext, 0, 0, TYPE_KEY);
+        gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), 0);
+        return;
+    }
+
+    if (controls->prev)
+    {
+        KeyControls* c;
+        GtkWidget* grid;
+        int row;
+
+        gtk_widget_destroy(GTK_WIDGET(controls->button));
+        gtk_widget_destroy(GTK_WIDGET(controls->keytext));
+        gtk_widget_destroy(GTK_WIDGET(controls->combobox));
+
+        row=0;
+        c = controls->first;
+        while (c) {
+            if (c == controls) break;
+            row++;
+            c = c->next;
+        }
+        c = controls->next;
+        controls->prev->next = controls->next;
+        if (controls->next)
+            controls->next->prev = controls->prev;
+        g_free(controls);
+        if (c) grid = c->grid; else grid = nullptr;
+        while (c)
+        {
+            g_object_ref(c->combobox);
+            g_object_ref(c->keytext);
+            g_object_ref(c->button);
+
+            gtk_container_remove( GTK_CONTAINER(c->grid) , c->combobox);
+            gtk_container_remove( GTK_CONTAINER(c->grid) , c->keytext);
+            gtk_container_remove( GTK_CONTAINER(c->grid) , c->button);
+
+            gtk_table_attach_defaults (GTK_TABLE (c->grid), c->combobox, 0, 1, row, row + 1);
+            gtk_table_attach_defaults (GTK_TABLE (c->grid), c->keytext, 1, 2, row, row + 1);
+            gtk_table_attach_defaults (GTK_TABLE (c->grid), c->button, 2, 3, row, row + 1);
+
+            g_object_unref(c->combobox);
+            g_object_unref(c->keytext);
+            g_object_unref(c->button);
+
+            c = c->next;
+            row++;
+        }
+        if (grid)
+            gtk_widget_show_all (GTK_WIDGET (grid));
+
+        return;
+    }
+}
+
+void add_callback (GtkWidget *widget, void * data)
+{
+    KeyControls* controls = (KeyControls*)data;
+    HotkeyConfiguration temphotkey;
+    int count;
+    if (controls == nullptr) return;
+    if ((controls->next == nullptr)&&(controls->hotkey.event+1 == EVENT_MAX)) return;
+    controls = controls->first;
+    if (controls == nullptr) return;
+    count = 1;
+    while (controls->next) {
+        controls = controls->next;
+        count = count + 1;
+    }
+    temphotkey.key = 0;
+    temphotkey.mask = 0;
+    temphotkey.type = TYPE_KEY;
+    temphotkey.event = (EVENT) (controls->hotkey.event + 1);
+    if (temphotkey.event >= EVENT_MAX)
+        temphotkey.event = (EVENT) 0;
+    add_event_controls(controls, controls->grid, count, &temphotkey);
+    gtk_widget_show_all (GTK_WIDGET (controls->grid));
+}
+
+void destroy_callback ()
+{
+    KeyControls* controls = first_controls;
+
+    grab_keys ();
+
+    while (controls) {
+        KeyControls *old;
+        old = controls;
+        controls = controls->next;
+        g_free(old);
+    }
+
+    first_controls = nullptr;
+}
+
+void ok_callback ()
+{
+    KeyControls *controls = first_controls;
+    PluginConfig* plugin_cfg = get_config();
+    HotkeyConfiguration *hotkey;
+
+    hotkey = &(plugin_cfg->first);
+    hotkey = hotkey->next;
+    while (hotkey)
+    {
+        HotkeyConfiguration * old;
+        old = hotkey;
+        hotkey = hotkey->next;
+        g_free(old);
+    }
+    plugin_cfg->first.next = nullptr;
+    plugin_cfg->first.key = 0;
+    plugin_cfg->first.event = (EVENT) 0;
+    plugin_cfg->first.mask = 0;
+
+    hotkey = &(plugin_cfg->first);
+    while (controls)
+    {
+        if (controls->hotkey.key) {
+            if (hotkey->key) {
+                hotkey->next = g_new(HotkeyConfiguration, 1);
+                hotkey = hotkey->next;
+                hotkey->next = nullptr;
+            }
+            hotkey->key = controls->hotkey.key;
+            hotkey->mask = controls->hotkey.mask;
+            hotkey->event = (EVENT) gtk_combo_box_get_active( GTK_COMBO_BOX(controls->combobox) );
+            hotkey->type = controls->hotkey.type;
+        }
+        controls = controls->next;
+    }
+
+    save_config ( );
+}
+
+
+static const PreferencesWidget hotkey_widgets[] = {
+    WidgetCustomGTK (make_config_widget)
+};
+
+const PluginPreferences hotkey_prefs = {
+    {hotkey_widgets},
+    nullptr,  // init
+    ok_callback,
+    destroy_callback
+};
diff --git a/src/hotkey/gui.h b/src/hotkey/gui.h
index db40c381311e..78e6562d8b1a 100644
--- a/src/hotkey/gui.h
+++ b/src/hotkey/gui.h
@@ -1,6 +1,8 @@
 #ifndef _GUI_H_INCLUDED_
 #define _GUI_H_INCLUDED_
 
-void show_configure (void);
+struct PluginPreferences;
+
+extern const PluginPreferences hotkey_prefs;
 
 #endif
diff --git a/src/hotkey/plugin.c b/src/hotkey/plugin.c
deleted file mode 100644
index 09b02523ae16..000000000000
--- a/src/hotkey/plugin.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- *  This file is part of audacious-hotkey plugin for audacious
- *
- *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
- *  Name: plugin.c
- *  Description: plugin.c
- *
- *  Part of this code is from itouch-ctrl plugin.
- *  Authors of itouch-ctrl are listed below:
- *
- *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
- *
- *  Part of this code are from xmms-itouch plugin.
- *  Authors of xmms-itouch are listed below:
- *
- *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
- *                         Bryn Davies <curious at ihug.com.au>
- *                         Jonathan A. Davis <davis at jdhouse.org>
- *                         Jeremy Tan <nsx at nsx.homeip.net>
- *
- *  audacious-hotkey 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.
- *
- *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <X11/XF86keysym.h>
-
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-
-#include "plugin.h"
-#include "gui.h"
-#include "grab.h"
-
-
-/* func defs */
-static gboolean init (void);
-static void cleanup (void);
-
-
-/* global vars */
-static PluginConfig plugin_cfg;
-static gboolean loaded = FALSE;
-
-static const char about[] =
- N_("Global Hotkey Plugin\n"
-    "Control the player with global key combinations or multimedia keys.\n\n"
-    "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n\n"
-    "Contributers include:\n"
-    "Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
-    "Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
-    " Bryn Davies <curious at ihug.com.au>,\n"
-    " Jonathan A. Davis <davis at jdhouse.org>,\n"
-    " Jeremy Tan <nsx at nsx.homeip.net>");
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Global Hotkeys"),
-    .domain = PACKAGE,
-    .about_text = about,
-    .init = init,
-    .configure = show_configure,
-    .cleanup = cleanup
-)
-
-PluginConfig* get_config(void)
-{
-    return &plugin_cfg;
-}
-
-
-/*
- * plugin activated
- */
-static gboolean init (void)
-{
-    if (! gtk_init_check (NULL, NULL))
-    {
-        fprintf (stderr, "hotkey: GTK+ initialization failed.\n");
-        return FALSE;
-    }
-
-    setup_filter();
-    load_config ( );
-    grab_keys ( );
-
-    loaded = TRUE;
-    return TRUE;
-}
-
-/* handle keys */
-gboolean handle_keyevent (EVENT event)
-{
-    gint current_volume, old_volume;
-    static gint volume_static = 0;
-    gboolean mute;
-
-    /* get current volume */
-    aud_drct_get_volume_main (&current_volume);
-    old_volume = current_volume;
-    if (current_volume)
-    {
-        /* volume is not mute */
-        mute = FALSE;
-    } else {
-        /* volume is mute */
-        mute = TRUE;
-    }
-
-    /* mute the playback */
-    if (event == EVENT_MUTE)
-    {
-        if (!mute)
-        {
-            volume_static = current_volume;
-            aud_drct_set_volume_main (0);
-            mute = TRUE;
-        } else {
-            aud_drct_set_volume_main (volume_static);
-            mute = FALSE;
-        }
-        return TRUE;
-    }
-
-    /* decreace volume */
-    if (event == EVENT_VOL_DOWN)
-    {
-        if (mute)
-        {
-            current_volume = old_volume;
-            old_volume = 0;
-            mute = FALSE;
-        }
-
-        if ((current_volume -= plugin_cfg.vol_decrement) < 0)
-        {
-            current_volume = 0;
-        }
-
-        if (current_volume != old_volume)
-        {
-            aud_drct_set_volume_main (current_volume);
-        }
-
-        old_volume = current_volume;
-        return TRUE;
-    }
-
-    /* increase volume */
-    if (event == EVENT_VOL_UP)
-    {
-        if (mute)
-        {
-            current_volume = old_volume;
-            old_volume = 0;
-            mute = FALSE;
-        }
-
-        if ((current_volume += plugin_cfg.vol_increment) > 100)
-        {
-            current_volume = 100;
-        }
-
-        if (current_volume != old_volume)
-        {
-            aud_drct_set_volume_main (current_volume);
-        }
-
-        old_volume = current_volume;
-        return TRUE;
-    }
-
-    /* play */
-    if (event == EVENT_PLAY)
-    {
-        aud_drct_play ();
-        return TRUE;
-    }
-
-    /* pause */
-    if (event == EVENT_PAUSE)
-    {
-        aud_drct_play_pause ();
-        return TRUE;
-    }
-
-    /* stop */
-    if (event == EVENT_STOP)
-    {
-        aud_drct_stop ();
-        return TRUE;
-    }
-
-    /* prev track */
-    if (event == EVENT_PREV_TRACK)
-    {
-        aud_drct_pl_prev ();
-        return TRUE;
-    }
-
-    /* next track */
-    if (event == EVENT_NEXT_TRACK)
-    {
-        aud_drct_pl_next ();
-        return TRUE;
-    }
-
-    /* forward */
-    if (event == EVENT_FORWARD)
-    {
-        aud_drct_seek (aud_drct_get_time () + 5000);
-        return TRUE;
-    }
-
-    /* backward */
-    if (event == EVENT_BACKWARD)
-    {
-        gint time = aud_drct_get_time ();
-        if (time > 5000) time -= 5000; /* Jump 5s back */
-            else time = 0;
-        aud_drct_seek (time);
-        return TRUE;
-    }
-
-    /* Open Jump-To-File dialog */
-    if (event == EVENT_JUMP_TO_FILE && ! aud_headless_mode ())
-    {
-        audgui_jump_to_track ();
-        return TRUE;
-    }
-
-    /* Toggle Windows */
-    if (event == EVENT_TOGGLE_WIN && ! aud_headless_mode ())
-    {
-        aud_interface_show (! aud_interface_is_shown ());
-        return TRUE;
-    }
-
-    /* Show OSD through AOSD plugin*/
-    if (event == EVENT_SHOW_AOSD)
-    {
-        hook_call("aosd toggle", NULL);
-        return TRUE;
-    }
-
-    if (event == EVENT_TOGGLE_REPEAT)
-    {
-        aud_set_bool (NULL, "repeat", ! aud_get_bool (NULL, "repeat"));
-        return TRUE;
-    }
-
-    if (event == EVENT_TOGGLE_SHUFFLE)
-    {
-        aud_set_bool (NULL, "shuffle", ! aud_get_bool (NULL, "shuffle"));
-        return TRUE;
-    }
-
-    if (event == EVENT_TOGGLE_STOP)
-    {
-        aud_set_bool (NULL, "stop_after_current_song", ! aud_get_bool (NULL, "stop_after_current_song"));
-        return TRUE;
-    }
-
-    if (event == EVENT_RAISE)
-    {
-        aud_interface_show (TRUE);
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-void add_hotkey(HotkeyConfiguration** pphotkey, KeySym keysym, gint mask, gint type, EVENT event)
-{
-    KeyCode keycode;
-    HotkeyConfiguration *photkey;
-    if (keysym == 0) return;
-    if (pphotkey == NULL) return;
-    photkey = *pphotkey;
-    if (photkey == NULL) return;
-    keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym);
-    if (keycode == 0) return;
-    if (photkey->key) {
-        photkey->next = g_new(HotkeyConfiguration, 1);
-        photkey = photkey->next;
-        *pphotkey = photkey;
-        photkey->next = NULL;
-    }
-    photkey->key = (gint)keycode;
-    photkey->mask = mask;
-    photkey->event = event;
-    photkey->type = type;
-}
-
-void load_defaults (void)
-{
-    HotkeyConfiguration* hotkey;
-
-    hotkey = &(plugin_cfg.first);
-
-    add_hotkey(&hotkey, XF86XK_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK);
-    add_hotkey(&hotkey, XF86XK_AudioPlay, 0, TYPE_KEY, EVENT_PLAY);
-    add_hotkey(&hotkey, XF86XK_AudioPause, 0, TYPE_KEY, EVENT_PAUSE);
-    add_hotkey(&hotkey, XF86XK_AudioStop, 0, TYPE_KEY, EVENT_STOP);
-    add_hotkey(&hotkey, XF86XK_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK);
-
-/*    add_hotkey(&hotkey, XF86XK_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); */
-
-    add_hotkey(&hotkey, XF86XK_AudioMute, 0, TYPE_KEY, EVENT_MUTE);
-    add_hotkey(&hotkey, XF86XK_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP);
-    add_hotkey(&hotkey, XF86XK_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN);
-
-/*    add_hotkey(&hotkey, XF86XK_AudioMedia, 0, TYPE_KEY, EVENT_JUMP_TO_FILE);
-    add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, EVENT_TOGGLE_WIN); */
-}
-
-/* load plugin configuration */
-void load_config (void)
-{
-    HotkeyConfiguration *hotkey;
-    int i,max;
-
-    /* default volume level */
-    plugin_cfg.vol_increment = 4;
-    plugin_cfg.vol_decrement = 4;
-
-    hotkey = &(plugin_cfg.first);
-    hotkey->next = NULL;
-    hotkey->key = 0;
-    hotkey->mask = 0;
-    hotkey->event = 0;
-    hotkey->type = TYPE_KEY;
-
-    max = aud_get_int ("globalHotkey", "NumHotkeys");
-    if (max == 0)
-        load_defaults();
-    else for (i=0; i<max; i++)
-    {
-        gchar *text = NULL;
-
-        if (hotkey->key) {
-            hotkey->next = g_new(HotkeyConfiguration, 1);
-            hotkey = hotkey->next;
-            hotkey->next = NULL;
-            hotkey->key = 0;
-            hotkey->mask = 0;
-            hotkey->event = 0;
-            hotkey->type = TYPE_KEY;
-        }
-        text = g_strdup_printf("Hotkey_%d_key", i);
-        hotkey->key = aud_get_int ("globalHotkey", text);
-        g_free(text);
-
-        text = g_strdup_printf("Hotkey_%d_mask", i);
-        hotkey->mask = aud_get_int ("globalHotkey", text);
-        g_free(text);
-
-        text = g_strdup_printf("Hotkey_%d_type", i);
-        hotkey->type = aud_get_int ("globalHotkey", text);
-        g_free(text);
-
-        text = g_strdup_printf("Hotkey_%d_event", i);
-        hotkey->event = aud_get_int ("globalHotkey", text);
-        g_free(text);
-    }
-}
-
-/* save plugin configuration */
-void save_config (void)
-{
-    int max;
-    HotkeyConfiguration *hotkey;
-
-    hotkey = &(plugin_cfg.first);
-    max = 0;
-    while (hotkey) {
-        gchar *text = NULL;
-        if (hotkey->key) {
-            text = g_strdup_printf("Hotkey_%d_key", max);
-            aud_set_int ("globalHotkey", text, hotkey->key);
-            g_free(text);
-
-            text = g_strdup_printf("Hotkey_%d_mask", max);
-            aud_set_int ("globalHotkey", text, hotkey->mask);
-            g_free(text);
-
-            text = g_strdup_printf("Hotkey_%d_type", max);
-            aud_set_int ("globalHotkey", text, hotkey->type);
-            g_free(text);
-
-            text = g_strdup_printf("Hotkey_%d_event", max);
-            aud_set_int ("globalHotkey", text, hotkey->event);
-            g_free(text);
-            max++;
-        }
-
-        hotkey = hotkey->next;
-    }
-
-    aud_set_int ("globalHotkey", "NumHotkeys", max);
-}
-
-static void cleanup (void)
-{
-    HotkeyConfiguration* hotkey;
-    if (!loaded) return;
-    ungrab_keys ();
-    release_filter();
-    hotkey = &(plugin_cfg.first);
-    hotkey = hotkey->next;
-    while (hotkey)
-    {
-        HotkeyConfiguration * old;
-        old = hotkey;
-        hotkey = hotkey->next;
-        g_free(old);
-    }
-    plugin_cfg.first.next = NULL;
-    plugin_cfg.first.key = 0;
-    plugin_cfg.first.event = 0;
-    plugin_cfg.first.mask = 0;
-    loaded = FALSE;
-}
-
-gboolean is_loaded (void)
-{
-    return loaded;
-}
diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc
new file mode 100644
index 000000000000..7c2cc230031a
--- /dev/null
+++ b/src/hotkey/plugin.cc
@@ -0,0 +1,446 @@
+/*
+ *  This file is part of audacious-hotkey plugin for audacious
+ *
+ *  Copyright (c) 2007 - 2008  Sascha Hlusiak <contact at saschahlusiak.de>
+ *  Name: plugin.c
+ *  Description: plugin.c
+ *
+ *  Part of this code is from itouch-ctrl plugin.
+ *  Authors of itouch-ctrl are listed below:
+ *
+ *  Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov at gmail.com>
+ *
+ *  Part of this code are from xmms-itouch plugin.
+ *  Authors of xmms-itouch are listed below:
+ *
+ *  Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>
+ *                         Bryn Davies <curious at ihug.com.au>
+ *                         Jonathan A. Davis <davis at jdhouse.org>
+ *                         Jeremy Tan <nsx at nsx.homeip.net>
+ *
+ *  audacious-hotkey 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.
+ *
+ *  audacious-hotkey is distributed in the hope that 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-hotkey; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+
+#include <X11/XF86keysym.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include "plugin.h"
+#include "gui.h"
+#include "grab.h"
+
+class GlobalHotkeys : public GeneralPlugin
+{
+public:
+    static const char about[];
+
+    static constexpr PluginInfo info = {
+        N_("Global Hotkeys"),
+        PACKAGE,
+        about,
+        & hotkey_prefs
+    };
+
+    constexpr GlobalHotkeys () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT GlobalHotkeys aud_plugin_instance;
+
+/* global vars */
+static PluginConfig plugin_cfg;
+
+const char GlobalHotkeys::about[] =
+ N_("Global Hotkey Plugin\n"
+    "Control the player with global key combinations or multimedia keys.\n\n"
+    "Copyright (C) 2007-2008 Sascha Hlusiak <contact at saschahlusiak.de>\n\n"
+    "Contributers include:\n"
+    "Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov at gmail.com>\n"
+    "Copyright (C) 2000-2002 Ville Syrjälä <syrjala at sci.fi>,\n"
+    " Bryn Davies <curious at ihug.com.au>,\n"
+    " Jonathan A. Davis <davis at jdhouse.org>,\n"
+    " Jeremy Tan <nsx at nsx.homeip.net>");
+
+PluginConfig* get_config(void)
+{
+    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");
+        return false;
+    }
+
+    setup_filter();
+    load_config ( );
+    grab_keys ( );
+
+    return true;
+}
+
+/* handle keys */
+gboolean handle_keyevent (EVENT event)
+{
+    int current_volume, old_volume;
+    static int volume_static = 0;
+    gboolean mute;
+
+    /* get current volume */
+    current_volume = aud_drct_get_volume_main ();
+    old_volume = current_volume;
+    if (current_volume)
+    {
+        /* volume is not mute */
+        mute = FALSE;
+    } else {
+        /* volume is mute */
+        mute = TRUE;
+    }
+
+    /* mute the playback */
+    if (event == EVENT_MUTE)
+    {
+        if (!mute)
+        {
+            volume_static = current_volume;
+            aud_drct_set_volume_main (0);
+            mute = TRUE;
+        } else {
+            aud_drct_set_volume_main (volume_static);
+            mute = FALSE;
+        }
+        return TRUE;
+    }
+
+    /* decreace volume */
+    if (event == EVENT_VOL_DOWN)
+    {
+        if (mute)
+        {
+            current_volume = old_volume;
+            old_volume = 0;
+            mute = FALSE;
+        }
+
+        if ((current_volume -= plugin_cfg.vol_decrement) < 0)
+        {
+            current_volume = 0;
+        }
+
+        if (current_volume != old_volume)
+        {
+            aud_drct_set_volume_main (current_volume);
+        }
+
+        old_volume = current_volume;
+        return TRUE;
+    }
+
+    /* increase volume */
+    if (event == EVENT_VOL_UP)
+    {
+        if (mute)
+        {
+            current_volume = old_volume;
+            old_volume = 0;
+            mute = FALSE;
+        }
+
+        if ((current_volume += plugin_cfg.vol_increment) > 100)
+        {
+            current_volume = 100;
+        }
+
+        if (current_volume != old_volume)
+        {
+            aud_drct_set_volume_main (current_volume);
+        }
+
+        old_volume = current_volume;
+        return TRUE;
+    }
+
+    /* play */
+    if (event == EVENT_PLAY)
+    {
+        aud_drct_play ();
+        return TRUE;
+    }
+
+    /* pause */
+    if (event == EVENT_PAUSE)
+    {
+        aud_drct_play_pause ();
+        return TRUE;
+    }
+
+    /* stop */
+    if (event == EVENT_STOP)
+    {
+        aud_drct_stop ();
+        return TRUE;
+    }
+
+    /* prev track */
+    if (event == EVENT_PREV_TRACK)
+    {
+        aud_drct_pl_prev ();
+        return TRUE;
+    }
+
+    /* next track */
+    if (event == EVENT_NEXT_TRACK)
+    {
+        aud_drct_pl_next ();
+        return TRUE;
+    }
+
+    /* forward */
+    if (event == EVENT_FORWARD)
+    {
+        aud_drct_seek (aud_drct_get_time () + 5000);
+        return TRUE;
+    }
+
+    /* backward */
+    if (event == EVENT_BACKWARD)
+    {
+        int time = aud_drct_get_time ();
+        if (time > 5000) time -= 5000; /* Jump 5s back */
+            else time = 0;
+        aud_drct_seek (time);
+        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;
+    }
+
+    /* Toggle Windows */
+    if (event == EVENT_TOGGLE_WIN && ! aud_get_headless_mode ())
+    {
+        aud_ui_show (! aud_ui_is_shown ());
+        return TRUE;
+    }
+
+    /* Show OSD through AOSD plugin*/
+    if (event == EVENT_SHOW_AOSD)
+    {
+        hook_call("aosd toggle", nullptr);
+        return TRUE;
+    }
+
+    if (event == EVENT_TOGGLE_REPEAT)
+    {
+        aud_set_bool (nullptr, "repeat", ! aud_get_bool (nullptr, "repeat"));
+        return TRUE;
+    }
+
+    if (event == EVENT_TOGGLE_SHUFFLE)
+    {
+        aud_set_bool (nullptr, "shuffle", ! aud_get_bool (nullptr, "shuffle"));
+        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;
+    }
+
+    if (event == EVENT_RAISE)
+    {
+        aud_ui_show (TRUE);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+void add_hotkey(HotkeyConfiguration** pphotkey, KeySym keysym, int mask, int type, EVENT event)
+{
+    KeyCode keycode;
+    HotkeyConfiguration *photkey;
+    if (keysym == 0) return;
+    if (pphotkey == nullptr) return;
+    photkey = *pphotkey;
+    if (photkey == nullptr) return;
+    keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym);
+    if (keycode == 0) return;
+    if (photkey->key) {
+        photkey->next = g_new(HotkeyConfiguration, 1);
+        photkey = photkey->next;
+        *pphotkey = photkey;
+        photkey->next = nullptr;
+    }
+    photkey->key = (int)keycode;
+    photkey->mask = mask;
+    photkey->event = event;
+    photkey->type = type;
+}
+
+void load_defaults (void)
+{
+    HotkeyConfiguration* hotkey;
+
+    hotkey = &(plugin_cfg.first);
+
+    add_hotkey(&hotkey, XF86XK_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK);
+    add_hotkey(&hotkey, XF86XK_AudioPlay, 0, TYPE_KEY, EVENT_PLAY);
+    add_hotkey(&hotkey, XF86XK_AudioPause, 0, TYPE_KEY, EVENT_PAUSE);
+    add_hotkey(&hotkey, XF86XK_AudioStop, 0, TYPE_KEY, EVENT_STOP);
+    add_hotkey(&hotkey, XF86XK_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK);
+
+/*    add_hotkey(&hotkey, XF86XK_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); */
+
+    add_hotkey(&hotkey, XF86XK_AudioMute, 0, TYPE_KEY, EVENT_MUTE);
+    add_hotkey(&hotkey, XF86XK_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP);
+    add_hotkey(&hotkey, XF86XK_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN);
+
+/*    add_hotkey(&hotkey, XF86XK_AudioMedia, 0, TYPE_KEY, EVENT_JUMP_TO_FILE);
+    add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, EVENT_TOGGLE_WIN); */
+}
+
+/* load plugin configuration */
+void load_config (void)
+{
+    HotkeyConfiguration *hotkey;
+    int i,max;
+
+    /* default volume level */
+    plugin_cfg.vol_increment = 4;
+    plugin_cfg.vol_decrement = 4;
+
+    hotkey = &(plugin_cfg.first);
+    hotkey->next = nullptr;
+    hotkey->key = 0;
+    hotkey->mask = 0;
+    hotkey->event = (EVENT) 0;
+    hotkey->type = TYPE_KEY;
+
+    max = aud_get_int ("globalHotkey", "NumHotkeys");
+    if (max == 0)
+        load_defaults();
+    else for (i=0; i<max; i++)
+    {
+        char *text = nullptr;
+
+        if (hotkey->key) {
+            hotkey->next = g_new(HotkeyConfiguration, 1);
+            hotkey = hotkey->next;
+            hotkey->next = nullptr;
+            hotkey->key = 0;
+            hotkey->mask = 0;
+            hotkey->event = (EVENT) 0;
+            hotkey->type = TYPE_KEY;
+        }
+        text = g_strdup_printf("Hotkey_%d_key", i);
+        hotkey->key = aud_get_int ("globalHotkey", text);
+        g_free(text);
+
+        text = g_strdup_printf("Hotkey_%d_mask", i);
+        hotkey->mask = aud_get_int ("globalHotkey", text);
+        g_free(text);
+
+        text = g_strdup_printf("Hotkey_%d_type", i);
+        hotkey->type = aud_get_int ("globalHotkey", text);
+        g_free(text);
+
+        text = g_strdup_printf("Hotkey_%d_event", i);
+        hotkey->event = (EVENT) aud_get_int ("globalHotkey", text);
+        g_free(text);
+    }
+}
+
+/* save plugin configuration */
+void save_config (void)
+{
+    int max;
+    HotkeyConfiguration *hotkey;
+
+    hotkey = &(plugin_cfg.first);
+    max = 0;
+    while (hotkey) {
+        char *text = nullptr;
+        if (hotkey->key) {
+            text = g_strdup_printf("Hotkey_%d_key", max);
+            aud_set_int ("globalHotkey", text, hotkey->key);
+            g_free(text);
+
+            text = g_strdup_printf("Hotkey_%d_mask", max);
+            aud_set_int ("globalHotkey", text, hotkey->mask);
+            g_free(text);
+
+            text = g_strdup_printf("Hotkey_%d_type", max);
+            aud_set_int ("globalHotkey", text, hotkey->type);
+            g_free(text);
+
+            text = g_strdup_printf("Hotkey_%d_event", max);
+            aud_set_int ("globalHotkey", text, hotkey->event);
+            g_free(text);
+            max++;
+        }
+
+        hotkey = hotkey->next;
+    }
+
+    aud_set_int ("globalHotkey", "NumHotkeys", max);
+}
+
+void GlobalHotkeys::cleanup ()
+{
+    HotkeyConfiguration* hotkey;
+    ungrab_keys ();
+    release_filter();
+    hotkey = &(plugin_cfg.first);
+    hotkey = hotkey->next;
+    while (hotkey)
+    {
+        HotkeyConfiguration * old;
+        old = hotkey;
+        hotkey = hotkey->next;
+        g_free(old);
+    }
+    plugin_cfg.first.next = nullptr;
+    plugin_cfg.first.key = 0;
+    plugin_cfg.first.event = (EVENT) 0;
+    plugin_cfg.first.mask = 0;
+}
diff --git a/src/hotkey/plugin.h b/src/hotkey/plugin.h
index abebde4b927d..673b9678cd80 100644
--- a/src/hotkey/plugin.h
+++ b/src/hotkey/plugin.h
@@ -33,15 +33,15 @@ typedef enum {
 
 
 typedef struct _HotkeyConfiguration {
-    gint key, mask;
-    gint type;
+    unsigned key, mask;
+    unsigned type;
     EVENT event;
     struct _HotkeyConfiguration *next;
 } HotkeyConfiguration;
 
 typedef struct {
-    gint vol_increment;
-    gint vol_decrement;
+    int vol_increment;
+    int vol_decrement;
 
     /* keyboard */
     HotkeyConfiguration first;
@@ -52,7 +52,6 @@ typedef struct {
 void load_config (void);
 void save_config (void);
 PluginConfig* get_config(void);
-gboolean is_loaded (void);
 gboolean handle_keyevent(EVENT event);
 
 #endif
diff --git a/src/jack-ng/Makefile b/src/jack-ng/Makefile
new file mode 100644
index 000000000000..f2f54913fac9
--- /dev/null
+++ b/src/jack-ng/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = jack-ng${PLUGIN_SUFFIX}
+
+SRCS = jack-ng.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
+
+LD = ${CXX}
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${JACK_CFLAGS} -I../..
+LIBS += ${JACK_LIBS}
diff --git a/src/jack-ng/jack-ng.cc b/src/jack-ng/jack-ng.cc
new file mode 100644
index 000000000000..656447550ca4
--- /dev/null
+++ b/src/jack-ng/jack-ng.cc
@@ -0,0 +1,402 @@
+/*
+ * JACK Output Plugin for Audacious
+ * Copyright 2014 John Lindgren
+ *
+ * Based on the SDL Output Plugin and the previous JACK Output Plugin.
+ *
+ * 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 <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+#include <algorithm>
+
+#include <assert.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#include <jack/jack.h>
+
+static_assert(std::is_same<jack_default_audio_sample_t, float>::value,
+ "JACK must be compiled to use float samples");
+
+class JACKOutput : public OutputPlugin
+{
+public:
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("JACK Output"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr JACKOutput (RingBuf<float> & buffer) :
+        OutputPlugin (info, 0),
+        m_buffer (buffer) {}
+
+    bool init ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int format, int rate, int channels);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+
+private:
+    bool connect_ports (int channels);
+    void generate (jack_nframes_t frames);
+
+    static void error_cb (const char * error)
+        { AUDWARN ("%s\n", error); }
+    static int generate_cb (jack_nframes_t frames, void * obj)
+        { ((JACKOutput *) obj)->generate (frames); return 0; }
+
+    int m_rate = 0, m_channels = 0;
+    bool m_paused = false, m_prebuffer = false;
+
+    int m_last_write_frames = 0;
+    timeval m_last_write_time = timeval ();
+    bool m_rate_mismatch = false;
+
+    RingBuf<float> & m_buffer;
+
+    jack_client_t * m_client = nullptr;
+    jack_port_t * m_ports[AUD_MAX_CHANNELS] = {};
+
+    pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_cond_t m_cond = PTHREAD_COND_INITIALIZER;
+};
+
+// must be separate in order for JACKOutput() to be constexpr
+static RingBuf<float> s_buffer;
+
+EXPORT JACKOutput aud_plugin_instance (s_buffer);
+
+const char * const JACKOutput::defaults[] = {
+    "auto_connect", "TRUE",
+    "volume_left", "100",
+    "volume_right", "100",
+    nullptr
+};
+
+const PreferencesWidget JACKOutput::widgets[] = {
+    WidgetCheck (N_("Automatically connect to output ports"),
+        WidgetBool ("jack", "auto_connect"))
+};
+
+const PluginPreferences JACKOutput::prefs = {{widgets}};
+
+bool JACKOutput::init ()
+{
+    aud_config_set_defaults ("jack", defaults);
+    return true;
+}
+
+void JACKOutput::set_volume (StereoVolume v)
+{
+    aud_set_int ("jack", "volume_left", v.left);
+    aud_set_int ("jack", "volume_right", v.right);
+}
+
+StereoVolume JACKOutput::get_volume ()
+{
+    return {aud_get_int ("jack", "volume_left"), aud_get_int ("jack", "volume_right")};
+}
+
+bool JACKOutput::connect_ports (int channels)
+{
+    bool success = false;
+    const char * * ports = nullptr;
+    int count = 0;
+
+    if (! (ports = jack_get_ports (m_client, nullptr, nullptr,
+     JackPortIsPhysical | JackPortIsInput)))
+    {
+        AUDERR ("jack_get_ports() failed\n");
+        goto fail;
+    }
+
+    while (ports[count])
+        count ++;
+
+    if (count < channels)
+    {
+        aud_ui_show_error (str_printf (_("Only %d JACK output ports were "
+         "found but %d are required."), count, channels));
+        goto fail;
+    }
+
+    for (int i = 0; i < channels; i ++)
+    {
+        if (jack_connect (m_client, jack_port_name (m_ports[i]), ports[i]) != 0)
+        {
+            aud_ui_show_error (str_printf (_("Failed to connect to JACK port %s."), ports[i]));
+            goto fail;
+        }
+    }
+
+    success = true;
+
+fail:
+    if (ports)
+        jack_free (ports);
+
+    return success;
+}
+
+bool JACKOutput::open_audio (int format, int rate, int channels)
+{
+    int buffer_time;
+
+    if (format != FMT_FLOAT)
+    {
+        aud_ui_show_error (_("JACK supports only floating-point audio.  You "
+         "must change the output bit depth to floating-point in Audacious "
+         "settings."));
+        return false;
+    }
+
+    assert (rate > 0 && channels > 0 && channels < AUD_MAX_CHANNELS);
+    assert (! m_client);
+
+    jack_set_error_function (error_cb);
+
+    if (! (m_client = jack_client_open ("audacious", JackNoStartServer, nullptr)))
+    {
+        aud_ui_show_error (_("Failed to connect to the JACK server; is it running?"));
+        goto fail;
+    }
+
+    for (int i = 0; i < channels; i ++)
+    {
+        StringBuf name = str_printf ("out_%d", i);
+        if (! (m_ports[i] = jack_port_register (m_client, name,
+         JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
+        {
+            AUDERR ("jack_port_register() failed\n");
+            goto fail;
+        }
+    }
+
+    buffer_time = aud_get_int (nullptr, "output_buffer_size");
+    m_buffer.alloc (aud::rescale (buffer_time, 1000, rate) * channels);
+
+    m_rate = rate;
+    m_channels = channels;
+    m_paused = false;
+    m_prebuffer = true;
+
+    m_last_write_frames = 0;
+    m_last_write_time = timeval ();
+    m_rate_mismatch = false;
+
+    jack_set_process_callback (m_client, generate_cb, this);
+
+    if (jack_activate (m_client) != 0)
+    {
+        AUDERR ("jack_activate() failed\n");
+        goto fail;
+    }
+
+    if (aud_get_bool ("jack", "auto_connect"))
+    {
+        if (! connect_ports (channels))
+            goto fail;
+    }
+
+    return true;
+
+fail:
+    close_audio ();
+    return false;
+}
+
+void JACKOutput::close_audio ()
+{
+    if (m_client)
+        jack_client_close (m_client);
+
+    m_buffer.destroy ();
+
+    std::fill (m_ports, std::end (m_ports), nullptr);
+    m_client = nullptr;
+}
+
+void JACKOutput::generate (jack_nframes_t frames)
+{
+    pthread_mutex_lock (& m_mutex);
+
+    m_last_write_frames = 0;
+    gettimeofday (& m_last_write_time, nullptr);
+
+    float * out[AUD_MAX_CHANNELS];
+    for (int i = 0; i < m_channels; i ++)
+        out[i] = (float *) jack_port_get_buffer (m_ports[i], frames);
+
+    int jack_rate = jack_get_sample_rate (m_client);
+
+    if (jack_rate != m_rate)
+    {
+        if (! m_rate_mismatch)
+        {
+            aud_ui_show_error (str_printf (_("The JACK server requires a "
+             "sample rate of %d Hz, but Audacious is playing at %d Hz.  Please "
+             "use the Sample Rate Converter effect to correct the mismatch."),
+             jack_rate, m_rate));
+            m_rate_mismatch = true;
+        }
+
+        goto silence;
+    }
+
+    m_rate_mismatch = false;
+
+    if (m_paused || m_prebuffer)
+        goto silence;
+
+    while (frames && m_buffer.len ())
+    {
+        int linear_samples = m_buffer.linear ();
+        assert (linear_samples % m_channels == 0);
+
+        int frames_to_copy = aud::min (frames, (jack_nframes_t) linear_samples / m_channels);
+
+        audio_amplify (& m_buffer[0], m_channels, frames_to_copy, get_volume ());
+        audio_deinterlace (& m_buffer[0], FMT_FLOAT, m_channels,
+         (void * const *) out, frames_to_copy);
+
+        m_last_write_frames += frames_to_copy;
+        m_buffer.discard (frames_to_copy * m_channels);
+
+        for (int i = 0; i < m_channels; i ++)
+            out[i] += frames_to_copy;
+
+        frames -= frames_to_copy;
+    }
+
+silence:
+    for (int i = 0; i < m_channels; i ++)
+        std::fill (out[i], out[i] + frames, 0.0);
+
+    pthread_cond_broadcast (& m_cond);
+    pthread_mutex_unlock (& m_mutex);
+}
+
+void JACKOutput::period_wait ()
+{
+    pthread_mutex_lock (& m_mutex);
+
+    while (! m_buffer.space ())
+    {
+        m_prebuffer = false;
+        pthread_cond_wait (& m_cond, & m_mutex);
+    }
+
+    pthread_mutex_unlock (& m_mutex);
+}
+
+int JACKOutput::write_audio (const void * data, int size)
+{
+    pthread_mutex_lock (& m_mutex);
+
+    int samples = size / sizeof (float);
+    assert (samples % m_channels == 0);
+
+    samples = aud::min (samples, m_buffer.space ());
+
+    m_buffer.copy_in ((const float *) data, samples);
+
+    if (m_buffer.len () >= m_buffer.size () / 4)
+        m_prebuffer = false;
+
+    pthread_mutex_unlock (& m_mutex);
+    return samples * sizeof (float);
+}
+
+void JACKOutput::drain ()
+{
+    pthread_mutex_lock (& m_mutex);
+
+    m_prebuffer = false;
+
+    while (m_buffer.len () || m_last_write_frames)
+        pthread_cond_wait (& m_cond, & m_mutex);
+
+    pthread_mutex_unlock (& m_mutex);
+}
+
+int JACKOutput::get_delay ()
+{
+    auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
+        { return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
+
+    pthread_mutex_lock (& m_mutex);
+
+    int delay = aud::rescale (m_buffer.len (), m_channels * m_rate, 1000);
+
+    if (m_last_write_frames)
+    {
+        timeval now;
+        gettimeofday (& now, nullptr);
+
+        int written = aud::rescale (m_last_write_frames, m_rate, 1000);
+        delay += aud::max (written - timediff (m_last_write_time, now), (int64_t) 0);
+    }
+
+    pthread_mutex_unlock (& m_mutex);
+    return delay;
+}
+
+void JACKOutput::pause (bool pause)
+{
+    pthread_mutex_lock (& m_mutex);
+    m_paused = pause;
+    pthread_cond_broadcast (& m_cond);
+    pthread_mutex_unlock (& m_mutex);
+}
+
+void JACKOutput::flush ()
+{
+    pthread_mutex_lock (& m_mutex);
+
+    m_buffer.discard ();
+
+    m_prebuffer = true;
+
+    m_last_write_frames = 0;
+    m_last_write_time = timeval ();
+
+    pthread_cond_broadcast (& m_cond);
+    pthread_mutex_unlock (& m_mutex);
+}
diff --git a/src/jack/Makefile b/src/jack/Makefile
deleted file mode 100644
index 2f313bfb63e8..000000000000
--- a/src/jack/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-PLUGIN = jackout${PLUGIN_SUFFIX}
-
-SRCS = jack.c		\
-       bio2jack.c
-
-include ../../buildsys.mk
-include ../../extra.mk
-
-plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
-
-CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${JACK_LIBS} -lsamplerate -lm
diff --git a/src/jack/bio2jack.c b/src/jack/bio2jack.c
deleted file mode 100644
index f00b0a6e3698..000000000000
--- a/src/jack/bio2jack.c
+++ /dev/null
@@ -1,2652 +0,0 @@
-/*
- * Copyright 2003-2006 Chris Morgan <cmorgan at alum.wpi.edu>
- *
- * 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
- */
-
-/* NOTE: All functions that take a jack_driver_t* do NOT lock the device, in order to get a */
-/*       jack_driver_t* you must call getDriver() which will pthread_mutex_lock() */
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <math.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <jack/jack.h>
-#include <jack/ringbuffer.h>
-#include <pthread.h>
-#include <sys/time.h>
-#include <samplerate.h>
-
-#include <glib.h>
-
-#include "bio2jack.h"
-
-/* enable/disable TRACING through the JACK_Callback() function */
-/* this can sometimes be too much information */
-#define TRACE_CALLBACK          0
-
-/* set to 1 for verbose output */
-#define VERBOSE_OUTPUT          0
-
-/* set to 1 to enable debug messages */
-#define DEBUG_OUTPUT            0
-
-/* set to 1 to enable tracing */
-#define TRACE_ENABLE            0
-
-/* set to 1 to enable the function timers */
-#define TIMER_ENABLE            0
-
-/* set to 1 to enable tracing of getDriver() and releaseDriver() */
-#define TRACE_getReleaseDevice  0
-
-#define ENABLE_WARNINGS         0
-
-#define DEFAULT_RB_SIZE         4096
-
-#define OUTFILE stderr
-
-#if TIMER_ENABLE
-/* This seemingly construct makes timing arbitrary functions really easy
-   all you have to do is place a 'TIMER("start\n")' at the beginning and
-   a 'TIMER("stop\n")' at the end of any function and this does the rest
-   (naturally you can place any printf-compliant text you like in the argument
-   along with the associated values). */
-static struct timeval timer_now;
-#define TIMER(format,args...) gettimeofday(&timer_now,0); \
-  fprintf(OUTFILE, "%ld.%06ld: %s::%s(%d) "format, timer_now.tv_sec, timer_now.tv_usec, __FILE__, __FUNCTION__, __LINE__, ##args)
-#else
-#define TIMER(...)
-#endif
-
-#if TRACE_ENABLE
-#define TRACE(format,args...) fprintf(OUTFILE, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args)
-#else
-#define TRACE(...)
-#endif
-
-#if DEBUG_OUTPUT
-#define DEBUG(format,args...) fprintf(OUTFILE, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args)
-#else
-#define DEBUG(...)
-#endif
-
-#if TRACE_CALLBACK
-#define CALLBACK_TRACE(format,args...) fprintf(OUTFILE, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args)
-#else
-#define CALLBACK_TRACE(...)
-#endif
-
-#if ENABLE_WARNINGS
-#define WARN(format,args...) fprintf(OUTFILE, "WARN: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args)
-#else
-#define WARN(...)
-#endif
-
-#define ERR(format,args...) fprintf(OUTFILE, "ERR: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args)
-
-#define min(a,b)   (((a) < (b)) ? (a) : (b))
-#define max(a,b)   (((a) < (b)) ? (b) : (a))
-
-#define MAX_OUTPUT_PORTS  10
-#define MAX_INPUT_PORTS   10
-
-#define SAMPLE_FMT_INTEGER 0 /* Regular integer samples */
-#define SAMPLE_FMT_PACKED_24B 1 /* 24 bit samples packed to 32 bit values */
-#define SAMPLE_FMT_FLOAT 2 /* 32 bit floating point samples */
-
-typedef struct jack_driver_s
-{
-  bool allocated;                       /* whether or not this device has been allocated */
-
-  int deviceID;                         /* id of this device */
-  int clientCtr;                        /* to prevent overlapping client ids */
-  long jack_sample_rate;                /* jack samples(frames) per second */
-
-  long client_sample_rate;              /* client samples(frames) per second */
-  double output_sample_rate_ratio;      /* ratio between jack's output rate & ours */
-  double input_sample_rate_ratio;       /* ratio between our input rate & jack's */
-
-  unsigned long num_input_channels;     /* number of input channels(1 is mono, 2 stereo etc..) */
-  unsigned long num_output_channels;    /* number of output channels(1 is mono, 2 stereo etc..) */
-
-  unsigned long bits_per_channel;       /* number of bits per channel (8, 16, 24 or 32 supported) */
-  int sample_format;                    /* special sample format or SAMPLE_FMT_INTEGER for signed native-endian integers using all bits_per_channel bit  */
-
-  unsigned long bytes_per_output_frame; /* (num_output_channels * bits_per_channel) / 8 */
-  unsigned long bytes_per_input_frame;  /* (num_input_channels * bits_per_channel) / 8 */
-
-  unsigned long bytes_per_jack_output_frame;    /* (num_output_channels * bits_per_channel) / 8 */
-  unsigned long bytes_per_jack_input_frame;     /* (num_input_channels * bits_per_channel) / 8 */
-
-  long clientBytesInJack;       /* number of INPUT bytes(from the client of bio2jack) we wrote to jack(not necessary the number of bytes we wrote to jack) */
-  long jack_buffer_size;        /* size of the buffer jack will pass in to the process callback */
-
-  unsigned long callback_buffer1_size;  /* number of bytes in the buffer allocated for processing data in JACK_Callback */
-  char *callback_buffer1;
-  unsigned long callback_buffer2_size;  /* number of bytes in the buffer allocated for processing data in JACK_Callback */
-  char *callback_buffer2;
-
-  unsigned long rw_buffer1_size;        /* number of bytes in the buffer allocated for processing data in JACK_(Read|Write) */
-  char *rw_buffer1;
-
-  struct timeval previousTime;  /* time of last JACK_Callback() write to jack, allows for MS accurate bytes played  */
-
-  unsigned long written_client_bytes;   /* input bytes we wrote to jack, not necessarily actual bytes we wrote to jack due to channel and other conversion */
-  unsigned long played_client_bytes;    /* input bytes that jack has played */
-
-  unsigned long client_bytes;   /* total bytes written by the client of bio2jack via JACK_Write() */
-
-  jack_port_t *output_port[MAX_OUTPUT_PORTS];   /* output ports */
-  jack_port_t *input_port[MAX_OUTPUT_PORTS];    /* input ports */
-
-  jack_client_t *client;        /* pointer to jack client */
-
-  char **jack_port_name;        /* user given strings for the port names, can be NULL */
-  unsigned int jack_port_name_count;    /* the number of port names given */
-
-  unsigned long jack_output_port_flags; /* flags to be passed to jack when opening the output ports */
-  unsigned long jack_input_port_flags;  /* flags to be passed to jack when opening the output ports */
-
-  jack_ringbuffer_t *pPlayPtr;  /* the playback ringbuffer */
-  jack_ringbuffer_t *pRecPtr;   /* the recording ringbuffer */
-
-  SRC_STATE *output_src;        /* SRC object for the output stream */
-  SRC_STATE *input_src;         /* SRC object for the output stream */
-
-  enum status_enum state;       /* one of PLAYING, PAUSED, STOPPED, CLOSED, RESET etc */
-
-  unsigned int volume[MAX_OUTPUT_PORTS];        /* percentage of sample value to preserve, 100 would be no attenuation */
-  enum JACK_VOLUME_TYPE volumeEffectType;       /* linear or dbAttenuation, if dbAttenuation volume is the number of dBs of
-                                                   attenuation to apply, 0 volume being no attenuation, full volume */
-
-  long position_byte_offset;    /* an offset that we will apply to returned position queries to achieve */
-                                /* the position that the user of the driver desires set */
-
-  bool in_use;                  /* true if this device is currently in use */
-
-  pthread_mutex_t mutex;        /* mutex to lock this specific device */
-
-  /* variables used for trying to restart the connection to jack */
-  bool jackd_died;              /* true if jackd has died and we should try to restart it */
-  struct timeval last_reconnect_attempt;
-} jack_driver_t;
-
-
-static char *client_name;       /* the name bio2jack will use when creating a new
-                                   jack client. client_name_%deviceID% will be used */
-
-
-static bool do_sample_rate_conversion;  /* whether the client has requested sample rate conversion,
-                                           default to on for improved compatibility */
-
-/*
-  Which SRC converter function we should use when doing sample rate conversion.
-  Default to the fastest of the 'good quality' set.
- */
-static int preferred_src_converter = SRC_SINC_FASTEST;
-
-static bool init_done = 0;      /* just to prevent clients from calling JACK_Init twice, that would be very bad */
-
-static enum JACK_PORT_CONNECTION_MODE port_connection_mode = CONNECT_ALL;
-
-/* enable/disable code that allows us to close a device without actually closing the jack device */
-/* this works around the issue where jack doesn't always close devices by the time the close function call returns */
-#define JACK_CLOSE_HACK 1
-
-typedef jack_default_audio_sample_t sample_t;
-typedef jack_nframes_t nframes_t;
-
-/* allocate devices for output */
-/* if you increase this past 10, you might want to update 'out_client_name = ... ' in JACK_OpenDevice */
-#define MAX_OUTDEVICES 10
-static jack_driver_t outDev[MAX_OUTDEVICES];
-
-static pthread_mutex_t device_mutex = PTHREAD_MUTEX_INITIALIZER;        /* this is to lock the entire outDev array
-                                                                           to make managing it in a threaded
-                                                                           environment sane */
-
-#if JACK_CLOSE_HACK
-static void JACK_CloseDevice(jack_driver_t * drv, bool close_client);
-#else
-static void JACK_CloseDevice(jack_driver_t * drv);
-#endif
-
-
-/* Prototypes */
-static int JACK_OpenDevice(jack_driver_t * drv);
-static unsigned long JACK_GetBytesFreeSpaceFromDriver(jack_driver_t * drv);
-static void JACK_ResetFromDriver(jack_driver_t * drv);
-static long JACK_GetPositionFromDriver(jack_driver_t * drv,
-                                       enum pos_enum position, int type);
-static void JACK_CleanupDriver(jack_driver_t * drv);
-
-
-/* Return the difference between two timeval structures in terms of milliseconds */
-long
-TimeValDifference(struct timeval *start, struct timeval *end)
-{
-  double long ms;               /* milliseconds value */
-
-  ms = end->tv_sec - start->tv_sec;     /* compute seconds difference */
-  ms *= (double) 1000;          /* convert to milliseconds */
-
-  ms += (double) (end->tv_usec - start->tv_usec) / (double) 1000;       /* add on microseconds difference */
-
-  return (long) ms;
-}
-
-/* get a device and lock the devices mutex */
-/* */
-/* also attempt to reconnect to jack since this function is called from */
-/* most other bio2jack functions it provides a good point to attempt reconnection */
-/* */
-/* Ok, I know this looks complicated and it kind of is. The point is that when you're
-   trying to trace mutexes it's more important to know *who* called us than just that
-   we were called.  This uses from pre-processor trickery so that the fprintf is actually
-   placed in the function making the getDriver call.  Thus, the __FUNCTION__ and __LINE__
-   macros will actually reference our caller, rather than getDriver.  The reason the
-   fprintf call is passes as a parameter is because this macro has to still return a
-   jack_driver_t* and we want to log both before *and* after the getDriver call for
-   easier detection of blocked calls.
- */
-#if TRACE_getReleaseDevice
-#define getDriver(x) _getDriver(x,fprintf(OUTFILE, "%s::%s(%d) getting driver %d\n", __FILE__, __FUNCTION__, __LINE__,x)); TRACE("got driver %d\n",x);
-jack_driver_t *
-_getDriver(int deviceID, int ignored)
-{
-  fflush(OUTFILE);
-#else
-jack_driver_t *
-getDriver(int deviceID)
-{
-#endif
-  jack_driver_t *drv = &outDev[deviceID];
-
-  pthread_mutex_lock(&drv->mutex);
-
-  /* should we try to restart the jack server? */
-  if(drv->jackd_died && drv->client == 0)
-  {
-    struct timeval now;
-    gettimeofday(&now, 0);
-
-    /* wait 250ms before trying again */
-    if(TimeValDifference(&drv->last_reconnect_attempt, &now) >= 250)
-    {
-      JACK_OpenDevice(drv);
-      drv->last_reconnect_attempt = now;
-    }
-  }
-
-  return drv;
-}
-
-#if TRACE_getReleaseDevice
-#define tryGetDriver(x) _tryGetDriver(x,fprintf(OUTFILE, "%s::%s(%d) trying to get driver %d\n", __FILE__, __FUNCTION__, __LINE__,x)); TRACE("got driver %d\n",x);
-jack_driver_t *
-_tryGetDriver(int deviceID, int ignored)
-{
-  fflush(OUTFILE);
-#else
-jack_driver_t *
-tryGetDriver(int deviceID)
-{
-#endif
-  jack_driver_t *drv = &outDev[deviceID];
-
-  int err;
-  if((err = pthread_mutex_trylock(&drv->mutex)) == 0)
-    return drv;
-
-  if(err == EBUSY)
-  {
-    TRACE("driver %d is busy\n",deviceID);
-    return 0;
-  }
-
-  ERR("lock returned an error\n");
-  return 0;
-}
-
-
-/* release a device's mutex */
-/* */
-/* This macro is similar to the one for getDriver above, only simpler since we only
-   really need to know when the lock was release for the sake of debugging.
-*/
-#if TRACE_getReleaseDevice
-#define releaseDriver(x) TRACE("releasing driver %d\n",x->deviceID); _releaseDriver(x);
-void
-_releaseDriver(jack_driver_t * drv)
-#else
-void
-releaseDriver(jack_driver_t * drv)
-#endif
-{
-  /*
-     #if TRACE_getReleaseDevice
-     TRACE("deviceID == %d\n", drv->deviceID);
-     #endif
-   */
-  pthread_mutex_unlock(&drv->mutex);
-}
-
-
-/* Return a string corresponding to the input state */
-char *
-DEBUGSTATE(enum status_enum state)
-{
-  if(state == PLAYING)
-    return "PLAYING";
-  else if(state == PAUSED)
-    return "PAUSED";
-  else if(state == STOPPED)
-    return "STOPPED";
-  else if(state == CLOSED)
-    return "CLOSED";
-  else if(state == RESET)
-    return "RESET";
-  else
-    return "unknown state";
-}
-
-#define SAMPLE_MAX_24BIT  8388608.0f
-#define SAMPLE_MAX_16BIT  32768.0f
-#define SAMPLE_MAX_8BIT   255.0f
-
-/* floating point volume routine */
-/* volume should be a value between 0.0 and 1.0 */
-static void
-float_volume_effect(sample_t * buf, unsigned long nsamples, float volume,
-                    int skip)
-{
-  if(volume < 0)
-    volume = 0;
-  if(volume > 1.0)
-    volume = 1.0;
-
-  while(nsamples--)
-  {
-    *buf = (*buf) * volume;
-    buf += skip;
-  }
-}
-
-/* place one channel into a multi-channel stream */
-static inline void
-mux(sample_t * dst, sample_t * src, unsigned long nsamples,
-    unsigned long dst_skip)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  while(nsamples--)
-  {
-    *dst = *src;
-    dst += dst_skip;
-    src++;
-  }
-}
-
-/* pull one channel out of a multi-channel stream */
-static void
-demux(sample_t * dst, sample_t * src, unsigned long nsamples,
-      unsigned long src_skip)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  while(nsamples--)
-  {
-    *dst = *src;
-    dst++;
-    src += src_skip;
-  }
-}
-
-/* copy floating point samples */
-static inline void
-sample_move_float_float(sample_t * dst, float * src, unsigned long nsamples)
-{
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (sample_t) (src[i]);
-}
-
-/* convert from 32 bit samples to floating point */
-static inline void
-sample_move_int32_float(sample_t * dst, int32_t * src, unsigned long nsamples)
-{
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (sample_t) (src[i] >> 8) / SAMPLE_MAX_24BIT;
-}
-
-/* convert from 24 bit samples packed into 32 bits to floating point */
-static inline void
-sample_move_int24_float(sample_t * dst, int32_t * src, unsigned long nsamples)
-{
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (sample_t) (src[i]) / SAMPLE_MAX_24BIT;
-}
-
-/* convert from 16 bit to floating point */
-static inline void
-sample_move_short_float(sample_t * dst, short *src, unsigned long nsamples)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (sample_t) (src[i]) / SAMPLE_MAX_16BIT;
-}
-
-/* convert from floating point to 16 bit */
-static inline void
-sample_move_float_short(short *dst, sample_t * src, unsigned long nsamples)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (short) ((src[i]) * SAMPLE_MAX_16BIT);
-}
-
-/* convert from 8 bit to floating point */
-static inline void
-sample_move_char_float(sample_t * dst, unsigned char *src, unsigned long nsamples)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (sample_t) (src[i]) / SAMPLE_MAX_8BIT;
-}
-
-/* convert from floating point to 8 bit */
-static inline void
-sample_move_float_char(unsigned char *dst, sample_t * src, unsigned long nsamples)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  unsigned long i;
-  for(i = 0; i < nsamples; i++)
-    dst[i] = (char) ((src[i]) * SAMPLE_MAX_8BIT);
-}
-
-/* fill dst buffer with nsamples worth of silence */
-static void inline
-sample_silence_float(sample_t * dst, unsigned long nsamples)
-{
-  /* ALERT: signed sign-extension portability !!! */
-  while(nsamples--)
-  {
-    *dst = 0;
-    dst++;
-  }
-}
-
-static bool inline
-ensure_buffer_size(char **buffer, unsigned long *cur_size,
-                   unsigned long needed_size)
-{
-  DEBUG("current size = %lu, needed size = %lu\n", *cur_size, needed_size);
-  if(*cur_size >= needed_size)
-    return TRUE;
-  DEBUG("reallocing\n");
-  char *tmp = realloc(*buffer, needed_size);
-  if(tmp)
-  {
-    *cur_size = needed_size;
-    *buffer = tmp;
-    return TRUE;
-  }
-  DEBUG("reallocing failed\n");
-  return FALSE;
-}
-
-/******************************************************************
- *    JACK_callback
- *
- * every time the jack server wants something from us it calls this
- * function, so we either deliver it some sound to play or deliver it nothing
- * to play
- */
-static int
-JACK_callback(nframes_t nframes, void *arg)
-{
-  jack_driver_t *drv = (jack_driver_t *) arg;
-
-  int i, src_error = 0;
-
-  TIMER("start\n");
-  gettimeofday(&drv->previousTime, 0);  /* record the current time */
-
-  CALLBACK_TRACE("nframes %ld, sizeof(sample_t) == %d\n", (long) nframes,
-                 sizeof(sample_t));
-
-  if(!drv->client)
-    ERR("client is closed, this is weird...\n");
-
-  sample_t *out_buffer[MAX_OUTPUT_PORTS];
-  /* retrieve the buffers for the output ports */
-  for(i = 0; i < drv->num_output_channels; i++)
-    out_buffer[i] = (sample_t *) jack_port_get_buffer(drv->output_port[i], nframes);
-
-  sample_t *in_buffer[MAX_INPUT_PORTS];
-  /* retrieve the buffers for the input ports */
-  for(i = 0; i < drv->num_input_channels; i++)
-    in_buffer[i] = (sample_t *) jack_port_get_buffer(drv->input_port[i], nframes);
-
-  /* handle playing state */
-  if(drv->state == PLAYING)
-  {
-    /* handle playback data, if any */
-    if(drv->num_output_channels > 0)
-    {
-      unsigned long jackFramesAvailable = nframes;      /* frames we have left to write to jack */
-      unsigned long numFramesToWrite;   /* num frames we are writing */
-      size_t inputBytesAvailable = jack_ringbuffer_read_space(drv->pPlayPtr);
-      unsigned long inputFramesAvailable;       /* frames we have available */
-
-      inputFramesAvailable = inputBytesAvailable / drv->bytes_per_jack_output_frame;
-      size_t jackBytesAvailable = jackFramesAvailable * drv->bytes_per_jack_output_frame;
-
-      long read = 0;
-
-      CALLBACK_TRACE("playing... jackFramesAvailable = %ld inputFramesAvailable = %ld\n",
-         jackFramesAvailable, inputFramesAvailable);
-
-#if JACK_CLOSE_HACK
-      if(drv->in_use == FALSE)
-      {
-        /* output silence if nothing is being outputted */
-        for(i = 0; i < drv->num_output_channels; i++)
-          sample_silence_float(out_buffer[i], nframes);
-
-        return -1;
-      }
-#endif
-
-      /* make sure our buffer is large enough for the data we are writing */
-      /* ie. callback_buffer2_size < (bytes we already wrote + bytes we are going to write in this loop) */
-      if(!ensure_buffer_size
-         (&drv->callback_buffer2, &drv->callback_buffer2_size,
-          jackBytesAvailable))
-      {
-        ERR("allocated %lu bytes, need %lu bytes\n",
-            drv->callback_buffer2_size, (unsigned long)jackBytesAvailable);
-        return -1;
-      }
-
-      /* do sample rate conversion if needed & requested */
-      if(drv->output_src && drv->output_sample_rate_ratio != 1.0)
-      {
-        long bytes_needed_write = nframes * drv->bytes_per_jack_output_frame;
-
-        /* make a very good guess at how many raw bytes we'll need to satisfy jack's request after conversion */
-        long bytes_needed_read = min(inputBytesAvailable,
-                                     (double) (bytes_needed_write +
-                                               drv->
-                                               output_sample_rate_ratio
-                                               *
-                                               drv->
-                                               bytes_per_jack_output_frame)
-                                     / drv->output_sample_rate_ratio);
-        DEBUG("guessing that we need %ld bytes in and %ld out for rate conversion ratio = %f\n",
-           bytes_needed_read, bytes_needed_write,
-           drv->output_sample_rate_ratio);
-
-        if(!ensure_buffer_size(&drv->callback_buffer1,
-                               &drv->callback_buffer1_size,
-                               bytes_needed_read))
-        {
-          ERR("could not realloc callback_buffer2!\n");
-          return 1;
-        }
-        if(!ensure_buffer_size(&drv->callback_buffer2,
-                               &drv->callback_buffer2_size,
-                               bytes_needed_write))
-        {
-          ERR("could not realloc callback_buffer2!\n");
-          return 1;
-        }
-
-        if(jackFramesAvailable && inputBytesAvailable > 0)
-        {
-          /* read in the data, but don't move the read pointer until we know how much SRC used */
-          jack_ringbuffer_peek(drv->pPlayPtr, drv->callback_buffer1,
-                               bytes_needed_read);
-
-          SRC_DATA srcdata;
-          srcdata.data_in = (sample_t *) drv->callback_buffer1;
-          srcdata.input_frames = bytes_needed_read / drv->bytes_per_jack_output_frame;
-          srcdata.src_ratio = drv->output_sample_rate_ratio;
-          srcdata.data_out = (sample_t *) drv->callback_buffer2;
-          srcdata.output_frames = nframes;
-          srcdata.end_of_input = 0;     // it's a stream, it never ends
-          DEBUG("input_frames = %ld, output_frames = %ld\n",
-                srcdata.input_frames, srcdata.output_frames);
-          /* convert the sample rate */
-          src_error = src_process(drv->output_src, &srcdata);
-          DEBUG("used = %ld, generated = %ld, error = %d: %s.\n",
-                srcdata.input_frames_used, srcdata.output_frames_gen,
-                src_error, src_strerror(src_error));
-
-          if(src_error == 0)
-          {
-            /* now we can move the read pointer */
-            jack_ringbuffer_read_advance(drv->pPlayPtr,
-                                         srcdata.
-                                         input_frames_used *
-                                         drv->bytes_per_jack_output_frame);
-            /* add on what we wrote */
-            read = srcdata.input_frames_used * drv->bytes_per_output_frame;
-            jackFramesAvailable -= srcdata.output_frames_gen;   /* take away what was used */
-          }
-        }
-      }
-      else                      /* no resampling needed or requested */
-      {
-        /* read as much data from the buffer as is available */
-        if(jackFramesAvailable && inputBytesAvailable > 0)
-        {
-          /* write as many bytes as we have space remaining, or as much as we have data to write */
-          numFramesToWrite = min(jackFramesAvailable, inputFramesAvailable);
-          jack_ringbuffer_read(drv->pPlayPtr, drv->callback_buffer2,
-                               jackBytesAvailable);
-          /* add on what we wrote */
-          read = numFramesToWrite * drv->bytes_per_output_frame;
-          jackFramesAvailable -= numFramesToWrite;      /* take away what was written */
-        }
-      }
-
-      drv->written_client_bytes += read;
-      drv->played_client_bytes += drv->clientBytesInJack;       /* move forward by the previous bytes we wrote since those must have finished by now */
-      drv->clientBytesInJack = read;    /* record the input bytes we wrote to jack */
-
-      /* see if we still have jackBytesLeft here, if we do that means that we
-         ran out of wave data to play and had a buffer underrun, fill in
-         the rest of the space with zero bytes so at least there is silence */
-      if(jackFramesAvailable)
-      {
-        WARN("buffer underrun of %ld frames\n", jackFramesAvailable);
-        for(i = 0; i < drv->num_output_channels; i++)
-          sample_silence_float(out_buffer[i] +
-                               (nframes - jackFramesAvailable),
-                               jackFramesAvailable);
-      }
-
-      /* if we aren't converting or we are converting and src_error == 0 then we should */
-      /* apply volume and demux */
-      if(!(drv->output_src && drv->output_sample_rate_ratio != 1.0) || (src_error == 0))
-      {
-          /* apply volume */
-          for(i = 0; i < drv->num_output_channels; i++)
-          {
-              if(drv->volumeEffectType == dbAttenuation)
-              {
-                  /* assume the volume setting is dB of attenuation, a volume of 0 */
-                  /* is 0dB attenuation */
-                  float volume = powf(10.0, -((float) drv->volume[i]) / 20.0);
-                  float_volume_effect((sample_t *) drv->callback_buffer2 + i,
-                                      (nframes - jackFramesAvailable), volume, drv->num_output_channels);
-              } else
-              {
-                  float_volume_effect((sample_t *) drv->callback_buffer2 + i, (nframes - jackFramesAvailable),
-                                      ((float) drv->volume[i] / 100.0),
-                                      drv->num_output_channels);
-              }
-          }
-
-          /* demux the stream: we skip over the number of samples we have output channels as the channel data */
-          /* is encoded like chan1,chan2,chan3,chan1,chan2,chan3... */
-          for(i = 0; i < drv->num_output_channels; i++)
-          {
-              demux(out_buffer[i],
-                    (sample_t *) drv->callback_buffer2 + i,
-                    (nframes - jackFramesAvailable), drv->num_output_channels);
-          }
-      }
-    }
-
-    /* handle record data, if any */
-    if(drv->num_input_channels > 0)
-    {
-      long jack_bytes = nframes * drv->bytes_per_jack_input_frame;      /* how many bytes jack is feeding us */
-
-      if(!ensure_buffer_size(&drv->callback_buffer1, &drv->callback_buffer1_size, jack_bytes))
-      {
-        ERR("allocated %lu bytes, need %ld bytes\n",
-            drv->callback_buffer1_size, jack_bytes);
-        return -1;
-      }
-
-      /* mux the invividual channels into one stream */
-      for(i = 0; i < drv->num_input_channels; i++)
-      {
-        mux((sample_t *) drv->callback_buffer1 + i, in_buffer[i],
-            nframes, drv->num_input_channels);
-      }
-
-      /* do sample rate conversion if needed & requested */
-      if(drv->input_src && drv->input_sample_rate_ratio != 1.0)
-      {
-        /* make a very good guess at how many raw bytes we'll need to read all the data jack gave us */
-        long bytes_needed_write = (double) (jack_bytes +
-                                            drv->input_sample_rate_ratio *
-                                            drv->bytes_per_jack_input_frame) *
-          drv->input_sample_rate_ratio;
-        DEBUG("guessing that we need %ld bytes in and %ld out for rate conversion ratio = %f\n",
-              nframes * drv->bytes_per_jack_input_frame,
-              bytes_needed_write, drv->input_sample_rate_ratio);
-
-        if(!ensure_buffer_size(&drv->callback_buffer2,
-                               &drv->callback_buffer2_size,
-                               bytes_needed_write))
-        {
-          ERR("could not realloc callback_buffer2!\n");
-          return 1;
-        }
-
-        SRC_DATA srcdata;
-        srcdata.data_in = (sample_t *) drv->callback_buffer1;
-        srcdata.input_frames = nframes;
-        srcdata.src_ratio = drv->input_sample_rate_ratio;
-        srcdata.data_out = (sample_t *) drv->callback_buffer2;
-        srcdata.output_frames = drv->callback_buffer2_size / drv->bytes_per_jack_input_frame;
-        srcdata.end_of_input = 0;       // it's a stream, it never ends
-        DEBUG("input_frames = %ld, output_frames = %ld\n",
-              srcdata.input_frames, srcdata.output_frames);
-        /* convert the sample rate */
-        src_error = src_process(drv->input_src, &srcdata);
-        DEBUG("used = %ld, generated = %ld, error = %d: %s.\n",
-              srcdata.input_frames_used, srcdata.output_frames_gen,
-              src_error, src_strerror(src_error));
-
-        if(src_error == 0)
-        {
-          long write_space = jack_ringbuffer_write_space(drv->pRecPtr);
-          long bytes_used =  srcdata.output_frames_gen * drv->bytes_per_jack_input_frame;
-          /* if there isn't enough room, make some.  sure this discards data, but when dealing with input sources
-             it seems like it's better to throw away old data than new */
-          if(write_space < bytes_used)
-          {
-            /* the ringbuffer is designed such that only one thread should ever access each pointer.
-               since calling read_advance here will be touching the read pointer which is also accessed
-               by JACK_Read, we need to lock the mutex first for safety */
-            jack_driver_t *d = tryGetDriver(drv->deviceID);
-            if( d )
-            {
-              /* double check the write space after we've gained the lock, just
-                 in case JACK_Read was being called before we gained it */
-              write_space = jack_ringbuffer_write_space(drv->pRecPtr);
-              if(write_space < bytes_used)
-              {
-                /* hey, we warn about underruns, we might as well warn about overruns as well */
-                WARN("buffer overrun of %ld bytes\n", jack_bytes - write_space);
-                jack_ringbuffer_read_advance(drv->pRecPtr, bytes_used - write_space);
-              }
-
-              releaseDriver(drv);
-            }
-          }
-
-          jack_ringbuffer_write(drv->pRecPtr, drv->callback_buffer2,
-                                bytes_used);
-        }
-      }
-      else                      /* no resampling needed */
-      {
-        long write_space = jack_ringbuffer_write_space(drv->pRecPtr);
-        /* if there isn't enough room, make some.  sure this discards data, but when dealing with input sources
-           it seems like it's better to throw away old data than new */
-        if(write_space < jack_bytes)
-        {
-          /* the ringbuffer is designed such that only one thread should ever access each pointer.
-             since calling read_advance here will be touching the read pointer which is also accessed
-             by JACK_Read, we need to lock the mutex first for safety */
-	        jack_driver_t *d = tryGetDriver(drv->deviceID);
-          if( d )
-          {
-            /* double check the write space after we've gained the lock, just
-               in case JACK_Read was being called before we gained it */
-            write_space = jack_ringbuffer_write_space(drv->pRecPtr);
-            if(write_space < jack_bytes)
-            {
-             ERR("buffer overrun of %ld bytes\n", jack_bytes - write_space);
-             jack_ringbuffer_read_advance(drv->pRecPtr, jack_bytes - write_space);
-            }
-	          releaseDriver(drv);
-          }
-        }
-
-        jack_ringbuffer_write(drv->pRecPtr, drv->callback_buffer1,
-                              jack_bytes);
-      }
-    }
-  }
-  else if(drv->state == PAUSED  ||
-          drv->state == STOPPED ||
-          drv->state == CLOSED  || drv->state == RESET)
-  {
-    CALLBACK_TRACE("%s, outputting silence\n", DEBUGSTATE(drv->state));
-
-    /* output silence if nothing is being outputted */
-    for(i = 0; i < drv->num_output_channels; i++)
-      sample_silence_float(out_buffer[i], nframes);
-
-    /* if we were told to reset then zero out some variables */
-    /* and transition to STOPPED */
-    if(drv->state == RESET)
-    {
-      drv->written_client_bytes = 0;
-      drv->played_client_bytes = 0;     /* number of the clients bytes that jack has played */
-
-      drv->client_bytes = 0;    /* bytes that the client wrote to use */
-
-      drv->clientBytesInJack = 0;       /* number of input bytes in jack(not necessary the number of bytes written to jack) */
-
-      drv->position_byte_offset = 0;
-
-      if(drv->pPlayPtr)
-        jack_ringbuffer_reset(drv->pPlayPtr);
-
-      if(drv->pRecPtr)
-        jack_ringbuffer_reset(drv->pRecPtr);
-
-      drv->state = STOPPED;     /* transition to STOPPED */
-    }
-  }
-
-  CALLBACK_TRACE("done\n");
-  TIMER("finish\n");
-
-  return 0;
-}
-
-
-/******************************************************************
- *             JACK_bufsize
- *
- *             Called whenever the jack server changes the the max number
- *             of frames passed to JACK_callback
- */
-static int
-JACK_bufsize(nframes_t nframes, void *arg)
-{
-  jack_driver_t *drv = (jack_driver_t *) arg;
-  TRACE("the maximum buffer size is now %lu frames\n", (long) nframes);
-
-  drv->jack_buffer_size = nframes;
-
-  return 0;
-}
-
-/******************************************************************
- *		JACK_srate
- */
-int
-JACK_srate(nframes_t nframes, void *arg)
-{
-  jack_driver_t *drv = (jack_driver_t *) arg;
-
-  drv->jack_sample_rate = (long) nframes;
-
-  /* make sure to recalculate the ratios needed for proper sample rate conversion */
-  drv->output_sample_rate_ratio = (double) drv->jack_sample_rate / (double) drv->client_sample_rate;
-  if(drv->output_src) src_set_ratio(drv->output_src, drv->output_sample_rate_ratio);
-
-  drv->input_sample_rate_ratio = (double) drv->client_sample_rate / (double) drv->jack_sample_rate;
-  if(drv->input_src) src_set_ratio(drv->input_src, drv->input_sample_rate_ratio);
-
-  TRACE("the sample rate is now %lu/sec\n", (long) nframes);
-  return 0;
-}
-
-
-/******************************************************************
- *		JACK_shutdown
- *
- * if this is called then jack shut down... handle this appropriately */
-void
-JACK_shutdown(void *arg)
-{
-  jack_driver_t *drv = (jack_driver_t *) arg;
-
-  TRACE("\n");
-
-  getDriver(drv->deviceID);
-
-  drv->client = 0;              /* reset client */
-  drv->jackd_died = TRUE;
-
-  TRACE("jack shutdown, setting client to 0 and jackd_died to true, closing device\n");
-
-#if JACK_CLOSE_HACK
-  JACK_CloseDevice(drv, TRUE);
-#else
-  JACK_CloseDevice(drv);
-#endif
-
-  TRACE("trying to reconnect right now\n");
-  /* lets see if we can't reestablish the connection */
-  if(JACK_OpenDevice(drv) != ERR_SUCCESS)
-  {
-    ERR("unable to reconnect with jack\n");
-  }
-
-  releaseDriver(drv);
-}
-
-
-/******************************************************************
- *		JACK_Error
- *
- * Callback for jack errors
- */
-static void
-JACK_Error(const char *desc)
-{
-  ERR("%s\n", desc);
-}
-
-
-/******************************************************************
- *		JACK_OpenDevice
- *
- *  RETURNS: ERR_SUCCESS upon success
- */
-static int
-JACK_OpenDevice(jack_driver_t * drv)
-{
-  const char **ports;
-  char *our_client_name = 0;
-  int i, failed = 0;
-
-  TRACE("creating jack client and setting up callbacks\n");
-
-#if JACK_CLOSE_HACK
-  /* see if this device is already open */
-  if(drv->client)
-  {
-    /* if this device is already in use then it is bad for us to be in here */
-    if(drv->in_use)
-      return ERR_OPENING_JACK;
-
-    TRACE("using existing client\n");
-    drv->in_use = TRUE;
-    return ERR_SUCCESS;
-  }
-#endif
-
-  /* set up an error handler */
-  jack_set_error_function(JACK_Error);
-
-
-  /* build the client name */
-  our_client_name = g_strdup_printf("%s_%d_%d%02d", client_name, getpid(),
-                                    drv->deviceID, drv->clientCtr++);
-
-  /* try to become a client of the JACK server */
-  TRACE("client name '%s'\n", our_client_name);
-  if((drv->client = jack_client_open(our_client_name, JackNullOption | JackNoStartServer, NULL)) == 0)
-  {
-    /* try once more */
-    TRACE("trying once more to jack_client_new");
-    if((drv->client = jack_client_open(our_client_name, JackNullOption | JackNoStartServer, NULL)) == 0)
-    {
-      ERR("jack server not running?\n");
-      g_free(our_client_name);
-      return ERR_OPENING_JACK;
-    }
-  }
-
-  g_free(our_client_name);
-
-  TRACE("setting up jack callbacks\n");
-
-  /* JACK server to call `JACK_callback()' whenever
-     there is work to be done. */
-  jack_set_process_callback(drv->client, JACK_callback, drv);
-
-  /* setup a buffer size callback */
-  jack_set_buffer_size_callback(drv->client, JACK_bufsize, drv);
-
-  /* tell the JACK server to call `srate()' whenever
-     the sample rate of the system changes. */
-  jack_set_sample_rate_callback(drv->client, JACK_srate, drv);
-
-  /* tell the JACK server to call `jack_shutdown()' if
-     it ever shuts down, either entirely, or if it
-     just decides to stop calling us. */
-  jack_on_shutdown(drv->client, JACK_shutdown, drv);
-
-  /* display the current sample rate. once the client is activated
-     (see below), you should rely on your own sample rate
-     callback (see above) for this value. */
-  drv->jack_sample_rate = jack_get_sample_rate(drv->client);
-  drv->output_sample_rate_ratio = (double) drv->jack_sample_rate / (double) drv->client_sample_rate;
-  drv->input_sample_rate_ratio = (double) drv->client_sample_rate / (double) drv->jack_sample_rate;
-  TRACE("client sample rate: %lu, jack sample rate: %lu, output ratio = %f, input ratio = %f\n",
-        drv->client_sample_rate, drv->jack_sample_rate,
-        drv->output_sample_rate_ratio, drv->input_sample_rate_ratio);
-
-  drv->jack_buffer_size = jack_get_buffer_size(drv->client);
-
-  /* create the output ports */
-  TRACE("creating output ports\n");
-  for(i = 0; i < drv->num_output_channels; i++)
-  {
-    char portname[32];
-    sprintf(portname, "out_%d", i);
-    TRACE("port %d is named '%s'\n", i, portname);
-    /* NOTE: Yes, this is supposed to be JackPortIsOutput since this is an output */
-    /* port FROM bio2jack */
-    drv->output_port[i] = jack_port_register(drv->client, portname,
-                                             JACK_DEFAULT_AUDIO_TYPE,
-                                             JackPortIsOutput, 0);
-  }
-
-  /* create the input ports */
-  TRACE("creating input ports\n");
-  for(i = 0; i < drv->num_input_channels; i++)
-  {
-    char portname[32];
-    sprintf(portname, "in_%d", i);
-    TRACE("port %d is named '%s'\n", i, portname);
-    /* NOTE: Yes, this is supposed to be JackPortIsInput since this is an input */
-    /* port TO bio2jack */
-    drv->input_port[i] = jack_port_register(drv->client, portname,
-                                            JACK_DEFAULT_AUDIO_TYPE,
-                                            JackPortIsInput, 0);
-  }
-
-#if JACK_CLOSE_HACK
-  drv->in_use = TRUE;
-#endif
-
-  /* tell the JACK server that we are ready to roll */
-  TRACE("calling jack_activate()\n");
-  if(jack_activate(drv->client))
-  {
-    ERR("cannot activate client\n");
-    return ERR_OPENING_JACK;
-  }
-
-  /* if we have output channels and the port connection mode isn't CONNECT_NONE */
-  /* then we should connect up some ports */
-  if((drv->num_output_channels > 0) && (port_connection_mode != CONNECT_NONE))
-  {
-    /* determine how we are to acquire output port names */
-    if((drv->jack_port_name_count == 0) || (drv->jack_port_name_count == 1))
-    {
-      if(drv->jack_port_name_count == 0)
-      {
-        TRACE("jack_get_ports() passing in NULL/NULL\n");
-        ports = jack_get_ports(drv->client, NULL, NULL,
-                               drv->jack_output_port_flags);
-      }
-      else
-      {
-        TRACE("jack_get_ports() passing in port of '%s'\n",
-              drv->jack_port_name[0]);
-        ports = jack_get_ports(drv->client, drv->jack_port_name[0], NULL,
-                               drv->jack_output_port_flags);
-      }
-
-      /* display a trace of the output ports we found */
-      int num_ports = 0;
-      if(ports)
-      {
-        for(i = 0; ports[i]; i++)
-        {
-          TRACE("ports[%d] = '%s'\n", i, ports[i]);
-          num_ports++;
-        }
-      }
-
-      /* ensure that we found enough ports */
-      if(!ports || (i < drv->num_output_channels))
-      {
-        TRACE("ERR: jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n",
-              drv->jack_output_port_flags);
-#if JACK_CLOSE_HACK
-        JACK_CloseDevice(drv, TRUE);
-#else
-        JACK_CloseDevice(drv);
-#endif
-        return ERR_PORT_NOT_FOUND;
-      }
-
-      /* connect a port for each output channel. Note: you can't do this before
-         the client is activated (this may change in the future). */
-      for(i = 0; i < drv->num_output_channels; i++)
-      {
-        TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[i]);
-        if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[i]))
-        {
-          ERR("cannot connect to output port %d('%s')\n", i, ports[i]);
-          failed = 1;
-        }
-      }
-
-      /* only if we are in CONNECT_ALL mode should we keep connecting ports up beyond */
-      /* the minimum number of ports required for each output channel coming into bio2jack */
-      if(port_connection_mode == CONNECT_ALL)
-      {
-          /* It's much cheaper and easier to let JACK do the processing required to
-             connect 2 channels to 4 or 4 channels to 2 or any other combinations.
-             This effectively eliminates the need for sample_move_d16_d16() */
-          if(drv->num_output_channels < num_ports)
-          {
-              for(i = drv->num_output_channels; ports[i]; i++)
-              {
-                  int n = i % drv->num_output_channels;
-                  TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[n]);
-                  if(jack_connect(drv->client, jack_port_name(drv->output_port[n]), ports[i]))
-                  {
-                      // non fatal
-                      ERR("cannot connect to output port %d('%s')\n", n, ports[i]);
-                  }
-              }
-          }
-          else if(drv->num_output_channels > num_ports)
-          {
-              for(i = num_ports; i < drv->num_output_channels; i++)
-              {
-                  int n = i % num_ports;
-                  TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[n]);
-                  if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[n]))
-                  {
-                      // non fatal
-                      ERR("cannot connect to output port %d('%s')\n", i, ports[n]);
-                  }
-              }
-          }
-      }
-
-      g_free(ports);              /* free the returned array of ports */
-    }
-    else
-    {
-      for(i = 0; i < drv->jack_port_name_count; i++)
-      {
-        TRACE("jack_get_ports() portname %d of '%s\n", i,
-              drv->jack_port_name[i]);
-        ports = jack_get_ports(drv->client, drv->jack_port_name[i], NULL,
-                               drv->jack_output_port_flags);
-
-        if(!ports)
-        {
-          ERR("jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n",
-              drv->jack_output_port_flags);
-          return ERR_PORT_NOT_FOUND;
-        }
-
-        TRACE("ports[%d] = '%s'\n", 0, ports[0]);       /* display a trace of the output port we found */
-
-        /* connect the port */
-        TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[i]);
-        if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[0]))
-        {
-          ERR("cannot connect to output port %d('%s')\n", 0, ports[0]);
-          failed = 1;
-        }
-        g_free(ports);            /* free the returned array of ports */
-      }
-    }
-  }                             /* if( drv->num_output_channels > 0 ) */
-
-
-  if(drv->num_input_channels > 0)
-  {
-    /* determine how we are to acquire input port names */
-    if((drv->jack_port_name_count == 0) || (drv->jack_port_name_count == 1))
-    {
-      if(drv->jack_port_name_count == 0)
-      {
-        TRACE("jack_get_ports() passing in NULL/NULL\n");
-        ports = jack_get_ports(drv->client, NULL, NULL, drv->jack_input_port_flags);
-      }
-      else
-      {
-        TRACE("jack_get_ports() passing in port of '%s'\n",
-              drv->jack_port_name[0]);
-        ports = jack_get_ports(drv->client, drv->jack_port_name[0], NULL,
-                               drv->jack_input_port_flags);
-      }
-
-      /* display a trace of the input ports we found */
-      int num_ports = 0;
-      if(ports)
-      {
-        for(i = 0; ports[i]; i++)
-        {
-          TRACE("ports[%d] = '%s'\n", i, ports[i]);
-          num_ports++;
-        }
-      }
-
-      /* ensure that we found enough ports */
-      if(!ports || (i < drv->num_input_channels))
-      {
-        TRACE("ERR: jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n",
-              drv->jack_input_port_flags);
-#if JACK_CLOSE_HACK
-        JACK_CloseDevice(drv, TRUE);
-#else
-        JACK_CloseDevice(drv);
-#endif
-        return ERR_PORT_NOT_FOUND;
-      }
-
-      /* connect the ports. Note: you can't do this before
-         the client is activated (this may change in the future). */
-      for(i = 0; i < drv->num_input_channels; i++)
-      {
-        TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[i]);
-        if(jack_connect(drv->client, ports[i], jack_port_name(drv->input_port[i])))
-        {
-          ERR("cannot connect to input port %d('%s')\n", i, ports[i]);
-          failed = 1;
-        }
-      }
-
-      /* It's much cheaper and easier to let JACK do the processing required to
-         connect 2 channels to 4 or 4 channels to 2 or any other combinations.
-         This effectively eliminates the need for sample_move_d16_d16() */
-      if(drv->num_input_channels < num_ports)
-      {
-        for(i = drv->num_input_channels; ports[i]; i++)
-        {
-          int n = i % drv->num_input_channels;
-          TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[n]);
-          if(jack_connect(drv->client, ports[i], jack_port_name(drv->input_port[n])))
-          {
-            // non fatal
-            ERR("cannot connect to input port %d('%s')\n", n, ports[i]);
-          }
-        }
-      }
-      else if(drv->num_input_channels > num_ports)
-      {
-        for(i = num_ports; i < drv->num_input_channels; i++)
-        {
-          int n = i % num_ports;
-          TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[n]);
-          if(jack_connect(drv->client, ports[n], jack_port_name(drv->input_port[i])))
-          {
-            // non fatal
-            ERR("cannot connect to input port %d('%s')\n", i, ports[n]);
-          }
-        }
-      }
-
-      g_free(ports);              /* free the returned array of ports */
-    }
-    else
-    {
-      for(i = 0; i < drv->jack_port_name_count; i++)
-      {
-        TRACE("jack_get_ports() portname %d of '%s\n", i,
-              drv->jack_port_name[i]);
-        ports = jack_get_ports(drv->client, drv->jack_port_name[i], NULL,
-                               drv->jack_input_port_flags);
-
-        if(!ports)
-        {
-          ERR("jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n",
-              drv->jack_input_port_flags);
-          return ERR_PORT_NOT_FOUND;
-        }
-
-        TRACE("ports[%d] = '%s'\n", 0, ports[0]);       /* display a trace of the input port we found */
-
-        /* connect the port */
-        TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[i]);
-        if(jack_connect(drv->client, jack_port_name(drv->input_port[i]), ports[0]))
-        {
-          ERR("cannot connect to input port %d('%s')\n", 0, ports[0]);
-          failed = 1;
-        }
-        g_free(ports);            /* free the returned array of ports */
-      }
-    }
-  }                             /* if( drv->num_input_channels > 0 ) */
-
-  /* if something failed we need to shut the client down and return 0 */
-  if(failed)
-  {
-    TRACE("failed, closing and returning error\n");
-#if JACK_CLOSE_HACK
-    JACK_CloseDevice(drv, TRUE);
-#else
-    JACK_CloseDevice(drv);
-#endif
-    return ERR_OPENING_JACK;
-  }
-
-  TRACE("success\n");
-
-  drv->jackd_died = FALSE;      /* clear out this flag so we don't keep attempting to restart things */
-  drv->state = PLAYING;         /* clients seem to behave much better with this on from the start, especially when recording */
-
-  return ERR_SUCCESS;           /* return success */
-}
-
-
-/******************************************************************
- *		JACK_CloseDevice
- *
- *	Close the connection to the server cleanly.
- *  If close_client is TRUE we close the client for this device instead of
- *    just marking the device as in_use(JACK_CLOSE_HACK only)
- */
-#if JACK_CLOSE_HACK
-static void
-JACK_CloseDevice(jack_driver_t * drv, bool close_client)
-#else
-static void
-JACK_CloseDevice(jack_driver_t * drv)
-#endif
-{
-  unsigned int i;
-
-#if JACK_CLOSE_HACK
-  if(close_client)
-  {
-#endif
-
-    TRACE("closing the jack client thread\n");
-    if(drv->client)
-    {
-      TRACE("after jack_deactivate()\n");
-      int errorCode = jack_client_close(drv->client);
-      if(errorCode)
-        ERR("jack_client_close() failed returning an error code of %d\n",
-            errorCode);
-    }
-
-    /* reset client */
-    drv->client = 0;
-
-    /* free up the port strings */
-    TRACE("freeing up %d port strings\n", drv->jack_port_name_count);
-    if(drv->jack_port_name_count > 1)
-    {
-      for(i = 0; i < drv->jack_port_name_count; i++)
-        g_free(drv->jack_port_name[i]);
-      g_free(drv->jack_port_name);
-    }
-    JACK_CleanupDriver(drv);
-
-    JACK_ResetFromDriver(drv);
-
-#if JACK_CLOSE_HACK
-  } else
-  {
-    TRACE("setting in_use to FALSE\n");
-    drv->in_use = FALSE;
-
-    if(!drv->client)
-    {
-      TRACE("critical error, closing a device that has no client\n");
-    }
-  }
-#endif
-}
-
-
-
-
-/**************************************/
-/* External interface functions below */
-/**************************************/
-
-/* Clear out any buffered data, stop playing, zero out some variables */
-static void
-JACK_ResetFromDriver(jack_driver_t * drv)
-{
-  TRACE("resetting drv->deviceID(%d)\n", drv->deviceID);
-
-  /* NOTE: we use the RESET state so we don't need to worry about clearing out */
-  /* variables that the callback modifies while the callback is running */
-  /* we set the state to RESET and the callback clears the variables out for us */
-  drv->state = RESET;           /* tell the callback that we are to reset, the callback will transition this to STOPPED */
-}
-
-/* Clear out any buffered data, stop playing, zero out some variables */
-void
-JACK_Reset(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  TRACE("resetting deviceID(%d)\n", deviceID);
-  JACK_ResetFromDriver(drv);
-  releaseDriver(drv);
-}
-
-
-/*
- * open the audio device for writing to
- *
- * deviceID is set to the opened device
- * if client is non-zero and in_use is FALSE then just set in_use to TRUE
- *
- * return value is zero upon success, non-zero upon failure
- *
- * if ERR_RATE_MISMATCH (*rate) will be updated with the jack servers rate
- */
-int
-JACK_Open(int *deviceID, unsigned int bits_per_channel, int floating_point,
-	  unsigned long *rate, int channels)
-{
-  /* we call through to JACK_OpenEx(), but default the input channels to 0 for better backwards
-     compatibility with clients written before recording was available */
-  return JACK_OpenEx(deviceID, bits_per_channel,
-                     floating_point, rate,
-                     0, channels,
-                     NULL, 0, JackPortIsPhysical);
-}
-
-/*
- * see JACK_Open() for comments
- * NOTE: jack_port_name has three ways of being used:
- *       - NULL - finds all ports with the given flags
- *       - A single regex string used to retrieve all port names
- *       - A series of port names, one for each output channel
- *
- * we set *deviceID
- */
-int
-JACK_OpenEx(int *deviceID, unsigned int bits_per_channel,
-	    int floating_point, unsigned long *rate,
-            unsigned int input_channels, unsigned int output_channels,
-            const char **jack_port_name,
-            unsigned int jack_port_name_count, unsigned long jack_port_flags)
-{
-  jack_driver_t *drv = 0;
-  int sample_format = SAMPLE_FMT_INTEGER;
-  unsigned int i;
-  int retval;
-
-  if(input_channels < 1 && output_channels < 1)
-  {
-    ERR("no input OR output channels, nothing to do\n");
-    return ERR_OPENING_JACK;
-  }
-
-  switch (bits_per_channel)
-  {
-  case 8:
-  case 16:
-  case 32:
-    break;
-  case 24:
-    bits_per_channel = 32;
-    sample_format = SAMPLE_FMT_PACKED_24B;
-    break;
-  default:
-    ERR("invalid bits_per_channel\n");
-    return ERR_OPENING_JACK;
-  }
-
-  if (floating_point)
-  {
-    if (bits_per_channel != 32) {
-      ERR("bits_per_channel must be 32 for floating point\n");
-      return ERR_OPENING_JACK;
-    }
-    else
-    {
-      sample_format = SAMPLE_FMT_FLOAT;
-    }
-  }
-
-  /* Lock the device_mutex and find one that's not allocated already.
-     We'll keep this lock until we've either made use of it, or given up. */
-  pthread_mutex_lock(&device_mutex);
-
-  for(i = 0; i < MAX_OUTDEVICES; i++)
-  {
-    if(!outDev[i].allocated)
-    {
-      drv = &outDev[i];
-      break;
-    }
-  }
-
-  if(!drv)
-  {
-    ERR("no more devices available\n");
-    pthread_mutex_unlock(&device_mutex);
-    return ERR_OPENING_JACK;
-  }
-
-  /* We found an unallocated device, now lock it for extra saftey */
-  getDriver(drv->deviceID);
-
-  TRACE("bits_per_channel=%d rate=%ld, input_channels=%d, output_channels=%d\n",
-     bits_per_channel, *rate, input_channels, output_channels);
-
-  if(output_channels > MAX_OUTPUT_PORTS)
-  {
-    ERR("output_channels == %u, MAX_OUTPUT_PORTS == %u\n", output_channels,
-        MAX_OUTPUT_PORTS);
-    releaseDriver(drv);
-    pthread_mutex_unlock(&device_mutex);
-    return ERR_TOO_MANY_OUTPUT_CHANNELS;
-  }
-
-  if(input_channels > MAX_INPUT_PORTS)
-  {
-    ERR("input_channels == %u, MAX_INPUT_PORTS == %u\n", input_channels,
-        MAX_INPUT_PORTS);
-    releaseDriver(drv);
-    pthread_mutex_unlock(&device_mutex);
-    return ERR_TOO_MANY_INPUT_CHANNELS;
-  }
-
-  drv->jack_output_port_flags = jack_port_flags | JackPortIsInput;      /* port must be input(ie we can put data into it), so mask this in */
-  drv->jack_input_port_flags = jack_port_flags | JackPortIsOutput;      /* port must be output(ie we can get data from it), so mask this in */
-
-  /* check that we have the correct number of port names
-     FIXME?: not sure how we should handle output ports vs input ports....
-   */
-  if((jack_port_name_count > 1)
-     && ((jack_port_name_count < output_channels)
-         || (jack_port_name_count < input_channels)))
-  {
-    ERR("specified individual port names but not enough, gave %u names, need %u\n",
-       jack_port_name_count, output_channels);
-    releaseDriver(drv);
-    pthread_mutex_unlock(&device_mutex);
-    return ERR_PORT_NAME_OUTPUT_CHANNEL_MISMATCH;
-  } else
-  {
-    /* copy this data into the device information */
-    drv->jack_port_name_count = jack_port_name_count;
-
-    if(drv->jack_port_name_count != 0)
-    {
-      drv->jack_port_name = g_new(char *, drv->jack_port_name_count);
-      for(i = 0; i < drv->jack_port_name_count; i++)
-      {
-        drv->jack_port_name[i] = g_strdup(jack_port_name[i]);
-        TRACE("jack_port_name[%d] == '%s'\n", i, jack_port_name[i]);
-      }
-    } else
-    {
-      drv->jack_port_name = NULL;
-      TRACE("jack_port_name = NULL\n");
-    }
-  }
-
-  /* initialize some variables */
-  drv->in_use = FALSE;
-
-  JACK_ResetFromDriver(drv);    /* flushes all queued buffers, sets status to STOPPED and resets some variables */
-
-  /* drv->jack_sample_rate is set by JACK_OpenDevice() */
-  drv->client_sample_rate = *rate;
-  drv->bits_per_channel = bits_per_channel;
-  drv->sample_format = sample_format;
-  drv->num_input_channels = input_channels;
-  drv->num_output_channels = output_channels;
-  drv->bytes_per_input_frame = (drv->bits_per_channel * drv->num_input_channels) / 8;
-  drv->bytes_per_output_frame = (drv->bits_per_channel * drv->num_output_channels) / 8;
-  drv->bytes_per_jack_output_frame = sizeof(sample_t) * drv->num_output_channels;
-  drv->bytes_per_jack_input_frame = sizeof(sample_t) * drv->num_input_channels;
-
-  if(drv->num_output_channels > 0)
-  {
-    drv->pPlayPtr = jack_ringbuffer_create(drv->num_output_channels *
-                                           drv->bytes_per_jack_output_frame *
-                                           DEFAULT_RB_SIZE);
-  }
-
-  if(drv->num_input_channels > 0)
-  {
-      drv->pRecPtr = jack_ringbuffer_create(drv->num_input_channels *
-                                            drv->bytes_per_jack_input_frame *
-                                            DEFAULT_RB_SIZE);
-  }
-
-  DEBUG("bytes_per_output_frame == %ld\n", drv->bytes_per_output_frame);
-  DEBUG("bytes_per_input_frame  == %ld\n", drv->bytes_per_input_frame);
-  DEBUG("bytes_per_jack_output_frame == %ld\n",
-        drv->bytes_per_jack_output_frame);
-  DEBUG("bytes_per_jack_input_frame == %ld\n",
-        drv->bytes_per_jack_input_frame);
-
-  /* go and open up the device */
-  retval = JACK_OpenDevice(drv);
-  if(retval != ERR_SUCCESS)
-  {
-    TRACE("error opening jack device\n");
-    releaseDriver(drv);
-    pthread_mutex_unlock(&device_mutex);
-    return retval;
-  }
-  else
-  {
-    TRACE("succeeded opening jack device\n");
-  }
-
-  /* setup SRC objects just in case they'll be needed but only if requested */
-  if(do_sample_rate_conversion)
-  {
-    int error;
-    if(drv->num_output_channels > 0)
-    {
-      drv->output_src = src_new(preferred_src_converter, drv->num_output_channels, &error);
-      if(error != 0)
-      {
-        src_delete(drv->output_src);
-        drv->output_src = 0;
-        ERR("Could not created SRC object for output stream %d: %s\n",
-            error, src_strerror(error));
-      }
-    }
-    if(drv->num_input_channels > 0)
-    {
-      drv->input_src = src_new(preferred_src_converter, drv->num_input_channels, &error);
-      if(error != 0)
-      {
-        src_delete(drv->input_src);
-        drv->input_src = 0;
-        ERR("Could not created SRC object for input stream %d: %s\n",
-            error, src_strerror(error));
-      }
-    }
-  }
-  else if((long) (*rate) != drv->jack_sample_rate)
-  {
-    TRACE("rate of %ld doesn't match jack sample rate of %ld, returning error\n",
-          *rate, drv->jack_sample_rate);
-    *rate = drv->jack_sample_rate;
-#if JACK_CLOSE_HACK
-    JACK_CloseDevice(drv, TRUE);
-#else
-    JACK_CloseDevice(drv);
-#endif
-    releaseDriver(drv);
-    pthread_mutex_unlock(&device_mutex);
-    return ERR_RATE_MISMATCH;
-  }
-
-  drv->allocated = TRUE;        /* record that we opened this device */
-
-  DEBUG("sizeof(sample_t) == %d\n", sizeof(sample_t));
-
-  *deviceID = drv->deviceID;    /* set the deviceID for the caller */
-  releaseDriver(drv);
-  pthread_mutex_unlock(&device_mutex);
-  return ERR_SUCCESS;           /* success */
-}
-
-/* Close the jack device */
-//FIXME: add error handling in here at some point...
-/* NOTE: return 0 for success, non-zero for failure */
-int
-JACK_Close(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-
-  TRACE("deviceID(%d)\n", deviceID);
-
-#if JACK_CLOSE_HACK
-  JACK_CloseDevice(drv, TRUE);
-#else
-  JACK_CloseDevice(drv);
-#endif
-
-  JACK_ResetFromDriver(drv);    /* reset this device to a normal starting state */
-
-  pthread_mutex_lock(&device_mutex);
-
-  /* free buffer memory */
-  drv->callback_buffer1_size = 0;
-  if(drv->callback_buffer1) g_free(drv->callback_buffer1);
-  drv->callback_buffer1 = 0;
-
-  drv->callback_buffer2_size = 0;
-  if(drv->callback_buffer2) g_free(drv->callback_buffer2);
-  drv->callback_buffer2 = 0;
-
-  drv->rw_buffer1_size = 0;
-  if(drv->rw_buffer1) g_free(drv->rw_buffer1);
-  drv->rw_buffer1 = 0;
-
-  if(drv->pPlayPtr) jack_ringbuffer_free(drv->pPlayPtr);
-  drv->pPlayPtr = 0;
-
-  if(drv->pRecPtr) jack_ringbuffer_free(drv->pRecPtr);
-  drv->pRecPtr = 0;
-
-  /* free the SRC objects */
-  if(drv->output_src) src_delete(drv->output_src);
-  drv->output_src = 0;
-
-  if(drv->input_src) src_delete(drv->input_src);
-  drv->input_src = 0;
-
-  drv->allocated = FALSE;       /* release this device */
-
-  pthread_mutex_unlock(&device_mutex);
-
-  releaseDriver(drv);
-
-  return 0;
-}
-
-/* If we haven't already taken in the max allowed data then create a wave header */
-/* to package the audio data and attach the wave header to the end of the */
-/* linked list of wave headers */
-/* These wave headers will be peeled off as they are played by the callback routine */
-/* Return value is the number of bytes written */
-/* NOTE: this function takes the length of data to be written bytes */
-long
-JACK_Write(int deviceID, unsigned char *data, unsigned long bytes)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-
-  long frames_free, frames;
-
-  TIMER("start\n");
-
-  TRACE("deviceID(%d), bytes == %ld\n", deviceID, bytes);
-
-  /* check and see that we have enough space for this audio */
-  frames_free =
-    jack_ringbuffer_write_space(drv->pPlayPtr) /
-    drv->bytes_per_jack_output_frame;
-  frames = bytes / drv->bytes_per_output_frame;
-  TRACE("frames free == %ld, bytes = %lu\n", frames_free, bytes);
-
-  TRACE("state = '%s'\n", DEBUGSTATE(drv->state));
-  /* if we are currently STOPPED we should start playing now...
-     do this before the check for bytes == 0 since some clients like
-     to write 0 bytes the first time out */
-  if(drv->state == STOPPED)
-  {
-    TRACE("currently STOPPED, transitioning to PLAYING\n");
-    drv->state = PLAYING;
-  }
-
-  /* handle the case where the user calls this routine with 0 bytes */
-  if(bytes == 0 || frames_free < 1)
-  {
-    TRACE("no room left\n");
-    TIMER("finish (nothing to do, buffer is full)\n");
-    releaseDriver(drv);
-    return 0;                   /* indicate that we couldn't write any bytes */
-  }
-
-  frames = min(frames, frames_free);
-  long jack_bytes = frames * drv->bytes_per_jack_output_frame;
-  if(!ensure_buffer_size(&drv->rw_buffer1, &drv->rw_buffer1_size, jack_bytes))
-  {
-    ERR("couldn't allocate enough space for the buffer\n");
-    releaseDriver(drv);
-    return 0;
-  }
-  /* adjust bytes to be how many client bytes we're actually writing */
-  bytes = frames * drv->bytes_per_output_frame;
-
-  /* convert from client samples to jack samples
-     we have to tell it how many samples there are, which is frames * channels */
-  switch (drv->bits_per_channel)
-  {
-  case 8:
-    sample_move_char_float((sample_t *) drv->rw_buffer1, (unsigned char *) data,
-                           frames * drv->num_output_channels);
-    break;
-  case 16:
-    sample_move_short_float((sample_t *) drv->rw_buffer1, (short *) data,
-                            frames * drv->num_output_channels);
-    break;
-  case 32:
-    if (drv->sample_format == SAMPLE_FMT_FLOAT)
-      sample_move_float_float((sample_t *) drv->rw_buffer1, (float *) data,
-                            frames * drv->num_output_channels);
-    else if (drv->sample_format == SAMPLE_FMT_PACKED_24B)
-      sample_move_int24_float((sample_t *) drv->rw_buffer1, (int32_t *) data,
-			      frames * drv->num_output_channels);
-    else
-      sample_move_int32_float((sample_t *) drv->rw_buffer1, (int32_t *) data,
-			      frames * drv->num_output_channels);
-    break;
-  }
-
-  DEBUG("ringbuffer read space = %d, write space = %d\n",
-        jack_ringbuffer_read_space(drv->pPlayPtr),
-        jack_ringbuffer_write_space(drv->pPlayPtr));
-
-  jack_ringbuffer_write(drv->pPlayPtr, drv->rw_buffer1, jack_bytes);
-  DEBUG("wrote %lu bytes, %lu jack_bytes\n", bytes, jack_bytes);
-
-  DEBUG("ringbuffer read space = %d, write space = %d\n",
-        jack_ringbuffer_read_space(drv->pPlayPtr),
-        jack_ringbuffer_write_space(drv->pPlayPtr));
-
-  drv->client_bytes += bytes;   /* update client_bytes */
-
-  TIMER("finish\n");
-
-  DEBUG("returning bytes written of %ld\n", bytes);
-
-  releaseDriver(drv);
-  return bytes;                 /* return the number of bytes we wrote out */
-}
-
-long
-JACK_Read(int deviceID, unsigned char *data, unsigned long bytes)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-
-  long frames_available, frames;
-
-  TIMER("start\n");
-
-  TRACE("deviceID(%d), bytes == %ld\n", deviceID, bytes);
-
-  /* find out if there's any room to write this data */
-  frames_available =
-    jack_ringbuffer_read_space(drv->pRecPtr) /
-    drv->bytes_per_jack_input_frame;
-  frames = bytes / drv->bytes_per_input_frame;
-  DEBUG("frames available = %ld, bytes = %lu\n", frames_available, bytes);
-
-  TRACE("state = '%s'\n", DEBUGSTATE(drv->state));
-  /* if we are currently STOPPED we should start recording now... */
-  if(drv->state == STOPPED)
-  {
-    TRACE("currently STOPPED, transitioning to PLAYING\n");
-    drv->state = PLAYING;
-  }
-
-  /* handle the case where the user calls this routine with 0 bytes */
-  if(bytes == 0 || frames_available < 1)
-  {
-    TRACE("no bytes in buffer\n");
-
-    TIMER("finish (nothing to do)\n");
-    releaseDriver(drv);
-    return 0;
-  }
-
-  frames = min(frames, frames_available);
-  long jack_bytes = frames * drv->bytes_per_jack_input_frame;
-  if(!ensure_buffer_size(&drv->rw_buffer1, &drv->rw_buffer1_size, jack_bytes))
-  {
-    ERR("couldn't allocate enough space for the buffer\n");
-    releaseDriver(drv);
-    return 0;
-  }
-
-  DEBUG("ringbuffer read space = %d, write space = %d\n",
-        jack_ringbuffer_read_space(drv->pRecPtr),
-        jack_ringbuffer_write_space(drv->pRecPtr));
-
-  jack_ringbuffer_read(drv->pRecPtr, drv->rw_buffer1,
-                       frames * drv->bytes_per_jack_input_frame);
-
-  DEBUG("ringbuffer read space = %d, write space = %d\n",
-        jack_ringbuffer_read_space(drv->pRecPtr),
-        jack_ringbuffer_write_space(drv->pRecPtr));
-
-  int i;
-  for(i = 0; i < drv->num_output_channels; i++)
-  {
-    /* apply volume to the floating value */
-    if(drv->volumeEffectType == dbAttenuation)
-    {
-      /* assume the volume setting is dB of attenuation, a volume of 0 */
-      /* is 0dB attenuation */
-      float volume = powf(10.0, -((float) drv->volume[i]) / 20.0);
-      float_volume_effect((sample_t *) drv->rw_buffer1 + i,
-                          frames, volume, drv->num_output_channels);
-    } else
-    {
-      float_volume_effect((sample_t *) drv->rw_buffer1 + i, frames,
-                          ((float) drv->volume[i] / 100.0),
-                          drv->num_output_channels);
-    }
-  }
-
-  /* convert from jack samples to client samples
-     we have to tell it how many samples there are, which is frames * channels */
-  switch (drv->bits_per_channel)
-  {
-  case 8:
-    sample_move_float_char((unsigned char *) data, (sample_t *) drv->rw_buffer1,
-                           frames * drv->num_input_channels);
-    break;
-  case 16:
-    sample_move_float_short((short *) data, (sample_t *) drv->rw_buffer1,
-                            frames * drv->num_input_channels);
-    break;
-  }
-
-  TIMER("finish\n");
-
-  long read_bytes = frames * drv->bytes_per_input_frame;
-
-  DEBUG("returning bytes read of %ld\n", bytes);
-
-  releaseDriver(drv);
-  return read_bytes;
-}
-
-/* return ERR_SUCCESS for success */
-static int
-JACK_SetVolumeForChannelFromDriver(jack_driver_t * drv,
-                                   unsigned int channel, unsigned int volume)
-{
-  /* TODO?: maybe we should have different volume levels for input & output */
-  /* ensure that we have the channel we are setting volume for */
-  if(channel > (drv->num_output_channels - 1))
-    return 1;
-
-  if(volume > 100)
-    volume = 100;               /* check for values in excess of max */
-
-  drv->volume[channel] = volume;
-  return ERR_SUCCESS;
-}
-
-/* return ERR_SUCCESS for success */
-int
-JACK_SetVolumeForChannel(int deviceID, unsigned int channel,
-                         unsigned int volume)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  int retval = JACK_SetVolumeForChannelFromDriver(drv, channel, volume);
-  releaseDriver(drv);
-  return retval;
-}
-
-/* Set the volume */
-/* return 0 for success */
-/* NOTE: we check for invalid volume values */
-int
-JACK_SetAllVolume(int deviceID, unsigned int volume)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  unsigned int i;
-
-  TRACE("deviceID(%d), setting volume of %d\n", deviceID, volume);
-
-  for(i = 0; i < drv->num_output_channels; i++)
-  {
-    if(JACK_SetVolumeForChannelFromDriver(drv, i, volume) != ERR_SUCCESS)
-    {
-      releaseDriver(drv);
-      return 1;
-    }
-  }
-
-  releaseDriver(drv);
-  return ERR_SUCCESS;
-}
-
-/* Return the current volume in the inputted pointers */
-/* NOTE: we check for null pointers being passed in just in case */
-void
-JACK_GetVolumeForChannel(int deviceID, unsigned int channel,
-                         unsigned int *volume)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-
-  /* ensure that we have the channel we are getting volume for */
-  if(channel > (drv->num_output_channels - 1))
-  {
-    ERR("asking for channel index %u but we only have %lu channels\n", channel, drv->num_output_channels);
-    releaseDriver(drv);
-    return;
-  }
-
-  if(volume)
-    *volume = drv->volume[channel];
-
-#if VERBOSE_OUTPUT
-  if(volume)
-  {
-    TRACE("deviceID(%d), returning volume of %d for channel %d\n",
-          deviceID, *volume, channel);
-  }
-  else
-  {
-    TRACE("volume is null, can't dereference it\n");
-  }
-#endif
-
-  releaseDriver(drv);
-}
-
-
-/* linear means 0 volume is silence, 100 is full volume */
-/* dbAttenuation means 0 volume is 0dB attenuation */
-/* Bio2jack defaults to linear */
-enum JACK_VOLUME_TYPE
-JACK_SetVolumeEffectType(int deviceID, enum JACK_VOLUME_TYPE type)
-{
-  enum JACK_VOLUME_TYPE retval;
-  jack_driver_t *drv = getDriver(deviceID);
-
-  TRACE("setting type of '%s'\n",
-        (type == dbAttenuation ? "dbAttenuation" : "linear"));
-
-  retval = drv->volumeEffectType;
-  drv->volumeEffectType = type;
-
-  releaseDriver(drv);
-  return retval;
-}
-
-
-/* Controls the state of the playback(playing, paused, ...) */
-int
-JACK_SetState(int deviceID, enum status_enum state)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-
-  switch (state)
-  {
-  case PAUSED:
-    drv->state = PAUSED;
-    break;
-  case PLAYING:
-    drv->state = PLAYING;
-    break;
-  case STOPPED:
-    drv->state = STOPPED;
-    break;
-  default:
-    TRACE("unknown state of %d\n", state);
-  }
-
-  TRACE("%s\n", DEBUGSTATE(drv->state));
-
-  releaseDriver(drv);
-  return 0;
-}
-
-/* Retrieve the current state of the device */
-enum status_enum
-JACK_GetState(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  enum status_enum return_val;
-
-  return_val = drv->state;
-  releaseDriver(drv);
-
-  TRACE("deviceID(%d), returning current state of %s\n", deviceID,
-        DEBUGSTATE(return_val));
-  return return_val;
-}
-
-/* Retrieve the number of bytes per second we are outputting */
-unsigned long
-JACK_GetOutputBytesPerSecondFromDriver(jack_driver_t * drv)
-{
-  unsigned long return_val;
-
-  return_val = drv->bytes_per_output_frame * drv->client_sample_rate;
-
-#if VERBOSE_OUTPUT
-  TRACE("deviceID(%d), return_val = %ld\n", drv->deviceID, return_val);
-#endif
-
-  return return_val;
-}
-
-/* Retrieve the number of bytes per second we are outputting */
-unsigned long
-JACK_GetOutputBytesPerSecond(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  unsigned long return_val;
-
-  return_val = JACK_GetOutputBytesPerSecondFromDriver(drv);
-  releaseDriver(drv);
-
-  return return_val;
-}
-
-/* Retrieve the number of input bytes(from jack) per second we are outputting
-   to the user of bio2jack */
-static long
-JACK_GetInputBytesPerSecondFromDriver(jack_driver_t * drv)
-{
-  long return_val;
-
-  return_val = drv->bytes_per_input_frame * drv->client_sample_rate;
-#if VERBOSE_OUTPUT
-  TRACE("drv->deviceID(%d), return_val = %ld\n", drv->deviceID, return_val);
-#endif
-
-  return return_val;
-}
-
-/* Retrieve the number of input bytes(from jack) per second we are outputting
-   to the user of bio2jack */
-unsigned long
-JACK_GetInputBytesPerSecond(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val = JACK_GetInputBytesPerSecondFromDriver(drv);
-  releaseDriver(drv);
-
-#if VERBOSE_OUTPUT
-  TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val);
-#endif
-
-  return return_val;
-}
-
-/* Return the number of bytes we have buffered thus far for output */
-/* NOTE: convert from output bytes to input bytes in here */
-static long
-JACK_GetBytesStoredFromDriver(jack_driver_t * drv)
-{
-  if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0)
-    return 0;
-
-  /* leave at least one frame in the buffer at all times to prevent underruns */
-  long return_val =
-    jack_ringbuffer_read_space(drv->pPlayPtr) - drv->jack_buffer_size;
-  if(return_val <= 0)
-  {
-    return_val = 0;
-  } else
-  {
-    /* adjust from jack bytes to client bytes */
-    return_val =
-      return_val / drv->bytes_per_jack_output_frame *
-      drv->bytes_per_output_frame;
-  }
-
-  return return_val;
-}
-
-/* An approximation of how many bytes we have to send out to jack */
-/* that is computed as if we were sending jack a continuous stream of */
-/* bytes rather than chunks during discrete callbacks.  */
-/* Return the number of bytes we have buffered thus far for output */
-/* NOTE: convert from output bytes to input bytes in here */
-unsigned long
-JACK_GetBytesStored(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long retval = JACK_GetBytesStoredFromDriver(drv);
-  releaseDriver(drv);
-  TRACE("deviceID(%d), retval = %ld\n", deviceID, retval);
-  return retval;
-}
-
-static unsigned long
-JACK_GetBytesFreeSpaceFromDriver(jack_driver_t * drv)
-{
-  if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0)
-    return 0;
-
-  /* leave at least one frame in the buffer at all times to prevent underruns */
-  long return_val = jack_ringbuffer_write_space(drv->pPlayPtr) - drv->jack_buffer_size;
-  if(return_val <= 0)
-  {
-    return_val = 0;
-  } else
-  {
-    /* adjust from jack bytes to client bytes */
-    return_val =
-      return_val / drv->bytes_per_jack_output_frame *
-      drv->bytes_per_output_frame;
-  }
-
-  return return_val;
-}
-
-/* Return the number of bytes we can write to the device */
-unsigned long
-JACK_GetBytesFreeSpace(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  unsigned long return_val;
-
-  return_val = JACK_GetBytesFreeSpaceFromDriver(drv);
-  releaseDriver(drv);
-
-  TRACE("deviceID(%d), retval == %ld\n", deviceID, return_val);
-
-  return return_val;
-}
-
-/* bytes of space used in the input buffer */
-unsigned long
-JACK_GetBytesUsedSpace(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val;
-
-  if(drv->pRecPtr == 0 || drv->bytes_per_jack_input_frame == 0)
-  {
-    return_val = 0;
-  } else
-  {
-    /* adjust from jack bytes to client bytes */
-    return_val =
-      jack_ringbuffer_read_space(drv->pRecPtr) /
-      drv->bytes_per_jack_input_frame * drv->bytes_per_input_frame;
-  }
-
-  releaseDriver(drv);
-
-  if(return_val < 0)
-    return_val = 0;
-  TRACE("deviceID(%d), retval == %ld\n", deviceID, return_val);
-
-  return return_val;
-}
-
-/* Get the current position of the driver, either in bytes or */
-/* in milliseconds */
-/* NOTE: this is position relative to input bytes, output bytes may differ greatly due to
-   input vs. output channel count */
-static long
-JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
-                           int type)
-{
-  long return_val = 0;
-  struct timeval now;
-  long elapsedMS;
-  double sec2msFactor = 1000;
-
-#if TRACE_ENABLE
-  char *type_str = "UNKNOWN type";
-#endif
-
-  /* if we are reset we should return a position of 0 */
-  if(drv->state == RESET)
-  {
-    TRACE("we are currently RESET, returning 0\n");
-    return 0;
-  }
-
-  if(type == WRITTEN)
-  {
-#if TRACE_ENABLE
-    type_str = "WRITTEN";
-#endif
-    return_val = drv->client_bytes;
-  } else if(type == WRITTEN_TO_JACK)
-  {
-#if TRACE_ENABLE
-    type_str = "WRITTEN_TO_JACK";
-#endif
-    return_val = drv->written_client_bytes;
-  } else if(type == PLAYED)       /* account for the elapsed time for the played_bytes */
-  {
-#if TRACE_ENABLE
-    type_str = "PLAYED";
-#endif
-    return_val = drv->played_client_bytes;
-    gettimeofday(&now, 0);
-
-    elapsedMS = TimeValDifference(&drv->previousTime, &now);    /* find the elapsed milliseconds since last JACK_Callback() */
-
-    TRACE("elapsedMS since last callback is '%ld'\n", elapsedMS);
-
-    /* account for the bytes played since the last JACK_Callback() */
-    /* NOTE: [Xms * (Bytes/Sec)] * (1 sec/1,000ms) */
-    /* NOTE: don't do any compensation if no data has been sent to jack since the last callback */
-    /* as this would result a bogus computed result */
-    if(drv->clientBytesInJack != 0)
-    {
-      return_val += (long) ((double) elapsedMS *
-                            ((double) JACK_GetOutputBytesPerSecondFromDriver(drv) /
-                             sec2msFactor));
-    } else
-    {
-      TRACE("clientBytesInJack == 0\n");
-    }
-  }
-
-  /* add on the offset */
-  return_val += drv->position_byte_offset;
-
-  /* convert byte position to milliseconds value if necessary */
-  if(position == MILLISECONDS)
-  {
-    if(JACK_GetOutputBytesPerSecondFromDriver(drv) != 0)
-    {
-      return_val = (long) (((double) return_val /
-                            (double) JACK_GetOutputBytesPerSecondFromDriver(drv)) *
-                           (double) sec2msFactor);
-    } else
-    {
-      return_val = 0;
-    }
-  }
-
-  TRACE("drv->deviceID(%d), type(%s), return_val = %ld\n", drv->deviceID,
-        type_str, return_val);
-
-  return return_val;
-}
-
-/* Get the current position of the driver, either in bytes or */
-/* in milliseconds */
-/* NOTE: this is position relative to input bytes, output bytes may differ greatly due to input vs. output channel count */
-long
-JACK_GetPosition(int deviceID, enum pos_enum position, int type)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long retval = JACK_GetPositionFromDriver(drv, position, type);
-  releaseDriver(drv);
-  TRACE("retval == %ld\n", retval);
-  return retval;
-}
-
-// Set position always applies to written bytes
-// NOTE: we must apply this instantly because if we pass this as a message
-//   to the callback we risk the user sending us audio data in the mean time
-//   and there is no need to send this as a message, we don't modify any
-//   internal variables
-void
-JACK_SetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
-                           long value)
-{
-  double sec2msFactor = 1000;
-#if TRACE_ENABLE
-  long input_value = value;
-#endif
-
-  /* convert the incoming value from milliseconds into bytes */
-  if(position == MILLISECONDS)
-  {
-    value = (long) (((double) value *
-                     (double) JACK_GetOutputBytesPerSecondFromDriver(drv)) /
-                    sec2msFactor);
-  }
-
-  /* ensure that if the user asks for the position */
-  /* they will at this instant get the correct position */
-  drv->position_byte_offset = value - drv->client_bytes;
-
-  TRACE("deviceID(%d) input_value of %ld %s, new value of %ld, setting position_byte_offset to %ld\n",
-        drv->deviceID, input_value, (position == MILLISECONDS) ? "ms" : "bytes",
-        value, drv->position_byte_offset);
-}
-
-// Set position always applies to written bytes
-// NOTE: we must apply this instantly because if we pass this as a message
-//   to the callback we risk the user sending us audio data in the mean time
-//   and there is no need to send this as a message, we don't modify any
-//   internal variables
-void
-JACK_SetPosition(int deviceID, enum pos_enum position, long value)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  JACK_SetPositionFromDriver(drv, position, value);
-  releaseDriver(drv);
-
-  TRACE("deviceID(%d) value of %ld\n", drv->deviceID, value);
-}
-
-/* Return the number of bytes per frame, or (output_channels * bits_per_channel) / 8 */
-unsigned long
-JACK_GetBytesPerOutputFrame(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val = drv->bytes_per_output_frame;
-  releaseDriver(drv);
-  TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val);
-  return return_val;
-}
-
-/* Return the number of bytes per frame, or (input_channels * bits_per_channel) / 8 */
-unsigned long
-JACK_GetBytesPerInputFrame(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val = drv->bytes_per_input_frame;
-  releaseDriver(drv);
-  TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val);
-  return return_val;
-}
-
-/* Return the number of output bytes we buffer max */
-long
-JACK_GetMaxOutputBufferedBytes(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val;
-
-  /* adjust from jack bytes to client bytes */
-  if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0)
-    return_val = 0;
-  else
-    return_val =
-      (jack_ringbuffer_read_space(drv->pPlayPtr) +
-       jack_ringbuffer_write_space(drv->pPlayPtr)) /
-      drv->bytes_per_jack_output_frame * drv->bytes_per_output_frame;
-
-  releaseDriver(drv);
-
-  TRACE("return_val = %ld\n", return_val);
-
-  return return_val;
-}
-
-/* Return the number of input bytes we buffer max */
-long
-JACK_GetMaxInputBufferedBytes(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val;
-
-  /* adjust from jack bytes to client bytes */
-  if(drv->pRecPtr == 0 || drv->bytes_per_jack_input_frame == 0)
-    return_val = 0;
-  else
-    return_val =
-      (jack_ringbuffer_read_space(drv->pRecPtr) +
-       jack_ringbuffer_write_space(drv->pRecPtr)) /
-      drv->bytes_per_jack_input_frame * drv->bytes_per_input_frame;
-
-  releaseDriver(drv);
-
-  TRACE("return_val = %ld\n", return_val);
-
-  return return_val;
-}
-
-/* Get the number of output channels */
-int
-JACK_GetNumOutputChannels(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  int return_val = drv->num_output_channels;
-  releaseDriver(drv);
-  TRACE("getting num_output_channels of %d\n", return_val);
-  return return_val;
-}
-
-/* Get the number of input channels */
-int
-JACK_GetNumInputChannels(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  int return_val = drv->num_input_channels;
-  releaseDriver(drv);
-  TRACE("getting num_input_channels of %d\n", return_val);
-  return return_val;
-}
-
-/* Get the number of samples per second, the sample rate */
-long
-JACK_GetSampleRate(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  int return_val = drv->client_sample_rate;
-  releaseDriver(drv);
-  TRACE("getting sample_rate of %d\n", return_val);
-  return return_val;
-}
-
-void
-JACK_CleanupDriver(jack_driver_t * drv)
-{
-  TRACE("\n");
-  /* things that need to be reset both in JACK_Init & JACK_CloseDevice */
-  drv->client = 0;
-  drv->in_use = FALSE;
-  drv->state = CLOSED;
-  drv->jack_sample_rate = 0;
-  drv->output_sample_rate_ratio = 1.0;
-  drv->input_sample_rate_ratio = 1.0;
-  drv->jackd_died = FALSE;
-  gettimeofday(&drv->previousTime, 0);  /* record the current time */
-  gettimeofday(&drv->last_reconnect_attempt, 0);
-}
-
-/* Initialize the jack porting library to a clean state */
-void
-JACK_Init(void)
-{
-  jack_driver_t *drv;
-  int x, y;
-
-  if(init_done)
-  {
-    TRACE("not initing twice\n");
-    return;
-  }
-
-  init_done = 1;
-
-  TRACE("\n");
-
-  pthread_mutex_lock(&device_mutex);
-
-  /* initialize the device structures */
-  for(x = 0; x < MAX_OUTDEVICES; x++)
-  {
-    drv = &outDev[x];
-
-    pthread_mutex_init(&drv->mutex, NULL);
-
-    getDriver(x);
-
-    memset(drv, 0, sizeof(jack_driver_t));
-    drv->volumeEffectType = linear;
-    drv->deviceID = x;
-
-    for(y = 0; y < MAX_OUTPUT_PORTS; y++)       /* make all volume 25% as a default */
-      drv->volume[y] = 25;
-
-    JACK_CleanupDriver(drv);
-    JACK_ResetFromDriver(drv);
-    releaseDriver(drv);
-  }
-
-  client_name = 0;              /* initialize the name to null */
-  do_sample_rate_conversion = TRUE;     /* default to on */
-  JACK_SetClientName("bio2jack");
-
-  pthread_mutex_unlock(&device_mutex);
-
-  TRACE("finished\n");
-}
-
-/* Get the latency, in frames, of jack */
-long
-JACK_GetJackOutputLatency(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val = 0;
-
-  if(drv->client && drv->num_output_channels)
-  {
-    /* Disclaimer: I have no experience with JACK and don't know if this is
-     * correct. -jlindgren */
-    jack_latency_range_t range;
-    jack_port_get_latency_range(drv->output_port[0], JackPlaybackLatency, & range);
-    return_val = (range.min + range.max) / 2;
-  }
-
-  TRACE("got latency of %ld frames\n", return_val);
-
-  releaseDriver(drv);
-  return return_val;
-}
-
-/* bytes that jack requests during each callback */
-unsigned long
-JACK_GetJackBufferedBytes(int deviceID)
-{
-  jack_driver_t *drv = getDriver(deviceID);
-  long return_val;
-
-  if(drv->bytes_per_jack_output_frame == 0)
-  {
-    return_val = 0;
-  } else
-  {
-    /* adjust from jack bytes to client bytes */
-    return_val =
-      drv->jack_buffer_size / drv->bytes_per_jack_output_frame *
-      drv->bytes_per_output_frame * drv->num_output_channels;
-  }
-
-  releaseDriver(drv);
-  return return_val;
-}
-
-/* value = TRUE, perform sample rate conversion */
-void
-JACK_DoSampleRateConversion(bool value)
-{
-  do_sample_rate_conversion = value;
-}
-
-/* FIXME: put the filename of the resample library header file with the decoders in here */
-/* consider mapping them in the bio2jack.h header file since its useless to the user unless */
-/* they can figure out wtf the settings on */
-void
-JACK_SetSampleRateConversionFunction(int converter)
-{
-  preferred_src_converter = converter;
-}
-
-/* set the client name that will be reported to jack when we open a */
-/* connection via JACK_OpenDevice() */
-void
-JACK_SetClientName(char *name)
-{
-  if(name)
-  {
-    if(client_name) g_free(client_name);
-
-    client_name = g_strdup(name);
-  }
-}
-
-void
-JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode)
-{
-    port_connection_mode = mode;
-}
diff --git a/src/jack/bio2jack.h b/src/jack/bio2jack.h
deleted file mode 100644
index cbb3b16f3fc4..000000000000
--- a/src/jack/bio2jack.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2003-2004 Chris Morgan <cmorgan at alum.wpi.edu>
- *
- * 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
- */
-
-#ifndef _H_JACK_OUT_H
-#define _H_JACK_OUT_H
-
-#include <jack/jack.h>
-
-#ifdef __cplusplus
-extern "C" {
-#else
-#define bool long
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define ERR_SUCCESS                           0
-#define ERR_OPENING_JACK                      1
-#define ERR_RATE_MISMATCH                     2
-#define ERR_BYTES_PER_OUTPUT_FRAME_INVALID    3
-#define ERR_BYTES_PER_INPUT_FRAME_INVALID     4
-#define ERR_TOO_MANY_OUTPUT_CHANNELS          5
-#define ERR_PORT_NAME_OUTPUT_CHANNEL_MISMATCH 6
-#define ERR_PORT_NOT_FOUND                    7
-#define ERR_TOO_MANY_INPUT_CHANNELS           8
-#define ERR_PORT_NAME_INPUT_CHANNEL_MISMATCH  9
-
-enum status_enum { PLAYING, PAUSED, STOPPED, CLOSED, RESET };
-enum pos_enum    { BYTES, MILLISECONDS };
-
-#define PLAYED          1 /* played out of the speakers(estimated value but should be close */
-#define WRITTEN_TO_JACK 2 /* amount written out to jack */
-#define WRITTEN         3 /* amount written to the bio2jack device */
-
-/**********************/
-/* External functions */
-void JACK_Init(void); /* call this before any other bio2jack calls */
-void JACK_DoSampleRateConversion(bool value); /* whether the next device that's Open()d should do
-                                                 sample rate conversion if necessary */
-void JACK_SetSampleRateConversionFunction(int converter); /* which SRC converter function should be used
-                                                             for the next Open()d device */
-int  JACK_Open(int *deviceID, unsigned int bits_per_channel, int floating_point,
-	       unsigned long *rate, int channels); /* Note: defaults to 0 input channels
-						      if you need input (record) use OpenEx
-						      instead */
-int  JACK_OpenEx(int *deviceID, unsigned int bits_per_channel,
-		 int floating_point, unsigned long *rate,
-                 unsigned int input_channels, unsigned int output_channels,
-                 const char **jack_port_name, unsigned int jack_port_name_count,
-                 unsigned long jack_port_flags);
-int  JACK_Close(int deviceID); /* return 0 for success */
-void JACK_Reset(int deviceID); /* free all buffered data and reset several values in the device */
-long JACK_Write(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes written */
-long JACK_Read(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes read */
-
-/* state setting values */
-/* set/get the written/played/buffered value based on a byte or millisecond input value */
-long JACK_GetPosition(int deviceID, enum pos_enum position, int type);
-void JACK_SetPosition(int deviceID, enum pos_enum position, long value);
-
-long JACK_GetJackLatency(int deviceID); /* deprectated, you probably want JACK_GetJackOutputLatency */
-long JACK_GetJackOutputLatency(int deviceID); /* return the output latency in frames */
-
-int JACK_SetState(int deviceID, enum status_enum state); /* playing, paused, stopped */
-enum status_enum JACK_GetState(int deviceID);
-
-long JACK_GetMaxOutputBufferedBytes(int deviceID);
-long JACK_GetMaxInputBufferedBytes(int deviceID);
-
-/* bytes that jack requests during each callback */
-unsigned long JACK_GetJackBufferedBytes(int deviceID);
-
-/* Properties of the jack driver */
-
-/* linear means 0 volume is silence, 100 is full volume */
-/* dbAttenuation means 0 volume is 0dB attenuation */
-/* Bio2jack defaults to linear */
-/* Note: volume controls only effect output channels for now */
-enum JACK_VOLUME_TYPE { linear, dbAttenuation };
-enum JACK_VOLUME_TYPE JACK_SetVolumeEffectType(int deviceID,
-                                               enum JACK_VOLUME_TYPE type);
-
-int  JACK_SetAllVolume(int deviceID, unsigned int volume); /* returns 0 on success */
-int  JACK_SetVolumeForChannel(int deviceID, unsigned int channel, unsigned int volume);
-void JACK_GetVolumeForChannel(int deviceID, unsigned int channel, unsigned int *volume);
-
-
-unsigned long JACK_GetOutputBytesPerSecond(int deviceID); /* bytes_per_output_frame * sample_rate */
-unsigned long JACK_GetInputBytesPerSecond(int deviceID);  /* bytes_per_input_frame * sample_rate */
-unsigned long JACK_GetBytesStored(int deviceID);          /* bytes currently buffered in the output buffer */
-unsigned long JACK_GetBytesFreeSpace(int deviceID);       /* bytes of free space in the output buffer */
-unsigned long JACK_GetBytesUsedSpace(int deviceID);       /* bytes of space used in the input buffer */
-unsigned long JACK_GetBytesPerOutputFrame(int deviceID);
-unsigned long JACK_GetBytesPerInputFrame(int deviceID);
-
-/* Note: these will probably be removed in a future release */
-int  JACK_GetNumInputChannels(int deviceID);
-int  JACK_GetNumOutputChannels(int deviceID);
-
-long JACK_GetSampleRate(int deviceID); /* samples per second */
-
-void JACK_SetClientName(char *name); /* sets the name that bio2jack will use when
-                                        creating a new jack client.  name_%pid%_%deviceID%%counter%
-                                        will be used
-                                        NOTE: this defaults to name = bio2jack
-                                        NOTE: we limit the size of the client name to
-                                           jack_client_name_size() */
-
-enum JACK_PORT_CONNECTION_MODE
-{
-    CONNECT_ALL,    /* connect to all avaliable ports */
-    CONNECT_OUTPUT, /* connect only to the ports we need for output */
-    CONNECT_NONE    /* don't connect to any ports */
-};
-
-/* set the mode for port connections */
-/* defaults to CONNECT_ALL */
-void JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* #ifndef JACK_OUT_H */
diff --git a/src/jack/jack.c b/src/jack/jack.c
deleted file mode 100644
index b5c1b987b05b..000000000000
--- a/src/jack/jack.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*      xmms - jack output plugin
- *    Copyright 2002 Chris Morgan<cmorgan at alum.wpi.edu>
- *
- *      audacious port (2005-2006) by Giacomo Lozito from develia.org
- *
- *    This code maps xmms calls into the jack translation library
- */
-
-#include <dlfcn.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#include "bio2jack.h" /* includes for the bio2jack library */
-#include "jack.h"
-
-/* set to 1 for verbose output */
-#define VERBOSE_OUTPUT          0
-
-jackconfig jack_cfg;
-
-#define OUTFILE stderr
-
-#define TRACE(...)                                      \
-    if(jack_cfg.isTraceEnabled) {                       \
-        fprintf(OUTFILE, "%s:", __FUNCTION__),          \
-        fprintf(OUTFILE, __VA_ARGS__),                    \
-        fflush(OUTFILE);                                \
-    }
-
-#define ERR(...)                                        \
-    if(jack_cfg.isTraceEnabled) {                       \
-        fprintf(OUTFILE, "ERR: %s:", __FUNCTION__),     \
-        fprintf(OUTFILE, __VA_ARGS__),                    \
-        fflush(OUTFILE);                                \
-    }
-
-
-static int driver = 0; /* handle to the jack output device */
-
-typedef struct format_info {
-  int format;
-  long    frequency;
-  int     channels;
-  long    bps;
-} format_info_t;
-
-static format_info_t input;
-static format_info_t effect;
-static format_info_t output;
-
-static bool_t output_opened; /* true if we have a connection to jack */
-static bool_t paused;
-
-
-/* Giacomo's note: removed the destructor from the original xmms-jack, cause
-   destructors + thread join + NPTL currently leads to problems; solved this
-   by adding a cleanup function callback for output plugins in Audacious, this
-   is used to close the JACK connection and to perform a correct shutdown */
-static void jack_cleanup(void)
-{
-  int errval;
-  TRACE("cleanup\n");
-
-  if((errval = JACK_Close(driver)))
-    ERR("error closing device, errval of %d\n", errval);
-
-  return;
-}
-
-
-/* Set the volume */
-static void jack_set_volume(int l, int r)
-{
-  if(output.channels == 1)
-  {
-    TRACE("l(%d)\n", l);
-  } else if(output.channels > 1)
-  {
-    TRACE("l(%d), r(%d)\n", l, r);
-  }
-
-  if(output.channels > 0) {
-      JACK_SetVolumeForChannel(driver, 0, l);
-      jack_cfg.volume_left = l;
-  }
-  if(output.channels > 1) {
-      JACK_SetVolumeForChannel(driver, 1, r);
-      jack_cfg.volume_right = r;
-  }
-}
-
-
-/* Get the current volume setting */
-static void jack_get_volume(int *l, int *r)
-{
-  unsigned int _l, _r;
-
-  if(output.channels > 0)
-  {
-      JACK_GetVolumeForChannel(driver, 0, &_l);
-      (*l) = _l;
-  }
-  if(output.channels > 1)
-  {
-      JACK_GetVolumeForChannel(driver, 1, &_r);
-      (*r) = _r;
-  }
-
-#if VERBOSE_OUTPUT
-  if(output.channels == 1)
-      TRACE("l(%d)\n", *l);
-  else if(output.channels > 1)
-      TRACE("l(%d), r(%d)\n", *l, *r);
-#endif
-}
-
-
-/* Return the current number of milliseconds of audio data that has */
-/* been played out of the audio device, not including the buffer */
-static int jack_get_output_time(void)
-{
-  int return_val;
-
-  /* don't try to get any values if the device is still closed */
-  if(JACK_GetState(driver) == CLOSED)
-    return_val = 0;
-  else
-    return_val = JACK_GetPosition(driver, MILLISECONDS, PLAYED); /* get played position in terms of milliseconds */
-
-  TRACE("returning %d milliseconds\n", return_val);
-  return return_val;
-}
-
-
-/* returns TRUE if we are currently playing */
-/* NOTE: this was confusing at first BUT, if the device is open and there */
-/* is no more audio to be played, then the device is NOT PLAYING */
-#if 0
-static int jack_playing(void)
-{
-  int return_val;
-
-  /* If we are playing see if we ACTUALLY have something to play */
-  if(JACK_GetState(driver) == PLAYING)
-  {
-    /* If we have zero bytes stored, we are done playing */
-    if(JACK_GetBytesStored(driver) == 0)
-      return_val = FALSE;
-    else
-      return_val = TRUE;
-  }
-  else
-    return_val = FALSE;
-
-  TRACE("returning %d\n", return_val);
-  return return_val;
-}
-#endif
-
-void jack_set_port_connection_mode()
-{
-  /* setup the port connection mode that determines how bio2jack will connect ports */
-  char * mode_str = aud_get_str ("jack", "port_connection_mode");
-  enum JACK_PORT_CONNECTION_MODE mode;
-
-  if(strcmp(mode_str, "CONNECT_ALL") == 0)
-      mode = CONNECT_ALL;
-  else if(strcmp(mode_str, "CONNECT_OUTPUT") == 0)
-      mode = CONNECT_OUTPUT;
-  else if(strcmp(mode_str, "CONNECT_NONE") == 0)
-      mode = CONNECT_NONE;
-  else
-  {
-      TRACE("Defaulting to CONNECT_ALL");
-      mode = CONNECT_ALL;
-  }
-
-  JACK_SetPortConnectionMode(mode);
-  str_unref (mode_str);
-}
-
-static const char * const jack_defaults[] = {
- "isTraceEnabled", "FALSE",
- "port_connection_mode", "CONNECT_ALL",
- "volume_left", "25",
- "volume_right", "25",
- NULL};
-
-static const ComboBoxElements mode_list[] = {
- {"CONNECT_ALL", N_("Connect to all available jack ports")},
- {"CONNECT_OUTPUT", N_("Connect only the output ports")},
- {"CONNECT_NONE", N_("Don't connect to any port")},
-};
-
-static const PreferencesWidget jack_widgets[] = {
- {WIDGET_COMBO_BOX, N_("Connection mode:"),
-  .cfg_type = VALUE_STRING, .csect = "jack", .cname = "port_connection_mode",
-  .data.combo = {mode_list, ARRAY_LEN (mode_list)}},
- {WIDGET_CHK_BTN, N_("Enable debug printing"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "jack", .cname = "isTraceEnabled"},
-};
-
-static const PluginPreferences jack_prefs = {
- .widgets = jack_widgets,
- .n_widgets = ARRAY_LEN (jack_widgets)
-};
-
-/* Initialize necessary things */
-static bool_t jack_init (void)
-{
-  aud_config_set_defaults ("jack", jack_defaults);
-
-  jack_cfg.isTraceEnabled = aud_get_bool ("jack", "isTraceEnabled");
-  jack_cfg.volume_left = aud_get_int ("jack", "volume_left");
-  jack_cfg.volume_right = aud_get_int ("jack", "volume_right");
-
-  TRACE("initializing\n");
-  JACK_Init(); /* initialize the driver */
-
-  /* set the bio2jack name so users will see xmms-jack in their */
-  /* jack client list */
-  JACK_SetClientName("audacious-jack");
-
-  /* set the port connection mode */
-  jack_set_port_connection_mode();
-
-  output_opened = FALSE;
-
-  /* Always return OK, as we don't know about physical devices here */
-  return TRUE;
-}
-
-
-/* Return the amount of data that can be written to the device */
-static int audacious_jack_free(void)
-{
-  unsigned long return_val = JACK_GetBytesFreeSpace(driver);
-  unsigned long tmp;
-
-  /* adjust for frequency differences, otherwise xmms could send us */
-  /* as much data as we have free, then we go to convert this to */
-  /* the output frequency and won't have enough space, so adjust */
-  /* by the ratio of the two */
-  if(effect.frequency != output.frequency)
-  {
-    tmp = return_val;
-    return_val = (return_val * effect.frequency) / output.frequency;
-    TRACE("adjusting from %lu to %lu free bytes to compensate for frequency differences\n", tmp, return_val);
-  }
-
-  if(return_val > INT_MAX)
-  {
-      TRACE("Warning: return_val > INT_MAX\n");
-      return_val = INT_MAX;
-  }
-
-  TRACE("free space of %lu bytes\n", return_val);
-
-  return return_val;
-}
-
-
-/* Close the device */
-static void jack_close(void)
-{
-  aud_set_int ("jack", "volume_left", jack_cfg.volume_left);
-  aud_set_int ("jack", "volume_right", jack_cfg.volume_right);
-
-  JACK_Reset(driver); /* flush buffers, reset position and set state to STOPPED */
-  TRACE("resetting driver, not closing now, destructor will close for us\n");
-}
-
-
-/* Open the device up */
-static int jack_open(int fmt, int sample_rate, int num_channels)
-{
-  int bits_per_sample;
-  int floating_point = FALSE;
-  int retval;
-  unsigned long rate;
-
-  TRACE("fmt == %d, sample_rate == %d, num_channels == %d\n",
-    fmt, sample_rate, num_channels);
-
-  if((fmt == FMT_U8) || (fmt == FMT_S8))
-  {
-    bits_per_sample = 8;
-  } else if(fmt == FMT_S16_NE)
-  {
-    bits_per_sample = 16;
-  } else if (fmt == FMT_S24_NE)
-  {
-    /* interpreted by bio2jack as 24 bit values packed to 32 bit samples */
-    bits_per_sample = 24;
-  } else if (fmt == FMT_S32_NE)
-  {
-    bits_per_sample = 32;
-  } else if (fmt == FMT_FLOAT)
-  {
-    bits_per_sample = 32;
-    floating_point = TRUE;
-  } else {
-    TRACE("sample format not supported\n");
-    return 0;
-  }
-
-  /* record some useful information */
-  input.format    = fmt;
-  input.frequency = sample_rate;
-  input.bps       = bits_per_sample * sample_rate * num_channels;
-  input.channels  = num_channels;
-
-  /* setup the effect as matching the input format */
-  effect.format    = input.format;
-  effect.frequency = input.frequency;
-  effect.channels  = input.channels;
-  effect.bps       = input.bps;
-
-  /* if we are already opened then don't open again */
-  if(output_opened)
-  {
-    /* if something has changed we should close and re-open the connect to jack */
-    if((output.channels != input.channels) ||
-       (output.frequency != input.frequency) ||
-       (output.format != input.format))
-    {
-      TRACE("output.channels is %d, jack_open called with %d channels\n", output.channels, input.channels);
-      TRACE("output.frequency is %ld, jack_open called with %ld\n", output.frequency, input.frequency);
-      TRACE("output.format is %d, jack_open called with %d\n", output.format, input.format);
-      jack_close();
-      JACK_Close(driver);
-    } else
-    {
-        TRACE("output_opened is TRUE and no options changed, not reopening\n");
-        paused = FALSE;
-        return 1;
-    }
-  }
-
-  /* try to open the jack device with the requested rate at first */
-  output.frequency = input.frequency;
-  output.bps       = input.bps;
-  output.channels  = input.channels;
-  output.format    = input.format;
-
-  rate = output.frequency;
-  retval = JACK_Open(&driver, bits_per_sample, floating_point, &rate, output.channels);
-  output.frequency = rate; /* avoid compile warning as output.frequency differs in type
-                              from what JACK_Open() wants for the type of the rate parameter */
-  if(retval == ERR_RATE_MISMATCH)
-  {
-    TRACE("set the resampling rate properly");
-    return 0;
-  } else if(retval != ERR_SUCCESS)
-  {
-    TRACE("failed to open jack with JACK_Open(), error %d\n", retval);
-    return 0;
-  }
-
-  jack_set_volume(jack_cfg.volume_left, jack_cfg.volume_right); /* sets the volume to stored value */
-  output_opened = TRUE;
-  paused = FALSE;
-
-  return 1;
-}
-
-
-/* write some audio out to the device */
-static void jack_write(void * ptr, int length)
-{
-  long written;
-
-  TRACE("starting length of %d\n", length);
-
-  /* loop until we have written all the data out to the jack device */
-  /* this is due to xmms' audio driver api */
-  char *buf = (char*)ptr;
-  while(length > 0)
-  {
-    TRACE("writing %d bytes\n", length);
-    written = JACK_Write(driver, (unsigned char*)buf, length);
-    length-=written;
-    buf+=written;
-  }
-  TRACE("finished\n");
-}
-
-
-/* Flush any output currently buffered */
-/* and set the number of bytes written based on ms_offset_time, */
-/* the number of milliseconds of offset passed in */
-/* This is done so the driver itself keeps track of */
-/* current playing position of the mp3 */
-static void jack_flush(int ms_offset_time)
-{
-  TRACE("setting values for ms_offset_time of %d\n", ms_offset_time);
-
-  JACK_Reset(driver); /* flush buffers and set state to STOPPED */
-
-  /* update the internal driver values to correspond to the input time given */
-  JACK_SetPosition(driver, MILLISECONDS, ms_offset_time);
-
-  if (paused)
-    JACK_SetState(driver, PAUSED);
-  else
-    JACK_SetState(driver, PLAYING);
-}
-
-
-/* Pause the jack device */
-static void jack_pause (bool_t p)
-{
-  TRACE("p == %d\n", p);
-
-  paused = p;
-
-  /* pause the device if p is non-zero, unpause the device if p is zero and */
-  /* we are currently paused */
-  if(p)
-    JACK_SetState(driver, PAUSED);
-  else if(JACK_GetState(driver) == PAUSED)
-    JACK_SetState(driver, PLAYING);
-}
-
-static const char jack_about[] =
- N_("Based on xmms-jack, by Chris Morgan:\n"
-    "http://xmms-jack.sourceforge.net/\n\n"
-    "Ported to Audacious by Giacomo Lozito");
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("JACK Output"),
-    .domain = PACKAGE,
-    .about_text = jack_about,
-    .init = jack_init,
-    .cleanup = jack_cleanup,
-    .prefs = & jack_prefs,
-    .get_volume = jack_get_volume,
-    .set_volume = jack_set_volume,
-    .open_audio = jack_open,
-    .write_audio = jack_write,
-    .close_audio = jack_close,
-    .flush = jack_flush,
-    .pause = jack_pause,
-    .buffer_free = audacious_jack_free,
-    .output_time = jack_get_output_time
-)
diff --git a/src/jack/jack.h b/src/jack/jack.h
deleted file mode 100644
index 17131ba0008a..000000000000
--- a/src/jack/jack.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _JACK_H
-#define _JACK_H
-
-#include <libaudcore/core.h>
-
-void jack_configure(void);
-
-typedef struct
-{
-    bool_t isTraceEnabled; /* if true we will print debug information to the console */
-    int volume_left, volume_right; /* for loading the stored volume setting */
-} jackconfig;
-
-void jack_set_port_connection_mode(); /* called by jack_init() and the 'ok' handler in configure.c */
-
-#endif /* #ifndef _JACK_H */
diff --git a/src/ladspa/Makefile b/src/ladspa/Makefile
index 797bfe664ea5..1bbf746e7730 100644
--- a/src/ladspa/Makefile
+++ b/src/ladspa/Makefile
@@ -1,15 +1,17 @@
 PLUGIN = ladspa${PLUGIN_SUFFIX}
 
-SRCS = effect.c \
-       loaded-list.c \
-       plugin.c \
-       plugin-list.c
+SRCS = effect.cc \
+       loaded-list.cc \
+       plugin.cc \
+       plugin-list.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${GTK_CFLAGS} ${GMODULE_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += -lm ${GTK_LIBS} ${GMODULE_LIBS}
+LIBS += -lm ${GTK_LIBS} ${GMODULE_LIBS} -laudgui
diff --git a/src/ladspa/effect.c b/src/ladspa/effect.c
deleted file mode 100644
index 5d60c95d63e4..000000000000
--- a/src/ladspa/effect.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * LADSPA Host for Audacious
- * Copyright 2011 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 <assert.h>
-#include <stdio.h>
-
-#include "ladspa.h"
-#include "plugin.h"
-
-static int ladspa_channels, ladspa_rate;
-
-static void start_plugin (LoadedPlugin * loaded)
-{
-    if (loaded->active)
-        return;
-
-    loaded->active = 1;
-
-    PluginData * plugin = loaded->plugin;
-    const LADSPA_Descriptor * desc = plugin->desc;
-
-    int ports = plugin->in_ports->len;
-
-    if (ports == 0 || ports != plugin->out_ports->len)
-    {
-        fprintf (stderr, "Plugin has unusable port configuration: %s\n", desc->Name);
-        return;
-    }
-
-    if (ladspa_channels % ports != 0)
-    {
-        fprintf (stderr, "Plugin cannot be used with %d channels: %s\n",
-         ladspa_channels, desc->Name);
-        return;
-    }
-
-    int instances = ladspa_channels / ports;
-
-    loaded->instances = index_new ();
-    loaded->in_bufs = g_malloc (sizeof (float *) * ladspa_channels);
-    loaded->out_bufs = g_malloc (sizeof (float *) * ladspa_channels);
-
-    for (int i = 0; i < instances; i ++)
-    {
-        LADSPA_Handle handle = desc->instantiate (desc, ladspa_rate);
-        index_insert (loaded->instances, -1, handle);
-
-        int controls = index_count (plugin->controls);
-        for (int c = 0; c < controls; c ++)
-        {
-            ControlData * control = index_get (plugin->controls, c);
-            desc->connect_port (handle, control->port, & loaded->values[c]);
-        }
-
-        for (int p = 0; p < ports; p ++)
-        {
-            int channel = ports * i + p;
-
-            float * in = g_malloc (sizeof (float) * LADSPA_BUFLEN);
-            loaded->in_bufs[channel] = in;
-            int in_port = g_array_index (plugin->in_ports, int, p);
-            desc->connect_port (handle, in_port, in);
-
-            float * out = g_malloc (sizeof (float) * LADSPA_BUFLEN);
-            loaded->out_bufs[channel] = out;
-            int out_port = g_array_index (plugin->out_ports, int, p);
-            desc->connect_port (handle, out_port, out);
-        }
-
-        if (desc->activate)
-            desc->activate (handle);
-    }
-}
-
-static void run_plugin (LoadedPlugin * loaded, float * data, int samples)
-{
-    if (! loaded->instances)
-        return;
-
-    PluginData * plugin = loaded->plugin;
-    const LADSPA_Descriptor * desc = plugin->desc;
-
-    int ports = plugin->in_ports->len;
-    int instances = index_count (loaded->instances);
-    assert (ports * instances == ladspa_channels);
-
-    while (samples / ladspa_channels > 0)
-    {
-        int frames = MIN (samples / ladspa_channels, LADSPA_BUFLEN);
-
-        for (int i = 0; i < instances; i ++)
-        {
-            LADSPA_Handle * handle = index_get (loaded->instances, i);
-
-            for (int p = 0; p < ports; p ++)
-            {
-                int channel = ports * i + p;
-                float * get = data + channel;
-                float * in = loaded->in_bufs[channel];
-                float * in_end = in + frames;
-
-                while (in < in_end)
-                {
-                    * in ++ = * get;
-                    get += ladspa_channels;
-                }
-            }
-
-            desc->run (handle, frames);
-
-            for (int p = 0; p < ports; p ++)
-            {
-                int channel = ports * i + p;
-                float * set = data + channel;
-                float * out = loaded->out_bufs[channel];
-                float * out_end = out + frames;
-
-                while (out < out_end)
-                {
-                    * set = * out ++;
-                    set += ladspa_channels;
-                }
-            }
-        }
-
-        data += ladspa_channels * frames;
-        samples -= ladspa_channels * frames;
-    }
-}
-
-static void flush_plugin (LoadedPlugin * loaded)
-{
-    if (! loaded->instances)
-        return;
-
-    PluginData * plugin = loaded->plugin;
-    const LADSPA_Descriptor * desc = plugin->desc;
-
-    int instances = index_count (loaded->instances);
-    for (int i = 0; i < instances; i ++)
-    {
-        LADSPA_Handle * handle = index_get (loaded->instances, i);
-
-        if (desc->deactivate)
-            desc->deactivate (handle);
-        if (desc->activate)
-            desc->activate (handle);
-    }
-}
-
-void shutdown_plugin_locked (LoadedPlugin * loaded)
-{
-    loaded->active = 0;
-
-    if (! loaded->instances)
-        return;
-
-    PluginData * plugin = loaded->plugin;
-    const LADSPA_Descriptor * desc = plugin->desc;
-
-    int instances = index_count (loaded->instances);
-    for (int i = 0; i < instances; i ++)
-    {
-        LADSPA_Handle * handle = index_get (loaded->instances, i);
-
-        if (desc->deactivate)
-            desc->deactivate (handle);
-
-        desc->cleanup (handle);
-    }
-
-    for (int channel = 0; channel < ladspa_channels; channel ++)
-    {
-        g_free (loaded->in_bufs[channel]);
-        g_free (loaded->out_bufs[channel]);
-    }
-
-    index_free (loaded->instances);
-    loaded->instances = NULL;
-    g_free (loaded->in_bufs);
-    loaded->in_bufs = NULL;
-    g_free (loaded->out_bufs);
-    loaded->out_bufs = NULL;
-}
-
-void ladspa_start (int * channels, int * rate)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        shutdown_plugin_locked (loaded);
-    }
-
-    ladspa_channels = * channels;
-    ladspa_rate = * rate;
-
-    pthread_mutex_unlock (& mutex);
-}
-
-void ladspa_process (float * * data, int * samples)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        start_plugin (loaded);
-        run_plugin (loaded, * data, * samples);
-    }
-
-    pthread_mutex_unlock (& mutex);
-}
-
-void ladspa_flush (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        flush_plugin (loaded);
-    }
-
-    pthread_mutex_unlock (& mutex);
-}
-
-void ladspa_finish (float * * data, int * samples)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        start_plugin (loaded);
-        run_plugin (loaded, * data, * samples);
-        shutdown_plugin_locked (loaded);
-    }
-
-    pthread_mutex_unlock (& mutex);
-}
diff --git a/src/ladspa/effect.cc b/src/ladspa/effect.cc
new file mode 100644
index 000000000000..ced1737018b1
--- /dev/null
+++ b/src/ladspa/effect.cc
@@ -0,0 +1,241 @@
+/*
+ * LADSPA Host for Audacious
+ * Copyright 2011 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 <assert.h>
+
+#include "ladspa.h"
+#include "plugin.h"
+
+#include <libaudcore/runtime.h>
+
+static int ladspa_channels, ladspa_rate;
+
+static void start_plugin (LoadedPlugin & loaded)
+{
+    if (loaded.active)
+        return;
+
+    loaded.active = 1;
+
+    PluginData & plugin = loaded.plugin;
+    const LADSPA_Descriptor & desc = plugin.desc;
+
+    int ports = plugin.in_ports.len ();
+
+    if (ports == 0 || ports != plugin.out_ports.len ())
+    {
+        AUDERR ("Plugin has unusable port configuration: %s\n", desc.Name);
+        return;
+    }
+
+    if (ladspa_channels % ports != 0)
+    {
+        AUDERR ("Plugin cannot be used with %d channels: %s\n",
+         ladspa_channels, desc.Name);
+        return;
+    }
+
+    int instances = ladspa_channels / ports;
+
+    loaded.in_bufs.insert (0, ladspa_channels);
+    loaded.out_bufs.insert (0, ladspa_channels);
+
+    for (int i = 0; i < instances; i ++)
+    {
+        LADSPA_Handle handle = desc.instantiate (& desc, ladspa_rate);
+        loaded.instances.append (handle);
+
+        int controls = plugin.controls.len ();
+        for (int c = 0; c < controls; c ++)
+            desc.connect_port (handle, plugin.controls[c].port, & loaded.values[c]);
+
+        for (int p = 0; p < ports; p ++)
+        {
+            int channel = ports * i + p;
+
+            Index<float> & in = loaded.in_bufs[channel];
+            in.insert (0, LADSPA_BUFLEN);
+            desc.connect_port (handle, plugin.in_ports[p], in.begin ());
+
+            Index<float> & out = loaded.out_bufs[channel];
+            out.insert (0, LADSPA_BUFLEN);
+            desc.connect_port (handle, plugin.out_ports[p], out.begin ());
+        }
+
+        if (desc.activate)
+            desc.activate (handle);
+    }
+}
+
+static void run_plugin (LoadedPlugin & loaded, float * data, int samples)
+{
+    if (! loaded.instances.len ())
+        return;
+
+    PluginData & plugin = loaded.plugin;
+    const LADSPA_Descriptor & desc = plugin.desc;
+
+    int ports = plugin.in_ports.len ();
+    int instances = loaded.instances.len ();
+    assert (ports * instances == ladspa_channels);
+
+    while (samples / ladspa_channels > 0)
+    {
+        int frames = aud::min (samples / ladspa_channels, LADSPA_BUFLEN);
+
+        for (int i = 0; i < instances; i ++)
+        {
+            LADSPA_Handle handle = loaded.instances[i];
+
+            for (int p = 0; p < ports; p ++)
+            {
+                int channel = ports * i + p;
+                float * get = data + channel;
+                float * in = loaded.in_bufs[channel].begin ();
+                float * in_end = in + frames;
+
+                while (in < in_end)
+                {
+                    * in ++ = * get;
+                    get += ladspa_channels;
+                }
+            }
+
+            desc.run (handle, frames);
+
+            for (int p = 0; p < ports; p ++)
+            {
+                int channel = ports * i + p;
+                float * set = data + channel;
+                float * out = loaded.out_bufs[channel].begin ();
+                float * out_end = out + frames;
+
+                while (out < out_end)
+                {
+                    * set = * out ++;
+                    set += ladspa_channels;
+                }
+            }
+        }
+
+        data += ladspa_channels * frames;
+        samples -= ladspa_channels * frames;
+    }
+}
+
+static void flush_plugin (LoadedPlugin & loaded)
+{
+    if (! loaded.instances.len ())
+        return;
+
+    PluginData & plugin = loaded.plugin;
+    const LADSPA_Descriptor & desc = plugin.desc;
+
+    int instances = loaded.instances.len ();
+    for (int i = 0; i < instances; i ++)
+    {
+        LADSPA_Handle handle = loaded.instances[i];
+
+        if (desc.deactivate)
+            desc.deactivate (handle);
+        if (desc.activate)
+            desc.activate (handle);
+    }
+}
+
+void shutdown_plugin_locked (LoadedPlugin & loaded)
+{
+    loaded.active = 0;
+
+    if (! loaded.instances.len ())
+        return;
+
+    PluginData & plugin = loaded.plugin;
+    const LADSPA_Descriptor & desc = plugin.desc;
+
+    int instances = loaded.instances.len ();
+    for (int i = 0; i < instances; i ++)
+    {
+        LADSPA_Handle handle = loaded.instances[i];
+
+        if (desc.deactivate)
+            desc.deactivate (handle);
+
+        desc.cleanup (handle);
+    }
+
+    loaded.instances.clear ();
+    loaded.in_bufs.clear ();
+    loaded.out_bufs.clear ();
+}
+
+void LADSPAHost::start (int & channels, int & rate)
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & loaded : loadeds)
+        shutdown_plugin_locked (* loaded);
+
+    ladspa_channels = channels;
+    ladspa_rate = rate;
+
+    pthread_mutex_unlock (& mutex);
+}
+
+Index<float> & LADSPAHost::process (Index<float> & data)
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & loaded : loadeds)
+    {
+        start_plugin (* loaded);
+        run_plugin (* loaded, data.begin (), data.len ());
+    }
+
+    pthread_mutex_unlock (& mutex);
+    return data;
+}
+
+bool LADSPAHost::flush (bool force)
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & loaded : loadeds)
+        flush_plugin (* loaded);
+
+    pthread_mutex_unlock (& mutex);
+    return true;
+}
+
+Index<float> & LADSPAHost::finish (Index<float> & data, bool end_of_playlist)
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & loaded : loadeds)
+    {
+        start_plugin (* loaded);
+        run_plugin (* loaded, data.begin (), data.len ());
+
+        if (end_of_playlist)
+            shutdown_plugin_locked (* loaded);
+    }
+
+    pthread_mutex_unlock (& mutex);
+    return data;
+}
diff --git a/src/ladspa/ladspa.h b/src/ladspa/ladspa.h
index b1a9c4e59530..58e37ab7b7be 100644
--- a/src/ladspa/ladspa.h
+++ b/src/ladspa/ladspa.h
@@ -16,7 +16,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    USA. */
 
 #ifndef LADSPA_INCLUDED
@@ -356,7 +356,7 @@ typedef struct _LADSPA_PortRangeHint {
 /* Plugin Handles:
 
    This plugin handle indicates a particular instance of the plugin
-   concerned. It is valid to compare this to NULL (0 for C++) but
+   concerned. It is valid to compare this to nullptr (0 for C++) but
    otherwise the host should not attempt to interpret it. The plugin
    may use it to reference internal instance data. */
 
@@ -393,7 +393,7 @@ typedef struct _LADSPA_Descriptor {
   const char * Name;
 
   /* This member points to the null-terminated string indicating the
-     maker of the plugin. This can be an empty string but not NULL. */
+     maker of the plugin. This can be an empty string but not nullptr. */
   const char * Maker;
 
   /* This member points to the null-terminated string indicating any
@@ -429,7 +429,7 @@ typedef struct _LADSPA_Descriptor {
      handle is returned indicating the new plugin instance. The
      instantiation function accepts a sample rate as a parameter. The
      plugin descriptor from which this instantiate function was found
-     must also be passed. This function must return NULL if
+     must also be passed. This function must return nullptr if
      instantiation fails.
 
      Note that instance initialisation should generally occur in
@@ -475,7 +475,7 @@ typedef struct _LADSPA_Descriptor {
      information dependent on the history of the plugin instance
      except for any data locations provided by connect_port() and any
      gain set by set_run_adding_gain(). If there is nothing for
-     activate() to do then the plugin writer may provide a NULL rather
+     activate() to do then the plugin writer may provide a nullptr rather
      than an empty function.
 
      When present, hosts must call this function once before run() (or
@@ -516,7 +516,7 @@ typedef struct _LADSPA_Descriptor {
      addition.
 
      run_adding() is optional. When it is not provided by a plugin,
-     this function pointer must be set to NULL. When it is provided,
+     this function pointer must be set to nullptr. When it is provided,
      the function set_run_adding_gain() must be provided also. */
   void (*run_adding)(LADSPA_Handle Instance,
                      unsigned long SampleCount);
@@ -529,13 +529,13 @@ typedef struct _LADSPA_Descriptor {
 
      This function should be provided by the plugin if and only if the
      run_adding() function is provided. When it is absent this
-     function pointer must be set to NULL. */
+     function pointer must be set to nullptr. */
   void (*set_run_adding_gain)(LADSPA_Handle Instance,
                               LADSPA_Data   Gain);
 
   /* This is the counterpart to activate() (see above). If there is
      nothing for deactivate() to do then the plugin writer may provide
-     a NULL rather than an empty function.
+     a nullptr rather than an empty function.
 
      Hosts must deactivate all activated units after they have been
      run() (or run_adding()) for the last time. This call should be
@@ -583,8 +583,8 @@ typedef struct _LADSPA_Descriptor {
 
    Plugin types are accessed by index (not ID) using values from 0
    upwards. Out of range indexes must result in this function
-   returning NULL, so the plugin count can be determined by checking
-   for the least index that results in NULL being returned. */
+   returning nullptr, so the plugin count can be determined by checking
+   for the least index that results in nullptr being returned. */
 
 const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
 
diff --git a/src/ladspa/loaded-list.c b/src/ladspa/loaded-list.c
deleted file mode 100644
index 89d65caa0fe5..000000000000
--- a/src/ladspa/loaded-list.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * LADSPA Host for Audacious
- * Copyright 2011 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 <libaudgui/list.h>
-
-#include "plugin.h"
-
-static void get_value (void * user, int row, int column, GValue * value)
-{
-    g_return_if_fail (row >= 0 && row < index_count (loadeds));
-    g_return_if_fail (column == 0);
-
-    LoadedPlugin * loaded = index_get (loadeds, row);
-    g_value_set_string (value, loaded->plugin->desc->Name);
-}
-
-static int get_selected (void * user, int row)
-{
-    g_return_val_if_fail (row >= 0 && row < index_count (loadeds), 0);
-
-    LoadedPlugin * loaded = index_get (loadeds, row);
-    return loaded->selected;
-}
-
-static void set_selected (void * user, int row, int selected)
-{
-    g_return_if_fail (row >= 0 && row < index_count (loadeds));
-
-    LoadedPlugin * loaded = index_get (loadeds, row);
-    loaded->selected = selected;
-}
-
-static void select_all (void * user, int selected)
-{
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        loaded->selected = selected;
-    }
-}
-
-static void shift_rows (void * user, int row, int before)
-{
-    int rows = index_count (loadeds);
-    g_return_if_fail (row >= 0 && row < rows);
-    g_return_if_fail (before >= 0 && before <= rows);
-
-    if (before == row)
-        return;
-
-    pthread_mutex_lock (& mutex);
-
-    Index * move = index_new ();
-    Index * others = index_new ();
-
-    int begin, end;
-    if (before < row)
-    {
-        begin = before;
-        end = row + 1;
-        while (end < rows && ((LoadedPlugin *) index_get (loadeds, end))->selected)
-            end ++;
-    }
-    else
-    {
-        begin = row;
-        while (begin > 0 && ((LoadedPlugin *) index_get (loadeds, begin - 1))->selected)
-            begin --;
-        end = before;
-    }
-
-    for (gint i = begin; i < end; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        index_insert (loaded->selected ? move : others, -1, loaded);
-    }
-
-    if (before < row)
-    {
-        index_copy_insert (others, 0, move, -1, -1);
-        index_free (others);
-    }
-    else
-    {
-        index_copy_insert (move, 0, others, -1, -1);
-        index_free (move);
-        move = others;
-    }
-
-    index_copy_set (move, 0, loadeds, begin, end - begin);
-    index_free (move);
-
-    pthread_mutex_unlock (& mutex);
-
-    if (loaded_list)
-        update_loaded_list (loaded_list);
-}
-
-static const AudguiListCallbacks callbacks = {
- .get_value = get_value,
- .get_selected = get_selected,
- .set_selected = set_selected,
- .select_all = select_all,
- .shift_rows = shift_rows};
-
-GtkWidget * create_loaded_list (void)
-{
-    GtkWidget * list = audgui_list_new (& callbacks, NULL, index_count (loadeds));
-    audgui_list_add_column (list, NULL, 0, G_TYPE_STRING, -1);
-    gtk_tree_view_set_headers_visible ((GtkTreeView *) list, 0);
-    return list;
-}
-
-void update_loaded_list (GtkWidget * list)
-{
-    audgui_list_delete_rows (list, 0, audgui_list_row_count (list));
-    audgui_list_insert_rows (list, 0, index_count (loadeds));
-}
diff --git a/src/ladspa/loaded-list.cc b/src/ladspa/loaded-list.cc
new file mode 100644
index 000000000000..2fae37ce1a9a
--- /dev/null
+++ b/src/ladspa/loaded-list.cc
@@ -0,0 +1,125 @@
+/*
+ * LADSPA Host for Audacious
+ * Copyright 2011 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 <libaudgui/list.h>
+
+#include "plugin.h"
+
+static void get_value (void * user, int row, int column, GValue * value)
+{
+    g_return_if_fail (row >= 0 && row < loadeds.len ());
+    g_return_if_fail (column == 0);
+
+    g_value_set_string (value, loadeds[row]->plugin.desc.Name);
+}
+
+static bool get_selected (void * user, int row)
+{
+    g_return_val_if_fail (row >= 0 && row < loadeds.len (), 0);
+
+    return loadeds[row]->selected;
+}
+
+static void set_selected (void * user, int row, bool selected)
+{
+    g_return_if_fail (row >= 0 && row < loadeds.len ());
+
+    loadeds[row]->selected = selected;
+}
+
+static void select_all (void * user, bool selected)
+{
+    for (auto & loaded : loadeds)
+        loaded->selected = selected;
+}
+
+static void shift_rows (void * user, int row, int before)
+{
+    int rows = loadeds.len ();
+    g_return_if_fail (row >= 0 && row < rows);
+    g_return_if_fail (before >= 0 && before <= rows);
+
+    if (before == row)
+        return;
+
+    pthread_mutex_lock (& mutex);
+
+    Index<SmartPtr<LoadedPlugin>> move;
+    Index<SmartPtr<LoadedPlugin>> others;
+
+    int begin, end;
+    if (before < row)
+    {
+        begin = before;
+        end = row + 1;
+        while (end < rows && loadeds[end]->selected)
+            end ++;
+    }
+    else
+    {
+        begin = row;
+        while (begin > 0 && loadeds[begin - 1]->selected)
+            begin --;
+        end = before;
+    }
+
+    for (int i = begin; i < end; i ++)
+    {
+        if (loadeds[i]->selected)
+            move.append (std::move (loadeds[i]));
+        else
+            others.append (std::move (loadeds[i]));
+    }
+
+    if (before < row)
+        move.move_from (others, 0, -1, -1, true, true);
+    else
+        move.move_from (others, 0, 0, -1, true, true);
+
+    loadeds.move_from (move, 0, begin, end - begin, false, true);
+
+    pthread_mutex_unlock (& mutex);
+
+    if (loaded_list)
+        update_loaded_list (loaded_list);
+}
+
+static const AudguiListCallbacks callbacks = {
+    get_value,
+    get_selected,
+    set_selected,
+    select_all,
+    nullptr,  // activate_row
+    nullptr,  // right_click
+    shift_rows
+};
+
+GtkWidget * create_loaded_list ()
+{
+    GtkWidget * list = audgui_list_new (& callbacks, nullptr, loadeds.len ());
+    audgui_list_add_column (list, nullptr, 0, G_TYPE_STRING, -1);
+    gtk_tree_view_set_headers_visible ((GtkTreeView *) list, 0);
+    return list;
+}
+
+void update_loaded_list (GtkWidget * list)
+{
+    audgui_list_delete_rows (list, 0, audgui_list_row_count (list));
+    audgui_list_insert_rows (list, 0, loadeds.len ());
+}
diff --git a/src/ladspa/plugin-list.c b/src/ladspa/plugin-list.c
deleted file mode 100644
index 411bef958773..000000000000
--- a/src/ladspa/plugin-list.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * LADSPA Host for Audacious
- * Copyright 2011 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 <libaudgui/list.h>
-
-#include "plugin.h"
-
-static void get_value (void * user, int row, int column, GValue * value)
-{
-    g_return_if_fail (row >= 0 && row < index_count (plugins));
-    g_return_if_fail (column == 0);
-
-    PluginData * plugin = index_get (plugins, row);
-    g_value_set_string (value, plugin->desc->Name);
-}
-
-static int get_selected (void * user, int row)
-{
-    g_return_val_if_fail (row >= 0 && row < index_count (plugins), 0);
-
-    PluginData * plugin = index_get (plugins, row);
-    return plugin->selected;
-}
-
-static void set_selected (void * user, int row, int selected)
-{
-    g_return_if_fail (row >= 0 && row < index_count (plugins));
-
-    PluginData * plugin = index_get (plugins, row);
-    plugin->selected = selected;
-}
-
-static void select_all (void * user, int selected)
-{
-    int count = index_count (plugins);
-    for (int i = 0; i < count; i ++)
-    {
-        PluginData * plugin = index_get (plugins, i);
-        plugin->selected = selected;
-    }
-}
-
-static const AudguiListCallbacks callbacks = {
- .get_value = get_value,
- .get_selected = get_selected,
- .set_selected = set_selected,
- .select_all = select_all};
-
-GtkWidget * create_plugin_list (void)
-{
-    GtkWidget * list = audgui_list_new (& callbacks, NULL, index_count (plugins));
-    audgui_list_add_column (list, NULL, 0, G_TYPE_STRING, -1);
-    gtk_tree_view_set_headers_visible ((GtkTreeView *) list, 0);
-    return list;
-}
-
-void update_plugin_list (GtkWidget * list)
-{
-    audgui_list_delete_rows (list, 0, audgui_list_row_count (list));
-    audgui_list_insert_rows (list, 0, index_count (plugins));
-}
diff --git a/src/ladspa/plugin-list.cc b/src/ladspa/plugin-list.cc
new file mode 100644
index 000000000000..eb4a0797c9b5
--- /dev/null
+++ b/src/ladspa/plugin-list.cc
@@ -0,0 +1,71 @@
+/*
+ * LADSPA Host for Audacious
+ * Copyright 2011 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 <libaudgui/list.h>
+
+#include "plugin.h"
+
+static void get_value (void * user, int row, int column, GValue * value)
+{
+    g_return_if_fail (row >= 0 && row < plugins.len ());
+    g_return_if_fail (column == 0);
+
+    g_value_set_string (value, plugins[row]->desc.Name);
+}
+
+static bool get_selected (void * user, int row)
+{
+    g_return_val_if_fail (row >= 0 && row < plugins.len (), 0);
+
+    return plugins[row]->selected;
+}
+
+static void set_selected (void * user, int row, bool selected)
+{
+    g_return_if_fail (row >= 0 && row < plugins.len ());
+
+    plugins[row]->selected = selected;
+}
+
+static void select_all (void * user, bool selected)
+{
+    for (auto & plugin : plugins)
+        plugin->selected = selected;
+}
+
+static const AudguiListCallbacks callbacks = {
+    get_value,
+    get_selected,
+    set_selected,
+    select_all
+};
+
+GtkWidget * create_plugin_list ()
+{
+    GtkWidget * list = audgui_list_new (& callbacks, nullptr, plugins.len ());
+    audgui_list_add_column (list, nullptr, 0, G_TYPE_STRING, -1);
+    gtk_tree_view_set_headers_visible ((GtkTreeView *) list, 0);
+    return list;
+}
+
+void update_plugin_list (GtkWidget * list)
+{
+    audgui_list_delete_rows (list, 0, audgui_list_row_count (list));
+    audgui_list_insert_rows (list, 0, plugins.len ());
+}
diff --git a/src/ladspa/plugin.c b/src/ladspa/plugin.c
deleted file mode 100644
index 4776db19306a..000000000000
--- a/src/ladspa/plugin.c
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * LADSPA Host for Audacious
- * Copyright 2011 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 <errno.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <gmodule.h>
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "plugin.h"
-
-static const gchar * const ladspa_defaults[] = {
- "plugin_count", "0",
- NULL};
-
-pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-char * module_path;
-Index * modules; /* (void *) */
-Index * plugins; /* (PluginData *) */
-Index * loadeds; /* (LoadedPlugin *) */
-
-GtkWidget * config_win;
-GtkWidget * plugin_list;
-GtkWidget * loaded_list;
-
-static ControlData * parse_control (const LADSPA_Descriptor * desc, int port)
-{
-    g_return_val_if_fail (desc->PortNames[port], NULL);
-    const LADSPA_PortRangeHint * hint = & desc->PortRangeHints[port];
-
-    ControlData * control = g_slice_new (ControlData);
-    control->port = port;
-    control->name = g_strdup (desc->PortNames[port]);
-    control->is_toggle = LADSPA_IS_HINT_TOGGLED (hint->HintDescriptor) ? 1 : 0;
-
-    control->min = LADSPA_IS_HINT_BOUNDED_BELOW (hint->HintDescriptor) ? hint->LowerBound :
-     LADSPA_IS_HINT_BOUNDED_ABOVE (hint->HintDescriptor) ? hint->UpperBound - 100 : -100;
-    control->max = LADSPA_IS_HINT_BOUNDED_ABOVE (hint->HintDescriptor) ? hint->UpperBound :
-     LADSPA_IS_HINT_BOUNDED_BELOW (hint->HintDescriptor) ? hint->LowerBound + 100 : 100;
-
-    if (LADSPA_IS_HINT_SAMPLE_RATE (hint->HintDescriptor))
-    {
-        control->min *= 96000;
-        control->max *= 96000;
-    }
-
-    if (LADSPA_IS_HINT_DEFAULT_0 (hint->HintDescriptor))
-        control->def = 0;
-    else if (LADSPA_IS_HINT_DEFAULT_1 (hint->HintDescriptor))
-        control->def = 1;
-    else if (LADSPA_IS_HINT_DEFAULT_100 (hint->HintDescriptor))
-        control->def = 100;
-    else if (LADSPA_IS_HINT_DEFAULT_440 (hint->HintDescriptor))
-        control->def = 440;
-    else if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hint->HintDescriptor))
-        control->def = control->min;
-    else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hint->HintDescriptor))
-        control->def = control->max;
-    else if (LADSPA_IS_HINT_DEFAULT_LOW (hint->HintDescriptor))
-    {
-        if (LADSPA_IS_HINT_LOGARITHMIC (hint->HintDescriptor))
-            control->def = expf (0.75 * logf (control->min) + 0.25 * logf (control->max));
-        else
-            control->def = 0.75 * control->min + 0.25 * control->max;
-    }
-    else if (LADSPA_IS_HINT_DEFAULT_HIGH (hint->HintDescriptor))
-    {
-        if (LADSPA_IS_HINT_LOGARITHMIC (hint->HintDescriptor))
-            control->def = expf (0.25 * logf (control->min) + 0.75 * logf (control->max));
-        else
-            control->def = 0.25 * control->min + 0.75 * control->max;
-    }
-    else
-    {
-        if (LADSPA_IS_HINT_LOGARITHMIC (hint->HintDescriptor))
-            control->def = expf (0.5 * logf (control->min) + 0.5 * logf (control->max));
-        else
-            control->def = 0.5 * control->min + 0.5 * control->max;
-    }
-
-    return control;
-}
-
-static void free_control (ControlData * control)
-{
-    g_free (control->name);
-    g_slice_free (ControlData, control);
-}
-
-static PluginData * open_plugin (const char * path, const LADSPA_Descriptor * desc)
-{
-    const char * slash = strrchr (path, G_DIR_SEPARATOR);
-    g_return_val_if_fail (slash && slash[1], NULL);
-    g_return_val_if_fail (desc->Label && desc->Name, NULL);
-
-    PluginData * plugin = g_slice_new (PluginData);
-    plugin->path = g_strdup (slash + 1);
-    plugin->desc = desc;
-    plugin->controls = index_new ();
-    plugin->in_ports = g_array_new (0, 0, sizeof (int));
-    plugin->out_ports = g_array_new (0, 0, sizeof (int));
-    plugin->selected = 0;
-
-    for (int i = 0; i < desc->PortCount; i ++)
-    {
-        if (LADSPA_IS_PORT_CONTROL (desc->PortDescriptors[i]))
-        {
-            ControlData * control = parse_control (desc, i);
-            if (control)
-                index_insert (plugin->controls, -1, control);
-        }
-        else if (LADSPA_IS_PORT_AUDIO (desc->PortDescriptors[i]) &&
-         LADSPA_IS_PORT_INPUT (desc->PortDescriptors[i]))
-            g_array_append_val (plugin->in_ports, i);
-        else if (LADSPA_IS_PORT_AUDIO (desc->PortDescriptors[i]) &&
-         LADSPA_IS_PORT_OUTPUT (desc->PortDescriptors[i]))
-            g_array_append_val (plugin->out_ports, i);
-    }
-
-    return plugin;
-}
-
-static void close_plugin (PluginData * plugin)
-{
-    g_free (plugin->path);
-    index_free_full (plugin->controls, (IndexFreeFunc) free_control);
-    g_array_free (plugin->in_ports, 1);
-    g_array_free (plugin->out_ports, 1);
-    g_slice_free (PluginData, plugin);
-}
-
-static void * open_module (const char * path)
-{
-    GModule * handle = g_module_open (path, G_MODULE_BIND_LOCAL);
-    if (! handle)
-    {
-        fprintf (stderr, "ladspa: Failed to open module %s: %s\n", path, g_module_error ());
-        return NULL;
-    }
-
-    void * sym;
-    if (! g_module_symbol (handle, "ladspa_descriptor", & sym))
-    {
-        fprintf (stderr, "ladspa: Not a valid LADSPA module: %s\n", path);
-        g_module_close (handle);
-        return NULL;
-    }
-
-    LADSPA_Descriptor_Function descfun = (LADSPA_Descriptor_Function) sym;
-
-    const LADSPA_Descriptor * desc;
-    for (int i = 0; (desc = descfun (i)); i ++)
-    {
-        PluginData * plugin = open_plugin (path, desc);
-        if (plugin)
-            index_insert (plugins, -1, plugin);
-    }
-
-    return handle;
-}
-
-static void open_modules_for_path (const char * path)
-{
-    GDir * folder = g_dir_open (path, 0, NULL);
-    if (! folder)
-    {
-        fprintf (stderr, "ladspa: Failed to read folder %s: %s\n", path, strerror (errno));
-        return;
-    }
-
-    const char * name;
-    while ((name = g_dir_read_name (folder)))
-    {
-        if (! str_has_suffix_nocase (name, G_MODULE_SUFFIX))
-            continue;
-
-        char * filename = filename_build (path, name);
-        void * handle = open_module (filename);
-
-        if (handle)
-            index_insert (modules, -1, handle);
-
-        str_unref (filename);
-    }
-
-    g_dir_close (folder);
-}
-
-static void open_modules_for_paths (const char * paths)
-{
-    if (! paths || ! paths[0])
-        return;
-
-    char * * split = g_strsplit (paths, ":", -1);
-
-    for (int i = 0; split[i]; i ++)
-        open_modules_for_path (split[i]);
-
-    g_strfreev (split);
-}
-
-static void open_modules (void)
-{
-    open_modules_for_paths (getenv ("LADSPA_PATH"));
-    open_modules_for_paths (module_path);
-}
-
-static void close_modules (void)
-{
-    index_delete_full (plugins, 0, -1, (IndexFreeFunc) close_plugin);
-    index_delete_full (modules, 0, -1, (IndexFreeFunc) g_module_close);
-}
-
-LoadedPlugin * enable_plugin_locked (PluginData * plugin)
-{
-    LoadedPlugin * loaded = g_slice_new (LoadedPlugin);
-    loaded->plugin = plugin;
-    loaded->selected = 0;
-
-    int count = index_count (plugin->controls);
-    loaded->values = g_malloc (sizeof (float) * count);
-
-    for (int i = 0; i < count; i ++)
-    {
-        ControlData * control = index_get (plugin->controls, i);
-        loaded->values[i] = control->def;
-    }
-
-    loaded->active = 0;
-    loaded->instances = NULL;
-    loaded->in_bufs = NULL;
-    loaded->out_bufs = NULL;
-
-    loaded->settings_win = NULL;
-
-    index_insert (loadeds, -1, loaded);
-    return loaded;
-}
-
-void disable_plugin_locked (int i)
-{
-    g_return_if_fail (i >= 0 && i < index_count (loadeds));
-    LoadedPlugin * loaded = index_get (loadeds, i);
-
-    if (loaded->settings_win)
-        gtk_widget_destroy (loaded->settings_win);
-
-    shutdown_plugin_locked (loaded);
-
-    g_free (loaded->values);
-    g_slice_free (LoadedPlugin, loaded);
-    index_delete (loadeds, i, 1);
-}
-
-static PluginData * find_plugin (const char * path, const char * label)
-{
-    int count = index_count (plugins);
-    for (int i = 0; i < count; i ++)
-    {
-        PluginData * plugin = index_get (plugins, i);
-        if (! strcmp (plugin->path, path) && ! strcmp (plugin->desc->Label, label))
-            return plugin;
-    }
-
-    return NULL;
-}
-
-static void save_enabled_to_config (void)
-{
-    int count = index_count (loadeds);
-    int old_count = aud_get_int ("ladspa", "plugin_count");
-    aud_set_int ("ladspa", "plugin_count", count);
-
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, 0);
-        char key[32];
-
-        snprintf (key, sizeof key, "plugin%d_path", i);
-        aud_set_str ("ladspa", key, loaded->plugin->path);
-
-        snprintf (key, sizeof key, "plugin%d_label", i);
-        aud_set_str ("ladspa", key, loaded->plugin->desc->Label);
-
-        snprintf (key, sizeof key, "plugin%d_controls", i);
-
-        int ccount = index_count (loaded->plugin->controls);
-        double temp[ccount];
-
-        for (int ci = 0; ci < ccount; ci ++)
-            temp[ci] = loaded->values[ci];
-
-        char * controls = double_array_to_str (temp, ccount);
-        aud_set_str ("ladspa", key, controls);
-        str_unref (controls);
-
-        disable_plugin_locked (0);
-    }
-
-    for (int i = count; i < old_count; i ++)
-    {
-        char key[32];
-
-        snprintf (key, sizeof key, "plugin%d_path", i);
-        aud_set_str ("ladspa", key, "");
-
-        snprintf (key, sizeof key, "plugin%d_label", i);
-        aud_set_str ("ladspa", key, "");
-
-        snprintf (key, sizeof key, "plugin%d_controls", i);
-        aud_set_str ("ladspa", key, "");
-    }
-}
-
-static void load_enabled_from_config (void)
-{
-    int count = aud_get_int ("ladspa", "plugin_count");
-
-    for (int i = 0; i < count; i ++)
-    {
-        char key[32];
-
-        snprintf (key, sizeof key, "plugin%d_path", i);
-        char * path = aud_get_str ("ladspa", key);
-
-        snprintf (key, sizeof key, "plugin%d_label", i);
-        char * label = aud_get_str ("ladspa", key);
-
-        PluginData * plugin = find_plugin (path, label);
-        if (plugin)
-        {
-            LoadedPlugin * loaded = enable_plugin_locked (plugin);
-
-            snprintf (key, sizeof key, "plugin%d_controls", i);
-
-            int ccount = index_count (loaded->plugin->controls);
-            double temp[ccount];
-
-            char * controls = aud_get_str ("ladspa", key);
-
-            if (str_to_double_array (controls, temp, ccount))
-            {
-                for (int ci = 0; ci < ccount; ci ++)
-                    loaded->values[ci] = temp[ci];
-            }
-            else
-            {
-                /* migrate from old config format */
-                for (int ci = 0; ci < ccount; ci ++)
-                {
-                    snprintf (key, sizeof key, "plugin%d_control%d", i, ci);
-                    loaded->values[ci] = aud_get_double ("ladspa", key);
-                    aud_set_str ("ladspa", key, "");
-                }
-            }
-
-            str_unref (controls);
-        }
-
-        str_unref (path);
-        str_unref (label);
-    }
-}
-
-static int init (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    modules = index_new ();
-    plugins = index_new ();
-    loadeds = index_new ();
-
-    aud_config_set_defaults ("ladspa", ladspa_defaults);
-
-    module_path = aud_get_str ("ladspa", "module_path");
-
-    open_modules ();
-    load_enabled_from_config ();
-
-    pthread_mutex_unlock (& mutex);
-    return 1;
-}
-
-static void cleanup (void)
-{
-    if (config_win)
-        gtk_widget_destroy (config_win);
-
-    pthread_mutex_lock (& mutex);
-
-    aud_set_str ("ladspa", "module_path", module_path);
-    save_enabled_to_config ();
-    close_modules ();
-
-    index_free (modules);
-    modules = NULL;
-    index_free (plugins);
-    plugins = NULL;
-    index_free (loadeds);
-    loadeds = NULL;
-
-    str_unref (module_path);
-    module_path = NULL;
-
-    pthread_mutex_unlock (& mutex);
-}
-
-static void set_module_path (GtkEntry * entry)
-{
-    pthread_mutex_lock (& mutex);
-
-    save_enabled_to_config ();
-    close_modules ();
-
-    str_unref (module_path);
-    module_path = str_get (gtk_entry_get_text (entry));
-
-    open_modules ();
-    load_enabled_from_config ();
-
-    pthread_mutex_unlock (& mutex);
-
-    if (plugin_list)
-        update_plugin_list (plugin_list);
-    if (loaded_list)
-        update_loaded_list (loaded_list);
-}
-
-static void enable_selected (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (plugins);
-    for (int i = 0; i < count; i ++)
-    {
-        PluginData * plugin = index_get (plugins, i);
-        if (plugin->selected)
-            enable_plugin_locked (plugin);
-    }
-
-    pthread_mutex_unlock (& mutex);
-
-    if (loaded_list)
-        update_loaded_list (loaded_list);
-}
-
-static void disable_selected (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    int offset = 0;
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i - offset);
-        if (loaded->selected)
-        {
-            disable_plugin_locked (i - offset);
-            offset ++;
-        }
-    }
-
-    pthread_mutex_unlock (& mutex);
-
-    if (loaded_list)
-        update_loaded_list (loaded_list);
-}
-
-static void control_toggled (GtkToggleButton * toggle, float * value)
-{
-    pthread_mutex_lock (& mutex);
-    * value = gtk_toggle_button_get_active (toggle) ? 1 : 0;
-    pthread_mutex_unlock (& mutex);
-}
-
-static void control_changed (GtkSpinButton * spin, float * value)
-{
-    pthread_mutex_lock (& mutex);
-    * value = gtk_spin_button_get_value (spin);
-    pthread_mutex_unlock (& mutex);
-}
-
-static void configure_plugin (LoadedPlugin * loaded)
-{
-    if (loaded->settings_win)
-    {
-        gtk_window_present ((GtkWindow *) loaded->settings_win);
-        return;
-    }
-
-    PluginData * plugin = loaded->plugin;
-    char buf[200];
-
-    snprintf (buf, sizeof buf, _("%s Settings"), plugin->desc->Name);
-    loaded->settings_win = gtk_dialog_new_with_buttons (buf, (GtkWindow *)
-     config_win, GTK_DIALOG_DESTROY_WITH_PARENT, _("_Close"),
-     GTK_RESPONSE_CLOSE, NULL);
-    gtk_window_set_resizable ((GtkWindow *) loaded->settings_win, 0);
-
-    GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) loaded->settings_win);
-
-    int count = index_count (plugin->controls);
-    for (int i = 0; i < count; i ++)
-    {
-        ControlData * control = index_get (plugin->controls, i);
-
-        GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-        gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0);
-
-        if (control->is_toggle)
-        {
-            GtkWidget * toggle = gtk_check_button_new_with_label (control->name);
-            gtk_toggle_button_set_active ((GtkToggleButton *) toggle, (loaded->values[i] > 0) ? 1 : 0);
-            gtk_box_pack_start ((GtkBox *) hbox, toggle, 0, 0, 0);
-
-            g_signal_connect (toggle, "toggled", (GCallback) control_toggled, & loaded->values[i]);
-        }
-        else
-        {
-            snprintf (buf, sizeof buf, "%s:", control->name);
-            GtkWidget * label = gtk_label_new (buf);
-            gtk_box_pack_start ((GtkBox *) hbox, label, 0, 0, 0);
-
-            GtkWidget * spin = gtk_spin_button_new_with_range (control->min, control->max, 0.01);
-            gtk_spin_button_set_value ((GtkSpinButton *) spin, loaded->values[i]);
-            gtk_box_pack_start ((GtkBox *) hbox, spin, 0, 0, 0);
-
-            g_signal_connect (spin, "value-changed", (GCallback) control_changed, & loaded->values[i]);
-        }
-    }
-
-    g_signal_connect (loaded->settings_win, "response", (GCallback) gtk_widget_destroy, NULL);
-    g_signal_connect (loaded->settings_win, "destroy", (GCallback)
-     gtk_widget_destroyed, & loaded->settings_win);
-
-    gtk_widget_show_all (loaded->settings_win);
-}
-
-static void configure_selected (void)
-{
-    pthread_mutex_lock (& mutex);
-
-    int count = index_count (loadeds);
-    for (int i = 0; i < count; i ++)
-    {
-        LoadedPlugin * loaded = index_get (loadeds, i);
-        if (loaded->selected)
-            configure_plugin (loaded);
-    }
-
-    pthread_mutex_unlock (& mutex);
-}
-
-static void configure (void)
-{
-    if (config_win)
-    {
-        gtk_window_present ((GtkWindow *) config_win);
-        return;
-    }
-
-    config_win = gtk_dialog_new_with_buttons (_("LADSPA Host Settings"), NULL,
-     0, _("_Close"), GTK_RESPONSE_CLOSE, NULL);
-    gtk_window_set_default_size ((GtkWindow *) config_win, 480, 360);
-
-    GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) config_win);
-
-    GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0);
-
-    GtkWidget * label = gtk_label_new (_("Module paths:"));
-    gtk_box_pack_start ((GtkBox *) hbox, label, 0, 0, 0);
-
-    label = gtk_label_new (0);
-    gtk_label_set_markup ((GtkLabel *) label,
-     _("<small>Separate multiple paths with a colon.\n"
-     "These paths are searched in addition to LADSPA_PATH.\n"
-     "After adding new paths, press Enter to scan for new plugins.</small>"));
-    gtk_misc_set_padding ((GtkMisc *) label, 12, 6);
-    gtk_misc_set_alignment ((GtkMisc *) label, 0, 0);
-    gtk_box_pack_start ((GtkBox *) vbox, label, 0, 0, 0);
-
-    GtkWidget * entry = gtk_entry_new ();
-    gtk_box_pack_start ((GtkBox *) hbox, entry, 1, 1, 0);
-
-    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox, hbox, 1, 1, 0);
-
-    GtkWidget * vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-    gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0);
-
-    label = gtk_label_new (_("Available plugins:"));
-    gtk_box_pack_start ((GtkBox *) vbox2, label, 0, 0, 0);
-
-    GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN);
-    gtk_box_pack_start ((GtkBox *) vbox2, scrolled, 1, 1, 0);
-
-    plugin_list = create_plugin_list ();
-    gtk_container_add ((GtkContainer *) scrolled, plugin_list);
-
-    GtkWidget * hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 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_box_new (GTK_ORIENTATION_VERTICAL, 6);
-    gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0);
-
-    label = gtk_label_new (_("Enabled plugins:"));
-    gtk_box_pack_start ((GtkBox *) vbox2, label, 0, 0, 0);
-
-    scrolled = gtk_scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN);
-    gtk_box_pack_start ((GtkBox *) vbox2, scrolled, 1, 1, 0);
-
-    loaded_list = create_loaded_list ();
-    gtk_container_add ((GtkContainer *) scrolled, loaded_list);
-
-    hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-    gtk_box_pack_start ((GtkBox *) vbox2, hbox2, 0, 0, 0);
-
-    GtkWidget * disable_button = gtk_button_new_with_label (_("Disable"));
-    gtk_box_pack_end ((GtkBox *) hbox2, disable_button, 0, 0, 0);
-
-    GtkWidget * settings_button = gtk_button_new_with_label (_("Settings"));
-    gtk_box_pack_end ((GtkBox *) hbox2, settings_button, 0, 0, 0);
-
-    if (module_path)
-        gtk_entry_set_text ((GtkEntry *) entry, module_path);
-
-    g_signal_connect (config_win, "response", (GCallback) gtk_widget_destroy, NULL);
-    g_signal_connect (config_win, "destroy", (GCallback) gtk_widget_destroyed, & config_win);
-    g_signal_connect (entry, "activate", (GCallback) set_module_path, NULL);
-    g_signal_connect (plugin_list, "destroy", (GCallback) gtk_widget_destroyed, & plugin_list);
-    g_signal_connect (enable_button, "clicked", (GCallback) enable_selected, NULL);
-    g_signal_connect (loaded_list, "destroy", (GCallback) gtk_widget_destroyed, & loaded_list);
-    g_signal_connect (disable_button, "clicked", (GCallback) disable_selected, NULL);
-    g_signal_connect (settings_button, "clicked", (GCallback) configure_selected, NULL);
-
-    gtk_widget_show_all (config_win);
-}
-
-static const char about[] =
- N_("LADSPA Host for Audacious\n"
-    "Copyright 2011 John Lindgren");
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("LADSPA Host"),
-    .domain = PACKAGE,
-    .about_text = about,
-    .init = init,
-    .cleanup = cleanup,
-    .configure = configure,
-    .start = ladspa_start,
-    .process = ladspa_process,
-    .flush = ladspa_flush,
-    .finish = ladspa_finish,
-    .preserves_format = 1,
-)
diff --git a/src/ladspa/plugin.cc b/src/ladspa/plugin.cc
new file mode 100644
index 000000000000..4b0e07ed1cfc
--- /dev/null
+++ b/src/ladspa/plugin.cc
@@ -0,0 +1,560 @@
+/*
+ * LADSPA Host for Audacious
+ * Copyright 2011 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 <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include <gmodule.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+#include "plugin.h"
+
+const char * const LADSPAHost::defaults[] = {
+ "plugin_count", "0",
+ nullptr};
+
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+String module_path;
+Index<GModule *> modules;
+Index<SmartPtr<PluginData>> plugins;
+Index<SmartPtr<LoadedPlugin>> loadeds;
+
+GtkWidget * plugin_list;
+GtkWidget * loaded_list;
+
+static ControlData parse_control (const LADSPA_Descriptor & desc, int port)
+{
+    const LADSPA_PortRangeHint & hint = desc.PortRangeHints[port];
+
+    ControlData control;
+    control.port = port;
+    control.name = String (desc.PortNames[port]);
+    control.is_toggle = LADSPA_IS_HINT_TOGGLED (hint.HintDescriptor) ? 1 : 0;
+
+    control.min = LADSPA_IS_HINT_BOUNDED_BELOW (hint.HintDescriptor) ? hint.LowerBound :
+     LADSPA_IS_HINT_BOUNDED_ABOVE (hint.HintDescriptor) ? hint.UpperBound - 100 : -100;
+    control.max = LADSPA_IS_HINT_BOUNDED_ABOVE (hint.HintDescriptor) ? hint.UpperBound :
+     LADSPA_IS_HINT_BOUNDED_BELOW (hint.HintDescriptor) ? hint.LowerBound + 100 : 100;
+
+    if (LADSPA_IS_HINT_SAMPLE_RATE (hint.HintDescriptor))
+    {
+        control.min *= 96000;
+        control.max *= 96000;
+    }
+
+    if (LADSPA_IS_HINT_DEFAULT_0 (hint.HintDescriptor))
+        control.def = 0;
+    else if (LADSPA_IS_HINT_DEFAULT_1 (hint.HintDescriptor))
+        control.def = 1;
+    else if (LADSPA_IS_HINT_DEFAULT_100 (hint.HintDescriptor))
+        control.def = 100;
+    else if (LADSPA_IS_HINT_DEFAULT_440 (hint.HintDescriptor))
+        control.def = 440;
+    else if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hint.HintDescriptor))
+        control.def = control.min;
+    else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hint.HintDescriptor))
+        control.def = control.max;
+    else if (LADSPA_IS_HINT_DEFAULT_LOW (hint.HintDescriptor))
+    {
+        if (LADSPA_IS_HINT_LOGARITHMIC (hint.HintDescriptor))
+            control.def = expf (0.75 * logf (control.min) + 0.25 * logf (control.max));
+        else
+            control.def = 0.75 * control.min + 0.25 * control.max;
+    }
+    else if (LADSPA_IS_HINT_DEFAULT_HIGH (hint.HintDescriptor))
+    {
+        if (LADSPA_IS_HINT_LOGARITHMIC (hint.HintDescriptor))
+            control.def = expf (0.25 * logf (control.min) + 0.75 * logf (control.max));
+        else
+            control.def = 0.25 * control.min + 0.75 * control.max;
+    }
+    else
+    {
+        if (LADSPA_IS_HINT_LOGARITHMIC (hint.HintDescriptor))
+            control.def = expf (0.5 * logf (control.min) + 0.5 * logf (control.max));
+        else
+            control.def = 0.5 * control.min + 0.5 * control.max;
+    }
+
+    return control;
+}
+
+static void open_plugin (const char * path, const LADSPA_Descriptor & desc)
+{
+    const char * slash = strrchr (path, G_DIR_SEPARATOR);
+    g_return_if_fail (slash && slash[1]);
+    g_return_if_fail (desc.Label && desc.Name);
+
+    PluginData & plugin = * plugins.append (SmartNew<PluginData> (slash + 1, desc));
+
+    for (unsigned i = 0; i < desc.PortCount; i ++)
+    {
+        if (LADSPA_IS_PORT_CONTROL (desc.PortDescriptors[i]))
+            plugin.controls.append (parse_control (desc, i));
+        else if (LADSPA_IS_PORT_AUDIO (desc.PortDescriptors[i]) &&
+         LADSPA_IS_PORT_INPUT (desc.PortDescriptors[i]))
+            plugin.in_ports.append (i);
+        else if (LADSPA_IS_PORT_AUDIO (desc.PortDescriptors[i]) &&
+         LADSPA_IS_PORT_OUTPUT (desc.PortDescriptors[i]))
+            plugin.out_ports.append (i);
+    }
+}
+
+static GModule * open_module (const char * path)
+{
+    GModule * handle = g_module_open (path, G_MODULE_BIND_LOCAL);
+    if (! handle)
+    {
+        AUDERR ("Failed to open module %s: %s\n", path, g_module_error ());
+        return nullptr;
+    }
+
+    void * sym;
+    if (! g_module_symbol (handle, "ladspa_descriptor", & sym))
+    {
+        AUDERR ("Not a valid LADSPA module: %s\n", path);
+        g_module_close (handle);
+        return nullptr;
+    }
+
+    LADSPA_Descriptor_Function descfun = (LADSPA_Descriptor_Function) sym;
+
+    const LADSPA_Descriptor * desc;
+    for (int i = 0; (desc = descfun (i)); i ++)
+        open_plugin (path, * desc);
+
+    return handle;
+}
+
+static void open_modules_for_path (const char * path)
+{
+    GDir * folder = g_dir_open (path, 0, nullptr);
+    if (! folder)
+    {
+        AUDERR ("Failed to read folder %s: %s\n", path, strerror (errno));
+        return;
+    }
+
+    const char * name;
+    while ((name = g_dir_read_name (folder)))
+    {
+        if (! str_has_suffix_nocase (name, G_MODULE_SUFFIX))
+            continue;
+
+        GModule * handle = open_module (filename_build ({path, name}));
+
+        if (handle)
+            modules.append (handle);
+    }
+
+    g_dir_close (folder);
+}
+
+static void open_modules_for_paths (const char * paths)
+{
+    if (! paths || ! paths[0])
+        return;
+
+    char * * split = g_strsplit (paths, ":", -1);
+
+    for (int i = 0; split[i]; i ++)
+        open_modules_for_path (split[i]);
+
+    g_strfreev (split);
+}
+
+static void open_modules ()
+{
+    open_modules_for_paths (getenv ("LADSPA_PATH"));
+    open_modules_for_paths (module_path);
+}
+
+static void close_modules ()
+{
+    plugins.clear ();
+
+    for (GModule * module : modules)
+        g_module_close (module);
+}
+
+LoadedPlugin & enable_plugin_locked (PluginData & plugin)
+{
+    LoadedPlugin & loaded = * loadeds.append (SmartNew<LoadedPlugin> (plugin));
+
+    for (auto & control : plugin.controls)
+        loaded.values.append (control.def);
+
+    return loaded;
+}
+
+void disable_plugin_locked (LoadedPlugin & loaded)
+{
+    if (loaded.settings_win)
+        gtk_widget_destroy (loaded.settings_win);
+
+    shutdown_plugin_locked (loaded);
+}
+
+static PluginData * find_plugin (const char * path, const char * label)
+{
+    for (auto & plugin : plugins)
+    {
+        if (! strcmp (plugin->path, path) && ! strcmp (plugin->desc.Label, label))
+            return plugin.get ();
+    }
+
+    return nullptr;
+}
+
+static void save_enabled_to_config ()
+{
+    int count = loadeds.len ();
+    int old_count = aud_get_int ("ladspa", "plugin_count");
+    aud_set_int ("ladspa", "plugin_count", count);
+
+    for (int i = 0; i < count; i ++)
+    {
+        LoadedPlugin & loaded = * loadeds[i];
+
+        aud_set_str ("ladspa", str_printf ("plugin%d_path", i), loaded.plugin.path);
+        aud_set_str ("ladspa", str_printf ("plugin%d_label", i), loaded.plugin.desc.Label);
+
+        Index<double> temp;
+        temp.insert (0, loaded.values.len ());
+        std::copy (loaded.values.begin (), loaded.values.end (), temp.begin ());
+
+        aud_set_str ("ladspa", str_printf ("plugin%d_controls", i),
+         double_array_to_str (temp.begin (), temp.len ()));
+
+        disable_plugin_locked (loaded);
+    }
+
+    loadeds.clear ();
+
+    for (int i = count; i < old_count; i ++)
+    {
+        aud_set_str ("ladspa", str_printf ("plugin%d_path", i), "");
+        aud_set_str ("ladspa", str_printf ("plugin%d_label", i), "");
+        aud_set_str ("ladspa", str_printf ("plugin%d_controls", i), "");
+    }
+}
+
+static void load_enabled_from_config ()
+{
+    int count = aud_get_int ("ladspa", "plugin_count");
+
+    for (int i = 0; i < count; i ++)
+    {
+        String path = aud_get_str ("ladspa", str_printf ("plugin%d_path", i));
+        String label = aud_get_str ("ladspa", str_printf ("plugin%d_label", i));
+
+        PluginData * plugin = find_plugin (path, label);
+        if (! plugin)
+            continue;
+
+        LoadedPlugin & loaded = enable_plugin_locked (* plugin);
+
+        String controls = aud_get_str ("ladspa", str_printf ("plugin%d_controls", i));
+
+        Index<double> temp;
+        temp.insert (0, loaded.values.len ());
+
+        if (str_to_double_array (controls, temp.begin (), temp.len ()))
+            std::copy (temp.begin (), temp.end (), loaded.values.begin ());
+        else
+        {
+            /* migrate from old config format */
+            for (int ci = 0; ci < temp.len (); ci ++)
+            {
+                StringBuf key = str_printf ("plugin%d_control%d", i, ci);
+                loaded.values[ci] = aud_get_double ("ladspa", key);
+                aud_set_str ("ladspa", key, "");
+            }
+        }
+    }
+}
+
+bool LADSPAHost::init ()
+{
+    pthread_mutex_lock (& mutex);
+
+    aud_config_set_defaults ("ladspa", defaults);
+
+    module_path = aud_get_str ("ladspa", "module_path");
+
+    open_modules ();
+    load_enabled_from_config ();
+
+    pthread_mutex_unlock (& mutex);
+    return true;
+}
+
+void LADSPAHost::cleanup ()
+{
+    pthread_mutex_lock (& mutex);
+
+    aud_set_str ("ladspa", "module_path", module_path);
+    save_enabled_to_config ();
+    close_modules ();
+
+    modules.clear ();
+    plugins.clear ();
+    loadeds.clear ();
+
+    module_path = String ();
+
+    pthread_mutex_unlock (& mutex);
+}
+
+static void set_module_path (GtkEntry * entry)
+{
+    pthread_mutex_lock (& mutex);
+
+    save_enabled_to_config ();
+    close_modules ();
+
+    module_path = String (gtk_entry_get_text (entry));
+
+    open_modules ();
+    load_enabled_from_config ();
+
+    pthread_mutex_unlock (& mutex);
+
+    if (plugin_list)
+        update_plugin_list (plugin_list);
+    if (loaded_list)
+        update_loaded_list (loaded_list);
+}
+
+static void enable_selected ()
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & plugin : plugins)
+    {
+        if (plugin->selected)
+            enable_plugin_locked (* plugin);
+    }
+
+    pthread_mutex_unlock (& mutex);
+
+    if (loaded_list)
+        update_loaded_list (loaded_list);
+}
+
+static void disable_selected ()
+{
+    pthread_mutex_lock (& mutex);
+
+    for (int i = 0; i < loadeds.len (); i ++)
+    {
+        if (loadeds[i]->selected)
+        {
+            disable_plugin_locked (* loadeds[i]);
+            loadeds.remove (i, 1);
+        }
+        else
+            i ++;
+    }
+
+    pthread_mutex_unlock (& mutex);
+
+    if (loaded_list)
+        update_loaded_list (loaded_list);
+}
+
+static void control_toggled (GtkToggleButton * toggle, float * value)
+{
+    pthread_mutex_lock (& mutex);
+    * value = gtk_toggle_button_get_active (toggle) ? 1 : 0;
+    pthread_mutex_unlock (& mutex);
+}
+
+static void control_changed (GtkSpinButton * spin, float * value)
+{
+    pthread_mutex_lock (& mutex);
+    * value = gtk_spin_button_get_value (spin);
+    pthread_mutex_unlock (& mutex);
+}
+
+static void configure_plugin (LoadedPlugin & loaded)
+{
+    if (loaded.settings_win)
+    {
+        gtk_window_present ((GtkWindow *) loaded.settings_win);
+        return;
+    }
+
+    PluginData & plugin = loaded.plugin;
+
+    StringBuf title = str_printf (_("%s Settings"), plugin.desc.Name);
+    loaded.settings_win = gtk_dialog_new_with_buttons (title, nullptr,
+     (GtkDialogFlags) 0, _("_Close"), GTK_RESPONSE_CLOSE, nullptr);
+    gtk_window_set_resizable ((GtkWindow *) loaded.settings_win, 0);
+
+    GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) loaded.settings_win);
+
+    int count = plugin.controls.len ();
+    for (int i = 0; i < count; i ++)
+    {
+        ControlData & control = plugin.controls[i];
+
+        GtkWidget * hbox = gtk_hbox_new (FALSE, 6);
+        gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0);
+
+        if (control.is_toggle)
+        {
+            GtkWidget * toggle = gtk_check_button_new_with_label (control.name);
+            gtk_toggle_button_set_active ((GtkToggleButton *) toggle, (loaded.values[i] > 0) ? 1 : 0);
+            gtk_box_pack_start ((GtkBox *) hbox, toggle, 0, 0, 0);
+
+            g_signal_connect (toggle, "toggled", (GCallback) control_toggled, & loaded.values[i]);
+        }
+        else
+        {
+            GtkWidget * label = gtk_label_new (str_printf ("%s:", (const char *) control.name));
+            gtk_box_pack_start ((GtkBox *) hbox, label, 0, 0, 0);
+
+            GtkWidget * spin = gtk_spin_button_new_with_range (control.min, control.max, 0.01);
+            gtk_spin_button_set_value ((GtkSpinButton *) spin, loaded.values[i]);
+            gtk_box_pack_start ((GtkBox *) hbox, spin, 0, 0, 0);
+
+            g_signal_connect (spin, "value-changed", (GCallback) control_changed, & loaded.values[i]);
+        }
+    }
+
+    g_signal_connect (loaded.settings_win, "response", (GCallback) gtk_widget_destroy, nullptr);
+    g_signal_connect (loaded.settings_win, "destroy", (GCallback)
+     gtk_widget_destroyed, & loaded.settings_win);
+
+    gtk_widget_show_all (loaded.settings_win);
+}
+
+static void configure_selected ()
+{
+    pthread_mutex_lock (& mutex);
+
+    for (auto & loaded : loadeds)
+    {
+        if (loaded->selected)
+            configure_plugin (* loaded);
+    }
+
+    pthread_mutex_unlock (& mutex);
+}
+
+static void * make_config_widget ()
+{
+    GtkWidget * vbox = gtk_vbox_new (FALSE, 6);
+    gtk_widget_set_size_request (vbox, 480, 360);
+
+    GtkWidget * hbox = gtk_hbox_new (FALSE, 6);
+    gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0);
+
+    GtkWidget * label = gtk_label_new (_("Module paths:"));
+    gtk_box_pack_start ((GtkBox *) hbox, label, 0, 0, 0);
+
+    label = gtk_label_new (0);
+    gtk_label_set_markup ((GtkLabel *) label,
+     _("<small>Separate multiple paths with a colon.\n"
+     "These paths are searched in addition to LADSPA_PATH.\n"
+     "After adding new paths, press Enter to scan for new plugins.</small>"));
+    gtk_misc_set_padding ((GtkMisc *) label, 12, 6);
+    gtk_misc_set_alignment ((GtkMisc *) label, 0, 0);
+    gtk_box_pack_start ((GtkBox *) vbox, label, 0, 0, 0);
+
+    GtkWidget * entry = gtk_entry_new ();
+    gtk_box_pack_start ((GtkBox *) hbox, entry, 1, 1, 0);
+
+    hbox = gtk_hbox_new (FALSE, 6);
+    gtk_box_pack_start ((GtkBox *) vbox, hbox, 1, 1, 0);
+
+    GtkWidget * vbox2 = gtk_vbox_new (FALSE, 6);
+    gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0);
+
+    label = gtk_label_new (_("Available plugins:"));
+    gtk_box_pack_start ((GtkBox *) vbox2, label, 0, 0, 0);
+
+    GtkWidget * scrolled = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN);
+    gtk_box_pack_start ((GtkBox *) vbox2, scrolled, 1, 1, 0);
+
+    plugin_list = create_plugin_list ();
+    gtk_container_add ((GtkContainer *) scrolled, plugin_list);
+
+    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);
+    gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0);
+
+    label = gtk_label_new (_("Enabled plugins:"));
+    gtk_box_pack_start ((GtkBox *) vbox2, label, 0, 0, 0);
+
+    scrolled = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN);
+    gtk_box_pack_start ((GtkBox *) vbox2, scrolled, 1, 1, 0);
+
+    loaded_list = create_loaded_list ();
+    gtk_container_add ((GtkContainer *) scrolled, loaded_list);
+
+    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"));
+    gtk_box_pack_end ((GtkBox *) hbox2, disable_button, 0, 0, 0);
+
+    GtkWidget * settings_button = gtk_button_new_with_label (_("Settings"));
+    gtk_box_pack_end ((GtkBox *) hbox2, settings_button, 0, 0, 0);
+
+    if (module_path)
+        gtk_entry_set_text ((GtkEntry *) entry, module_path);
+
+    g_signal_connect (entry, "activate", (GCallback) set_module_path, nullptr);
+    g_signal_connect (plugin_list, "destroy", (GCallback) gtk_widget_destroyed, & plugin_list);
+    g_signal_connect (enable_button, "clicked", (GCallback) enable_selected, nullptr);
+    g_signal_connect (loaded_list, "destroy", (GCallback) gtk_widget_destroyed, & loaded_list);
+    g_signal_connect (disable_button, "clicked", (GCallback) disable_selected, nullptr);
+    g_signal_connect (settings_button, "clicked", (GCallback) configure_selected, nullptr);
+
+    return vbox;
+}
+
+const char LADSPAHost::about[] =
+ N_("LADSPA Host for Audacious\n"
+    "Copyright 2011 John Lindgren");
+
+const PreferencesWidget LADSPAHost::widgets[] = {
+    WidgetCustomGTK (make_config_widget)
+};
+
+const PluginPreferences LADSPAHost::prefs = {{widgets}};
+
+EXPORT LADSPAHost aud_plugin_instance;
diff --git a/src/ladspa/plugin.h b/src/ladspa/plugin.h
index cd242c1b343b..22c7ca0842be 100644
--- a/src/ladspa/plugin.h
+++ b/src/ladspa/plugin.h
@@ -22,36 +22,75 @@
 
 #include <pthread.h>
 #include <gtk/gtk.h>
-#include <libaudcore/index.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
 
 #include "ladspa.h"
 
 #define LADSPA_BUFLEN 1024
 
-typedef struct {
+struct PreferencesWidget;
+
+struct ControlData {
     int port;
-    char * name;
-    char is_toggle;
+    String name;
+    bool is_toggle;
     float min, max, def;
-} ControlData;
-
-typedef struct {
-    char * path;
-    const LADSPA_Descriptor * desc;
-    Index * controls; /* (ControlData *) */
-    GArray * in_ports, * out_ports; /* (int) */
-    char selected;
-} PluginData;
-
-typedef struct {
-    PluginData * plugin;
-    float * values;
-    char selected;
-    char active;
-    Index * instances; /* (LADSPA_Handle) */
-    float * * in_bufs, * * out_bufs; /* (float *) */
-    GtkWidget * settings_win;
-} LoadedPlugin;
+};
+
+struct PluginData
+{
+    String path;
+    const LADSPA_Descriptor & desc;
+    Index<ControlData> controls;
+    Index<int> in_ports, out_ports;
+    bool selected = false;
+
+    PluginData (const char * path, const LADSPA_Descriptor & desc) :
+        path (path),
+        desc (desc) {}
+};
+
+struct LoadedPlugin
+{
+    PluginData & plugin;
+    Index<float> values;
+    bool selected = false;
+    bool active = false;
+    Index<LADSPA_Handle> instances;
+    Index<Index<float>> in_bufs, out_bufs;
+    GtkWidget * settings_win = nullptr;
+
+    LoadedPlugin (PluginData & plugin) :
+        plugin (plugin) {}
+};
+
+class LADSPAHost : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("LADSPA Host"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr LADSPAHost () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+    Index<float> & finish (Index<float> & data, bool end_of_playlist);
+};
 
 /* plugin.c */
 
@@ -60,36 +99,29 @@ typedef struct {
  * audio thread is reading from them. */
 
 extern pthread_mutex_t mutex;
-extern char * module_path;
-extern Index * modules; /* (GModule *) */
-extern Index * plugins; /* (PluginData *) */
-extern Index * loadeds; /* (LoadedPlugin *) */
+extern String module_path;
+extern Index<GModule *> modules;
+extern Index<SmartPtr<PluginData>> plugins;
+extern Index<SmartPtr<LoadedPlugin>> loadeds;
 
-extern GtkWidget * about_win;
-extern GtkWidget * config_win;
 extern GtkWidget * plugin_list;
 extern GtkWidget * loaded_list;
 
-LoadedPlugin * enable_plugin_locked (PluginData * plugin);
-void disable_plugin_locked (int i);
+LoadedPlugin & enable_plugin_locked (PluginData & plugin);
+void disable_plugin_locked (LoadedPlugin & loaded);
 
 /* effect.c */
 
-void shutdown_plugin_locked (LoadedPlugin * loaded);
-
-void ladspa_start (gint * channels, gint * rate);
-void ladspa_process (gfloat * * data, gint * samples);
-void ladspa_flush (void);
-void ladspa_finish (gfloat * * data, gint * samples);
+void shutdown_plugin_locked (LoadedPlugin & loaded);
 
 /* plugin-list.c */
 
-GtkWidget * create_plugin_list (void);
+GtkWidget * create_plugin_list ();
 void update_plugin_list (GtkWidget * list);
 
 /* loaded-list.c */
 
-GtkWidget * create_loaded_list (void);
+GtkWidget * create_loaded_list ();
 void update_loaded_list (GtkWidget * list);
 
 #endif
diff --git a/src/lirc/Makefile b/src/lirc/Makefile
index b40bcf1c3378..6ee32c7f4246 100644
--- a/src/lirc/Makefile
+++ b/src/lirc/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = lirc${PLUGIN_SUFFIX}
 
-SRCS = lirc.c
+SRCS = lirc.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
 LIBS += ${GLIB_LIBS} -llirc_client
diff --git a/src/lirc/lirc.c b/src/lirc/lirc.c
deleted file mode 100644
index b4d1b0e4b89d..000000000000
--- a/src/lirc/lirc.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/* Audacious LIRC plugin - lirc.c
-
-   Copyright (C) 2012 Joonas Harjumäki (jharjuma at gmail.com)
-
-   Copyright (C) 2005 Audacious development team
-
-   Copyright (c) 1998-1999 Carl van Schaik (carl at leg.uct.ac.za)
-
-   Copyright (C) 2000 Christoph Bartelmus (xmms at bartelmus.de)
-
-   some code was stolen from:
-   IRman plugin for xmms by Charles Sielski (stray at teklabs.net)
-
-   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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <stdlib.h>
-
-#include <glib.h>
-#include <lirc/lirc_client.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <libaudcore/hook.h>
-
-static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data);
-
-static const char * const lirc_defaults[] = {
- "enable_reconnect", "TRUE",
- "reconnect_timeout", "5",
- NULL};
-
-const char *plugin_name = "LIRC Plugin";
-
-int lirc_fd = -1;
-struct lirc_config *config = NULL;
-gint tracknr = 0;
-gint mute = 0;                  /* mute flag */
-gint mute_vol = 0;              /* holds volume before mute */
-
-guint input_tag;
-
-char track_no[64];
-int track_no_pos;
-gint tid;
-
-void init_lirc (void)
-{
-    int flags;
-
-    if ((lirc_fd = lirc_init ("audacious", 1)) == -1)
-    {
-        fprintf (stderr, _("%s: could not init LIRC support\n"), plugin_name);
-        return;
-    }
-    if (lirc_readconfig (NULL, &config, NULL) == -1)
-    {
-        lirc_deinit ();
-        fprintf (stderr,
-                 _("%s: could not read LIRC config file\n"
-                   "%s: please read the documentation of LIRC\n"
-                   "%s: how to create a proper config file\n"),
-                 plugin_name, plugin_name, plugin_name);
-        return;
-    }
-
-    input_tag =
-        g_io_add_watch (g_io_channel_unix_new (lirc_fd), G_IO_IN,
-                        lirc_input_callback, NULL);
-
-    fcntl (lirc_fd, F_SETOWN, getpid ());
-    flags = fcntl (lirc_fd, F_GETFL, 0);
-    if (flags != -1)
-    {
-        fcntl (lirc_fd, F_SETFL, flags | O_NONBLOCK);
-    }
-    fflush (stdout);
-}
-
-gboolean init (void)
-{
-    aud_config_set_defaults ("lirc", lirc_defaults);
-    init_lirc ();
-    track_no_pos = 0;
-    tid = 0;
-    return TRUE;
-}
-
-gboolean reconnect_lirc (gpointer data)
-{
-    fprintf (stderr, _("%s: trying to reconnect...\n"), plugin_name);
-    init ();
-    return (lirc_fd == -1);
-}
-
-void cleanup ()
-{
-    if (config)
-    {
-        if (input_tag)
-            g_source_remove (input_tag);
-
-        config = NULL;
-    }
-    if (lirc_fd != -1)
-    {
-        lirc_deinit ();
-        lirc_fd = -1;
-    }
-}
-
-gboolean jump_to (gpointer data)
-{
-    int playlist = aud_playlist_get_active ();
-    aud_playlist_set_position (playlist, atoi (track_no) - 1);
-    track_no_pos = 0;
-    tid = 0;
-    return FALSE;
-}
-
-static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data)
-{
-    char *code;
-    char *c;
-    gint playlist_time, playlist_pos, output_time, v;
-    int ret;
-    char *ptr;
-    gint balance;
-#if 0
-    gboolean show_pl;
-#endif
-    int n;
-    gchar *utf8_title_markup;
-
-    while ((ret = lirc_nextcode (&code)) == 0 && code != NULL)
-    {
-        while ((ret = lirc_code2char (config, code, &c)) == 0 && c != NULL)
-        {
-            if (g_ascii_strcasecmp ("PLAY", c) == 0)
-                aud_drct_play ();
-            else if (g_ascii_strcasecmp ("STOP", c) == 0)
-                aud_drct_stop ();
-            else if (g_ascii_strcasecmp ("PAUSE", c) == 0)
-                aud_drct_pause ();
-            else if (g_ascii_strcasecmp ("PLAYPAUSE", c) == 0)
-                aud_drct_play_pause ();
-            else if (g_ascii_strncasecmp ("NEXT", c, 4) == 0)
-            {
-                ptr = c + 4;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-
-                if (n <= 0)
-                    n = 1;
-                for (; n > 0; n--)
-                {
-                    aud_drct_pl_next ();
-                }
-            }
-            else if (g_ascii_strncasecmp ("PREV", c, 4) == 0)
-            {
-                ptr = c + 4;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-
-                if (n <= 0)
-                    n = 1;
-                for (; n > 0; n--)
-                {
-                    aud_drct_pl_prev ();
-                }
-            }
-            else if (g_ascii_strcasecmp ("SHUFFLE", c) == 0)
-                aud_set_bool (NULL, "shuffle", ! aud_get_bool (NULL, "shuffle"));
-            else if (g_ascii_strcasecmp ("REPEAT", c) == 0)
-                aud_set_bool (NULL, "repeat", ! aud_get_bool (NULL, "repeat"));
-            else if (g_ascii_strncasecmp ("FWD", c, 3) == 0)
-            {
-                ptr = c + 3;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr) * 1000;
-
-                if (n <= 0)
-                    n = 5000;
-                output_time = aud_drct_get_time ();
-
-                int playlist = aud_playlist_get_active ();
-                playlist_pos = aud_playlist_get_position (playlist);
-                playlist_time =
-                    aud_playlist_entry_get_length (playlist, playlist_pos,
-                                                   FALSE);
-                if (playlist_time - output_time < n)
-                    output_time = playlist_time - n;
-                aud_drct_seek (output_time + n);
-            }
-            else if (g_ascii_strncasecmp ("BWD", c, 3) == 0)
-            {
-                ptr = c + 3;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr) * 1000;
-
-                if (n <= 0)
-                    n = 5000;
-                output_time = aud_drct_get_time ();
-                if (output_time < n)
-                    output_time = n;
-                aud_drct_seek (output_time - n);
-            }
-            else if (g_ascii_strncasecmp ("VOL_UP", c, 6) == 0)
-            {
-                ptr = c + 6;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-                if (n <= 0)
-                    n = 5;
-
-                aud_drct_get_volume_main (&v);
-                if (v > (100 - n))
-                    v = 100 - n;
-                aud_drct_set_volume_main (v + n);
-            }
-            else if (g_ascii_strncasecmp ("VOL_DOWN", c, 8) == 0)
-            {
-                ptr = c + 8;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-                if (n <= 0)
-                    n = 5;
-
-                aud_drct_get_volume_main (&v);
-                if (v < n)
-                    v = n;
-                aud_drct_set_volume_main (v - n);
-            }
-            else if (g_ascii_strcasecmp ("QUIT", c) == 0)
-            {
-                aud_drct_quit ();
-            }
-            else if (g_ascii_strcasecmp ("MUTE", c) == 0)
-            {
-                if (mute == 0)
-                {
-                    mute = 1;
-                    /* store the master volume so
-                       we can restore it on unmute. */
-                    aud_drct_get_volume_main (&mute_vol);
-                    aud_drct_set_volume_main (0);
-                }
-                else
-                {
-                    mute = 0;
-                    aud_drct_set_volume_main (mute_vol);
-                }
-            }
-            else if (g_ascii_strncasecmp ("BAL_LEFT", c, 8) == 0)
-            {
-                ptr = c + 8;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-                if (n <= 0)
-                    n = 5;
-
-                aud_drct_get_volume_balance (&balance);
-                balance -= n;
-                if (balance < -100)
-                    balance = -100;
-                aud_drct_set_volume_balance (balance);
-            }
-            else if (g_ascii_strncasecmp ("BAL_RIGHT", c, 9) == 0)
-            {
-                ptr = c + 9;
-                while (g_ascii_isspace (*ptr))
-                    ptr++;
-                n = atoi (ptr);
-                if (n <= 0)
-                    n = 5;
-
-                aud_drct_get_volume_balance (&balance);
-                balance += n;
-                if (balance > 100)
-                    balance = 100;
-                aud_drct_set_volume_balance (balance);
-            }
-            else if (g_ascii_strcasecmp ("BAL_CENTER", c) == 0)
-            {
-                balance = 0;
-                aud_drct_set_volume_balance (balance);
-            }
-            else if (g_ascii_strcasecmp ("LIST", c) == 0)
-            {
-#if 0
-                show_pl = aud_drct_pl_win_is_visible ();
-                show_pl = (show_pl) ? 0 : 1;
-                aud_drct_pl_win_toggle (show_pl);
-#endif
-            }
-            else if (g_ascii_strcasecmp ("PLAYLIST_CLEAR", c) == 0)
-            {
-                aud_drct_stop ();
-                int playlist = aud_playlist_get_active ();
-                aud_playlist_entry_delete (playlist, 0,
-                                           aud_playlist_entry_count
-                                           (playlist));
-            }
-            else if (g_ascii_strncasecmp ("PLAYLIST_ADD ", c, 13) == 0)
-            {
-                aud_drct_pl_add (c + 13, -1);
-            }
-            else if ((strlen (c) == 1) && ((*c >= '0') || (*c <= '9')))
-            {
-                if (track_no_pos < 63)
-                {
-                    if (tid)
-                        g_source_remove (tid);
-                    track_no[track_no_pos++] = *c;
-                    track_no[track_no_pos] = 0;
-                    tid = g_timeout_add (1500, jump_to, NULL);
-                    utf8_title_markup = g_markup_printf_escaped ("%s", track_no);
-                    hook_call ("aosd toggle", utf8_title_markup);
-                }
-            }
-            else
-            {
-                fprintf (stderr, _("%s: unknown command \"%s\"\n"),
-                         plugin_name, c);
-            }
-        }
-        g_free (code);
-        if (ret == -1)
-            break;
-    }
-    if (ret == -1)
-    {
-        /* something went badly wrong */
-        fprintf (stderr, _("%s: disconnected from LIRC\n"), plugin_name);
-        cleanup ();
-        if (aud_get_bool ("lirc", "enable_reconnect"))
-        {
-            int reconnect_timeout = aud_get_int ("lirc", "reconnect_timeout");
-            fprintf (stderr,
-                     _("%s: will try reconnect every %d seconds...\n"),
-                     plugin_name, reconnect_timeout);
-            g_timeout_add (1000 * reconnect_timeout, reconnect_lirc, NULL);
-        }
-    }
-
-    return TRUE;
-}
-
-static const char about[] =
- N_("A simple plugin to control Audacious using the LIRC remote control daemon\n\n"
-    "Adapted for Audacious by:\n"
-    "Tony Vroon <chainsaw at gentoo.org>\n"
-    "Joonas Harjumäki <jharjuma at gmail.com>\n\n"
-    "Based on the XMMS LIRC plugin by:\n"
-    "Carl van Schaik <carl at leg.uct.ac.za>\n"
-    "Christoph Bartelmus <xmms at bartelmus.de>\n"
-    "Andrew O. Shadoura <bugzilla at tut.by>\n\n"
-    "For more information about LIRC, see http://lirc.org.");
-
-static const PreferencesWidget widgets[] = {
- {WIDGET_LABEL, N_("<b>Connection</b>")},
- {WIDGET_CHK_BTN, N_("Reconnect to LIRC server"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "lirc", .cname = "enable_reconnect"},
- {WIDGET_SPIN_BTN, N_("Wait before reconnecting:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "lirc", .cname = "reconnect_timeout",
-  .data = {.spin_btn = {1, 120, 1, N_("seconds")}}}};
-
-static const PluginPreferences prefs = {
- .widgets = widgets,
- .n_widgets = ARRAY_LEN (widgets)};
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("LIRC Plugin"),
-    .domain = PACKAGE,
-    .about_text = about,
-    .prefs = & prefs,
-    .init = init,
-    .cleanup = cleanup
-)
diff --git a/src/lirc/lirc.cc b/src/lirc/lirc.cc
new file mode 100644
index 000000000000..d0668df9d015
--- /dev/null
+++ b/src/lirc/lirc.cc
@@ -0,0 +1,401 @@
+/* Audacious LIRC plugin - lirc.c
+
+   Copyright (C) 2012 Joonas Harjumäki (jharjuma at gmail.com)
+
+   Copyright (C) 2005 Audacious development team
+
+   Copyright (c) 1998-1999 Carl van Schaik (carl at leg.uct.ac.za)
+
+   Copyright (C) 2000 Christoph Bartelmus (xmms at bartelmus.de)
+
+   some code was stolen from:
+   IRman plugin for xmms by Charles Sielski (stray at teklabs.net)
+
+   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.
+*/
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <lirc/lirc_client.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/hook.h>
+
+class LIRCPlugin : public GeneralPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("LIRC Plugin"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr LIRCPlugin () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT LIRCPlugin aud_plugin_instance;
+
+static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data);
+
+const char * const LIRCPlugin::defaults[] = {
+ "enable_reconnect", "TRUE",
+ "reconnect_timeout", "5",
+ nullptr};
+
+int lirc_fd = -1;
+struct lirc_config *config = nullptr;
+int tracknr = 0;
+int mute = 0;                  /* mute flag */
+int mute_vol = 0;              /* holds volume before mute */
+
+unsigned input_tag;
+
+char track_no[64];
+int track_no_pos;
+int tid;
+
+void init_lirc (void)
+{
+    int flags;
+
+    if ((lirc_fd = lirc_init ((char *) "audacious", 1)) == -1)
+    {
+        AUDERR ("could not init LIRC support\n");
+        return;
+    }
+    if (lirc_readconfig (nullptr, &config, nullptr) == -1)
+    {
+        lirc_deinit ();
+        AUDERR ("could not read LIRC config file\n");
+        return;
+    }
+
+    input_tag =
+        g_io_add_watch (g_io_channel_unix_new (lirc_fd), G_IO_IN,
+                        lirc_input_callback, nullptr);
+
+    fcntl (lirc_fd, F_SETOWN, getpid ());
+    flags = fcntl (lirc_fd, F_GETFL, 0);
+    if (flags != -1)
+    {
+        fcntl (lirc_fd, F_SETFL, flags | O_NONBLOCK);
+    }
+}
+
+bool LIRCPlugin::init ()
+{
+    aud_config_set_defaults ("lirc", defaults);
+    init_lirc ();
+    track_no_pos = 0;
+    tid = 0;
+    return true;
+}
+
+gboolean reconnect_lirc (void * data)
+{
+    AUDERR ("trying to reconnect...\n");
+    aud_plugin_instance.init ();
+    return (lirc_fd == -1);
+}
+
+void LIRCPlugin::cleanup ()
+{
+    if (config)
+    {
+        if (input_tag)
+            g_source_remove (input_tag);
+
+        config = nullptr;
+    }
+    if (lirc_fd != -1)
+    {
+        lirc_deinit ();
+        lirc_fd = -1;
+    }
+}
+
+gboolean jump_to (void * data)
+{
+    int playlist = aud_playlist_get_active ();
+    aud_playlist_set_position (playlist, atoi (track_no) - 1);
+    track_no_pos = 0;
+    tid = 0;
+    return false;
+}
+
+static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data)
+{
+    char *code;
+    char *c;
+    int output_time, v;
+    int ret;
+    char *ptr;
+    int balance;
+#if 0
+    gboolean show_pl;
+#endif
+    int n;
+    char *utf8_title_markup;
+
+    while ((ret = lirc_nextcode (&code)) == 0 && code != nullptr)
+    {
+        while ((ret = lirc_code2char (config, code, &c)) == 0 && c != nullptr)
+        {
+            if (g_ascii_strcasecmp ("PLAY", c) == 0)
+                aud_drct_play ();
+            else if (g_ascii_strcasecmp ("STOP", c) == 0)
+                aud_drct_stop ();
+            else if (g_ascii_strcasecmp ("PAUSE", c) == 0)
+                aud_drct_pause ();
+            else if (g_ascii_strcasecmp ("PLAYPAUSE", c) == 0)
+                aud_drct_play_pause ();
+            else if (g_ascii_strncasecmp ("NEXT", c, 4) == 0)
+            {
+                ptr = c + 4;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+
+                if (n <= 0)
+                    n = 1;
+                for (; n > 0; n--)
+                {
+                    aud_drct_pl_next ();
+                }
+            }
+            else if (g_ascii_strncasecmp ("PREV", c, 4) == 0)
+            {
+                ptr = c + 4;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+
+                if (n <= 0)
+                    n = 1;
+                for (; n > 0; n--)
+                {
+                    aud_drct_pl_prev ();
+                }
+            }
+            else if (g_ascii_strcasecmp ("SHUFFLE", c) == 0)
+                aud_set_bool (nullptr, "shuffle", ! aud_get_bool (nullptr, "shuffle"));
+            else if (g_ascii_strcasecmp ("REPEAT", c) == 0)
+                aud_set_bool (nullptr, "repeat", ! aud_get_bool (nullptr, "repeat"));
+            else if (g_ascii_strncasecmp ("FWD", c, 3) == 0)
+            {
+                ptr = c + 3;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr) * 1000;
+
+                if (n <= 0)
+                    n = 5000;
+                output_time = aud_drct_get_time ();
+                aud_drct_seek (output_time + n);
+            }
+            else if (g_ascii_strncasecmp ("BWD", c, 3) == 0)
+            {
+                ptr = c + 3;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr) * 1000;
+
+                if (n <= 0)
+                    n = 5000;
+                output_time = aud_drct_get_time ();
+                aud_drct_seek (output_time - n);
+            }
+            else if (g_ascii_strncasecmp ("VOL_UP", c, 6) == 0)
+            {
+                ptr = c + 6;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+                if (n <= 0)
+                    n = 5;
+
+                v = aud_drct_get_volume_main ();
+                if (v > (100 - n))
+                    v = 100 - n;
+                aud_drct_set_volume_main (v + n);
+            }
+            else if (g_ascii_strncasecmp ("VOL_DOWN", c, 8) == 0)
+            {
+                ptr = c + 8;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+                if (n <= 0)
+                    n = 5;
+
+                v = aud_drct_get_volume_main ();
+                if (v < n)
+                    v = n;
+                aud_drct_set_volume_main (v - n);
+            }
+            else if (g_ascii_strcasecmp ("QUIT", c) == 0)
+            {
+                aud_quit ();
+            }
+            else if (g_ascii_strcasecmp ("MUTE", c) == 0)
+            {
+                if (mute == 0)
+                {
+                    mute = 1;
+                    /* store the master volume so
+                       we can restore it on unmute. */
+                    mute_vol = aud_drct_get_volume_main ();
+                    aud_drct_set_volume_main (0);
+                }
+                else
+                {
+                    mute = 0;
+                    aud_drct_set_volume_main (mute_vol);
+                }
+            }
+            else if (g_ascii_strncasecmp ("BAL_LEFT", c, 8) == 0)
+            {
+                ptr = c + 8;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+                if (n <= 0)
+                    n = 5;
+
+                balance = aud_drct_get_volume_balance ();
+                balance -= n;
+                if (balance < -100)
+                    balance = -100;
+                aud_drct_set_volume_balance (balance);
+            }
+            else if (g_ascii_strncasecmp ("BAL_RIGHT", c, 9) == 0)
+            {
+                ptr = c + 9;
+                while (g_ascii_isspace (*ptr))
+                    ptr++;
+                n = atoi (ptr);
+                if (n <= 0)
+                    n = 5;
+
+                balance = aud_drct_get_volume_balance ();
+                balance += n;
+                if (balance > 100)
+                    balance = 100;
+                aud_drct_set_volume_balance (balance);
+            }
+            else if (g_ascii_strcasecmp ("BAL_CENTER", c) == 0)
+            {
+                balance = 0;
+                aud_drct_set_volume_balance (balance);
+            }
+            else if (g_ascii_strcasecmp ("LIST", c) == 0)
+            {
+#if 0
+                show_pl = aud_drct_pl_win_is_visible ();
+                show_pl = (show_pl) ? 0 : 1;
+                aud_drct_pl_win_toggle (show_pl);
+#endif
+            }
+            else if (g_ascii_strcasecmp ("PLAYLIST_CLEAR", c) == 0)
+            {
+                aud_drct_stop ();
+                int playlist = aud_playlist_get_active ();
+                aud_playlist_entry_delete (playlist, 0,
+                                           aud_playlist_entry_count
+                                           (playlist));
+            }
+            else if (g_ascii_strncasecmp ("PLAYLIST_ADD ", c, 13) == 0)
+            {
+                aud_drct_pl_add (c + 13, -1);
+            }
+            else if ((strlen (c) == 1) && ((*c >= '0') || (*c <= '9')))
+            {
+                if (track_no_pos < 63)
+                {
+                    if (tid)
+                        g_source_remove (tid);
+                    track_no[track_no_pos++] = *c;
+                    track_no[track_no_pos] = 0;
+                    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);
+                }
+            }
+            else
+            {
+                AUDERR ("unknown command \"%s\"\n", c);
+            }
+        }
+        g_free (code);
+        if (ret == -1)
+            break;
+    }
+    if (ret == -1)
+    {
+        /* something went badly wrong */
+        AUDERR ("disconnected from LIRC\n");
+        aud_plugin_instance.cleanup ();
+        if (aud_get_bool ("lirc", "enable_reconnect"))
+        {
+            int reconnect_timeout = aud_get_int ("lirc", "reconnect_timeout");
+            AUDERR ("will try reconnect every %d seconds...\n", reconnect_timeout);
+            g_timeout_add (1000 * reconnect_timeout, reconnect_lirc, nullptr);
+        }
+    }
+
+    return true;
+}
+
+const char LIRCPlugin::about[] =
+ N_("A simple plugin to control Audacious using the LIRC remote control daemon\n\n"
+    "Adapted for Audacious by:\n"
+    "Tony Vroon <chainsaw at gentoo.org>\n"
+    "Joonas Harjumäki <jharjuma at gmail.com>\n\n"
+    "Based on the XMMS LIRC plugin by:\n"
+    "Carl van Schaik <carl at leg.uct.ac.za>\n"
+    "Christoph Bartelmus <xmms at bartelmus.de>\n"
+    "Andrew O. Shadoura <bugzilla at tut.by>\n\n"
+    "For more information about LIRC, see http://lirc.org.");
+
+const PreferencesWidget LIRCPlugin::widgets[] = {
+    WidgetLabel (N_("<b>Connection</b>")),
+    WidgetCheck (N_("Reconnect to LIRC server"),
+        WidgetBool ("lirc", "enable_reconnect")),
+    WidgetSpin (N_("Wait before reconnecting:"),
+        WidgetInt ("lirc", "reconnect_timeout"),
+        {1, 120, 1, N_("seconds")},
+        WIDGET_CHILD)
+};
+
+const PluginPreferences LIRCPlugin::prefs = {{widgets}};
diff --git a/src/lyricwiki-qt/Makefile b/src/lyricwiki-qt/Makefile
new file mode 100644
index 000000000000..a17bc66d7497
--- /dev/null
+++ b/src/lyricwiki-qt/Makefile
@@ -0,0 +1,14 @@
+PLUGIN = lyricwiki-qt${PLUGIN_SUFFIX}
+
+SRCS = lyricwiki.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
+
+LD = ${CXX}
+
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${QT_CFLAGS} ${GLIB_CFLAGS} ${XML_CFLAGS} -I../..
+LIBS += ${QT_LIBS} ${GLIB_LIBS}  ${XML_LIBS}
diff --git a/src/lyricwiki-qt/lyricwiki.cc b/src/lyricwiki-qt/lyricwiki.cc
new file mode 100644
index 000000000000..371909745f3d
--- /dev/null
+++ b/src/lyricwiki-qt/lyricwiki.cc
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010, 2014 William Pitcock <nenolod at dereferenced.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QTextEdit>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xpath.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/vfs_async.h>
+#include <libaudcore/runtime.h>
+
+#include <libaudqt/libaudqt.h>
+
+typedef struct {
+    String filename; /* of song file */
+    String title, artist;
+    String uri; /* URI we are trying to retrieve */
+} LyricsState;
+
+static LyricsState state;
+
+class LyricWikiQt : public GeneralPlugin {
+public:
+    static constexpr PluginInfo info = {
+        N_("LyricWiki Plugin (Qt)"),
+        PACKAGE
+    };
+
+    constexpr LyricWikiQt() : GeneralPlugin (info, false) {}
+    void * get_qt_widget ();
+};
+
+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, ...)
+{
+}
+
+/* g_free() returned text */
+static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len)
+{
+    xmlDocPtr doc;
+    char *ret = nullptr;
+
+    /*
+     * temporarily set our error-handling functor to our suppression function,
+     * but we have to set it back because other components of Audacious depend
+     * on libxml and we don't want to step on their code paths.
+     *
+     * unfortunately, libxml is anti-social and provides us with no way to get
+     * 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);
+
+    if (doc != nullptr)
+    {
+        xmlXPathContextPtr xpath_ctx = nullptr;
+        xmlXPathObjectPtr xpath_obj = nullptr;
+        xmlNodePtr node = nullptr;
+
+        xpath_ctx = xmlXPathNewContext(doc);
+        if (xpath_ctx == nullptr)
+            goto give_up;
+
+        xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx);
+        if (xpath_obj == nullptr)
+            goto give_up;
+
+        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_ctx != nullptr)
+            xmlXPathFreeContext(xpath_ctx);
+
+        if (node != nullptr)
+        {
+            xmlChar *lyric = xmlNodeGetContent(node);
+
+            if (lyric != nullptr)
+            {
+                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);
+
+                ret = g_match_info_fetch(match_info, 2);
+                if (!g_utf8_collate(ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->"))
+                {
+                    g_free(ret);
+                    ret = g_strdup(_("No lyrics available"));
+                }
+
+                g_regex_unref(reg);
+            }
+
+            xmlFree(lyric);
+        }
+
+        xmlFreeDoc(doc);
+    }
+
+    return ret;
+}
+
+static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t len)
+{
+    xmlDocPtr doc;
+    String uri;
+
+    /*
+     * workaround buggy lyricwiki search output where it cuts the lyrics
+     * halfway through the UTF-8 symbol resulting in invalid XML.
+     */
+    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);
+
+    /*
+     * temporarily set our error-handling functor to our suppression function,
+     * but we have to set it back because other components of Audacious depend
+     * on libxml and we don't want to step on their code paths.
+     *
+     * unfortunately, libxml is anti-social and provides us with no way to get
+     * 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);
+
+    if (doc != nullptr)
+    {
+        xmlNodePtr root, cur;
+
+        root = xmlDocGetRootElement(doc);
+
+        for (cur = root->xmlChildrenNode; cur; cur = cur->next)
+        {
+            if (xmlStrEqual(cur->name, (xmlChar *) "url"))
+            {
+                xmlChar *lyric;
+                char *basename;
+
+                lyric = xmlNodeGetContent(cur);
+                basename = g_path_get_basename((char *) lyric);
+
+                uri = String (str_printf ("http://lyrics.wikia.com/index.php?"
+                 "action=edit&title=%s", basename));
+
+                g_free(basename);
+                xmlFree(lyric);
+            }
+        }
+
+        xmlFreeDoc(doc);
+    }
+
+    g_free(newbuf);
+
+    return uri;
+}
+
+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*)
+{
+    if (!state.uri || strcmp(state.uri, uri))
+        return;
+
+    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());
+
+    if (!lyrics)
+    {
+        update_lyrics_window (_("Error"), nullptr,
+         str_printf (_("Unable to parse %s"), uri));
+        return;
+    }
+
+    update_lyrics_window(state.title, state.artist, lyrics);
+
+    g_free(lyrics);
+}
+
+static void get_lyrics_step_2(const char *uri1, const Index<char> &buf, void*)
+{
+    if (!state.uri || strcmp(state.uri, uri1))
+        return;
+
+    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());
+
+    if (!uri)
+    {
+        update_lyrics_window (_("Error"), nullptr,
+         str_printf (_("Unable to parse %s"), uri1));
+        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);
+}
+
+static void get_lyrics_step_1(void)
+{
+    if(!state.artist || !state.title)
+    {
+        update_lyrics_window(_("Error"), nullptr, _("Missing song metadata"));
+        return;
+    }
+
+    StringBuf title_buf = str_encode_percent (state.title);
+    StringBuf artist_buf = str_encode_percent (state.artist);
+
+    state.uri = String (str_printf ("http://lyrics.wikia.com/api.php?"
+     "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);
+}
+
+static QTextEdit * textedit;
+
+static void update_lyrics_window(const char *title, const char *artist, const char *lyrics)
+{
+    QTextDocument doc;
+    QTextCursor cursor (& doc);
+
+    if (! textedit)
+        return;
+
+    cursor.insertHtml (QString ("<big>") + QString (title) + QString ("</big>"));
+
+    if (artist != nullptr)
+    {
+        cursor.insertHtml (QString ("<br><i>") + QString (artist) + QString ("</i>"));
+    }
+
+    cursor.insertHtml ("<br>");
+    cursor.insertText (lyrics);
+
+    AUDDBG ("update document <%p>\n", textedit);
+
+    textedit->setDocument (doc.clone ());
+}
+
+static void lyricwiki_playback_began(void)
+{
+    /* FIXME: cancel previous VFS requests (not possible with current API) */
+
+    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);
+
+    state.uri = String ();
+
+    get_lyrics_step_1();
+}
+
+static void lw_cleanup (QObject * object = nullptr)
+{
+    state.filename = String ();
+    state.title = String ();
+    state.artist = String ();
+    state.uri = String ();
+
+    hook_dissociate ("tuple change", (HookFunction) lyricwiki_playback_began);
+    hook_dissociate ("playback ready", (HookFunction) lyricwiki_playback_began);
+
+    textedit = nullptr;
+}
+
+void * LyricWikiQt::get_qt_widget ()
+{
+    textedit = new QTextEdit;
+    textedit->setReadOnly (true);
+
+    hook_associate ("tuple change", (HookFunction) lyricwiki_playback_began, nullptr);
+    hook_associate ("playback ready", (HookFunction) lyricwiki_playback_began, nullptr);
+
+    if (aud_drct_get_ready ())
+        lyricwiki_playback_began ();
+
+    QObject::connect (textedit, &QObject::destroyed, lw_cleanup);
+
+    return textedit;
+}
diff --git a/src/lyricwiki/Makefile b/src/lyricwiki/Makefile
index 91cc27bd1efe..fe1381a93458 100644
--- a/src/lyricwiki/Makefile
+++ b/src/lyricwiki/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = lyricwiki${PLUGIN_SUFFIX}
 
-SRCS = lyricwiki.c
+SRCS = lyricwiki.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${XML_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} ${GLIB_LIBS}  ${XML_LIBS}
diff --git a/src/lyricwiki/lyricwiki.c b/src/lyricwiki/lyricwiki.c
deleted file mode 100644
index 0095b16ed941..000000000000
--- a/src/lyricwiki/lyricwiki.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <glib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/HTMLparser.h>
-#include <libxml/xpath.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <audacious/plugins.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudcore/vfs_async.h>
-
-/* all strings in this struct are pooled */
-typedef struct {
-	char *filename; /* of song file */
-	char *title, *artist;
-	char *uri; /* URI we are trying to retrieve */
-} LyricsState;
-
-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, ...)
-{
-}
-
-/* g_free() returned text */
-static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len)
-{
-	xmlDocPtr doc;
-	gchar *ret = NULL;
-
-	/*
-	 * temporarily set our error-handling functor to our suppression function,
-	 * but we have to set it back because other components of Audacious depend
-	 * on libxml and we don't want to step on their code paths.
-	 *
-	 * unfortunately, libxml is anti-social and provides us with no way to get
-	 * the previous error functor, so we just have to set it back to default after
-	 * parsing and hope for the best.
-	 */
-	xmlSetGenericErrorFunc(NULL, libxml_error_handler);
-	doc = htmlReadMemory(buf, (int) len, NULL, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET));
-	xmlSetGenericErrorFunc(NULL, NULL);
-
-	if (doc != NULL)
-	{
-		xmlXPathContextPtr xpath_ctx = NULL;
-		xmlXPathObjectPtr xpath_obj = NULL;
-		xmlNodePtr node = NULL;
-
-		xpath_ctx = xmlXPathNewContext(doc);
-		if (xpath_ctx == NULL)
-			goto give_up;
-
-		xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx);
-		if (xpath_obj == NULL)
-			goto give_up;
-
-		if (!xpath_obj->nodesetval->nodeMax)
-			goto give_up;
-
-		node = xpath_obj->nodesetval->nodeTab[0];
-give_up:
-		if (xpath_obj != NULL)
-			xmlXPathFreeObject(xpath_obj);
-
-		if (xpath_ctx != NULL)
-			xmlXPathFreeContext(xpath_ctx);
-
-		if (node != NULL)
-		{
-			xmlChar *lyric = xmlNodeGetContent(node);
-
-			if (lyric != NULL)
-			{
-				GMatchInfo *match_info;
-				GRegex *reg;
-
-				reg = g_regex_new("<(lyrics?)>[[:space:]]*(.*?)[[:space:]]*</\\1>", (G_REGEX_MULTILINE | G_REGEX_DOTALL), 0, NULL);
-				g_regex_match(reg, (gchar *) 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) -->"))
-				{
-					g_free(ret);
-					ret = g_strdup(_("No lyrics available"));
-				}
-
-				g_regex_unref(reg);
-			}
-
-			xmlFree(lyric);
-		}
-
-		xmlFreeDoc(doc);
-	}
-
-	return ret;
-}
-
-/* str_unref() returned string */
-static char *scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t len)
-{
-	xmlDocPtr doc;
-	gchar *uri = NULL;
-
-	/*
-	 * workaround buggy lyricwiki search output where it cuts the lyrics
-	 * halfway through the UTF-8 symbol resulting in invalid XML.
-	 */
-	GRegex *reg;
-
-	reg = g_regex_new("<(lyrics?)>.*</\\1>", (G_REGEX_MULTILINE | G_REGEX_DOTALL | G_REGEX_UNGREEDY), 0, NULL);
-	gchar *newbuf = g_regex_replace_literal(reg, buf, len, 0, "", G_REGEX_MATCH_NEWLINE_ANY, NULL);
-	g_regex_unref(reg);
-
-	/*
-	 * temporarily set our error-handling functor to our suppression function,
-	 * but we have to set it back because other components of Audacious depend
-	 * on libxml and we don't want to step on their code paths.
-	 *
-	 * unfortunately, libxml is anti-social and provides us with no way to get
-	 * the previous error functor, so we just have to set it back to default after
-	 * parsing and hope for the best.
-	 */
-	xmlSetGenericErrorFunc(NULL, libxml_error_handler);
-	doc = xmlParseMemory(newbuf, strlen(newbuf));
-	xmlSetGenericErrorFunc(NULL, NULL);
-
-	if (doc != NULL)
-	{
-		xmlNodePtr root, cur;
-
-		root = xmlDocGetRootElement(doc);
-
-		for (cur = root->xmlChildrenNode; cur; cur = cur->next)
-		{
-			if (xmlStrEqual(cur->name, (xmlChar *) "url"))
-			{
-				xmlChar *lyric;
-				gchar *basename;
-
-				lyric = xmlNodeGetContent(cur);
-				basename = g_path_get_basename((gchar *) lyric);
-
-				uri = str_printf("http://lyrics.wikia.com/index.php?action=edit"
-				 "&title=%s", basename);
-
-				g_free(basename);
-				xmlFree(lyric);
-			}
-		}
-
-		xmlFreeDoc(doc);
-	}
-
-	g_free(newbuf);
-
-	return uri;
-}
-
-static void update_lyrics_window(const char *title, const char *artist, const char *lyrics);
-
-static bool_t get_lyrics_step_3(void *buf, int64_t len, void *requri)
-{
-	if (!state.uri || strcmp(state.uri, requri))
-	{
-		g_free(buf);
-		str_unref(requri);
-		return FALSE;
-	}
-	str_unref(requri);
-
-	if(!len)
-	{
-		SPRINTF(error, _("Unable to fetch %s"), state.uri);
-		update_lyrics_window(_("Error"), NULL, error);
-		g_free(buf);
-		return FALSE;
-	}
-
-	char *lyrics = scrape_lyrics_from_lyricwiki_edit_page(buf, len);
-
-	if(!lyrics)
-	{
-		SPRINTF(error, _("Unable to parse %s"), state.uri);
-		update_lyrics_window(_("Error"), NULL, error);
-		g_free(buf);
-		return FALSE;
-	}
-
-	update_lyrics_window(state.title, state.artist, lyrics);
-
-	g_free(lyrics);
-	return TRUE;
-}
-
-static bool_t get_lyrics_step_2(void *buf, int64_t len, void *requri)
-{
-	if (strcmp(state.uri, requri))
-	{
-		g_free(buf);
-		str_unref(requri);
-		return FALSE;
-	}
-	str_unref(requri);
-
-	if(!len)
-	{
-		SPRINTF(error, _("Unable to fetch %s"), state.uri);
-		update_lyrics_window(_("Error"), NULL, error);
-		g_free(buf);
-		return FALSE;
-	}
-
-	char *uri = scrape_uri_from_lyricwiki_search_result(buf, len);
-
-	if(!uri)
-	{
-		SPRINTF(error, _("Unable to parse %s"), state.uri);
-		update_lyrics_window(_("Error"), NULL, error);
-		g_free(buf);
-		return FALSE;
-	}
-
-	str_unref(state.uri);
-	state.uri = uri;
-
-	update_lyrics_window(state.title, state.artist, _("Looking for lyrics ..."));
-	vfs_async_file_get_contents(uri, get_lyrics_step_3, str_ref(state.uri));
-
-	g_free(buf);
-	return TRUE;
-}
-
-static void get_lyrics_step_1(void)
-{
-	if(!state.artist || !state.title)
-	{
-		update_lyrics_window(_("Error"), NULL, _("Missing song metadata"));
-		return;
-	}
-
-	char title_buf[strlen(state.title) * 3 + 1];
-	char artist_buf[strlen(state.artist) * 3 + 1];
-	str_encode_percent(state.title, -1, title_buf);
-	str_encode_percent(state.artist, -1, artist_buf);
-
-	str_unref(state.uri);
-	state.uri = str_printf("http://lyrics.wikia.com/api.php?action=lyrics&"
-	 "artist=%s&song=%s&fmt=xml", artist_buf, 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, str_ref(state.uri));
-}
-
-static GtkWidget *scrollview, *vbox;
-static GtkWidget *textview;
-static GtkTextBuffer *textbuffer;
-
-static GtkWidget *build_widget(void)
-{
-	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));
-
-	scrollview = gtk_scrolled_window_new(NULL, NULL);
-	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_box_new(GTK_ORIENTATION_VERTICAL, 10);
-
-	gtk_container_add(GTK_CONTAINER(scrollview), textview);
-
-	gtk_box_pack_start(GTK_BOX(vbox), scrollview, TRUE, TRUE, 0);
-
-	gtk_widget_show(textview);
-	gtk_widget_show(scrollview);
-	gtk_widget_show(vbox);
-
-	gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "weight_bold", "weight", PANGO_WEIGHT_BOLD, NULL);
-	gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "size_x_large", "scale", PANGO_SCALE_X_LARGE, NULL);
-	gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "style_italic", "style", PANGO_STYLE_ITALIC, NULL);
-
-	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)
-{
-	GtkTextIter iter;
-
-	if (textbuffer == NULL)
-		return;
-
-	gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuffer), "", -1);
-
-	gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter);
-
-	gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), &iter,
-			title, -1, "weight_bold", "size_x_large", NULL);
-
-	if (artist != NULL)
-	{
-		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", NULL);
-	}
-
-	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_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter);
-	gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview), &iter, 0, TRUE, 0, 0);
-}
-
-static void lyricwiki_playback_began(void)
-{
-	if (!aud_drct_get_playing())
-		return;
-
-	/* FIXME: cancel previous VFS requests (not possible with current API) */
-	str_unref(state.filename);
-	str_unref(state.title);
-	str_unref(state.artist);
-	str_unref(state.uri);
-
-	int playlist = aud_playlist_get_playing();
-	int pos = aud_playlist_get_position(playlist);
-
-	state.filename = aud_playlist_entry_get_filename(playlist, pos);
-	aud_playlist_entry_describe(playlist, pos, &state.title, &state.artist, NULL, FALSE);
-	state.uri = NULL;
-
-	get_lyrics_step_1();
-}
-
-static gboolean init (void)
-{
-	hook_associate("title change", (HookFunction) lyricwiki_playback_began, NULL);
-	hook_associate("playback ready", (HookFunction) lyricwiki_playback_began, NULL);
-
-	build_widget();
-
-	lyricwiki_playback_began();
-	return TRUE;
-}
-
-static void cleanup(void)
-{
-	str_unref(state.filename);
-	str_unref(state.title);
-	str_unref(state.artist);
-	str_unref(state.uri);
-	state.filename = NULL;
-	state.title = NULL;
-	state.artist = NULL;
-	state.uri = NULL;
-
-	hook_dissociate("title change", (HookFunction) lyricwiki_playback_began);
-	hook_dissociate("playback ready", (HookFunction) lyricwiki_playback_began);
-
-	if (vbox)
-		gtk_widget_destroy (vbox);
-	textbuffer = NULL;
-}
-
-static void *get_widget(void)
-{
-	if (! vbox)
-		build_widget ();
-	return vbox;
-}
-
-AUD_GENERAL_PLUGIN
-(
-	.name = N_("LyricWiki Plugin"),
-	.domain = PACKAGE,
-	.init = init,
-	.cleanup = cleanup,
-	.get_widget = get_widget,
-)
diff --git a/src/lyricwiki/lyricwiki.cc b/src/lyricwiki/lyricwiki.cc
new file mode 100644
index 000000000000..ca7f9f83545a
--- /dev/null
+++ b/src/lyricwiki/lyricwiki.cc
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xpath.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/vfs_async.h>
+
+class LyricWiki : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("LyricWiki Plugin"),
+        PACKAGE
+    };
+
+    constexpr LyricWiki () : GeneralPlugin (info, false) {}
+
+    void * get_gtk_widget ();
+};
+
+EXPORT LyricWiki aud_plugin_instance;
+
+typedef struct {
+    String filename; /* of song file */
+    String title, artist;
+    String uri; /* URI we are trying to retrieve */
+} LyricsState;
+
+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, ...)
+{
+}
+
+/* g_free() returned text */
+static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len)
+{
+    xmlDocPtr doc;
+    char *ret = nullptr;
+
+    /*
+     * temporarily set our error-handling functor to our suppression function,
+     * but we have to set it back because other components of Audacious depend
+     * on libxml and we don't want to step on their code paths.
+     *
+     * unfortunately, libxml is anti-social and provides us with no way to get
+     * 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);
+
+    if (doc != nullptr)
+    {
+        xmlXPathContextPtr xpath_ctx = nullptr;
+        xmlXPathObjectPtr xpath_obj = nullptr;
+        xmlNodePtr node = nullptr;
+
+        xpath_ctx = xmlXPathNewContext(doc);
+        if (xpath_ctx == nullptr)
+            goto give_up;
+
+        xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx);
+        if (xpath_obj == nullptr)
+            goto give_up;
+
+        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_ctx != nullptr)
+            xmlXPathFreeContext(xpath_ctx);
+
+        if (node != nullptr)
+        {
+            xmlChar *lyric = xmlNodeGetContent(node);
+
+            if (lyric != nullptr)
+            {
+                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);
+
+                ret = g_match_info_fetch(match_info, 2);
+                if (!g_utf8_collate(ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->"))
+                {
+                    g_free(ret);
+                    ret = g_strdup(_("No lyrics available"));
+                }
+
+                g_regex_unref(reg);
+            }
+
+            xmlFree(lyric);
+        }
+
+        xmlFreeDoc(doc);
+    }
+
+    return ret;
+}
+
+static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t len)
+{
+    xmlDocPtr doc;
+    String uri;
+
+    /*
+     * workaround buggy lyricwiki search output where it cuts the lyrics
+     * halfway through the UTF-8 symbol resulting in invalid XML.
+     */
+    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);
+
+    /*
+     * temporarily set our error-handling functor to our suppression function,
+     * but we have to set it back because other components of Audacious depend
+     * on libxml and we don't want to step on their code paths.
+     *
+     * unfortunately, libxml is anti-social and provides us with no way to get
+     * 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);
+
+    if (doc != nullptr)
+    {
+        xmlNodePtr root, cur;
+
+        root = xmlDocGetRootElement(doc);
+
+        for (cur = root->xmlChildrenNode; cur; cur = cur->next)
+        {
+            if (xmlStrEqual(cur->name, (xmlChar *) "url"))
+            {
+                xmlChar *lyric;
+                char *basename;
+
+                lyric = xmlNodeGetContent(cur);
+                basename = g_path_get_basename((char *) lyric);
+
+                uri = String (str_printf ("http://lyrics.wikia.com/index.php?"
+                 "action=edit&title=%s", basename));
+
+                g_free(basename);
+                xmlFree(lyric);
+            }
+        }
+
+        xmlFreeDoc(doc);
+    }
+
+    g_free(newbuf);
+
+    return uri;
+}
+
+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*)
+{
+    if (!state.uri || strcmp(state.uri, uri))
+        return;
+
+    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());
+
+    if (!lyrics)
+    {
+        update_lyrics_window (_("Error"), nullptr,
+         str_printf (_("Unable to parse %s"), uri));
+        return;
+    }
+
+    update_lyrics_window(state.title, state.artist, lyrics);
+
+    g_free(lyrics);
+}
+
+static void get_lyrics_step_2(const char *uri1, const Index<char> &buf, void*)
+{
+    if (!state.uri || strcmp(state.uri, uri1))
+        return;
+
+    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());
+
+    if (!uri)
+    {
+        update_lyrics_window (_("Error"), nullptr,
+         str_printf (_("Unable to parse %s"), uri1));
+        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);
+}
+
+static void get_lyrics_step_1(void)
+{
+    if(!state.artist || !state.title)
+    {
+        update_lyrics_window(_("Error"), nullptr, _("Missing song metadata"));
+        return;
+    }
+
+    StringBuf title_buf = str_encode_percent (state.title);
+    StringBuf artist_buf = str_encode_percent (state.artist);
+
+    state.uri = String (str_printf ("http://lyrics.wikia.com/api.php?"
+     "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);
+}
+
+static GtkWidget *scrollview, *vbox;
+static GtkWidget *textview;
+static GtkTextBuffer *textbuffer;
+
+static GtkWidget *build_widget(void)
+{
+    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));
+
+    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);
+
+    gtk_container_add(GTK_CONTAINER(scrollview), textview);
+
+    gtk_box_pack_start(GTK_BOX(vbox), scrollview, TRUE, TRUE, 0);
+
+    gtk_widget_show(textview);
+    gtk_widget_show(scrollview);
+    gtk_widget_show(vbox);
+
+    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);
+
+    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)
+{
+    GtkTextIter iter;
+
+    if (textbuffer == nullptr)
+        return;
+
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuffer), "", -1);
+
+    gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter);
+
+    gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), &iter,
+            title, -1, "weight_bold", "size_x_large", nullptr);
+
+    if (artist != nullptr)
+    {
+        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(GTK_TEXT_BUFFER(textbuffer), &iter, "\n\n", -1);
+    gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, lyrics, -1);
+
+    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);
+}
+
+static void lyricwiki_playback_began(void)
+{
+    /* FIXME: cancel previous VFS requests (not possible with current API) */
+
+    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);
+
+    state.uri = String ();
+
+    get_lyrics_step_1();
+}
+
+static void destroy_cb ()
+{
+    state.filename = String ();
+    state.title = String ();
+    state.artist = String ();
+    state.uri = String ();
+
+    hook_dissociate ("tuple change", (HookFunction) lyricwiki_playback_began);
+    hook_dissociate ("playback ready", (HookFunction) lyricwiki_playback_began);
+
+    textbuffer = nullptr;
+}
+
+void * LyricWiki::get_gtk_widget ()
+{
+    build_widget ();
+
+    hook_associate ("tuple change", (HookFunction) lyricwiki_playback_began, nullptr);
+    hook_associate ("playback ready", (HookFunction) lyricwiki_playback_began, nullptr);
+
+    if (aud_drct_get_ready ())
+        lyricwiki_playback_began ();
+
+    g_signal_connect (vbox, "destroy", destroy_cb, nullptr);
+
+    return vbox;
+}
diff --git a/src/m3u/Makefile b/src/m3u/Makefile
index 5e153a3e0a86..1ae9eee8d8c7 100644
--- a/src/m3u/Makefile
+++ b/src/m3u/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = m3u${PLUGIN_SUFFIX}
 
-SRCS = m3u.c
+SRCS = m3u.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/m3u/m3u.c b/src/m3u/m3u.c
deleted file mode 100644
index a37fff9465c0..000000000000
--- a/src/m3u/m3u.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006-2010 William Pitcock, Tony Vroon, George Averill, Giacomo
- *  Lozito, Derek Pomery and Yoshiki Yazawa, and 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; 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.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-static void strip_char (char * text, char c)
-{
-    char * set = text;
-    char a;
-
-    while ((a = * text ++))
-        if (a != c)
-            * set ++ = a;
-
-    * set = 0;
-}
-
-static char * read_win_text (VFSFile * file)
-{
-    void * raw = NULL;
-    vfs_file_read_all (file, & raw, NULL);
-    if (! raw)
-        return NULL;
-
-    strip_char (raw, '\r');
-    return raw;
-}
-
-static char * split_line (char * line)
-{
-    char * feed = strchr (line, '\n');
-    if (! feed)
-        return NULL;
-
-    * feed = 0;
-    return feed + 1;
-}
-
-static bool_t playlist_load_m3u (const char * path, VFSFile * file,
- char * * title, Index * filenames, Index * tuples)
-{
-    char * text = read_win_text (file);
-    if (! text)
-        return FALSE;
-
-    * title = NULL;
-
-    char * parse = text;
-
-    while (parse)
-    {
-        char * next = split_line (parse);
-
-        while (* parse == ' ' || * parse == '\t')
-            parse ++;
-
-        if (! * parse)
-            goto NEXT;
-
-        if (* parse == '#')
-            goto NEXT;
-
-        char * s = aud_construct_uri (parse, path);
-        if (s)
-            index_insert (filenames, -1, s);
-
-NEXT:
-        parse = next;
-    }
-
-    g_free (text);
-    return TRUE;
-}
-
-static bool_t playlist_save_m3u (const char * path, VFSFile * file,
- const char * title, Index * filenames, Index * tuples)
-{
-    int count = index_count (filenames);
-
-    for (int i = 0; i < count; i ++)
-        vfs_fprintf (file, "%s\n", (const char *) index_get (filenames, i));
-
-    return TRUE;
-}
-
-static const char * const m3u_exts[] = {"m3u", "m3u8", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
- .name = N_("M3U Playlists"),
- .domain = PACKAGE,
- .extensions = m3u_exts,
- .load = playlist_load_m3u,
- .save = playlist_save_m3u
-)
diff --git a/src/m3u/m3u.cc b/src/m3u/m3u.cc
new file mode 100644
index 000000000000..0ce63af765b5
--- /dev/null
+++ b/src/m3u/m3u.cc
@@ -0,0 +1,117 @@
+/*
+ * Audacious: A cross-platform multimedia player
+ * Copyright (c) 2006-2010 William Pitcock, Tony Vroon, George Averill, Giacomo
+ *  Lozito, Derek Pomery and Yoshiki Yazawa, and 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; 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.
+ */
+
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+static const char * const m3u_exts[] = {"m3u", "m3u8"};
+
+class M3ULoader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("M3U Playlists"), PACKAGE};
+
+    constexpr M3ULoader () : PlaylistPlugin (info, m3u_exts, true) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+    bool save (const char * filename, VFSFile & file, const char * title,
+     const Index<PlaylistAddItem> & items);
+};
+
+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;
+    return feed + 1;
+}
+
+bool M3ULoader::load (const char * path, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    Index<char> text = read_win_text (file);
+    if (! text.len ())
+        return false;
+
+    char * parse = text.begin ();
+
+    while (parse)
+    {
+        char * next = split_line (parse);
+
+        while (* parse == ' ' || * parse == '\t')
+            parse ++;
+
+        if (* parse && * parse != '#')
+        {
+            StringBuf s = uri_construct (parse, path);
+            if (s)
+                items.append (String (s));
+        }
+
+        parse = next;
+    }
+
+    return true;
+}
+
+bool M3ULoader::save (const char * path, VFSFile & file, const char * title,
+ const Index<PlaylistAddItem> & items)
+{
+    for (auto & item : items)
+    {
+        StringBuf line = str_concat ({item.filename, "\n"});
+        if (file.fwrite (line, 1, line.len ()) != line.len ())
+            return false;
+    }
+
+    return true;
+}
diff --git a/src/mac-media-keys/MacMediaKeys.h b/src/mac-media-keys/MacMediaKeys.h
new file mode 100644
index 000000000000..d4fbce2f4215
--- /dev/null
+++ b/src/mac-media-keys/MacMediaKeys.h
@@ -0,0 +1,40 @@
+/*
+ * MacMediaKeys.h
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 MAC_MEDIA_KEYS_H
+#define MAC_MEDIA_KEYS_H
+
+#import "SPMediaKeyTap.h"
+
+ at interface SPMediaKeyTapAppDelegate : NSObject <NSApplicationDelegate>
+ at end
+
+class MacMediaKeys
+{
+public:
+    MacMediaKeys ();
+    ~MacMediaKeys ();
+    SPMediaKeyTapAppDelegate * delegate;
+    SPMediaKeyTap * keyTap;
+
+private:
+    void run ();
+};
+
+#endif
diff --git a/src/mac-media-keys/MacMediaKeys.mm b/src/mac-media-keys/MacMediaKeys.mm
new file mode 100644
index 000000000000..444faff8f0c1
--- /dev/null
+++ b/src/mac-media-keys/MacMediaKeys.mm
@@ -0,0 +1,103 @@
+/*
+ * MacMediaKeys.mm
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 <thread>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#import "MacMediaKeys.h"
+
+static MacMediaKeys * media;
+
+ at implementation SPMediaKeyTapAppDelegate
+- (void)mediaKeyTap:(SPMediaKeyTap *)keyTap receivedMediaKeyEvent:(NSEvent *)event;
+{
+    assert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys);
+
+    int keyCode = (([event data1] & 0xFFFF0000) >> 16);
+    int keyFlags = ([event data1] & 0x0000FFFF);
+    int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
+    // int keyRepeat = (keyFlags & 0x1);
+
+    if (keyState == 1)
+    {
+        switch (keyCode)
+        {
+            case NX_KEYTYPE_PLAY:
+                aud_drct_play_pause ();
+                return;
+
+            case NX_KEYTYPE_FAST:
+            case NX_KEYTYPE_NEXT:
+                aud_drct_pl_next ();
+                return;
+
+            case NX_KEYTYPE_REWIND:
+            case NX_KEYTYPE_PREVIOUS:
+                aud_drct_pl_prev ();
+                return;
+        }
+    }
+}
+ at end
+
+MacMediaKeys::MacMediaKeys ()
+{
+    std::thread thread (&MacMediaKeys::run, this);
+    thread.detach ();
+}
+
+MacMediaKeys::~MacMediaKeys ()
+{
+    [keyTap stopWatchingMediaKeys];
+}
+
+void MacMediaKeys::run ()
+{
+    // Register defaults for the whitelist of apps that want to use media keys
+    [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
+        [SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey,
+    nil]];
+
+    delegate = [SPMediaKeyTapAppDelegate alloc];
+    keyTap   = [[SPMediaKeyTap alloc] initWithDelegate: delegate];
+
+    if ([SPMediaKeyTap usesGlobalMediaKeyTap])
+        [keyTap startWatchingMediaKeys];
+}
+
+bool mac_media_keys_init ()
+{
+    media = new MacMediaKeys;
+    return true;
+}
+
+void mac_media_keys_cleanup ()
+{
+    delete media;
+}
+
+#define AUD_PLUGIN_NAME        N_("Mac Media Keys")
+#define AUD_PLUGIN_INIT        mac_media_keys_init
+#define AUD_PLUGIN_CLEANUP     mac_media_keys_cleanup
+
+#define AUD_DECLARE_GENERAL
+#include <libaudcore/plugin-declare.h>
diff --git a/src/mac-media-keys/Makefile b/src/mac-media-keys/Makefile
new file mode 100644
index 000000000000..3aaeee9424e7
--- /dev/null
+++ b/src/mac-media-keys/Makefile
@@ -0,0 +1,16 @@
+PLUGIN = mac-media-keys${PLUGIN_SUFFIX}
+
+SRCS = MacMediaKeys.mm \
+       SPInvocationGrabbing.m \
+       SPMediaKeyTap.m
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
+
+LD = ${OBJCXX}
+
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -framework AppKit
diff --git a/src/mac-media-keys/SPInvocationGrabbing.h b/src/mac-media-keys/SPInvocationGrabbing.h
new file mode 100644
index 000000000000..87dd23984994
--- /dev/null
+++ b/src/mac-media-keys/SPInvocationGrabbing.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (c) 2011, Joachim Bengtsson
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import <Foundation/Foundation.h>
+
+ at interface SPInvocationGrabber : NSObject {
+    id _object;
+    NSInvocation *_invocation;
+    int frameCount;
+    char **frameStrings;
+    BOOL backgroundAfterForward;
+    BOOL onMainAfterForward;
+    BOOL waitUntilDone;
+}
+-(id)initWithObject:(id)obj;
+-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
+ at property (readonly, retain, nonatomic) id object;
+ at property (readonly, retain, nonatomic) NSInvocation *invocation;
+ at property BOOL backgroundAfterForward;
+ at property BOOL onMainAfterForward;
+ at property BOOL waitUntilDone;
+-(void)invoke; // will release object and invocation
+-(void)printBacktrace;
+-(void)saveBacktrace;
+ at end
+
+ at interface NSObject (SPInvocationGrabbing)
+-(id)grab;
+-(id)invokeAfter:(NSTimeInterval)delta;
+-(id)nextRunloop;
+-(id)inBackground;
+-(id)onMainAsync:(BOOL)async;
+ at end
diff --git a/src/mac-media-keys/SPInvocationGrabbing.m b/src/mac-media-keys/SPInvocationGrabbing.m
new file mode 100644
index 000000000000..5b16d0091030
--- /dev/null
+++ b/src/mac-media-keys/SPInvocationGrabbing.m
@@ -0,0 +1,138 @@
+/*
+ Copyright (c) 2011, Joachim Bengtsson
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#import "SPInvocationGrabbing.h"
+#import <execinfo.h>
+
+#pragma mark Invocation grabbing
+ at interface SPInvocationGrabber ()
+ at property (readwrite, retain, nonatomic) id object;
+ at property (readwrite, retain, nonatomic) NSInvocation *invocation;
+
+ at end
+
+ at implementation SPInvocationGrabber
+- (id)initWithObject:(id)obj;
+{
+	return [self initWithObject:obj stacktraceSaving:YES];
+}
+
+-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
+{
+	self.object = obj;
+
+	if(saveStack)
+		[self saveBacktrace];
+
+	return self;
+}
+-(void)dealloc;
+{
+	free(frameStrings);
+	self.object = nil;
+	self.invocation = nil;
+	[super dealloc];
+}
+ at synthesize invocation = _invocation, object = _object;
+
+ at synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone;
+- (void)runInBackground;
+{
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+	@try {
+		[self invoke];
+	}
+	@finally {
+		[pool drain];
+	}
+}
+
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+	[anInvocation retainArguments];
+	anInvocation.target = _object;
+	self.invocation = anInvocation;
+
+	if(backgroundAfterForward)
+		[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil];
+	else if(onMainAfterForward)
+        [self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone];
+}
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector {
+	NSMethodSignature *signature = [super methodSignatureForSelector:inSelector];
+	if (signature == NULL)
+		signature = [_object methodSignatureForSelector:inSelector];
+
+	return signature;
+}
+
+- (void)invoke;
+{
+
+	@try {
+		[_invocation invoke];
+	}
+	@catch (NSException * e) {
+		NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e);
+		[self printBacktrace];
+		printf("\n");
+		[e raise];
+	}
+
+	self.invocation = nil;
+	self.object = nil;
+}
+
+-(void)saveBacktrace;
+{
+  void *backtraceFrames[128];
+  frameCount = backtrace(&backtraceFrames[0], 128);
+  frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount);
+}
+-(void)printBacktrace;
+{
+	for(int x = 3; x < frameCount; x++) {
+		if(frameStrings[x] == NULL) { break; }
+		printf("%s\n", frameStrings[x]);
+	}
+}
+ at end
+
+ at implementation NSObject (SPInvocationGrabbing)
+-(id)grab;
+{
+	return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease];
+}
+-(id)invokeAfter:(NSTimeInterval)delta;
+{
+	id grabber = [self grab];
+	[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO];
+	return grabber;
+}
+- (id)nextRunloop;
+{
+	return [self invokeAfter:0];
+}
+-(id)inBackground;
+{
+    SPInvocationGrabber *grabber = [self grab];
+	grabber.backgroundAfterForward = YES;
+	return grabber;
+}
+-(id)onMainAsync:(BOOL)async;
+{
+    SPInvocationGrabber *grabber = [self grab];
+	grabber.onMainAfterForward = YES;
+    grabber.waitUntilDone = !async;
+	return grabber;
+}
+
+ at end
diff --git a/src/mac-media-keys/SPMediaKeyTap.h b/src/mac-media-keys/SPMediaKeyTap.h
new file mode 100644
index 000000000000..61b98a12fe95
--- /dev/null
+++ b/src/mac-media-keys/SPMediaKeyTap.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2011, Joachim Bengtsson
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <Cocoa/Cocoa.h>
+#import <IOKit/hidsystem/ev_keymap.h>
+#import <Carbon/Carbon.h>
+
+// http://overooped.com/post/2593597587/mediakeys
+
+#define SPSystemDefinedEventMediaKeys 8
+
+ at interface SPMediaKeyTap : NSObject {
+	EventHandlerRef _app_switching_ref;
+	EventHandlerRef _app_terminating_ref;
+	CFMachPortRef _eventPort;
+	CFRunLoopSourceRef _eventPortSource;
+	CFRunLoopRef _tapThreadRL;
+	BOOL _shouldInterceptMediaKeyEvents;
+	id _delegate;
+	// The app that is frontmost in this list owns media keys
+	NSMutableArray *_mediaKeyAppList;
+}
++ (NSArray*)defaultMediaKeyUserBundleIdentifiers;
+
+-(id)initWithDelegate:(id)delegate;
+
++(BOOL)usesGlobalMediaKeyTap;
+-(void)startWatchingMediaKeys;
+-(void)stopWatchingMediaKeys;
+-(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event;
+ at end
+
+ at interface NSObject (SPMediaKeyTapDelegate)
+-(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
+ at end
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey;
+extern NSString *kIgnoreMediaKeysDefaultsKey;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/mac-media-keys/SPMediaKeyTap.m b/src/mac-media-keys/SPMediaKeyTap.m
new file mode 100644
index 000000000000..d3fb5740611f
--- /dev/null
+++ b/src/mac-media-keys/SPMediaKeyTap.m
@@ -0,0 +1,356 @@
+/*
+ Copyright (c) 2011, Joachim Bengtsson
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Copyright (c) 2010 Spotify AB
+#import "SPMediaKeyTap.h"
+#import "SPInvocationGrabbing.h" // https://gist.github.com/511181, in submodule
+
+ at interface SPMediaKeyTap ()
+-(BOOL)shouldInterceptMediaKeyEvents;
+-(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting;
+-(void)startWatchingAppSwitching;
+-(void)stopWatchingAppSwitching;
+-(void)eventTapThread;
+ at end
+static SPMediaKeyTap *singleton = nil;
+
+static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData);
+static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData);
+static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon);
+
+
+// Inspired by http://gist.github.com/546311
+
+ at implementation SPMediaKeyTap
+
+#pragma mark -
+#pragma mark Setup and teardown
+-(id)initWithDelegate:(id)delegate;
+{
+	_delegate = delegate;
+	[self startWatchingAppSwitching];
+	singleton = self;
+	_mediaKeyAppList = [NSMutableArray new];
+    _tapThreadRL=nil;
+    _eventPort=nil;
+    _eventPortSource=nil;
+	return self;
+}
+-(void)dealloc;
+{
+	[self stopWatchingMediaKeys];
+	[self stopWatchingAppSwitching];
+	[_mediaKeyAppList release];
+	[super dealloc];
+}
+
+-(void)startWatchingAppSwitching;
+{
+	// Listen to "app switched" event, so that we don't intercept media keys if we
+	// weren't the last "media key listening" app to be active
+	EventTypeSpec eventType = { kEventClassApplication, kEventAppFrontSwitched };
+    OSStatus err = InstallApplicationEventHandler(NewEventHandlerUPP(appSwitched), 1, &eventType, self, &_app_switching_ref);
+	assert(err == noErr);
+
+	eventType.eventKind = kEventAppTerminated;
+    err = InstallApplicationEventHandler(NewEventHandlerUPP(appTerminated), 1, &eventType, self, &_app_terminating_ref);
+	assert(err == noErr);
+}
+-(void)stopWatchingAppSwitching;
+{
+	if(!_app_switching_ref) return;
+	RemoveEventHandler(_app_switching_ref);
+	_app_switching_ref = NULL;
+}
+
+-(void)startWatchingMediaKeys;{
+    // Prevent having multiple mediaKeys threads
+    [self stopWatchingMediaKeys];
+
+	[self setShouldInterceptMediaKeyEvents:YES];
+
+	// Add an event tap to intercept the system defined media key events
+	_eventPort = CGEventTapCreate(kCGSessionEventTap,
+								  kCGHeadInsertEventTap,
+								  kCGEventTapOptionDefault,
+								  CGEventMaskBit(NX_SYSDEFINED),
+								  tapEventCallback,
+								  self);
+	assert(_eventPort != NULL);
+
+    _eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0);
+	assert(_eventPortSource != NULL);
+
+	// Let's do this in a separate thread so that a slow app doesn't lag the event tap
+	[NSThread detachNewThreadSelector:@selector(eventTapThread) toTarget:self withObject:nil];
+}
+-(void)stopWatchingMediaKeys;
+{
+	// TODO<nevyn>: Shut down thread, remove event tap port and source
+
+    if(_tapThreadRL){
+        CFRunLoopStop(_tapThreadRL);
+        _tapThreadRL=nil;
+    }
+
+    if(_eventPort){
+        CFMachPortInvalidate(_eventPort);
+        CFRelease(_eventPort);
+        _eventPort=nil;
+    }
+
+    if(_eventPortSource){
+        CFRelease(_eventPortSource);
+        _eventPortSource=nil;
+    }
+}
+
+#pragma mark -
+#pragma mark Accessors
+
++(BOOL)usesGlobalMediaKeyTap
+{
+#ifdef _DEBUG
+	// breaking in gdb with a key tap inserted sometimes locks up all mouse and keyboard input forever, forcing reboot
+	return NO;
+#else
+	// XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy.
+	return
+		![[NSUserDefaults standardUserDefaults] boolForKey:kIgnoreMediaKeysDefaultsKey]
+		&& floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/;
+#endif
+}
+
++ (NSArray*)defaultMediaKeyUserBundleIdentifiers;
+{
+	return [NSArray arrayWithObjects:
+		[[NSBundle mainBundle] bundleIdentifier], // your app
+		@"com.spotify.client",
+		@"com.apple.iTunes",
+		@"com.apple.QuickTimePlayerX",
+		@"com.apple.quicktimeplayer",
+		@"com.apple.iWork.Keynote",
+		@"com.apple.iPhoto",
+		@"org.videolan.vlc",
+		@"com.apple.Aperture",
+		@"com.plexsquared.Plex",
+		@"com.soundcloud.desktop",
+		@"org.niltsh.MPlayerX",
+		@"com.ilabs.PandorasHelper",
+		@"com.mahasoftware.pandabar",
+		@"com.bitcartel.pandorajam",
+		@"org.clementine-player.clementine",
+		@"fm.last.Last.fm",
+		@"fm.last.Scrobbler",
+		@"com.beatport.BeatportPro",
+		@"com.Timenut.SongKey",
+		@"com.macromedia.fireworks", // the tap messes up their mouse input
+		@"at.justp.Theremin",
+		@"ru.ya.themblsha.YandexMusic",
+		@"com.jriver.MediaCenter18",
+		@"com.jriver.MediaCenter19",
+		@"com.jriver.MediaCenter20",
+		@"co.rackit.mate",
+		@"com.ttitt.b-music",
+		@"com.beardedspice.BeardedSpice",
+		@"com.plug.Plug",
+        @"com.netease.163music",
+		nil
+	];
+}
+
+
+-(BOOL)shouldInterceptMediaKeyEvents;
+{
+	BOOL shouldIntercept = NO;
+	@synchronized(self) {
+		shouldIntercept = _shouldInterceptMediaKeyEvents;
+	}
+	return shouldIntercept;
+}
+
+-(void)pauseTapOnTapThread:(BOOL)yeahno;
+{
+	CGEventTapEnable(self->_eventPort, yeahno);
+}
+-(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting;
+{
+	BOOL oldSetting;
+	@synchronized(self) {
+		oldSetting = _shouldInterceptMediaKeyEvents;
+		_shouldInterceptMediaKeyEvents = newSetting;
+	}
+	if(_tapThreadRL && oldSetting != newSetting) {
+		id grab = [self grab];
+		[grab pauseTapOnTapThread:newSetting];
+		NSTimer *timer = [NSTimer timerWithTimeInterval:0 invocation:[grab invocation] repeats:NO];
+		CFRunLoopAddTimer(_tapThreadRL, (CFRunLoopTimerRef)timer, kCFRunLoopCommonModes);
+	}
+}
+
+#pragma mark
+#pragma mark -
+#pragma mark Event tap callbacks
+
+// Note: method called on background thread
+
+static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
+{
+	SPMediaKeyTap *self = refcon;
+
+    if(type == kCGEventTapDisabledByTimeout) {
+		NSLog(@"Media key event tap was disabled by timeout");
+		CGEventTapEnable(self->_eventPort, TRUE);
+		return event;
+	} else if(type == kCGEventTapDisabledByUserInput) {
+		// Was disabled manually by -[pauseTapOnTapThread]
+		return event;
+	}
+	NSEvent *nsEvent = nil;
+	@try {
+		nsEvent = [NSEvent eventWithCGEvent:event];
+	}
+	@catch (NSException * e) {
+		NSLog(@"Strange CGEventType: %d: %@", type, e);
+		assert(0);
+		return event;
+	}
+
+	if (type != NX_SYSDEFINED || [nsEvent subtype] != SPSystemDefinedEventMediaKeys)
+		return event;
+
+	int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16);
+    if (keyCode != NX_KEYTYPE_PLAY && keyCode != NX_KEYTYPE_FAST && keyCode != NX_KEYTYPE_REWIND && keyCode != NX_KEYTYPE_PREVIOUS && keyCode != NX_KEYTYPE_NEXT)
+		return event;
+
+	if (![self shouldInterceptMediaKeyEvents])
+		return event;
+
+	[nsEvent retain]; // matched in handleAndReleaseMediaKeyEvent:
+	[self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO];
+
+	return NULL;
+}
+
+static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
+{
+	NSAutoreleasePool *pool = [NSAutoreleasePool new];
+	CGEventRef ret = tapEventCallback2(proxy, type, event, refcon);
+	[pool drain];
+	return ret;
+}
+
+
+// event will have been retained in the other thread
+-(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event {
+	[event autorelease];
+
+	[_delegate mediaKeyTap:self receivedMediaKeyEvent:event];
+}
+
+
+-(void)eventTapThread;
+{
+	_tapThreadRL = CFRunLoopGetCurrent();
+	CFRunLoopAddSource(_tapThreadRL, _eventPortSource, kCFRunLoopCommonModes);
+	CFRunLoopRun();
+}
+
+#pragma mark Task switching callbacks
+
+NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys";
+NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys";
+
+
+
+-(void)mediaKeyAppListChanged;
+{
+	if([_mediaKeyAppList count] == 0) return;
+
+	/*NSLog(@"--");
+	int i = 0;
+	for (NSValue *psnv in _mediaKeyAppList) {
+		ProcessSerialNumber psn; [psnv getValue:&psn];
+		NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary(
+			&psn,
+			kProcessDictionaryIncludeAllInformationMask
+		) autorelease];
+		NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey];
+		NSLog(@"%d: %@", i++, bundleIdentifier);
+	}*/
+
+    ProcessSerialNumber mySerial, topSerial;
+	GetCurrentProcess(&mySerial);
+	[[_mediaKeyAppList objectAtIndex:0] getValue:&topSerial];
+
+	Boolean same;
+	OSErr err = SameProcess(&mySerial, &topSerial, &same);
+	[self setShouldInterceptMediaKeyEvents:(err == noErr && same)];
+
+}
+-(void)appIsNowFrontmost:(ProcessSerialNumber)psn;
+{
+	NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)];
+
+	NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary(
+		&psn,
+		kProcessDictionaryIncludeAllInformationMask
+	) autorelease];
+	NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey];
+
+	NSArray *whitelistIdentifiers = [[NSUserDefaults standardUserDefaults] arrayForKey:kMediaKeyUsingBundleIdentifiersDefaultsKey];
+	if(![whitelistIdentifiers containsObject:bundleIdentifier]) return;
+
+	[_mediaKeyAppList removeObject:psnv];
+	[_mediaKeyAppList insertObject:psnv atIndex:0];
+	[self mediaKeyAppListChanged];
+}
+-(void)appTerminated:(ProcessSerialNumber)psn;
+{
+	NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)];
+	[_mediaKeyAppList removeObject:psnv];
+	[self mediaKeyAppListChanged];
+}
+
+static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData)
+{
+	SPMediaKeyTap *self = (id)userData;
+
+    ProcessSerialNumber newSerial;
+    GetFrontProcess(&newSerial);
+
+	[self appIsNowFrontmost:newSerial];
+
+    return CallNextEventHandler(nextHandler, evt);
+}
+
+static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData)
+{
+	SPMediaKeyTap *self = (id)userData;
+
+	ProcessSerialNumber deadPSN;
+
+	GetEventParameter(
+		evt,
+		kEventParamProcessID,
+		typeProcessSerialNumber,
+		NULL,
+		sizeof(deadPSN),
+		NULL,
+		&deadPSN
+	);
+
+
+	[self appTerminated:deadPSN];
+    return CallNextEventHandler(nextHandler, evt);
+}
+
+ at end
diff --git a/src/metronom/Makefile b/src/metronom/Makefile
index da5b0a7b7dae..6c025d6752c2 100644
--- a/src/metronom/Makefile
+++ b/src/metronom/Makefile
@@ -1,11 +1,13 @@
 PLUGIN = metronom${PLUGIN_SUFFIX}
 
-SRCS = metronom.c
+SRCS = metronom.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/metronom/metronom.c b/src/metronom/metronom.c
deleted file mode 100644
index c63219cf46fe..000000000000
--- a/src/metronom/metronom.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  Copyright 2000 Martin Strauss <mys at faveve.uni-stuttgart.de>
- *
- *  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.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#define MIN_BPM         1
-#define MAX_BPM         512
-#define TACT_ID_MAX     12
-#define TACT_FORM_MAX   8
-
-#define AUDIO_FREQ      (44100)
-#define BUF_SAMPLES     512
-#define BUF_BYTES       (BUF_SAMPLES * 2)
-#define MAX_AMPL        0x7fff
-
-typedef struct
-{
-    int bpm;
-    int num;
-    int den;
-    int id;
-} metronom_t;
-
-int tact_id[TACT_ID_MAX][2] = {
-    {1, 1},
-    {2, 2},
-    {3, 2},
-    {4, 2},
-    {2, 4},
-    {3, 4},
-    {4, 4},
-    {6, 4},
-    {2, 8},
-    {3, 8},
-    {4, 8},
-    {6, 8}
-};
-
-double tact_form[TACT_ID_MAX][TACT_FORM_MAX] = {
-    {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.5, 0.6, 0.5, 0.5, 0.0, 0.0},
-    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
-    {1.0, 0.5, 0.5, 0.6, 0.5, 0.5, 0.0, 0.0}
-};
-
-static bool_t metronom_is_our_fd(const char * filename, VFSFile *fd)
-{
-    if (!strncmp(filename, "tact://", 7))
-        return TRUE;
-    return FALSE;
-}
-
-static bool_t metronom_get_cp(const char *filename, metronom_t *pmetronom, char **str)
-{
-    int count;
-
-    count = sscanf(filename, "tact://%d*%d/%d",
-        &pmetronom->bpm, &pmetronom->num, &pmetronom->den);
-
-    if (count != 1 && count != 3)
-        return FALSE;
-
-    if (pmetronom->bpm < MIN_BPM || pmetronom->bpm > MAX_BPM)
-        return FALSE;
-
-    if (count == 1)
-    {
-        pmetronom->num = 1;
-        pmetronom->den = 1;
-        pmetronom->id = 0;
-    }
-    else
-    {
-        bool_t flag;
-        int id;
-
-        if (pmetronom->num == 0 || pmetronom->den == 0)
-            return FALSE;
-
-        flag = FALSE;
-        for (id = 0; id < TACT_ID_MAX && !flag; id++)
-        {
-            if (pmetronom->num == tact_id[id][0] && pmetronom->den == tact_id[id][1])
-                flag = TRUE;
-        }
-
-        if (!flag)
-            return FALSE;
-        else
-            pmetronom->id = id;
-    }
-
-    if (str == NULL)
-        return TRUE;
-
-    if (pmetronom->num == 1 && pmetronom->den == 1)
-        *str = str_printf (_("Tact generator: %d bpm"), pmetronom->bpm);
-    else
-        *str = str_printf (_("Tact generator: %d bpm %d/%d"), pmetronom->bpm, pmetronom->num, pmetronom->den);
-
-    return TRUE;
-}
-
-static bool_t metronom_play (const char * filename, VFSFile * file)
-{
-    metronom_t pmetronom;
-    int16_t data[BUF_SAMPLES];
-    int t = 0, tact, num;
-    int datagoal = 0;
-    int datamiddle = 0;
-    int datacurrent = datamiddle;
-    int datalast = datamiddle;
-    int data_form[TACT_FORM_MAX];
-
-    if (aud_input_open_audio(FMT_S16_NE, AUDIO_FREQ, 1) == 0)
-        return FALSE;
-
-    if (!metronom_get_cp(filename, &pmetronom, NULL))
-    {
-        fprintf (stderr, "Invalid metronom tact parameters in URI %s", filename);
-        return FALSE;
-    }
-
-    aud_input_set_bitrate(sizeof(data[0]) * 8 * AUDIO_FREQ);
-
-    tact = 60 * AUDIO_FREQ / pmetronom.bpm;
-
-    /* prepare weighted amplitudes */
-    for (num = 0; num < pmetronom.num; num++)
-    {
-        data_form[num] = MAX_AMPL * tact_form[pmetronom.id][num];
-    }
-
-    num = 0;
-    while (!aud_input_check_stop())
-    {
-        int i;
-
-        for (i = 0; i < BUF_SAMPLES; i++)
-        {
-            if (t == tact)
-            {
-                t = 0;
-                datagoal = data_form[num];
-            }
-            else if (t == 10)
-            {
-                datagoal = -data_form[num];
-            }
-            else if (t == 25)
-            {
-                datagoal = data_form[num];
-                /* circle through weighted amplitudes */
-                num++;
-                if (num >= pmetronom.num)
-                    num = 0;
-            }
-            /* makes curve a little bit smoother  */
-            data[i] = (datalast + datacurrent + datagoal) / 3;
-            datalast = datacurrent;
-            datacurrent = data[i];
-            if (t > 35)
-                datagoal = (datamiddle + 7 * datagoal) / 8;
-            t++;
-        }
-
-        aud_input_write_audio(data, BUF_BYTES);
-    }
-
-    return TRUE;
-}
-
-static Tuple *metronom_probe_for_tuple(const char * filename, VFSFile *fd)
-{
-    Tuple *tuple = tuple_new_from_filename(filename);
-    metronom_t metronom;
-    char *tmp = NULL;
-
-    if (metronom_get_cp(filename, &metronom, &tmp))
-        tuple_set_str(tuple, FIELD_TITLE, tmp);
-
-    str_unref(tmp);
-
-    return tuple;
-}
-
-static const char metronom_about[] =
- N_("A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n\n"
-    "To use it, add a URL: tact://beats*num/den\n"
-    "e.g. tact://77 to play 77 beats per minute\n"
-    "or tact://60*3/4 to play 60 bpm in 3/4 tacts");
-
-static const char * const schemes[] = {"tact", NULL};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Tact Generator"),
-    .domain = PACKAGE,
-    .about_text = metronom_about,
-    .schemes = schemes,
-    .is_our_file_from_vfs = metronom_is_our_fd,
-    .play = metronom_play,
-    .probe_for_tuple = metronom_probe_for_tuple,
-)
diff --git a/src/metronom/metronom.cc b/src/metronom/metronom.cc
new file mode 100644
index 000000000000..0effeddbd838
--- /dev/null
+++ b/src/metronom/metronom.cc
@@ -0,0 +1,242 @@
+/*
+ *  Copyright 2000 Martin Strauss <mys at faveve.uni-stuttgart.de>
+ *
+ *  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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#define MIN_BPM         1
+#define MAX_BPM         512
+#define TACT_ID_MAX     12
+#define TACT_FORM_MAX   8
+
+#define AUDIO_FREQ      (44100)
+#define BUF_SAMPLES     512
+#define BUF_BYTES       (BUF_SAMPLES * 2)
+#define MAX_AMPL        0x7fff
+
+class Metronome : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char *const schemes[];
+
+    static constexpr PluginInfo info = {
+        N_("Tact Generator"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo()
+        .with_schemes(schemes);
+
+    constexpr Metronome() : InputPlugin(info, iinfo) {}
+
+    bool is_our_file(const char *filename, VFSFile &);
+    Tuple read_tuple(const char *filename, VFSFile &);
+    bool play(const char *filename, VFSFile &);
+};
+
+EXPORT Metronome aud_plugin_instance;
+
+typedef struct
+{
+    int bpm;
+    int num;
+    int den;
+    int id;
+} metronom_t;
+
+int tact_id[TACT_ID_MAX][2] = {
+    {1, 1},
+    {2, 2},
+    {3, 2},
+    {4, 2},
+    {2, 4},
+    {3, 4},
+    {4, 4},
+    {6, 4},
+    {2, 8},
+    {3, 8},
+    {4, 8},
+    {6, 8}
+};
+
+double tact_form[TACT_ID_MAX][TACT_FORM_MAX] = {
+    {1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.5, 0.6, 0.5, 0.5, 0.0, 0.0},
+    {1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.6, 0.5, 0.0, 0.0, 0.0, 0.0},
+    {1.0, 0.5, 0.5, 0.6, 0.5, 0.5, 0.0, 0.0}
+};
+
+bool Metronome::is_our_file(const char *filename, VFSFile &)
+{
+    if (!strncmp(filename, "tact://", 7))
+        return true;
+    return false;
+}
+
+static bool metronom_get_cp(const char *filename, metronom_t *pmetronom, String & str)
+{
+    int count;
+
+    count = sscanf(filename, "tact://%d*%d/%d",
+        &pmetronom->bpm, &pmetronom->num, &pmetronom->den);
+
+    if (count != 1 && count != 3)
+        return false;
+
+    if (pmetronom->bpm < MIN_BPM || pmetronom->bpm > MAX_BPM)
+        return false;
+
+    if (count == 1)
+    {
+        pmetronom->num = 1;
+        pmetronom->den = 1;
+        pmetronom->id = 0;
+    }
+    else
+    {
+        bool flag;
+        int id;
+
+        if (pmetronom->num == 0 || pmetronom->den == 0)
+            return false;
+
+        flag = false;
+        for (id = 0; id < TACT_ID_MAX && !flag; id++)
+        {
+            if (pmetronom->num == tact_id[id][0] && pmetronom->den == tact_id[id][1])
+                flag = true;
+        }
+
+        if (!flag)
+            return false;
+        else
+            pmetronom->id = id;
+    }
+
+    if (pmetronom->num == 1 && pmetronom->den == 1)
+        str = String (str_printf (_("Tact generator: %d bpm"), pmetronom->bpm));
+    else
+        str = String (str_printf (_("Tact generator: %d bpm %d/%d"),
+         pmetronom->bpm, pmetronom->num, pmetronom->den));
+
+    return true;
+}
+
+bool Metronome::play (const char * filename, VFSFile &)
+{
+    metronom_t pmetronom;
+    int16_t data[BUF_SAMPLES];
+    int t = 0, tact, num;
+    int datagoal = 0;
+    int datamiddle = 0;
+    int datacurrent = datamiddle;
+    int datalast = datamiddle;
+    int data_form[TACT_FORM_MAX];
+    String desc;
+
+    set_stream_bitrate(sizeof(data[0]) * 8 * AUDIO_FREQ);
+    open_audio(FMT_S16_NE, AUDIO_FREQ, 1);
+
+    if (!metronom_get_cp(filename, &pmetronom, desc))
+    {
+        AUDERR ("Invalid metronom tact parameters in URI %s", filename);
+        return false;
+    }
+
+    tact = 60 * AUDIO_FREQ / pmetronom.bpm;
+
+    /* prepare weighted amplitudes */
+    for (num = 0; num < pmetronom.num; num++)
+    {
+        data_form[num] = MAX_AMPL * tact_form[pmetronom.id][num];
+    }
+
+    num = 0;
+    while (!check_stop())
+    {
+        int i;
+
+        for (i = 0; i < BUF_SAMPLES; i++)
+        {
+            if (t == tact)
+            {
+                t = 0;
+                datagoal = data_form[num];
+            }
+            else if (t == 10)
+            {
+                datagoal = -data_form[num];
+            }
+            else if (t == 25)
+            {
+                datagoal = data_form[num];
+                /* circle through weighted amplitudes */
+                num++;
+                if (num >= pmetronom.num)
+                    num = 0;
+            }
+            /* makes curve a little bit smoother  */
+            data[i] = (datalast + datacurrent + datagoal) / 3;
+            datalast = datacurrent;
+            datacurrent = data[i];
+            if (t > 35)
+                datagoal = (datamiddle + 7 * datagoal) / 8;
+            t++;
+        }
+
+        write_audio(data, BUF_BYTES);
+    }
+
+    return true;
+}
+
+Tuple Metronome::read_tuple(const char *filename, VFSFile &)
+{
+    Tuple tuple;
+    metronom_t metronom;
+    String desc;
+
+    tuple.set_filename (filename);
+    if (metronom_get_cp(filename, &metronom, desc))
+        tuple.set_str (Tuple::Title, desc);
+
+    return tuple;
+}
+
+const char Metronome::about[] =
+ N_("A Tact Generator by Martin Strauss <mys at faveve.uni-stuttgart.de>\n\n"
+    "To use it, add a URL: tact://beats*num/den\n"
+    "e.g. tact://77 to play 77 beats per minute\n"
+    "or tact://60*3/4 to play 60 bpm in 3/4 tacts");
+
+const char *const Metronome::schemes[] = {"tact", nullptr};
diff --git a/src/mixer/Makefile b/src/mixer/Makefile
index 38feed85403e..212a9db5d1cf 100644
--- a/src/mixer/Makefile
+++ b/src/mixer/Makefile
@@ -1,12 +1,12 @@
 PLUGIN = mixer${PLUGIN_SUFFIX}
 
-SRCS = mixer.c
+SRCS = mixer.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
+LD = ${CXX}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += ${GLIB_LIBS}
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
deleted file mode 100644
index e77ea2cd515e..000000000000
--- a/src/mixer/mixer.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Channel Mixer Plugin for Audacious
- * Copyright 2011-2012 John Lindgren and Michał Lipski
- *
- * 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.
- */
-
-/* TODO: implement more surround converters */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#define MAX_CHANNELS 8
-
-typedef void (* Converter) (float * * data, int * samples);
-
-static float * mixer_buf;
-
-static void mono_to_stereo (float * * data, int * samples)
-{
-    int frames = * samples;
-    float * get = * data;
-    float * set = mixer_buf = g_renew (float, mixer_buf, 2 * frames);
-
-    * data = mixer_buf;
-    * samples = 2 * frames;
-
-    while (frames --)
-    {
-        float val = * get ++;
-        * set ++ = val;
-        * set ++ = val;
-    }
-}
-
-static void stereo_to_mono (float * * data, int * samples)
-{
-    int frames = * samples / 2;
-    float * get = * data;
-    float * set = mixer_buf = g_renew (float, mixer_buf, frames);
-
-    * data = mixer_buf;
-    * samples = frames;
-
-    while (frames --)
-    {
-        float val = * get ++;
-        val += * get ++;
-        * set ++ = val / 2;
-    }
-}
-
-static void quadro_to_stereo (float * * data, int * samples)
-{
-    int frames = * samples / 4;
-    float * get = * data;
-    float * set = mixer_buf = g_renew (float, mixer_buf, 2 * frames);
-
-    * data = mixer_buf;
-    * samples = 2 * frames;
-
-    while (frames --)
-    {
-        float front_left  = * get ++;
-        float front_right = * get ++;
-        float back_left   = * get ++;
-        float back_right  = * get ++;
-        * set ++ = front_left + (back_left * 0.7);
-        * set ++ = front_right + (back_right * 0.7);
-    }
-}
-
-static void surround_5p1_to_stereo (float * * data, int * samples)
-{
-    int frames = * samples / 6;
-    float * get = * data;
-    float * set = mixer_buf = g_renew (float, mixer_buf, 2 * frames);
-
-    * data = mixer_buf;
-    * samples = 2 * frames;
-
-    while (frames --)
-    {
-        float front_left  = * get ++;
-        float front_right = * get ++;
-        float center = * get ++;
-        float lfe    = * get ++;
-        float rear_left   = * get ++;
-        float rear_right  = * get ++;
-        * set ++ = front_left + (center * 0.5) + (lfe * 0.5) + (rear_left * 0.5);
-        * set ++ = front_right + (center * 0.5) + (lfe * 0.5) + (rear_right * 0.5);
-    }
-}
-
-static const Converter converters[MAX_CHANNELS + 1][MAX_CHANNELS + 1] = {
- [1][2] = mono_to_stereo,
- [2][1] = stereo_to_mono,
- [4][2] = quadro_to_stereo,
- [6][2] = surround_5p1_to_stereo};
-
-static int input_channels, output_channels;
-
-void mixer_start (int * channels, int * rate)
-{
-    input_channels = * channels;
-    output_channels = aud_get_int ("mixer", "channels");
-    output_channels = CLAMP (output_channels, 1, MAX_CHANNELS);
-
-    if (input_channels == output_channels)
-        return;
-
-    if (input_channels < 1 || input_channels > MAX_CHANNELS ||
-     ! converters[input_channels][output_channels])
-    {
-        fprintf (stderr, "Converting %d to %d channels is not implemented.\n",
-         input_channels, output_channels);
-        return;
-    }
-
-    * channels = output_channels;
-}
-
-void mixer_process (float * * data, int * samples)
-{
-    if (input_channels == output_channels)
-        return;
-
-    if (input_channels < 1 || input_channels > MAX_CHANNELS ||
-     ! converters[input_channels][output_channels])
-        return;
-
-    converters[input_channels][output_channels] (data, samples);
-}
-
-static const char * const mixer_defaults[] = {
- "channels", "2",
-  NULL};
-
-static bool_t mixer_init (void)
-{
-    aud_config_set_defaults ("mixer", mixer_defaults);
-    return TRUE;
-}
-
-static void mixer_cleanup (void)
-{
-    g_free (mixer_buf);
-    mixer_buf = 0;
-}
-
-static const char mixer_about[] =
- N_("Channel Mixer Plugin for Audacious\n"
-    "Copyright 2011-2012 John Lindgren and Michał Lipski");
-
-static const PreferencesWidget mixer_widgets[] = {
- {WIDGET_LABEL, N_("<b>Channel Mixer</b>")},
- {WIDGET_SPIN_BTN, N_("Output channels:"),
-  .cfg_type = VALUE_INT, .csect = "mixer", .cname = "channels",
-  .data = {.spin_btn = {1, MAX_CHANNELS, 1}}}};
-
-static const PluginPreferences mixer_prefs = {
- .widgets = mixer_widgets,
- .n_widgets = ARRAY_LEN (mixer_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Channel Mixer"),
-    .domain = PACKAGE,
-    .about_text = mixer_about,
-    .prefs = & mixer_prefs,
-    .init = mixer_init,
-    .cleanup = mixer_cleanup,
-    .start = mixer_start,
-    .process = mixer_process,
-    .finish = mixer_process,
-    .order = 2, /* must be before crossfade */
-)
diff --git a/src/mixer/mixer.cc b/src/mixer/mixer.cc
new file mode 100644
index 000000000000..9fe5728730ae
--- /dev/null
+++ b/src/mixer/mixer.cc
@@ -0,0 +1,212 @@
+/*
+ * Channel Mixer Plugin for Audacious
+ * Copyright 2011-2012 John Lindgren and Michał Lipski
+ *
+ * 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.
+ */
+
+/* TODO: implement more surround converters */
+
+#include <stdlib.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+class ChannelMixer : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Channel Mixer"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    /* order #2: must be before crossfade */
+    constexpr ChannelMixer () : EffectPlugin (info, 2, false) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+};
+
+EXPORT ChannelMixer aud_plugin_instance;
+
+typedef Index<float> & (* Converter) (Index<float> & data);
+
+static Index<float> mixer_buf;
+
+static Index<float> & mono_to_stereo (Index<float> & data)
+{
+    int frames = data.len ();
+    mixer_buf.resize (2 * frames);
+
+    float * get = data.begin ();
+    float * set = mixer_buf.begin ();
+
+    while (frames --)
+    {
+        float val = * get ++;
+        * set ++ = val;
+        * set ++ = val;
+    }
+
+    return mixer_buf;
+}
+
+static Index<float> & stereo_to_mono (Index<float> & data)
+{
+    int frames = data.len () / 2;
+    mixer_buf.resize (frames);
+
+    float * get = data.begin ();
+    float * set = mixer_buf.begin ();
+
+    while (frames --)
+    {
+        float val = * get ++;
+        val += * get ++;
+        * set ++ = val / 2;
+    }
+
+    return mixer_buf;
+}
+
+static Index<float> & quadro_to_stereo (Index<float> & data)
+{
+    int frames = data.len () / 4;
+    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 back_left   = * get ++;
+        float back_right  = * get ++;
+        * set ++ = front_left + (back_left * 0.7);
+        * set ++ = front_right + (back_right * 0.7);
+    }
+
+    return mixer_buf;
+}
+
+static Index<float> & surround_5p1_to_stereo (Index<float> & data)
+{
+    int frames = data.len () / 6;
+    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 lfe    = * get ++;
+        float rear_left   = * get ++;
+        float rear_right  = * get ++;
+        * set ++ = front_left + (center * 0.5) + (lfe * 0.5) + (rear_left * 0.5);
+        * set ++ = front_right + (center * 0.5) + (lfe * 0.5) + (rear_right * 0.5);
+    }
+
+    return mixer_buf;
+}
+
+static Converter get_converter (int in, int out)
+{
+    if (in == 1 && out == 2)
+        return mono_to_stereo;
+    if (in == 2 && out == 1)
+        return stereo_to_mono;
+    if (in == 4 && out == 2)
+        return quadro_to_stereo;
+    if (in == 6 && out == 2)
+        return surround_5p1_to_stereo;
+
+    return nullptr;
+}
+
+static int input_channels, output_channels;
+
+void ChannelMixer::start (int & channels, int & rate)
+{
+    input_channels = channels;
+    output_channels = aud_get_int ("mixer", "channels");
+
+    if (input_channels == output_channels)
+        return;
+
+    if (! get_converter (input_channels, output_channels))
+    {
+        AUDERR ("Converting %d to %d channels is not implemented.\n",
+         input_channels, output_channels);
+        return;
+    }
+
+    channels = output_channels;
+}
+
+Index<float> & ChannelMixer::process (Index<float> & data)
+{
+    if (input_channels == output_channels)
+        return data;
+
+    Converter converter = get_converter (input_channels, output_channels);
+    if (converter)
+        return converter (data);
+
+    return data;
+}
+
+const char * const ChannelMixer::defaults[] = {
+ "channels", "2",
+  nullptr};
+
+bool ChannelMixer::init ()
+{
+    aud_config_set_defaults ("mixer", defaults);
+    return true;
+}
+
+void ChannelMixer::cleanup ()
+{
+    mixer_buf.clear ();
+}
+
+const char ChannelMixer::about[] =
+ N_("Channel Mixer Plugin for Audacious\n"
+    "Copyright 2011-2012 John Lindgren and Michał Lipski");
+
+const PreferencesWidget ChannelMixer::widgets[] = {
+    WidgetLabel (N_("<b>Channel Mixer</b>")),
+    WidgetSpin (N_("Output channels:"),
+        WidgetInt ("mixer", "channels"),
+        {1, AUD_MAX_CHANNELS, 1})
+};
+
+const PluginPreferences ChannelMixer::prefs = {{widgets}};
diff --git a/src/mms/Makefile b/src/mms/Makefile
index daa2c4e1ca7d..9bba09fe6031 100644
--- a/src/mms/Makefile
+++ b/src/mms/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = mms${PLUGIN_SUFFIX}
 
-SRCS = mms.c
+SRCS = mms.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${TRANSPORT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MMS_CFLAGS} -I../.. -Wall
 CFLAGS += ${PLUGIN_CFLAGS}
 LIBS += ${MMS_LIBS}
diff --git a/src/mms/mms.c b/src/mms/mms.c
deleted file mode 100644
index c57f35373b77..000000000000
--- a/src/mms/mms.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * MMS/MMSH Transport for Audacious
- * Copyright 2007-2013 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:
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <libmms/mms.h>
-#include <libmms/mmsh.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-typedef struct
-{
-    mms_t * mms;
-    mmsh_t * mmsh;
-}
-MMSHandle;
-
-static void * mms_vfs_fopen_impl (const char * path, const char * mode)
-{
-    AUDDBG ("Opening %s.\n", path);
-
-    MMSHandle * h = g_new0 (MMSHandle, 1);
-
-    if (! (h->mmsh = mmsh_connect (NULL, NULL, path, 128 * 1024)))
-    {
-        AUDDBG ("Failed to connect with MMSH protocol; trying MMS.\n");
-
-        if (! (h->mms = mms_connect (NULL, NULL, path, 128 * 1024)))
-        {
-            fprintf (stderr, "mms: Failed to open %s.\n", path);
-            g_free (h);
-            return NULL;
-        }
-    }
-
-    return h;
-}
-
-static int mms_vfs_fclose_impl (VFSFile * file)
-{
-    MMSHandle * h = (MMSHandle *) vfs_get_handle (file);
-
-    if (h->mms)
-        mms_close (h->mms);
-    else
-        mmsh_close (h->mmsh);
-
-    g_free (h);
-    return 0;
-}
-
-static int64_t mms_vfs_fread_impl (void * buf, int64_t size, int64_t count, VFSFile * file)
-{
-    MMSHandle * h = vfs_get_handle (file);
-    int64_t bytes_total = size * count;
-    int64_t bytes_read = 0;
-
-    while (bytes_read < bytes_total)
-    {
-        int64_t readsize;
-
-        if (h->mms)
-            readsize = mms_read (NULL, h->mms, (char *) buf + bytes_read, bytes_total - bytes_read);
-        else
-            readsize = mmsh_read (NULL, h->mmsh, (char *) buf + bytes_read, bytes_total - bytes_read);
-
-        if (readsize < 0)
-            fprintf (stderr, "mms: Read failed.\n");
-
-        if (readsize <= 0)
-            break;
-
-        bytes_read += readsize;
-    }
-
-    return size ? bytes_read / size : 0;
-}
-
-static int64_t mms_vfs_fwrite_impl (const void * data, int64_t size, int64_t count, VFSFile * file)
-{
-    fprintf (stderr, "mms: Writing is not supported.\n");
-    return 0;
-}
-
-static int mms_vfs_fseek_impl (VFSFile * file, int64_t offset, int whence)
-{
-    MMSHandle * h = vfs_get_handle (file);
-
-    if (whence == SEEK_CUR)
-    {
-        if (h->mms)
-            offset += mms_get_current_pos (h->mms);
-        else
-            offset += mmsh_get_current_pos (h->mmsh);
-    }
-    else if (whence == SEEK_END)
-    {
-        if (h->mms)
-            offset += mms_get_length (h->mms);
-        else
-            offset += mmsh_get_length (h->mmsh);
-    }
-
-    int64_t ret;
-
-    if (h->mms)
-        ret = mms_seek (NULL, h->mms, offset, SEEK_SET);
-    else
-        ret = mmsh_seek (NULL, h->mmsh, offset, SEEK_SET);
-
-    if (ret < 0 || ret != offset)
-    {
-        fprintf (stderr, "mms: Seek failed.\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-static int64_t mms_vfs_ftell_impl (VFSFile * file)
-{
-    MMSHandle * h = vfs_get_handle (file);
-
-    if (h->mms)
-        return mms_get_current_pos (h->mms);
-    else
-        return mmsh_get_current_pos (h->mmsh);
-}
-
-static bool_t mms_vfs_feof_impl (VFSFile * file)
-{
-    MMSHandle * h = vfs_get_handle (file);
-
-    if (h->mms)
-        return (mms_get_current_pos (h->mms) < mms_get_length (h->mms));
-    else
-        return (mmsh_get_current_pos (h->mmsh) < mmsh_get_length (h->mmsh));
-}
-
-static int mms_vfs_truncate_impl (VFSFile * file, int64_t size)
-{
-    fprintf (stderr, "mms: Truncating is not supported.\n");
-    return -1;
-}
-
-static int64_t mms_vfs_fsize_impl (VFSFile * file)
-{
-    MMSHandle * h = vfs_get_handle (file);
-
-    if (h->mms)
-        return mms_get_length (h->mms);
-    else
-        return mmsh_get_length (h->mmsh);
-}
-
-static const char * const mms_schemes[] = {"mms", NULL};
-
-static VFSConstructor constructor =
-{
-    .vfs_fopen_impl = mms_vfs_fopen_impl,
-    .vfs_fclose_impl = mms_vfs_fclose_impl,
-    .vfs_fread_impl = mms_vfs_fread_impl,
-    .vfs_fwrite_impl = mms_vfs_fwrite_impl,
-    .vfs_fseek_impl = mms_vfs_fseek_impl,
-    .vfs_ftell_impl = mms_vfs_ftell_impl,
-    .vfs_feof_impl = mms_vfs_feof_impl,
-    .vfs_ftruncate_impl = mms_vfs_truncate_impl,
-    .vfs_fsize_impl = mms_vfs_fsize_impl
-};
-
-AUD_TRANSPORT_PLUGIN
-(
-    .name = N_("MMS Plugin"),
-    .domain = PACKAGE,
-    .schemes = mms_schemes,
-    .vtable = & constructor
-)
diff --git a/src/mms/mms.cc b/src/mms/mms.cc
new file mode 100644
index 000000000000..983e1f587431
--- /dev/null
+++ b/src/mms/mms.cc
@@ -0,0 +1,196 @@
+/*
+ * MMS/MMSH Transport for Audacious
+ * Copyright 2007-2013 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:
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <libmms/mms.h>
+#include <libmms/mmsh.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+static const char * const mms_schemes[] = {"mms"};
+
+class MMSTransport : public TransportPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("MMS Plugin"), PACKAGE};
+
+    constexpr MMSTransport () : TransportPlugin (info, mms_schemes) {}
+
+    VFSImpl * fopen (const char * path, const char * mode, String & error);
+};
+
+EXPORT MMSTransport aud_plugin_instance;
+
+class MMSFile : public VFSImpl
+{
+public:
+    MMSFile (const char * path, mms_t * mms, mmsh_t * mmsh) :
+        m_mms (mms),
+        m_mmsh (mmsh) {}
+
+    ~MMSFile ();
+
+    class OpenError {};  // exception
+
+    int64_t fread (void * ptr, int64_t size, int64_t nmemb);
+    int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb);
+
+    int fseek (int64_t offset, VFSSeekType whence);
+    int64_t ftell ();
+    int64_t fsize ();
+    bool feof ();
+    int ftruncate (int64_t size);
+    int fflush ();
+
+private:
+    mms_t * m_mms;
+    mmsh_t * m_mmsh;
+};
+
+VFSImpl * MMSTransport::fopen (const char * path, const char * mode, String & error)
+{
+    mms_t * mms = nullptr;
+    mmsh_t * mmsh = nullptr;
+
+    if (! (mmsh = mmsh_connect (nullptr, nullptr, path, 128 * 1024)))
+    {
+        AUDDBG ("Failed to connect with MMSH protocol; trying MMS.\n");
+
+        if (! (mms = mms_connect (nullptr, nullptr, path, 128 * 1024)))
+        {
+            AUDERR ("Failed to open %s.\n", path);
+            error = String (_("Error connecting to MMS server"));
+            return nullptr;
+        }
+    }
+
+    return new MMSFile (path, mms, mmsh);
+}
+
+MMSFile::~MMSFile ()
+{
+    if (m_mms)
+        mms_close (m_mms);
+    else
+        mmsh_close (m_mmsh);
+}
+
+int64_t MMSFile::fread (void * buf, int64_t size, int64_t count)
+{
+    int64_t bytes_total = size * count;
+    int64_t bytes_read = 0;
+
+    while (bytes_read < bytes_total)
+    {
+        int64_t readsize;
+
+        if (m_mms)
+            readsize = mms_read (nullptr, m_mms, (char *) buf + bytes_read, bytes_total - bytes_read);
+        else
+            readsize = mmsh_read (nullptr, m_mmsh, (char *) buf + bytes_read, bytes_total - bytes_read);
+
+        if (readsize < 0)
+            AUDERR ("Read failed.\n");
+
+        if (readsize <= 0)
+            break;
+
+        bytes_read += readsize;
+    }
+
+    return size ? bytes_read / size : 0;
+}
+
+int64_t MMSFile::fwrite (const void * data, int64_t size, int64_t count)
+{
+    AUDERR ("Writing is not supported.\n");
+    return 0;
+}
+
+int MMSFile::fseek (int64_t offset, VFSSeekType whence)
+{
+    if (whence == VFS_SEEK_CUR)
+    {
+        if (m_mms)
+            offset += mms_get_current_pos (m_mms);
+        else
+            offset += mmsh_get_current_pos (m_mmsh);
+    }
+    else if (whence == VFS_SEEK_END)
+    {
+        if (m_mms)
+            offset += mms_get_length (m_mms);
+        else
+            offset += mmsh_get_length (m_mmsh);
+    }
+
+    int64_t ret;
+
+    if (m_mms)
+        ret = mms_seek (nullptr, m_mms, offset, SEEK_SET);
+    else
+        ret = mmsh_seek (nullptr, m_mmsh, offset, SEEK_SET);
+
+    if (ret < 0 || ret != offset)
+    {
+        AUDERR ("Seek failed.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+int64_t MMSFile::ftell ()
+{
+    if (m_mms)
+        return mms_get_current_pos (m_mms);
+    else
+        return mmsh_get_current_pos (m_mmsh);
+}
+
+bool MMSFile::feof ()
+{
+    if (m_mms)
+        return (mms_get_current_pos (m_mms) < (int64_t) mms_get_length (m_mms));
+    else
+        return (mmsh_get_current_pos (m_mmsh) < (int64_t) mmsh_get_length (m_mmsh));
+}
+
+int MMSFile::ftruncate (int64_t size)
+{
+    AUDERR ("Truncating is not supported.\n");
+    return -1;
+}
+
+int64_t MMSFile::fsize ()
+{
+    if (m_mms)
+        return mms_get_length (m_mms);
+    else
+        return mmsh_get_length (m_mmsh);
+}
+
+int MMSFile::fflush ()
+{
+    return 0;
+}
diff --git a/src/modplug/Makefile b/src/modplug/Makefile
index 9036141213f2..560de5ff1c86 100644
--- a/src/modplug/Makefile
+++ b/src/modplug/Makefile
@@ -1,11 +1,10 @@
 PLUGIN = modplug${PLUGIN_SUFFIX}
 
-SRCS = archive/arch_raw.cxx \
-       archive/archive.cxx \
-       archive/open.cxx \
-       plugin.cxx \
-       modplugbmp.cxx \
-       plugin_main.c
+SRCS = archive/arch_raw.cc \
+       archive/archive.cc \
+       archive/open.cc \
+       modplugbmp.cc \
+       plugin_main.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -15,5 +14,5 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CXXFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${MODPLUG_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${MODPLUG_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MODPLUG_CFLAGS} -I../..
+LIBS += ${MODPLUG_LIBS}
diff --git a/src/modplug/archive/arch_raw.cc b/src/modplug/archive/arch_raw.cc
new file mode 100644
index 000000000000..f275af5d4dca
--- /dev/null
+++ b/src/modplug/archive/arch_raw.cc
@@ -0,0 +1,49 @@
+/* Modplug XMMS Plugin
+ * Authors: Kenton Varda <temporal at gauge3d.org>
+ *
+ * This source code is public domain.
+ */
+
+#include <cstdlib>
+
+#include "arch_raw.h"
+
+using namespace std;
+
+arch_Raw::arch_Raw(const string& aFileName)
+{
+    mFileDesc = VFSFile(aFileName.c_str(), "r");
+    if (!mFileDesc)
+    {
+        mSize = 0;
+        return;
+    }
+
+    mSize = mFileDesc.fsize ();
+    if (mSize <= 0)
+    {
+        mSize = 0;
+        return;
+    }
+
+    mMap = malloc(mSize);
+    if (mFileDesc.fread (mMap, 1, mSize) < mSize)
+    {
+        free(mMap);
+        mSize = 0;
+        return;
+    }
+}
+
+arch_Raw::~arch_Raw()
+{
+    if(mSize != 0)
+    {
+        free(mMap);
+    }
+}
+
+bool arch_Raw::ContainsMod(const string& aFileName)
+{
+    return IsOurFile(aFileName);
+}
diff --git a/src/modplug/archive/arch_raw.cxx b/src/modplug/archive/arch_raw.cxx
deleted file mode 100644
index 86b1b6b25790..000000000000
--- a/src/modplug/archive/arch_raw.cxx
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Modplug XMMS Plugin
- * Authors: Kenton Varda <temporal at gauge3d.org>
- *
- * This source code is public domain.
- */
-
-#include <cstdlib>
-
-#include "arch_raw.h"
-
-using namespace std;
-
-arch_Raw::arch_Raw(const string& aFileName)
-{
-    mFileDesc = vfs_fopen(aFileName.c_str(), "r");
-    if (!mFileDesc)
-    {
-        mSize = 0;
-        return;
-    }
-
-    mSize = vfs_fsize(mFileDesc);
-    if (mSize <= 0)
-    {
-        vfs_fclose(mFileDesc);
-        mSize = 0;
-        return;
-    }
-
-    mMap = malloc(mSize);
-    if (vfs_fread(mMap, 1, mSize, mFileDesc) < mSize)
-    {
-        free(mMap);
-        vfs_fclose(mFileDesc);
-        mSize = 0;
-        return;
-    }
-}
-
-arch_Raw::~arch_Raw()
-{
-    if(mSize != 0)
-    {
-        free(mMap);
-        vfs_fclose(mFileDesc);
-    }
-}
-
-bool arch_Raw::ContainsMod(const string& aFileName)
-{
-    return IsOurFile(aFileName);
-}
diff --git a/src/modplug/archive/arch_raw.h b/src/modplug/archive/arch_raw.h
index d9cae8dabf4d..4942c9baf8bb 100644
--- a/src/modplug/archive/arch_raw.h
+++ b/src/modplug/archive/arch_raw.h
@@ -9,13 +9,11 @@
 
 #include "archive.h"
 
-extern "C" {
 #include <libaudcore/vfs.h>
-}
 
 class arch_Raw: public Archive
 {
-    VFSFile *mFileDesc;
+    VFSFile mFileDesc;
 
 public:
     arch_Raw(const std::string& aFileName);
diff --git a/src/modplug/archive/archive.cc b/src/modplug/archive/archive.cc
new file mode 100644
index 000000000000..4bc67101c37a
--- /dev/null
+++ b/src/modplug/archive/archive.cc
@@ -0,0 +1,78 @@
+/* Modplug XMMS Plugin
+ * Authors: Kenton Varda <temporal at gauge3d.org>
+ *
+ * This source code is public domain.
+ */
+
+#include "archive.h"
+
+using namespace std;
+
+///* Open a read pipe */ File f;
+//f=popen("gzip -d compressed.file.name","r");
+///* Read some data in the usual manner, for example */
+//fscanf(f,"%d %f %f",name,&age,$id);
+///* Close the pipe */
+//pclose(f);
+
+Archive::~Archive()
+{
+}
+
+bool Archive::IsOurFile(const string& aFileName)
+{
+    string lExt;
+    uint32_t lPos;
+
+    lPos = aFileName.find_last_of('.');
+    if((int)lPos == -1)
+        return false;
+    lExt = aFileName.substr(lPos);
+    for(uint32_t i = 0; i < lExt.length(); i++)
+        lExt[i] = tolower(lExt[i]);
+
+    if (lExt == ".669")
+        return true;
+    if (lExt == ".amf")
+        return true;
+    if (lExt == ".ams")
+        return true;
+    if (lExt == ".dbm")
+        return true;
+    if (lExt == ".dbf")
+        return true;
+    if (lExt == ".dsm")
+        return true;
+    if (lExt == ".far")
+        return true;
+    if (lExt == ".it")
+        return true;
+    if (lExt == ".mdl")
+        return true;
+    if (lExt == ".med")
+        return true;
+    if (lExt == ".mod")
+        return true;
+    if (lExt == ".mtm")
+        return true;
+    if (lExt == ".okt")
+        return true;
+    if (lExt == ".ptm")
+        return true;
+    if (lExt == ".s3m")
+        return true;
+    if (lExt == ".stm")
+        return true;
+    if (lExt == ".ult")
+        return true;
+    if (lExt == ".umx")      //Unreal rocks!
+        return true;
+    if (lExt == ".xm")
+        return true;
+    if (lExt == ".mt2")
+        return true;
+    if (lExt == ".psm")
+        return true;
+
+    return false;
+}
diff --git a/src/modplug/archive/archive.cxx b/src/modplug/archive/archive.cxx
deleted file mode 100644
index 4bc67101c37a..000000000000
--- a/src/modplug/archive/archive.cxx
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Modplug XMMS Plugin
- * Authors: Kenton Varda <temporal at gauge3d.org>
- *
- * This source code is public domain.
- */
-
-#include "archive.h"
-
-using namespace std;
-
-///* Open a read pipe */ File f;
-//f=popen("gzip -d compressed.file.name","r");
-///* Read some data in the usual manner, for example */
-//fscanf(f,"%d %f %f",name,&age,$id);
-///* Close the pipe */
-//pclose(f);
-
-Archive::~Archive()
-{
-}
-
-bool Archive::IsOurFile(const string& aFileName)
-{
-    string lExt;
-    uint32_t lPos;
-
-    lPos = aFileName.find_last_of('.');
-    if((int)lPos == -1)
-        return false;
-    lExt = aFileName.substr(lPos);
-    for(uint32_t i = 0; i < lExt.length(); i++)
-        lExt[i] = tolower(lExt[i]);
-
-    if (lExt == ".669")
-        return true;
-    if (lExt == ".amf")
-        return true;
-    if (lExt == ".ams")
-        return true;
-    if (lExt == ".dbm")
-        return true;
-    if (lExt == ".dbf")
-        return true;
-    if (lExt == ".dsm")
-        return true;
-    if (lExt == ".far")
-        return true;
-    if (lExt == ".it")
-        return true;
-    if (lExt == ".mdl")
-        return true;
-    if (lExt == ".med")
-        return true;
-    if (lExt == ".mod")
-        return true;
-    if (lExt == ".mtm")
-        return true;
-    if (lExt == ".okt")
-        return true;
-    if (lExt == ".ptm")
-        return true;
-    if (lExt == ".s3m")
-        return true;
-    if (lExt == ".stm")
-        return true;
-    if (lExt == ".ult")
-        return true;
-    if (lExt == ".umx")      //Unreal rocks!
-        return true;
-    if (lExt == ".xm")
-        return true;
-    if (lExt == ".mt2")
-        return true;
-    if (lExt == ".psm")
-        return true;
-
-    return false;
-}
diff --git a/src/modplug/archive/open.cc b/src/modplug/archive/open.cc
new file mode 100644
index 000000000000..5d3492e50821
--- /dev/null
+++ b/src/modplug/archive/open.cc
@@ -0,0 +1,15 @@
+/* Modplug XMMS Plugin
+ * Authors: Kenton Varda <temporal at gauge3d.org>
+ *
+ * This source code is public domain.
+ */
+
+#include "open.h"
+#include "arch_raw.h"
+
+using namespace std;
+
+Archive* OpenArchive(const string& aFileName) //aFilename is url --yaz
+{
+    return new arch_Raw(aFileName);
+}
diff --git a/src/modplug/archive/open.cxx b/src/modplug/archive/open.cxx
deleted file mode 100644
index 5d3492e50821..000000000000
--- a/src/modplug/archive/open.cxx
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Modplug XMMS Plugin
- * Authors: Kenton Varda <temporal at gauge3d.org>
- *
- * This source code is public domain.
- */
-
-#include "open.h"
-#include "arch_raw.h"
-
-using namespace std;
-
-Archive* OpenArchive(const string& aFileName) //aFilename is url --yaz
-{
-    return new arch_Raw(aFileName);
-}
diff --git a/src/modplug/modplugbmp.cc b/src/modplug/modplugbmp.cc
new file mode 100644
index 000000000000..ae8d8b505f77
--- /dev/null
+++ b/src/modplug/modplugbmp.cc
@@ -0,0 +1,401 @@
+/* Modplug XMMS Plugin
+ * Authors: Kenton Varda <temporal at gauge3d.org>
+ *
+ * This source code is public domain.
+ */
+
+#include "modplugbmp.h"
+
+#include <fstream>
+#include <stdint.h>
+#include <sys/types.h>
+#include <math.h>
+
+#include <libmodplug/stdafx.h>
+#include <libmodplug/sndfile.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+
+#include "archive/open.h"
+
+using namespace std;
+
+// ModplugXMMS member functions ===============================
+
+bool ModplugXMMS::init ()
+{
+    load_settings ();
+    apply_settings ();
+    return true;
+}
+
+bool ModplugXMMS::is_our_file (const char * filename, VFSFile & file)
+{
+    string lExt;
+    uint32_t lPos;
+    const int magicSize = 32;
+    char magic[magicSize];
+
+    if (file.fread (magic, 1, magicSize) < magicSize)
+        return false;
+    if (!memcmp(magic, UMX_MAGIC, 4))
+        return true;
+    if (!memcmp(magic, "Extended Module:", 16))
+        return true;
+    if (!memcmp(magic, M669_MAGIC, 2))
+        return true;
+    if (!memcmp(magic, IT_MAGIC, 4))
+        return true;
+    if (!memcmp(magic, MTM_MAGIC, 4))
+        return true;
+    if (!memcmp(magic, PSM_MAGIC, 4))
+        return true;
+
+    if (file.fseek (44, VFS_SEEK_SET))
+        return false;
+    if (file.fread (magic, 1, 4) < 4)
+        return false;
+    if (!memcmp(magic, S3M_MAGIC, 4))
+        return true;
+
+    if (file.fseek (1080, VFS_SEEK_SET))
+        return false;
+    if (file.fread (magic, 1, 4) < 4)
+        return false;
+
+    // Check for Fast Tracker multichannel modules (xCHN, xxCH)
+    if (magic[1] == 'C' && magic[2] == 'H' && magic[3] == 'N') {
+        if (magic[0] == '6' || magic[0] == '8')
+            return true;
+    }
+    if (magic[2] == 'C' && magic[3] == 'H' && magic[0] >= '0' && magic[0] <= '9'
+     && magic[1] >= '0' && magic[1] <= '9') {
+        int nch = (magic[0] - '0') * 10 + (magic[1] - '0');
+        if ((nch % 2 == 0) && nch >= 10)
+            return true;
+    }
+
+    // Check for Amiga MOD module formats
+    if(mModProps.mGrabAmigaMOD) {
+    if (!memcmp(magic, MOD_MAGIC_PROTRACKER4, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_PROTRACKER4X, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_NOISETRACKER, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_STARTRACKER4, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_STARTRACKER8, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_STARTRACKER4X, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_STARTRACKER8X, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_FASTTRACKER4, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_OKTALYZER8, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_OKTALYZER8X, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_TAKETRACKER16, 4))
+        return true;
+    if (!memcmp(magic, MOD_MAGIC_TAKETRACKER32, 4))
+        return true;
+    } /* end of if(mModProps.mGrabAmigaMOD) */
+
+    /* We didn't find the magic bytes, fall back to extension check */
+    string aFilename = filename;
+    lPos = aFilename.find_last_of('.');
+    if((int)lPos == -1)
+        return false;
+    lExt = aFilename.substr(lPos);
+    for(uint32_t i = 0; i < lExt.length(); i++)
+        lExt[i] = tolower(lExt[i]);
+
+    if (lExt == ".amf")
+        return true;
+    if (lExt == ".ams")
+        return true;
+    if (lExt == ".dbm")
+        return true;
+    if (lExt == ".dbf")
+        return true;
+    if (lExt == ".dmf")
+        return true;
+    if (lExt == ".dsm")
+        return true;
+    if (lExt == ".far")
+        return true;
+    if (lExt == ".mdl")
+        return true;
+    if (lExt == ".stm")
+        return true;
+    if (lExt == ".ult")
+        return true;
+    if (lExt == ".mt2")
+        return true;
+
+    return false;
+}
+
+void ModplugXMMS::PlayLoop()
+{
+    uint32_t lLength;
+
+    while (! check_stop ())
+    {
+        int seek_time = check_seek ();
+        if (seek_time != -1)
+            mSoundFile->SetCurrentPos (seek_time * (int64_t)
+             mSoundFile->GetMaxPosition () / (mSoundFile->GetSongTime () * 1000));
+
+        lLength = mSoundFile->Read (mBuffer, mBufSize);
+
+        if (! lLength)
+            break;
+
+        if(mModProps.mPreamp)
+        {
+            //apply preamp
+            if(mModProps.mBits == 16)
+            {
+                unsigned n = mBufSize >> 1;
+                for(unsigned i = 0; i < n; i++) {
+                    short old = ((short*)mBuffer)[i];
+                    ((short*)mBuffer)[i] *= (short int)mPreampFactor;
+                    // detect overflow and clip!
+                    if ((old & 0x8000) !=
+                     (((short*)mBuffer)[i] & 0x8000))
+                      ((short*)mBuffer)[i] = old | 0x7FFF;
+
+                }
+            }
+            else
+            {
+                for(unsigned i = 0; i < mBufSize; i++) {
+                    unsigned char old = ((unsigned char*)mBuffer)[i];
+                    ((unsigned char*)mBuffer)[i] *= (short int)mPreampFactor;
+                    // detect overflow and clip!
+                    if ((old & 0x80) !=
+                     (((unsigned char*)mBuffer)[i] & 0x80))
+                      ((unsigned char*)mBuffer)[i] = old | 0x7F;
+                }
+            }
+        }
+
+        write_audio (mBuffer, mBufSize);
+    }
+}
+
+bool ModplugXMMS::play (const char * filename, VFSFile & file)
+{
+    //open and mmap the file
+    mArchive = OpenArchive(filename);
+    if(mArchive->Size() == 0)
+    {
+        delete mArchive;
+        return false;
+    }
+
+    mSoundFile = new CSoundFile;
+
+    //find buftime to get approx. 512 samples/block
+    mBufTime = 512000 / mModProps.mFrequency + 1;
+
+    mBufSize = mBufTime;
+    mBufSize *= mModProps.mFrequency;
+    mBufSize /= 1000;    //milliseconds
+    mBufSize *= mModProps.mChannels;
+    mBufSize *= mModProps.mBits / 8;
+
+    mBuffer = new unsigned char[mBufSize];
+
+    CSoundFile::SetWaveConfig
+    (
+        mModProps.mFrequency,
+        mModProps.mBits,
+        mModProps.mChannels
+    );
+    CSoundFile::SetWaveConfigEx
+    (
+        mModProps.mSurround,
+        !mModProps.mOversamp,
+        mModProps.mReverb,
+        true,
+        mModProps.mMegabass,
+        mModProps.mNoiseReduction,
+        false
+    );
+
+    // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
+    if(mModProps.mReverb)
+    {
+        CSoundFile::SetReverbParameters
+        (
+            mModProps.mReverbDepth,
+            mModProps.mReverbDelay
+        );
+    }
+    // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
+    if(mModProps.mMegabass)
+    {
+        CSoundFile::SetXBassParameters
+        (
+            mModProps.mBassAmount,
+            mModProps.mBassRange
+        );
+    }
+    // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
+    if(mModProps.mSurround)
+    {
+        CSoundFile::SetSurroundParameters
+        (
+            mModProps.mSurroundDepth,
+            mModProps.mSurroundDelay
+        );
+    }
+    CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
+    mSoundFile->SetRepeatCount(mModProps.mLoopCount);
+    mPreampFactor = exp(mModProps.mPreampLevel);
+
+    mSoundFile->Create
+    (
+        (unsigned char*)mArchive->Map(),
+        mArchive->Size()
+    );
+
+    Tuple ti = read_tuple (filename, file);
+    if (ti)
+        set_playback_tuple (std::move (ti));
+
+    set_stream_bitrate(mSoundFile->GetNumChannels() * 1000);
+
+    int fmt = (mModProps.mBits == 16) ? FMT_S16_NE : FMT_U8;
+    open_audio(fmt, mModProps.mFrequency, mModProps.mChannels);
+
+    PlayLoop();
+
+    delete[] mBuffer;
+    mBuffer = nullptr;
+    delete mSoundFile;
+    mSoundFile = nullptr;
+    delete mArchive;
+    mArchive = nullptr;
+
+    return true;
+}
+
+Tuple ModplugXMMS::read_tuple (const char * filename, VFSFile & file)
+{
+    CSoundFile* lSoundFile;
+    Archive* lArchive;
+    const char *tmps;
+
+    //open and mmap the file
+    lArchive = OpenArchive(filename);
+    if(lArchive->Size() == 0)
+    {
+        delete lArchive;
+        return Tuple ();
+    }
+
+    Tuple ti;
+    ti.set_filename (filename);
+
+    lSoundFile = new CSoundFile;
+    lSoundFile->Create((unsigned char*)lArchive->Map(), lArchive->Size());
+
+    switch(lSoundFile->GetType())
+        {
+    case MOD_TYPE_MOD:  tmps = "ProTracker"; break;
+    case MOD_TYPE_S3M:  tmps = "Scream Tracker 3"; break;
+    case MOD_TYPE_XM:   tmps = "Fast Tracker 2"; break;
+    case MOD_TYPE_IT:   tmps = "Impulse Tracker"; break;
+    case MOD_TYPE_MED:  tmps = "OctaMed"; break;
+    case MOD_TYPE_MTM:  tmps = "MultiTracker Module"; break;
+    case MOD_TYPE_669:  tmps = "669 Composer / UNIS 669"; break;
+    case MOD_TYPE_ULT:  tmps = "Ultra Tracker"; break;
+    case MOD_TYPE_STM:  tmps = "Scream Tracker"; break;
+    case MOD_TYPE_FAR:  tmps = "Farandole"; break;
+    case MOD_TYPE_AMF:  tmps = "ASYLUM Music Format"; break;
+    case MOD_TYPE_AMS:  tmps = "AMS module"; break;
+    case MOD_TYPE_DSM:  tmps = "DSIK Internal Format"; break;
+    case MOD_TYPE_MDL:  tmps = "DigiTracker"; break;
+    case MOD_TYPE_OKT:  tmps = "Oktalyzer"; break;
+    case MOD_TYPE_DMF:  tmps = "Delusion Digital Music Fileformat (X-Tracker)"; break;
+    case MOD_TYPE_PTM:  tmps = "PolyTracker"; break;
+    case MOD_TYPE_DBM:  tmps = "DigiBooster Pro"; break;
+    case MOD_TYPE_MT2:  tmps = "MadTracker 2"; break;
+    case MOD_TYPE_AMF0: tmps = "AMF0"; break;
+    case MOD_TYPE_PSM:  tmps = "Protracker Studio Module"; break;
+    default:        tmps = "ModPlug unknown"; break;
+    }
+    ti.set_str (Tuple::Codec, tmps);
+    ti.set_str (Tuple::Quality, _("sequenced"));
+    ti.set_int (Tuple::Length, lSoundFile->GetSongTime() * 1000);
+
+    const char *tmps2 = lSoundFile->GetTitle();
+    // Chop any leading spaces off. They are annoying in the playlist.
+    while (tmps2[0] == ' ')
+        tmps2++;
+    if (tmps2[0])
+        ti.set_str(Tuple::Title, tmps2);
+
+    //unload the file
+    lSoundFile->Destroy();
+    delete lSoundFile;
+    delete lArchive;
+    return ti;
+}
+
+void ModplugXMMS::apply_settings ()
+{
+    // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
+    if(mModProps.mReverb)
+    {
+        CSoundFile::SetReverbParameters
+        (
+            mModProps.mReverbDepth,
+            mModProps.mReverbDelay
+        );
+    }
+    // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
+    if(mModProps.mMegabass)
+    {
+        CSoundFile::SetXBassParameters
+        (
+            mModProps.mBassAmount,
+            mModProps.mBassRange
+        );
+    }
+    else //modplug seems to ignore the SetWaveConfigEx() setting for bass boost
+    {
+        CSoundFile::SetXBassParameters
+        (
+            0,
+            0
+        );
+    }
+    // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
+    if(mModProps.mSurround)
+    {
+        CSoundFile::SetSurroundParameters
+        (
+            mModProps.mSurroundDepth,
+            mModProps.mSurroundDelay
+        );
+    }
+    CSoundFile::SetWaveConfigEx
+    (
+        mModProps.mSurround,
+        !mModProps.mOversamp,
+        mModProps.mReverb,
+        true,
+        mModProps.mMegabass,
+        mModProps.mNoiseReduction,
+        false
+    );
+    CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
+    mPreampFactor = exp(mModProps.mPreampLevel);
+}
diff --git a/src/modplug/modplugbmp.cxx b/src/modplug/modplugbmp.cxx
deleted file mode 100644
index 2e7eacd1a49c..000000000000
--- a/src/modplug/modplugbmp.cxx
+++ /dev/null
@@ -1,414 +0,0 @@
-/* Modplug XMMS Plugin
- * Authors: Kenton Varda <temporal at gauge3d.org>
- *
- * This source code is public domain.
- */
-
-#include "modplugbmp.h"
-
-#include <fstream>
-#include <stdint.h>
-#include <sys/types.h>
-#include <math.h>
-
-#include <glib.h>
-
-#include <libmodplug/stdafx.h>
-#include <libmodplug/sndfile.h>
-
-extern "C" {
-#include <libaudcore/audstrings.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-}
-
-#include "archive/open.h"
-
-using namespace std;
-
-// ModplugXMMS member functions ===============================
-
-ModplugXMMS::ModplugXMMS()
-{
-    memset (this, 0, sizeof (* this));
-    mSoundFile = new CSoundFile;
-}
-
-ModplugXMMS::~ModplugXMMS()
-{
-    delete mSoundFile;
-}
-
-bool ModplugXMMS::CanPlayFileFromVFS(const string& aFilename, VFSFile *file)
-{
-    string lExt;
-    uint32_t lPos;
-    const int magicSize = 32;
-    char magic[magicSize];
-
-    if (vfs_fread(magic, 1, magicSize, file) < magicSize)
-        return false;
-    if (!memcmp(magic, UMX_MAGIC, 4))
-        return true;
-    if (!memcmp(magic, "Extended Module:", 16))
-        return true;
-    if (!memcmp(magic, M669_MAGIC, 2))
-        return true;
-    if (!memcmp(magic, IT_MAGIC, 4))
-        return true;
-    if (!memcmp(magic, MTM_MAGIC, 4))
-        return true;
-    if (!memcmp(magic, PSM_MAGIC, 4))
-        return true;
-
-    if (vfs_fseek(file, 44, SEEK_SET))
-        return false;
-    if (vfs_fread(magic, 1, 4, file) < 4)
-        return false;
-    if (!memcmp(magic, S3M_MAGIC, 4))
-        return true;
-
-    if (vfs_fseek(file, 1080, SEEK_SET))
-        return false;
-    if (vfs_fread(magic, 1, 4, file) < 4)
-        return false;
-
-    // Check for Fast Tracker multichannel modules (xCHN, xxCH)
-    if (magic[1] == 'C' && magic[2] == 'H' && magic[3] == 'N') {
-        if (magic[0] == '6' || magic[0] == '8')
-            return true;
-    }
-    if (magic[2] == 'C' && magic[3] == 'H' && g_ascii_isdigit(magic[0]) && g_ascii_isdigit(magic[1])) {
-        int nch = (magic[0] - '0') * 10 + (magic[1] - '0');
-        if ((nch % 2 == 0) && nch >= 10)
-            return true;
-    }
-
-    // Check for Amiga MOD module formats
-    if(mModProps.mGrabAmigaMOD) {
-    if (!memcmp(magic, MOD_MAGIC_PROTRACKER4, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_PROTRACKER4X, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_NOISETRACKER, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_STARTRACKER4, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_STARTRACKER8, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_STARTRACKER4X, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_STARTRACKER8X, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_FASTTRACKER4, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_OKTALYZER8, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_OKTALYZER8X, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_TAKETRACKER16, 4))
-        return true;
-    if (!memcmp(magic, MOD_MAGIC_TAKETRACKER32, 4))
-        return true;
-    } /* end of if(mModProps.mGrabAmigaMOD) */
-
-    /* We didn't find the magic bytes, fall back to extension check */
-    lPos = aFilename.find_last_of('.');
-    if((int)lPos == -1)
-        return false;
-    lExt = aFilename.substr(lPos);
-    for(uint32_t i = 0; i < lExt.length(); i++)
-        lExt[i] = tolower(lExt[i]);
-
-    if (lExt == ".amf")
-        return true;
-    if (lExt == ".ams")
-        return true;
-    if (lExt == ".dbm")
-        return true;
-    if (lExt == ".dbf")
-        return true;
-    if (lExt == ".dmf")
-        return true;
-    if (lExt == ".dsm")
-        return true;
-    if (lExt == ".far")
-        return true;
-    if (lExt == ".mdl")
-        return true;
-    if (lExt == ".stm")
-        return true;
-    if (lExt == ".ult")
-        return true;
-    if (lExt == ".mt2")
-        return true;
-
-    return false;
-}
-
-void ModplugXMMS::PlayLoop()
-{
-    uint32_t lLength;
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_time = aud_input_check_seek ();
-        if (seek_time != -1)
-            mSoundFile->SetCurrentPos (seek_time * (int64_t)
-             mSoundFile->GetMaxPosition () / (mSoundFile->GetSongTime () * 1000));
-
-        lLength = mSoundFile->Read (mBuffer, mBufSize);
-
-        if (! lLength)
-            break;
-
-        if(mModProps.mPreamp)
-        {
-            //apply preamp
-            if(mModProps.mBits == 16)
-            {
-                unsigned n = mBufSize >> 1;
-                for(unsigned i = 0; i < n; i++) {
-                    short old = ((short*)mBuffer)[i];
-                    ((short*)mBuffer)[i] *= (short int)mPreampFactor;
-                    // detect overflow and clip!
-                    if ((old & 0x8000) !=
-                     (((short*)mBuffer)[i] & 0x8000))
-                      ((short*)mBuffer)[i] = old | 0x7FFF;
-
-                }
-            }
-            else
-            {
-                for(unsigned i = 0; i < mBufSize; i++) {
-                    unsigned char old = ((unsigned char*)mBuffer)[i];
-                    ((unsigned char*)mBuffer)[i] *= (short int)mPreampFactor;
-                    // detect overflow and clip!
-                    if ((old & 0x80) !=
-                     (((unsigned char*)mBuffer)[i] & 0x80))
-                      ((unsigned char*)mBuffer)[i] = old | 0x7F;
-                }
-            }
-        }
-
-        aud_input_write_audio (mBuffer, mBufSize);
-    }
-
-    //Unload the file
-    mSoundFile->Destroy();
-    delete mArchive;
-
-    if (mBuffer)
-    {
-        delete [] mBuffer;
-        mBuffer = NULL;
-    }
-}
-
-bool ModplugXMMS::PlayFile(const string& aFilename)
-{
-    //open and mmap the file
-    mArchive = OpenArchive(aFilename);
-    if(mArchive->Size() == 0)
-    {
-        delete mArchive;
-        return false;
-    }
-
-    if (mBuffer)
-        delete [] mBuffer;
-
-    //find buftime to get approx. 512 samples/block
-    mBufTime = 512000 / mModProps.mFrequency + 1;
-
-    mBufSize = mBufTime;
-    mBufSize *= mModProps.mFrequency;
-    mBufSize /= 1000;    //milliseconds
-    mBufSize *= mModProps.mChannels;
-    mBufSize *= mModProps.mBits / 8;
-
-    mBuffer = new unsigned char[mBufSize];
-    if(!mBuffer)
-        return false;        //out of memory!
-
-    CSoundFile::SetWaveConfig
-    (
-        mModProps.mFrequency,
-        mModProps.mBits,
-        mModProps.mChannels
-    );
-    CSoundFile::SetWaveConfigEx
-    (
-        mModProps.mSurround,
-        !mModProps.mOversamp,
-        mModProps.mReverb,
-        true,
-        mModProps.mMegabass,
-        mModProps.mNoiseReduction,
-        false
-    );
-
-    // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
-    if(mModProps.mReverb)
-    {
-        CSoundFile::SetReverbParameters
-        (
-            mModProps.mReverbDepth,
-            mModProps.mReverbDelay
-        );
-    }
-    // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
-    if(mModProps.mMegabass)
-    {
-        CSoundFile::SetXBassParameters
-        (
-            mModProps.mBassAmount,
-            mModProps.mBassRange
-        );
-    }
-    // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
-    if(mModProps.mSurround)
-    {
-        CSoundFile::SetSurroundParameters
-        (
-            mModProps.mSurroundDepth,
-            mModProps.mSurroundDelay
-        );
-    }
-    CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
-    mSoundFile->SetRepeatCount(mModProps.mLoopCount);
-    mPreampFactor = exp(mModProps.mPreampLevel);
-
-    mSoundFile->Create
-    (
-        (unsigned char*)mArchive->Map(),
-        mArchive->Size()
-    );
-
-    Tuple* ti = GetSongTuple( aFilename );
-    if ( ti ) {
-        aud_input_set_tuple(ti);
-    }
-
-    aud_input_set_bitrate(mSoundFile->GetNumChannels() * 1000);
-
-    int fmt = (mModProps.mBits == 16) ? FMT_S16_NE : FMT_U8;
-    if (! aud_input_open_audio(fmt, mModProps.mFrequency, mModProps.mChannels))
-        return false;
-
-    PlayLoop();
-
-    return true;
-}
-
-Tuple* ModplugXMMS::GetSongTuple(const string& aFilename)
-{
-    CSoundFile* lSoundFile;
-    Archive* lArchive;
-    const char *tmps;
-
-    //open and mmap the file
-        lArchive = OpenArchive(aFilename);
-        if(lArchive->Size() == 0)
-        {
-                delete lArchive;
-                return NULL;
-        }
-
-    Tuple *ti = tuple_new_from_filename(aFilename.c_str());
-    lSoundFile = new CSoundFile;
-    lSoundFile->Create((unsigned char*)lArchive->Map(), lArchive->Size());
-
-    switch(lSoundFile->GetType())
-        {
-    case MOD_TYPE_MOD:  tmps = "ProTracker"; break;
-    case MOD_TYPE_S3M:  tmps = "Scream Tracker 3"; break;
-    case MOD_TYPE_XM:   tmps = "Fast Tracker 2"; break;
-    case MOD_TYPE_IT:   tmps = "Impulse Tracker"; break;
-    case MOD_TYPE_MED:  tmps = "OctaMed"; break;
-    case MOD_TYPE_MTM:  tmps = "MultiTracker Module"; break;
-    case MOD_TYPE_669:  tmps = "669 Composer / UNIS 669"; break;
-    case MOD_TYPE_ULT:  tmps = "Ultra Tracker"; break;
-    case MOD_TYPE_STM:  tmps = "Scream Tracker"; break;
-    case MOD_TYPE_FAR:  tmps = "Farandole"; break;
-    case MOD_TYPE_AMF:  tmps = "ASYLUM Music Format"; break;
-    case MOD_TYPE_AMS:  tmps = "AMS module"; break;
-    case MOD_TYPE_DSM:  tmps = "DSIK Internal Format"; break;
-    case MOD_TYPE_MDL:  tmps = "DigiTracker"; break;
-    case MOD_TYPE_OKT:  tmps = "Oktalyzer"; break;
-    case MOD_TYPE_DMF:  tmps = "Delusion Digital Music Fileformat (X-Tracker)"; break;
-    case MOD_TYPE_PTM:  tmps = "PolyTracker"; break;
-    case MOD_TYPE_DBM:  tmps = "DigiBooster Pro"; break;
-    case MOD_TYPE_MT2:  tmps = "MadTracker 2"; break;
-    case MOD_TYPE_AMF0: tmps = "AMF0"; break;
-    case MOD_TYPE_PSM:  tmps = "Protracker Studio Module"; break;
-    default:        tmps = "ModPlug unknown"; break;
-    }
-    tuple_set_str(ti, FIELD_CODEC, tmps);
-    tuple_set_str(ti, FIELD_QUALITY, _("sequenced"));
-    tuple_set_int(ti, FIELD_LENGTH, lSoundFile->GetSongTime() * 1000);
-
-    const char *tmps2 = lSoundFile->GetTitle();
-    // Chop any leading spaces off. They are annoying in the playlist.
-    while ( *tmps2 == ' ' ) tmps2++ ;
-    tuple_set_str(ti, FIELD_TITLE, tmps2);
-
-    //unload the file
-    lSoundFile->Destroy();
-    delete lSoundFile;
-    delete lArchive;
-    return ti;
-}
-
-void ModplugXMMS::SetModProps(const ModplugSettings& aModProps)
-{
-    mModProps = aModProps;
-
-    // [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
-    if(mModProps.mReverb)
-    {
-        CSoundFile::SetReverbParameters
-        (
-            mModProps.mReverbDepth,
-            mModProps.mReverbDelay
-        );
-    }
-    // [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100]
-    if(mModProps.mMegabass)
-    {
-        CSoundFile::SetXBassParameters
-        (
-            mModProps.mBassAmount,
-            mModProps.mBassRange
-        );
-    }
-    else //modplug seems to ignore the SetWaveConfigEx() setting for bass boost
-    {
-        CSoundFile::SetXBassParameters
-        (
-            0,
-            0
-        );
-    }
-    // [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms]
-    if(mModProps.mSurround)
-    {
-        CSoundFile::SetSurroundParameters
-        (
-            mModProps.mSurroundDepth,
-            mModProps.mSurroundDelay
-        );
-    }
-    CSoundFile::SetWaveConfigEx
-    (
-        mModProps.mSurround,
-        !mModProps.mOversamp,
-        mModProps.mReverb,
-        true,
-        mModProps.mMegabass,
-        mModProps.mNoiseReduction,
-        false
-    );
-    CSoundFile::SetResamplingMode(mModProps.mResamplingMode);
-    mPreampFactor = exp(mModProps.mPreampLevel);
-}
diff --git a/src/modplug/modplugbmp.h b/src/modplug/modplugbmp.h
index 63af9fc5a3c3..c2887ceb9865 100644
--- a/src/modplug/modplugbmp.h
+++ b/src/modplug/modplugbmp.h
@@ -7,11 +7,8 @@
 #ifndef __MODPLUGXMMS_CMODPLUGXMMS_H_INCLUDED__
 #define __MODPLUGXMMS_CMODPLUGXMMS_H_INCLUDED__
 
-#include <string>
-
-extern "C" {
-#include <audacious/plugin.h>
-}
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
 
 #include "settings.h"
 
@@ -42,32 +39,49 @@ extern "C" {
 class CSoundFile;
 class Archive;
 
-class ModplugXMMS
+struct PreferencesWidget;
+
+class ModplugXMMS : public InputPlugin
 {
 public:
-    ModplugXMMS();
-    ~ModplugXMMS();
+    static const char * const exts[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
 
-    bool CanPlayFileFromVFS(const std::string& aFilename, VFSFile *file);
+    static constexpr PluginInfo info = {
+        N_("ModPlug (Module Player)"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
 
-    bool PlayFile(const std::string& aFilename);
+    static constexpr auto iinfo = InputInfo (FlagSubtunes)
+        .with_exts (exts);
 
-    Tuple* GetSongTuple(const std::string& aFilename);
+    constexpr ModplugXMMS () : InputPlugin (info, iinfo) {}
 
-    void SetModProps(const ModplugSettings& aModProps);
+    bool init ();
+
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
 
 private:
-    unsigned char*  mBuffer;
-    uint32_t  mBufSize;
+    unsigned char * mBuffer = nullptr;
+    uint32_t mBufSize = 0;
+
+    ModplugSettings mModProps {};
 
-    ModplugSettings mModProps;
+    uint32_t mBufTime = 0; // milliseconds
 
-    uint32_t  mBufTime;     //milliseconds
+    CSoundFile * mSoundFile = nullptr;
+    Archive * mArchive = nullptr;
 
-    CSoundFile* mSoundFile;
-    Archive*    mArchive;
+    float mPreampFactor = 0;
 
-    float mPreampFactor;
+    void load_settings ();
+    void apply_settings ();
 
     void PlayLoop();
 };
diff --git a/src/modplug/plugin.cxx b/src/modplug/plugin.cxx
deleted file mode 100644
index a7a182f3db03..000000000000
--- a/src/modplug/plugin.cxx
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Modplug XMMS Plugin
- * Authors: Kenton Varda <temporal at gauge3d.org>
- *
- * This source code is public domain.
- */
-
-#include "plugin.h"
-#include "modplugbmp.h"
-
-static ModplugXMMS gModplugXMMS;
-
-extern "C" {
-
-void InitSettings (const ModplugSettings * settings)
-{
-    gModplugXMMS.SetModProps (* settings);
-}
-
-int CanPlayFileFromVFS(const char* aFilename, VFSFile *VFSFile)
-{
-    if(gModplugXMMS.CanPlayFileFromVFS(aFilename, VFSFile))
-        return 1;
-    return 0;
-}
-
-bool_t PlayFile(const char * filename, VFSFile * file)
-{
-    return gModplugXMMS.PlayFile(filename);
-}
-
-Tuple* GetSongTuple(const char* aFilename, VFSFile *fd)
-{
-    return gModplugXMMS.GetSongTuple(aFilename);
-}
-
-} /* extern "C" */
diff --git a/src/modplug/plugin.h b/src/modplug/plugin.h
deleted file mode 100644
index e4b5698871f3..000000000000
--- a/src/modplug/plugin.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef MODPLUG_PLUGIN_H
-#define MODPLUG_PLUGIN_H
-
-#include "settings.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <audacious/plugin.h>
-
-void InitSettings (const ModplugSettings * settings);
-int CanPlayFileFromVFS (const char * filename, VFSFile * file);
-bool_t PlayFile (const char * filename, VFSFile * file);
-Tuple * GetSongTuple (const char * filename, VFSFile * file);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* MODPLUG_PLUGIN_H */
diff --git a/src/modplug/plugin_main.c b/src/modplug/plugin_main.c
deleted file mode 100644
index a24aafbcd3ab..000000000000
--- a/src/modplug/plugin_main.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Modplug Audacious Plugin
- *
- * Configuration GUI contributed in part by Vladimir Strakh.
- *
- * This source code is public domain.
- */
-
-#include "plugin.h"
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#define MODPLUG_CFGID "modplug"
-
-static const char * fmts[] =
-    { "amf", "ams", "dbm", "dbf", "dsm", "far", "mdl", "stm", "ult", "mt2",
-      "mod", "s3m", "dmf", "umx", "it", "669", "xm", "mtm", "psm", "ft2",
-      NULL };
-
-static const char * const modplug_defaults[] = {
- "Bits", "16",
- "Channels", "2",
- "ResamplingMode", "3", /* SRCMODE_POLYPHASE */
- "Frequency", "44100",
-
- "Reverb", "FALSE",
- "ReverbDepth", "30",
- "ReverbDelay", "100",
-
- "Megabass", "FALSE",
- "BassAmount", "40",
- "BassRange", "30",
-
- "Surround", "TRUE",
- "SurroundDepth", "20",
- "SurroundDelay", "20",
-
- "PreAmp", "FALSE",
- "PreAmpLevel", "0",
-
- "Oversampling", "TRUE",
- "NoiseReduction", "TRUE",
- "GrabAmigaMOD", "TRUE",
- "LoopCount", "0",
-
- NULL
-};
-
-static ModplugSettings modplug_settings;
-
-static const PreferencesWidget quality_widgets[] = {
-    {WIDGET_LABEL, N_("<b>Resolution</b>")},
-    {WIDGET_RADIO_BTN, N_("8-bit"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mBits, .data = {.radio_btn = {8}}},
-    {WIDGET_RADIO_BTN, N_("16-bit"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mBits, .data = {.radio_btn = {16}}},
-    {WIDGET_LABEL, N_("<b>Channels</b>")},
-    {WIDGET_RADIO_BTN, N_("Mono"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mChannels, .data = {.radio_btn = {1}}},
-    {WIDGET_RADIO_BTN, N_("Stereo"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mChannels, .data = {.radio_btn = {2}}},
-    {WIDGET_LABEL, N_("<b>Resampling</b>")},
-    {WIDGET_RADIO_BTN, N_("Nearest (fastest)"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mResamplingMode, .data = {.radio_btn = {0}}},
-    {WIDGET_RADIO_BTN, N_("Linear (fast)"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mResamplingMode, .data = {.radio_btn = {1}}},
-    {WIDGET_RADIO_BTN, N_("Spline (good)"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mResamplingMode, .data = {.radio_btn = {2}}},
-    {WIDGET_RADIO_BTN, N_("Polyphase (best)"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mResamplingMode, .data = {.radio_btn = {3}}},
-    {WIDGET_LABEL, N_("<b>Sampling rate</b>")},
-    {WIDGET_RADIO_BTN, N_("22 kHz"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mFrequency, .data = {.radio_btn = {22050}}},
-    {WIDGET_RADIO_BTN, N_("44 kHz"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mFrequency, .data = {.radio_btn = {44100}}},
-    {WIDGET_RADIO_BTN, N_("48 kHz"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mFrequency, .data = {.radio_btn = {48000}}},
-    {WIDGET_RADIO_BTN, N_("96 kHz"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mFrequency, .data = {.radio_btn = {96000}}}
-};
-
-static PreferencesWidget reverb_fields[] = {
-    {WIDGET_SPIN_BTN, N_("Level:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mReverbDepth, .data = {.spin_btn = {0, 100, 1, "%"}}},
-    {WIDGET_SPIN_BTN, N_("Delay:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mReverbDelay, .data = {.spin_btn = {40, 200, 1, N_("ms")}}}
-};
-
-static PreferencesWidget bass_fields[] = {
-    {WIDGET_SPIN_BTN, N_("Level:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mBassAmount, .data = {.spin_btn = {0, 100, 1, "%"}}},
-    {WIDGET_SPIN_BTN, N_("Cutoff:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mBassRange, .data = {.spin_btn = {10, 100, 1, N_("Hz")}}}
-};
-
-static PreferencesWidget surround_fields[] = {
-    {WIDGET_SPIN_BTN, N_("Level:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mSurroundDepth, .data = {.spin_btn = {0, 100, 1, "%"}}},
-    {WIDGET_SPIN_BTN, N_("Delay:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mSurroundDelay, .data = {.spin_btn = {5,  40, 1, N_("ms")}}}
-};
-
-static PreferencesWidget preamp_fields[] = {
-    {WIDGET_SPIN_BTN, N_("Volume:"), .cfg_type = VALUE_FLOAT,
-     .cfg = & modplug_settings.mPreampLevel, .data = {.spin_btn = {-3, 3, 0.1}}},
-};
-
-static const PreferencesWidget effects_widgets[] = {
-    {WIDGET_LABEL, N_("<b>Reverb</b>")},
-    {WIDGET_CHK_BTN, N_("Enable"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mReverb},
-    {WIDGET_TABLE, .child = TRUE, .data = {.table = {reverb_fields, ARRAY_LEN (reverb_fields)}}},
-    {WIDGET_LABEL, N_("<b>Bass Boost</b>")},
-    {WIDGET_CHK_BTN, N_("Enable"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mMegabass },
-    {WIDGET_TABLE, .child = TRUE, .data = {.table = {bass_fields, ARRAY_LEN (bass_fields)}}},
-    {WIDGET_LABEL, N_("<b>Surround</b>")},
-    {WIDGET_CHK_BTN, N_("Enable"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mSurround },
-    {WIDGET_TABLE, .child = TRUE, .data = {.table = {surround_fields, ARRAY_LEN (surround_fields)}}},
-    {WIDGET_LABEL, N_("<b>Preamp</b>")},
-    {WIDGET_CHK_BTN, N_("Enable"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mPreamp },
-    {WIDGET_TABLE, .child = TRUE, .data = {.table = {preamp_fields, ARRAY_LEN (preamp_fields)}}}
-};
-
-static const PreferencesWidget misc_widgets[] = {
-    {WIDGET_LABEL, N_("<b>Miscellaneous</b>")},
-    {WIDGET_CHK_BTN, N_("Oversample"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mOversamp},
-    {WIDGET_CHK_BTN, N_("Noise reduction"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mNoiseReduction},
-    {WIDGET_CHK_BTN, N_("Play Amiga MODs"), .cfg_type = VALUE_BOOLEAN,
-     .cfg = & modplug_settings.mGrabAmigaMOD},
-    {WIDGET_LABEL, N_("<b>Repeat</b>")},
-    {WIDGET_SPIN_BTN, N_("Repeat count:"), .cfg_type = VALUE_INT,
-     .cfg = & modplug_settings.mLoopCount, .data = {.spin_btn = {-1, 100, 1}}},
-    {WIDGET_LABEL, N_("To repeat forever, set the repeat count to -1.")}
-};
-
-static const PreferencesWidget modplug_columns[] = {
-    {WIDGET_BOX, .data = {.box = {quality_widgets, ARRAY_LEN (quality_widgets)}}},
-    {WIDGET_SEPARATOR},
-    {WIDGET_BOX, .data = {.box = {effects_widgets, ARRAY_LEN (effects_widgets)}}},
-    {WIDGET_SEPARATOR},
-    {WIDGET_BOX, .data = {.box = {misc_widgets, ARRAY_LEN (misc_widgets)}}}
-};
-
-static const PreferencesWidget modplug_widgets[] = {
-    {WIDGET_BOX, .data = {.box = {modplug_columns, ARRAY_LEN (modplug_columns), .horizontal = TRUE}}}
-};
-
-static void modplug_settings_load ()
-{
-    aud_config_set_defaults (MODPLUG_CFGID, modplug_defaults);
-
-    modplug_settings.mBits = aud_get_int (MODPLUG_CFGID, "Bits");
-    modplug_settings.mChannels = aud_get_int (MODPLUG_CFGID, "Channels");
-    modplug_settings.mResamplingMode = aud_get_int (MODPLUG_CFGID, "ResamplingMode");
-    modplug_settings.mFrequency = aud_get_int (MODPLUG_CFGID, "Frequency");
-
-    modplug_settings.mReverb = aud_get_bool (MODPLUG_CFGID, "Reverb");
-    modplug_settings.mReverbDepth = aud_get_int (MODPLUG_CFGID, "ReverbDepth");
-    modplug_settings.mReverbDelay = aud_get_int (MODPLUG_CFGID, "ReverbDelay");
-
-    modplug_settings.mMegabass = aud_get_bool (MODPLUG_CFGID, "Megabass");
-    modplug_settings.mBassAmount = aud_get_int (MODPLUG_CFGID, "BassAmount");
-    modplug_settings.mBassRange = aud_get_int (MODPLUG_CFGID, "BassRange");
-
-    modplug_settings.mSurround = aud_get_bool (MODPLUG_CFGID, "Surround");
-    modplug_settings.mSurroundDepth = aud_get_int (MODPLUG_CFGID, "SurroundDepth");
-    modplug_settings.mSurroundDelay = aud_get_int (MODPLUG_CFGID, "SurroundDelay");
-
-    modplug_settings.mPreamp = aud_get_bool (MODPLUG_CFGID, "PreAmp");
-    modplug_settings.mPreampLevel = aud_get_double (MODPLUG_CFGID, "PreAmpLevel");
-
-    modplug_settings.mOversamp = aud_get_bool (MODPLUG_CFGID, "Oversampling");
-    modplug_settings.mNoiseReduction = aud_get_bool (MODPLUG_CFGID, "NoiseReduction");
-    modplug_settings.mGrabAmigaMOD = aud_get_bool (MODPLUG_CFGID, "GrabAmigaMOD");
-    modplug_settings.mLoopCount = aud_get_int (MODPLUG_CFGID, "LoopCount");
-}
-
-static void modplug_settings_save ()
-{
-    aud_set_int (MODPLUG_CFGID, "Bits", modplug_settings.mBits);
-    aud_set_int (MODPLUG_CFGID, "Channels", modplug_settings.mChannels);
-    aud_set_int (MODPLUG_CFGID, "ResamplingMode", modplug_settings.mResamplingMode);
-    aud_set_int (MODPLUG_CFGID, "Frequency", modplug_settings.mFrequency);
-
-    aud_set_bool (MODPLUG_CFGID, "Reverb", modplug_settings.mReverb);
-    aud_set_int (MODPLUG_CFGID, "ReverbDepth", modplug_settings.mReverbDepth);
-    aud_set_int (MODPLUG_CFGID, "ReverbDelay", modplug_settings.mReverbDelay);
-
-    aud_set_bool (MODPLUG_CFGID, "Megabass", modplug_settings.mMegabass);
-    aud_set_int (MODPLUG_CFGID, "BassAmount", modplug_settings.mBassAmount);
-    aud_set_int (MODPLUG_CFGID, "BassRange", modplug_settings.mBassRange);
-
-    aud_set_bool (MODPLUG_CFGID, "Surround", modplug_settings.mSurround);
-    aud_set_int (MODPLUG_CFGID, "SurroundDepth", modplug_settings.mSurroundDepth);
-    aud_set_int (MODPLUG_CFGID, "SurroundDelay", modplug_settings.mSurroundDelay);
-
-    aud_set_bool (MODPLUG_CFGID, "PreAmp", modplug_settings.mPreamp);
-    aud_set_double (MODPLUG_CFGID, "PreAmpLevel", modplug_settings.mPreampLevel);
-
-    aud_set_bool (MODPLUG_CFGID, "Oversampling", modplug_settings.mOversamp);
-    aud_set_bool (MODPLUG_CFGID, "NoiseReduction", modplug_settings.mNoiseReduction);
-    aud_set_bool (MODPLUG_CFGID, "GrabAmigaMOD", modplug_settings.mGrabAmigaMOD);
-    aud_set_int (MODPLUG_CFGID, "LoopCount", modplug_settings.mLoopCount);
-}
-
-static bool_t modplug_init (void)
-{
-    modplug_settings_load ();
-    InitSettings (& modplug_settings);
-    return TRUE;
-}
-
-static void modplug_settings_apply (void)
-{
-    InitSettings (& modplug_settings);
-    modplug_settings_save ();
-}
-
-static const PluginPreferences modplug_prefs = {
- .widgets = modplug_widgets,
- .n_widgets = ARRAY_LEN (modplug_widgets),
- .init = modplug_settings_load,
- .apply = modplug_settings_apply
-};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("ModPlug (Module Player)"),
-    .domain = PACKAGE,
-    .prefs = &modplug_prefs,
-    .init = modplug_init,
-    .play = PlayFile,
-    .probe_for_tuple = GetSongTuple,
-    .is_our_file_from_vfs = CanPlayFileFromVFS,
-    .extensions = fmts,
-    .have_subtune = TRUE,   // to exclude .zip etc which doesn't contain any mod file --yaz
-)
diff --git a/src/modplug/plugin_main.cc b/src/modplug/plugin_main.cc
new file mode 100644
index 000000000000..6d22ea4e2373
--- /dev/null
+++ b/src/modplug/plugin_main.cc
@@ -0,0 +1,158 @@
+/*
+ * Modplug Audacious Plugin
+ *
+ * Configuration GUI contributed in part by Vladimir Strakh.
+ *
+ * This source code is public domain.
+ */
+
+#include "modplugbmp.h"
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/preferences.h>
+
+#define MODPLUG_CFGID "modplug"
+
+EXPORT ModplugXMMS aud_plugin_instance;
+
+const char * const ModplugXMMS::exts[] =
+    { "amf", "ams", "dbm", "dbf", "dsm", "far", "mdl", "stm", "ult", "mt2",
+      "mod", "s3m", "dmf", "umx", "it", "669", "xm", "mtm", "psm", "ft2",
+      nullptr };
+
+const char * const ModplugXMMS::defaults[] = {
+ "Bits", "16",
+ "Channels", "2",
+ "ResamplingMode", "3", /* SRCMODE_POLYPHASE */
+ "Frequency", "44100",
+
+ "Reverb", "FALSE",
+ "ReverbDepth", "30",
+ "ReverbDelay", "100",
+
+ "Megabass", "FALSE",
+ "BassAmount", "40",
+ "BassRange", "30",
+
+ "Surround", "TRUE",
+ "SurroundDepth", "20",
+ "SurroundDelay", "20",
+
+ "PreAmp", "FALSE",
+ "PreAmpLevel", "0",
+
+ "Oversampling", "TRUE",
+ "NoiseReduction", "TRUE",
+ "GrabAmigaMOD", "TRUE",
+ "LoopCount", "0",
+
+ nullptr
+};
+
+static const PreferencesWidget quality_widgets[] = {
+    WidgetLabel (N_("<b>Resolution</b>")),
+    WidgetRadio (N_("8-bit"), WidgetInt (MODPLUG_CFGID, "Bits"), {8}),
+    WidgetRadio (N_("16-bit"), WidgetInt (MODPLUG_CFGID, "Bits"), {16}),
+    WidgetLabel (N_("<b>Channels</b>")),
+    WidgetRadio (N_("Mono"), WidgetInt (MODPLUG_CFGID, "Channels"), {1}),
+    WidgetRadio (N_("Stereo"), WidgetInt (MODPLUG_CFGID, "Channels"), {2}),
+    WidgetLabel (N_("<b>Resampling</b>")),
+    WidgetRadio (N_("Nearest (fastest)"), WidgetInt (MODPLUG_CFGID, "ResamplingMode"), {0}),
+    WidgetRadio (N_("Linear (fast)"), WidgetInt (MODPLUG_CFGID, "ResamplingMode"), {1}),
+    WidgetRadio (N_("Spline (good)"), WidgetInt (MODPLUG_CFGID, "ResamplingMode"), {2}),
+    WidgetRadio (N_("Polyphase (best)"), WidgetInt (MODPLUG_CFGID, "ResamplingMode"), {3}),
+    WidgetLabel (N_("<b>Sample rate</b>")),
+    WidgetRadio (N_("22 kHz"), WidgetInt (MODPLUG_CFGID, "Frequency"), {22050}),
+    WidgetRadio (N_("44 kHz"), WidgetInt (MODPLUG_CFGID, "Frequency"), {44100}),
+    WidgetRadio (N_("48 kHz"), WidgetInt (MODPLUG_CFGID, "Frequency"), {48000}),
+    WidgetRadio (N_("96 kHz"), WidgetInt (MODPLUG_CFGID, "Frequency"), {96000})
+};
+
+static const PreferencesWidget reverb_fields[] = {
+    WidgetSpin (N_("Level:"), WidgetInt (MODPLUG_CFGID, "ReverbDepth"), {0, 100, 1, "%"}),
+    WidgetSpin (N_("Delay:"), WidgetInt (MODPLUG_CFGID, "ReverbDelay"), {40, 200, 1, N_("ms")})
+};
+
+static const PreferencesWidget bass_fields[] = {
+    WidgetSpin (N_("Level:"), WidgetInt (MODPLUG_CFGID, "BassAmount"), {0, 100, 1, "%"}),
+    WidgetSpin (N_("Cutoff:"), WidgetInt (MODPLUG_CFGID, "BassRange"), {10, 100, 1, N_("Hz")})
+};
+
+static const PreferencesWidget surround_fields[] = {
+    WidgetSpin (N_("Level:"), WidgetInt (MODPLUG_CFGID, "SurroundDepth"), {0, 100, 1, "%"}),
+    WidgetSpin (N_("Delay:"), WidgetInt (MODPLUG_CFGID, "SurroundDelay"), {5,  40, 1, N_("ms")})
+};
+
+static const PreferencesWidget preamp_fields[] = {
+    WidgetSpin (N_("Volume:"), WidgetFloat (MODPLUG_CFGID, "PreampLevel"), {-3, 3, 0.1}),
+};
+
+static const PreferencesWidget effects_widgets[] = {
+    WidgetLabel (N_("<b>Reverb</b>")),
+    WidgetCheck (N_("Enable"), WidgetBool (MODPLUG_CFGID, "Reverb")),
+    WidgetTable ({{reverb_fields}}, WIDGET_CHILD),
+    WidgetLabel (N_("<b>Bass Boost</b>")),
+    WidgetCheck (N_("Enable"), WidgetBool (MODPLUG_CFGID, "Megabass")),
+    WidgetTable ({{bass_fields}}, WIDGET_CHILD),
+    WidgetLabel (N_("<b>Surround</b>")),
+    WidgetCheck (N_("Enable"), WidgetBool (MODPLUG_CFGID, "Surround")),
+    WidgetTable ({{surround_fields}}, WIDGET_CHILD),
+    WidgetLabel (N_("<b>Preamp</b>")),
+    WidgetCheck (N_("Enable"), WidgetBool (MODPLUG_CFGID, "Preamp")),
+    WidgetTable ({{preamp_fields}}, WIDGET_CHILD)
+};
+
+static const PreferencesWidget misc_widgets[] = {
+    WidgetLabel (N_("<b>Miscellaneous</b>")),
+    WidgetCheck (N_("Oversample"), WidgetBool (MODPLUG_CFGID, "Oversamp")),
+    WidgetCheck (N_("Noise reduction"), WidgetBool (MODPLUG_CFGID, "NoiseReduction")),
+    WidgetCheck (N_("Play Amiga MODs"), WidgetBool (MODPLUG_CFGID, "GrabAmigaMOD")),
+    WidgetLabel (N_("<b>Repeat</b>")),
+    WidgetSpin (N_("Repeat count:"), WidgetInt (MODPLUG_CFGID, "LoopCount"), {-1, 100, 1}),
+    WidgetLabel (N_("To repeat forever, set the repeat count to -1."))
+};
+
+static const PreferencesWidget widget_columns[] = {
+    WidgetBox ({{quality_widgets}}),
+    WidgetSeparator (),
+    WidgetBox ({{effects_widgets}}),
+    WidgetSeparator (),
+    WidgetBox ({{misc_widgets}})
+};
+
+const PreferencesWidget ModplugXMMS::widgets[] = {
+    WidgetBox ({{widget_columns}, true}),
+    WidgetLabel (N_("These settings will take effect when Audacious is restarted."))
+};
+
+const PluginPreferences ModplugXMMS::prefs = {{widgets}};
+
+void ModplugXMMS::load_settings ()
+{
+    aud_config_set_defaults (MODPLUG_CFGID, defaults);
+
+    mModProps.mBits = aud_get_int (MODPLUG_CFGID, "Bits");
+    mModProps.mChannels = aud_get_int (MODPLUG_CFGID, "Channels");
+    mModProps.mResamplingMode = aud_get_int (MODPLUG_CFGID, "ResamplingMode");
+    mModProps.mFrequency = aud_get_int (MODPLUG_CFGID, "Frequency");
+
+    mModProps.mReverb = aud_get_bool (MODPLUG_CFGID, "Reverb");
+    mModProps.mReverbDepth = aud_get_int (MODPLUG_CFGID, "ReverbDepth");
+    mModProps.mReverbDelay = aud_get_int (MODPLUG_CFGID, "ReverbDelay");
+
+    mModProps.mMegabass = aud_get_bool (MODPLUG_CFGID, "Megabass");
+    mModProps.mBassAmount = aud_get_int (MODPLUG_CFGID, "BassAmount");
+    mModProps.mBassRange = aud_get_int (MODPLUG_CFGID, "BassRange");
+
+    mModProps.mSurround = aud_get_bool (MODPLUG_CFGID, "Surround");
+    mModProps.mSurroundDepth = aud_get_int (MODPLUG_CFGID, "SurroundDepth");
+    mModProps.mSurroundDelay = aud_get_int (MODPLUG_CFGID, "SurroundDelay");
+
+    mModProps.mPreamp = aud_get_bool (MODPLUG_CFGID, "PreAmp");
+    mModProps.mPreampLevel = aud_get_double (MODPLUG_CFGID, "PreAmpLevel");
+
+    mModProps.mOversamp = aud_get_bool (MODPLUG_CFGID, "Oversampling");
+    mModProps.mNoiseReduction = aud_get_bool (MODPLUG_CFGID, "NoiseReduction");
+    mModProps.mGrabAmigaMOD = aud_get_bool (MODPLUG_CFGID, "GrabAmigaMOD");
+    mModProps.mLoopCount = aud_get_int (MODPLUG_CFGID, "LoopCount");
+}
diff --git a/src/modplug/settings.h b/src/modplug/settings.h
index 4fa939a2cb16..58e9116d5407 100644
--- a/src/modplug/settings.h
+++ b/src/modplug/settings.h
@@ -1,41 +1,31 @@
 #ifndef MODPLUG_SETTINGS_H
 #define MODPLUG_SETTINGS_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <libaudcore/core.h>
-
 typedef struct {
     int mBits;
     int mChannels;
     int mResamplingMode;
     int mFrequency;
 
-    bool_t mReverb;
+    bool mReverb;
     int mReverbDepth;
     int mReverbDelay;
 
-    bool_t mMegabass;
+    bool mMegabass;
     int mBassAmount;
     int mBassRange;
 
-    bool_t mSurround;
+    bool mSurround;
     int mSurroundDepth;
     int mSurroundDelay;
 
-    bool_t mPreamp;
-    float mPreampLevel;
+    bool mPreamp;
+    double mPreampLevel;
 
-    bool_t mOversamp;
-    bool_t mNoiseReduction;
-    bool_t mGrabAmigaMOD;
+    bool mOversamp;
+    bool mNoiseReduction;
+    bool mGrabAmigaMOD;
     int mLoopCount;
 } ModplugSettings;
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
 #endif /* MODPLUG_SETTINGS_H */
diff --git a/src/mpg123/Makefile b/src/mpg123/Makefile
index 4b5b578a008b..85d5f392c299 100644
--- a/src/mpg123/Makefile
+++ b/src/mpg123/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = madplug${PLUGIN_SUFFIX}
 
-SRCS = mpg123.c
+SRCS = mpg123.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MPG123_CFLAGS} -I../..
 LIBS += ${MPG123_LIBS} -laudtag -lm
diff --git a/src/mpg123/mpg123.c b/src/mpg123/mpg123.c
deleted file mode 100644
index 636dc5d0f2ce..000000000000
--- a/src/mpg123/mpg123.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>.
- * Copyright (c) 2010-2011 John Lindgren <john.lindgren at tds.net>.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string.h>
-
-#include <mpg123.h>
-
-#ifdef DEBUG_MPG123_IO
-# define MPG123_IODBG(...)	AUDDBG(__VA_ARGS__)
-#else
-# define MPG123_IODBG(...)	do { } while (0)
-#endif
-
-#include <libaudcore/audstrings.h>
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-#include <audacious/audtag.h>
-
-/* Define to read all frame headers when calculating file length */
-/* #define FULL_SCAN */
-
-#define DECODE_OPTIONS (MPG123_QUIET | MPG123_GAPLESS | MPG123_SEEKBUFFER | MPG123_FUZZY)
-
-static ssize_t replace_read (void * file, void * buffer, size_t length)
-{
-	return vfs_fread (buffer, 1, length, file);
-}
-
-static off_t replace_lseek (void * file, off_t to, int whence)
-{
-	return (! vfs_fseek (file, to, whence)) ? vfs_ftell (file) : -1;
-}
-
-static off_t replace_lseek_dummy (void * file, off_t to, int whence)
-{
-	return -1;
-}
-
-/** plugin glue **/
-static bool_t aud_mpg123_init (void)
-{
-	AUDDBG("initializing mpg123 library\n");
-	mpg123_init();
-
-	return TRUE;
-}
-
-static void
-aud_mpg123_deinit(void)
-{
-	AUDDBG("deinitializing mpg123 library\n");
-	mpg123_exit();
-}
-
-static void set_format (mpg123_handle * dec)
-{
-	static const int rates[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000,
-	 44100, 48000};
-
-	mpg123_format_none (dec);
-	for (int i = 0; i < ARRAY_LEN (rates); i ++)
-		mpg123_format (dec, rates[i], 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);
-}
-
-static bool_t mpg123_probe_for_fd (const char * fname, VFSFile * file)
-{
-	if (! file)
-		return FALSE;
-
-	/* 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;
-
-	bool_t is_streaming = vfs_is_streaming (file);
-
-	/* 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)
-	{
-		char id3buf[3];
-		if (vfs_fread (id3buf, 1, 3, file) != 3)
-			return FALSE;
-
-		if (! memcmp (id3buf, "ID3", 3))
-			return TRUE;
-
-		if (vfs_fseek (file, 0, SEEK_SET) < 0)
-			return FALSE;
-	}
-
-	mpg123_handle * dec = mpg123_new (NULL, NULL);
-	mpg123_param (dec, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0);
-
-	if (is_streaming)
-		mpg123_replace_reader_handle (dec, replace_read, replace_lseek_dummy, NULL);
-	else
-		mpg123_replace_reader_handle (dec, replace_read, replace_lseek, NULL);
-
-	set_format (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;
-	}
-
-#ifdef FULL_SCAN
-	if (mpg123_scan (dec) < 0)
-		goto ERR;
-#endif
-
-RETRY:;
-	long rate;
-	int chan, enc;
-	if ((res = mpg123_getformat (dec, & rate, & chan, & enc)) < 0)
-		goto ERR;
-
-	struct mpg123_frameinfo info;
-	if ((res = mpg123_info (dec, & info)) < 0)
-		goto ERR;
-
-	float out[chan * (rate / 10)];
-	size_t done;
-	while ((res = mpg123_read (dec, (void *) out, sizeof out, & done)) < 0)
-	{
-		if (res == MPG123_NEW_FORMAT)
-			goto RETRY;
-		goto ERR;
-	}
-
-	char str[32];
-	make_format_string (& info, str, sizeof str);
-	AUDDBG ("Accepted as %s: %s.\n", str, fname);
-
-	mpg123_delete (dec);
-	return TRUE;
-}
-
-static Tuple * mpg123_probe_for_tuple (const char * filename, VFSFile * file)
-{
-	if (! file)
-		return NULL;
-
-	bool_t stream = vfs_is_streaming (file);
-	mpg123_handle * decoder = mpg123_new (NULL, NULL);
-	int result;
-	long rate;
-	int channels, encoding;
-	struct mpg123_frameinfo info;
-	char scratch[32];
-
-	mpg123_param (decoder, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0);
-
-	if (stream)
-		mpg123_replace_reader_handle (decoder, replace_read, replace_lseek_dummy, NULL);
-	else
-		mpg123_replace_reader_handle (decoder, replace_read, replace_lseek, NULL);
-
-	if ((result = mpg123_open_handle (decoder, file)) < 0)
-		goto ERR;
-
-#ifdef FULL_SCAN
-	if (mpg123_scan (decoder) < 0)
-		goto ERR;
-#endif
-
-	if ((result = mpg123_getformat (decoder, & rate, & channels, & encoding)) < 0)
-		goto ERR;
-	if ((result = mpg123_info (decoder, & info)) < 0)
-		goto ERR;
-
-	Tuple * tuple = tuple_new_from_filename (filename);
-	make_format_string (& info, scratch, sizeof scratch);
-	tuple_set_str (tuple, FIELD_CODEC, scratch);
-	snprintf (scratch, sizeof scratch, "%s, %d Hz", (channels == 2)
-	 ? _("Stereo") : (channels > 2) ? _("Surround") : _("Mono"), (int) rate);
-	tuple_set_str (tuple, FIELD_QUALITY, scratch);
-	tuple_set_int (tuple, FIELD_BITRATE, info.bitrate);
-
-	if (! stream)
-	{
-		int64_t size = vfs_fsize (file);
-		int64_t samples = mpg123_length (decoder);
-		int length = (samples > 0 && rate > 0) ? samples * 1000 / rate : 0;
-
-		if (length > 0)
-			tuple_set_int (tuple, FIELD_LENGTH, length);
-		if (size > 0 && length > 0)
-			tuple_set_int (tuple, FIELD_BITRATE, 8 * size / length);
-	}
-
-	mpg123_delete (decoder);
-
-	if (! stream && ! vfs_fseek (file, 0, SEEK_SET))
-		tag_tuple_read (tuple, file);
-
-	if (stream)
-		tag_update_stream_metadata (tuple, file);
-
-	return tuple;
-
-ERR:
-	fprintf (stderr, "mpg123 probe error for %s: %s\n", filename, mpg123_plain_strerror (result));
-	mpg123_delete (decoder);
-	return NULL;
-}
-
-typedef struct {
-	VFSFile *fd;
-	mpg123_handle *decoder;
-	long rate;
-	int channels;
-	int encoding;
-	bool_t stream;
-	Tuple *tu;
-} MPG123PlaybackContext;
-
-static void print_mpg123_error (const char * filename, mpg123_handle * decoder)
-{
-	fprintf (stderr, "mpg123 error in %s: %s\n", filename, mpg123_strerror (decoder));
-}
-
-static bool_t mpg123_playback_worker (const char * filename, VFSFile * file)
-{
-	bool_t error = FALSE;
-	MPG123PlaybackContext ctx;
-	int ret;
-	int bitrate = 0, bitrate_sum = 0, bitrate_count = 0;
-	int bitrate_updated = -1000; /* >= a second away from any position */
-	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);
-	ctx.fd = file;
-
-	AUDDBG ("Checking for streaming ...\n");
-	ctx.stream = vfs_is_streaming (file);
-	ctx.tu = ctx.stream ? aud_input_get_tuple () : NULL;
-
-	ctx.decoder = mpg123_new (NULL, NULL);
-	mpg123_param (ctx.decoder, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0);
-
-	if (ctx.stream)
-		mpg123_replace_reader_handle (ctx.decoder, replace_read, replace_lseek_dummy, NULL);
-	else
-		mpg123_replace_reader_handle (ctx.decoder, replace_read, replace_lseek, NULL);
-
-	set_format (ctx.decoder);
-
-	if (mpg123_open_handle (ctx.decoder, file) < 0)
-	{
-OPEN_ERROR:
-		print_mpg123_error (filename, ctx.decoder);
-		error = TRUE;
-		goto cleanup;
-	}
-
-	float outbuf[8192];
-	size_t outbuf_size = 0;
-
-#ifdef FULL_SCAN
-	if (mpg123_scan (ctx.decoder) < 0)
-		goto OPEN_ERROR;
-#endif
-
-GET_FORMAT:
-	if (mpg123_getformat (ctx.decoder, & ctx.rate, & ctx.channels,
-	 & ctx.encoding) < 0)
-		goto OPEN_ERROR;
-
-	while ((ret = mpg123_read (ctx.decoder, (void *) outbuf, sizeof outbuf,
-	 & outbuf_size)) < 0)
-	{
-		if (ret == MPG123_NEW_FORMAT)
-			goto GET_FORMAT;
-		goto OPEN_ERROR;
-	}
-
-	if (mpg123_info (ctx.decoder, & fi) < 0)
-		goto OPEN_ERROR;
-
-	bitrate = fi.bitrate * 1000;
-	aud_input_set_bitrate (bitrate);
-
-	if (! aud_input_open_audio (FMT_FLOAT, ctx.rate, ctx.channels))
-	{
-		error = TRUE;
-		goto cleanup;
-	}
-
-	while (! aud_input_check_stop ())
-	{
-		int seek = aud_input_check_seek ();
-
-		if (seek >= 0)
-		{
-			if (mpg123_seek (ctx.decoder, (int64_t) seek * ctx.rate / 1000, SEEK_SET) < 0)
-				print_mpg123_error (filename, ctx.decoder);
-
-			outbuf_size = 0;
-		}
-
-		mpg123_info(ctx.decoder, &fi);
-		bitrate_sum += fi.bitrate;
-		bitrate_count ++;
-
-		if (bitrate_sum / bitrate_count != bitrate && abs
-		 (aud_input_written_time () - bitrate_updated) >= 1000)
-		{
-			aud_input_set_bitrate (bitrate_sum / bitrate_count * 1000);
-			bitrate = bitrate_sum / bitrate_count;
-			bitrate_sum = 0;
-			bitrate_count = 0;
-			bitrate_updated = aud_input_written_time ();
-		}
-
-		if (ctx.tu && tag_update_stream_metadata (ctx.tu, file))
-		{
-			tuple_ref (ctx.tu);
-			aud_input_set_tuple (ctx.tu);
-		}
-
-		if (! outbuf_size && (ret = mpg123_read (ctx.decoder, (void *) outbuf,
-		 sizeof outbuf, & outbuf_size)) < 0)
-		{
-			if (ret == MPG123_DONE || ret == MPG123_ERR_READER)
-				break;
-
-			print_mpg123_error (filename, ctx.decoder);
-
-			if (++ error_count >= 10)
-			{
-				error = TRUE;
-				break;
-			}
-		}
-		else
-		{
-			error_count = 0;
-
-			aud_input_write_audio (outbuf, outbuf_size);
-			outbuf_size = 0;
-		}
-	}
-
-cleanup:
-	mpg123_delete(ctx.decoder);
-	if (ctx.tu)
-		tuple_unref (ctx.tu);
-	return ! error;
-}
-
-static bool_t mpg123_write_tag (const char * filename, VFSFile * handle, const Tuple * tuple)
-{
-	if (! handle)
-		return FALSE;
-
-	return tag_tuple_write (tuple, handle, TAG_TYPE_ID3V2);
-}
-
-static bool_t mpg123_get_image (const char * filename, VFSFile * handle,
- void * * data, int64_t * length)
-{
-	if (! handle || vfs_is_streaming (handle))
-		return FALSE;
-
-	return tag_image_read (handle, data, length);
-}
-
-/** plugin description header **/
-static const char *mpg123_fmts[] = { "mp3", "mp2", "mp1", "bmu", NULL };
-
-AUD_INPUT_PLUGIN
-(
-	.name = N_("MPG123 Plugin"),
-	.domain = PACKAGE,
-	.init = aud_mpg123_init,
-	.cleanup = aud_mpg123_deinit,
-	.extensions = mpg123_fmts,
-	.is_our_file_from_vfs = mpg123_probe_for_fd,
-	.probe_for_tuple = mpg123_probe_for_tuple,
-	.play = mpg123_playback_worker,
-	.update_song_tuple = mpg123_write_tag,
-	.get_song_image = mpg123_get_image,
-)
diff --git a/src/mpg123/mpg123.cc b/src/mpg123/mpg123.cc
new file mode 100644
index 000000000000..4807aec150c7
--- /dev/null
+++ b/src/mpg123/mpg123.cc
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>.
+ * Copyright (c) 2010-2011 John Lindgren <john.lindgren at tds.net>.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#undef EXPORT
+#include <mpg123.h>
+
+// mpg123.h redefines EXPORT
+#undef EXPORT
+#include "config.h"
+
+#ifdef DEBUG_MPG123_IO
+# define MPG123_IODBG(...)  AUDDBG(__VA_ARGS__)
+#else
+# define MPG123_IODBG(...)  do { } while (0)
+#endif
+
+#define WANT_VFS_STDIO_COMPAT
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <audacious/audtag.h>
+
+class MPG123Plugin : public InputPlugin
+{
+public:
+    static const char * const exts[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("MPG123 Plugin"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagWritesTag)
+        .with_exts (exts);
+
+    constexpr MPG123Plugin() : InputPlugin (info, iinfo) {}
+
+    bool init ();
+    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 write_tuple (const char * filename, VFSFile & file, const Tuple & tuple);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT MPG123Plugin aud_plugin_instance;
+
+const char * const MPG123Plugin::defaults[] = {
+    "full_scan", "FALSE",
+    nullptr
+};
+
+const PreferencesWidget MPG123Plugin::widgets[] = {
+    WidgetLabel (N_("<b>Advanced</b>")),
+    WidgetCheck (N_("Use accurate length calculation (slow)"),
+        WidgetBool ("mpg123", "full_scan"))
+};
+
+const PluginPreferences MPG123Plugin::prefs = {{widgets}};
+
+#define DECODE_OPTIONS (MPG123_QUIET | MPG123_GAPLESS | MPG123_SEEKBUFFER | MPG123_FUZZY)
+
+static ssize_t replace_read (void * file, void * buffer, size_t length)
+{
+    return ((VFSFile *) file)->fread (buffer, 1, length);
+}
+
+static off_t replace_lseek (void * file, off_t to, int whence)
+{
+    if (((VFSFile *) file)->fseek (to, to_vfs_seek_type (whence)) < 0)
+        return -1;
+
+    return ((VFSFile *) file)->ftell ();
+}
+
+static off_t replace_lseek_dummy (void * file, off_t to, int whence)
+{
+    return -1;
+}
+
+bool MPG123Plugin::init ()
+{
+    aud_config_set_defaults ("mpg123", defaults);
+
+    AUDDBG("initializing mpg123 library\n");
+    mpg123_init();
+
+    return true;
+}
+
+void MPG123Plugin::cleanup ()
+{
+    AUDDBG("deinitializing mpg123 library\n");
+    mpg123_exit();
+}
+
+static void set_format (mpg123_handle * dec)
+{
+    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;
+
+    bool is_streaming = (file.fsize () < 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 (! is_streaming)
+    {
+        char id3buf[3];
+        if (file.fread (id3buf, 1, 3) != 3)
+            return false;
+
+        if (! memcmp (id3buf, "ID3", 3))
+            return true;
+
+        if (file.fseek (0, VFS_SEEK_SET) < 0)
+            return false;
+    }
+
+    mpg123_handle * dec = mpg123_new (nullptr, nullptr);
+    mpg123_param (dec, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0);
+
+    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);
+
+    set_format (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;
+    }
+
+    if (! is_streaming && aud_get_bool ("mpg123", "full_scan") && mpg123_scan (dec) < 0)
+        goto ERR;
+
+RETRY:;
+    long rate;
+    int chan, enc;
+    if ((res = mpg123_getformat (dec, & rate, & chan, & enc)) < 0)
+        goto ERR;
+
+    struct mpg123_frameinfo info;
+    if ((res = mpg123_info (dec, & info)) < 0)
+        goto ERR;
+
+    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;
+    }
+
+    char str[32];
+    make_format_string (& info, str, sizeof str);
+    AUDDBG ("Accepted as %s: %s.\n", str, fname);
+
+    mpg123_delete (dec);
+    return true;
+}
+
+Tuple MPG123Plugin::read_tuple (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);
+
+    if (stream)
+        mpg123_replace_reader_handle (decoder, replace_read, replace_lseek_dummy, nullptr);
+    else
+        mpg123_replace_reader_handle (decoder, replace_read, replace_lseek, nullptr);
+
+    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 ();
+    }
+
+    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);
+
+    if (! stream)
+    {
+        int64_t size = file.fsize ();
+        int64_t samples = mpg123_length (decoder);
+        int length = (samples > 0 && rate > 0) ? samples * 1000 / 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);
+
+    if (! stream && ! file.fseek (0, VFS_SEEK_SET))
+        audtag::tuple_read (tuple, file);
+
+    if (stream)
+        tuple.fetch_stream_info (file);
+
+    return tuple;
+}
+
+typedef struct {
+    mpg123_handle *decoder;
+    long rate;
+    int channels;
+    int encoding;
+    bool stream;
+    Tuple tu;
+} MPG123PlaybackContext;
+
+static void print_mpg123_error (const char * filename, mpg123_handle * decoder)
+{
+    AUDERR ("mpg123 error in %s: %s\n", filename, mpg123_strerror (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;
+
+    if (mpg123_open_handle (ctx.decoder, & file) < 0)
+    {
+OPEN_ERROR:
+        print_mpg123_error (filename, ctx.decoder);
+        error = true;
+        goto cleanup;
+    }
+
+    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;
+    }
+
+    if (mpg123_info (ctx.decoder, & fi) < 0)
+        goto OPEN_ERROR;
+
+    bitrate = fi.bitrate * 1000;
+    set_stream_bitrate (bitrate);
+
+    if (ctx.tu && ctx.tu.fetch_stream_info (file))
+        set_playback_tuple (ctx.tu.ref ());
+
+    open_audio (FMT_FLOAT, ctx.rate, ctx.channels);
+
+    while (! check_stop ())
+    {
+        int seek = check_seek ();
+
+        if (seek >= 0)
+        {
+            if (mpg123_seek (ctx.decoder, (int64_t) seek * ctx.rate / 1000, SEEK_SET) < 0)
+                print_mpg123_error (filename, ctx.decoder);
+
+            outbuf_size = 0;
+        }
+
+        mpg123_info(ctx.decoder, &fi);
+        bitrate_sum += fi.bitrate;
+        bitrate_count ++;
+
+        if (bitrate_sum / bitrate_count != bitrate && bitrate_count >= 16)
+        {
+            set_stream_bitrate (bitrate_sum / bitrate_count * 1000);
+            bitrate = bitrate_sum / bitrate_count;
+            bitrate_sum = 0;
+            bitrate_count = 0;
+        }
+
+        if (ctx.tu && ctx.tu.fetch_stream_info (file))
+            set_playback_tuple (ctx.tu.ref ());
+
+        if (! outbuf_size && (ret = mpg123_read (ctx.decoder,
+         (unsigned char *) outbuf, sizeof outbuf, & outbuf_size)) < 0)
+        {
+            if (ret == MPG123_DONE || ret == MPG123_ERR_READER)
+                break;
+
+            print_mpg123_error (filename, ctx.decoder);
+
+            if (++ error_count >= 10)
+            {
+                error = true;
+                break;
+            }
+        }
+        else
+        {
+            error_count = 0;
+
+            write_audio (outbuf, outbuf_size);
+            outbuf_size = 0;
+        }
+    }
+
+cleanup:
+    mpg123_delete(ctx.decoder);
+    return ! error;
+}
+
+bool MPG123Plugin::write_tuple (const char * filename, VFSFile & file, const Tuple & tuple)
+{
+    if (file.fsize () < 0)  // stream?
+        return false;
+
+    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/Makefile b/src/mpris2/Makefile
index 3ec652ff28c7..4b09753bdf9c 100644
--- a/src/mpris2/Makefile
+++ b/src/mpris2/Makefile
@@ -1,6 +1,6 @@
 PLUGIN = mpris2${PLUGIN_SUFFIX}
 
-SRCS = object-core.c object-player.c plugin.c
+SRCS = object-core.c object-player.c plugin.cc
 CLEAN = object-core.c object-core.h object-player.c object-player.h
 
 include ../../buildsys.mk
@@ -8,6 +8,8 @@ include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${GLIB_CFLAGS} ${GIO_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
 LIBS += -lm ${GLIB_LIBS} ${GIO_LIBS}
diff --git a/src/mpris2/plugin.c b/src/mpris2/plugin.c
deleted file mode 100644
index c237874b883f..000000000000
--- a/src/mpris2/plugin.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * MPRIS 2 Server for Audacious
- * Copyright 2011-2012 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 <math.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/hook.h>
-
-#include "object-core.h"
-#include "object-player.h"
-
-static GObject * object_core, * object_player;
-static char * last_title, * last_artist, * last_album, * last_file;
-static int last_length;
-static const char * image_file;
-static bool_t recheck_image;
-static int update_timer;
-
-static bool_t quit_cb (MprisMediaPlayer2 * object, GDBusMethodInvocation * call,
- void * unused)
-{
-    aud_drct_quit ();
-    mpris_media_player2_complete_quit (object, call);
-    return TRUE;
-}
-
-static bool_t raise_cb (MprisMediaPlayer2 * object, GDBusMethodInvocation *
- call, void * unused)
-{
-    aud_interface_show (TRUE);
-    mpris_media_player2_complete_raise (object, call);
-    return TRUE;
-}
-
-static void update_metadata (void * data, GObject * object)
-{
-    char * title = NULL, * artist = NULL, * album = NULL, * file = NULL;
-    int length = 0;
-
-    int playlist = aud_playlist_get_playing ();
-    int entry = (playlist >= 0) ? aud_playlist_get_position (playlist) : -1;
-
-    if (entry >= 0)
-    {
-        aud_playlist_entry_describe (playlist, entry, & title, & artist, & album, TRUE);
-        file = aud_playlist_entry_get_filename (playlist, entry);
-        length = aud_playlist_entry_get_length (playlist, entry, TRUE);
-    }
-
-    if (str_equal (title, last_title) && str_equal (artist, last_artist) &&
-     str_equal (album, last_album) && str_equal (file, last_file) && length ==
-     last_length && ! recheck_image)
-    {
-        str_unref (title);
-        str_unref (artist);
-        str_unref (album);
-        str_unref (file);
-        return;
-    }
-
-    if (! str_equal (file, last_file) || recheck_image)
-    {
-        if (image_file)
-            aud_art_unref (last_file);
-        image_file = file ? aud_art_request_file (file) : NULL;
-        recheck_image = FALSE;
-    }
-
-    str_unref (last_title);
-    str_unref (last_artist);
-    str_unref (last_album);
-    str_unref (last_file);
-    last_title = title;
-    last_artist = artist;
-    last_album = album;
-    last_file = file;
-    last_length = length;
-
-    GVariant * elems[7];
-    int nelems = 0;
-
-    if (title)
-    {
-        GVariant * key = g_variant_new_string ("xesam:title");
-        GVariant * str = g_variant_new_string (title);
-        GVariant * var = g_variant_new_variant (str);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    if (artist)
-    {
-        GVariant * key = g_variant_new_string ("xesam:artist");
-        GVariant * str = g_variant_new_string (artist);
-        GVariant * array = g_variant_new_array (G_VARIANT_TYPE_STRING, & str, 1);
-        GVariant * var = g_variant_new_variant (array);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    if (album)
-    {
-        GVariant * key = g_variant_new_string ("xesam:album");
-        GVariant * str = g_variant_new_string (album);
-        GVariant * var = g_variant_new_variant (str);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    if (file)
-    {
-        GVariant * key = g_variant_new_string ("xesam:url");
-        GVariant * str = g_variant_new_string (file);
-        GVariant * var = g_variant_new_variant (str);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    if (length > 0)
-    {
-        GVariant * key = g_variant_new_string ("mpris:length");
-        GVariant * val = g_variant_new_int64 ((int64_t) length * 1000);
-        GVariant * var = g_variant_new_variant (val);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    if (image_file)
-    {
-        GVariant * key = g_variant_new_string ("mpris:artUrl");
-        GVariant * str = g_variant_new_string (image_file);
-        GVariant * var = g_variant_new_variant (str);
-        elems[nelems ++] = g_variant_new_dict_entry (key, var);
-    }
-
-    GVariant * key = g_variant_new_string ("mpris:trackid");
-    GVariant * str = g_variant_new_string ("/org/mpris/MediaPlayer2/CurrentTrack");
-    GVariant * var = g_variant_new_variant (str);
-    elems[nelems ++] = g_variant_new_dict_entry (key, var);
-
-    GVariant * array = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), elems, nelems);
-    g_object_set (object, "metadata", array, NULL);
-}
-
-static void update_image (void * data, GObject * object)
-{
-    recheck_image = TRUE;
-    update_metadata (data, object);
-}
-
-static void volume_changed (GObject * object)
-{
-    double vol;
-    g_object_get (object, "volume", & vol, NULL);
-    aud_drct_set_volume_main (round (vol * 100));
-}
-
-static bool_t update (GObject * object)
-{
-    int64_t pos = 0;
-    int vol = 0;
-
-    if (aud_drct_get_playing () && aud_drct_get_ready ())
-        pos = (int64_t) aud_drct_get_time () * 1000;
-
-    aud_drct_get_volume_main (& vol);
-
-    g_signal_handlers_block_by_func (object, (void *) volume_changed, NULL);
-    g_object_set (object, "position", pos, "volume", (double) vol / 100, NULL);
-    g_signal_handlers_unblock_by_func (object, (void *) volume_changed, NULL);
-    return TRUE;
-}
-
-static void update_playback_status (void * data, GObject * object)
-{
-    const char * status;
-
-    if (aud_drct_get_playing ())
-        status = aud_drct_get_paused () ? "Paused" : "Playing";
-    else
-        status = "Stopped";
-
-    g_object_set (object, "playback-status", status, NULL);
-    update (object);
-}
-
-static void emit_seek (void * data, GObject * object)
-{
-    g_signal_emit_by_name (object, "seeked", (int64_t) aud_drct_get_time () * 1000);
-}
-
-static bool_t next_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
- call, void * unused)
-{
-    aud_drct_pl_next ();
-    mpris_media_player2_player_complete_next (object, call);
-    return TRUE;
-}
-
-static bool_t pause_cb (MprisMediaPlayer2Player * object,
- GDBusMethodInvocation * call, void * unused)
-{
-    if (aud_drct_get_playing () && ! aud_drct_get_paused ())
-        aud_drct_pause ();
-
-    mpris_media_player2_player_complete_pause (object, call);
-    return TRUE;
-}
-
-static bool_t play_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
- call, void * unused)
-{
-    aud_drct_play ();
-    mpris_media_player2_player_complete_play (object, call);
-    return TRUE;
-}
-
-static bool_t play_pause_cb (MprisMediaPlayer2Player * object,
- GDBusMethodInvocation * call, void * unused)
-{
-    aud_drct_play_pause ();
-    mpris_media_player2_player_complete_play_pause (object, call);
-    return TRUE;
-}
-
-static bool_t previous_cb (MprisMediaPlayer2Player * object,
- GDBusMethodInvocation * call, void * unused)
-{
-    aud_drct_pl_prev ();
-    mpris_media_player2_player_complete_previous (object, call);
-    return TRUE;
-}
-
-static bool_t seek_cb (MprisMediaPlayer2Player * object,
- GDBusMethodInvocation * call, int64_t offset, void * unused)
-{
-    aud_drct_seek (aud_drct_get_time () + offset / 1000);
-    mpris_media_player2_player_complete_seek (object, call);
-    return TRUE;
-}
-
-static bool_t set_position_cb (MprisMediaPlayer2Player * object,
- GDBusMethodInvocation * call, const char * track, int64_t pos, void * unused)
-{
-    if (aud_drct_get_playing ())
-        aud_drct_seek (pos / 1000);
-
-    mpris_media_player2_player_complete_set_position (object, call);
-    return TRUE;
-}
-
-static bool_t stop_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
- call, void * unused)
-{
-    if (aud_drct_get_playing ())
-        aud_drct_stop ();
-
-    mpris_media_player2_player_complete_stop (object, call);
-    return TRUE;
-}
-
-void mpris2_cleanup (void)
-{
-    hook_dissociate ("playback begin", (HookFunction) update_playback_status);
-    hook_dissociate ("playback pause", (HookFunction) update_playback_status);
-    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) emit_seek);
-    hook_dissociate ("playback seek", (HookFunction) emit_seek);
-
-    if (update_timer)
-    {
-        g_source_remove (update_timer);
-        update_timer = 0;
-    }
-
-    g_object_unref (object_core);
-    g_object_unref (object_player);
-
-    if (image_file)
-    {
-        aud_art_unref (last_file);
-        image_file = NULL;
-    }
-
-    str_unref (last_title);
-    str_unref (last_artist);
-    str_unref (last_album);
-    str_unref (last_file);
-    last_title = last_artist = last_album = last_file = NULL;
-    last_length = 0;
-}
-
-bool_t mpris2_init (void)
-{
-    GError * error = NULL;
-    GDBusConnection * bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, & error);
-
-    if (! bus)
-    {
-        fprintf (stderr, "mpris2: %s\n", error->message);
-        g_error_free (error);
-        return FALSE;
-    }
-
-    g_bus_own_name_on_connection (bus, "org.mpris.MediaPlayer2.audacious", 0,
-     NULL, NULL, NULL, NULL);
-
-    object_core = (GObject *) mpris_media_player2_skeleton_new ();
-
-    g_object_set (object_core,
-     "can-quit", TRUE,
-     "can-raise", TRUE,
-     "desktop-entry", "audacious",
-     "identity", "Audacious",
-     NULL);
-
-    g_signal_connect (object_core, "handle-quit", (GCallback) quit_cb, NULL);
-    g_signal_connect (object_core, "handle-raise", (GCallback) raise_cb, NULL);
-
-    object_player = (GObject *) mpris_media_player2_player_skeleton_new ();
-
-    g_object_set (object_player,
-     "can-control", TRUE,
-     "can-go-next", TRUE,
-     "can-go-previous", TRUE,
-     "can-pause", TRUE,
-     "can-play", TRUE,
-     "can-seek", TRUE,
-     NULL);
-
-    update_timer = g_timeout_add (250, (GSourceFunc) update, object_player);
-    update_playback_status (NULL, object_player);
-
-    if (aud_drct_get_playing () && aud_drct_get_ready ())
-        emit_seek (NULL, object_player);
-
-    hook_associate ("playback begin", (HookFunction) update_playback_status, object_player);
-    hook_associate ("playback pause", (HookFunction) update_playback_status, object_player);
-    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) emit_seek, object_player);
-    hook_associate ("playback seek", (HookFunction) emit_seek, object_player);
-
-    g_signal_connect (object_player, "handle-next", (GCallback) next_cb, NULL);
-    g_signal_connect (object_player, "handle-pause", (GCallback) pause_cb, NULL);
-    g_signal_connect (object_player, "handle-play", (GCallback) play_cb, NULL);
-    g_signal_connect (object_player, "handle-play-pause", (GCallback) play_pause_cb, NULL);
-    g_signal_connect (object_player, "handle-previous", (GCallback) previous_cb, NULL);
-    g_signal_connect (object_player, "handle-seek", (GCallback) seek_cb, NULL);
-    g_signal_connect (object_player, "handle-set-position", (GCallback) set_position_cb, NULL);
-    g_signal_connect (object_player, "handle-stop", (GCallback) stop_cb, NULL);
-
-    g_signal_connect (object_player, "notify::volume", (GCallback) volume_changed, NULL);
-
-    if (! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
-     object_core, bus, "/org/mpris/MediaPlayer2", & error) ||
-     ! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
-     object_player, bus, "/org/mpris/MediaPlayer2", & error))
-    {
-        mpris2_cleanup ();
-        fprintf (stderr, "mpris2: %s\n", error->message);
-        g_error_free (error);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("MPRIS 2 Server"),
-    .domain = PACKAGE,
-    .enabled_by_default = TRUE,
-    .init = mpris2_init,
-    .cleanup = mpris2_cleanup
-)
diff --git a/src/mpris2/plugin.cc b/src/mpris2/plugin.cc
new file mode 100644
index 000000000000..95f592b66c45
--- /dev/null
+++ b/src/mpris2/plugin.cc
@@ -0,0 +1,413 @@
+/*
+ * MPRIS 2 Server for Audacious
+ * Copyright 2011-2012 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 <math.h>
+#include <stdint.h>
+
+#include <libaudcore/drct.h>
+#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>
+
+#include "object-core.h"
+#include "object-player.h"
+
+class MPRIS2Plugin : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("MPRIS 2 Server"),
+        PACKAGE
+    };
+
+    constexpr MPRIS2Plugin () : GeneralPlugin (info, true) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT MPRIS2Plugin aud_plugin_instance;
+
+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)
+{
+    aud_quit ();
+    mpris_media_player2_complete_quit (object, call);
+    return true;
+}
+
+static gboolean raise_cb (MprisMediaPlayer2 * object, GDBusMethodInvocation *
+ call, void * unused)
+{
+    aud_ui_show (true);
+    mpris_media_player2_complete_raise (object, call);
+    return true;
+}
+
+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)
+    {
+        Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess);
+
+        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);
+    }
+
+    if (title == last_title && artist == last_artist && album == last_album
+     && file == last_file && length == last_length && ! recheck_image)
+        return;
+
+    if (file != last_file || recheck_image)
+    {
+        if (image_file)
+            aud_art_unref (last_file);
+        image_file = file ? aud_art_request_file (file) : nullptr;
+        recheck_image = false;
+    }
+
+    last_title = title;
+    last_artist = artist;
+    last_album = album;
+    last_file = file;
+    last_length = length;
+
+    GVariant * elems[7];
+    int nelems = 0;
+
+    if (title)
+    {
+        GVariant * key = g_variant_new_string ("xesam:title");
+        GVariant * str = g_variant_new_string (title);
+        GVariant * var = g_variant_new_variant (str);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    if (artist)
+    {
+        GVariant * key = g_variant_new_string ("xesam:artist");
+        GVariant * str = g_variant_new_string (artist);
+        GVariant * array = g_variant_new_array (G_VARIANT_TYPE_STRING, & str, 1);
+        GVariant * var = g_variant_new_variant (array);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    if (album)
+    {
+        GVariant * key = g_variant_new_string ("xesam:album");
+        GVariant * str = g_variant_new_string (album);
+        GVariant * var = g_variant_new_variant (str);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    if (file)
+    {
+        GVariant * key = g_variant_new_string ("xesam:url");
+        GVariant * str = g_variant_new_string (file);
+        GVariant * var = g_variant_new_variant (str);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    if (length > 0)
+    {
+        GVariant * key = g_variant_new_string ("mpris:length");
+        GVariant * val = g_variant_new_int64 ((int64_t) length * 1000);
+        GVariant * var = g_variant_new_variant (val);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    if (image_file)
+    {
+        GVariant * key = g_variant_new_string ("mpris:artUrl");
+        GVariant * str = g_variant_new_string (image_file);
+        GVariant * var = g_variant_new_variant (str);
+        elems[nelems ++] = g_variant_new_dict_entry (key, var);
+    }
+
+    GVariant * key = g_variant_new_string ("mpris:trackid");
+    GVariant * str = g_variant_new_string ("/org/mpris/MediaPlayer2/CurrentTrack");
+    GVariant * var = g_variant_new_variant (str);
+    elems[nelems ++] = g_variant_new_dict_entry (key, var);
+
+    GVariant * array = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), elems, nelems);
+    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;
+    g_object_get (object, "volume", & vol, nullptr);
+    aud_drct_set_volume_main (round (vol * 100));
+}
+
+static gboolean update (GObject * object)
+{
+    int64_t pos = 0;
+    int vol = 0;
+
+    if (aud_drct_get_playing () && aud_drct_get_ready ())
+        pos = (int64_t) aud_drct_get_time () * 1000;
+
+    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_signal_handlers_unblock_by_func (object, (void *) volume_changed, nullptr);
+    return true;
+}
+
+static void update_playback_status (void * data, GObject * object)
+{
+    const char * status;
+
+    if (aud_drct_get_playing ())
+        status = aud_drct_get_paused () ? "Paused" : "Playing";
+    else
+        status = "Stopped";
+
+    g_object_set (object, "playback-status", status, nullptr);
+    update (object);
+}
+
+static void emit_seek (void * data, GObject * object)
+{
+    g_signal_emit_by_name (object, "seeked", (int64_t) aud_drct_get_time () * 1000);
+}
+
+static gboolean next_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
+ call, void * unused)
+{
+    aud_drct_pl_next ();
+    mpris_media_player2_player_complete_next (object, call);
+    return true;
+}
+
+static gboolean pause_cb (MprisMediaPlayer2Player * object,
+ GDBusMethodInvocation * call, void * unused)
+{
+    if (aud_drct_get_playing () && ! aud_drct_get_paused ())
+        aud_drct_pause ();
+
+    mpris_media_player2_player_complete_pause (object, call);
+    return true;
+}
+
+static gboolean play_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
+ call, void * unused)
+{
+    aud_drct_play ();
+    mpris_media_player2_player_complete_play (object, call);
+    return true;
+}
+
+static gboolean play_pause_cb (MprisMediaPlayer2Player * object,
+ GDBusMethodInvocation * call, void * unused)
+{
+    aud_drct_play_pause ();
+    mpris_media_player2_player_complete_play_pause (object, call);
+    return true;
+}
+
+static gboolean previous_cb (MprisMediaPlayer2Player * object,
+ GDBusMethodInvocation * call, void * unused)
+{
+    aud_drct_pl_prev ();
+    mpris_media_player2_player_complete_previous (object, call);
+    return true;
+}
+
+static gboolean seek_cb (MprisMediaPlayer2Player * object,
+ GDBusMethodInvocation * call, int64_t offset, void * unused)
+{
+    aud_drct_seek (aud_drct_get_time () + offset / 1000);
+    mpris_media_player2_player_complete_seek (object, call);
+    return true;
+}
+
+static gboolean set_position_cb (MprisMediaPlayer2Player * object,
+ GDBusMethodInvocation * call, const char * track, int64_t pos, void * unused)
+{
+    if (aud_drct_get_playing ())
+        aud_drct_seek (pos / 1000);
+
+    mpris_media_player2_player_complete_set_position (object, call);
+    return true;
+}
+
+static gboolean stop_cb (MprisMediaPlayer2Player * object, GDBusMethodInvocation *
+ call, void * unused)
+{
+    if (aud_drct_get_playing ())
+        aud_drct_stop ();
+
+    mpris_media_player2_player_complete_stop (object, call);
+    return true;
+}
+
+void MPRIS2Plugin::cleanup ()
+{
+    hook_dissociate ("playback begin", (HookFunction) update_playback_status);
+    hook_dissociate ("playback pause", (HookFunction) update_playback_status);
+    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) emit_seek);
+    hook_dissociate ("playback seek", (HookFunction) emit_seek);
+
+    if (update_timer)
+    {
+        g_source_remove (update_timer);
+        update_timer = 0;
+    }
+
+    g_object_unref (object_core);
+    g_object_unref (object_player);
+
+    if (image_file)
+    {
+        aud_art_unref (last_file);
+        image_file = nullptr;
+    }
+
+    last_title = String ();
+    last_artist = String ();
+    last_album = String ();
+    last_file = String ();
+    last_length = 0;
+}
+
+bool MPRIS2Plugin::init ()
+{
+#if ! GLIB_CHECK_VERSION (2, 36, 0)
+    g_type_init ();
+#endif
+
+    GError * error = nullptr;
+    GDBusConnection * bus = g_bus_get_sync (G_BUS_TYPE_SESSION, nullptr, & error);
+
+    if (! bus)
+    {
+        AUDERR ("%s\n", error->message);
+        g_error_free (error);
+        return false;
+    }
+
+    g_bus_own_name_on_connection (bus, "org.mpris.MediaPlayer2.audacious",
+     (GBusNameOwnerFlags) 0, nullptr, nullptr, nullptr, nullptr);
+
+    object_core = (GObject *) mpris_media_player2_skeleton_new ();
+
+    g_object_set (object_core,
+     "can-quit", (gboolean) true,
+     "can-raise", (gboolean) true,
+     "desktop-entry", "audacious",
+     "identity", "Audacious",
+     nullptr);
+
+    g_signal_connect (object_core, "handle-quit", (GCallback) quit_cb, nullptr);
+    g_signal_connect (object_core, "handle-raise", (GCallback) raise_cb, nullptr);
+
+    object_player = (GObject *) mpris_media_player2_player_skeleton_new ();
+
+    g_object_set (object_player,
+     "can-control", (gboolean) true,
+     "can-go-next", (gboolean) true,
+     "can-go-previous", (gboolean) true,
+     "can-pause", (gboolean) true,
+     "can-play", (gboolean) true,
+     "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 ())
+        emit_seek (nullptr, object_player);
+
+    hook_associate ("playback begin", (HookFunction) update_playback_status, object_player);
+    hook_associate ("playback pause", (HookFunction) update_playback_status, object_player);
+    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) emit_seek, object_player);
+    hook_associate ("playback seek", (HookFunction) emit_seek, 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);
+    g_signal_connect (object_player, "handle-play-pause", (GCallback) play_pause_cb, nullptr);
+    g_signal_connect (object_player, "handle-previous", (GCallback) previous_cb, nullptr);
+    g_signal_connect (object_player, "handle-seek", (GCallback) seek_cb, nullptr);
+    g_signal_connect (object_player, "handle-set-position", (GCallback) set_position_cb, nullptr);
+    g_signal_connect (object_player, "handle-stop", (GCallback) stop_cb, nullptr);
+
+    g_signal_connect (object_player, "notify::volume", (GCallback) volume_changed, nullptr);
+
+    if (! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
+     object_core, bus, "/org/mpris/MediaPlayer2", & error) ||
+     ! g_dbus_interface_skeleton_export ((GDBusInterfaceSkeleton *)
+     object_player, bus, "/org/mpris/MediaPlayer2", & error))
+    {
+        cleanup ();
+        AUDERR ("%s\n", error->message);
+        g_error_free (error);
+        return false;
+    }
+
+    return true;
+}
diff --git a/src/neon/Makefile b/src/neon/Makefile
index e4cdb421d485..d8ae392943f3 100644
--- a/src/neon/Makefile
+++ b/src/neon/Makefile
@@ -1,14 +1,15 @@
 PLUGIN = neon${PLUGIN_SUFFIX}
 
-SRCS = neon.c	\
-       rb.c	\
-       cert_verification.c
+SRCS = neon.cc	\
+       cert_verification.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${TRANSPORT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} ${NEON_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${NEON_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${NEON_CFLAGS} -I../..
+LIBS += ${GLIB_LIBS} ${NEON_LIBS}
diff --git a/src/neon/cert_verification.c b/src/neon/cert_verification.c
deleted file mode 100644
index 61f9ec525073..000000000000
--- a/src/neon/cert_verification.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- *  Wget like SSL certificate validation from environmental variables.
- *  Copyright (C) 2009 Jussi Judin
- *
- *  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.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <ne_ssl.h>
-#include <ne_session.h>
-
-#include <libaudcore/core.h>
-
-#include "cert_verification.h"
-
-// Certificate validation handling.
-
-const int LENGTH_SHORTFORM_MAX = 127;
-const int LENGTH_INDEFINITE_VALUE = 128;
-const int LENGTH_LONGFORM_MASK = 0x7f;
-const int OCTET_BITS = 8;
-const int ASNTYPE_CODE_MASK = 0x1f;
-const int HASH_BYTES = 4;
-const uint32_t MAX_CERT_CHECKS = UINT32_MAX;
-
-enum AsnType
-{
-    ASNTYPE_INTEGER = 2,
-    ASNTYPE_SEQUENCE = 16,
-    ASNTYPE_VARLEN_IDENTIFIER = 31
-};
-
-struct DerData
-{
-    unsigned char * start;
-    unsigned char * end;
-    unsigned char * nextStart;
-    unsigned char * bufferEnd;
-    enum AsnType type;
-};
-
-/**
- * X.509 certificate has following structure defined in RFC5280:
- *
- * Certificate  ::= SEQUENCE  {
- *      tbsCertificate       TBSCertificate,
- *      signatureAlgorithm   AlgorithmIdentifier,
- *      signatureValue       BIT STRING  }
- *
- * TBSCertificate  ::=  SEQUENCE  {
- *      version         [0]  EXPLICIT Version DEFAULT v1,
- *      serialNumber         CertificateSerialNumber,
- *      signature            AlgorithmIdentifier,
- *      issuer               Name,
- *      validity             Validity,
- *      subject              Name,
- * ...
- *
- * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
- * CertificateSerialNumber  ::=  INTEGER
- * AlgorithmIdentifier  ::=  SEQUENCE  {
- *      algorithm               OBJECT IDENTIFIER,
- *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
- * Validity ::= SEQUENCE {
- *      notBefore      Time,
- *      notAfter       Time }
- * Time ::= CHOICE {
- *      utcTime        UTCTime,
- *      generalTime    GeneralizedTime }
- * Name ::= CHOICE { -- only one possibility for now --
- *   rdnSequence  RDNSequence }
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * And we are only interested in subject field.
- */
-
-/**
- * Returns the tag number of DER data.
- */
-static bool_t der_read_tag_number (unsigned char * in_buffer,
- const unsigned char * in_bufferEnd, unsigned char * * out_lengthStart,
- enum AsnType * out_type)
-{
-    if (in_bufferEnd - in_buffer < 2)
-        return FALSE;
-
-    unsigned char typeOctet = in_buffer[0];
-    enum AsnType typeCode = typeOctet & ASNTYPE_CODE_MASK;
-    int typeCodeLength = 1;
-
-    // Variable length types are not supported.
-    if (typeCode == ASNTYPE_VARLEN_IDENTIFIER)
-        return FALSE;
-
-    * out_type = typeCode;
-    * out_lengthStart = in_buffer + typeCodeLength;
-
-    return TRUE;
-}
-
-/**
- * Returns pointers that point to the content of DER data value when identifier
- * is not present.
- */
-static bool_t der_read_content_length (unsigned char * in_buffer,
- const unsigned char * in_bufferEnd, unsigned char * * out_start,
- unsigned char * * out_end, unsigned char * * out_nextStart)
-{
-    if (in_bufferEnd - in_buffer < 1)
-        return FALSE;
-
-    unsigned char lengthDescription = in_buffer[0];
-
-    if (lengthDescription <= LENGTH_SHORTFORM_MAX)
-    {
-        * out_start = in_buffer + 1;
-        * out_end = * out_start + lengthDescription;
-
-        if (in_bufferEnd < * out_end)
-            return FALSE;
-
-        * out_nextStart = * out_end;
-        return TRUE;
-    }
-
-    if (lengthDescription == LENGTH_INDEFINITE_VALUE)
-    {
-        * out_start = in_buffer + 1;
-        unsigned char * currentPos = in_buffer + 1;
-
-        while (currentPos < in_bufferEnd - 1)
-        {
-            if (! currentPos[0] && ! currentPos[1])
-            {
-                * out_end = currentPos;
-                * out_nextStart = * out_end + 1;
-                return TRUE;
-            }
-        }
-
-        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;
-
-    if (in_bufferEnd < in_buffer + 1 + lengthOctets)
-        return FALSE;
-
-    size_t contentLength = 0;
-    size_t i = 0;
-
-    for (i = 0; i < lengthOctets; i++)
-    {
-        contentLength <<= OCTET_BITS;
-        contentLength |= in_buffer[i + 1];
-    }
-
-    * out_start = in_buffer + 1 + lengthOctets;
-    * out_end = * out_start + contentLength;
-
-    if (in_bufferEnd < * out_end)
-        return FALSE;
-
-    * out_nextStart = * out_end;
-    return TRUE;
-}
-
-/**
- * Returns pointers that point to the content of DER data value.
- */
-static bool_t der_read_content (struct DerData * data, struct DerData * content)
-{
-    unsigned char * lengthStart = NULL;
-    bool_t typeOk = der_read_tag_number (data->start, data->bufferEnd,
-     & lengthStart, & content->type);
-
-    if (! typeOk)
-        return FALSE;
-
-    content->bufferEnd = data->bufferEnd;
-    return der_read_content_length (lengthStart, data->bufferEnd,
-     & content->start, & content->end, & content->nextStart);
-}
-
-/**
- * Returns pointers that point to next DER data value.
- */
-static bool_t der_read_next (struct DerData * currentContent, struct DerData * nextContent)
-{
-    nextContent->start = currentContent->nextStart;
-
-    unsigned char * lengthStart = NULL;
-    bool_t typeOk = der_read_tag_number (currentContent->start,
-     currentContent->bufferEnd, & lengthStart, & nextContent->type);
-
-    if (! typeOk)
-        return FALSE;
-
-    unsigned char * nextContentStart = NULL;
-    return der_read_content_length (lengthStart, currentContent->bufferEnd,
-     & nextContentStart, & nextContent->end, & nextContent->nextStart);
-}
-
-/**
- * Returns certificate hash that can be used to certificate links generated
- * by c_rehash command.
- *
- * Certificate hash is just 4 first octets of MD5 sum of certificate subject id
- * DER format.
- *
- * @return TRUE if given certificate could be parsed by this, FALSE otherwise.
- */
-static bool_t cert_get_hash (const ne_ssl_certificate * cert, uint32_t * out_hash)
-{
-    char * certPem = ne_ssl_cert_export (cert);
-    g_return_val_if_fail (certPem != NULL, 1);
-    size_t derLength = 0;
-    unsigned char * certDer = g_base64_decode (certPem, &derLength);
-    g_free (certPem);
-    g_return_val_if_fail (certDer != NULL, 1);
-
-    struct DerData data =
-    {
-        .start = certDer,
-        .bufferEnd = (certDer + derLength)
-    };
-    struct DerData content;
-
-    // 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);
-    // tbsCertificate
-    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);
-    // signature
-    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);
-    // validity
-    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);
-
-    // Calculate MD5 sum of subject.
-    unsigned char md5pword[16];
-    size_t md5len = 16;
-
-    GChecksum * state = g_checksum_new (G_CHECKSUM_MD5);
-    g_checksum_update (state, content.start, content.nextStart - content.start);
-    g_checksum_get_digest (state, md5pword, & md5len);
-    g_checksum_free (state);
-
-    uint32_t hash = 0;
-
-    // Hash is reverse of four first bytes of MD5 checksum of DER encoded
-    // subject ASN.1 field.
-    for (int i = HASH_BYTES - 1; i >= 0; i --)
-    {
-        hash <<= OCTET_BITS;
-        hash |= md5pword[i];
-    }
-
-    * out_hash = hash;
-
-    g_free (certDer);
-    return TRUE;
-}
-
-/**
- * Checks if given certificate is signed by given signer certificate.
- *
- * Goes up in certificate signer chain of certificate and compares if any one
- * of them is same as given signer.
- */
-static bool_t is_signer_of_cert (const ne_ssl_certificate * signer, const ne_ssl_certificate * cert)
-{
-    const ne_ssl_certificate * certSigner = cert;
-
-    while (certSigner != NULL)
-    {
-        if (ne_ssl_cert_cmp (signer, certSigner) == 0)
-            return TRUE;
-
-        certSigner = ne_ssl_cert_signedby (certSigner);
-    }
-
-    return FALSE;
-}
-
-/**
- * Checks if given file includes certificate that has signed given certificate.
- */
-static bool_t file_is_signer_of_cert (const char * filename, const ne_ssl_certificate * cert)
-{
-    ne_ssl_certificate * signer = ne_ssl_cert_read (filename);
-
-    if (signer != NULL)
-    {
-        bool_t signOk = is_signer_of_cert (signer, cert);
-        ne_ssl_cert_free (signer);
-
-        if (signOk)
-            return TRUE;
-    }
-
-    return FALSE;
-}
-
-/**
- * Checks if directory includes a file that can be signer of given certificate.
- */
-static bool_t validate_directory_certs (const char * directory,
- const ne_ssl_certificate * serverCert, uint32_t certHash)
-{
-    // Search certificate names in ascending order and assume that all names
-    // point to valid certificates.
-    uint32_t certId = 0;
-
-    while (certId < MAX_CERT_CHECKS)
-    {
-        // Construct certificate name.
-        char certFilename[20] = {0};
-        snprintf (certFilename, sizeof certFilename, "%08x.%d", certHash, certId);
-        char * certPath = g_build_filename (directory, certFilename, NULL);
-
-        bool_t signOk = file_is_signer_of_cert (certPath, serverCert);
-        g_free (certPath);
-
-        if (signOk)
-            return TRUE;
-
-        certId ++;
-    }
-
-    return FALSE;
-}
-
-/**
- * Checks if given certificate is valid certificate according to certificates
- * found from SSL_CERT_FILE or SSL_CERT_DIR environmental variables.
- */
-int neon_vfs_verify_environment_ssl_certs (void * userdata, int failures,
- const ne_ssl_certificate * serverCert)
-{
-    // First check the certificate file, if we have one.
-    const char * sslCertFile = g_getenv ("SSL_CERT_FILE");
-
-    if (sslCertFile != NULL)
-    {
-        if (file_is_signer_of_cert (sslCertFile, serverCert))
-            return failures & ~NE_SSL_UNTRUSTED;
-    }
-
-    // check if we have list of directories where certificates can be.
-    const char * sslCertDirPaths = g_getenv ("SSL_CERT_DIR");
-
-    if (sslCertDirPaths == NULL)
-        return failures;
-
-    uint32_t certHash = 0;
-    g_return_val_if_fail (cert_get_hash (serverCert, & certHash), failures);
-
-    char * sslCertDirPathsStart = g_strdup (sslCertDirPaths);
-    char * sslCertDirPathsEnd = sslCertDirPathsStart + strlen (sslCertDirPathsStart);
-    char * sslCertDir = sslCertDirPathsStart;
-    char * dirnameStart = sslCertDir;
-    char * dirnameEnd = dirnameStart;
-
-    // Start going through all directories in SSL_CERT_DIR
-    for (; dirnameEnd <= sslCertDirPathsEnd; dirnameEnd ++)
-    {
-        if (* dirnameEnd == G_SEARCHPATH_SEPARATOR || dirnameEnd == sslCertDirPathsEnd)
-        {
-            * dirnameEnd = 0;
-
-            // Skip empty directories
-            if (dirnameStart[0] == 0)
-            {
-                // Start next directory name after the inserted zero.
-                dirnameStart = dirnameEnd + 1;
-                continue;
-            }
-
-            if (validate_directory_certs (dirnameStart, serverCert, certHash))
-            {
-                g_free (sslCertDirPathsStart);
-                return failures & ~NE_SSL_UNTRUSTED;
-            }
-
-            // Start next directory name after the inserted zero.
-            dirnameStart = dirnameEnd + 1;
-        }
-    }
-
-    g_free (sslCertDirPathsStart);
-
-    return failures;
-}
diff --git a/src/neon/cert_verification.cc b/src/neon/cert_verification.cc
new file mode 100644
index 000000000000..8ffd9529960e
--- /dev/null
+++ b/src/neon/cert_verification.cc
@@ -0,0 +1,427 @@
+/*
+ *  Wget like SSL certificate validation from environmental variables.
+ *  Copyright (C) 2009 Jussi Judin
+ *
+ *  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.
+ */
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <ne_ssl.h>
+#include <ne_session.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "cert_verification.h"
+
+// Certificate validation handling.
+
+const int LENGTH_SHORTFORM_MAX = 127;
+const int LENGTH_INDEFINITE_VALUE = 128;
+const int LENGTH_LONGFORM_MASK = 0x7f;
+const int OCTET_BITS = 8;
+const int ASNTYPE_CODE_MASK = 0x1f;
+const int HASH_BYTES = 4;
+const uint32_t MAX_CERT_CHECKS = UINT32_MAX;
+
+enum AsnType
+{
+    ASNTYPE_INTEGER = 2,
+    ASNTYPE_SEQUENCE = 16,
+    ASNTYPE_VARLEN_IDENTIFIER = 31
+};
+
+struct DerData
+{
+    unsigned char * start;
+    unsigned char * end;
+    unsigned char * nextStart;
+    unsigned char * bufferEnd;
+    enum AsnType type;
+};
+
+/**
+ * X.509 certificate has following structure defined in RFC5280:
+ *
+ * Certificate  ::= SEQUENCE  {
+ *      tbsCertificate       TBSCertificate,
+ *      signatureAlgorithm   AlgorithmIdentifier,
+ *      signatureValue       BIT STRING  }
+ *
+ * TBSCertificate  ::=  SEQUENCE  {
+ *      version         [0]  EXPLICIT Version DEFAULT v1,
+ *      serialNumber         CertificateSerialNumber,
+ *      signature            AlgorithmIdentifier,
+ *      issuer               Name,
+ *      validity             Validity,
+ *      subject              Name,
+ * ...
+ *
+ * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+ * CertificateSerialNumber  ::=  INTEGER
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *      algorithm               OBJECT IDENTIFIER,
+ *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
+ * Validity ::= SEQUENCE {
+ *      notBefore      Time,
+ *      notAfter       Time }
+ * Time ::= CHOICE {
+ *      utcTime        UTCTime,
+ *      generalTime    GeneralizedTime }
+ * Name ::= CHOICE { -- only one possibility for now --
+ *   rdnSequence  RDNSequence }
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * And we are only interested in subject field.
+ */
+
+/**
+ * Returns the tag number of DER data.
+ */
+static bool der_read_tag_number (unsigned char * in_buffer,
+ const unsigned char * in_bufferEnd, unsigned char * * out_lengthStart,
+ enum AsnType * out_type)
+{
+    if (in_bufferEnd - in_buffer < 2)
+        return FALSE;
+
+    unsigned char typeOctet = in_buffer[0];
+    enum AsnType typeCode = (AsnType) (typeOctet & ASNTYPE_CODE_MASK);
+    int typeCodeLength = 1;
+
+    // Variable length types are not supported.
+    if (typeCode == ASNTYPE_VARLEN_IDENTIFIER)
+        return FALSE;
+
+    * out_type = typeCode;
+    * out_lengthStart = in_buffer + typeCodeLength;
+
+    return TRUE;
+}
+
+/**
+ * Returns pointers that point to the content of DER data value when identifier
+ * is not present.
+ */
+static bool der_read_content_length (unsigned char * in_buffer,
+ const unsigned char * in_bufferEnd, unsigned char * * out_start,
+ unsigned char * * out_end, unsigned char * * out_nextStart)
+{
+    if (in_bufferEnd - in_buffer < 1)
+        return FALSE;
+
+    unsigned char lengthDescription = in_buffer[0];
+
+    if (lengthDescription <= LENGTH_SHORTFORM_MAX)
+    {
+        * out_start = in_buffer + 1;
+        * out_end = * out_start + lengthDescription;
+
+        if (in_bufferEnd < * out_end)
+            return FALSE;
+
+        * out_nextStart = * out_end;
+        return TRUE;
+    }
+
+    if (lengthDescription == LENGTH_INDEFINITE_VALUE)
+    {
+        * out_start = in_buffer + 1;
+        unsigned char * currentPos = in_buffer + 1;
+
+        while (currentPos < in_bufferEnd - 1)
+        {
+            if (! currentPos[0] && ! currentPos[1])
+            {
+                * out_end = currentPos;
+                * out_nextStart = * out_end + 1;
+                return TRUE;
+            }
+        }
+
+        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;
+
+    if (in_bufferEnd < in_buffer + 1 + lengthOctets)
+        return FALSE;
+
+    size_t contentLength = 0;
+    size_t i = 0;
+
+    for (i = 0; i < lengthOctets; i++)
+    {
+        contentLength <<= OCTET_BITS;
+        contentLength |= in_buffer[i + 1];
+    }
+
+    * out_start = in_buffer + 1 + lengthOctets;
+    * out_end = * out_start + contentLength;
+
+    if (in_bufferEnd < * out_end)
+        return FALSE;
+
+    * out_nextStart = * out_end;
+    return TRUE;
+}
+
+/**
+ * Returns pointers that point to the content of DER data value.
+ */
+static bool der_read_content (struct DerData * data, struct DerData * content)
+{
+    unsigned char * lengthStart = nullptr;
+    bool typeOk = der_read_tag_number (data->start, data->bufferEnd,
+     & lengthStart, & content->type);
+
+    if (! typeOk)
+        return FALSE;
+
+    content->bufferEnd = data->bufferEnd;
+    return der_read_content_length (lengthStart, data->bufferEnd,
+     & content->start, & content->end, & content->nextStart);
+}
+
+/**
+ * Returns pointers that point to next DER data value.
+ */
+static bool der_read_next (struct DerData * currentContent, struct DerData * nextContent)
+{
+    nextContent->start = currentContent->nextStart;
+
+    unsigned char * lengthStart = nullptr;
+    bool typeOk = der_read_tag_number (currentContent->start,
+     currentContent->bufferEnd, & lengthStart, & nextContent->type);
+
+    if (! typeOk)
+        return FALSE;
+
+    unsigned char * nextContentStart = nullptr;
+    return der_read_content_length (lengthStart, currentContent->bufferEnd,
+     & nextContentStart, & nextContent->end, & nextContent->nextStart);
+}
+
+/**
+ * Returns certificate hash that can be used to certificate links generated
+ * by c_rehash command.
+ *
+ * Certificate hash is just 4 first octets of MD5 sum of certificate subject id
+ * DER format.
+ *
+ * @return TRUE if given certificate could be parsed by this, FALSE otherwise.
+ */
+static bool cert_get_hash (const ne_ssl_certificate * cert, uint32_t * out_hash)
+{
+    char * certPem = ne_ssl_cert_export (cert);
+    g_return_val_if_fail (certPem != nullptr, 1);
+    size_t derLength = 0;
+    unsigned char * certDer = g_base64_decode (certPem, &derLength);
+    g_free (certPem);
+    g_return_val_if_fail (certDer != nullptr, 1);
+
+    struct DerData data = {0};
+    struct DerData content = {0};
+
+    data.start = certDer;
+    data.bufferEnd = certDer + derLength;
+
+    // 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);
+    // tbsCertificate
+    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);
+    // signature
+    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);
+    // validity
+    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);
+
+    // Calculate MD5 sum of subject.
+    unsigned char md5pword[16];
+    size_t md5len = 16;
+
+    GChecksum * state = g_checksum_new (G_CHECKSUM_MD5);
+    g_checksum_update (state, content.start, content.nextStart - content.start);
+    g_checksum_get_digest (state, md5pword, & md5len);
+    g_checksum_free (state);
+
+    uint32_t hash = 0;
+
+    // Hash is reverse of four first bytes of MD5 checksum of DER encoded
+    // subject ASN.1 field.
+    for (int i = HASH_BYTES - 1; i >= 0; i --)
+    {
+        hash <<= OCTET_BITS;
+        hash |= md5pword[i];
+    }
+
+    * out_hash = hash;
+
+    g_free (certDer);
+    return TRUE;
+}
+
+/**
+ * Checks if given certificate is signed by given signer certificate.
+ *
+ * Goes up in certificate signer chain of certificate and compares if any one
+ * of them is same as given signer.
+ */
+static bool is_signer_of_cert (const ne_ssl_certificate * signer, const ne_ssl_certificate * cert)
+{
+    const ne_ssl_certificate * certSigner = cert;
+
+    while (certSigner != nullptr)
+    {
+        if (ne_ssl_cert_cmp (signer, certSigner) == 0)
+            return TRUE;
+
+        certSigner = ne_ssl_cert_signedby (certSigner);
+    }
+
+    return FALSE;
+}
+
+/**
+ * Checks if given file includes certificate that has signed given certificate.
+ */
+static bool file_is_signer_of_cert (const char * filename, const ne_ssl_certificate * cert)
+{
+    ne_ssl_certificate * signer = ne_ssl_cert_read (filename);
+
+    if (signer != nullptr)
+    {
+        bool signOk = is_signer_of_cert (signer, cert);
+        ne_ssl_cert_free (signer);
+
+        if (signOk)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+/**
+ * Checks if directory includes a file that can be signer of given certificate.
+ */
+static bool validate_directory_certs (const char * directory,
+ const ne_ssl_certificate * serverCert, uint32_t certHash)
+{
+    // Search certificate names in ascending order and assume that all names
+    // point to valid certificates.
+    uint32_t certId = 0;
+
+    while (certId < MAX_CERT_CHECKS)
+    {
+        // Construct certificate name.
+        StringBuf certFilename = str_printf ("%08x.%d", certHash, certId);
+        char * certPath = g_build_filename (directory, (const char *) certFilename, nullptr);
+
+        bool signOk = file_is_signer_of_cert (certPath, serverCert);
+        g_free (certPath);
+
+        if (signOk)
+            return TRUE;
+
+        certId ++;
+    }
+
+    return FALSE;
+}
+
+/**
+ * Checks if given certificate is valid certificate according to certificates
+ * found from SSL_CERT_FILE or SSL_CERT_DIR environmental variables.
+ */
+int neon_vfs_verify_environment_ssl_certs (void * userdata, int failures,
+ const ne_ssl_certificate * serverCert)
+{
+    // First check the certificate file, if we have one.
+    const char * sslCertFile = g_getenv ("SSL_CERT_FILE");
+
+    if (sslCertFile != nullptr)
+    {
+        if (file_is_signer_of_cert (sslCertFile, serverCert))
+            return failures & ~NE_SSL_UNTRUSTED;
+    }
+
+    // check if we have list of directories where certificates can be.
+    const char * sslCertDirPaths = g_getenv ("SSL_CERT_DIR");
+
+    if (sslCertDirPaths == nullptr)
+        return failures;
+
+    uint32_t certHash = 0;
+    g_return_val_if_fail (cert_get_hash (serverCert, & certHash), failures);
+
+    char * sslCertDirPathsStart = g_strdup (sslCertDirPaths);
+    char * sslCertDirPathsEnd = sslCertDirPathsStart + strlen (sslCertDirPathsStart);
+    char * sslCertDir = sslCertDirPathsStart;
+    char * dirnameStart = sslCertDir;
+    char * dirnameEnd = dirnameStart;
+
+    // Start going through all directories in SSL_CERT_DIR
+    for (; dirnameEnd <= sslCertDirPathsEnd; dirnameEnd ++)
+    {
+        if (* dirnameEnd == G_SEARCHPATH_SEPARATOR || dirnameEnd == sslCertDirPathsEnd)
+        {
+            * dirnameEnd = 0;
+
+            // Skip empty directories
+            if (dirnameStart[0] == 0)
+            {
+                // Start next directory name after the inserted zero.
+                dirnameStart = dirnameEnd + 1;
+                continue;
+            }
+
+            if (validate_directory_certs (dirnameStart, serverCert, certHash))
+            {
+                g_free (sslCertDirPathsStart);
+                return failures & ~NE_SSL_UNTRUSTED;
+            }
+
+            // Start next directory name after the inserted zero.
+            dirnameStart = dirnameEnd + 1;
+        }
+    }
+
+    g_free (sslCertDirPathsStart);
+
+    return failures;
+}
diff --git a/src/neon/debug.h b/src/neon/debug.h
deleted file mode 100644
index a6b1c1a2661d..000000000000
--- a/src/neon/debug.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  Copyright (C) 2005 Ralf Ertzinger
- *
- *  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 DEBUG_H
-#define DEBUG_H
-
-#include <stdio.h>
-
-#define _ERROR(...) do { printf ("neon: " __VA_ARGS__); putchar ('\n'); } while (0)
-
-#ifdef NEON_DEBUG
-#define _DEBUG _ERROR
-#else
-#define _DEBUG(...)
-#endif
-
-#endif
diff --git a/src/neon/neon.c b/src/neon/neon.c
deleted file mode 100644
index fa7c12a522a1..000000000000
--- a/src/neon/neon.c
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*
- *  A neon HTTP input plugin for Audacious
- *  Copyright (C) 2007 Ralf Ertzinger
- *
- *  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.
- */
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <glib.h>
-
-#ifdef DEBUG
-#define NEON_DEBUG
-#endif
-
-#include "neon.h"
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include <ne_socket.h>
-#include <ne_utils.h>
-#include <ne_redirect.h>
-#include <ne_request.h>
-#include <ne_auth.h>
-
-#include "debug.h"
-#include "rb.h"
-#include "cert_verification.h"
-
-#define NEON_BUFSIZE        (128u*1024u)
-#define NEON_NETBLKSIZE     (4096u)
-#define NEON_ICY_BUFSIZE    (4096)
-#define NEON_RETRY_COUNT 6
-
-static bool_t neon_plugin_init (void)
-{
-    int ret = ne_sock_init ();
-
-    if (ret != 0)
-    {
-        _ERROR ("Could not initialize neon library: %d\n", ret);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static void neon_plugin_fini (void)
-{
-    ne_sock_exit ();
-}
-
-static struct neon_handle * handle_init (void)
-{
-    struct neon_handle * h = g_new0 (struct neon_handle, 1);
-
-    pthread_mutex_init (& h->reader_status.mutex, NULL);
-    pthread_cond_init (& h->reader_status.cond, NULL);
-    h->reader_status.reading = FALSE;
-    h->reader_status.status = NEON_READER_INIT;
-
-    init_rb_with_lock (& h->rb, NEON_BUFSIZE, & h->reader_status.mutex);
-
-    h->purl = g_new0 (ne_uri, 1);
-    h->content_length = -1;
-
-    return h;
-}
-
-static void handle_free (struct neon_handle * h)
-{
-    ne_uri_free (h->purl);
-    g_free (h->purl);
-    destroy_rb (& h->rb);
-
-    pthread_mutex_destroy (& h->reader_status.mutex);
-    pthread_cond_destroy (& h->reader_status.cond);
-
-    g_free (h->icy_metadata.stream_name);
-    g_free (h->icy_metadata.stream_title);
-    g_free (h->icy_metadata.stream_url);
-    g_free (h->icy_metadata.stream_contenttype);
-    g_free (h->url);
-    g_free (h);
-}
-
-static bool_t neon_strcmp (const char * str, const char * cmp)
-{
-    return ! g_ascii_strncasecmp (str, cmp, strlen (cmp));
-}
-
-static void add_icy (struct icy_metadata * m, char * name, char * value)
-{
-    if (neon_strcmp (name, "StreamTitle"))
-    {
-        _DEBUG ("Found StreamTitle: %s", value);
-        g_free (m->stream_title);
-        m->stream_title = g_strdup (value);
-    }
-
-    if (neon_strcmp (name, "StreamUrl"))
-    {
-        _DEBUG ("Found StreamUrl: %s", value);
-        g_free (m->stream_url);
-        m->stream_url = g_strdup (value);
-    }
-}
-
-static void parse_icy (struct icy_metadata * m, char * metadata, size_t len)
-{
-    typedef enum
-    {
-        STATE_READ_NAME,
-        STATE_WAIT_VALUE,
-        STATE_READ_VALUE,
-        STATE_WAIT_NAME,
-    } TagReadState;
-
-    TagReadState state = STATE_READ_NAME;
-
-    char * p = metadata;
-    char * tstart = metadata;
-    size_t pos = 1;
-
-    char name[NEON_ICY_BUFSIZE];
-    char value[NEON_ICY_BUFSIZE];
-
-    name[0] = 0;
-    value[0] = 0;
-
-    while (pos < len && p[0])
-    {
-        switch (state)
-        {
-        case STATE_READ_NAME:
-
-            /* Reading tag name */
-            if (p[0] == '=')
-            {
-                /* End of tag name. */
-                p[0] = 0;
-                g_strlcpy (name, tstart, NEON_ICY_BUFSIZE);
-                _DEBUG ("Found tag name: %s", name);
-                state = STATE_WAIT_VALUE;
-            }
-
-            break;
-
-        case STATE_WAIT_VALUE:
-
-            /* Waiting for start of value */
-            if (p[0] == '\'')
-            {
-                /* Leading ' of value */
-                tstart = p + 1;
-                state = STATE_READ_VALUE;
-                value[0] = 0;
-            }
-
-            break;
-
-        case STATE_READ_VALUE:
-
-            /* Reading value */
-            if (p[0] == '\'' && p[1] == ';')
-            {
-                /* End of value */
-                p[0] = 0;
-                g_strlcpy (value, tstart, NEON_ICY_BUFSIZE);
-                _DEBUG ("Found tag value: %s", value);
-                add_icy (m, name, value);
-                state = STATE_WAIT_NAME;
-            }
-
-            break;
-
-        case STATE_WAIT_NAME:
-
-            /* Waiting for next tag start */
-            if (p[0] == ';')
-            {
-                /* Next tag name starts after this char */
-                tstart = p + 1;
-                state = STATE_READ_NAME;
-                name[0] = 0;
-                value[0] = 0;
-            }
-
-            break;
-        }
-
-        p ++;
-        pos ++;
-    }
-}
-
-static void kill_reader (struct neon_handle * h)
-{
-    _DEBUG ("Signaling reader thread to terminate");
-    pthread_mutex_lock (& h->reader_status.mutex);
-    h->reader_status.reading = FALSE;
-    pthread_cond_broadcast (& h->reader_status.cond);
-    pthread_mutex_unlock (& h->reader_status.mutex);
-
-    _DEBUG ("Waiting for reader thread to die...");
-    pthread_join (h->reader, NULL);
-    _DEBUG ("Reader thread has died");
-}
-
-static int server_auth_callback (void * userdata, const char * realm,
- int attempt, char * username, char * password)
-{
-    struct neon_handle * h = userdata;
-
-    if (! h->purl->userinfo || ! h->purl->userinfo[0])
-    {
-        _ERROR ("Authentication required, but no credentials set");
-        return 1;
-    }
-
-    char * * authtok = g_strsplit (h->purl->userinfo, ":", 2);
-
-    if (strlen (authtok[1]) > NE_ABUFSIZ - 1 || strlen (authtok[0]) > NE_ABUFSIZ - 1)
-    {
-        _ERROR ("Username/Password too long");
-        g_strfreev (authtok);
-        return 1;
-    }
-
-    g_strlcpy (username, authtok[0], NE_ABUFSIZ);
-    g_strlcpy (password, authtok[1], NE_ABUFSIZ);
-
-    _DEBUG ("Authenticating: Username: %s, Password: %s", username, password);
-
-    g_strfreev (authtok);
-
-    return attempt;
-}
-
-static void handle_headers (struct neon_handle * h)
-{
-    const char * name;
-    const char * value;
-    void * cursor = NULL;
-
-    _DEBUG ("Header responses:");
-
-    while ((cursor = ne_response_header_iterate (h->request, cursor, & name, & value)))
-    {
-        _DEBUG ("HEADER: %s: %s", name, value);
-
-        if (neon_strcmp (name, "accept-ranges"))
-        {
-            /* The server advertises range capability. we need "bytes" */
-            if (strstr (value, "bytes"))
-            {
-                _DEBUG ("server can_ranges");
-                h->can_ranges = TRUE;
-            }
-        }
-        else if (neon_strcmp (name, "content-length"))
-        {
-            /* The server sent us the content length. Parse and store. */
-            char * endptr;
-            long len = strtol (value, & endptr, 10);
-
-            if (value[0] && ! endptr[0] && len >= 0)
-            {
-                /* Valid data. */
-                _DEBUG ("Content length as advertised by server: %ld", len);
-                h->content_length = len;
-            }
-            else
-                _ERROR ("Invalid content length header: %s", value);
-        }
-        else if (neon_strcmp (name, "content-type"))
-        {
-            /* The server sent us a content type. Save it for later */
-            _DEBUG ("Content-Type: %s", value);
-            g_free (h->icy_metadata.stream_contenttype);
-            h->icy_metadata.stream_contenttype = g_strdup (value);
-        }
-        else if (neon_strcmp (name, "icy-metaint"))
-        {
-            /* The server sent us a ICY metaint header. Parse and store. */
-            char * endptr;
-            long len = strtol (value, & endptr, 10);
-
-            if (value[0] && ! endptr[0] && len > 0)
-            {
-                /* Valid data */
-                _DEBUG ("ICY MetaInt as advertised by server: %ld", len);
-                h->icy_metaint = len;
-                h->icy_metaleft = len;
-            }
-            else
-                _ERROR ("Invalid ICY MetaInt header: %s", value);
-        }
-        else if (neon_strcmp (name, "icy-name"))
-        {
-            /* The server sent us a ICY name. Save it for later */
-            _DEBUG ("ICY stream name: %s", value);
-            g_free (h->icy_metadata.stream_name);
-            h->icy_metadata.stream_name = g_strdup (value);
-        }
-        else if (neon_strcmp (name, "icy-br"))
-        {
-            /* The server sent us a bitrate. We might want to use it. */
-            _DEBUG ("ICY bitrate: %d", atoi (value));
-            h->icy_metadata.stream_bitrate = atoi (value);
-        }
-    }
-}
-
-static int neon_proxy_auth_cb (void * userdata, const char * realm, int attempt,
- char * username, char * password)
-{
-    char * value = aud_get_str (NULL, "proxy_user");
-    g_strlcpy (username, value, NE_ABUFSIZ);
-    str_unref (value);
-
-    value = aud_get_str (NULL, "proxy_pass");
-    g_strlcpy (password, value, NE_ABUFSIZ);
-    str_unref (value);
-
-    return attempt;
-}
-
-static int open_request (struct neon_handle * handle, uint64_t startbyte)
-{
-    int ret;
-    const ne_status * status;
-    ne_uri * rediruri;
-
-    if (handle->purl->query && * (handle->purl->query))
-    {
-        SCONCAT3 (tmp, handle->purl->path, "?", handle->purl->query);
-        handle->request = ne_request_create (handle->session, "GET", tmp);
-    }
-    else
-        handle->request = ne_request_create (handle->session, "GET", handle->purl->path);
-
-    if (startbyte > 0)
-        ne_print_request_header (handle->request, "Range", "bytes=%"PRIu64"-", startbyte);
-
-    ne_print_request_header (handle->request, "Icy-MetaData", "1");
-
-    /* Try to connect to the server. */
-    _DEBUG ("<%p> Connecting...", handle);
-    ret = ne_begin_request (handle->request);
-    status = ne_get_status (handle->request);
-    _DEBUG ("<%p> Return: %d, Status: %d", handle, ret, status->code);
-
-    if (ret == NE_OK)
-    {
-        switch (status->code)
-        {
-        case 401:
-            /* Authorization required. Reconnect to authenticate */
-            _DEBUG ("Reconnecting due to 401");
-            ne_end_request (handle->request);
-            ret = ne_begin_request (handle->request);
-            break;
-
-        case 301:
-        case 302:
-        case 303:
-        case 307:
-            /* Redirect encountered. Reconnect. */
-            ne_end_request (handle->request);
-            ret = NE_REDIRECT;
-            break;
-
-        case 407:
-            /* Proxy auth required. Reconnect to authenticate */
-            _DEBUG ("Reconnecting due to 407");
-            ne_end_request (handle->request);
-            ret = ne_begin_request (handle->request);
-            break;
-        }
-    }
-
-    switch (ret)
-    {
-    case NE_OK:
-        if (status->code > 199 && status->code < 300)
-        {
-            /* URL opened OK */
-            _DEBUG ("<%p> URL opened OK", handle);
-            handle->content_start = startbyte;
-            handle->pos = startbyte;
-            handle_headers (handle);
-            return 0;
-        }
-
-        break;
-
-    case NE_REDIRECT:
-        /* We hit a redirect. Handle it. */
-        _DEBUG ("<%p> Redirect encountered", handle);
-        handle->redircount += 1;
-        rediruri = (ne_uri *) ne_redirect_location (handle->session);
-        ne_request_destroy (handle->request);
-        handle->request = NULL;
-
-        if (! rediruri)
-        {
-            _ERROR ("<%p> Could not parse redirect response", (void *) handle);
-            return -1;
-        }
-
-        ne_uri_free (handle->purl);
-        ne_uri_copy (handle->purl, rediruri);
-        return 1;
-    }
-
-    /* Something went wrong. */
-    _ERROR ("<%p> Could not open URL: %d (%d)", (void *) handle, ret, status->code);
-
-    if (ret)
-        _ERROR ("<%p> neon error string: %s", (void *) handle, ne_get_error (handle->session));
-
-    ne_request_destroy (handle->request);
-    handle->request = NULL;
-    return -1;
-}
-
-static int open_handle (struct neon_handle * handle, uint64_t startbyte)
-{
-    int ret;
-    char * proxy_host = NULL;
-    int proxy_port = 0;
-
-    bool_t use_proxy = aud_get_bool (NULL, "use_proxy");
-    bool_t use_proxy_auth = aud_get_bool (NULL, "use_proxy_auth");
-
-    if (use_proxy)
-    {
-        proxy_host = aud_get_str (NULL, "proxy_host");
-        proxy_port = aud_get_int (NULL, "proxy_port");
-    }
-
-    handle->redircount = 0;
-
-    _DEBUG ("<%p> Parsing URL", handle);
-
-    if (ne_uri_parse (handle->url, handle->purl) != 0)
-    {
-        _ERROR ("<%p> Could not parse URL '%s'", (void *) handle, handle->url);
-        return -1;
-    }
-
-    while (handle->redircount < 10)
-    {
-        if (! handle->purl->port)
-            handle->purl->port = ne_uri_defaultport (handle->purl->scheme);
-
-        _DEBUG ("<%p> Creating session to %s://%s:%d", handle,
-         handle->purl->scheme, handle->purl->host, handle->purl->port);
-        handle->session = ne_session_create (handle->purl->scheme,
-         handle->purl->host, handle->purl->port);
-        ne_redirect_register (handle->session);
-        ne_add_server_auth (handle->session, NE_AUTH_BASIC, server_auth_callback, (void *) handle);
-        ne_set_session_flag (handle->session, NE_SESSFLAG_ICYPROTO, 1);
-        ne_set_session_flag (handle->session, NE_SESSFLAG_PERSIST, 0);
-
-#ifdef HAVE_NE_SET_CONNECT_TIMEOUT
-        ne_set_connect_timeout (handle->session, 10);
-#endif
-
-        ne_set_read_timeout (handle->session, 10);
-        ne_set_useragent (handle->session, "Audacious/" PACKAGE_VERSION);
-
-        if (use_proxy)
-        {
-            _DEBUG ("<%p> Using proxy: %s:%d", handle, proxy_host, proxy_port);
-            ne_session_proxy (handle->session, proxy_host, proxy_port);
-
-            if (use_proxy_auth)
-            {
-                _DEBUG ("<%p> Using proxy authentication", handle);
-                ne_add_proxy_auth (handle->session, NE_AUTH_BASIC,
-                 neon_proxy_auth_cb, (void *) handle);
-            }
-        }
-
-        if (! strcmp ("https", handle->purl->scheme))
-        {
-            ne_ssl_trust_default_ca (handle->session);
-            ne_ssl_set_verify (handle->session,
-             neon_vfs_verify_environment_ssl_certs, handle->session);
-        }
-
-        _DEBUG ("<%p> Creating request", handle);
-        ret = open_request (handle, startbyte);
-
-        if (! ret)
-        {
-            str_unref (proxy_host);
-            return 0;
-        }
-
-        if (ret == -1)
-        {
-            ne_session_destroy (handle->session);
-            handle->session = NULL;
-            str_unref (proxy_host);
-            return -1;
-        }
-
-        _DEBUG ("<%p> Following redirect...", handle);
-        ne_session_destroy (handle->session);
-        handle->session = NULL;
-    }
-
-    /* If we get here, our redirect count exceeded */
-    _ERROR ("<%p> Redirect count exceeded for URL %s", (void *) handle, handle->url);
-
-    str_unref (proxy_host);
-    return 1;
-}
-
-typedef enum
-{
-    FILL_BUFFER_SUCCESS,
-    FILL_BUFFER_ERROR,
-    FILL_BUFFER_EOF
-} FillBufferResult;
-
-static FillBufferResult fill_buffer (struct neon_handle * h)
-{
-    int bsize = free_rb (& h->rb);
-    int to_read = MIN (bsize, NEON_NETBLKSIZE);
-
-    char buffer[NEON_NETBLKSIZE];
-
-    bsize = ne_read_response_block (h->request, buffer, to_read);
-
-    if (! bsize)
-    {
-        _DEBUG ("<%p> End of file encountered", h);
-        return FILL_BUFFER_EOF;
-    }
-
-    if (bsize < 0)
-    {
-        _ERROR ("<%p> Error while reading from the network", (void *) h);
-        ne_request_destroy (h->request);
-        h->request = NULL;
-        return FILL_BUFFER_ERROR;
-    }
-
-    _DEBUG ("<%p> Read %d bytes of %d", h, bsize, to_read);
-
-    write_rb (& h->rb, buffer, bsize);
-
-    return FILL_BUFFER_SUCCESS;
-}
-
-static void * reader_thread (void * data)
-{
-    struct neon_handle * h = data;
-
-    pthread_mutex_lock (& h->reader_status.mutex);
-
-    while (h->reader_status.reading)
-    {
-        /* Hit the network only if we have more than NEON_NETBLKSIZE of free buffer */
-        if (NEON_NETBLKSIZE < free_rb_locked (& h->rb))
-        {
-            pthread_mutex_unlock (& h->reader_status.mutex);
-
-            FillBufferResult ret = fill_buffer (h);
-
-            pthread_mutex_lock (& h->reader_status.mutex);
-
-            /* Wake up main thread if it is waiting. */
-            pthread_cond_broadcast (& h->reader_status.cond);
-
-            if (ret == FILL_BUFFER_ERROR)
-            {
-                _ERROR ("<%p> Error while reading from the network. "
-                        "Terminating reader thread", (void *) h);
-                h->reader_status.status = NEON_READER_ERROR;
-                pthread_mutex_unlock (& h->reader_status.mutex);
-                return NULL;
-            }
-            else if (ret == FILL_BUFFER_EOF)
-            {
-                _DEBUG ("<%p> EOF encountered while reading from the network. "
-                        "Terminating reader thread", (void *) h);
-                h->reader_status.status = NEON_READER_EOF;
-                pthread_mutex_unlock (& h->reader_status.mutex);
-                return NULL;
-            }
-        }
-        else
-        {
-            /* Not enough free space in the buffer.
-             * Sleep until the main thread wakes us up. */
-            pthread_cond_wait (& h->reader_status.cond, & h->reader_status.mutex);
-        }
-    }
-
-    _DEBUG ("<%p> Reader thread terminating gracefully", h);
-    h->reader_status.status = NEON_READER_TERM;
-    pthread_mutex_unlock (& h->reader_status.mutex);
-
-    return NULL;
-}
-
-void * neon_vfs_fopen_impl (const char * path, const char * mode)
-{
-    struct neon_handle * handle = handle_init ();
-
-    _DEBUG ("<%p> Trying to open '%s' with neon", (void *) handle, path);
-
-    handle->url = g_strdup (path);
-
-    if (open_handle (handle, 0) != 0)
-    {
-        _ERROR ("<%p> Could not open URL", (void *) handle);
-        handle_free (handle);
-        return NULL;
-    }
-
-    return handle;
-}
-
-int neon_vfs_fclose_impl (VFSFile * file)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    if (h->reader_status.reading)
-        kill_reader (h);
-
-    if (h->request)
-        ne_request_destroy (h->request);
-    if (h->session)
-        ne_session_destroy (h->session);
-
-    handle_free (h);
-
-    return 0;
-}
-
-static int64_t neon_fread_real (void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    if (! h->request)
-    {
-        _ERROR ("<%p> No request to read from, seek gone wrong?", (void *) h);
-        return 0;
-    }
-
-    if (! size || ! nmemb || h->eof)
-        return 0;
-
-    /* If the buffer is empty, wait for the reader thread to fill it. */
-    pthread_mutex_lock (& h->reader_status.mutex);
-
-    for (int retries = 0; retries < NEON_RETRY_COUNT; retries ++)
-    {
-        if (used_rb_locked (& h->rb) / size > 0 || ! h->reader_status.reading ||
-         h->reader_status.status != NEON_READER_RUN)
-            break;
-
-        pthread_cond_broadcast (& h->reader_status.cond);
-        pthread_cond_wait (& h->reader_status.cond, & h->reader_status.mutex);
-    }
-
-    pthread_mutex_unlock (& h->reader_status.mutex);
-
-    if (! h->reader_status.reading)
-    {
-        if (h->reader_status.status != NEON_READER_EOF || h->content_length != -1)
-        {
-            /* There is no reader thread yet. Read the first bytes from
-             * the network ourselves, and then fire up the reader thread
-             * to keep the buffer filled up. */
-            _DEBUG ("<%p> Doing initial buffer fill", h);
-            FillBufferResult ret = fill_buffer (h);
-
-            if (ret == FILL_BUFFER_ERROR)
-            {
-                _ERROR ("<%p> Error while reading from the network", (void *) h);
-                return 0;
-            }
-
-            /* We have some data in the buffer now.
-             * Start the reader thread if we did not reach EOF during
-             * the initial fill */
-            pthread_mutex_lock (& h->reader_status.mutex);
-
-            if (ret == FILL_BUFFER_SUCCESS)
-            {
-                h->reader_status.reading = TRUE;
-                _DEBUG ("<%p> Starting reader thread", h);
-                pthread_create (& h->reader, NULL, reader_thread, h);
-                h->reader_status.status = NEON_READER_RUN;
-            }
-            else if (ret == FILL_BUFFER_EOF)
-            {
-                _DEBUG ("<%p> No reader thread needed (stream has reached EOF during fill)", h);
-                h->reader_status.reading = FALSE;
-                h->reader_status.status = NEON_READER_EOF;
-            }
-
-            pthread_mutex_unlock (& h->reader_status.mutex);
-        }
-    }
-    else
-    {
-        /* There already is a reader thread. Look if it is in good shape. */
-        pthread_mutex_lock (& h->reader_status.mutex);
-
-        switch (h->reader_status.status)
-        {
-        case NEON_READER_INIT:
-        case NEON_READER_RUN:
-            /* All is well, nothing to be done. */
-            break;
-
-        case NEON_READER_ERROR:
-            /* A reader error happened. Log it, and treat it like an EOF
-             * condition, by falling through to the NEON_READER_EOF codepath. */
-            _DEBUG ("<%p> NEON_READER_ERROR happened. Terminating reader thread and marking EOF.", h);
-            h->reader_status.status = NEON_READER_EOF;
-            pthread_mutex_unlock (& h->reader_status.mutex);
-
-            if (h->reader_status.reading)
-                kill_reader (h);
-
-            pthread_mutex_lock (& h->reader_status.mutex);
-
-        case NEON_READER_EOF:
-            /* If there still is data in the buffer, carry on.
-             * If not, terminate the reader thread and return 0. */
-            if (! used_rb_locked (& h->rb))
-            {
-                _DEBUG ("<%p> Reached end of stream", h);
-                pthread_mutex_unlock (& h->reader_status.mutex);
-
-                if (h->reader_status.reading)
-                    kill_reader (h);
-
-                h->eof = TRUE;
-                return 0;
-            }
-
-            break;
-
-        case NEON_READER_TERM:
-            /* The reader thread terminated gracefully, most likely on our own request.
-             * We should not get here. */
-            g_warn_if_reached ();
-            pthread_mutex_unlock (& h->reader_status.mutex);
-            return 0;
-        }
-
-        pthread_mutex_unlock (& h->reader_status.mutex);
-    }
-
-    /* Deliver data from the buffer */
-    if (! used_rb (& h->rb))
-    {
-        /* The buffer is still empty, we can deliver no data! */
-        _ERROR ("<%p> Buffer still underrun, fatal.", (void *) h);
-        return 0;
-    }
-
-    int belem = used_rb (& h->rb) / size;
-
-    if (h->icy_metaint)
-    {
-        if (! h->icy_metaleft)
-        {
-            /* The next data in the buffer is a ICY metadata announcement.
-             * Get the length byte */
-            unsigned char icy_metalen;
-            read_rb (& h->rb, & icy_metalen, 1);
-
-            /*  We need enough data in the buffer to
-             * a) Read the complete ICY metadata block
-             * b) deliver at least one byte to the reader */
-            _DEBUG ("<%p> Expecting %d bytes of ICY metadata", h, (icy_metalen*16));
-
-            if (free_rb (& h->rb) - icy_metalen * 16 < size)
-            {
-                /* 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. */
-                _ERROR ("<%p> Buffer underrun when reading metadata. Expect "
-                 "audio degradation", (void *) h);
-                h->icy_metaleft = h->icy_metaint + icy_metalen * 16;
-            }
-            else
-            {
-                /* Grab the metadata from the buffer and send it to the parser */
-                char icy_metadata[NEON_ICY_BUFSIZE];
-                read_rb (& h->rb, icy_metadata, icy_metalen * 16);
-                parse_icy (& h->icy_metadata, icy_metadata, icy_metalen * 16);
-                h->icy_metaleft = h->icy_metaint;
-            }
-        }
-
-        /* The maximum number of bytes we can deliver is determined
-         * by the number of bytes left until the next metadata announcement */
-        belem = MIN (used_rb (& h->rb), h->icy_metaleft) / size;
-    }
-
-    nmemb = MIN (belem, nmemb);
-    read_rb (& h->rb, ptr, nmemb * size);
-
-    /* Signal the network thread to continue reading */
-    pthread_mutex_lock (& h->reader_status.mutex);
-
-    if (h->reader_status.status == NEON_READER_EOF)
-    {
-        if (! free_rb_locked (& h->rb))
-        {
-            _DEBUG ("<%p> stream EOF reached and buffer empty", h);
-            h->eof = TRUE;
-        }
-    }
-    else
-        pthread_cond_broadcast (& h->reader_status.cond);
-
-    pthread_mutex_unlock (& h->reader_status.mutex);
-
-    h->pos += nmemb * size;
-    h->icy_metaleft -= nmemb * size;
-
-    return nmemb;
-}
-
-/* neon_fread_real will do only a partial read if the buffer underruns, so we
- * must call it repeatedly until we have read the full request. */
-int64_t neon_vfs_fread_impl (void * buffer, int64_t size, int64_t count, VFSFile * handle)
-{
-    size_t total = 0, new;
-
-    _DEBUG ("<%p> fread %d x %d", (void *) handle, (int) size, (int) count);
-
-    while (count > 0 && (new = neon_fread_real (buffer, size, count, handle)) > 0)
-    {
-        buffer = (char *) buffer + size * new;
-        total += new;
-        count -= new;
-    }
-
-    _DEBUG ("<%p> fread = %d", (void *) handle, (int) total);
-
-    return total;
-}
-
-int64_t neon_vfs_fwrite_impl (const void * ptr, int64_t size, int64_t nmemb, VFSFile * file)
-{
-    _ERROR ("<%p> NOT IMPLEMENTED", (void *) vfs_get_handle (file));
-
-    return 0;
-}
-
-int64_t neon_vfs_ftell_impl (VFSFile * file)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    _DEBUG ("<%p> Current file position: %ld", h, h->pos);
-
-    return h->pos;
-}
-
-bool_t neon_vfs_feof_impl (VFSFile * file)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    _DEBUG ("<%p> EOF status: %s", h, h->eof ? "TRUE" : "FALSE");
-
-    return h->eof;
-}
-
-int neon_vfs_truncate_impl (VFSFile * file, int64_t size)
-{
-    _ERROR ("<%p> NOT IMPLEMENTED", (void *) vfs_get_handle (file));
-
-    return 0;
-}
-
-int neon_vfs_fseek_impl (VFSFile * file, int64_t offset, int whence)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    _DEBUG ("<%p> Seek requested: offset %ld, whence %d", h, offset, whence);
-
-    /* To seek to a non-zero offset, two things must be satisfied:
-     * - the server must advertise a content-length
-     * - the server must advertise accept-ranges: bytes */
-    if ((whence != SEEK_SET || offset) && (h->content_length < 0 || ! h->can_ranges))
-    {
-        _DEBUG ("<%p> Can not seek due to server restrictions", h);
-        return -1;
-    }
-
-    int64_t content_length = h->content_length + h->content_start;
-    int64_t newpos;
-
-    switch (whence)
-    {
-    case SEEK_SET:
-        newpos = offset;
-        break;
-
-    case SEEK_CUR:
-        newpos = h->pos + offset;
-        break;
-
-    case SEEK_END:
-        if (offset == 0)
-        {
-            h->pos = content_length;
-            h->eof = TRUE;
-            return 0;
-        }
-
-        newpos = content_length + offset;
-        break;
-
-    default:
-        _ERROR ("<%p> Invalid whence specified", (void *) h);
-        return -1;
-    }
-
-    _DEBUG ("<%p> Position to seek to: %ld, current: %ld", h, newpos, h->pos);
-
-    if (newpos < 0)
-    {
-        _ERROR ("<%p> Can not seek before start of stream", (void *) h);
-        return -1;
-    }
-
-    if (newpos && newpos >= content_length)
-    {
-        _ERROR ("<%p> Can not seek beyond end of stream (%ld >= %ld)",
-         (void *) h, (long) newpos, (long) content_length);
-        return -1;
-    }
-
-    if (newpos == h->pos)
-        return 0;
-
-    /* To seek to the new position we have to
-     * - stop the current reader thread, if there is one
-     * - destroy the current request
-     * - dump all data currently in the ringbuffer
-     * - create a new request starting at newpos */
-    if (h->reader_status.reading)
-        kill_reader (h);
-
-    if (h->request)
-    {
-        ne_request_destroy (h->request);
-        h->request = NULL;
-    }
-
-    if (h->session)
-    {
-        ne_session_destroy (h->session);
-        h->session = NULL;
-    }
-
-    reset_rb (& h->rb);
-
-    if (open_handle (h, newpos) != 0)
-    {
-        _ERROR ("<%p> Error while creating new request!", (void *) h);
-        return -1;
-    }
-
-    /* Things seem to have worked. The next read request will start
-     * the reader thread again. */
-    h->eof = FALSE;
-
-    return 0;
-}
-
-char * neon_vfs_metadata_impl (VFSFile * file, const char * field)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    _DEBUG ("<%p> Field name: %s", h, field);
-
-    if (! strcmp (field, "track-name") && h->icy_metadata.stream_title)
-        return str_to_utf8 (h->icy_metadata.stream_title, -1);
-
-    if (! strcmp (field, "stream-name") && h->icy_metadata.stream_name)
-        return str_to_utf8 (h->icy_metadata.stream_name, -1);
-
-    if (! strcmp (field, "content-type") && h->icy_metadata.stream_contenttype)
-        return str_to_utf8 (h->icy_metadata.stream_contenttype, -1);
-
-    if (! strcmp (field, "content-bitrate"))
-        return int_to_str (h->icy_metadata.stream_bitrate * 1000);
-
-    return NULL;
-}
-
-int64_t neon_vfs_fsize_impl (VFSFile * file)
-{
-    struct neon_handle * h = vfs_get_handle (file);
-
-    if (h->content_length < 0)
-    {
-        _DEBUG ("<%p> Unknown content length", h);
-        return -1;
-    }
-
-    return h->content_start + h->content_length;
-}
-
-static const char * const neon_schemes[] = {"http", "https", NULL};
-
-static VFSConstructor constructor =
-{
-    .vfs_fopen_impl = neon_vfs_fopen_impl,
-    .vfs_fclose_impl = neon_vfs_fclose_impl,
-    .vfs_fread_impl = neon_vfs_fread_impl,
-    .vfs_fwrite_impl = neon_vfs_fwrite_impl,
-    .vfs_fseek_impl = neon_vfs_fseek_impl,
-    .vfs_ftell_impl = neon_vfs_ftell_impl,
-    .vfs_feof_impl = neon_vfs_feof_impl,
-    .vfs_ftruncate_impl = neon_vfs_truncate_impl,
-    .vfs_fsize_impl = neon_vfs_fsize_impl,
-    .vfs_get_metadata_impl = neon_vfs_metadata_impl
-};
-
-AUD_TRANSPORT_PLUGIN
-(
-    .name = N_("Neon HTTP/HTTPS Plugin"),
-    .domain = PACKAGE,
-    .schemes = neon_schemes,
-    .init = neon_plugin_init,
-    .cleanup = neon_plugin_fini,
-    .vtable = & constructor
-)
diff --git a/src/neon/neon.cc b/src/neon/neon.cc
new file mode 100644
index 000000000000..153eba6f4b3b
--- /dev/null
+++ b/src/neon/neon.cc
@@ -0,0 +1,1102 @@
+/*
+ *  A neon HTTP input plugin for Audacious
+ *  Copyright (C) 2007 Ralf Ertzinger
+ *
+ *  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.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+#include <ne_auth.h>
+#include <ne_session.h>
+#include <ne_socket.h>
+#include <ne_redirect.h>
+#include <ne_request.h>
+#include <ne_uri.h>
+#include <ne_utils.h>
+
+#include "cert_verification.h"
+
+#define NEON_NETBLKSIZE     (4096)
+#define NEON_ICY_BUFSIZE    (4096)
+#define NEON_RETRY_COUNT 6
+
+enum FillBufferResult {
+    FILL_BUFFER_SUCCESS,
+    FILL_BUFFER_ERROR,
+    FILL_BUFFER_EOF
+};
+
+enum neon_reader_t {
+    NEON_READER_INIT = 0,
+    NEON_READER_RUN = 1,
+    NEON_READER_ERROR,
+    NEON_READER_EOF,
+    NEON_READER_TERM
+};
+
+struct reader_status
+{
+    bool reading = false;
+    neon_reader_t status = NEON_READER_INIT;
+
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+
+    reader_status ()
+    {
+        pthread_mutex_init (& mutex, nullptr);
+        pthread_cond_init (& cond, nullptr);
+    }
+
+    ~reader_status ()
+    {
+        pthread_mutex_destroy (& mutex);
+        pthread_cond_destroy (& cond);
+    }
+};
+
+struct icy_metadata
+{
+    String stream_name;
+    String stream_title;
+    String stream_url;
+    String stream_contenttype;
+    int stream_bitrate = 0;
+};
+
+static const char * const neon_schemes[] = {"http", "https"};
+
+class NeonTransport : public TransportPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("Neon HTTP/HTTPS Plugin"), PACKAGE};
+
+    constexpr NeonTransport () : TransportPlugin (info, neon_schemes) {}
+
+    bool init ();
+    void cleanup ();
+
+    VFSImpl * fopen (const char * path, const char * mode, String & error);
+};
+
+EXPORT NeonTransport aud_plugin_instance;
+
+bool NeonTransport::init ()
+{
+    int ret = ne_sock_init ();
+
+    if (ret != 0)
+    {
+        AUDERR ("Could not initialize neon library: %d\n", ret);
+        return false;
+    }
+
+    return true;
+}
+
+void NeonTransport::cleanup ()
+{
+    ne_sock_exit ();
+}
+
+class NeonFile : public VFSImpl
+{
+public:
+    NeonFile (const char * url);
+    ~NeonFile ();
+
+    int open_handle (uint64_t startbyte, String * error = nullptr);
+
+protected:
+    int64_t fread (void * ptr, int64_t size, int64_t nmemb);
+    int fseek (int64_t offset, VFSSeekType whence);
+
+    int64_t ftell ();
+    int64_t fsize ();
+    bool feof ();
+
+    int64_t fwrite (const void * ptr, int64_t size, int64_t nmemb);
+    int ftruncate (int64_t length);
+    int fflush ();
+
+    String get_metadata (const char * field);
+
+private:
+    String m_url;               /* The URL, as passed to us */
+    ne_uri m_purl = ne_uri ();  /* The URL, parsed into a structure */
+
+    unsigned char m_redircount = 0;     /* Redirect count for the opened URL */
+    long m_pos = 0;                     /* Current position in the stream (number of last byte delivered to the player) */
+    unsigned long m_content_start = 0;  /* Start position in the stream */
+    long m_content_length = -1;         /* Total content length, counting from content_start, if known. -1 if unknown */
+    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 */
+
+    bool m_eof = false;
+
+    RingBuf<char> m_rb;           /* Ringbuffer for our data */
+    icy_metadata m_icy_metadata;  /* Current ICY metadata */
+
+    ne_session * m_session = nullptr;
+    ne_request * m_request = nullptr;
+
+    pthread_t m_reader;
+    reader_status m_reader_status;
+
+    void kill_reader ();
+    int server_auth (const char * realm, int attempt, char * username, char * password);
+    void handle_headers ();
+    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);
+
+    static int server_auth_callback (void * data, const char * realm, int attempt,
+     char * username, char * password)
+        { return ((NeonFile *) data)->server_auth (realm, attempt, username, password); }
+
+    static void * reader_thread (void * data)
+        { ((NeonFile *) data)->reader (); return nullptr; }
+};
+
+NeonFile::NeonFile (const char * url) :
+    m_url (url)
+{
+    int buffer_kb = aud_get_int (nullptr, "net_buffer_kb");
+    m_rb.alloc (1024 * aud::clamp (buffer_kb, 16, 1024));
+}
+
+NeonFile::~NeonFile ()
+{
+    if (m_reader_status.reading)
+        kill_reader ();
+
+    if (m_request)
+        ne_request_destroy (m_request);
+    if (m_session)
+        ne_session_destroy (m_session);
+
+    ne_uri_free (& m_purl);
+}
+
+static bool neon_strcmp (const char * str, const char * cmp)
+{
+    return ! g_ascii_strncasecmp (str, cmp, strlen (cmp));
+}
+
+static void add_icy (struct icy_metadata * m, const char * name, const char * value)
+{
+    if (neon_strcmp (name, "StreamTitle"))
+    {
+        AUDDBG ("Found StreamTitle: %s\n", value);
+        m->stream_title = String (str_to_utf8 (value, -1));
+    }
+
+    if (neon_strcmp (name, "StreamUrl"))
+    {
+        AUDDBG ("Found StreamUrl: %s\n", value);
+        m->stream_url = String (str_to_utf8 (value, -1));
+    }
+}
+
+static void parse_icy (struct icy_metadata * m, char * metadata, size_t len)
+{
+    enum TagReadState
+    {
+        STATE_READ_NAME,
+        STATE_WAIT_VALUE,
+        STATE_READ_VALUE,
+        STATE_WAIT_NAME,
+    };
+
+    TagReadState state = STATE_READ_NAME;
+
+    char * p = metadata;
+    char * tstart = metadata;
+    size_t pos = 1;
+
+    char name[NEON_ICY_BUFSIZE];
+    char value[NEON_ICY_BUFSIZE];
+
+    name[0] = 0;
+    value[0] = 0;
+
+    while (pos < len && p[0])
+    {
+        switch (state)
+        {
+        case STATE_READ_NAME:
+
+            /* Reading tag name */
+            if (p[0] == '=')
+            {
+                /* End of tag name. */
+                p[0] = 0;
+                g_strlcpy (name, tstart, NEON_ICY_BUFSIZE);
+                AUDDBG ("Found tag name: %s\n", name);
+                state = STATE_WAIT_VALUE;
+            }
+
+            break;
+
+        case STATE_WAIT_VALUE:
+
+            /* Waiting for start of value */
+            if (p[0] == '\'')
+            {
+                /* Leading ' of value */
+                tstart = p + 1;
+                state = STATE_READ_VALUE;
+                value[0] = 0;
+            }
+
+            break;
+
+        case STATE_READ_VALUE:
+
+            /* Reading value */
+            if (p[0] == '\'' && p[1] == ';')
+            {
+                /* End of value */
+                p[0] = 0;
+                g_strlcpy (value, tstart, NEON_ICY_BUFSIZE);
+                AUDDBG ("Found tag value: %s\n", value);
+                add_icy (m, name, value);
+                state = STATE_WAIT_NAME;
+            }
+
+            break;
+
+        case STATE_WAIT_NAME:
+
+            /* Waiting for next tag start */
+            if (p[0] == ';')
+            {
+                /* Next tag name starts after this char */
+                tstart = p + 1;
+                state = STATE_READ_NAME;
+                name[0] = 0;
+                value[0] = 0;
+            }
+
+            break;
+        }
+
+        p ++;
+        pos ++;
+    }
+}
+
+void NeonFile::kill_reader ()
+{
+    AUDDBG ("Signaling reader thread to terminate\n");
+    pthread_mutex_lock (& m_reader_status.mutex);
+    m_reader_status.reading = false;
+    pthread_cond_broadcast (& m_reader_status.cond);
+    pthread_mutex_unlock (& m_reader_status.mutex);
+
+    AUDDBG ("Waiting for reader thread to die...\n");
+    pthread_join (m_reader, nullptr);
+    AUDDBG ("Reader thread has died\n");
+}
+
+int NeonFile::server_auth (const char * realm, int attempt, char * username, char * password)
+{
+    if (! m_purl.userinfo || ! m_purl.userinfo[0])
+    {
+        AUDERR ("Authentication required, but no credentials set\n");
+        return 1;
+    }
+
+    char * * authtok = g_strsplit (m_purl.userinfo, ":", 2);
+
+    if (strlen (authtok[1]) > NE_ABUFSIZ - 1 || strlen (authtok[0]) > NE_ABUFSIZ - 1)
+    {
+        AUDERR ("Username/Password too long\n");
+        g_strfreev (authtok);
+        return 1;
+    }
+
+    g_strlcpy (username, authtok[0], NE_ABUFSIZ);
+    g_strlcpy (password, authtok[1], NE_ABUFSIZ);
+
+    AUDDBG ("Authenticating: Username: %s, Password: %s\n", username, password);
+
+    g_strfreev (authtok);
+
+    return attempt;
+}
+
+void NeonFile::handle_headers ()
+{
+    const char * name;
+    const char * value;
+    void * cursor = nullptr;
+
+    AUDDBG ("Header responses:\n");
+
+    while ((cursor = ne_response_header_iterate (m_request, cursor, & name, & value)))
+    {
+        AUDDBG ("HEADER: %s: %s\n", name, value);
+
+        if (neon_strcmp (name, "accept-ranges"))
+        {
+            /* The server advertises range capability. we need "bytes" */
+            if (strstr (value, "bytes"))
+            {
+                AUDDBG ("server can_ranges\n");
+                m_can_ranges = true;
+            }
+        }
+        else if (neon_strcmp (name, "content-length"))
+        {
+            /* The server sent us the content length. Parse and store. */
+            char * endptr;
+            long len = strtol (value, & endptr, 10);
+
+            if (value[0] && ! endptr[0] && len >= 0)
+            {
+                /* Valid data. */
+                AUDDBG ("Content length as advertised by server: %ld\n", len);
+                m_content_length = len;
+            }
+            else
+                AUDERR ("Invalid content length header: %s\n", value);
+        }
+        else if (neon_strcmp (name, "content-type"))
+        {
+            /* The server sent us a content type. Save it for later */
+            AUDDBG ("Content-Type: %s\n", value);
+            m_icy_metadata.stream_contenttype = String (str_to_utf8 (value, -1));
+        }
+        else if (neon_strcmp (name, "icy-metaint"))
+        {
+            /* The server sent us a ICY metaint header. Parse and store. */
+            char * endptr;
+            long len = strtol (value, & endptr, 10);
+
+            if (value[0] && ! endptr[0] && len > 0)
+            {
+                /* Valid data */
+                AUDDBG ("ICY MetaInt as advertised by server: %ld\n", len);
+                m_icy_metaint = len;
+                m_icy_metaleft = len;
+            }
+            else
+                AUDERR ("Invalid ICY MetaInt header: %s\n", value);
+        }
+        else if (neon_strcmp (name, "icy-name"))
+        {
+            /* The server sent us a ICY name. Save it for later */
+            AUDDBG ("ICY stream name: %s\n", value);
+            m_icy_metadata.stream_name = String (value);
+        }
+        else if (neon_strcmp (name, "icy-br"))
+        {
+            /* The server sent us a bitrate. We might want to use it. */
+            AUDDBG ("ICY bitrate: %d\n", atoi (value));
+            m_icy_metadata.stream_bitrate = atoi (value);
+        }
+    }
+}
+
+static int neon_proxy_auth_cb (void * userdata, const char * realm, int attempt,
+ char * username, char * password)
+{
+    String value = aud_get_str (nullptr, "proxy_user");
+    g_strlcpy (username, value, NE_ABUFSIZ);
+
+    value = aud_get_str (nullptr, "proxy_pass");
+    g_strlcpy (password, value, NE_ABUFSIZ);
+
+    return attempt;
+}
+
+int NeonFile::open_request (uint64_t startbyte, String * error)
+{
+    int ret;
+    const ne_status * status;
+    ne_uri * rediruri;
+
+    if (m_purl.query && * (m_purl.query))
+    {
+        StringBuf tmp = str_concat ({m_purl.path, "?", m_purl.query});
+        m_request = ne_request_create (m_session, "GET", tmp);
+    }
+    else
+        m_request = ne_request_create (m_session, "GET", m_purl.path);
+
+    if (startbyte > 0)
+        ne_print_request_header (m_request, "Range", "bytes=%" PRIu64 "-", startbyte);
+
+    ne_print_request_header (m_request, "Icy-MetaData", "1");
+
+    /* Try to connect to the server. */
+    AUDDBG ("<%p> Connecting...\n", this);
+    ret = ne_begin_request (m_request);
+    status = ne_get_status (m_request);
+    AUDDBG ("<%p> Return: %d, Status: %d\n", this, ret, status->code);
+
+    if (ret == NE_OK)
+    {
+        switch (status->code)
+        {
+        case 401:
+            /* Authorization required. Reconnect to authenticate */
+            AUDDBG ("Reconnecting due to 401\n");
+            ne_end_request (m_request);
+            ret = ne_begin_request (m_request);
+            break;
+
+        case 301:
+        case 302:
+        case 303:
+        case 307:
+            /* Redirect encountered. Reconnect. */
+            ne_end_request (m_request);
+            ret = NE_REDIRECT;
+            break;
+
+        case 407:
+            /* Proxy auth required. Reconnect to authenticate */
+            AUDDBG ("Reconnecting due to 407\n");
+            ne_end_request (m_request);
+            ret = ne_begin_request (m_request);
+            break;
+        }
+    }
+
+    switch (ret)
+    {
+    case NE_OK:
+        if (status->code > 199 && status->code < 300)
+        {
+            /* URL opened OK */
+            AUDDBG ("<%p> URL opened OK\n", this);
+            m_content_start = startbyte;
+            m_pos = startbyte;
+            handle_headers ();
+            return 0;
+        }
+
+        break;
+
+    case NE_REDIRECT:
+        /* We hit a redirect. Handle it. */
+        AUDDBG ("<%p> Redirect encountered\n", this);
+        m_redircount += 1;
+        rediruri = (ne_uri *) ne_redirect_location (m_session);
+        ne_request_destroy (m_request);
+        m_request = nullptr;
+
+        if (! rediruri)
+        {
+            if (error)
+                * error = String (_("Error parsing redirect"));
+
+            AUDERR ("<%p> Could not parse redirect response\n", this);
+            return -1;
+        }
+
+        ne_uri_free (& m_purl);
+        ne_uri_copy (& m_purl, rediruri);
+        return 1;
+    }
+
+    /* Something went wrong. */
+    const char * ne_error = ne_get_error (m_session);
+    if (error)
+        * error = String (ne_error ? ne_error : _("Unknown HTTP error"));
+
+    AUDERR ("<%p> Could not open URL: %d (%d)\n", this, ret, status->code);
+
+    if (ne_error)
+        AUDERR ("<%p> neon error string: %s\n", this, ne_error);
+
+    ne_request_destroy (m_request);
+    m_request = nullptr;
+    return -1;
+}
+
+int NeonFile::open_handle (uint64_t startbyte, String * error)
+{
+    int ret;
+    String proxy_host;
+    int proxy_port = 0;
+
+    bool use_proxy = aud_get_bool (nullptr, "use_proxy");
+    bool use_proxy_auth = aud_get_bool (nullptr, "use_proxy_auth");
+
+    if (use_proxy)
+    {
+        proxy_host = aud_get_str (nullptr, "proxy_host");
+        proxy_port = aud_get_int (nullptr, "proxy_port");
+    }
+
+    m_redircount = 0;
+
+    AUDDBG ("<%p> Parsing URL\n", this);
+
+    if (ne_uri_parse (m_url, & m_purl) != 0)
+    {
+        if (error)
+            * error = String (_("Error parsing URL"));
+
+        AUDERR ("<%p> Could not parse URL '%s'\n", this, (const char *) m_url);
+        return -1;
+    }
+
+    while (m_redircount < 10)
+    {
+        if (! m_purl.port)
+            m_purl.port = ne_uri_defaultport (m_purl.scheme);
+
+        AUDDBG ("<%p> Creating session to %s://%s:%d\n", this,
+         m_purl.scheme, m_purl.host, m_purl.port);
+        m_session = ne_session_create (m_purl.scheme,
+         m_purl.host, m_purl.port);
+        ne_redirect_register (m_session);
+        ne_add_server_auth (m_session, NE_AUTH_BASIC, server_auth_callback, this);
+        ne_set_session_flag (m_session, NE_SESSFLAG_ICYPROTO, 1);
+        ne_set_session_flag (m_session, NE_SESSFLAG_PERSIST, 0);
+        ne_set_connect_timeout (m_session, 10);
+        ne_set_read_timeout (m_session, 10);
+        ne_set_useragent (m_session, "Audacious/" PACKAGE_VERSION);
+
+        if (use_proxy)
+        {
+            AUDDBG ("<%p> Using proxy: %s:%d\n", this, (const char *) proxy_host, proxy_port);
+            ne_session_proxy (m_session, proxy_host, proxy_port);
+
+            if (use_proxy_auth)
+            {
+                AUDDBG ("<%p> Using proxy authentication\n", this);
+                ne_add_proxy_auth (m_session, NE_AUTH_BASIC,
+                 neon_proxy_auth_cb, (void *) this);
+            }
+        }
+
+        if (! strcmp ("https", m_purl.scheme))
+        {
+            ne_ssl_trust_default_ca (m_session);
+            ne_ssl_set_verify (m_session,
+             neon_vfs_verify_environment_ssl_certs, m_session);
+        }
+
+        AUDDBG ("<%p> Creating request\n", this);
+        ret = open_request (startbyte, error);
+
+        if (! ret)
+            return 0;
+
+        if (ret == -1)
+        {
+            ne_session_destroy (m_session);
+            m_session = nullptr;
+            return -1;
+        }
+
+        AUDDBG ("<%p> Following redirect...\n", this);
+        ne_session_destroy (m_session);
+        m_session = nullptr;
+    }
+
+    /* If we get here, our redirect count exceeded */
+    if (error)
+        * error = String (_("Too many redirects"));
+
+    AUDERR ("<%p> Redirect count exceeded for URL %s\n", this, (const char *) m_url);
+    return 1;
+}
+
+FillBufferResult NeonFile::fill_buffer ()
+{
+    char buffer[NEON_NETBLKSIZE];
+    int to_read;
+
+    pthread_mutex_lock (& m_reader_status.mutex);
+    to_read = aud::min (m_rb.space (), NEON_NETBLKSIZE);
+    pthread_mutex_unlock (& m_reader_status.mutex);
+
+    int bsize = ne_read_response_block (m_request, buffer, to_read);
+
+    if (! bsize)
+    {
+        AUDDBG ("<%p> End of file encountered\n", this);
+        return FILL_BUFFER_EOF;
+    }
+
+    if (bsize < 0)
+    {
+        AUDERR ("<%p> Error while reading from the network\n", this);
+        ne_request_destroy (m_request);
+        m_request = nullptr;
+        return FILL_BUFFER_ERROR;
+    }
+
+    AUDDBG ("<%p> Read %d bytes of %d\n", this, bsize, to_read);
+
+    pthread_mutex_lock (& m_reader_status.mutex);
+    m_rb.copy_in (buffer, bsize);
+    pthread_mutex_unlock (& m_reader_status.mutex);
+
+    return FILL_BUFFER_SUCCESS;
+}
+
+void NeonFile::reader ()
+{
+    pthread_mutex_lock (& m_reader_status.mutex);
+
+    while (m_reader_status.reading)
+    {
+        /* Hit the network only if we have more than NEON_NETBLKSIZE of free buffer */
+        if (m_rb.space () > NEON_NETBLKSIZE)
+        {
+            pthread_mutex_unlock (& m_reader_status.mutex);
+
+            FillBufferResult ret = fill_buffer ();
+
+            pthread_mutex_lock (& m_reader_status.mutex);
+
+            /* Wake up main thread if it is waiting. */
+            pthread_cond_broadcast (& m_reader_status.cond);
+
+            if (ret == FILL_BUFFER_ERROR)
+            {
+                AUDERR ("<%p> Error while reading from the network. "
+                        "Terminating reader thread\n", this);
+                m_reader_status.status = NEON_READER_ERROR;
+                pthread_mutex_unlock (& m_reader_status.mutex);
+                return;
+            }
+            else if (ret == FILL_BUFFER_EOF)
+            {
+                AUDDBG ("<%p> EOF encountered while reading from the network. "
+                        "Terminating reader thread\n", this);
+                m_reader_status.status = NEON_READER_EOF;
+                pthread_mutex_unlock (& m_reader_status.mutex);
+                return;
+            }
+        }
+        else
+        {
+            /* Not enough free space in the buffer.
+             * Sleep until the main thread wakes us up. */
+            pthread_cond_wait (& m_reader_status.cond, & m_reader_status.mutex);
+        }
+    }
+
+    AUDDBG ("<%p> Reader thread terminating gracefully\n", this);
+    m_reader_status.status = NEON_READER_TERM;
+    pthread_mutex_unlock (& m_reader_status.mutex);
+}
+
+VFSImpl * NeonTransport::fopen (const char * path, const char * mode, String & error)
+{
+    NeonFile * file = new NeonFile (path);
+
+    AUDDBG ("<%p> Trying to open '%s' with neon\n", file, path);
+
+    if (file->open_handle (0, & error) != 0)
+    {
+        AUDERR ("<%p> Could not open URL\n", file);
+        delete file;
+        return nullptr;
+    }
+
+    return file;
+}
+
+int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb)
+{
+    if (! m_request)
+    {
+        AUDERR ("<%p> No request to read from, seek gone wrong?\n", this);
+        return 0;
+    }
+
+    if (! size || ! nmemb || m_eof)
+        return 0;
+
+    /* If the buffer is empty, wait for the reader thread to fill it. */
+    pthread_mutex_lock (& m_reader_status.mutex);
+
+    for (int retries = 0; retries < NEON_RETRY_COUNT; retries ++)
+    {
+        if (m_rb.len () / size > 0 || ! m_reader_status.reading ||
+         m_reader_status.status != NEON_READER_RUN)
+            break;
+
+        pthread_cond_broadcast (& m_reader_status.cond);
+        pthread_cond_wait (& m_reader_status.cond, & m_reader_status.mutex);
+    }
+
+    pthread_mutex_unlock (& m_reader_status.mutex);
+
+    if (! m_reader_status.reading)
+    {
+        if (m_reader_status.status != NEON_READER_EOF || m_content_length != -1)
+        {
+            /* There is no reader thread yet. Read the first bytes from
+             * the network ourselves, and then fire up the reader thread
+             * to keep the buffer filled up. */
+            AUDDBG ("<%p> Doing initial buffer fill\n", this);
+            FillBufferResult ret = fill_buffer ();
+
+            if (ret == FILL_BUFFER_ERROR)
+            {
+                AUDERR ("<%p> Error while reading from the network\n", this);
+                return 0;
+            }
+
+            /* We have some data in the buffer now.
+             * Start the reader thread if we did not reach EOF during
+             * the initial fill */
+            pthread_mutex_lock (& m_reader_status.mutex);
+
+            if (ret == FILL_BUFFER_SUCCESS)
+            {
+                m_reader_status.reading = true;
+                AUDDBG ("<%p> Starting reader thread\n", this);
+                pthread_create (& m_reader, nullptr, reader_thread, this);
+                m_reader_status.status = NEON_READER_RUN;
+            }
+            else if (ret == FILL_BUFFER_EOF)
+            {
+                AUDDBG ("<%p> No reader thread needed (stream has reached EOF during fill)\n", this);
+                m_reader_status.reading = false;
+                m_reader_status.status = NEON_READER_EOF;
+            }
+
+            pthread_mutex_unlock (& m_reader_status.mutex);
+        }
+    }
+    else
+    {
+        /* There already is a reader thread. Look if it is in good shape. */
+        pthread_mutex_lock (& m_reader_status.mutex);
+
+        switch (m_reader_status.status)
+        {
+        case NEON_READER_INIT:
+        case NEON_READER_RUN:
+            /* All is well, nothing to be done. */
+            break;
+
+        case NEON_READER_ERROR:
+            /* A reader error happened. Log it, and treat it like an EOF
+             * condition, by falling through to the NEON_READER_EOF codepath. */
+            AUDDBG ("<%p> NEON_READER_ERROR happened. Terminating reader thread and marking EOF.\n", this);
+            m_reader_status.status = NEON_READER_EOF;
+            pthread_mutex_unlock (& m_reader_status.mutex);
+
+            if (m_reader_status.reading)
+                kill_reader ();
+
+            pthread_mutex_lock (& m_reader_status.mutex);
+
+        case NEON_READER_EOF:
+            /* If there still is data in the buffer, carry on.
+             * If not, terminate the reader thread and return 0. */
+            if (! m_rb.len ())
+            {
+                AUDDBG ("<%p> Reached end of stream\n", this);
+                pthread_mutex_unlock (& m_reader_status.mutex);
+
+                if (m_reader_status.reading)
+                    kill_reader ();
+
+                m_eof = true;
+                return 0;
+            }
+
+            break;
+
+        case NEON_READER_TERM:
+            /* The reader thread terminated gracefully, most likely on our own request.
+             * We should not get here. */
+            g_warn_if_reached ();
+            pthread_mutex_unlock (& m_reader_status.mutex);
+            return 0;
+        }
+
+        pthread_mutex_unlock (& m_reader_status.mutex);
+    }
+
+    /* Deliver data from the buffer */
+    pthread_mutex_lock (& m_reader_status.mutex);
+
+    if (! m_rb.len ())
+    {
+        /* The buffer is still empty, we can deliver no data! */
+        AUDERR ("<%p> Buffer still underrun, fatal.\n", this);
+        pthread_mutex_unlock (& m_reader_status.mutex);
+        return 0;
+    }
+
+    int64_t belem = m_rb.len () / size;
+
+    if (m_icy_metaint)
+    {
+        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)
+            {
+                /* 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;
+            }
+            else
+            {
+                /* 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);
+                m_icy_metaleft = m_icy_metaint;
+            }
+        }
+
+        /* The maximum number of bytes we can deliver is determined
+         * by the number of bytes left until the next metadata announcement */
+        belem = aud::min ((int64_t) m_rb.len (), m_icy_metaleft) / size;
+    }
+
+    nmemb = aud::min (belem, nmemb);
+    m_rb.move_out ((char *) ptr, nmemb * size);
+
+    /* Signal the network thread to continue reading */
+    if (m_reader_status.status == NEON_READER_EOF)
+    {
+        if (! m_rb.len ())
+        {
+            AUDDBG ("<%p> stream EOF reached and buffer empty\n", this);
+            m_eof = true;
+        }
+    }
+    else
+        pthread_cond_broadcast (& m_reader_status.cond);
+
+    pthread_mutex_unlock (& m_reader_status.mutex);
+
+    m_pos += nmemb * size;
+    m_icy_metaleft -= nmemb * size;
+
+    return nmemb;
+}
+
+/* try_fread will do only a partial read if the buffer underruns, so we
+ * 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;
+
+    AUDDBG ("<%p> fread %d x %d\n", this, (int) size, (int) count);
+
+    while (count > 0 && (part = try_fread (buffer, size, count)) > 0)
+    {
+        buffer = (char *) buffer + size * part;
+        total += part;
+        count -= part;
+    }
+
+    AUDDBG ("<%p> fread = %d\n", this, (int) total);
+
+    return total;
+}
+
+int64_t NeonFile::fwrite (const void * ptr, int64_t size, int64_t nmemb)
+{
+    AUDERR ("<%p> NOT IMPLEMENTED\n", this);
+
+    return 0;
+}
+
+int64_t NeonFile::ftell ()
+{
+    AUDDBG ("<%p> Current file position: %ld\n", this, m_pos);
+
+    return m_pos;
+}
+
+bool NeonFile::feof ()
+{
+    AUDDBG ("<%p> EOF status: %s\n", this, m_eof ? "true" : "false");
+
+    return m_eof;
+}
+
+int NeonFile::ftruncate (int64_t size)
+{
+    AUDERR ("<%p> NOT IMPLEMENTED\n", this);
+
+    return 0;
+}
+
+int NeonFile::fflush ()
+{
+    return 0; /* no-op */
+}
+
+int NeonFile::fseek (int64_t offset, VFSSeekType whence)
+{
+    AUDDBG ("<%p> Seek requested: offset %ld, whence %d\n", this, offset, whence);
+
+    /* To seek to a non-zero offset, two things must be satisfied:
+     * - the server must advertise a content-length
+     * - the server must advertise accept-ranges: bytes */
+    if ((whence != VFS_SEEK_SET || offset) && (m_content_length < 0 || ! m_can_ranges))
+    {
+        AUDDBG ("<%p> Can not seek due to server restrictions\n", this);
+        return -1;
+    }
+
+    int64_t content_length = m_content_length + m_content_start;
+    int64_t newpos;
+
+    switch (whence)
+    {
+    case VFS_SEEK_SET:
+        newpos = offset;
+        break;
+
+    case VFS_SEEK_CUR:
+        newpos = m_pos + offset;
+        break;
+
+    case VFS_SEEK_END:
+        if (offset == 0)
+        {
+            m_pos = content_length;
+            m_eof = true;
+            return 0;
+        }
+
+        newpos = content_length + offset;
+        break;
+
+    default:
+        AUDERR ("<%p> Invalid whence specified\n", this);
+        return -1;
+    }
+
+    AUDDBG ("<%p> Position to seek to: %ld, current: %ld\n", this, newpos, m_pos);
+
+    if (newpos < 0)
+    {
+        AUDERR ("<%p> Can not seek before start of stream\n", this);
+        return -1;
+    }
+
+    if (newpos && newpos >= content_length)
+    {
+        AUDERR ("<%p> Can not seek beyond end of stream (%ld >= %ld)\n",
+         this, (long) newpos, (long) content_length);
+        return -1;
+    }
+
+    if (newpos == m_pos)
+        return 0;
+
+    /* To seek to the new position we have to
+     * - stop the current reader thread, if there is one
+     * - destroy the current request
+     * - dump all data currently in the ringbuffer
+     * - create a new request starting at newpos */
+    if (m_reader_status.reading)
+        kill_reader ();
+
+    if (m_request)
+    {
+        ne_request_destroy (m_request);
+        m_request = nullptr;
+    }
+
+    if (m_session)
+    {
+        ne_session_destroy (m_session);
+        m_session = nullptr;
+    }
+
+    m_rb.discard ();
+
+    if (open_handle (newpos) != 0)
+    {
+        AUDERR ("<%p> Error while creating new request!\n", this);
+        return -1;
+    }
+
+    /* Things seem to have worked. The next read request will start
+     * the reader thread again. */
+    m_eof = false;
+
+    return 0;
+}
+
+String NeonFile::get_metadata (const char * field)
+{
+    AUDDBG ("<%p> Field name: %s\n", this, field);
+
+    if (! strcmp (field, "track-name") && m_icy_metadata.stream_title)
+        return m_icy_metadata.stream_title;
+
+    if (! strcmp (field, "stream-name") && m_icy_metadata.stream_name)
+        return m_icy_metadata.stream_name;
+
+    if (! strcmp (field, "content-type") && m_icy_metadata.stream_contenttype)
+        return m_icy_metadata.stream_contenttype;
+
+    if (! strcmp (field, "content-bitrate"))
+        return String (int_to_str (m_icy_metadata.stream_bitrate * 1000));
+
+    return String ();
+}
+
+int64_t NeonFile::fsize ()
+{
+    if (m_content_length < 0)
+    {
+        AUDDBG ("<%p> Unknown content length\n", this);
+        return -1;
+    }
+
+    return m_content_start + m_content_length;
+}
diff --git a/src/neon/neon.h b/src/neon/neon.h
deleted file mode 100644
index 02f178959911..000000000000
--- a/src/neon/neon.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  A neon HTTP input plugin for Audacious
- *  Copyright (C) 2007 Ralf Ertzinger
- *
- *  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 _NEON_PLUGIN_H
-#define _NEON_PLUGIN_H
-
-#include <glib.h>
-#include <pthread.h>
-
-#include <libaudcore/vfs.h>
-#include <ne_session.h>
-#include <ne_request.h>
-#include <ne_uri.h>
-
-#include "rb.h"
-
-typedef enum
-{
-    NEON_READER_INIT=0,
-    NEON_READER_RUN=1,
-    NEON_READER_ERROR,
-    NEON_READER_EOF,
-    NEON_READER_TERM
-} neon_reader_t;
-
-struct reader_status
-{
-    pthread_mutex_t mutex;
-    pthread_cond_t cond;
-    bool_t reading;
-    neon_reader_t status;
-};
-
-struct icy_metadata
-{
-    char * stream_name;
-    char * stream_title;
-    char * stream_url;
-    char * stream_contenttype;
-    int   stream_bitrate;
-};
-
-struct neon_handle
-{
-    char * url;                        /* The URL, as passed to us */
-    ne_uri * purl;                      /* The URL, parsed into a structure */
-    struct ringbuf rb;                  /* Ringbuffer for our data */
-    unsigned char redircount;                  /* Redirect count for the opened URL */
-    long pos;                           /* Current position in the stream (number of last byte delivered to the player) */
-    gulong content_start;               /* Start position in the stream */
-    long content_length;                /* Total content length, counting from content_start, if known. -1 if unknown */
-    bool_t can_ranges;                /* TRUE if the webserver advertised accept-range: bytes */
-    gulong icy_metaint;                 /* Interval in which the server will send metadata announcements. 0 if no announcments */
-    gulong icy_metaleft;                /* Bytes left until the next metadata block */
-    struct icy_metadata icy_metadata;   /* Current ICY metadata */
-    ne_session * session;
-    ne_request * request;
-    pthread_t reader;
-    struct reader_status reader_status;
-    bool_t eof;
-};
-
-#endif
diff --git a/src/neon/rb.c b/src/neon/rb.c
deleted file mode 100644
index 113bffb1aa96..000000000000
--- a/src/neon/rb.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *  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.
- */
-
-/*
- * Ringbuffer implementation
- *
- * GPL
- */
-#include <assert.h>
-#include <string.h>
-#include <glib.h>
-
-#include "rb.h"
-
-/*
- * Reset a ringbuffer structure (i.e. discard all data inside of it)
- */
-void reset_rb (struct ringbuf * rb)
-{
-    _RB_LOCK (rb->lock);
-
-    rb->wp = rb->buf;
-    rb->rp = rb->buf;
-    rb->free = rb->size;
-    rb->used = 0;
-    rb->end = rb->buf + (rb->size - 1);
-
-    _RB_UNLOCK (rb->lock);
-}
-
-/*
- * Initialize a ringbuffer structure (including memory allocation.
- * The mutex to be used is passed in the function call.
- * The mutex must not be held while calling this function.
- */
-void init_rb_with_lock (struct ringbuf * rb, unsigned size, rb_mutex_t * lock)
-{
-    assert (size > 0);
-
-    rb->lock = lock;
-    rb->buf = g_malloc (size);
-    rb->size = size;
-    reset_rb (rb);
-}
-
-/*
- * Write size bytes at buf into the ringbuffer.
- */
-void write_rb (struct ringbuf * rb, void * buf, unsigned size)
-{
-    _RB_LOCK (rb->lock);
-
-    assert (size <= rb->free);
-
-    int endfree = (rb->end - rb->wp) + 1;
-
-    if (endfree < size)
-    {
-        /* There is enough space in the buffer, but not in one piece.
-         * We need to split the copy into two parts. */
-        memcpy (rb->wp, buf, endfree);
-        memcpy (rb->buf, (char *) buf + endfree, size - endfree);
-        rb->wp = rb->buf + (size-endfree);
-    }
-    else if (endfree > size)
-    {
-        /* There is more space than needed at the end */
-        memcpy (rb->wp, buf, size);
-        rb->wp += size;
-    }
-    else
-    {
-        /* There is exactly the space needed at the end.
-         * We need to wrap around the read pointer. */
-        memcpy (rb->wp, buf, size);
-        rb->wp = rb->buf;
-    }
-
-    rb->free -= size;
-    rb->used += size;
-
-    _RB_UNLOCK (rb->lock);
-}
-
-/*
- * Read size byes from buffer into buf.
- * Return -1 on error (not enough data in buffer)
- */
-int read_rb (struct ringbuf * rb, void * buf, unsigned size)
-{
-    _RB_LOCK (rb->lock);
-    int ret = read_rb_locked (rb, buf, size);
-    _RB_UNLOCK (rb->lock);
-
-    return ret;
-}
-
-/*
- * Read size bytes from buffer into buf, assuming the buffer lock is already held.
- * Return -1 on error (not enough data in buffer)
- */
-int read_rb_locked (struct ringbuf * rb, void * buf, unsigned size)
-{
-    if (rb->used < size)
-    {
-        /* Not enough bytes in buffer */
-        return -1;
-    }
-
-    if (rb->rp < rb->wp)
-    {
-        /* Read pointer is behind write pointer, all the data is available in one chunk */
-        memcpy (buf, rb->rp, size);
-        rb->rp += size;
-    }
-    else
-    {
-        /* Read pointer is before write pointer */
-        int endused = (rb->end - rb->rp) +1;
-
-        if (size < endused)
-        {
-            /* Data is available in one chunk */
-            memcpy (buf, rb->rp, size);
-            rb->rp += size;
-        }
-        else
-        {
-            /* There is enough data in the buffer, but it is fragmented. */
-            memcpy (buf, rb->rp, endused);
-            memcpy ((char *) buf + endused, rb->buf, size - endused);
-            rb->rp = rb->buf + (size-endused);
-        }
-    }
-
-    rb->free += size;
-    rb->used -= size;
-
-    return 0;
-}
-
-/*
- * Return the amount of free space currently in the rb
- */
-unsigned free_rb (struct ringbuf * rb)
-{
-    _RB_LOCK (rb->lock);
-    unsigned f = free_rb_locked (rb);
-    _RB_UNLOCK (rb->lock);
-
-    return f;
-}
-
-/*
- * Return the amount of free space currently in the rb.
- * Assume the rb lock is already being held.
- */
-unsigned free_rb_locked (struct ringbuf * rb)
-{
-    return rb->free;
-}
-
-/*
- * Return the amount of used space currently in the rb
- */
-unsigned used_rb (struct ringbuf * rb)
-{
-    _RB_LOCK (rb->lock);
-    unsigned u = used_rb_locked (rb);
-    _RB_UNLOCK (rb->lock);
-
-    return u;
-}
-
-/*
- * Return the amount of used space currently in the rb.
- * Assume the rb lock is already being held.
- */
-unsigned used_rb_locked (struct ringbuf * rb)
-{
-    return rb->used;
-}
-
-/*
- * destroy a ringbuffer
- */
-void destroy_rb (struct ringbuf * rb)
-{
-    g_free (rb->buf);
-}
diff --git a/src/neon/rb.h b/src/neon/rb.h
deleted file mode 100644
index 23512cd7d425..000000000000
--- a/src/neon/rb.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  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 _RB_H
-#define _RB_H
-
-#include <pthread.h>
-
-typedef pthread_mutex_t rb_mutex_t;
-
-#define _RB_LOCK(L) pthread_mutex_lock (L)
-#define _RB_UNLOCK(L) pthread_mutex_unlock (L)
-
-struct ringbuf
-{
-    rb_mutex_t * lock;
-    char * buf;
-    char * end;
-    char * wp;
-    char * rp;
-    unsigned free;
-    unsigned used;
-    unsigned size;
-};
-
-void init_rb_with_lock (struct ringbuf * rb, unsigned size, rb_mutex_t * lock);
-void write_rb (struct ringbuf * rb, void * buf, unsigned size);
-int read_rb (struct ringbuf * rb, void * buf, unsigned size);
-int read_rb_locked (struct ringbuf * rb, void * buf, unsigned size);
-void reset_rb (struct ringbuf * rb);
-unsigned free_rb (struct ringbuf * rb);
-unsigned free_rb_locked (struct ringbuf * rb);
-unsigned used_rb (struct ringbuf * rb);
-unsigned used_rb_locked (struct ringbuf * rb);
-void destroy_rb (struct ringbuf * rb);
-
-#endif
diff --git a/src/notify/Makefile b/src/notify/Makefile
index 36d2fbaebe7a..82f1476e8fc9 100644
--- a/src/notify/Makefile
+++ b/src/notify/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = notify${PLUGIN_SUFFIX}
 
-SRCS = event.c notify.c osd.c
+SRCS = event.cc notify.cc osd.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${NOTIFY_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += ${GTK_LIBS} ${NOTIFY_LIBS}
+LIBS += ${GTK_LIBS} ${NOTIFY_LIBS} -laudgui
diff --git a/src/notify/event.c b/src/notify/event.c
deleted file mode 100644
index 9e613be3f9a9..000000000000
--- a/src/notify/event.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * event.c
- *
- * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
- * Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "event.h"
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/playlist.h>
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "osd.h"
-
-static char * last_title = NULL, * last_message = NULL; /* pooled */
-static GdkPixbuf * last_pixbuf = NULL;
-
-static void clear_cache (void)
-{
-    str_unref (last_title);
-    last_title = NULL;
-    str_unref (last_message);
-    last_message = NULL;
-
-    if (last_pixbuf)
-    {
-        g_object_unref (last_pixbuf);
-        last_pixbuf = NULL;
-    }
-}
-
-static bool_t get_album_art (void)
-{
-    if (last_pixbuf)
-        return FALSE;
-
-    last_pixbuf = audgui_pixbuf_request_current ();
-    if (! last_pixbuf)
-        return FALSE;
-
-    audgui_pixbuf_scale_within (& last_pixbuf, 96);
-    return TRUE;
-}
-
-static void show_stopped (void)
-{
-    osd_show (_("Stopped"), _("Audacious is not playing."), "audacious", NULL);
-}
-
-static void show_playing (void)
-{
-    if (last_title && last_message)
-        osd_show (last_title, last_message, "audio-x-generic", last_pixbuf);
-}
-
-static void playback_update (void)
-{
-    if (! aud_drct_get_playing () || ! aud_drct_get_ready ())
-        return;
-
-    int list = aud_playlist_get_playing ();
-    int entry = aud_playlist_get_position (list);
-
-    char * title, * artist, * album;
-    aud_playlist_entry_describe (list, entry, & title, & artist, & album, FALSE);
-
-    char * message;
-    if (artist)
-    {
-        if (album)
-            message = str_printf ("%s\n%s", artist, album);
-        else
-            message = str_ref (artist);
-    }
-    else if (album)
-        message = str_ref (album);
-    else
-        message = str_get ("");
-
-    str_unref (artist);
-    str_unref (album);
-
-    if (str_equal (title, last_title) && str_equal (message, last_message))
-    {
-        str_unref (title);
-        str_unref (message);
-        return;
-    }
-
-    str_unref (last_title);
-    last_title = title;
-    str_unref (last_message);
-    last_message = message;
-
-    get_album_art ();
-    show_playing ();
-}
-
-static void art_ready (void)
-{
-    if (aud_drct_get_playing () && get_album_art ())
-        show_playing ();
-}
-
-static void playback_paused (void)
-{
-    if (aud_get_bool ("notify", "resident"))
-        show_playing ();
-}
-
-static void playback_stopped (void)
-{
-    clear_cache ();
-
-    if (aud_get_bool ("notify", "resident"))
-        show_stopped ();
-}
-
-static void force_show (void)
-{
-    if (aud_drct_get_playing ())
-        show_playing ();
-    else
-        show_stopped ();
-}
-
-void event_init (void)
-{
-    if (aud_drct_get_playing ())
-        playback_update ();
-    else
-        playback_stopped ();
-
-    hook_associate ("playback begin", (HookFunction) clear_cache, NULL);
-    hook_associate ("playback ready", (HookFunction) playback_update, NULL);
-    hook_associate ("playlist update", (HookFunction) playback_update, NULL);
-    hook_associate ("current art ready", (HookFunction) art_ready, NULL);
-    hook_associate ("playback pause", (HookFunction) playback_paused, NULL);
-    hook_associate ("playback unpause", (HookFunction) playback_paused, NULL);
-    hook_associate ("playback stop", (HookFunction) playback_stopped, NULL);
-
-    hook_associate ("aosd toggle", (HookFunction) force_show, NULL);
-}
-
-void event_uninit (void)
-{
-    hook_dissociate ("playback begin", (HookFunction) clear_cache);
-    hook_dissociate ("playback ready", (HookFunction) playback_update);
-    hook_dissociate ("playlist update", (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);
-
-    hook_dissociate ("aosd toggle", (HookFunction) force_show);
-
-    clear_cache ();
-    osd_hide ();
-}
diff --git a/src/notify/event.cc b/src/notify/event.cc
new file mode 100644
index 000000000000..7134c87777e0
--- /dev/null
+++ b/src/notify/event.cc
@@ -0,0 +1,162 @@
+/*
+ * event.c
+ *
+ * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
+ * Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "event.h"
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+#include "osd.h"
+
+static String last_title, last_message;
+static GdkPixbuf * last_pixbuf = nullptr;
+
+static void clear_cache (void)
+{
+    last_title = String ();
+    last_message = String ();
+
+    if (last_pixbuf)
+    {
+        g_object_unref (last_pixbuf);
+        last_pixbuf = nullptr;
+    }
+
+    osd_hide ();
+}
+
+static gboolean get_album_art (void)
+{
+    if (last_pixbuf)
+        return FALSE;
+
+    last_pixbuf = audgui_pixbuf_request_current ();
+    if (! last_pixbuf)
+        return FALSE;
+
+    audgui_pixbuf_scale_within (& last_pixbuf, 96);
+    return TRUE;
+}
+
+static void show_stopped (void)
+{
+    osd_show (_("Stopped"), _("Audacious is not playing."), "audacious", nullptr);
+}
+
+static void show_playing (void)
+{
+    if (last_title && last_message)
+        osd_show (last_title, last_message, "audio-x-generic", last_pixbuf);
+}
+
+static void playback_update (void)
+{
+    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);
+
+    String message;
+    if (artist)
+    {
+        if (album && aud_get_bool ("notify", "album"))
+            message = String (str_printf ("%s\n%s", (const char *) artist, (const char *) album));
+        else
+            message = artist;
+    }
+    else if (album)
+        message = album;
+    else
+        message = String ("");
+
+    if (title == last_title && message == last_message)
+        return;
+
+    last_title = title;
+    last_message = message;
+
+    get_album_art ();
+    show_playing ();
+}
+
+static void art_ready (void)
+{
+    if (aud_drct_get_playing () && get_album_art ())
+        show_playing ();
+}
+
+static void playback_paused (void)
+{
+    if (aud_get_bool ("notify", "resident"))
+        show_playing ();
+}
+
+static void playback_stopped (void)
+{
+    clear_cache ();
+
+    if (aud_get_bool ("notify", "resident"))
+        show_stopped ();
+}
+
+static void force_show (void)
+{
+    if (aud_drct_get_playing ())
+        show_playing ();
+    else
+        show_stopped ();
+}
+
+void event_init (void)
+{
+    if (aud_drct_get_ready ())
+        playback_update ();
+    else
+        playback_stopped ();
+
+    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);
+
+    hook_associate ("aosd toggle", (HookFunction) force_show, nullptr);
+}
+
+void event_uninit (void)
+{
+    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);
+
+    hook_dissociate ("aosd toggle", (HookFunction) force_show);
+
+    clear_cache ();
+}
diff --git a/src/notify/notify.c b/src/notify/notify.c
deleted file mode 100644
index 3b2193784eed..000000000000
--- a/src/notify/notify.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * notify.c
- *
- * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
- * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <gtk/gtk.h>
-
-#include <libnotify/notify.h>
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <audacious/misc.h>
-
-#include "event.h"
-
-static const char plugin_about[] =
- N_("Desktop Notifications Plugin for Audacious\n"
-    "Copyright (C) 2010 Maximilian Bogner\n"
-    "Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n\n"
-    "This plugin is free software: you can redistribute it and/or modify "
-    "it under the terms of the GNU General Public License as published by "
-    "the Free Software Foundation, either version 3 of the License, or "
-    "(at your option) any later version.\n\n"
-    "This plugin is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.");
-
-static const char * const notify_defaults[] = {
- "actions", "TRUE",
- "resident", "FALSE",
- NULL
-};
-
-static bool_t plugin_init (void)
-{
-    aud_config_set_defaults ("notify", notify_defaults);
-
-    if (! notify_init ("Audacious"))
-        return FALSE;
-
-    event_init();
-    return TRUE;
-}
-
-static void plugin_cleanup (void)
-{
-    event_uninit ();
-    notify_uninit ();
-}
-
-static void plugin_reinit (void)
-{
-    event_uninit ();
-    event_init ();
-}
-
-static const PreferencesWidget prefs_widgets[] = {
- {WIDGET_CHK_BTN, N_("Show playback controls"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "actions",
-  .callback = plugin_reinit},
- {WIDGET_CHK_BTN, N_("Always show notification"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "resident",
-  .callback = plugin_reinit}
-};
-
-static const PluginPreferences plugin_prefs = {
- .widgets = prefs_widgets,
- .n_widgets = ARRAY_LEN (prefs_widgets)
-};
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Desktop Notifications"),
-    .domain = PACKAGE,
-    .about_text = plugin_about,
-    .prefs = & plugin_prefs,
-    .init = plugin_init,
-    .cleanup = plugin_cleanup
-)
diff --git a/src/notify/notify.cc b/src/notify/notify.cc
new file mode 100644
index 000000000000..ac37654d07d7
--- /dev/null
+++ b/src/notify/notify.cc
@@ -0,0 +1,118 @@
+/*
+ * notify.c
+ *
+ * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
+ * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+
+#include <libnotify/notify.h>
+
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/libaudgui.h>
+
+#include "event.h"
+
+class NotifyPlugin : public GeneralPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Desktop Notifications"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr NotifyPlugin () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+
+private:
+    static void reinit ();
+};
+
+EXPORT NotifyPlugin aud_plugin_instance;
+
+const char NotifyPlugin::about[] =
+ N_("Desktop Notifications Plugin for Audacious\n"
+    "Copyright (C) 2010 Maximilian Bogner\n"
+    "Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n\n"
+    "This plugin is free software: you can redistribute it and/or modify "
+    "it under the terms of the GNU General Public License as published by "
+    "the Free Software Foundation, either version 3 of the License, or "
+    "(at your option) any later version.\n\n"
+    "This plugin is distributed in the hope that 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, see <http://www.gnu.org/licenses/>.");
+
+const char * const NotifyPlugin::defaults[] = {
+ "actions", "TRUE",
+ "resident", "FALSE",
+ "album", "TRUE",
+ nullptr
+};
+
+bool NotifyPlugin::init ()
+{
+    if (aud_get_mainloop_type () != MainloopType::GLib)
+        return false;
+
+    aud_config_set_defaults ("notify", defaults);
+
+    if (! notify_init ("Audacious"))
+        return false;
+
+    audgui_init ();
+    event_init ();
+    return true;
+}
+
+void NotifyPlugin::cleanup ()
+{
+    event_uninit ();
+    audgui_cleanup ();
+    notify_uninit ();
+}
+
+void NotifyPlugin::reinit ()
+{
+    event_uninit ();
+    event_init ();
+}
+
+const PreferencesWidget NotifyPlugin::widgets[] = {
+    WidgetCheck (N_("Show playback controls"),
+        WidgetBool ("notify", "actions", reinit)),
+    WidgetCheck (N_("Always show notification"),
+        WidgetBool ("notify", "resident", reinit)),
+    WidgetCheck (N_("Include album name in notification"),
+        WidgetBool ("notify", "album", reinit))
+};
+
+const PluginPreferences NotifyPlugin::prefs = {{widgets}};
diff --git a/src/notify/osd.c b/src/notify/osd.c
deleted file mode 100644
index ca7448fc2f74..000000000000
--- a/src/notify/osd.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * osd.c
- *
- * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
- * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "osd.h"
-
-#include <libnotify/notify.h>
-
-#include <audacious/i18n.h>
-#include <audacious/drct.h>
-#include <audacious/misc.h>
-
-static void show_cb (void)
-{
-    aud_interface_show (TRUE);
-}
-
-static void osd_setup (NotifyNotification *notification)
-{
-    bool_t 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, "resident", g_variant_new_boolean (resident));
-    notify_notification_set_hint (notification, "transient", g_variant_new_boolean (! resident));
-
-    notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
-    notify_notification_set_timeout (notification, resident ?
-     NOTIFY_EXPIRES_NEVER : NOTIFY_EXPIRES_DEFAULT);
-}
-
-void osd_setup_buttons (NotifyNotification *notification)
-{
-    notify_notification_clear_actions (notification);
-
-    if (! aud_get_bool ("notify", "actions"))
-        return;
-
-    notify_notification_add_action (notification, "default", _("Show"),
-     NOTIFY_ACTION_CALLBACK (show_cb), NULL, NULL);
-
-    bool_t playing = aud_drct_get_playing ();
-    bool_t paused = aud_drct_get_paused ();
-
-    if (playing && ! paused)
-        notify_notification_add_action (notification, "media-playback-pause",
-         _("Pause"), NOTIFY_ACTION_CALLBACK (aud_drct_pause), NULL, NULL);
-    else
-        notify_notification_add_action (notification, "media-playback-start",
-         _("Play"), NOTIFY_ACTION_CALLBACK (aud_drct_play), NULL, NULL);
-
-    if (playing)
-        notify_notification_add_action (notification, "media-skip-forward",
-         _("Next"), NOTIFY_ACTION_CALLBACK (aud_drct_pl_next), NULL, NULL);
-}
-
-static NotifyNotification * notification = NULL;
-
-void osd_show (const char * title, const char * _message, const char * icon,
- GdkPixbuf * pixbuf)
-{
-    char * message = g_markup_escape_text (_message, -1);
-
-    if (pixbuf)
-        icon = NULL;
-
-    if (notification)
-        notify_notification_update (notification, title, message, icon);
-    else
-    {
-        notification = notify_notification_new (title, message, icon);
-        osd_setup (notification);
-    }
-
-    if (pixbuf)
-        notify_notification_set_image_from_pixbuf (notification, pixbuf);
-
-    osd_setup_buttons (notification);
-    notify_notification_show (notification, NULL);
-
-    g_free (message);
-}
-
-void osd_hide (void)
-{
-    if (! notification)
-        return;
-
-    notify_notification_close (notification, NULL);
-    g_object_unref (notification);
-    notification = NULL;
-}
diff --git a/src/notify/osd.cc b/src/notify/osd.cc
new file mode 100644
index 000000000000..d2ebfe24680a
--- /dev/null
+++ b/src/notify/osd.cc
@@ -0,0 +1,111 @@
+/*
+ * osd.c
+ *
+ * Copyright (C) 2010 Maximilian Bogner <max at mbogner.de>
+ * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "osd.h"
+
+#include <libnotify/notify.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/runtime.h>
+
+static void show_cb (void)
+{
+    aud_ui_show (TRUE);
+}
+
+static void osd_setup (NotifyNotification *notification)
+{
+    gboolean 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, "resident", g_variant_new_boolean (resident));
+    notify_notification_set_hint (notification, "transient", g_variant_new_boolean (! resident));
+
+    notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+    notify_notification_set_timeout (notification, resident ?
+     NOTIFY_EXPIRES_NEVER : NOTIFY_EXPIRES_DEFAULT);
+}
+
+void osd_setup_buttons (NotifyNotification *notification)
+{
+    notify_notification_clear_actions (notification);
+
+    if (! aud_get_bool ("notify", "actions"))
+        return;
+
+    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 ();
+
+    if (playing && ! paused)
+        notify_notification_add_action (notification, "media-playback-pause",
+         _("Pause"), NOTIFY_ACTION_CALLBACK (aud_drct_pause), nullptr, nullptr);
+    else
+        notify_notification_add_action (notification, "media-playback-start",
+         _("Play"), NOTIFY_ACTION_CALLBACK (aud_drct_play), nullptr, nullptr);
+
+    if (playing)
+        notify_notification_add_action (notification, "media-skip-forward",
+         _("Next"), NOTIFY_ACTION_CALLBACK (aud_drct_pl_next), nullptr, nullptr);
+}
+
+static NotifyNotification * notification = nullptr;
+
+void osd_show (const char * title, const char * _message, const char * icon,
+ GdkPixbuf * pixbuf)
+{
+    char * message = g_markup_escape_text (_message, -1);
+
+    if (pixbuf)
+        icon = nullptr;
+
+    if (notification)
+        notify_notification_update (notification, title, message, icon);
+    else
+    {
+        notification = notify_notification_new (title, message, icon);
+        osd_setup (notification);
+    }
+
+    if (pixbuf)
+        notify_notification_set_image_from_pixbuf (notification, pixbuf);
+
+    osd_setup_buttons (notification);
+    notify_notification_show (notification, nullptr);
+
+    g_free (message);
+}
+
+void osd_hide (void)
+{
+    if (! notification)
+        return;
+
+    notify_notification_close (notification, nullptr);
+    g_object_unref (notification);
+    notification = nullptr;
+}
diff --git a/src/oss4/Makefile b/src/oss4/Makefile
index ff01addd4ed2..c0e83511d774 100644
--- a/src/oss4/Makefile
+++ b/src/oss4/Makefile
@@ -1,13 +1,15 @@
 PLUGIN = oss4${PLUGIN_SUFFIX}
 
-SRCS = plugin.c     \
-       oss.c        \
-       utils.c
+SRCS = plugin.cc     \
+       oss.cc        \
+       utils.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${OSS_CFLAGS} -I../..
diff --git a/src/oss4/oss.c b/src/oss4/oss.c
deleted file mode 100644
index b8dd5961473a..000000000000
--- a/src/oss4/oss.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * oss.c
- * Copyright 2010-2012 Michał Lipski
- *
- * I would like to thank people on #audacious, especially Tony Vroon and
- * John Lindgren and of course the authors of the previous OSS plugin.
- *
- * 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 "oss.h"
-
-#include <libaudcore/audstrings.h>
-
-static const char * const oss_defaults[] = {
- "device", DEFAULT_DSP,
- "use_alt_device", "FALSE",
- "alt_device", DEFAULT_DSP,
- "save_volume", "TRUE",
- "volume", "12850", /* 0x3232 */
- "cookedmode", "TRUE",
- "exclusive", "FALSE",
- NULL};
-
-oss_data_t *oss_data;
-static int64_t oss_time; /* microseconds */
-static bool_t oss_paused;
-static int oss_paused_time;
-static int oss_delay; /* miliseconds */
-static bool_t oss_ioctl_vol = FALSE;
-
-bool_t oss_init(void)
-{
-    AUDDBG("Init.\n");
-
-    aud_config_set_defaults("oss4", oss_defaults);
-    oss_data = (oss_data_t *) malloc(sizeof(oss_data_t));
-    oss_data->fd = -1;
-
-    return oss_hardware_present();
-}
-
-void oss_cleanup(void)
-{
-    AUDDBG("Cleanup.\n");
-
-    free(oss_data);
-}
-
-static bool_t set_format(int format, int rate, int channels)
-{
-    int param;
-
-    AUDDBG("Audio format: %s, sample rate: %dHz, number of channels: %d.\n", oss_format_to_text(format), rate, channels);
-
-    /* Enable/disable format conversions made by the OSS software */
-    param = aud_get_bool("oss4", "cookedmode");
-    CHECK(ioctl, oss_data->fd, SNDCTL_DSP_COOKEDMODE, &param);
-
-    AUDDBG("%s format conversions made by the OSS software.\n", param ? "Enabled" : "Disabled");
-
-    param = format;
-    CHECK_NOISY(ioctl, oss_data->fd, SNDCTL_DSP_SETFMT, &param);
-    CHECK_VAL(param == format, ERROR_NOISY, "Selected audio format is not supported by the device.\n");
-
-    param = rate;
-    CHECK_NOISY(ioctl, oss_data->fd, SNDCTL_DSP_SPEED, &param);
-    CHECK_VAL(param >= rate * 9 / 10 && param <= rate * 11 / 10, ERROR_NOISY,
-     "Selected sample rate is not supported by the device.\n");
-
-    param = channels;
-    CHECK_NOISY(ioctl, oss_data->fd, SNDCTL_DSP_CHANNELS, &param);
-    CHECK_VAL(param == channels, ERROR_NOISY, "Selected number of channels is not supported by the device.\n");
-
-    oss_data->format = format;
-    oss_data->rate = rate;
-    oss_data->channels = channels;
-    oss_data->bits_per_sample = oss_format_to_bits(oss_data->format);
-
-    return TRUE;
-
-FAILED:
-    return FALSE;
-}
-
-static int open_device(void)
-{
-    int res = -1;
-    int flags = O_WRONLY;
-    char *device = aud_get_str("oss4", "device");
-    char *alt_device = aud_get_str("oss4", "alt_device");
-
-    if (aud_get_bool("oss4", "exclusive"))
-    {
-        AUDDBG("Enabled exclusive mode.\n");
-        flags |= O_EXCL;
-    }
-
-    if (aud_get_bool("oss4", "use_alt_device") && alt_device != NULL)
-        res = open(alt_device, flags);
-    else if (device != NULL)
-        res = open(device, flags);
-    else
-        res = open(DEFAULT_DSP, flags);
-
-    str_unref(device);
-    str_unref(alt_device);
-
-    return res;
-}
-
-static void close_device(void)
-{
-    close(oss_data->fd);
-    oss_data->fd = -1;
-}
-
-int oss_open_audio(int aud_format, int rate, int channels)
-{
-    AUDDBG("Opening audio.\n");
-
-    int format;
-    int vol_left, vol_right;
-    audio_buf_info buf_info;
-
-    CHECK_NOISY(oss_data->fd = open_device);
-
-    format = oss_convert_aud_format(aud_format);
-
-    if (!set_format(format, rate, channels))
-        goto FAILED;
-
-    CHECK_NOISY(ioctl, oss_data->fd, SNDCTL_DSP_GETOSPACE, &buf_info);
-
-    AUDDBG("Buffer information, fragstotal: %d, fragsize: %d, bytes: %d.\n",
-        buf_info.fragstotal,
-        buf_info.fragsize,
-        buf_info.bytes);
-
-    oss_time = 0;
-    oss_paused = FALSE;
-    oss_paused_time = 0;
-    oss_delay = oss_bytes_to_frames(buf_info.fragstotal * buf_info.fragsize) * 1000 / oss_data->rate;
-    oss_ioctl_vol = TRUE;
-
-    AUDDBG("Internal OSS buffer size: %dms.\n", oss_delay);
-
-    if (aud_get_bool("oss4", "save_volume"))
-    {
-        vol_right = (aud_get_int("oss4", "volume") & 0xFF00) >> 8;
-        vol_left  = (aud_get_int("oss4", "volume") & 0x00FF);
-        oss_set_volume(vol_left, vol_right);
-    }
-
-    return 1;
-
-FAILED:
-    close_device();
-    return 0;
-}
-
-void oss_close_audio(void)
-{
-    AUDDBG ("Closing audio.\n");
-
-    close_device();
-}
-
-void oss_write_audio(void *data, int length)
-{
-    int written = 0, start = 0;
-
-    while (length > 0)
-    {
-        written = write(oss_data->fd, (char *) data + start, length);
-
-        if (written < 0)
-        {
-            DESCRIBE_ERROR;
-            return;
-        }
-
-        length -= written;
-        start += written;
-        oss_time += (int64_t) oss_bytes_to_frames(written) * 1000000 / oss_data->rate;
-    }
-}
-
-void oss_drain(void)
-{
-    AUDDBG("Drain.\n");
-
-    if (ioctl(oss_data->fd, SNDCTL_DSP_SYNC, NULL) == -1)
-        DESCRIBE_ERROR;
-}
-
-int oss_buffer_free(void)
-{
-    audio_buf_info buf_info;
-
-    if (oss_paused)
-        return 0;
-
-    CHECK(ioctl, oss_data->fd, SNDCTL_DSP_GETOSPACE, &buf_info);
-
-    return MAX(0, buf_info.fragments - 1) * buf_info.fragsize;
-
-FAILED:
-    return 0;
-}
-
-static int real_output_time()
-{
-    int  time = 0;
-
-    time = (oss_time - (int64_t) (oss_delay * 1000)) / 1000;
-    return time;
-}
-
-int oss_output_time(void)
-{
-    int time = 0;
-
-    if (oss_paused)
-        time = oss_paused_time;
-    else
-        time = real_output_time();
-    return time;
-}
-
-void oss_flush(int time)
-{
-    AUDDBG("Flush.\n");
-
-    CHECK(ioctl, oss_data->fd, SNDCTL_DSP_RESET, NULL);
-
-FAILED:
-    oss_time = (int64_t) time * 1000;
-    oss_paused_time = time;
-}
-
-void oss_pause(bool_t pause)
-{
-    AUDDBG("%sause.\n", pause ? "P" : "Unp");
-
-    if (pause)
-    {
-        oss_paused_time = real_output_time();
-        CHECK(ioctl, oss_data->fd, SNDCTL_DSP_SILENCE, NULL);
-    }
-    else
-        CHECK(ioctl, oss_data->fd, SNDCTL_DSP_SKIP, NULL);
-
-FAILED:
-    oss_paused = pause;
-}
-
-void oss_get_volume(int *left, int *right)
-{
-    *left = *right = 0;
-
-    int vol;
-
-    if (oss_data->fd == -1 || !oss_ioctl_vol)
-    {
-        if (aud_get_int("oss4", "save_volume"))
-        {
-            *right = (aud_get_int("oss4", "volume") & 0xFF00) >> 8;
-            *left  = (aud_get_int("oss4", "volume") & 0x00FF);
-        }
-        return;
-    }
-
-    CHECK(ioctl, oss_data->fd, SNDCTL_DSP_GETPLAYVOL, &vol);
-
-    *right = (vol & 0xFF00) >> 8;
-    *left  = (vol & 0x00FF);
-    aud_set_int("oss4", "volume", vol);
-
-    return;
-
-FAILED:
-    if (errno == EINVAL)
-        oss_ioctl_vol = FALSE;
-}
-
-void oss_set_volume(int left, int right)
-{
-    int vol = (right << 8) | left;
-
-    if (aud_get_int("oss4", "save_volume"))
-        aud_set_int("oss4", "volume", vol);
-
-    if (oss_data->fd == -1 || !oss_ioctl_vol)
-        return;
-
-    CHECK(ioctl, oss_data->fd, SNDCTL_DSP_SETPLAYVOL, &vol);
-
-    return;
-
-FAILED:
-    if (errno == EINVAL)
-        oss_ioctl_vol = FALSE;
-}
diff --git a/src/oss4/oss.cc b/src/oss4/oss.cc
new file mode 100644
index 000000000000..923449d7cfd8
--- /dev/null
+++ b/src/oss4/oss.cc
@@ -0,0 +1,365 @@
+/*
+ * oss.c
+ * Copyright 2010-2012 Michał Lipski
+ *
+ * I would like to thank people on #audacious, especially Tony Vroon and
+ * John Lindgren and of course the authors of the previous OSS plugin.
+ *
+ * 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 "oss.h"
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+
+#include <poll.h>
+
+constexpr StereoVolume to_stereo_volume(int vol)
+    { return {vol & 0x00ff, vol >> 8}; }
+constexpr int from_stereo_volume(StereoVolume v)
+    { return v.left | (v.right << 8); }
+
+const char * const OSSPlugin::defaults[] = {
+ "device", DEFAULT_DSP,
+ "use_alt_device", "FALSE",
+ "alt_device", DEFAULT_DSP,
+ "save_volume", "TRUE",
+ "volume", aud::numeric_string<0x3232>::str,
+ "cookedmode", "TRUE",
+ "exclusive", "FALSE",
+ nullptr};
+
+static int poll_pipe[2];
+static pollfd poll_handles[2];
+
+bool OSSPlugin::init()
+{
+    AUDDBG("Init.\n");
+
+    aud_config_set_defaults("oss4", defaults);
+
+    return oss_hardware_present();
+}
+
+bool OSSPlugin::set_format(int format, int rate, int channels)
+{
+    int param;
+
+    AUDDBG("Audio format: %s, sample rate: %dHz, number of channels: %d.\n", oss_format_to_text(format), rate, channels);
+
+#ifdef SNDCTL_DSP_COOKEDMODE
+    /* Enable/disable format conversions made by the OSS software */
+    param = aud_get_bool("oss4", "cookedmode");
+    CHECK(ioctl, m_fd, SNDCTL_DSP_COOKEDMODE, &param);
+
+    AUDDBG("%s format conversions made by the OSS software.\n", param ? "Enabled" : "Disabled");
+#endif
+
+    param = format;
+    CHECK_NOISY(ioctl, m_fd, SNDCTL_DSP_SETFMT, &param);
+    CHECK_VAL(param == format, ERROR_NOISY, "Selected audio format is not supported by the device.\n");
+
+    param = rate;
+    CHECK_NOISY(ioctl, m_fd, SNDCTL_DSP_SPEED, &param);
+    CHECK_VAL(param >= rate * 9 / 10 && param <= rate * 11 / 10, ERROR_NOISY,
+     "Selected sample rate is not supported by the device.\n");
+
+    param = channels;
+    CHECK_NOISY(ioctl, m_fd, SNDCTL_DSP_CHANNELS, &param);
+    CHECK_VAL(param == channels, ERROR_NOISY, "Selected number of channels is not supported by the device.\n");
+
+    m_format = format;
+    m_rate = rate;
+    m_channels = channels;
+    m_bytes_per_sample = oss_format_to_bytes(m_format);
+
+    return true;
+
+FAILED:
+    return false;
+}
+
+static int log2(int x)
+{
+    int y = 0;
+
+    while((x >>= 1))
+        y++;
+
+    return y;
+}
+
+bool OSSPlugin::set_buffer()
+{
+    int milliseconds = aud_get_int(nullptr, "output_buffer_size");
+    int bytes = frames_to_bytes(aud::rescale(milliseconds, 1000, m_rate));
+    int fragorder = aud::clamp(log2(bytes / 4), 9, 15);
+    int numfrags = aud::clamp(aud::rdiv(bytes, 1 << fragorder), 4, 32767);
+
+    int param = (numfrags << 16) | fragorder;
+    CHECK_NOISY(ioctl, m_fd, SNDCTL_DSP_SETFRAGMENT, &param);
+
+    return true;
+
+FAILED:
+    return false;
+}
+
+static int open_device()
+{
+    int res = -1;
+    int flags = O_WRONLY | O_NONBLOCK;
+    String device = aud_get_str("oss4", "device");
+    String alt_device = aud_get_str("oss4", "alt_device");
+
+    if (aud_get_bool("oss4", "exclusive"))
+    {
+        AUDDBG("Enabled exclusive mode.\n");
+        flags |= O_EXCL;
+    }
+
+    if (aud_get_bool("oss4", "use_alt_device") && alt_device != nullptr)
+        res = open(alt_device, flags);
+    else if (device != nullptr)
+        res = open(device, flags);
+    else
+        res = open(DEFAULT_DSP, flags);
+
+    return res;
+}
+
+static void close_device(int &fd)
+{
+    close(fd);
+    fd = -1;
+}
+
+static bool poll_setup(int fd)
+{
+    if (pipe(poll_pipe))
+    {
+        AUDERR("Failed to create pipe: %s.\n", strerror(errno));
+        return false;
+    }
+
+    if (fcntl(poll_pipe[0], F_SETFL, O_NONBLOCK))
+    {
+        AUDERR("Failed to set O_NONBLOCK on pipe: %s.\n", strerror(errno));
+        close(poll_pipe[0]);
+        close(poll_pipe[1]);
+        return false;
+    }
+
+    poll_handles[0].fd = poll_pipe[0];
+    poll_handles[0].events = POLLIN;
+    poll_handles[1].fd = fd;
+    poll_handles[1].events = POLLOUT;
+
+    return true;
+}
+
+static void poll_sleep()
+{
+    if (poll(poll_handles, 2, -1) < 0)
+    {
+        AUDERR("Failed to poll: %s.\n", strerror(errno));
+        return;
+    }
+
+    if (poll_handles[0].revents & POLLIN)
+    {
+        char c;
+        while (read(poll_pipe[0], &c, 1) == 1)
+            ;
+    }
+}
+
+static void poll_wake()
+{
+    const char c = 0;
+    if (write(poll_pipe[1], &c, 1) < 0)
+        AUDERR("Failed to write to pipe: %s.\n", strerror(errno));
+}
+
+static void poll_cleanup()
+{
+    close(poll_pipe[0]);
+    close(poll_pipe[1]);
+}
+
+bool OSSPlugin::open_audio(int aud_format, int rate, int channels)
+{
+    AUDDBG("Opening audio.\n");
+
+    int format;
+    audio_buf_info buf_info;
+
+    CHECK_NOISY(m_fd = open_device);
+
+    if (!poll_setup(m_fd))
+        goto CLOSE;
+
+    format = oss_convert_aud_format(aud_format);
+
+    if (!set_format(format, rate, channels))
+        goto FAILED;
+
+    if (!set_buffer())
+        goto FAILED;
+
+    memset(&buf_info, 0, sizeof buf_info);
+    CHECK_NOISY(ioctl, m_fd, SNDCTL_DSP_GETOSPACE, &buf_info);
+
+    AUDINFO("Buffer information, fragstotal: %d, fragsize: %d, bytes: %d.\n",
+        buf_info.fragstotal,
+        buf_info.fragsize,
+        buf_info.bytes);
+
+    m_paused = false;
+    m_ioctl_vol = true;
+
+    if (aud_get_bool("oss4", "save_volume"))
+        set_volume(to_stereo_volume(aud_get_int("oss4", "volume")));
+
+    return true;
+
+FAILED:
+    poll_cleanup();
+CLOSE:
+    close_device(m_fd);
+    return false;
+}
+
+void OSSPlugin::close_audio()
+{
+    AUDDBG("Closing audio.\n");
+
+    poll_cleanup();
+    close_device(m_fd);
+}
+
+int OSSPlugin::write_audio(const void *data, int length)
+{
+    if (m_paused)
+        return 0;
+
+    int written = write(m_fd, data, length);
+
+    if (written < 0)
+    {
+        if (errno != EAGAIN)
+            DESCRIBE_ERROR;
+
+        return 0;
+    }
+
+    return written;
+}
+
+void OSSPlugin::period_wait()
+{
+    poll_sleep();
+}
+
+void OSSPlugin::drain()
+{
+    AUDDBG("Drain.\n");
+
+    if (ioctl(m_fd, SNDCTL_DSP_SYNC, nullptr) == -1)
+        DESCRIBE_ERROR;
+}
+
+int OSSPlugin::get_delay()
+{
+    int delay_bytes = 0;
+    CHECK(ioctl, m_fd, SNDCTL_DSP_GETODELAY, &delay_bytes);
+
+FAILED:
+    return aud::rescale<int64_t>(bytes_to_frames(delay_bytes), m_rate, 1000);
+}
+
+void OSSPlugin::flush()
+{
+    AUDDBG("Flush.\n");
+
+    CHECK(ioctl, m_fd, SNDCTL_DSP_RESET, nullptr);
+
+FAILED:
+    poll_wake();
+}
+
+void OSSPlugin::pause(bool pause)
+{
+    AUDDBG("%sause.\n", pause ? "P" : "Unp");
+
+#ifdef SNDCTL_DSP_SILENCE
+    if (pause)
+        CHECK(ioctl, m_fd, SNDCTL_DSP_SILENCE, nullptr);
+    else
+        CHECK(ioctl, m_fd, SNDCTL_DSP_SKIP, nullptr);
+
+FAILED:
+#endif
+    m_paused = pause;
+}
+
+StereoVolume OSSPlugin::get_volume()
+{
+#ifdef SNDCTL_DSP_GETPLAYVOL
+    int vol = 0;
+
+    if (m_fd == -1 || !m_ioctl_vol)
+    {
+        if (aud_get_bool("oss4", "save_volume"))
+            return to_stereo_volume(aud_get_int("oss4", "volume"));
+
+        goto FAILED;
+    }
+
+    CHECK(ioctl, m_fd, SNDCTL_DSP_GETPLAYVOL, &vol);
+
+    aud_set_int("oss4", "volume", vol);
+
+    return to_stereo_volume(vol);
+
+FAILED:
+    if (errno == EINVAL)
+        m_ioctl_vol = false;
+#endif
+
+    return to_stereo_volume(0);
+}
+
+void OSSPlugin::set_volume(StereoVolume v)
+{
+#ifdef SNDCTL_DSP_SETPLAYVOL
+    int vol = from_stereo_volume(v);
+
+    if (aud_get_bool("oss4", "save_volume"))
+        aud_set_int("oss4", "volume", vol);
+
+    if (m_fd == -1 || !m_ioctl_vol)
+        return;
+
+    CHECK(ioctl, m_fd, SNDCTL_DSP_SETPLAYVOL, &vol);
+
+    return;
+
+FAILED:
+    if (errno == EINVAL)
+        m_ioctl_vol = false;
+#endif
+}
diff --git a/src/oss4/oss.h b/src/oss4/oss.h
index 5e198b540800..4de81109829f 100644
--- a/src/oss4/oss.h
+++ b/src/oss4/oss.h
@@ -23,7 +23,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/ioctl.h>
@@ -34,21 +33,16 @@
 #include <soundcard.h>
 #endif
 
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-#include <audacious/debug.h>
-#include <audacious/misc.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
 
-#define ERROR(...) \
-do { \
-    fprintf(stderr, "OSS4 %s:%d [%s]: ", __FILE__, __LINE__, __FUNCTION__); \
-    fprintf(stderr, __VA_ARGS__); \
-} while (0)
+#define ERROR AUDERR
 
 #define ERROR_NOISY(...) \
 do { \
-    SPRINTF(oss_error_buf, "OSS4 error: "__VA_ARGS__); \
-    aud_interface_show_error(oss_error_buf); \
+    aud_ui_show_error(str_printf("OSS4 error: " __VA_ARGS__)); \
     ERROR(__VA_ARGS__); \
 } while (0) \
 
@@ -84,43 +78,81 @@ do { \
 #define DEFAULT_MIXER "/dev/mixer"
 #define DEFAULT_DSP "/dev/dsp"
 
-typedef struct
+struct PreferencesWidget;
+
+class OSSPlugin : public OutputPlugin
 {
-    int fd;
-    int format;
-    int rate;
-    int channels;
-    int bits_per_sample;
-} oss_data_t;
-
-extern oss_data_t *oss_data;
-
-/* oss.c */
-bool_t oss_init(void);
-void oss_cleanup(void);
-int oss_open_audio(int aud_format, int rate, int channels);
-void oss_close_audio(void);
-void oss_write_audio(void *data, int length);
-void oss_drain(void);
-int oss_buffer_free(void);
-int oss_output_time(void);
-void oss_flush(int time);
-void oss_pause(bool_t pause);
-void oss_get_volume(int *left, int *right);
-void oss_set_volume(int left, int right);
-
-/* configure.c */
-void oss_configure(void);
+public:
+    static const char about[];
+    static const char *const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+#ifdef SNDCTL_SYSINFO
+        N_("OSS4 Output"),
+#else
+        N_("OSS3 Output"),
+#endif
+        PACKAGE,
+        about,
+        &prefs
+    };
+
+    // OSS4 is preferred over ALSA (priority 5).
+    // ALSA is preferred over OSS3.
+#ifdef SNDCTL_SYSINFO
+    constexpr OSSPlugin() : OutputPlugin(info, 6) {}
+#else
+    constexpr OSSPlugin() : OutputPlugin(info, 4) {}
+#endif
+
+    bool init();
+
+    StereoVolume get_volume();
+    void set_volume(StereoVolume v);
+
+    bool open_audio(int aud_format, int rate, int chans);
+    void close_audio();
+
+    void period_wait();
+    int write_audio(const void *data, int size);
+    void drain();
+
+    int get_delay();
+
+    void pause(bool pause);
+    void flush();
+
+private:
+    bool set_format(int format, int rate, int channels);
+    bool set_buffer();
+
+    int frames_to_bytes(int frames) const
+        { return frames * (m_bytes_per_sample * m_channels); }
+    int bytes_to_frames(int bytes) const
+        { return bytes / (m_bytes_per_sample * m_channels); }
+
+    int m_fd = -1;
+    int m_format = 0;
+    int m_rate = 0;
+    int m_channels = 0;
+    int m_bytes_per_sample = 0;
+
+    bool m_paused = false;
+    bool m_ioctl_vol = false;
+};
 
 /* utils.c */
 int oss_convert_aud_format(int aud_format);
-char *oss_format_to_text(int format);
-int oss_format_to_bits(int format);
-int oss_frames_to_bytes(int frames);
-int oss_bytes_to_frames(int bytes);
-int oss_calc_bitrate(void);
-char *oss_describe_error(void);
+const char *oss_format_to_text(int format);
+int oss_format_to_bytes(int format);
+const char *oss_describe_error();
+
+#ifdef SNDCTL_SYSINFO
 int oss_probe_for_adev(oss_sysinfo *sysinfo);
-bool_t oss_hardware_present(void);
+#endif
+
+bool oss_hardware_present();
 
 #endif
diff --git a/src/oss4/plugin.c b/src/oss4/plugin.c
deleted file mode 100644
index aa99e6043e0d..000000000000
--- a/src/oss4/plugin.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * plugin.c
- * Copyright 2010-2012 Michał Lipski
- *
- * 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 "oss.h"
-
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.h>
-
-static void combo_init(ComboBoxElements ** elements, int * n_elements)
-{
-    oss_sysinfo sysinfo;
-    int mixerfd;
-
-    CHECK_NOISY(mixerfd = open, DEFAULT_MIXER, O_RDWR);
-    CHECK(ioctl, mixerfd, SNDCTL_SYSINFO, &sysinfo);
-    CHECK_NOISY(oss_probe_for_adev, &sysinfo);
-
-    * elements = (ComboBoxElements *) malloc((sysinfo.numaudios + 1) * sizeof(ComboBoxElements));
-    * n_elements = 1;
-    ComboBoxElements * tmp = * elements;
-
-    tmp->label = N_("1. Default device");
-    tmp->value = DEFAULT_DSP;
-
-    for (int i = 0; i < sysinfo.numaudios; i++)
-    {
-        oss_audioinfo ainfo;
-        ainfo.dev = i;
-
-        CHECK(ioctl, mixerfd, SNDCTL_AUDIOINFO, &ainfo);
-
-        if (ainfo.caps & PCM_CAP_OUTPUT)
-        {
-            tmp++;
-            (* n_elements) ++;
-            SPRINTF(str, "%d. %s", * n_elements, ainfo.name);
-            tmp->label = strdup(str);
-            tmp->value = strdup(ainfo.devnode);
-        }
-        else
-            continue;
-    }
-
-FAILED:
-    close(mixerfd);
-}
-
-static void combo_cleanup(ComboBoxElements * elements, int n_elements)
-{
-    /* first elements were allocated statically */
-    for (int i = 1; i < n_elements; i++)
-    {
-        free(elements[i].value);
-        free((char *) elements[i].label);
-    }
-
-    free(elements);
-}
-
-static PreferencesWidget oss_widgets[] = {
- {WIDGET_COMBO_BOX, N_("Audio device:"),
-  .cfg_type = VALUE_STRING, .csect = "oss4", .cname = "device"},
- {WIDGET_CHK_BTN, N_("Use alternate device:"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "oss4", .cname = "use_alt_device"},
- {WIDGET_ENTRY,
-  .cfg_type = VALUE_STRING, .csect = "oss4", .cname = "alt_device", .child = TRUE},
- {WIDGET_CHK_BTN, N_("Save volume between sessions."),
-  .cfg_type = VALUE_BOOLEAN, .csect = "oss4", .cname = "save_volume"},
- {WIDGET_CHK_BTN, N_("Enable format conversions made by the OSS software."),
-  .cfg_type = VALUE_BOOLEAN, .csect = "oss4", .cname = "cookedmode"},
- {WIDGET_CHK_BTN, N_("Enable exclusive mode to prevent virtual mixing."),
-  .cfg_type = VALUE_BOOLEAN, .csect = "oss4", .cname = "exclusive"},
-};
-
-static void prefs_init()
-{
-    combo_init((ComboBoxElements **) &oss_widgets[0].data.combo.elements,
-     &oss_widgets[0].data.combo.n_elements);
-}
-
-static void prefs_cleanup()
-{
-    combo_cleanup((ComboBoxElements *) oss_widgets[0].data.combo.elements,
-     oss_widgets[0].data.combo.n_elements);
-}
-
-static const PluginPreferences oss_prefs = {
- .widgets = oss_widgets,
- .n_widgets = ARRAY_LEN(oss_widgets),
- .init = prefs_init,
- .cleanup = prefs_cleanup};
-
-static const char oss_about[] =
- N_("OSS4 Output Plugin for Audacious\n"
-    "Copyright 2010-2012 Michał Lipski\n\n"
-    "I would like to thank people on #audacious, especially Tony Vroon and "
-    "John Lindgren and of course the authors of the previous OSS plugin.");
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("OSS4 Output"),
-    .domain = PACKAGE,
-    .probe_priority = 5,
-    .init = oss_init,
-    .cleanup = oss_cleanup,
-    .open_audio = oss_open_audio,
-    .close_audio = oss_close_audio,
-    .write_audio = oss_write_audio,
-    .drain = oss_drain,
-    .buffer_free = oss_buffer_free,
-    .output_time = oss_output_time,
-    .flush = oss_flush,
-    .pause = oss_pause,
-    .set_volume = oss_set_volume,
-    .get_volume = oss_get_volume,
-    .about_text = oss_about,
-    .prefs = &oss_prefs
-)
diff --git a/src/oss4/plugin.cc b/src/oss4/plugin.cc
new file mode 100644
index 000000000000..dd02694fe9b7
--- /dev/null
+++ b/src/oss4/plugin.cc
@@ -0,0 +1,103 @@
+/*
+ * plugin.c
+ * Copyright 2010-2012 Michał Lipski
+ *
+ * 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 "oss.h"
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/preferences.h>
+
+EXPORT OSSPlugin aud_plugin_instance;
+
+static Index<ComboItem> oss_elements;
+
+static void combo_init()
+{
+    int mixerfd;
+
+    CHECK_NOISY(mixerfd = open, DEFAULT_MIXER, O_RDWR);
+
+    oss_elements.append(ComboItem(strdup(N_("Default device")), strdup(DEFAULT_DSP)));
+
+#ifdef SNDCTL_SYSINFO
+    oss_sysinfo sysinfo;
+    memset(&sysinfo, 0, sizeof sysinfo);
+    CHECK(ioctl, mixerfd, SNDCTL_SYSINFO, &sysinfo);
+    CHECK_NOISY(oss_probe_for_adev, &sysinfo);
+
+    for (int i = 0; i < sysinfo.numaudios; i++)
+    {
+        oss_audioinfo ainfo;
+        memset(&ainfo, 0, sizeof ainfo);
+        ainfo.dev = i;
+
+        CHECK(ioctl, mixerfd, SNDCTL_AUDIOINFO, &ainfo);
+
+        if (ainfo.caps & PCM_CAP_OUTPUT)
+            oss_elements.append(ComboItem(strdup(ainfo.name), strdup(ainfo.devnode)));
+    }
+#endif
+
+FAILED:
+    close(mixerfd);
+}
+
+ArrayRef<ComboItem> combo_fill()
+{
+    return {oss_elements.begin(), oss_elements.len()};
+}
+
+static void combo_cleanup()
+{
+    for (ComboItem & elem : oss_elements)
+    {
+        free((char *)elem.label);
+        free((char *)elem.str);
+    }
+
+    oss_elements.clear();
+}
+
+const PreferencesWidget OSSPlugin::widgets[] = {
+    WidgetCombo(N_("Audio device:"),
+        WidgetString ("oss4", "device"),
+        {0, combo_fill}),
+    WidgetCheck(N_("Use alternate device:"),
+        WidgetBool ("oss4", "use_alt_device")),
+    WidgetEntry(0, WidgetString ("oss4", "alt_device"),
+        {}, WIDGET_CHILD),
+    WidgetCheck(N_("Save volume between sessions."),
+        WidgetBool ("oss4", "save_volume")),
+    WidgetCheck(N_("Enable format conversions made by the OSS software."),
+        WidgetBool ("oss4", "cookedmode")),
+    WidgetCheck(N_("Enable exclusive mode to prevent virtual mixing."),
+        WidgetBool ("oss4", "exclusive"))
+};
+
+const PluginPreferences OSSPlugin::prefs = {
+    {widgets},
+    combo_init,
+    nullptr,  // apply
+    combo_cleanup
+};
+
+const char OSSPlugin::about[] =
+ N_("OSS4 Output Plugin for Audacious\n"
+    "Copyright 2010-2012 Michał Lipski\n\n"
+    "I would like to thank people on #audacious, especially Tony Vroon and "
+    "John Lindgren and of course the authors of the previous OSS plugin.");
diff --git a/src/oss4/utils.c b/src/oss4/utils.c
deleted file mode 100644
index affd321dd8aa..000000000000
--- a/src/oss4/utils.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * utils.c
- * Copyright 2010-2011 Michał Lipski
- *
- * 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 "oss.h"
-
-#include <libaudcore/audstrings.h>
-
-char *oss_format_to_text(int format)
-{
-    const struct
-    {
-        int format;
-        char *format_text;
-    }
-    table[] =
-    {
-#ifdef AFMT_FLOAT
-        {AFMT_FLOAT,  "AFMT_FLOAT"},
-#endif
-        {AFMT_S8,     "AFMT_S8"},
-        {AFMT_U8,     "AFMT_U8"},
-        {AFMT_S16_LE, "AFMT_S16_LE"},
-        {AFMT_S16_BE, "AFMT_S16_BE"},
-        {AFMT_U16_LE, "AFMT_U16_LE"},
-        {AFMT_U16_BE, "AFMT_U16_BE"},
-        {AFMT_S24_LE, "AFMT_S24_LE"},
-        {AFMT_S24_BE, "AFMT_S24_BE"},
-        {AFMT_S32_LE, "AFMT_S32_LE"},
-        {AFMT_S32_BE, "AFMT_S32_BE"},
-    };
-
-    int count;
-
-    for (count = 0; count < ARRAY_LEN(table); count++)
-    {
-        if (table[count].format == format)
-        {
-            return table[count].format_text;
-        }
-    }
-
-    return "FMT_UNKNOWN";
-}
-
-int oss_convert_aud_format(int aud_format)
-{
-    const struct
-    {
-        int aud_format;
-        int format;
-    }
-    table[] =
-    {
-#ifdef AFMT_FLOAT
-        {FMT_FLOAT,  AFMT_FLOAT},
-#endif
-        {FMT_S8,     AFMT_S8},
-        {FMT_U8,     AFMT_U8},
-        {FMT_S16_LE, AFMT_S16_LE},
-        {FMT_S16_BE, AFMT_S16_BE},
-        {FMT_U16_LE, AFMT_U16_LE},
-        {FMT_U16_BE, AFMT_U16_BE},
-        {FMT_S24_LE, AFMT_S24_LE},
-        {FMT_S24_BE, AFMT_S24_BE},
-        {FMT_S32_LE, AFMT_S32_LE},
-        {FMT_S32_BE, AFMT_S32_BE},
-    };
-
-    int count;
-
-    for (count = 0; count < ARRAY_LEN(table); count++)
-    {
-        if (table[count].aud_format == aud_format)
-        {
-            return table[count].format;
-        }
-    }
-
-    return -1;
-}
-
-int oss_format_to_bits(int format)
-{
-    char bits;
-
-    switch (format)
-    {
-        case AFMT_U8:
-        case AFMT_S8:
-            bits = 8;
-            break;
-        case AFMT_S16_LE:
-        case AFMT_S16_BE:
-        case AFMT_U16_LE:
-        case AFMT_U16_BE:
-            bits = 16;
-            break;
-        case AFMT_S24_LE:
-        case AFMT_S24_BE:
-        case AFMT_S32_LE:
-        case AFMT_S32_BE:
-            bits = 32;
-            break;
-#ifdef AFMT_FLOAT
-        case AFMT_FLOAT:
-            bits = sizeof(float) * 8;
-            break;
-#endif
-        default:
-            bits = 8;
-    }
-
-    return bits;
-}
-
-int oss_frames_to_bytes(int frames)
-{
-    return frames * oss_data->bits_per_sample * oss_data->channels / 8;
-}
-
-int oss_bytes_to_frames(int bytes)
-{
-    return bytes * 8 / oss_data->channels / oss_data->bits_per_sample;
-}
-
-int oss_calc_bitrate(void)
-{
-    return (oss_data->rate * oss_data->channels * oss_data->bits_per_sample) >> 3;
-}
-
-char *oss_describe_error(void)
-{
-    const struct
-    {
-        int error;
-        char *text;
-    }
-    table[] =
-    {
-        {EINVAL, "The ioctl call is not supported by current OSS version."},
-        {EACCES, "You do not have permissions to access the device."},
-        {EBUSY,  "The device is busy. There is some other application using it."},
-        {ENXIO,  "OSS has not detected any supported sound hardware in your system."},
-        {ENODEV, "The device file was found in /dev but OSS is not loaded. You need to "
-                 "load it by executing the soundon command."},
-        {ENOSPC, "Your system cannot allocate memory for the device buffers. Reboot your "
-                 "machine and try again."},
-        {ENOENT, "The device file is missing from /dev. Perhaps you have not installed "
-                 "and started Open Sound System yet."},
-    };
-
-    int count;
-    for (count = 0; count < ARRAY_LEN(table); count++)
-    {
-        if (table[count].error == errno)
-            return table[count].text;
-    }
-
-    return strerror(errno);
-}
-
-int oss_probe_for_adev(oss_sysinfo *sysinfo)
-{
-    int num;
-    if ((num = sysinfo->numaudios) < 1)
-    {
-        errno = ENXIO;
-        return -1;
-    }
-
-    return num;
-}
-
-bool_t oss_hardware_present(void)
-{
-    int mixerfd;
-    oss_sysinfo sysinfo;
-
-    CHECK_NOISY(mixerfd = open, DEFAULT_MIXER, O_RDWR, 0);
-    CHECK(ioctl, mixerfd, SNDCTL_SYSINFO, &sysinfo);
-    CHECK_NOISY(oss_probe_for_adev, &sysinfo);
-
-    close(mixerfd);
-    return TRUE;
-
-FAILED:
-    close(mixerfd);
-    return FALSE;
-}
diff --git a/src/oss4/utils.cc b/src/oss4/utils.cc
new file mode 100644
index 000000000000..22fd78ab7cd5
--- /dev/null
+++ b/src/oss4/utils.cc
@@ -0,0 +1,204 @@
+/*
+ * utils.c
+ * Copyright 2010-2011 Michał Lipski
+ *
+ * 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 "oss.h"
+
+#include <libaudcore/audstrings.h>
+
+const char *oss_format_to_text(int format)
+{
+    static const struct
+    {
+        int format;
+        const char *format_text;
+    }
+    table[] =
+    {
+#ifdef AFMT_FLOAT
+        {AFMT_FLOAT,  "AFMT_FLOAT"},
+#endif
+        {AFMT_S8,     "AFMT_S8"},
+        {AFMT_U8,     "AFMT_U8"},
+        {AFMT_S16_LE, "AFMT_S16_LE"},
+        {AFMT_S16_BE, "AFMT_S16_BE"},
+        {AFMT_U16_LE, "AFMT_U16_LE"},
+        {AFMT_U16_BE, "AFMT_U16_BE"},
+#ifdef AFMT_S24_LE
+        {AFMT_S24_LE, "AFMT_S24_LE"},
+        {AFMT_S24_BE, "AFMT_S24_BE"},
+#endif
+#ifdef AFMT_S32_LE
+        {AFMT_S32_LE, "AFMT_S32_LE"},
+        {AFMT_S32_BE, "AFMT_S32_BE"},
+#endif
+    };
+
+    for (auto & conv : table)
+    {
+        if (conv.format == format)
+            return conv.format_text;
+    }
+
+    return "FMT_UNKNOWN";
+}
+
+int oss_convert_aud_format(int aud_format)
+{
+    const struct
+    {
+        int aud_format;
+        int format;
+    }
+    table[] =
+    {
+#ifdef AFMT_FLOAT
+        {FMT_FLOAT,  AFMT_FLOAT},
+#endif
+        {FMT_S8,     AFMT_S8},
+        {FMT_U8,     AFMT_U8},
+        {FMT_S16_LE, AFMT_S16_LE},
+        {FMT_S16_BE, AFMT_S16_BE},
+        {FMT_U16_LE, AFMT_U16_LE},
+        {FMT_U16_BE, AFMT_U16_BE},
+#ifdef AFMT_S24_LE
+        {FMT_S24_LE, AFMT_S24_LE},
+        {FMT_S24_BE, AFMT_S24_BE},
+#endif
+#ifdef AFMT_S32_LE
+        {FMT_S32_LE, AFMT_S32_LE},
+        {FMT_S32_BE, AFMT_S32_BE},
+#endif
+    };
+
+    int count;
+
+    for (count = 0; count < aud::n_elems(table); count++)
+    {
+        if (table[count].aud_format == aud_format)
+        {
+            return table[count].format;
+        }
+    }
+
+    return -1;
+}
+
+int oss_format_to_bytes(int format)
+{
+    int bytes = 1;
+
+    switch (format)
+    {
+        case AFMT_U8:
+        case AFMT_S8:
+            bytes = 1;
+            break;
+        case AFMT_S16_LE:
+        case AFMT_S16_BE:
+        case AFMT_U16_LE:
+        case AFMT_U16_BE:
+            bytes = 2;
+            break;
+#ifdef AFMT_S24_LE
+        case AFMT_S24_LE:
+        case AFMT_S24_BE:
+            bytes = 4;
+            break;
+#endif
+#ifdef AFMT_S32_LE
+        case AFMT_S32_LE:
+        case AFMT_S32_BE:
+            bytes = 4;
+            break;
+#endif
+#ifdef AFMT_FLOAT
+        case AFMT_FLOAT:
+            bytes = sizeof(float);
+            break;
+#endif
+    }
+
+    return bytes;
+}
+
+const char *oss_describe_error()
+{
+    const struct
+    {
+        int error;
+        const char *text;
+    }
+    table[] =
+    {
+        {EINVAL, "The ioctl call is not supported by current OSS version."},
+        {EACCES, "You do not have permissions to access the device."},
+        {EBUSY,  "The device is busy. There is some other application using it."},
+        {ENXIO,  "OSS has not detected any supported sound hardware in your system."},
+        {ENODEV, "The device file was found in /dev but OSS is not loaded. You need to "
+                 "load it by executing the soundon command."},
+        {ENOSPC, "Your system cannot allocate memory for the device buffers. Reboot your "
+                 "machine and try again."},
+        {ENOENT, "The device file is missing from /dev. Perhaps you have not installed "
+                 "and started Open Sound System yet."},
+    };
+
+    int count;
+    for (count = 0; count < aud::n_elems(table); count++)
+    {
+        if (table[count].error == errno)
+            return table[count].text;
+    }
+
+    return strerror(errno);
+}
+
+#ifdef SNDCTL_SYSINFO
+int oss_probe_for_adev(oss_sysinfo *sysinfo)
+{
+    int num;
+    if ((num = sysinfo->numaudios) < 1)
+    {
+        errno = ENXIO;
+        return -1;
+    }
+
+    return num;
+}
+#endif
+
+bool oss_hardware_present()
+{
+    int mixerfd;
+
+    CHECK_NOISY(mixerfd = open, DEFAULT_MIXER, O_RDWR, 0);
+
+#ifdef SNDCTL_SYSINFO
+    oss_sysinfo sysinfo;
+    memset(&sysinfo, 0, sizeof sysinfo);
+    CHECK(ioctl, mixerfd, SNDCTL_SYSINFO, &sysinfo);
+    CHECK_NOISY(oss_probe_for_adev, &sysinfo);
+#endif
+
+    close(mixerfd);
+    return true;
+
+FAILED:
+    close(mixerfd);
+    return false;
+}
diff --git a/src/playlist-manager/Makefile b/src/playlist-manager/Makefile
new file mode 100644
index 000000000000..2be43667c9bb
--- /dev/null
+++ b/src/playlist-manager/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = playlist-manager${PLUGIN_SUFFIX}
+
+SRCS = playlist-manager.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
+
+LD = ${CXX}
+CPPFLAGS += -I../.. ${GTK_CFLAGS}
+CFLAGS += ${PLUGIN_CFLAGS}
+LIBS += ${GTK_LIBS} -laudgui
diff --git a/src/playlist-manager/playlist-manager.cc b/src/playlist-manager/playlist-manager.cc
new file mode 100644
index 000000000000..a006aacd6d23
--- /dev/null
+++ b/src/playlist-manager/playlist-manager.cc
@@ -0,0 +1,271 @@
+/*
+ * Playlist Manager Plugin for Audacious
+ * Copyright 2006-2014 Giacomo Lozito, John Lindgren, and Thomas Lange
+ *
+ * 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 <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+#include <libaudgui/list.h>
+
+#include <string.h>
+
+class PlaylistManager : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Playlist Manager"),
+        PACKAGE
+    };
+
+    constexpr PlaylistManager () : GeneralPlugin (info, false) {}
+
+    void * get_gtk_widget ();
+    int take_message (const char * code, const void * data, int size);
+};
+
+EXPORT PlaylistManager aud_plugin_instance;
+
+static GtkWidget * focus_widget;
+
+static void activate_row (void * user, int row);
+
+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 ());
+}
+
+static void get_value (void * user, int row, int column, GValue * value)
+{
+    switch (column)
+    {
+    case 0:
+    {
+        g_value_set_string (value, aud_playlist_get_title (row));
+        break;
+    }
+    case 1:
+        g_value_set_int (value, aud_playlist_entry_count (row));
+        break;
+    }
+}
+
+static bool get_selected (void * user, int row)
+{
+    return (row == aud_playlist_get_active ());
+}
+
+static void set_selected (void * user, int row, bool selected)
+{
+    if (selected)
+        aud_playlist_set_active (row);
+}
+
+static void select_all (void * user, bool selected)
+{
+}
+
+static void activate_row (void * user, int row)
+{
+    aud_playlist_set_active (row);
+    aud_playlist_play (row);
+}
+
+static void shift_rows (void * user, int row, int before)
+{
+    if (before < row)
+        aud_playlist_reorder (row, before, 1);
+    else if (before - 1 > row)
+        aud_playlist_reorder (row, before - 1, 1);
+}
+
+static const AudguiListCallbacks callbacks = {
+    get_value,
+    get_selected,
+    set_selected,
+    select_all,
+    activate_row,
+    nullptr,  // right_click
+    shift_rows
+};
+
+static gboolean search_cb (GtkTreeModel * model, int column, const char * key,
+ GtkTreeIter * iter, void * user)
+{
+    GtkTreePath * path = gtk_tree_model_get_path (model, iter);
+    g_return_val_if_fail (path, true);
+    int row = gtk_tree_path_get_indices (path)[0];
+    gtk_tree_path_free (path);
+
+    String title = aud_playlist_get_title (row);
+    g_return_val_if_fail (title, true);
+
+    Index<String> keys = str_list_to_index (key, " ");
+
+    if (! keys.len ())
+        return true;  /* not matched */
+
+    for (const String & key : keys)
+    {
+        if (! strstr_nocase_utf8 (title, key))
+            return true;  /* not matched */
+    }
+
+    return false;  /* matched */
+}
+
+static gboolean position_changed = false;
+static gboolean playlist_activated = false;
+
+static void update_hook (void * data, void * list_)
+{
+    auto level = aud::from_ptr<Playlist::UpdateLevel> (data);
+    GtkWidget * list = (GtkWidget *) list_;
+    int rows = aud_playlist_count ();
+
+    if (level == Playlist::Structure)
+    {
+        int old_rows = audgui_list_row_count (list);
+
+        if (rows < old_rows)
+            audgui_list_delete_rows (list, rows, old_rows - rows);
+        else if (rows > old_rows)
+            audgui_list_insert_rows (list, old_rows, rows - old_rows);
+
+        position_changed = true;
+        playlist_activated = true;
+    }
+
+    if (level >= Playlist::Metadata)
+        audgui_list_update_rows (list, 0, rows);
+
+    if (playlist_activated)
+    {
+        audgui_list_set_focus (list, aud_playlist_get_active ());
+        audgui_list_update_selection (list, 0, rows);
+        playlist_activated = false;
+    }
+
+    if (position_changed)
+    {
+        audgui_list_set_highlight (list, aud_playlist_get_playing ());
+        position_changed = false;
+    }
+}
+
+static void activate_hook (void * data, void * list_)
+{
+    GtkWidget * list = (GtkWidget *) list_;
+
+    if (aud_playlist_update_pending ())
+        playlist_activated = true;
+    else
+    {
+        audgui_list_set_focus (list, aud_playlist_get_active ());
+        audgui_list_update_selection (list, 0, aud_playlist_count ());
+    }
+}
+
+static void position_hook (void * data, void * list_)
+{
+    GtkWidget * list = (GtkWidget *) list_;
+
+    if (aud_playlist_update_pending ())
+        position_changed = true;
+    else
+        audgui_list_set_highlight (list, aud_playlist_get_playing ());
+}
+
+static void destroy_cb (GtkWidget * window)
+{
+    hook_dissociate ("playlist update", update_hook);
+    hook_dissociate ("playlist activate", activate_hook);
+    hook_dissociate ("playlist set playing", position_hook);
+
+    focus_widget = nullptr;
+}
+
+void * PlaylistManager::get_gtk_widget ()
+{
+    GtkWidget * playman_vbox = gtk_vbox_new (false, 6);
+
+    /* ListView */
+    GtkWidget * playman_pl_lv = audgui_list_new (& callbacks, nullptr, aud_playlist_count ());
+    audgui_list_add_column (playman_pl_lv, _("Title"), 0, G_TYPE_STRING, -1);
+    audgui_list_add_column (playman_pl_lv, _("Entries"), 1, G_TYPE_INT, 7);
+    audgui_list_set_highlight (playman_pl_lv, aud_playlist_get_playing ());
+    gtk_tree_view_set_search_equal_func ((GtkTreeView *) playman_pl_lv,
+     search_cb, nullptr, nullptr);
+    hook_associate ("playlist update", update_hook, playman_pl_lv);
+    hook_associate ("playlist activate", activate_hook, playman_pl_lv);
+    hook_associate ("playlist set playing", position_hook, playman_pl_lv);
+
+    GtkWidget * playman_pl_lv_sw = gtk_scrolled_window_new (nullptr, nullptr);
+    gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) playman_pl_lv_sw,
+     GTK_SHADOW_IN);
+    gtk_scrolled_window_set_policy ((GtkScrolledWindow *) playman_pl_lv_sw,
+     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_container_add ((GtkContainer *) playman_pl_lv_sw, playman_pl_lv);
+    gtk_box_pack_start ((GtkBox *) playman_vbox, playman_pl_lv_sw, true, true, 0);
+
+    /* ButtonBox */
+    GtkWidget * playman_button_hbox = gtk_hbox_new (false, 6);
+    GtkWidget * new_button = audgui_button_new (_("_New"), "document-new", new_cb, 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);
+
+    gtk_box_pack_start ((GtkBox *) playman_button_hbox, new_button, false, false, 0);
+    gtk_box_pack_start ((GtkBox *) playman_button_hbox, delete_button, false, false, 0);
+    gtk_box_pack_end ((GtkBox *) playman_button_hbox, rename_button, false, false, 0);
+    gtk_box_pack_start ((GtkBox *) playman_vbox, playman_button_hbox, false, false, 0);
+
+    focus_widget = playman_pl_lv;
+
+    g_signal_connect (playman_vbox, "destroy", (GCallback) destroy_cb, nullptr);
+
+    return playman_vbox;
+}
+
+int PlaylistManager::take_message (const char * code, const void * data, int size)
+{
+    if (! strcmp (code, "grab focus"))
+    {
+        if (focus_widget)
+            gtk_widget_grab_focus (focus_widget);
+
+        return 0;
+    }
+
+    return -1;
+}
diff --git a/src/pls/Makefile b/src/pls/Makefile
index 420a9acffbac..5dc3e6955a87 100644
--- a/src/pls/Makefile
+++ b/src/pls/Makefile
@@ -1,11 +1,11 @@
 PLUGIN = pls${PLUGIN_SUFFIX}
-SRCS = pls.c
+SRCS = pls.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/pls/pls.c b/src/pls/pls.c
deleted file mode 100644
index 2cf7ed44ede8..000000000000
--- a/src/pls/pls.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- *                    Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
- * Copyright (c) 2011-2013 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; 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/inifile.h>
-
-typedef struct {
-    const char * filename;
-    bool_t valid_heading;
-    Index * filenames;
-} PLSLoadState;
-
-void pls_handle_heading (const char * heading, void * data)
-{
-    PLSLoadState * state = data;
-
-    state->valid_heading = ! g_ascii_strcasecmp (heading, "playlist");
-}
-
-void pls_handle_entry (const char * key, const char * value, void * data)
-{
-    PLSLoadState * state = data;
-
-    if (! state->valid_heading || g_ascii_strncasecmp (key, "file", 4))
-        return;
-
-    char * uri = aud_construct_uri (value, state->filename);
-    if (uri)
-        index_insert (state->filenames, -1, uri);
-}
-
-static bool_t playlist_load_pls (const char * filename, VFSFile * file,
- char * * title, Index * filenames, Index * tuples)
-{
-    PLSLoadState state = {
-        .filename = filename,
-        .valid_heading = FALSE,
-        .filenames = filenames
-    };
-
-    inifile_parse (file, pls_handle_heading, pls_handle_entry, & state);
-
-    return (index_count (filenames) != 0);
-}
-
-static bool_t playlist_save_pls (const char * filename, VFSFile * file,
-                                   const char * title, Index * filenames, Index * tuples)
-{
-    int entries = index_count (filenames);
-
-    vfs_fprintf (file, "[playlist]\n");
-    vfs_fprintf (file, "NumberOfEntries=%d\n", entries);
-
-    for (int count = 0; count < entries; count ++)
-    {
-        const char * filename = index_get (filenames, count);
-        char * fn;
-
-        if (! strncmp (filename, "file://", 7))
-            fn = uri_to_filename (filename);
-        else
-            fn = str_ref (filename);
-
-        vfs_fprintf (file, "File%d=%s\n", 1 + count, fn);
-        str_unref (fn);
-    }
-
-    return TRUE;
-}
-
-static const char * const pls_exts[] = {"pls", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
-    .name = N_("PLS Playlists"),
-    .domain = PACKAGE,
-    .extensions = pls_exts,
-    .load = playlist_load_pls,
-    .save = playlist_save_pls
-)
diff --git a/src/pls/pls.cc b/src/pls/pls.cc
new file mode 100644
index 000000000000..409545384cfd
--- /dev/null
+++ b/src/pls/pls.cc
@@ -0,0 +1,100 @@
+/*
+ * Audacious: A cross-platform multimedia player
+ * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
+ *                    Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
+ * Copyright (c) 2011-2013 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; 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/inifile.h>
+
+static const char * const pls_exts[] = {"pls"};
+
+class PLSLoader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("PLS Playlists"), PACKAGE};
+
+    constexpr PLSLoader () : PlaylistPlugin (info, pls_exts, true) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+    bool save (const char * filename, VFSFile & file, const char * title,
+     const Index<PlaylistAddItem> & items);
+};
+
+EXPORT PLSLoader aud_plugin_instance;
+
+class PLSParser : public IniParser
+{
+public:
+    PLSParser (const char * filename, Index<PlaylistAddItem> & items) :
+        filename (filename),
+        items (items),
+        valid_heading (false) {}
+
+private:
+    const char * filename;
+    Index<PlaylistAddItem> & items;
+    bool valid_heading;
+
+    void handle_heading (const char * heading)
+        { valid_heading = ! strcmp_nocase (heading, "playlist"); }
+
+    void handle_entry (const char * key, const char * value)
+    {
+        if (! valid_heading || strcmp_nocase (key, "file", 4))
+            return;
+
+        StringBuf uri = uri_construct (value, filename);
+        if (uri)
+            items.append (String (uri));
+    }
+};
+
+bool PLSLoader::load (const char * filename, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    PLSParser (filename, items).parse (file);
+    return (items.len () > 0);
+}
+
+bool PLSLoader::save (const char * filename, VFSFile & file, const char * title,
+ const Index<PlaylistAddItem> & items)
+{
+    int entries = items.len ();
+
+    StringBuf header = str_printf ("[playlist]\nNumberOfEntries=%d\n", entries);
+    if (file.fwrite (header, 1, header.len ()) != header.len ())
+        return false;
+
+    for (int count = 0; count < entries; count ++)
+    {
+        const char * uri = items[count].filename;
+        StringBuf local = uri_to_filename (uri);
+        StringBuf line = str_printf ("File%d=%s\n", 1 + count, local ? local : uri);
+        if (file.fwrite (line, 1, line.len ()) != line.len ())
+            return false;
+    }
+
+    return true;
+}
diff --git a/src/psf/Makefile b/src/psf/Makefile
index 4984a7667d48..0c93a1202917 100644
--- a/src/psf/Makefile
+++ b/src/psf/Makefile
@@ -1,22 +1,24 @@
 PLUGIN = psf2${PLUGIN_SUFFIX}
 
-SRCS = corlett.c \
-       plugin.c \
-       psx.c \
-       psx_hw.c \
-       eng_psf.c \
-       eng_psf2.c \
-       eng_spx.c \
-       peops/spu.c \
-       peops2/dma.c \
-       peops2/registers.c \
-       peops2/spu.c \
+SRCS = corlett.cc \
+       plugin.cc \
+       psx.cc \
+       psx_hw.cc \
+       eng_psf.cc \
+       eng_psf2.cc \
+       eng_spx.cc \
+       peops/spu.cc \
+       peops2/dma.cc \
+       peops2/registers.cc \
+       peops2/spu.cc \
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
-CFLAGS += ${PLUGIN_CFLAGS} -O0
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../.. -Ispu/ -I.
-LIBS += -lz ${GLIB_LIBS}
+LD = ${CXX}
+
+CXXFLAGS += ${PLUGIN_CFLAGS} -Wno-sign-compare
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. -Ispu/ -I.
+LIBS += -lz
diff --git a/src/psf/ao.h b/src/psf/ao.h
index 377c784e2ee8..3b89b5173b50 100644
--- a/src/psf/ao.h
+++ b/src/psf/ao.h
@@ -9,6 +9,10 @@
 
 #include <stdint.h>
 
+#define WANT_AUD_BSWAP
+#include <libaudcore/audio.h>
+#include <libaudcore/index.h>
+
 #define AO_SUCCESS					1
 #define AO_FAIL						0
 #define AO_FAIL_DECOMPRESSION		-1
@@ -16,14 +20,6 @@
 #define MAX_DISP_INFO_LENGTH		256
 #define AUDIO_RATE					(44100)
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
 enum
 {
 	COMMAND_NONE = 0,
@@ -37,6 +33,6 @@ enum
 	COMMAND_JUMP
 };
 
-int ao_get_lib(char *filename, uint8_t **buffer, uint64_t *length);
+Index<char> ao_get_lib(char *filename);
 
 #endif // AO_H
diff --git a/src/psf/corlett.c b/src/psf/corlett.c
deleted file mode 100644
index eaac91d415e6..000000000000
--- a/src/psf/corlett.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Audio Overload SDK - generic PSF loader
- *
- * Copyright (c) 2007 R. Belmont and Richard Bannister.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * - Neither the names of R. Belmont and Richard Bannister nor the names of its
- *   contributors may be used to endorse or promote products derived from this
- *   software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// corlett.c
-
-// Decodes file format designed by Neill Corlett (PSF, QSF, ...)
-
-/*
- - First 3 bytes: ASCII signature: "PSF" (case sensitive)
-
-- Next 1 byte: Version byte
-  The version byte is used to determine the type of PSF file.  It does NOT
-  affect the basic structure of the file in any way.
-
-  Currently accepted version bytes are:
-    0x01: Playstation (PSF1)
-    0x02: Playstation 2 (PSF2)
-    0x11: Saturn (SSF) [TENTATIVE]
-    0x12: Dreamcast (DSF) [TENTATIVE]
-    0x21: Nintendo 64 (USF) [RESERVED]
-    0x41: Capcom QSound (QSF)
-
-- Next 4 bytes: Size of reserved area (R), little-endian unsigned long
-
-- Next 4 bytes: Compressed program length (N), little-endian unsigned long
-  This is the length of the program data _after_ compression.
-
-- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long
-  This is the CRC-32 of the program data _after_ compression.  Filling in
-  this value is mandatory, as a PSF file may be regarded as corrupt if it
-  does not match.
-
-- Next R bytes: Reserved area.
-  May be empty if R is 0 bytes.
-
-- Next N bytes: Compressed program, in zlib compress() format.
-  May be empty if N is 0 bytes.
-
-The following data is optional and may be omitted:
-
-- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive)
-  If these 5 bytes do not match, then the remainder of the file may be
-  regarded as invalid and discarded.
-
-- Remainder of file: Uncompressed ASCII tag data.
-*/
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-#include <zlib.h>
-
-#include "ao.h"
-#include "corlett.h"
-
-#define LE32(x) GUINT32_FROM_LE(x)
-
-#define DECOMP_MAX_SIZE		((32 * 1024 * 1024) + 12)
-
-int corlett_decode(uint8_t *input, uint32_t input_len, uint8_t **output, uint64_t *size, corlett_t **c)
-{
-	uint32_t *buf;
-	uint32_t res_area, comp_crc,  actual_crc;
-	uint8_t *decomp_dat, *tag_dec;
-	uLongf decomp_length, comp_length;
-
-	// 32-bit pointer to data
-	buf = (uint32_t *)input;
-
-	// Check we have a PSF format file.
-	if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F'))
-	{
-		return AO_FAIL;
-	}
-
-	// Get our values
-	res_area = LE32(buf[1]);
-	comp_length = LE32(buf[2]);
-	comp_crc = LE32(buf[3]);
-
-	if (comp_length > 0)
-	{
-		// Check length
-		if (input_len < comp_length + 16)
-			return AO_FAIL;
-
-		// Check CRC is correct
-		actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length);
-		if (actual_crc != comp_crc)
-			return AO_FAIL;
-
-		// Decompress data if any
-		decomp_dat = malloc(DECOMP_MAX_SIZE);
-		decomp_length = DECOMP_MAX_SIZE;
-		if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK)
-		{
-			free(decomp_dat);
-			return AO_FAIL;
-		}
-
-		// Resize memory buffer to what we actually need
-		decomp_dat = realloc(decomp_dat, (size_t)decomp_length + 1);
-	}
-	else
-	{
-		decomp_dat = NULL;
-		decomp_length =  0;
-	}
-
-	// Make structure
-	*c = malloc(sizeof(corlett_t));
-	if (!(*c))
-	{
-		free(decomp_dat);
-		return AO_FAIL;
-	}
-	memset(*c, 0, sizeof(corlett_t));
-	strcpy((*c)->inf_title, "n/a");
-	strcpy((*c)->inf_copy, "n/a");
-	strcpy((*c)->inf_artist, "n/a");
-	strcpy((*c)->inf_game, "n/a");
-	strcpy((*c)->inf_year, "n/a");
-	strcpy((*c)->inf_length, "n/a");
-	strcpy((*c)->inf_fade, "n/a");
-
-	// set reserved section pointer
-	(*c)->res_section = &buf[4];
-	(*c)->res_size = res_area;
-
-	// Return it
-	if (output != NULL && size != NULL)
-	{
-		*output = decomp_dat;
-		*size = decomp_length;
-	}
-	else
-		free(decomp_dat);
-
-	// Next check for tags
-	input_len -= (comp_length + 16 + res_area);
-	if (input_len < 5)
-		return AO_SUCCESS;
-
-//	printf("\n\nNew corlett: input len %d\n", input_len);
-
-	tag_dec = input + (comp_length + res_area + 16);
-	if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']'))
-	{
-		int l, num_tags, data;
-
-		// Tags found!
-		tag_dec += 5;
-		input_len -= 5;
-
-		data = FALSE;
-		num_tags = 0;
-		l = 0;
-		while (input_len && (num_tags < MAX_UNKNOWN_TAGS))
-		{
-			if (data)
-			{
-				if ((*tag_dec == 0xA) || (*tag_dec == 0x00))
-				{
-					(*c)->tag_data[num_tags][l] = 0;
-					data = FALSE;
-					num_tags++;
-					l = 0;
-				}
-				else
-				{
-					(*c)->tag_data[num_tags][l++] = *tag_dec;
-				}
-			}
-			else
-			{
-				if (*tag_dec == '=')
-				{
-					(*c)->tag_name[num_tags][l] = 0;
-					l = 0;
-					data = TRUE;
-				}
-				else
-				{
-					(*c)->tag_name[num_tags][l++] = *tag_dec;
-				}
-			}
-
-			tag_dec++;
-			input_len--;
-		}
-
-
-		// Now, process that tag array into what we expect
-		for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++)
-		{
-			// See if tag belongs in one of the special fields we have
-			if (!g_ascii_strcasecmp((*c)->tag_name[num_tags], "_lib"))
-			{
-				strcpy((*c)->lib, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5))
-			{
-				strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5))
-			{
-				strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5))
-			{
-				strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5))
-			{
-				strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5))
-			{
-				strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5))
-			{
-				strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5))
-			{
-				strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5))
-			{
-				strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8))
-			{
-				strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "title", 5))
-			{
-				strcpy((*c)->inf_title, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9))
-			{
-				strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "artist", 6))
-			{
-				strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "game", 4))
-			{
-				strcpy((*c)->inf_game, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "year", 4))
-			{
-				strcpy((*c)->inf_year, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "length", 6))
-			{
-				strcpy((*c)->inf_length, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "fade", 4))
-			{
-				strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-		}
-	}
-
-	// Bingo
-	return AO_SUCCESS;
-}
-
-uint32_t psfTimeToMS(char *str)
-{
-	int x, c=0;
-	uint32_t acc=0;
-	char s[100];
-
-	strncpy(s,str,100);
-	s[99]=0;
-
-	for (x=strlen(s); x>=0; x--)
-	{
-		if (s[x]=='.' || s[x]==',')
-		{
-			acc=atoi(s+x+1);
-			s[x]=0;
-		}
-		else if (s[x]==':')
-		{
-			if(c==0)
-			{
-				acc+=atoi(s+x+1)*10;
-			}
-			else if(c==1)
-			{
-				acc+=atoi(s+x+(x?1:0))*10*60;
-			}
-
-			c++;
-			s[x]=0;
-		}
-		else if (x==0)
-		{
-			if(c==0)
-			{
-				acc+=atoi(s+x)*10;
-			}
-			else if(c==1)
-			{
-				acc+=atoi(s+x)*10*60;
-			}
-			else if(c==2)
-			{
-				acc+=atoi(s+x)*10*60*60;
-			}
-		}
-	}
-
-	acc*=100;
-	return(acc);
-}
-
diff --git a/src/psf/corlett.cc b/src/psf/corlett.cc
new file mode 100644
index 000000000000..4089c901a938
--- /dev/null
+++ b/src/psf/corlett.cc
@@ -0,0 +1,390 @@
+/*
+ * Audio Overload SDK - generic PSF loader
+ *
+ * Copyright (c) 2007 R. Belmont and Richard Bannister.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ *
+ * - Neither the names of R. Belmont and Richard Bannister nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// corlett.c
+
+// Decodes file format designed by Neill Corlett (PSF, QSF, ...)
+
+/*
+ - First 3 bytes: ASCII signature: "PSF" (case sensitive)
+
+- Next 1 byte: Version byte
+  The version byte is used to determine the type of PSF file.  It does NOT
+  affect the basic structure of the file in any way.
+
+  Currently accepted version bytes are:
+    0x01: Playstation (PSF1)
+    0x02: Playstation 2 (PSF2)
+    0x11: Saturn (SSF) [TENTATIVE]
+    0x12: Dreamcast (DSF) [TENTATIVE]
+    0x21: Nintendo 64 (USF) [RESERVED]
+    0x41: Capcom QSound (QSF)
+
+- Next 4 bytes: Size of reserved area (R), little-endian unsigned long
+
+- Next 4 bytes: Compressed program length (N), little-endian unsigned long
+  This is the length of the program data _after_ compression.
+
+- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long
+  This is the CRC-32 of the program data _after_ compression.  Filling in
+  this value is mandatory, as a PSF file may be regarded as corrupt if it
+  does not match.
+
+- Next R bytes: Reserved area.
+  May be empty if R is 0 bytes.
+
+- Next N bytes: Compressed program, in zlib compress() format.
+  May be empty if N is 0 bytes.
+
+The following data is optional and may be omitted:
+
+- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive)
+  If these 5 bytes do not match, then the remainder of the file may be
+  regarded as invalid and discarded.
+
+- Remainder of file: Uncompressed ASCII tag data.
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <zlib.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "ao.h"
+#include "corlett.h"
+
+#define LE32(x) FROM_LE32(x)
+
+#define DECOMP_MAX_SIZE		((32 * 1024 * 1024) + 12)
+
+int corlett_decode(uint8_t *input, uint32_t input_len, uint8_t **output, uint64_t *size, corlett_t **c)
+{
+	uint32_t *buf;
+	uint32_t res_area, comp_crc,  actual_crc;
+	uint8_t *decomp_dat, *tag_dec;
+	uLongf decomp_length, comp_length;
+
+	// 32-bit pointer to data
+	buf = (uint32_t *)input;
+
+	// Check we have a PSF format file.
+	if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F'))
+	{
+		return AO_FAIL;
+	}
+
+	// Get our values
+	res_area = LE32(buf[1]);
+	comp_length = LE32(buf[2]);
+	comp_crc = LE32(buf[3]);
+
+	if (comp_length > 0)
+	{
+		// Check length
+		if (input_len < comp_length + 16)
+			return AO_FAIL;
+
+		// Check CRC is correct
+		actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length);
+		if (actual_crc != comp_crc)
+			return AO_FAIL;
+
+		// Decompress data if any
+		decomp_dat = (uint8_t *) malloc(DECOMP_MAX_SIZE);
+		decomp_length = DECOMP_MAX_SIZE;
+		if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK)
+		{
+			free(decomp_dat);
+			return AO_FAIL;
+		}
+
+		// Resize memory buffer to what we actually need
+		decomp_dat = (uint8_t *) realloc(decomp_dat, (size_t)decomp_length + 1);
+	}
+	else
+	{
+		decomp_dat = nullptr;
+		decomp_length =  0;
+	}
+
+	// Make structure
+	*c = (corlett_t *) malloc(sizeof(corlett_t));
+	if (!(*c))
+	{
+		free(decomp_dat);
+		return AO_FAIL;
+	}
+	memset(*c, 0, sizeof(corlett_t));
+	strcpy((*c)->inf_title, "n/a");
+	strcpy((*c)->inf_copy, "n/a");
+	strcpy((*c)->inf_artist, "n/a");
+	strcpy((*c)->inf_game, "n/a");
+	strcpy((*c)->inf_year, "n/a");
+	strcpy((*c)->inf_length, "n/a");
+	strcpy((*c)->inf_fade, "n/a");
+
+	// set reserved section pointer
+	(*c)->res_section = &buf[4];
+	(*c)->res_size = res_area;
+
+	// Return it
+	if (output != nullptr && size != nullptr)
+	{
+		*output = decomp_dat;
+		*size = decomp_length;
+	}
+	else
+		free(decomp_dat);
+
+	// Next check for tags
+	input_len -= (comp_length + 16 + res_area);
+	if (input_len < 5)
+		return AO_SUCCESS;
+
+//	printf("\n\nNew corlett: input len %d\n", input_len);
+
+	tag_dec = input + (comp_length + res_area + 16);
+	if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']'))
+	{
+		int l, num_tags, data;
+
+		// Tags found!
+		tag_dec += 5;
+		input_len -= 5;
+
+		data = false;
+		num_tags = 0;
+		l = 0;
+		while (input_len && (num_tags < MAX_UNKNOWN_TAGS))
+		{
+			if (data)
+			{
+				if ((*tag_dec == 0xA) || (*tag_dec == 0x00))
+				{
+					(*c)->tag_data[num_tags][l] = 0;
+					data = false;
+					num_tags++;
+					l = 0;
+				}
+				else
+				{
+					(*c)->tag_data[num_tags][l++] = *tag_dec;
+				}
+			}
+			else
+			{
+				if (*tag_dec == '=')
+				{
+					(*c)->tag_name[num_tags][l] = 0;
+					l = 0;
+					data = true;
+				}
+				else
+				{
+					(*c)->tag_name[num_tags][l++] = *tag_dec;
+				}
+			}
+
+			tag_dec++;
+			input_len--;
+		}
+
+
+		// Now, process that tag array into what we expect
+		for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++)
+		{
+			// See if tag belongs in one of the special fields we have
+			if (!strcmp_nocase((*c)->tag_name[num_tags], "_lib"))
+			{
+				strcpy((*c)->lib, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5))
+			{
+				strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5))
+			{
+				strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5))
+			{
+				strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5))
+			{
+				strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5))
+			{
+				strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5))
+			{
+				strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5))
+			{
+				strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5))
+			{
+				strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8))
+			{
+				strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "title", 5))
+			{
+				strcpy((*c)->inf_title, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9))
+			{
+				strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "artist", 6))
+			{
+				strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "game", 4))
+			{
+				strcpy((*c)->inf_game, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "year", 4))
+			{
+				strcpy((*c)->inf_year, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "length", 6))
+			{
+				strcpy((*c)->inf_length, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "fade", 4))
+			{
+				strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+		}
+	}
+
+	// Bingo
+	return AO_SUCCESS;
+}
+
+uint32_t psfTimeToMS(char *str)
+{
+	int x, c=0;
+	uint32_t acc=0;
+	char s[100];
+
+	strncpy(s,str,100);
+	s[99]=0;
+
+	for (x=strlen(s); x>=0; x--)
+	{
+		if (s[x]=='.' || s[x]==',')
+		{
+			acc=atoi(s+x+1);
+			s[x]=0;
+		}
+		else if (s[x]==':')
+		{
+			if(c==0)
+			{
+				acc+=atoi(s+x+1)*10;
+			}
+			else if(c==1)
+			{
+				acc+=atoi(s+x+(x?1:0))*10*60;
+			}
+
+			c++;
+			s[x]=0;
+		}
+		else if (x==0)
+		{
+			if(c==0)
+			{
+				acc+=atoi(s+x)*10;
+			}
+			else if(c==1)
+			{
+				acc+=atoi(s+x)*10*60;
+			}
+			else if(c==2)
+			{
+				acc+=atoi(s+x)*10*60*60;
+			}
+		}
+	}
+
+	acc*=100;
+	return(acc);
+}
+
diff --git a/src/psf/cpuintrf.h b/src/psf/cpuintrf.h
index 69035ddfd45e..8678e29a98ef 100644
--- a/src/psf/cpuintrf.h
+++ b/src/psf/cpuintrf.h
@@ -10,7 +10,7 @@
 
 #define CLEAR_LINE		0		/* clear (a fired, held or pulsed) line */
 #define ASSERT_LINE     1       /* assert an interrupt immediately */
-#define HOLD_LINE       2       /* hold interrupt line until enable is TRUE */
+#define HOLD_LINE       2       /* hold interrupt line until enable is true */
 #define PULSE_LINE		3		/* pulse interrupt line for one instruction */
 
 #define MAX_REGS		64		/* maximum number of register of any CPU */
@@ -650,7 +650,7 @@ enum
 
 	CPUINFO_PTR_CPU_SPECIFIC = 0x18000,					/* R/W: CPU-specific values start here */
 
-	/* --- the following bits of info are returned as NULL-terminated strings --- */
+	/* --- the following bits of info are returned as nullptr-terminated strings --- */
 	CPUINFO_STR_FIRST = 0x20000,
 
 	CPUINFO_STR_NAME = CPUINFO_STR_FIRST,				/* R/O: name of the CPU */
diff --git a/src/psf/eng_protos.h b/src/psf/eng_protos.h
index a5b4eaf4641e..d3488eb44895 100644
--- a/src/psf/eng_protos.h
+++ b/src/psf/eng_protos.h
@@ -1,20 +1,20 @@
-#include <audacious/plugin.h>
+#include <libaudcore/plugin.h>
 
 int32_t psf2_start(uint8_t *, uint32_t length);
-int32_t psf2_execute(void);
+int32_t psf2_execute(void (*update)(const void *, int));
 int32_t psf2_stop(void);
 int32_t psf2_command(int32_t, int32_t);
 int32_t psf2_fill_info(Tuple *);
 int   psf2_seek(uint32_t);
 
 int32_t psf_start(uint8_t *buffer, uint32_t length);
-int32_t psf_execute(void);
+int32_t psf_execute(void (*update)(const void *, int));
 int   psf_seek(uint32_t);
 int32_t psf_stop(void);
 
 int32_t spx_start(uint8_t *buffer, uint32_t length);
-int32_t spx_execute(void);
+int32_t spx_execute(void (*update)(const void *, int));
 int   spx_seek(uint32_t);
 int32_t spx_stop(void);
 
-extern bool_t stop_flag;
+extern bool stop_flag;
diff --git a/src/psf/eng_psf.c b/src/psf/eng_psf.c
deleted file mode 100644
index caa607a69abb..000000000000
--- a/src/psf/eng_psf.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
-	Audio Overload SDK - PSF file format engine
-
-	Copyright (c) 2007 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include "ao.h"
-#include "eng_protos.h"
-#include "cpuintrf.h"
-#include "psx.h"
-
-#include "peops/stdafx.h"
-#include "peops/externals.h"
-#include "peops/regs.h"
-#include "peops/registers.h"
-#include "peops/spu.h"
-
-#include "corlett.h"
-
-#define DEBUG_LOADER	(0)
-
-#define LE32(x) GUINT32_FROM_LE(x)
-
-static corlett_t	*c = NULL;
-static char 		psfby[256];
-int			psf_refresh  = -1;
-
-
-// main RAM
-extern uint32_t psx_ram[((2*1024*1024)/4)+4];
-extern uint32_t psx_scratch[0x400];
-extern uint32_t initial_ram[((2*1024*1024)/4)+4];
-extern uint32_t initial_scratch[0x400];
-static uint32_t initialPC, initialGP, initialSP;
-
-extern void mips_init( void );
-extern void mips_reset( void *param );
-extern int mips_execute( int cycles );
-extern void mips_set_info(uint32_t state, union cpuinfo *info);
-extern void psx_hw_init(void);
-extern void psx_hw_slice(void);
-extern void psx_hw_frame(void);
-extern void setlength(int32_t stop, int32_t fade);
-
-int32_t psf_start(uint8_t *buffer, uint32_t length)
-{
-	uint8_t *file, *lib_decoded, *lib_raw_file, *alib_decoded;
-	uint32_t offset, plength, PC, SP, GP, lengthMS, fadeMS;
-	uint64_t file_len, lib_len, lib_raw_length, alib_len;
-	corlett_t *lib;
-	int i;
-	union cpuinfo mipsinfo;
-
-	// clear PSX work RAM before we start scribbling in it
-	memset(psx_ram, 0, 2*1024*1024);
-
-//	printf("Length = %d\n", length);
-
-	// Decode the current GSF
-	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
-	{
-		return AO_FAIL;
-	}
-
-//	printf("file_len %d reserve %d\n", file_len, c->res_size);
-
-	// check for PSX EXE signature
-	if (strncmp((char *)file, "PS-X EXE", 8))
-	{
-		return AO_FAIL;
-	}
-
-	#if DEBUG_LOADER
-	offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
-	printf("Text section start: %x\n", offset);
-	offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
-	printf("Text section size: %x\n", offset);
-	printf("Region: [%s]\n", &file[0x4c]);
-	printf("refresh: [%s]\n", c->inf_refresh);
-	#endif
-
-	if (c->inf_refresh[0] == '5')
-	{
-		psf_refresh = 50;
-	}
-	if (c->inf_refresh[0] == '6')
-	{
-		psf_refresh = 60;
-	}
-
-	PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24;
-	GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24;
-	SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24;
-
-	#if DEBUG_LOADER
-	printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP);
-	#endif
-
-	// Get the library file, if any
-	if (c->lib[0] != 0)
-	{
-		uint64_t tmp_length;
-
-		#if DEBUG_LOADER
-		printf("Loading library: %s\n", c->lib);
-		#endif
-		if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
-		{
-			return AO_FAIL;
-		}
-		lib_raw_length = tmp_length;
-
-		if (lib_raw_file == NULL)
-			return AO_FAIL;
-
-		if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
-		{
-			free(lib_raw_file);
-			return AO_FAIL;
-		}
-
-		// Free up raw file
-		free(lib_raw_file);
-
-		if (strncmp((char *)lib_decoded, "PS-X EXE", 8))
-		{
-			printf("Major error!  PSF was OK, but referenced library is not!\n");
-			free(lib);
-			return AO_FAIL;
-		}
-
-		#if DEBUG_LOADER
-		offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
-		printf("Text section start: %x\n", offset);
-		offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
-		printf("Text section size: %x\n", offset);
-		printf("Region: [%s]\n", &lib_decoded[0x4c]);
-		printf("refresh: [%s]\n", lib->inf_refresh);
-		#endif
-
-		// if the original file had no refresh tag, give the lib a shot
-		if (psf_refresh == -1)
-		{
-			if (lib->inf_refresh[0] == '5')
-			{
-				psf_refresh = 50;
-			}
-			if (lib->inf_refresh[0] == '6')
-			{
-				psf_refresh = 60;
-			}
-		}
-
-		PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24;
-		GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24;
-		SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24;
-
-		#if DEBUG_LOADER
-		printf("Library: PC %x GP %x SP %x\n", PC, GP, SP);
-		#endif
-
-		// now patch the file into RAM
-		offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
-		offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
-
-		/* valid PS-X EXE image must be at least 2048 bytes, plength section may be wrong on
-		 * shite rips... --nenolod */
-		if (lib_len < 2048)
-			plength = 0;
-		else
-			plength = lib_len - 2048;
-
-		#if DEBUG_LOADER
-		printf("library offset: %x plength: %d\n", offset, plength);
-		#endif
-		memcpy(&psx_ram[offset/4], lib_decoded + 2048, plength);
-
-		// Dispose the corlett structure for the lib - we don't use it
-		free(lib);
-	}
-
-	// now patch the main file into RAM OVER the libraries (but not the aux lib)
-	offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
-	offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
-
-	if (file_len < 2048)
-		plength = 0;
-	else
-		plength = file_len - 2048;
-
-	memcpy(&psx_ram[offset/4], file + 2048, plength);
-
-	// load any auxiliary libraries now
-	for (i = 0; i < 8; i++)
-	{
-		if (c->libaux[i][0] != 0)
-		{
-			uint64_t tmp_length;
-
-			#if DEBUG_LOADER
-			printf("Loading aux library: %s\n", c->libaux[i]);
-			#endif
-
-			if (ao_get_lib(c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS)
-			{
-				return AO_FAIL;
-			}
-			lib_raw_length = tmp_length;
-
-			if (lib_raw_file == NULL)
-				return AO_FAIL;
-
-			if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS)
-			{
-				free(lib_raw_file);
-				return AO_FAIL;
-			}
-
-			// Free up raw file
-			free(lib_raw_file);
-
-			if (strncmp((char *)alib_decoded, "PS-X EXE", 8))
-			{
-				printf("Major error!  PSF was OK, but referenced library is not!\n");
-				free(lib);
-				return AO_FAIL;
-			}
-
-			#if DEBUG_LOADER
-			offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
-			printf("Text section start: %x\n", offset);
-			offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
-			printf("Text section size: %x\n", offset);
-			printf("Region: [%s]\n", &alib_decoded[0x4c]);
-			#endif
-
-			// now patch the file into RAM
-			offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
-			offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
-
-			if (alib_len < 2048)
-				plength = 0;
-			else
-				plength = alib_len - 2048;
-
-			memcpy(&psx_ram[offset/4], alib_decoded + 2048, plength);
-
-			// Dispose the corlett structure for the lib - we don't use it
-			free(lib);
-		}
-	}
-
-	free(file);
-//	free(lib_decoded);
-
-	// Finally, set psfby tag
-	strcpy(psfby, "n/a");
-	if (c)
-	{
-		int i;
-		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
-		{
-			if (!g_ascii_strcasecmp(c->tag_name[i], "psfby"))
-				strcpy(psfby, c->tag_data[i]);
-		}
-	}
-
-	mips_init();
-	mips_reset(NULL);
-
-	// set the initial PC, SP, GP
-	#if DEBUG_LOADER
-	printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP);
-	printf("Refresh = %d\n", psf_refresh);
-	#endif
-	mipsinfo.i = PC;
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-	// set some reasonable default for the stack
-	if (SP == 0)
-	{
-		SP = 0x801fff00;
-	}
-
-	mipsinfo.i = SP;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
-
-	mipsinfo.i = GP;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
-
-	#if DEBUG_LOADER && 1
-	{
-		FILE *f;
-
-		f = fopen("psxram.bin", "wb");
-		fwrite(psx_ram, 2*1024*1024, 1, f);
-		fclose(f);
-	}
-	#endif
-
-	psx_hw_init();
-	SPUinit();
-	SPUopen();
-
-	lengthMS = psfTimeToMS(c->inf_length);
-	fadeMS = psfTimeToMS(c->inf_fade);
-
-	#if DEBUG_LOADER
-	printf("length %d fade %d\n", lengthMS, fadeMS);
-	#endif
-
-	if (lengthMS == 0)
-	{
-		lengthMS = ~0;
-	}
-
-	setlength(lengthMS, fadeMS);
-
-	// patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
-	// and rely on Highly Experimental's buggy-ass CPU to rescue them.  Verified on real hardware
-	// that the initial code is wrong.
-	if (c->inf_game)
-	{
-		if (!strcmp(c->inf_game, "Chocobo Dungeon 2"))
-		{
-			if (psx_ram[0xbc090/4] == LE32(0x0802f040))
-			{
-		 		psx_ram[0xbc090/4] = LE32(0);
-				psx_ram[0xbc094/4] = LE32(0x0802f040);
-				psx_ram[0xbc098/4] = LE32(0);
-			}
-		}
-	}
-
-//	psx_ram[0x118b8/4] = LE32(0);	// crash 2 hack
-
-	// backup the initial state for restart
-	memcpy(initial_ram, psx_ram, 2*1024*1024);
-	memcpy(initial_scratch, psx_scratch, 0x400);
-	initialPC = PC;
-	initialGP = GP;
-	initialSP = SP;
-
-	mips_execute(5000);
-
-	return AO_SUCCESS;
-}
-
-int32_t psf_execute(void)
-{
-	int i;
-
-	while (!stop_flag) {
-		for (i = 0; i < 44100 / 60; i++) {
-			psx_hw_slice();
-			SPUasync(384);
-		}
-
-		psx_hw_frame();
-	}
-
-	return AO_SUCCESS;
-}
-
-int32_t psf_stop(void)
-{
-	SPUclose();
-	free(c);
-
-	return AO_SUCCESS;
-}
diff --git a/src/psf/eng_psf.cc b/src/psf/eng_psf.cc
new file mode 100644
index 000000000000..61cc70319ec1
--- /dev/null
+++ b/src/psf/eng_psf.cc
@@ -0,0 +1,372 @@
+/*
+	Audio Overload SDK - PSF file format engine
+
+	Copyright (c) 2007 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "ao.h"
+#include "eng_protos.h"
+#include "cpuintrf.h"
+#include "psx.h"
+
+#include "peops/stdafx.h"
+#include "peops/externals.h"
+#include "peops/regs.h"
+#include "peops/registers.h"
+#include "peops/spu.h"
+
+#include "corlett.h"
+
+#define DEBUG_LOADER	(0)
+
+#define LE32(x) FROM_LE32(x)
+
+static corlett_t	*c = nullptr;
+static char 		psfby[256];
+int			psf_refresh  = -1;
+
+
+// main RAM
+extern uint32_t psx_ram[((2*1024*1024)/4)+4];
+extern uint32_t psx_scratch[0x400];
+extern uint32_t initial_ram[((2*1024*1024)/4)+4];
+extern uint32_t initial_scratch[0x400];
+static uint32_t initialPC, initialGP, initialSP;
+
+extern void mips_init( void );
+extern void mips_reset( void *param );
+extern int mips_execute( int cycles );
+extern void mips_set_info(uint32_t state, union cpuinfo *info);
+extern void psx_hw_init(void);
+extern void psx_hw_slice(void);
+extern void psx_hw_frame(void);
+extern void setlength(int32_t stop, int32_t fade);
+
+int32_t psf_start(uint8_t *buffer, uint32_t length)
+{
+	uint8_t *file, *lib_decoded, *alib_decoded;
+	uint32_t offset, plength, PC, SP, GP, lengthMS, fadeMS;
+	uint64_t file_len, lib_len, alib_len;
+	corlett_t *lib;
+	int i;
+	union cpuinfo mipsinfo;
+
+	// clear PSX work RAM before we start scribbling in it
+	memset(psx_ram, 0, 2*1024*1024);
+
+//	printf("Length = %d\n", length);
+
+	// Decode the current GSF
+	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
+	{
+		return AO_FAIL;
+	}
+
+//	printf("file_len %d reserve %d\n", file_len, c->res_size);
+
+	// check for PSX EXE signature
+	if (strncmp((char *)file, "PS-X EXE", 8))
+	{
+		return AO_FAIL;
+	}
+
+	#if DEBUG_LOADER
+	offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
+	printf("Text section start: %x\n", offset);
+	offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
+	printf("Text section size: %x\n", offset);
+	printf("Region: [%s]\n", &file[0x4c]);
+	printf("refresh: [%s]\n", c->inf_refresh);
+	#endif
+
+	if (c->inf_refresh[0] == '5')
+	{
+		psf_refresh = 50;
+	}
+	if (c->inf_refresh[0] == '6')
+	{
+		psf_refresh = 60;
+	}
+
+	PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24;
+	GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24;
+	SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24;
+
+	#if DEBUG_LOADER
+	printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP);
+	#endif
+
+	// Get the library file, if any
+	if (c->lib[0] != 0)
+	{
+		#if DEBUG_LOADER
+		printf("Loading library: %s\n", c->lib);
+		#endif
+
+		Index<char> buf = ao_get_lib(c->lib);
+
+		if (!buf.len())
+			return AO_FAIL;
+
+		if (corlett_decode((uint8_t *)buf.begin(), buf.len(), &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
+			return AO_FAIL;
+
+		if (strncmp((char *)lib_decoded, "PS-X EXE", 8))
+		{
+			printf("Major error!  PSF was OK, but referenced library is not!\n");
+			free(lib);
+			return AO_FAIL;
+		}
+
+		#if DEBUG_LOADER
+		offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
+		printf("Text section start: %x\n", offset);
+		offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
+		printf("Text section size: %x\n", offset);
+		printf("Region: [%s]\n", &lib_decoded[0x4c]);
+		printf("refresh: [%s]\n", lib->inf_refresh);
+		#endif
+
+		// if the original file had no refresh tag, give the lib a shot
+		if (psf_refresh == -1)
+		{
+			if (lib->inf_refresh[0] == '5')
+			{
+				psf_refresh = 50;
+			}
+			if (lib->inf_refresh[0] == '6')
+			{
+				psf_refresh = 60;
+			}
+		}
+
+		PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24;
+		GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24;
+		SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24;
+
+		#if DEBUG_LOADER
+		printf("Library: PC %x GP %x SP %x\n", PC, GP, SP);
+		#endif
+
+		// now patch the file into RAM
+		offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
+		offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
+
+		/* valid PS-X EXE image must be at least 2048 bytes, plength section may be wrong on
+		 * shite rips... --nenolod */
+		if (lib_len < 2048)
+			plength = 0;
+		else
+			plength = lib_len - 2048;
+
+		#if DEBUG_LOADER
+		printf("library offset: %x plength: %d\n", offset, plength);
+		#endif
+		memcpy(&psx_ram[offset/4], lib_decoded + 2048, plength);
+
+		// Dispose the corlett structure for the lib - we don't use it
+		free(lib);
+	}
+
+	// now patch the main file into RAM OVER the libraries (but not the aux lib)
+	offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
+	offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
+
+	if (file_len < 2048)
+		plength = 0;
+	else
+		plength = file_len - 2048;
+
+	memcpy(&psx_ram[offset/4], file + 2048, plength);
+
+	// load any auxiliary libraries now
+	for (i = 0; i < 8; i++)
+	{
+		if (c->libaux[i][0] != 0)
+		{
+			#if DEBUG_LOADER
+			printf("Loading aux library: %s\n", c->libaux[i]);
+			#endif
+
+			Index<char> buf = ao_get_lib(c->libaux[i]);
+
+			if (!buf.len())
+				return AO_FAIL;
+
+			if (corlett_decode((uint8_t *)buf.begin(), buf.len(), &alib_decoded, &alib_len, &lib) != AO_SUCCESS)
+				return AO_FAIL;
+
+			if (strncmp((char *)alib_decoded, "PS-X EXE", 8))
+			{
+				printf("Major error!  PSF was OK, but referenced library is not!\n");
+				free(lib);
+				return AO_FAIL;
+			}
+
+			#if DEBUG_LOADER
+			offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
+			printf("Text section start: %x\n", offset);
+			offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
+			printf("Text section size: %x\n", offset);
+			printf("Region: [%s]\n", &alib_decoded[0x4c]);
+			#endif
+
+			// now patch the file into RAM
+			offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
+			offset &= 0x3fffffff;	// kill any MIPS cache segment indicators
+
+			if (alib_len < 2048)
+				plength = 0;
+			else
+				plength = alib_len - 2048;
+
+			memcpy(&psx_ram[offset/4], alib_decoded + 2048, plength);
+
+			// Dispose the corlett structure for the lib - we don't use it
+			free(lib);
+		}
+	}
+
+	free(file);
+//	free(lib_decoded);
+
+	// Finally, set psfby tag
+	strcpy(psfby, "n/a");
+	if (c)
+	{
+		int i;
+		for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
+		{
+			if (!strcmp_nocase(c->tag_name[i], "psfby"))
+				strcpy(psfby, c->tag_data[i]);
+		}
+	}
+
+	mips_init();
+	mips_reset(nullptr);
+
+	// set the initial PC, SP, GP
+	#if DEBUG_LOADER
+	printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP);
+	printf("Refresh = %d\n", psf_refresh);
+	#endif
+	mipsinfo.i = PC;
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+	// set some reasonable default for the stack
+	if (SP == 0)
+	{
+		SP = 0x801fff00;
+	}
+
+	mipsinfo.i = SP;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
+
+	mipsinfo.i = GP;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
+
+	#if DEBUG_LOADER && 1
+	{
+		FILE *f;
+
+		f = fopen("psxram.bin", "wb");
+		fwrite(psx_ram, 2*1024*1024, 1, f);
+		fclose(f);
+	}
+	#endif
+
+	psx_hw_init();
+	SPUinit();
+	SPUopen();
+
+	lengthMS = psfTimeToMS(c->inf_length);
+	fadeMS = psfTimeToMS(c->inf_fade);
+
+	#if DEBUG_LOADER
+	printf("length %d fade %d\n", lengthMS, fadeMS);
+	#endif
+
+	if (lengthMS == 0)
+	{
+		lengthMS = ~0;
+	}
+
+	setlength(lengthMS, fadeMS);
+
+	// patch illegal Chocobo Dungeon 2 code - CaitSith2 put a jump in the delay slot from a BNE
+	// and rely on Highly Experimental's buggy-ass CPU to rescue them.  Verified on real hardware
+	// that the initial code is wrong.
+	if (!strcmp(c->inf_game, "Chocobo Dungeon 2"))
+	{
+		if (psx_ram[0xbc090/4] == LE32(0x0802f040))
+		{
+			psx_ram[0xbc090/4] = LE32(0);
+			psx_ram[0xbc094/4] = LE32(0x0802f040);
+			psx_ram[0xbc098/4] = LE32(0);
+		}
+	}
+
+//	psx_ram[0x118b8/4] = LE32(0);	// crash 2 hack
+
+	// backup the initial state for restart
+	memcpy(initial_ram, psx_ram, 2*1024*1024);
+	memcpy(initial_scratch, psx_scratch, 0x400);
+	initialPC = PC;
+	initialGP = GP;
+	initialSP = SP;
+
+	mips_execute(5000);
+
+	return AO_SUCCESS;
+}
+
+int32_t psf_execute(void (*update)(const void *, int))
+{
+	int i;
+
+	while (!stop_flag) {
+		for (i = 0; i < 44100 / 60; i++) {
+			psx_hw_slice();
+			SPUasync(384, update);
+		}
+
+		psx_hw_frame();
+	}
+
+	return AO_SUCCESS;
+}
+
+int32_t psf_stop(void)
+{
+	SPUclose();
+	free(c);
+
+	return AO_SUCCESS;
+}
diff --git a/src/psf/eng_psf2.c b/src/psf/eng_psf2.c
deleted file mode 100644
index d30bff64e4d8..000000000000
--- a/src/psf/eng_psf2.c
+++ /dev/null
@@ -1,671 +0,0 @@
-/*
-	Audio Overload SDK - PSF2 file format engine
-
-	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-//
-// Audio Overload
-// Emulated music player
-//
-// (C) 2000-2008 Richard F. Bannister
-//
-
-//
-// eng_psf2.c
-//
-// References:
-// psf_format.txt v1.6 by Neill Corlett (filesystem and decompression info)
-// Intel ELF format specs ELF.PS (general ELF parsing info)
-// http://ps2dev.org/kb.x?T=457 (IRX relocation and inter-module call info)
-// http://ps2dev.org/ (the whole site - lots of IOP info)
-// spu2regs.txt (comes with SexyPSF source: IOP hardware info)
-// 64-bit ELF Object File Specification: http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf (MIPS ELF relocation types)
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-#include <zlib.h>
-
-#include "ao.h"
-#include "eng_protos.h"
-#include "cpuintrf.h"
-#include "psx.h"
-
-#include "peops2/stdafx.h"
-#include "peops2/externals.h"
-#include "peops2/regs.h"
-#include "peops2/registers.h"
-#include "peops2/spu.h"
-
-#include "corlett.h"
-
-#define DEBUG_LOADER	(0)
-#define MAX_FS		(32)	// maximum # of filesystems (libs and subdirectories)
-
-// ELF relocation helpers
-#define ELF32_R_SYM(val)                ((val) >> 8)
-#define ELF32_R_TYPE(val)               ((val) & 0xff)
-
-#define LE32(x) GUINT32_FROM_LE(x)
-
-static corlett_t	*c = NULL;
-
-// main RAM
-extern uint32_t psx_ram[(2*1024*1024)/4];
-extern uint32_t initial_ram[(2*1024*1024)/4];
-static uint32_t initialPC, initialSP;
-static uint32_t loadAddr, lengthMS, fadeMS;
-
-static uint8_t *filesys[MAX_FS];
-static uint8_t *lib_raw_file;
-static uint32_t fssize[MAX_FS];
-static int num_fs;
-
-extern void mips_init( void );
-extern void mips_reset( void *param );
-extern int mips_execute( int cycles );
-extern void mips_set_info(uint32_t state, union cpuinfo *info);
-extern void psx_hw_init(void);
-extern void ps2_hw_slice(void);
-extern void ps2_hw_frame(void);
-extern void setlength2(int32_t stop, int32_t fade);
-
-static void do_iopmod(uint8_t *start, uint32_t offset)
-{
-	#if DEBUG_LOADER
-	uint32_t nameoffs, saddr, heap, tsize, dsize, bsize, vers2;
-
-	nameoffs = start[offset] | start[offset+1]<<8 | start[offset+2]<<16 | start[offset+3]<<24;
-
-	saddr = start[offset+4] | start[offset+5]<<8 | start[offset+6]<<16 | start[offset+7]<<24;
-	heap = start[offset+8] | start[offset+9]<<8 | start[offset+10]<<16 | start[offset+11]<<24;
-	tsize = start[offset+12] | start[offset+13]<<8 | start[offset+14]<<16 | start[offset+15]<<24;
-	dsize = start[offset+16] | start[offset+17]<<8 | start[offset+18]<<16 | start[offset+19]<<24;
-	bsize = start[offset+20] | start[offset+21]<<8 | start[offset+22]<<16 | start[offset+23]<<24;
-	vers2 = start[offset+24] | start[offset+25]<<8;
-
-//	printf("nameoffs %08x saddr %08x heap %08x tsize %08x dsize %08x bsize %08x\n", nameoffs, saddr, heap, tsize, dsize, bsize);
-	printf("vers: %04x name [%s]\n", vers2, &start[offset+26]);
-	#endif
-}
-
-uint32_t psf2_load_elf(uint8_t *start, uint32_t len)
-{
-	uint32_t entry, shoff, shentsize, shnum;
-	uint32_t type, addr, offset, size, shent;
-//	uint32_t phoff, phentsize, phnum, shstrndx, name, flags;
-	uint32_t totallen;
-	int i, rec;
-//	FILE *f;
-
-	if (loadAddr & 3)
-	{
-		loadAddr &= ~3;
-		loadAddr += 4;
-	}
-
-	#if DEBUG_LOADER
-	printf("psf2_load_elf: starting at %08x\n", loadAddr | 0x80000000);
-	#endif
-
-	if ((start[0] != 0x7f) || (start[1] != 'E') || (start[2] != 'L') || (start[3] != 'F'))
-	{
-		printf("Not an ELF file\n");
-		return 0xffffffff;
-	}
-
-	entry = start[24] | start[25]<<8 | start[26]<<16 | start[27]<<24;	// 0x18
-//	phoff = start[28] | start[29]<<8 | start[30]<<16 | start[31]<<24; 	// 0x1c
-	shoff = start[32] | start[33]<<8 | start[34]<<16 | start[35]<<24; 	// 0x20
-
-//	printf("Entry: %08x phoff %08x shoff %08x\n", entry, phoff, shoff);
-
-//	phentsize = start[42] | start[43]<<8;			// 0x2a
-//	phnum = start[44] | start[45]<<8;			// 0x2c
-	shentsize = start[46] | start[47]<<8;			// 0x2e
-	shnum = start[48] | start[49]<<8;			// 0x30
-//	shstrndx = start[50] | start[51]<<8;			// 0x32
-
-//	printf("phentsize %08x phnum %d shentsize %08x shnum %d shstrndx %d\n", phentsize, phnum, shentsize, shnum, shstrndx);
-
-	// process ELF sections
-	shent = shoff;
-	totallen = 0;
-	for (i = 0; i < shnum; i++)
-	{
-//		name = start[shent] | start[shent+1]<<8 | start[shent+2]<<16 | start[shent+3]<<24;
-		type = start[shent+4] | start[shent+5]<<8 | start[shent+6]<<16 | start[shent+7]<<24;
-//		flags = start[shent+8] | start[shent+9]<<8 | start[shent+10]<<16 | start[shent+11]<<24;
-		addr = start[shent+12] | start[shent+13]<<8 | start[shent+14]<<16 | start[shent+15]<<24;
-		offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24;
-		size = start[shent+20] | start[shent+21]<<8 | start[shent+22]<<16 | start[shent+23]<<24;
-
-//		printf("Section %02d: name %08x [%s] type %08x flags %08x addr %08x offset %08x size %08x\n", i, name, &start[secname(start, shstrndx, shoff, shentsize, name)], type, flags, addr, offset, size);
-
-		switch (type)
-		{
-			case 0:			// section table header - do nothing
-				break;
-
-			case 1:			// PROGBITS: copy data to destination
-				memcpy(&psx_ram[(loadAddr + addr)/4], &start[offset], size);
-				totallen += size;
-				break;
-
-			case 2:			// SYMTAB: ignore
-				break;
-
-			case 3:			// STRTAB: ignore
-				break;
-
-			case 8:			// NOBITS: BSS region, zero out destination
-				memset(&psx_ram[(loadAddr + addr)/4], 0, size);
-				totallen += size;
-				break;
-
-			case 9:			// REL: short relocation data
-		  		for (rec = 0; rec < (size/8); rec++)
-				{
-					uint32_t offs, info, target, temp, val, vallo;
-					static uint32_t hi16offs = 0, hi16target = 0;
-
-					offs = start[offset+(rec*8)] | start[offset+1+(rec*8)]<<8 | start[offset+2+(rec*8)]<<16 | start[offset+3+(rec*8)]<<24;
-					info = start[offset+4+(rec*8)] | start[offset+5+(rec*8)]<<8 | start[offset+6+(rec*8)]<<16 | start[offset+7+(rec*8)]<<24;
-					target = LE32(psx_ram[(loadAddr+offs)/4]);
-
-//					printf("[%04d] offs %08x type %02x info %08x => %08x\n", rec, offs, ELF32_R_TYPE(info), ELF32_R_SYM(info), target);
-
-					switch (ELF32_R_TYPE(info))
-					{
-						case 2:	      	// R_MIPS_32
-							target += loadAddr;
-//							target |= 0x80000000;
-							break;
-
-						case 4:		// R_MIPS_26
-							temp = (target & 0x03ffffff);
-							target &= 0xfc000000;
-							temp += (loadAddr>>2);
-							target |= temp;
-							break;
-
-						case 5:		// R_MIPS_HI16
-							hi16offs = offs;
-							hi16target = target;
-							break;
-
-						case 6:		// R_MIPS_LO16
-							vallo = ((target & 0xffff) ^ 0x8000) - 0x8000;
-
-							val = ((hi16target & 0xffff) << 16) +	vallo;
-							val += loadAddr;
-//							val |= 0x80000000;
-
-							/* Account for the sign extension that will happen in the low bits.  */
-							val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
-
-							hi16target = (hi16target & ~0xffff) | val;
-
-							/* Ok, we're done with the HI16 relocs.  Now deal with the LO16.  */
-							val = loadAddr + vallo;
-							target = (target & ~0xffff) | (val & 0xffff);
-
-							psx_ram[(loadAddr+hi16offs)/4] = LE32(hi16target);
-							break;
-
-						default:
-							printf("FATAL: Unknown MIPS ELF relocation!\n");
-							return 0xffffffff;
-							break;
-					}
-
-					psx_ram[(loadAddr+offs)/4] = LE32(target);
-				}
-				break;
-
-			case 0x70000080:	// .iopmod
-				do_iopmod(start, offset);
-				break;
-
-			default:
-				#if DEBUG_LOADER
-				printf("Unhandled ELF section type %d\n", type);
-				#endif
-				break;
-		}
-
-		shent += shentsize;
-	}
-
-	entry += loadAddr;
-	entry |= 0x80000000;
-	loadAddr += totallen;
-
-	#if DEBUG_LOADER
-	printf("psf2_load_elf: entry PC %08x\n", entry);
-	#endif
-	return entry;
-}
-
-static uint32_t load_file_ex(uint8_t *top, uint8_t *start, uint32_t len, char *file, uint8_t *buf, uint32_t buflen)
-{
-	int32_t numfiles, i, j;
-	uint8_t *cptr;
-	uint32_t offs, uncomp, bsize, cofs, uofs;
-	uint32_t X;
-	uLongf dlength;
-	int uerr;
-	char matchname[512], *remainder;
-
-	// strip out to only the directory name
-	i = 0;
-	while ((file[i] != '/') && (file[i] != '\\') && (file[i] != '\0'))
-	{
-		matchname[i] = file[i];
-		i++;
-	}
-	matchname[i] = '\0';
-	remainder = &file[i+1];
-
-	cptr = start + 4;
-
-	numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
-
-	for (i = 0; i < numfiles; i++)
-	{
-		offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
-		uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
-		bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
-
-		#if DEBUG_LOADER
-		printf("[%s vs %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, matchname, offs, uncomp, bsize);
-		#endif
-
-		if (!g_ascii_strcasecmp((char *)cptr, matchname))
-		{
-			if ((uncomp == 0) && (bsize == 0))
-			{
-				#if DEBUG_LOADER
-				printf("Drilling into subdirectory [%s] with [%s] at offset %x\n", matchname, remainder, offs);
-				#endif
-				return load_file_ex(top, &top[offs], len-offs, remainder, buf, buflen);
-			}
-
-			X = (uncomp + bsize - 1) / bsize;
-
-			cofs = offs + (X*4);
-			uofs = 0;
-			for (j = 0; j < X; j++)
-			{
-				uint32_t usize;
-
-				usize = top[offs+(j*4)] | top[offs+1+(j*4)]<<8 | top[offs+2+(j*4)]<<16 | top[offs+3+(j*4)]<<24;
-
-				dlength = buflen - uofs;
-
-				uerr = uncompress(&buf[uofs], &dlength, &top[cofs], usize);
-				if (uerr != Z_OK)
-				{
-					printf("Decompress fail: %lx %d!\n", dlength, uerr);
-					return 0xffffffff;
-				}
-
-				cofs += usize;
-				uofs += dlength;
-			}
-
-			return uncomp;
-		}
-		else
-		{
-			cptr += 48;
-		}
-	}
-
-	return 0xffffffff;
-}
-
-static uint32_t load_file(int fs, char *file, uint8_t *buf, uint32_t buflen)
-{
-	return load_file_ex(filesys[fs], filesys[fs], fssize[fs], file, buf, buflen);
-}
-
-#if 0
-static dump_files(int fs, uint8_t *buf, uint32_t buflen)
-{
-	int32_t numfiles, i, j;
-	uint8_t *cptr;
-	uint32_t offs, uncomp, bsize, cofs, uofs;
-	uint32_t X;
-	uLongf dlength;
-	int uerr;
-	uint8_t *start;
-	uint32_t len;
-	FILE *f;
-	char tfn[128];
-
-	printf("Dumping FS %d\n", fs);
-
-	start = filesys[fs];
-	len = fssize[fs];
-
-	cptr = start + 4;
-
-	numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
-
-	for (i = 0; i < numfiles; i++)
-	{
-		offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
-		uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
-		bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
-
-		if (bsize > 0)
-		{
-			X = (uncomp + bsize - 1) / bsize;
-
-			printf("[dump %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
-
-			cofs = offs + (X*4);
-			uofs = 0;
-			for (j = 0; j < X; j++)
-			{
-				uint32_t usize;
-
-				usize = start[offs+(j*4)] | start[offs+1+(j*4)]<<8 | start[offs+2+(j*4)]<<16 | start[offs+3+(j*4)]<<24;
-
-				dlength = buflen - uofs;
-
-				uerr = uncompress(&buf[uofs], &dlength, &start[cofs], usize);
-				if (uerr != Z_OK)
-				{
-					printf("Decompress fail: %x %d!\n", dlength, uerr);
-					return 0xffffffff;
-				}
-
-				cofs += usize;
-				uofs += dlength;
-			}
-
-			sprintf(tfn, "iopfiles/%s", cptr);
-			f = fopen(tfn, "wb");
-			fwrite(buf, uncomp, 1, f);
-			fclose(f);
-		}
-		else
-		{
-			printf("[subdir %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
-		}
-
-		cptr += 48;
-	}
-
-	return 0xffffffff;
-}
-#endif
-
-// find a file on our filesystems
-uint32_t psf2_load_file(char *file, uint8_t *buf, uint32_t buflen)
-{
-	int i;
-	uint32_t flen;
-
-	for (i = 0; i < num_fs; i++)
-	{
-		flen = load_file(i, file, buf, buflen);
-		if (flen != 0xffffffff)
-		{
-			return flen;
-		}
-	}
-
-	return 0xffffffff;
-}
-
-int32_t psf2_start(uint8_t *buffer, uint32_t length)
-{
-	uint8_t *file, *lib_decoded;
-	uint32_t irx_len;
-	uint64_t file_len, lib_raw_length, lib_len;
-	uint8_t *buf;
-	union cpuinfo mipsinfo;
-	corlett_t *lib;
-
-	loadAddr = 0x23f00;	// this value makes allocations work out similarly to how they would
-				// in Highly Experimental (as per Shadow Hearts' hard-coded assumptions)
-
-	// clear IOP work RAM before we start scribbling in it
-	memset(psx_ram, 0, 2*1024*1024);
-
-	// Decode the current PSF2
-	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
-	{
-		return AO_FAIL;
-	}
-
-	if (file_len > 0)
-		printf ("ERROR: PSF2 can't have a program section!  ps %lx\n", (unsigned long) file_len);
-
-	#if DEBUG_LOADER
-	printf("FS section: size %x\n", c->res_size);
-	#endif
-
-	num_fs = 1;
-	filesys[0] = (uint8_t *)c->res_section;
-	fssize[0] = c->res_size;
-
-	// Get the library file, if any
-	if (c->lib[0] != 0)
-	{
-		uint64_t tmp_length;
-
-		#if DEBUG_LOADER
-		printf("Loading library: %s\n", c->lib);
-		#endif
-		if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
-		{
-			return AO_FAIL;
-		}
-		lib_raw_length = tmp_length;
-
-		if (lib_raw_file == NULL)
-			return AO_FAIL;
-
-		if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
-		{
-			free(lib_raw_file);
-			return AO_FAIL;
-		}
-
-		#if DEBUG_LOADER
-		printf("Lib FS section: size %x bytes\n", lib->res_size);
-		#endif
-
-		num_fs++;
-		filesys[1] = (uint8_t *)lib->res_section;
- 		fssize[1] = lib->res_size;
-	}
-
-	// dump all files
-	#if 0
-	buf = (uint8_t *)malloc(16*1024*1024);
-	dump_files(0, buf, 16*1024*1024);
-	if (c->lib[0] != 0)
-		dump_files(1, buf, 16*1024*1024);
-	free(buf);
-	#endif
-
-	// load psf2.irx, which kicks everything off
-	buf = (uint8_t *)malloc(512*1024);
-	irx_len = psf2_load_file("psf2.irx", buf, 512*1024);
-
-	if (irx_len != 0xffffffff)
-	{
-		initialPC = psf2_load_elf(buf, irx_len);
-		initialSP = 0x801ffff0;
-	}
-	free(buf);
-
-	if (initialPC == 0xffffffff)
-	{
-		return AO_FAIL;
-	}
-
-	lengthMS = psfTimeToMS(c->inf_length);
-	fadeMS = psfTimeToMS(c->inf_fade);
-	if (lengthMS == 0)
-	{
-		lengthMS = ~0;
-	}
-	setlength2(lengthMS, fadeMS);
-
-	mips_init();
-	mips_reset(NULL);
-
-	mipsinfo.i = initialPC;
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-	mipsinfo.i = initialSP;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
-
-	// set RA
-	mipsinfo.i = 0x80000000;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-
-	// set A0 & A1 to point to "aofile:/"
-	mipsinfo.i = 2;	// argc
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-
-	mipsinfo.i = 0x80000004;	// argv
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
-	psx_ram[1] = LE32(0x80000008);
-
-	buf = (uint8_t *)&psx_ram[2];
-	strcpy((char *)buf, "aofile:/");
-
-	psx_ram[0] = LE32(FUNCT_HLECALL);
-
-	// back up initial RAM image to quickly restart songs
-	memcpy(initial_ram, psx_ram, 2*1024*1024);
-
-	psx_hw_init();
-	SPU2init();
-	SPU2open(NULL);
-
-	return AO_SUCCESS;
-}
-
-int32_t psf2_execute(void)
-{
-	int i;
-
-	while (!stop_flag)
-	{
-		for (i = 0; i < 44100 / 60; i++)
-		{
-			SPU2async(1);
-			ps2_hw_slice();
-		}
-
-		ps2_hw_frame();
-	}
-
-	return AO_SUCCESS;
-}
-
-int32_t psf2_stop(void)
-{
-	SPU2close();
-	if (c->lib[0] != 0)
-	{
-		free(lib_raw_file);
-	}
-	free(c);
-
-	return AO_SUCCESS;
-}
-
-int32_t psf2_command(int32_t command, int32_t parameter)
-{
-	union cpuinfo mipsinfo;
-	uint32_t lengthMS, fadeMS;
-
-	switch (command)
-	{
-		case COMMAND_RESTART:
-			SPU2close();
-
-			memcpy(psx_ram, initial_ram, 2*1024*1024);
-
-			mips_init();
-			mips_reset(NULL);
-			psx_hw_init();
-			SPU2init();
-			SPU2open(NULL);
-
-			mipsinfo.i = initialPC;
-			mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-			mipsinfo.i = initialSP;
-			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
-			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
-
-			// set RA
-			mipsinfo.i = 0x80000000;
-			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-
-			// set A0 & A1 to point to "aofile:/"
-			mipsinfo.i = 2;	// argc
-			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-
-			mipsinfo.i = 0x80000004;	// argv
-			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
-
-			psx_hw_init();
-
-			lengthMS = psfTimeToMS(c->inf_length);
-			fadeMS = psfTimeToMS(c->inf_fade);
-			if (lengthMS == 0)
-			{
-				lengthMS = ~0;
-			}
-			setlength2(lengthMS, fadeMS);
-
-			return AO_SUCCESS;
-
-	}
-	return AO_FAIL;
-}
-
-uint32_t psf2_get_loadaddr(void)
-{
-	return loadAddr;
-}
-
-void psf2_set_loadaddr(uint32_t new)
-{
-	loadAddr = new;
-}
diff --git a/src/psf/eng_psf2.cc b/src/psf/eng_psf2.cc
new file mode 100644
index 000000000000..ed1dde0cb04b
--- /dev/null
+++ b/src/psf/eng_psf2.cc
@@ -0,0 +1,662 @@
+/*
+	Audio Overload SDK - PSF2 file format engine
+
+	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+//
+// Audio Overload
+// Emulated music player
+//
+// (C) 2000-2008 Richard F. Bannister
+//
+
+//
+// eng_psf2.c
+//
+// References:
+// psf_format.txt v1.6 by Neill Corlett (filesystem and decompression info)
+// Intel ELF format specs ELF.PS (general ELF parsing info)
+// http://ps2dev.org/kb.x?T=457 (IRX relocation and inter-module call info)
+// http://ps2dev.org/ (the whole site - lots of IOP info)
+// spu2regs.txt (comes with SexyPSF source: IOP hardware info)
+// 64-bit ELF Object File Specification: http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf (MIPS ELF relocation types)
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <zlib.h>
+#include <libaudcore/audstrings.h>
+
+#include "ao.h"
+#include "eng_protos.h"
+#include "cpuintrf.h"
+#include "psx.h"
+
+#include "peops2/stdafx.h"
+#include "peops2/externals.h"
+#include "peops2/regs.h"
+#include "peops2/registers.h"
+#include "peops2/spu.h"
+
+#include "corlett.h"
+
+#define DEBUG_LOADER	(0)
+#define MAX_FS		(32)	// maximum # of filesystems (libs and subdirectories)
+
+// ELF relocation helpers
+#define ELF32_R_SYM(val)                ((val) >> 8)
+#define ELF32_R_TYPE(val)               ((val) & 0xff)
+
+#define LE32(x) FROM_LE32(x)
+
+static corlett_t	*c = nullptr;
+
+// main RAM
+extern uint32_t psx_ram[(2*1024*1024)/4];
+extern uint32_t initial_ram[(2*1024*1024)/4];
+static uint32_t initialPC, initialSP;
+static uint32_t loadAddr, lengthMS, fadeMS;
+
+static uint8_t *filesys[MAX_FS];
+static Index<char> lib_raw_file;
+static uint32_t fssize[MAX_FS];
+static int num_fs;
+
+extern void mips_init( void );
+extern void mips_reset( void *param );
+extern int mips_execute( int cycles );
+extern void mips_set_info(uint32_t state, union cpuinfo *info);
+extern void psx_hw_init(void);
+extern void ps2_hw_slice(void);
+extern void ps2_hw_frame(void);
+extern void setlength2(int32_t stop, int32_t fade);
+
+static void do_iopmod(uint8_t *start, uint32_t offset)
+{
+	#if DEBUG_LOADER
+	uint32_t nameoffs, saddr, heap, tsize, dsize, bsize, vers2;
+
+	nameoffs = start[offset] | start[offset+1]<<8 | start[offset+2]<<16 | start[offset+3]<<24;
+
+	saddr = start[offset+4] | start[offset+5]<<8 | start[offset+6]<<16 | start[offset+7]<<24;
+	heap = start[offset+8] | start[offset+9]<<8 | start[offset+10]<<16 | start[offset+11]<<24;
+	tsize = start[offset+12] | start[offset+13]<<8 | start[offset+14]<<16 | start[offset+15]<<24;
+	dsize = start[offset+16] | start[offset+17]<<8 | start[offset+18]<<16 | start[offset+19]<<24;
+	bsize = start[offset+20] | start[offset+21]<<8 | start[offset+22]<<16 | start[offset+23]<<24;
+	vers2 = start[offset+24] | start[offset+25]<<8;
+
+//	printf("nameoffs %08x saddr %08x heap %08x tsize %08x dsize %08x bsize %08x\n", nameoffs, saddr, heap, tsize, dsize, bsize);
+	printf("vers: %04x name [%s]\n", vers2, &start[offset+26]);
+	#endif
+}
+
+uint32_t psf2_load_elf(uint8_t *start, uint32_t len)
+{
+	uint32_t entry, shoff, shentsize, shnum;
+	uint32_t type, addr, offset, size, shent;
+//	uint32_t phoff, phentsize, phnum, shstrndx, name, flags;
+	uint32_t totallen;
+	int i, rec;
+//	FILE *f;
+
+	if (loadAddr & 3)
+	{
+		loadAddr &= ~3;
+		loadAddr += 4;
+	}
+
+	#if DEBUG_LOADER
+	printf("psf2_load_elf: starting at %08x\n", loadAddr | 0x80000000);
+	#endif
+
+	if ((start[0] != 0x7f) || (start[1] != 'E') || (start[2] != 'L') || (start[3] != 'F'))
+	{
+		printf("Not an ELF file\n");
+		return 0xffffffff;
+	}
+
+	entry = start[24] | start[25]<<8 | start[26]<<16 | start[27]<<24;	// 0x18
+//	phoff = start[28] | start[29]<<8 | start[30]<<16 | start[31]<<24; 	// 0x1c
+	shoff = start[32] | start[33]<<8 | start[34]<<16 | start[35]<<24; 	// 0x20
+
+//	printf("Entry: %08x phoff %08x shoff %08x\n", entry, phoff, shoff);
+
+//	phentsize = start[42] | start[43]<<8;			// 0x2a
+//	phnum = start[44] | start[45]<<8;			// 0x2c
+	shentsize = start[46] | start[47]<<8;			// 0x2e
+	shnum = start[48] | start[49]<<8;			// 0x30
+//	shstrndx = start[50] | start[51]<<8;			// 0x32
+
+//	printf("phentsize %08x phnum %d shentsize %08x shnum %d shstrndx %d\n", phentsize, phnum, shentsize, shnum, shstrndx);
+
+	// process ELF sections
+	shent = shoff;
+	totallen = 0;
+	for (i = 0; i < shnum; i++)
+	{
+//		name = start[shent] | start[shent+1]<<8 | start[shent+2]<<16 | start[shent+3]<<24;
+		type = start[shent+4] | start[shent+5]<<8 | start[shent+6]<<16 | start[shent+7]<<24;
+//		flags = start[shent+8] | start[shent+9]<<8 | start[shent+10]<<16 | start[shent+11]<<24;
+		addr = start[shent+12] | start[shent+13]<<8 | start[shent+14]<<16 | start[shent+15]<<24;
+		offset = start[shent+16] | start[shent+17]<<8 | start[shent+18]<<16 | start[shent+19]<<24;
+		size = start[shent+20] | start[shent+21]<<8 | start[shent+22]<<16 | start[shent+23]<<24;
+
+//		printf("Section %02d: name %08x [%s] type %08x flags %08x addr %08x offset %08x size %08x\n", i, name, &start[secname(start, shstrndx, shoff, shentsize, name)], type, flags, addr, offset, size);
+
+		switch (type)
+		{
+			case 0:			// section table header - do nothing
+				break;
+
+			case 1:			// PROGBITS: copy data to destination
+				memcpy(&psx_ram[(loadAddr + addr)/4], &start[offset], size);
+				totallen += size;
+				break;
+
+			case 2:			// SYMTAB: ignore
+				break;
+
+			case 3:			// STRTAB: ignore
+				break;
+
+			case 8:			// NOBITS: BSS region, zero out destination
+				memset(&psx_ram[(loadAddr + addr)/4], 0, size);
+				totallen += size;
+				break;
+
+			case 9:			// REL: short relocation data
+		  		for (rec = 0; rec < (size/8); rec++)
+				{
+					uint32_t offs, info, target, temp, val, vallo;
+					static uint32_t hi16offs = 0, hi16target = 0;
+
+					offs = start[offset+(rec*8)] | start[offset+1+(rec*8)]<<8 | start[offset+2+(rec*8)]<<16 | start[offset+3+(rec*8)]<<24;
+					info = start[offset+4+(rec*8)] | start[offset+5+(rec*8)]<<8 | start[offset+6+(rec*8)]<<16 | start[offset+7+(rec*8)]<<24;
+					target = LE32(psx_ram[(loadAddr+offs)/4]);
+
+//					printf("[%04d] offs %08x type %02x info %08x => %08x\n", rec, offs, ELF32_R_TYPE(info), ELF32_R_SYM(info), target);
+
+					switch (ELF32_R_TYPE(info))
+					{
+						case 2:	      	// R_MIPS_32
+							target += loadAddr;
+//							target |= 0x80000000;
+							break;
+
+						case 4:		// R_MIPS_26
+							temp = (target & 0x03ffffff);
+							target &= 0xfc000000;
+							temp += (loadAddr>>2);
+							target |= temp;
+							break;
+
+						case 5:		// R_MIPS_HI16
+							hi16offs = offs;
+							hi16target = target;
+							break;
+
+						case 6:		// R_MIPS_LO16
+							vallo = ((target & 0xffff) ^ 0x8000) - 0x8000;
+
+							val = ((hi16target & 0xffff) << 16) +	vallo;
+							val += loadAddr;
+//							val |= 0x80000000;
+
+							/* Account for the sign extension that will happen in the low bits.  */
+							val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+							hi16target = (hi16target & ~0xffff) | val;
+
+							/* Ok, we're done with the HI16 relocs.  Now deal with the LO16.  */
+							val = loadAddr + vallo;
+							target = (target & ~0xffff) | (val & 0xffff);
+
+							psx_ram[(loadAddr+hi16offs)/4] = LE32(hi16target);
+							break;
+
+						default:
+							printf("FATAL: Unknown MIPS ELF relocation!\n");
+							return 0xffffffff;
+							break;
+					}
+
+					psx_ram[(loadAddr+offs)/4] = LE32(target);
+				}
+				break;
+
+			case 0x70000080:	// .iopmod
+				do_iopmod(start, offset);
+				break;
+
+			default:
+				#if DEBUG_LOADER
+				printf("Unhandled ELF section type %d\n", type);
+				#endif
+				break;
+		}
+
+		shent += shentsize;
+	}
+
+	entry += loadAddr;
+	entry |= 0x80000000;
+	loadAddr += totallen;
+
+	#if DEBUG_LOADER
+	printf("psf2_load_elf: entry PC %08x\n", entry);
+	#endif
+	return entry;
+}
+
+static uint32_t load_file_ex(uint8_t *top, uint8_t *start, uint32_t len, const char *file, uint8_t *buf, uint32_t buflen)
+{
+	int32_t numfiles, i, j;
+	uint8_t *cptr;
+	uint32_t offs, uncomp, bsize, cofs, uofs;
+	uint32_t X;
+	uLongf dlength;
+	int uerr;
+	char matchname[512];
+	const char *remainder;
+
+	// strip out to only the directory name
+	i = 0;
+	while ((file[i] != '/') && (file[i] != '\\') && (file[i] != '\0'))
+	{
+		matchname[i] = file[i];
+		i++;
+	}
+	matchname[i] = '\0';
+	remainder = &file[i+1];
+
+	cptr = start + 4;
+
+	numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
+
+	for (i = 0; i < numfiles; i++)
+	{
+		offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
+		uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
+		bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
+
+		#if DEBUG_LOADER
+		printf("[%s vs %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, matchname, offs, uncomp, bsize);
+		#endif
+
+		if (!strcmp_nocase((char *)cptr, matchname))
+		{
+			if ((uncomp == 0) && (bsize == 0))
+			{
+				#if DEBUG_LOADER
+				printf("Drilling into subdirectory [%s] with [%s] at offset %x\n", matchname, remainder, offs);
+				#endif
+				return load_file_ex(top, &top[offs], len-offs, remainder, buf, buflen);
+			}
+
+			X = (uncomp + bsize - 1) / bsize;
+
+			cofs = offs + (X*4);
+			uofs = 0;
+			for (j = 0; j < X; j++)
+			{
+				uint32_t usize;
+
+				usize = top[offs+(j*4)] | top[offs+1+(j*4)]<<8 | top[offs+2+(j*4)]<<16 | top[offs+3+(j*4)]<<24;
+
+				dlength = buflen - uofs;
+
+				uerr = uncompress(&buf[uofs], &dlength, &top[cofs], usize);
+				if (uerr != Z_OK)
+				{
+					printf("Decompress fail: %lx %d!\n", dlength, uerr);
+					return 0xffffffff;
+				}
+
+				cofs += usize;
+				uofs += dlength;
+			}
+
+			return uncomp;
+		}
+		else
+		{
+			cptr += 48;
+		}
+	}
+
+	return 0xffffffff;
+}
+
+static uint32_t load_file(int fs, const char *file, uint8_t *buf, uint32_t buflen)
+{
+	return load_file_ex(filesys[fs], filesys[fs], fssize[fs], file, buf, buflen);
+}
+
+#if 0
+static dump_files(int fs, uint8_t *buf, uint32_t buflen)
+{
+	int32_t numfiles, i, j;
+	uint8_t *cptr;
+	uint32_t offs, uncomp, bsize, cofs, uofs;
+	uint32_t X;
+	uLongf dlength;
+	int uerr;
+	uint8_t *start;
+	uint32_t len;
+	FILE *f;
+	char tfn[128];
+
+	printf("Dumping FS %d\n", fs);
+
+	start = filesys[fs];
+	len = fssize[fs];
+
+	cptr = start + 4;
+
+	numfiles = start[0] | start[1]<<8 | start[2]<<16 | start[3]<<24;
+
+	for (i = 0; i < numfiles; i++)
+	{
+		offs = cptr[36] | cptr[37]<<8 | cptr[38]<<16 | cptr[39]<<24;
+		uncomp = cptr[40] | cptr[41]<<8 | cptr[42]<<16 | cptr[43]<<24;
+		bsize = cptr[44] | cptr[45]<<8 | cptr[46]<<16 | cptr[47]<<24;
+
+		if (bsize > 0)
+		{
+			X = (uncomp + bsize - 1) / bsize;
+
+			printf("[dump %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
+
+			cofs = offs + (X*4);
+			uofs = 0;
+			for (j = 0; j < X; j++)
+			{
+				uint32_t usize;
+
+				usize = start[offs+(j*4)] | start[offs+1+(j*4)]<<8 | start[offs+2+(j*4)]<<16 | start[offs+3+(j*4)]<<24;
+
+				dlength = buflen - uofs;
+
+				uerr = uncompress(&buf[uofs], &dlength, &start[cofs], usize);
+				if (uerr != Z_OK)
+				{
+					printf("Decompress fail: %x %d!\n", dlength, uerr);
+					return 0xffffffff;
+				}
+
+				cofs += usize;
+				uofs += dlength;
+			}
+
+			sprintf(tfn, "iopfiles/%s", cptr);
+			f = fopen(tfn, "wb");
+			fwrite(buf, uncomp, 1, f);
+			fclose(f);
+		}
+		else
+		{
+			printf("[subdir %s]: ofs %08x uncomp %08x bsize %08x\n", cptr, offs, uncomp, bsize);
+		}
+
+		cptr += 48;
+	}
+
+	return 0xffffffff;
+}
+#endif
+
+// find a file on our filesystems
+uint32_t psf2_load_file(const char *file, uint8_t *buf, uint32_t buflen)
+{
+	int i;
+	uint32_t flen;
+
+	for (i = 0; i < num_fs; i++)
+	{
+		flen = load_file(i, file, buf, buflen);
+		if (flen != 0xffffffff)
+		{
+			return flen;
+		}
+	}
+
+	return 0xffffffff;
+}
+
+int32_t psf2_start(uint8_t *buffer, uint32_t length)
+{
+	uint8_t *file, *lib_decoded;
+	uint32_t irx_len;
+	uint64_t file_len, lib_len;
+	uint8_t *buf;
+	union cpuinfo mipsinfo;
+	corlett_t *lib;
+
+	loadAddr = 0x23f00;	// this value makes allocations work out similarly to how they would
+				// in Highly Experimental (as per Shadow Hearts' hard-coded assumptions)
+
+	// clear IOP work RAM before we start scribbling in it
+	memset(psx_ram, 0, 2*1024*1024);
+
+	// Decode the current PSF2
+	if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
+	{
+		return AO_FAIL;
+	}
+
+	if (file_len > 0)
+		printf ("ERROR: PSF2 can't have a program section!  ps %lx\n", (unsigned long) file_len);
+
+	#if DEBUG_LOADER
+	printf("FS section: size %x\n", c->res_size);
+	#endif
+
+	num_fs = 1;
+	filesys[0] = (uint8_t *)c->res_section;
+	fssize[0] = c->res_size;
+
+	// Get the library file, if any
+	if (c->lib[0] != 0)
+	{
+		#if DEBUG_LOADER
+		printf("Loading library: %s\n", c->lib);
+		#endif
+
+		lib_raw_file = ao_get_lib(c->lib);
+
+		if (!lib_raw_file.len())
+			return AO_FAIL;
+
+		if (corlett_decode((uint8_t *)lib_raw_file.begin(), lib_raw_file.len(),
+		 &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
+			return AO_FAIL;
+
+		#if DEBUG_LOADER
+		printf("Lib FS section: size %x bytes\n", lib->res_size);
+		#endif
+
+		num_fs++;
+		filesys[1] = (uint8_t *)lib->res_section;
+ 		fssize[1] = lib->res_size;
+	}
+
+	// dump all files
+	#if 0
+	buf = (uint8_t *)malloc(16*1024*1024);
+	dump_files(0, buf, 16*1024*1024);
+	if (c->lib[0] != 0)
+		dump_files(1, buf, 16*1024*1024);
+	free(buf);
+	#endif
+
+	// load psf2.irx, which kicks everything off
+	buf = (uint8_t *)malloc(512*1024);
+	irx_len = psf2_load_file("psf2.irx", buf, 512*1024);
+
+	if (irx_len != 0xffffffff)
+	{
+		initialPC = psf2_load_elf(buf, irx_len);
+		initialSP = 0x801ffff0;
+	}
+	free(buf);
+
+	if (initialPC == 0xffffffff)
+	{
+		return AO_FAIL;
+	}
+
+	lengthMS = psfTimeToMS(c->inf_length);
+	fadeMS = psfTimeToMS(c->inf_fade);
+	if (lengthMS == 0)
+	{
+		lengthMS = ~0;
+	}
+	setlength2(lengthMS, fadeMS);
+
+	mips_init();
+	mips_reset(nullptr);
+
+	mipsinfo.i = initialPC;
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+	mipsinfo.i = initialSP;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
+
+	// set RA
+	mipsinfo.i = 0x80000000;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+
+	// set A0 & A1 to point to "aofile:/"
+	mipsinfo.i = 2;	// argc
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+
+	mipsinfo.i = 0x80000004;	// argv
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
+	psx_ram[1] = LE32(0x80000008);
+
+	buf = (uint8_t *)&psx_ram[2];
+	strcpy((char *)buf, "aofile:/");
+
+	psx_ram[0] = LE32(FUNCT_HLECALL);
+
+	// back up initial RAM image to quickly restart songs
+	memcpy(initial_ram, psx_ram, 2*1024*1024);
+
+	psx_hw_init();
+	SPU2init();
+	SPU2open(nullptr);
+
+	return AO_SUCCESS;
+}
+
+int32_t psf2_execute(void (*update)(const void *, int))
+{
+	int i;
+
+	while (!stop_flag)
+	{
+		for (i = 0; i < 44100 / 60; i++)
+		{
+			SPU2async(update);
+			ps2_hw_slice();
+		}
+
+		ps2_hw_frame();
+	}
+
+	return AO_SUCCESS;
+}
+
+int32_t psf2_stop(void)
+{
+	SPU2close();
+	lib_raw_file.clear();
+	free(c);
+
+	return AO_SUCCESS;
+}
+
+int32_t psf2_command(int32_t command, int32_t parameter)
+{
+	union cpuinfo mipsinfo;
+	uint32_t lengthMS, fadeMS;
+
+	switch (command)
+	{
+		case COMMAND_RESTART:
+			SPU2close();
+
+			memcpy(psx_ram, initial_ram, 2*1024*1024);
+
+			mips_init();
+			mips_reset(nullptr);
+			psx_hw_init();
+			SPU2init();
+			SPU2open(nullptr);
+
+			mipsinfo.i = initialPC;
+			mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+			mipsinfo.i = initialSP;
+			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
+			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
+
+			// set RA
+			mipsinfo.i = 0x80000000;
+			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+
+			// set A0 & A1 to point to "aofile:/"
+			mipsinfo.i = 2;	// argc
+			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+
+			mipsinfo.i = 0x80000004;	// argv
+			mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
+
+			psx_hw_init();
+
+			lengthMS = psfTimeToMS(c->inf_length);
+			fadeMS = psfTimeToMS(c->inf_fade);
+			if (lengthMS == 0)
+			{
+				lengthMS = ~0;
+			}
+			setlength2(lengthMS, fadeMS);
+
+			return AO_SUCCESS;
+
+	}
+	return AO_FAIL;
+}
+
+uint32_t psf2_get_loadaddr(void)
+{
+	return loadAddr;
+}
+
+void psf2_set_loadaddr(uint32_t addr)
+{
+	loadAddr = addr;
+}
diff --git a/src/psf/eng_spx.c b/src/psf/eng_spx.c
deleted file mode 100644
index 1d8293b4c20a..000000000000
--- a/src/psf/eng_spx.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-	Audio Overload SDK - SPU file format engine
-
-	Copyright (c) 2007 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-//
-// eng_spu.c
-//
-// Note: support for old-format files is not tested and may not work.  All the rips I could find
-//       are in the newer format.  Also, CDDA and XA commands do not work - I've not found a rip using them.
-//
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "ao.h"
-#include "eng_protos.h"
-#include "cpuintrf.h"
-#include "psx.h"
-
-#include "peops/stdafx.h"
-#include "peops/externals.h"
-#include "peops/regs.h"
-#include "peops/registers.h"
-#include "peops/spu.h"
-
-extern int SPUinit(void);
-extern int SPUopen(void);
-extern int SPUclose(void);
-extern void SPUinjectRAMImage(unsigned short *source);
-
-extern void setlength(int32_t stop, int32_t fade);
-
-static uint8_t *start_of_file, *song_ptr;
-static uint32_t cur_tick, cur_event, num_events, next_tick, end_tick;
-static int old_fmt;
-static char name[128], song[128], company[128];
-
-int32_t spx_start(uint8_t *buffer, uint32_t length)
-{
-	int i;
-	uint16_t reg;
-
-	if (strncmp((char *)buffer, "SPU", 3) && strncmp((char *)buffer, "SPX", 3))
-	{
-		return AO_FAIL;
-	}
-
-	start_of_file = buffer;
-
-	SPUinit();
-	SPUopen();
-	setlength(~0, 0);
-
-	// upload the SPU RAM image
-	SPUinjectRAMImage((unsigned short *)&buffer[0]);
-
-	// apply the register image
-	for (i = 0; i < 512; i += 2)
-	{
-		reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8;
-
-		SPUwriteRegister((i/2)+0x1f801c00, reg);
-	}
-
-	old_fmt = 1;
-
-	if ((buffer[0x80200] != 0x44) || (buffer[0x80201] != 0xac) || (buffer[0x80202] != 0x00) || (buffer[0x80203] != 0x00))
-	{
-		old_fmt = 0;
-	}
-
-	if (old_fmt)
-	{
-		num_events = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
-
-		if (((num_events * 12) + 0x80208) > length)
-		{
-			old_fmt = 0;
-		}
-		else
-		{
-			cur_tick = 0;
-		}
-	}
-
-	if (!old_fmt)
-	{
-		end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24;
-		cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
-		next_tick = cur_tick;
-	}
-
-	song_ptr = &buffer[0x80208];
-	cur_event = 0;
-
-	strncpy((char *)&buffer[4], name, 128);
-	strncpy((char *)&buffer[0x44], song, 128);
-	strncpy((char *)&buffer[0x84], company, 128);
-
-	return AO_SUCCESS;
-}
-
-extern int SPUasync(uint32_t cycles);
-static void spx_tick(void)
-{
-	uint32_t time, reg, size;
-	uint16_t rdata;
-	uint8_t opcode;
-
-	if (old_fmt)
-	{
-		time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-
-		while ((time == cur_tick) && (cur_event < num_events))
-		{
-			reg = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
-			rdata = song_ptr[8] | song_ptr[9]<<8;
-
-			SPUwriteRegister(reg, rdata);
-
-			cur_event++;
-			song_ptr += 12;
-
-			time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-		}
-	}
-	else
-	{
-		if (cur_tick < end_tick)
-		{
-			while (cur_tick == next_tick)
-			{
-				opcode = song_ptr[0];
-				song_ptr++;
-
-				switch (opcode)
-				{
-					case 0:	// write register
-						reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						rdata = song_ptr[4] | song_ptr[5]<<8;
-
-						SPUwriteRegister(reg, rdata);
-
-						next_tick = song_ptr[6] | song_ptr[7]<<8 | song_ptr[8]<<16 | song_ptr[9]<<24;
-						song_ptr += 10;
-						break;
-
-					case 1:	// read register
-				 		reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						SPUreadRegister(reg);
-						next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
-						song_ptr += 8;
-						break;
-
-					case 2: // dma write
-						size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						song_ptr += (4 + size);
-						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						song_ptr += 4;
-						break;
-
-					case 3: // dma read
-						next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
-						song_ptr += 8;
-						break;
-
-					case 4: // xa play
-						song_ptr += (32 + 16384);
-						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						song_ptr += 4;
-						break;
-
-					case 5: // cdda play
-						size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						song_ptr += (4 + size);
-						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
-						song_ptr += 4;
-						break;
-
-					default:
-						printf("Unknown opcode %d\n", opcode);
-						exit(-1);
-						break;
-				}
-			}
-		}
-	}
-
-	cur_tick++;
-}
-
-int32_t spx_execute(void)
-{
-	int i, run = 1;
-
-	while (!stop_flag)
-	{
-		if (old_fmt && (cur_event >= num_events))
-			run = 0;
-		else if (cur_tick >= end_tick)
-			run = 0;
-
-		if (run)
-		{
-			for (i = 0; i < 44100 / 60; i++)
-			{
-			  	spx_tick();
-				SPUasync(384);
-			}
-		}
-	}
-
-	return AO_SUCCESS;
-}
-
-int32_t spx_stop(void)
-{
-	SPUclose();
-
-	return AO_SUCCESS;
-}
diff --git a/src/psf/eng_spx.cc b/src/psf/eng_spx.cc
new file mode 100644
index 000000000000..4c4397f7b25c
--- /dev/null
+++ b/src/psf/eng_spx.cc
@@ -0,0 +1,243 @@
+/*
+	Audio Overload SDK - SPU file format engine
+
+	Copyright (c) 2007 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+//
+// eng_spu.c
+//
+// Note: support for old-format files is not tested and may not work.  All the rips I could find
+//       are in the newer format.  Also, CDDA and XA commands do not work - I've not found a rip using them.
+//
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ao.h"
+#include "eng_protos.h"
+#include "cpuintrf.h"
+#include "psx.h"
+
+#include "peops/stdafx.h"
+#include "peops/externals.h"
+#include "peops/regs.h"
+#include "peops/registers.h"
+#include "peops/spu.h"
+
+extern int SPUinit(void);
+extern int SPUopen(void);
+extern int SPUclose(void);
+extern void SPUinjectRAMImage(unsigned short *source);
+
+extern void setlength(int32_t stop, int32_t fade);
+
+static uint8_t *start_of_file, *song_ptr;
+static uint32_t cur_tick, cur_event, num_events, next_tick, end_tick;
+static int old_fmt;
+static char name[128], song[128], company[128];
+
+int32_t spx_start(uint8_t *buffer, uint32_t length)
+{
+	int i;
+	uint16_t reg;
+
+	if (strncmp((char *)buffer, "SPU", 3) && strncmp((char *)buffer, "SPX", 3))
+	{
+		return AO_FAIL;
+	}
+
+	start_of_file = buffer;
+
+	SPUinit();
+	SPUopen();
+	setlength(~0, 0);
+
+	// upload the SPU RAM image
+	SPUinjectRAMImage((unsigned short *)&buffer[0]);
+
+	// apply the register image
+	for (i = 0; i < 512; i += 2)
+	{
+		reg = buffer[0x80000+i] | buffer[0x80000+i+1]<<8;
+
+		SPUwriteRegister((i/2)+0x1f801c00, reg);
+	}
+
+	old_fmt = 1;
+
+	if ((buffer[0x80200] != 0x44) || (buffer[0x80201] != 0xac) || (buffer[0x80202] != 0x00) || (buffer[0x80203] != 0x00))
+	{
+		old_fmt = 0;
+	}
+
+	if (old_fmt)
+	{
+		num_events = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
+
+		if (((num_events * 12) + 0x80208) > length)
+		{
+			old_fmt = 0;
+		}
+		else
+		{
+			cur_tick = 0;
+		}
+	}
+
+	if (!old_fmt)
+	{
+		end_tick = buffer[0x80200] | buffer[0x80201]<<8 | buffer[0x80202]<<16 | buffer[0x80203]<<24;
+		cur_tick = buffer[0x80204] | buffer[0x80205]<<8 | buffer[0x80206]<<16 | buffer[0x80207]<<24;
+		next_tick = cur_tick;
+	}
+
+	song_ptr = &buffer[0x80208];
+	cur_event = 0;
+
+	strncpy((char *)&buffer[4], name, 128);
+	strncpy((char *)&buffer[0x44], song, 128);
+	strncpy((char *)&buffer[0x84], company, 128);
+
+	return AO_SUCCESS;
+}
+
+static void spx_tick(void)
+{
+	uint32_t time, reg, size;
+	uint16_t rdata;
+	uint8_t opcode;
+
+	if (old_fmt)
+	{
+		time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+
+		while ((time == cur_tick) && (cur_event < num_events))
+		{
+			reg = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
+			rdata = song_ptr[8] | song_ptr[9]<<8;
+
+			SPUwriteRegister(reg, rdata);
+
+			cur_event++;
+			song_ptr += 12;
+
+			time = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+		}
+	}
+	else
+	{
+		if (cur_tick < end_tick)
+		{
+			while (cur_tick == next_tick)
+			{
+				opcode = song_ptr[0];
+				song_ptr++;
+
+				switch (opcode)
+				{
+					case 0:	// write register
+						reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						rdata = song_ptr[4] | song_ptr[5]<<8;
+
+						SPUwriteRegister(reg, rdata);
+
+						next_tick = song_ptr[6] | song_ptr[7]<<8 | song_ptr[8]<<16 | song_ptr[9]<<24;
+						song_ptr += 10;
+						break;
+
+					case 1:	// read register
+				 		reg = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						SPUreadRegister(reg);
+						next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
+						song_ptr += 8;
+						break;
+
+					case 2: // dma write
+						size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						song_ptr += (4 + size);
+						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						song_ptr += 4;
+						break;
+
+					case 3: // dma read
+						next_tick = song_ptr[4] | song_ptr[5]<<8 | song_ptr[6]<<16 | song_ptr[7]<<24;
+						song_ptr += 8;
+						break;
+
+					case 4: // xa play
+						song_ptr += (32 + 16384);
+						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						song_ptr += 4;
+						break;
+
+					case 5: // cdda play
+						size = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						song_ptr += (4 + size);
+						next_tick = song_ptr[0] | song_ptr[1]<<8 | song_ptr[2]<<16 | song_ptr[3]<<24;
+						song_ptr += 4;
+						break;
+
+					default:
+						printf("Unknown opcode %d\n", opcode);
+						exit(-1);
+						break;
+				}
+			}
+		}
+	}
+
+	cur_tick++;
+}
+
+int32_t spx_execute(void (*update)(const void *, int))
+{
+	int i, run = 1;
+
+	while (!stop_flag)
+	{
+		if (old_fmt && (cur_event >= num_events))
+			run = 0;
+		else if (cur_tick >= end_tick)
+			run = 0;
+
+		if (run)
+		{
+			for (i = 0; i < 44100 / 60; i++)
+			{
+			  	spx_tick();
+				SPUasync(384, update);
+			}
+		}
+	}
+
+	return AO_SUCCESS;
+}
+
+int32_t spx_stop(void)
+{
+	SPUclose();
+
+	return AO_SUCCESS;
+}
diff --git a/src/psf/peops/License.txt b/src/psf/peops/License.txt
index e51338c2caa9..dc9e742f60fe 100644
--- a/src/psf/peops/License.txt
+++ b/src/psf/peops/License.txt
@@ -4,7 +4,8 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                          675 Mass Ave, Cambridge, MA 02139, USA
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
diff --git a/src/psf/peops/adsr.c b/src/psf/peops/adsr.c
deleted file mode 100644
index d9deca5a7632..000000000000
--- a/src/psf/peops/adsr.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/***************************************************************************
-                          adsr.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2003/01/06 - Pete
-// - added Neill's ADSR timings
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#define _IN_ADSR
-
-// will be included from spu.c
-#ifdef _IN_SPU
-
-////////////////////////////////////////////////////////////////////////
-// ADSR func
-////////////////////////////////////////////////////////////////////////
-
-static u32 RateTable[160];
-
-static void InitADSR(void)                                    // INIT ADSR
-{
- u32 r,rs,rd;int i;
-
- memset(RateTable,0,sizeof(u32)*160);        // build the rate table according to Neill's rules (see at bottom of file)
-
- r=3;rs=1;rd=0;
-
- for(i=32;i<160;i++)                                   // we start at pos 32 with the real values... everything before is 0
-  {
-   if(r<0x3FFFFFFF)
-    {
-     r+=rs;
-     rd++;if(rd==5) {rd=1;rs*=2;}
-    }
-   if(r>0x3FFFFFFF) r=0x3FFFFFFF;
-
-   RateTable[i]=r;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline void StartADSR(int ch)                          // MIX ADSR
-{
- s_chan[ch].ADSRX.lVolume=1;                           // and init some adsr vars
- s_chan[ch].ADSRX.State=0;
- s_chan[ch].ADSRX.EnvelopeVol=0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline int MixADSR(int ch)                             // MIX ADSR
-{
- static const int sexytable[8]=
-	{0,4,6,8,9,10,11,12};
-
- if(s_chan[ch].bStop)                                  // should be stopped:
-  {                                                    // do release
-   if(s_chan[ch].ADSRX.ReleaseModeExp)
-    {
-     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
-    }
-   else
-    {
-     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
-    }
-
-   if(s_chan[ch].ADSRX.EnvelopeVol<0)
-    {
-     s_chan[ch].ADSRX.EnvelopeVol=0;
-     s_chan[ch].bOn=0;
-     s_chan[ch].bNoise=0;
-    }
-
-   s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-   return s_chan[ch].ADSRX.lVolume;
-  }
- else                                                  // not stopped yet?
-  {
-   if(s_chan[ch].ADSRX.State==0)                       // -> attack
-    {
-     if(s_chan[ch].ADSRX.AttackModeExp)
-      {
-       if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
-        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
-       else
-        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
-      }
-     else
-      {
-       s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
-      }
-
-     if(s_chan[ch].ADSRX.EnvelopeVol<0)
-      {
-       s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
-       s_chan[ch].ADSRX.State=1;
-      }
-
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-   //--------------------------------------------------//
-   if(s_chan[ch].ADSRX.State==1)                       // -> decay
-    {
-     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
-
-     if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
-     if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
-      {
-       s_chan[ch].ADSRX.State=2;
-      }
-
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-   //--------------------------------------------------//
-   if(s_chan[ch].ADSRX.State==2)                       // -> sustain
-    {
-     if(s_chan[ch].ADSRX.SustainIncrease)
-      {
-       if(s_chan[ch].ADSRX.SustainModeExp)
-        {
-         if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
-          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
-         else
-          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
-        }
-       else
-        {
-         s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
-        }
-
-       if(s_chan[ch].ADSRX.EnvelopeVol<0)
-        {
-         s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
-        }
-      }
-     else
-      {
-       if(s_chan[ch].ADSRX.SustainModeExp)
-        s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
-       else
-        s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
-
-       if(s_chan[ch].ADSRX.EnvelopeVol<0)
-        {
-         s_chan[ch].ADSRX.EnvelopeVol=0;
-        }
-      }
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-  }
- return 0;
-}
-
-#endif
-
-/*
-James Higgs ADSR investigations:
-
-PSX SPU Envelope Timings
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-First, here is an extract from doomed's SPU doc, which explains the basics
-of the SPU "volume envelope":
-
-*** doomed doc extract start ***
-
---------------------------------------------------------------------------
-Voices.
---------------------------------------------------------------------------
-The SPU has 24 hardware voices. These voices can be used to reproduce sample
-data, noise or can be used as frequency modulator on the next voice.
-Each voice has it's own programmable ADSR envelope filter. The main volume
-can be programmed independently for left and right output.
-
-The ADSR envelope filter works as follows:
-Ar = Attack rate, which specifies the speed at which the volume increases
-     from zero to it's maximum value, as soon as the note on is given. The
-     slope can be set to lineair or exponential.
-Dr = Decay rate specifies the speed at which the volume decreases to the
-     sustain level. Decay is always decreasing exponentially.
-Sl = Sustain level, base level from which sustain starts.
-Sr = Sustain rate is the rate at which the volume of the sustained note
-     increases or decreases. This can be either lineair or exponential.
-Rr = Release rate is the rate at which the volume of the note decreases
-     as soon as the note off is given.
-
-     lvl |
-       ^ |     /\Dr     __
-     Sl _| _  / _ \__---  \
-         |   /       ---__ \ Rr
-         |  /Ar       Sr  \ \
-         | /                \\
-         |/___________________\________
-                                  ->time
-
-The overal volume can also be set to sweep up or down lineairly or
-exponentially from it's current value. This can be done seperately
-for left and right.
-
-Relevant SPU registers:
--------------------------------------------------------------
-$1f801xx8         Attack/Decay/Sustain level
-bit  |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
-desc.|Am|         Ar         |Dr         |Sl         |
-
-Am       0        Attack mode Linear
-         1                    Exponential
-
-Ar       0-7f     attack rate
-Dr       0-f      decay rate
-Sl       0-f      sustain level
--------------------------------------------------------------
-$1f801xxa         Sustain rate, Release Rate.
-bit  |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
-desc.|Sm|Sd| 0|   Sr               |Rm|Rr            |
-
-Sm       0        sustain rate mode linear
-         1                          exponential
-Sd       0        sustain rate mode increase
-         1                          decrease
-Sr       0-7f     Sustain Rate
-Rm       0        Linear decrease
-         1        Exponential decrease
-Rr       0-1f     Release Rate
-
-Note: decay mode is always Expontial decrease, and thus cannot
-be set.
--------------------------------------------------------------
-$1f801xxc         Current ADSR volume
-bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
-desc.|ADSRvol                                        |
-
-ADSRvol           Returns the current envelope volume when
-                  read.
--- James' Note: return range: 0 -> 32767
-
-*** doomed doc extract end ***
-
-By using a small PSX proggie to visualise the envelope as it was played,
-the following results for envelope timing were obtained:
-
-1. Attack rate value (linear mode)
-
-   Attack value range: 0 -> 127
-
-   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |    | 80 |
-   -----------------------------------------------------------------
-   Frames | 11 | 21 | 42 | 84 | 169| 338| 676|    |2890|
-
-   Note: frames is no. of PAL frames to reach full volume (100%
-   amplitude)
-
-   Hmm, noticing that the time taken to reach full volume doubles
-   every time we add 4 to our attack value, we know the equation is
-   of form:
-             frames = k * 2 ^ (value / 4)
-
-   (You may ponder about envelope generator hardware at this point,
-   or maybe not... :)
-
-   By substituting some stuff and running some checks, we get:
-
-       k = 0.00257              (close enuf)
-
-   therefore,
-             frames = 0.00257 * 2 ^ (value / 4)
-   If you just happen to be writing an emulator, then you can probably
-   use an equation like:
-
-       %volume_increase_per_tick = 1 / frames
-
-
-   ------------------------------------
-   Pete:
-   ms=((1<<(value>>2))*514)/10000
-   ------------------------------------
-
-2. Decay rate value (only has log mode)
-
-   Decay value range: 0 -> 15
-
-   Value  |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
-   ------------------------------------------------
-   frames |    |    |    |    |  6 | 12 | 24 | 47 |
-
-   Note: frames here is no. of PAL frames to decay to 50% volume.
-
-   formula: frames = k * 2 ^ (value)
-
-   Substituting, we get: k = 0.00146
-
-   Further info on logarithmic nature:
-   frames to decay to sustain level 3  =  3 * frames to decay to
-   sustain level 9
-
-   Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
-   50% volume.
-
-   Frag it - just use linear approx.
-
-   ------------------------------------
-   Pete:
-   ms=((1<<value)*292)/10000
-   ------------------------------------
-
-
-3. Sustain rate value (linear mode)
-
-   Sustain rate range: 0 -> 127
-
-   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
-   -------------------------------------------
-   frames |  9 | 19 | 37 | 74 | 147| 293| 587|
-
-   Here, frames = no. of PAL frames for volume amplitude to go from 100%
-   to 0% (or vice-versa).
-
-   Same formula as for attack value, just a different value for k:
-
-   k = 0.00225
-
-   ie: frames = 0.00225 * 2 ^ (value / 4)
-
-   For emulation purposes:
-
-   %volume_increase_or_decrease_per_tick = 1 / frames
-
-   ------------------------------------
-   Pete:
-   ms=((1<<(value>>2))*450)/10000
-   ------------------------------------
-
-
-4. Release rate (linear mode)
-
-   Release rate range: 0 -> 31
-
-   Value  | 13 | 14 | 15 | 16 | 17 |
-   ---------------------------------------------------------------
-   frames | 18 | 36 | 73 | 146| 292|
-
-   Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
-   after "note-off" is triggered.
-
-   Formula: frames = k * 2 ^ (value)
-
-   And so: k = 0.00223
-
-   ------------------------------------
-   Pete:
-   ms=((1<<value)*446)/10000
-   ------------------------------------
-
-
-Other notes:
-
-Log stuff not figured out. You may get some clues from the "Decay rate"
-stuff above. For emu purposes it may not be important - use linear
-approx.
-
-To get timings in millisecs, multiply frames by 20.
-
-
-
-- James Higgs 17/6/2000
-james7780 at yahoo.com
-
-//---------------------------------------------------------------
-
-OLD adsr mixing according to james' rules... has to be called
-every one millisecond
-
-
- i32 v,v2,lT,l1,l2,l3;
-
- if(s_chan[ch].bStop)                                  // psx wants to stop? -> release phase
-  {
-   if(s_chan[ch].ADSR.ReleaseVal!=0)                   // -> release not 0: do release (if 0: stop right now)
-    {
-     if(!s_chan[ch].ADSR.ReleaseVol)                   // --> release just started? set up the release stuff
-      {
-       s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
-       s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
-       s_chan[ch].ADSR.ReleaseTime =                   // --> calc how long does it take to reach the wanted sus level
-         (s_chan[ch].ADSR.ReleaseTime*
-          s_chan[ch].ADSR.ReleaseVol)/1024;
-      }
-                                                       // -> NO release exp mode used (yet)
-     v=s_chan[ch].ADSR.ReleaseVol;                     // -> get last volume
-     lT=s_chan[ch].ADSR.lTime-                         // -> how much time is past?
-        s_chan[ch].ADSR.ReleaseStartTime;
-     l1=s_chan[ch].ADSR.ReleaseTime;
-
-     if(lT<l1)                                         // -> we still have to release
-      {
-       v=v-((v*lT)/l1);                                // --> calc new volume
-      }
-     else                                              // -> release is over: now really stop that sample
-      {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
-    }
-   else                                                // -> release IS 0: release at once
-    {
-     v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
-    }
-  }
- else
-  {//--------------------------------------------------// not in release phase:
-   v=1024;
-   lT=s_chan[ch].ADSR.lTime;
-   l1=s_chan[ch].ADSR.AttackTime;
-
-   if(lT<l1)                                           // attack
-    {                                                  // no exp mode used (yet)
-//     if(s_chan[ch].ADSR.AttackModeExp)
-//      {
-//       v=(v*lT)/l1;
-//      }
-//     else
-      {
-       v=(v*lT)/l1;
-      }
-     if(v==0) v=1;
-    }
-   else                                                // decay
-    {                                                  // should be exp, but who cares? ;)
-     l2=s_chan[ch].ADSR.DecayTime;
-     v2=s_chan[ch].ADSR.SustainLevel;
-
-     lT-=l1;
-     if(lT<l2)
-      {
-       v-=(((v-v2)*lT)/l2);
-      }
-     else                                              // sustain
-      {                                                // no exp mode used (yet)
-       l3=s_chan[ch].ADSR.SustainTime;
-       lT-=l2;
-       if(s_chan[ch].ADSR.SustainModeDec>0)
-        {
-         if(l3!=0) v2+=((v-v2)*lT)/l3;
-         else      v2=v;
-        }
-       else
-        {
-         if(l3!=0) v2-=(v2*lT)/l3;
-         else      v2=v;
-        }
-
-       if(v2>v)  v2=v;
-       if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
-
-       v=v2;
-      }
-    }
-  }
-
- //----------------------------------------------------//
- // ok, done for this channel, so increase time
-
- s_chan[ch].ADSR.lTime+=1;                             // 1 = 1.020408f ms;
-
- if(v>1024)     v=1024;                                // adjust volume
- if(v<0)        v=0;
- s_chan[ch].ADSR.lVolume=v;                            // store act volume
-
- return v;                                             // return the volume factor
-*/
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-
-/*
------------------------------------------------------------------------------
-Neill Corlett
-Playstation SPU envelope timing notes
------------------------------------------------------------------------------
-
-This is preliminary.  This may be wrong.  But the model described herein fits
-all of my experimental data, and it's just simple enough to sound right.
-
-ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
-The value returned by channel reg 0xC is (envelope_level>>16).
-
-Each sample, an increment or decrement value will be added to or
-subtracted from this envelope level.
-
-Create the rate log table.  The values double every 4 entries.
-   entry #0 = 4
-
-    4, 5, 6, 7,
-    8,10,12,14,
-   16,20,24,28, ...
-
-   entry #40 = 4096...
-   entry #44 = 8192...
-   entry #48 = 16384...
-   entry #52 = 32768...
-   entry #56 = 65536...
-
-increments and decrements are in terms of ratelogtable[n]
-n may exceed the table bounds (plan on n being between -32 and 127).
-table values are all clipped between 0x00000000 and 0x3FFFFFFF
-
-when you "voice on", the envelope is always fully reset.
-(yes, it may click. the real thing does this too.)
-
-envelope level begins at zero.
-
-each state happens for at least 1 cycle
-(transitions are not instantaneous)
-this may result in some oddness: if the decay rate is uberfast, it will cut
-the envelope from full down to half in one sample, potentially skipping over
-the sustain level
-
-ATTACK
-------
-- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
-  proceed to DECAY.
-
-Linear attack mode:
-- line extends upward to 0x7FFFFFFF
-- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
-
-Logarithmic attack mode:
-if envelope_level < 0x60000000:
-  - line extends upward to 0x60000000
-  - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
-else:
-  - line extends upward to 0x7FFFFFFF
-  - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
-
-DECAY
------
-- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
-  Do not clip to the sustain level.
-- current line ends at (envelope_level & 0x07FFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
-  1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
-  2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
-  3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
-  4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
-  5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
-  6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
-  7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
-  (note that this is the same as the release rate formula, except that
-   decay rates 10-1F aren't possible... those would be slower in theory)
-
-SUSTAIN
--------
-- no terminating condition except for voice off
-- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
-- Sd=1 (decrease) behavior:
-Linear sustain decrease:
-- line extends to 0x00000000
-- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
-Logarithmic sustain decrease:
-- current line ends at (envelope_level & 0x07FFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(Sr^0x7F)-0x1B+0]
-  1: ratelogtable[(Sr^0x7F)-0x1B+4]
-  2: ratelogtable[(Sr^0x7F)-0x1B+6]
-  3: ratelogtable[(Sr^0x7F)-0x1B+8]
-  4: ratelogtable[(Sr^0x7F)-0x1B+9]
-  5: ratelogtable[(Sr^0x7F)-0x1B+10]
-  6: ratelogtable[(Sr^0x7F)-0x1B+11]
-  7: ratelogtable[(Sr^0x7F)-0x1B+12]
-
-RELEASE
--------
-- if the envelope level has overflowed to negative, clip to 0 and QUIT.
-
-Linear release mode:
-- line extends to 0x00000000
-- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
-
-Logarithmic release mode:
-- line extends to (envelope_level & 0x0FFFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
-  1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
-  2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
-  3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
-  4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
-  5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
-  6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
-  7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
-
------------------------------------------------------------------------------
-*/
diff --git a/src/psf/peops/adsr.cc b/src/psf/peops/adsr.cc
new file mode 100644
index 000000000000..d9deca5a7632
--- /dev/null
+++ b/src/psf/peops/adsr.cc
@@ -0,0 +1,618 @@
+/***************************************************************************
+                          adsr.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#define _IN_ADSR
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// ADSR func
+////////////////////////////////////////////////////////////////////////
+
+static u32 RateTable[160];
+
+static void InitADSR(void)                                    // INIT ADSR
+{
+ u32 r,rs,rd;int i;
+
+ memset(RateTable,0,sizeof(u32)*160);        // build the rate table according to Neill's rules (see at bottom of file)
+
+ r=3;rs=1;rd=0;
+
+ for(i=32;i<160;i++)                                   // we start at pos 32 with the real values... everything before is 0
+  {
+   if(r<0x3FFFFFFF)
+    {
+     r+=rs;
+     rd++;if(rd==5) {rd=1;rs*=2;}
+    }
+   if(r>0x3FFFFFFF) r=0x3FFFFFFF;
+
+   RateTable[i]=r;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline void StartADSR(int ch)                          // MIX ADSR
+{
+ s_chan[ch].ADSRX.lVolume=1;                           // and init some adsr vars
+ s_chan[ch].ADSRX.State=0;
+ s_chan[ch].ADSRX.EnvelopeVol=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline int MixADSR(int ch)                             // MIX ADSR
+{
+ static const int sexytable[8]=
+	{0,4,6,8,9,10,11,12};
+
+ if(s_chan[ch].bStop)                                  // should be stopped:
+  {                                                    // do release
+   if(s_chan[ch].ADSRX.ReleaseModeExp)
+    {
+     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
+    }
+   else
+    {
+     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
+    }
+
+   if(s_chan[ch].ADSRX.EnvelopeVol<0)
+    {
+     s_chan[ch].ADSRX.EnvelopeVol=0;
+     s_chan[ch].bOn=0;
+     s_chan[ch].bNoise=0;
+    }
+
+   s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+   return s_chan[ch].ADSRX.lVolume;
+  }
+ else                                                  // not stopped yet?
+  {
+   if(s_chan[ch].ADSRX.State==0)                       // -> attack
+    {
+     if(s_chan[ch].ADSRX.AttackModeExp)
+      {
+       if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+       else
+        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
+      }
+     else
+      {
+       s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+      }
+
+     if(s_chan[ch].ADSRX.EnvelopeVol<0)
+      {
+       s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+       s_chan[ch].ADSRX.State=1;
+      }
+
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+   //--------------------------------------------------//
+   if(s_chan[ch].ADSRX.State==1)                       // -> decay
+    {
+     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
+
+     if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
+     if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
+      {
+       s_chan[ch].ADSRX.State=2;
+      }
+
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+   //--------------------------------------------------//
+   if(s_chan[ch].ADSRX.State==2)                       // -> sustain
+    {
+     if(s_chan[ch].ADSRX.SustainIncrease)
+      {
+       if(s_chan[ch].ADSRX.SustainModeExp)
+        {
+         if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+         else
+          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
+        }
+       else
+        {
+         s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+        }
+
+       if(s_chan[ch].ADSRX.EnvelopeVol<0)
+        {
+         s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+        }
+      }
+     else
+      {
+       if(s_chan[ch].ADSRX.SustainModeExp)
+        s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B+32+sexytable[(s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7]];
+       else
+        s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
+
+       if(s_chan[ch].ADSRX.EnvelopeVol<0)
+        {
+         s_chan[ch].ADSRX.EnvelopeVol=0;
+        }
+      }
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+  }
+ return 0;
+}
+
+#endif
+
+/*
+James Higgs ADSR investigations:
+
+PSX SPU Envelope Timings
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+First, here is an extract from doomed's SPU doc, which explains the basics
+of the SPU "volume envelope":
+
+*** doomed doc extract start ***
+
+--------------------------------------------------------------------------
+Voices.
+--------------------------------------------------------------------------
+The SPU has 24 hardware voices. These voices can be used to reproduce sample
+data, noise or can be used as frequency modulator on the next voice.
+Each voice has it's own programmable ADSR envelope filter. The main volume
+can be programmed independently for left and right output.
+
+The ADSR envelope filter works as follows:
+Ar = Attack rate, which specifies the speed at which the volume increases
+     from zero to it's maximum value, as soon as the note on is given. The
+     slope can be set to lineair or exponential.
+Dr = Decay rate specifies the speed at which the volume decreases to the
+     sustain level. Decay is always decreasing exponentially.
+Sl = Sustain level, base level from which sustain starts.
+Sr = Sustain rate is the rate at which the volume of the sustained note
+     increases or decreases. This can be either lineair or exponential.
+Rr = Release rate is the rate at which the volume of the note decreases
+     as soon as the note off is given.
+
+     lvl |
+       ^ |     /\Dr     __
+     Sl _| _  / _ \__---  \
+         |   /       ---__ \ Rr
+         |  /Ar       Sr  \ \
+         | /                \\
+         |/___________________\________
+                                  ->time
+
+The overal volume can also be set to sweep up or down lineairly or
+exponentially from it's current value. This can be done seperately
+for left and right.
+
+Relevant SPU registers:
+-------------------------------------------------------------
+$1f801xx8         Attack/Decay/Sustain level
+bit  |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
+desc.|Am|         Ar         |Dr         |Sl         |
+
+Am       0        Attack mode Linear
+         1                    Exponential
+
+Ar       0-7f     attack rate
+Dr       0-f      decay rate
+Sl       0-f      sustain level
+-------------------------------------------------------------
+$1f801xxa         Sustain rate, Release Rate.
+bit  |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
+desc.|Sm|Sd| 0|   Sr               |Rm|Rr            |
+
+Sm       0        sustain rate mode linear
+         1                          exponential
+Sd       0        sustain rate mode increase
+         1                          decrease
+Sr       0-7f     Sustain Rate
+Rm       0        Linear decrease
+         1        Exponential decrease
+Rr       0-1f     Release Rate
+
+Note: decay mode is always Expontial decrease, and thus cannot
+be set.
+-------------------------------------------------------------
+$1f801xxc         Current ADSR volume
+bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
+desc.|ADSRvol                                        |
+
+ADSRvol           Returns the current envelope volume when
+                  read.
+-- James' Note: return range: 0 -> 32767
+
+*** doomed doc extract end ***
+
+By using a small PSX proggie to visualise the envelope as it was played,
+the following results for envelope timing were obtained:
+
+1. Attack rate value (linear mode)
+
+   Attack value range: 0 -> 127
+
+   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |    | 80 |
+   -----------------------------------------------------------------
+   Frames | 11 | 21 | 42 | 84 | 169| 338| 676|    |2890|
+
+   Note: frames is no. of PAL frames to reach full volume (100%
+   amplitude)
+
+   Hmm, noticing that the time taken to reach full volume doubles
+   every time we add 4 to our attack value, we know the equation is
+   of form:
+             frames = k * 2 ^ (value / 4)
+
+   (You may ponder about envelope generator hardware at this point,
+   or maybe not... :)
+
+   By substituting some stuff and running some checks, we get:
+
+       k = 0.00257              (close enuf)
+
+   therefore,
+             frames = 0.00257 * 2 ^ (value / 4)
+   If you just happen to be writing an emulator, then you can probably
+   use an equation like:
+
+       %volume_increase_per_tick = 1 / frames
+
+
+   ------------------------------------
+   Pete:
+   ms=((1<<(value>>2))*514)/10000
+   ------------------------------------
+
+2. Decay rate value (only has log mode)
+
+   Decay value range: 0 -> 15
+
+   Value  |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
+   ------------------------------------------------
+   frames |    |    |    |    |  6 | 12 | 24 | 47 |
+
+   Note: frames here is no. of PAL frames to decay to 50% volume.
+
+   formula: frames = k * 2 ^ (value)
+
+   Substituting, we get: k = 0.00146
+
+   Further info on logarithmic nature:
+   frames to decay to sustain level 3  =  3 * frames to decay to
+   sustain level 9
+
+   Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
+   50% volume.
+
+   Frag it - just use linear approx.
+
+   ------------------------------------
+   Pete:
+   ms=((1<<value)*292)/10000
+   ------------------------------------
+
+
+3. Sustain rate value (linear mode)
+
+   Sustain rate range: 0 -> 127
+
+   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
+   -------------------------------------------
+   frames |  9 | 19 | 37 | 74 | 147| 293| 587|
+
+   Here, frames = no. of PAL frames for volume amplitude to go from 100%
+   to 0% (or vice-versa).
+
+   Same formula as for attack value, just a different value for k:
+
+   k = 0.00225
+
+   ie: frames = 0.00225 * 2 ^ (value / 4)
+
+   For emulation purposes:
+
+   %volume_increase_or_decrease_per_tick = 1 / frames
+
+   ------------------------------------
+   Pete:
+   ms=((1<<(value>>2))*450)/10000
+   ------------------------------------
+
+
+4. Release rate (linear mode)
+
+   Release rate range: 0 -> 31
+
+   Value  | 13 | 14 | 15 | 16 | 17 |
+   ---------------------------------------------------------------
+   frames | 18 | 36 | 73 | 146| 292|
+
+   Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
+   after "note-off" is triggered.
+
+   Formula: frames = k * 2 ^ (value)
+
+   And so: k = 0.00223
+
+   ------------------------------------
+   Pete:
+   ms=((1<<value)*446)/10000
+   ------------------------------------
+
+
+Other notes:
+
+Log stuff not figured out. You may get some clues from the "Decay rate"
+stuff above. For emu purposes it may not be important - use linear
+approx.
+
+To get timings in millisecs, multiply frames by 20.
+
+
+
+- James Higgs 17/6/2000
+james7780 at yahoo.com
+
+//---------------------------------------------------------------
+
+OLD adsr mixing according to james' rules... has to be called
+every one millisecond
+
+
+ i32 v,v2,lT,l1,l2,l3;
+
+ if(s_chan[ch].bStop)                                  // psx wants to stop? -> release phase
+  {
+   if(s_chan[ch].ADSR.ReleaseVal!=0)                   // -> release not 0: do release (if 0: stop right now)
+    {
+     if(!s_chan[ch].ADSR.ReleaseVol)                   // --> release just started? set up the release stuff
+      {
+       s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
+       s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
+       s_chan[ch].ADSR.ReleaseTime =                   // --> calc how long does it take to reach the wanted sus level
+         (s_chan[ch].ADSR.ReleaseTime*
+          s_chan[ch].ADSR.ReleaseVol)/1024;
+      }
+                                                       // -> NO release exp mode used (yet)
+     v=s_chan[ch].ADSR.ReleaseVol;                     // -> get last volume
+     lT=s_chan[ch].ADSR.lTime-                         // -> how much time is past?
+        s_chan[ch].ADSR.ReleaseStartTime;
+     l1=s_chan[ch].ADSR.ReleaseTime;
+
+     if(lT<l1)                                         // -> we still have to release
+      {
+       v=v-((v*lT)/l1);                                // --> calc new volume
+      }
+     else                                              // -> release is over: now really stop that sample
+      {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+    }
+   else                                                // -> release IS 0: release at once
+    {
+     v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
+    }
+  }
+ else
+  {//--------------------------------------------------// not in release phase:
+   v=1024;
+   lT=s_chan[ch].ADSR.lTime;
+   l1=s_chan[ch].ADSR.AttackTime;
+
+   if(lT<l1)                                           // attack
+    {                                                  // no exp mode used (yet)
+//     if(s_chan[ch].ADSR.AttackModeExp)
+//      {
+//       v=(v*lT)/l1;
+//      }
+//     else
+      {
+       v=(v*lT)/l1;
+      }
+     if(v==0) v=1;
+    }
+   else                                                // decay
+    {                                                  // should be exp, but who cares? ;)
+     l2=s_chan[ch].ADSR.DecayTime;
+     v2=s_chan[ch].ADSR.SustainLevel;
+
+     lT-=l1;
+     if(lT<l2)
+      {
+       v-=(((v-v2)*lT)/l2);
+      }
+     else                                              // sustain
+      {                                                // no exp mode used (yet)
+       l3=s_chan[ch].ADSR.SustainTime;
+       lT-=l2;
+       if(s_chan[ch].ADSR.SustainModeDec>0)
+        {
+         if(l3!=0) v2+=((v-v2)*lT)/l3;
+         else      v2=v;
+        }
+       else
+        {
+         if(l3!=0) v2-=(v2*lT)/l3;
+         else      v2=v;
+        }
+
+       if(v2>v)  v2=v;
+       if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+
+       v=v2;
+      }
+    }
+  }
+
+ //----------------------------------------------------//
+ // ok, done for this channel, so increase time
+
+ s_chan[ch].ADSR.lTime+=1;                             // 1 = 1.020408f ms;
+
+ if(v>1024)     v=1024;                                // adjust volume
+ if(v<0)        v=0;
+ s_chan[ch].ADSR.lVolume=v;                            // store act volume
+
+ return v;                                             // return the volume factor
+*/
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+/*
+-----------------------------------------------------------------------------
+Neill Corlett
+Playstation SPU envelope timing notes
+-----------------------------------------------------------------------------
+
+This is preliminary.  This may be wrong.  But the model described herein fits
+all of my experimental data, and it's just simple enough to sound right.
+
+ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
+The value returned by channel reg 0xC is (envelope_level>>16).
+
+Each sample, an increment or decrement value will be added to or
+subtracted from this envelope level.
+
+Create the rate log table.  The values double every 4 entries.
+   entry #0 = 4
+
+    4, 5, 6, 7,
+    8,10,12,14,
+   16,20,24,28, ...
+
+   entry #40 = 4096...
+   entry #44 = 8192...
+   entry #48 = 16384...
+   entry #52 = 32768...
+   entry #56 = 65536...
+
+increments and decrements are in terms of ratelogtable[n]
+n may exceed the table bounds (plan on n being between -32 and 127).
+table values are all clipped between 0x00000000 and 0x3FFFFFFF
+
+when you "voice on", the envelope is always fully reset.
+(yes, it may click. the real thing does this too.)
+
+envelope level begins at zero.
+
+each state happens for at least 1 cycle
+(transitions are not instantaneous)
+this may result in some oddness: if the decay rate is uberfast, it will cut
+the envelope from full down to half in one sample, potentially skipping over
+the sustain level
+
+ATTACK
+------
+- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
+  proceed to DECAY.
+
+Linear attack mode:
+- line extends upward to 0x7FFFFFFF
+- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+
+Logarithmic attack mode:
+if envelope_level < 0x60000000:
+  - line extends upward to 0x60000000
+  - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+else:
+  - line extends upward to 0x7FFFFFFF
+  - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
+
+DECAY
+-----
+- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
+  Do not clip to the sustain level.
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
+  1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
+  2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
+  3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
+  4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
+  5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
+  6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
+  7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
+  (note that this is the same as the release rate formula, except that
+   decay rates 10-1F aren't possible... those would be slower in theory)
+
+SUSTAIN
+-------
+- no terminating condition except for voice off
+- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
+- Sd=1 (decrease) behavior:
+Linear sustain decrease:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
+Logarithmic sustain decrease:
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(Sr^0x7F)-0x1B+0]
+  1: ratelogtable[(Sr^0x7F)-0x1B+4]
+  2: ratelogtable[(Sr^0x7F)-0x1B+6]
+  3: ratelogtable[(Sr^0x7F)-0x1B+8]
+  4: ratelogtable[(Sr^0x7F)-0x1B+9]
+  5: ratelogtable[(Sr^0x7F)-0x1B+10]
+  6: ratelogtable[(Sr^0x7F)-0x1B+11]
+  7: ratelogtable[(Sr^0x7F)-0x1B+12]
+
+RELEASE
+-------
+- if the envelope level has overflowed to negative, clip to 0 and QUIT.
+
+Linear release mode:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
+
+Logarithmic release mode:
+- line extends to (envelope_level & 0x0FFFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
+  1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
+  2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
+  3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
+  4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
+  5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
+  6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
+  7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
+
+-----------------------------------------------------------------------------
+*/
diff --git a/src/psf/peops/dma.c b/src/psf/peops/dma.c
deleted file mode 100644
index 24994a0de2ff..000000000000
--- a/src/psf/peops/dma.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/***************************************************************************
-                            dma.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "../peops/stdafx.h"
-
-#define _IN_DMA
-
-extern uint32_t psx_ram[(2*1024*1024)/4];
-
-//#include "externals.h"
-////////////////////////////////////////////////////////////////////////
-// READ DMA (many values)
-////////////////////////////////////////////////////////////////////////
-
-void SPUreadDMAMem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-   ram16[usPSXMem>>1]=spuMem[spuAddr>>1];		// spu addr got by writeregister
-   usPSXMem+=2;
-   spuAddr+=2;                                         // inc spu addr
-   if(spuAddr>0x7ffff) spuAddr=0;                      // wrap
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-
-// to investigate: do sound data updates by writedma affect spu
-// irqs? Will an irq be triggered, if new data is written to
-// the memory irq address?
-
-////////////////////////////////////////////////////////////////////////
-// WRITE DMA (many values)
-////////////////////////////////////////////////////////////////////////
-
-void SPUwriteDMAMem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-//  printf("main RAM %x => SPU %x\n", usPSXMem, spuAddr);
-   spuMem[spuAddr>>1] = ram16[usPSXMem>>1];
-   usPSXMem+=2;                  			// spu addr got by writeregister
-   spuAddr+=2;                                         // inc spu addr
-   if(spuAddr>0x7ffff) spuAddr=0;                      // wrap
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-
diff --git a/src/psf/peops/dma.cc b/src/psf/peops/dma.cc
new file mode 100644
index 000000000000..24994a0de2ff
--- /dev/null
+++ b/src/psf/peops/dma.cc
@@ -0,0 +1,80 @@
+/***************************************************************************
+                            dma.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "../peops/stdafx.h"
+
+#define _IN_DMA
+
+extern uint32_t psx_ram[(2*1024*1024)/4];
+
+//#include "externals.h"
+////////////////////////////////////////////////////////////////////////
+// READ DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+void SPUreadDMAMem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+   ram16[usPSXMem>>1]=spuMem[spuAddr>>1];		// spu addr got by writeregister
+   usPSXMem+=2;
+   spuAddr+=2;                                         // inc spu addr
+   if(spuAddr>0x7ffff) spuAddr=0;                      // wrap
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+// to investigate: do sound data updates by writedma affect spu
+// irqs? Will an irq be triggered, if new data is written to
+// the memory irq address?
+
+////////////////////////////////////////////////////////////////////////
+// WRITE DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+void SPUwriteDMAMem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+//  printf("main RAM %x => SPU %x\n", usPSXMem, spuAddr);
+   spuMem[spuAddr>>1] = ram16[usPSXMem>>1];
+   usPSXMem+=2;                  			// spu addr got by writeregister
+   spuAddr+=2;                                         // inc spu addr
+   if(spuAddr>0x7ffff) spuAddr=0;                      // wrap
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/psf/peops/registers.c b/src/psf/peops/registers.c
deleted file mode 100644
index bcafc8c07938..000000000000
--- a/src/psf/peops/registers.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/***************************************************************************
-                         registers.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-/* ChangeLog 
-
- February 8, 2004	-	xodnizel
- - Fixed setting of reverb volume.  Just typecast val("u16") to s16.
-   Also adjusted the normal channel volume to be one less than what it was before when the 
-   "phase invert" bit is set.  I'm assuming it's just in two's complement.
-
- 2003/02/09 - kode54
- - removed &0x3fff from reverb volume registers, fixes a few games,
-   hopefully won't be breaking anything
-
- 2003/01/19 - Pete
- - added Neill's reverb
-
- 2003/01/06 - Pete
- - added Neill's ADSR timings
-
- 2002/05/15 - Pete
- - generic cleanup for the Peops release
-
-*/
-
-#include "stdafx.h"
-
-#define _IN_REGISTERS
-
-#include "../peops/externals.h"
-#include "../peops/registers.h"
-#include "../peops/regs.h"
-
-static void SoundOn(int start,int end,u16 val);
-static void SoundOff(int start,int end,u16 val);
-static void FModOn(int start,int end,u16 val);
-static void NoiseOn(int start,int end,u16 val);
-static void SetVolumeLR(int right, u8 ch,s16 vol);
-static void SetPitch(int ch,u16 val);
-
-////////////////////////////////////////////////////////////////////////
-// WRITE REGISTERS: called by main emu
-////////////////////////////////////////////////////////////////////////
-
-void SPUwriteRegister(u32 reg, u16 val)
-{
- const u32 r=reg&0xfff;
- regArea[(r-0xc00)>>1] = val;
-
-// printf("SPUwrite: r %x val %x\n", r, val);
-
- if(r>=0x0c00 && r<0x0d80)                             // some channel info?
-  {
-   int ch=(r>>4)-0xc0;                                 // calc channel
-
-   //if(ch==20) printf("%08x: %04x\n",reg,val);
-
-   switch(r&0x0f)
-    {
-     //------------------------------------------------// r volume
-     case 0:                                           
-       SetVolumeLR(0,(u8)ch,val);
-       break;
-     //------------------------------------------------// l volume
-     case 2:                                           
-       SetVolumeLR(1,(u8)ch,val);
-       break;
-     //------------------------------------------------// pitch
-     case 4:                                           
-       SetPitch(ch,val);
-       break;
-     //------------------------------------------------// start
-     case 6:      
-       s_chan[ch].pStart=spuMemC+((u32) val<<3);
-       break;
-     //------------------------------------------------// level with pre-calcs
-     case 8:
-       {
-        const u32 lval=val; // DEBUG CHECK
-        //---------------------------------------------//
-        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; 
-        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
-        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
-        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
-        //---------------------------------------------//
-      }
-      break;
-     //------------------------------------------------// adsr times with pre-calcs
-     case 10:
-      {
-       const u32 lval=val; // DEBUG CHECK
-
-       //----------------------------------------------//
-       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
-       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
-       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
-       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
-       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
-       //----------------------------------------------//
-      }
-     break;
-     //------------------------------------------------// adsr volume... mmm have to investigate this
-     //case 0xC:
-     //  break;
-     //------------------------------------------------//
-     case 0xE:                                          // loop?
-       s_chan[ch].pLoop=spuMemC+((u32) val<<3);
-       s_chan[ch].bIgnoreLoop=1;
-       break;
-     //------------------------------------------------//
-    }
-   return;
-  }
-
- switch(r)
-   {
-    //-------------------------------------------------//
-    case H_SPUaddr:
-      spuAddr = (u32) val<<3;
-      break;
-    //-------------------------------------------------//
-    case H_SPUdata:
-      spuMem[spuAddr>>1] = BFLIP16(val);
-      spuAddr+=2;
-      if(spuAddr>0x7ffff) spuAddr=0;
-      break;
-    //-------------------------------------------------//
-    case H_SPUctrl:
-      spuCtrl=val;
-      break;
-    //-------------------------------------------------//
-    case H_SPUstat:
-      spuStat=val & 0xf800;
-      break;
-    //-------------------------------------------------//
-    case H_SPUReverbAddr:
-      if(val==0xFFFF || val<=0x200)
-       {rvb.StartAddr=rvb.CurrAddr=0;}
-      else
-       {
-        const s32 iv=(u32)val<<2;
-        if(rvb.StartAddr!=iv)
-         {
-          rvb.StartAddr=(u32)val<<2;
-          rvb.CurrAddr=rvb.StartAddr;
-         }
-       }
-      break;
-    //-------------------------------------------------//
-    case H_SPUirqAddr:
-      spuIrq = val;
-      pSpuIrq=spuMemC+((u32) val<<3);
-      break;
-    //-------------------------------------------------//
-    /* Volume settings appear to be at least 15-bit unsigned in this case.  
-       Definitely NOT 15-bit signed.  Probably 16-bit signed, so s16 type cast.
-       Check out "Chrono Cross:  Shadow's End Forest"
-    */
-    case H_SPUrvolL:
-      rvb.VolLeft=(s16)val;
-      //printf("%d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUrvolR:
-      rvb.VolRight=(s16)val;
-      //printf("%d\n",val);
-      break;
-    //-------------------------------------------------//
-
-/*
-    case H_ExtLeft:
-     //auxprintf("EL %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_ExtRight:
-     //auxprintf("ER %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUmvolL:
-     //auxprintf("ML %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUmvolR:
-     //auxprintf("MR %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUMute1:
-     //printf("M0 %04x\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUMute2:
-    // printf("M1 %04x\n",val);
-      break;
-*/
-    //-------------------------------------------------//
-    case H_SPUon1:
-      SoundOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-     case H_SPUon2:
-	// printf("Boop: %08x: %04x\n",reg,val);
-      SoundOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUoff1:
-      SoundOff(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUoff2:
-      SoundOff(16,24,val);
-	// printf("Boop: %08x: %04x\n",reg,val);
-      break;
-    //-------------------------------------------------//
-    case H_FMod1:
-      FModOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_FMod2:
-      FModOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_Noise1:
-      NoiseOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_Noise2:
-      NoiseOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_RVBon1:
-      rvb.Enabled&=~0xFFFF;
-      rvb.Enabled|=val;
-      break;
-
-    //-------------------------------------------------//
-    case H_RVBon2:
-      rvb.Enabled&=0xFFFF;
-      rvb.Enabled|=val<<16;
-      break;
-
-    //-------------------------------------------------//
-    case H_Reverb+0:
-      rvb.FB_SRC_A=val;
-      break;
-
-    case H_Reverb+2   : rvb.FB_SRC_B=(s16)val;       break;
-    case H_Reverb+4   : rvb.IIR_ALPHA=(s16)val;      break;
-    case H_Reverb+6   : rvb.ACC_COEF_A=(s16)val;     break;
-    case H_Reverb+8   : rvb.ACC_COEF_B=(s16)val;     break;
-    case H_Reverb+10  : rvb.ACC_COEF_C=(s16)val;     break;
-    case H_Reverb+12  : rvb.ACC_COEF_D=(s16)val;     break;
-    case H_Reverb+14  : rvb.IIR_COEF=(s16)val;       break;
-    case H_Reverb+16  : rvb.FB_ALPHA=(s16)val;       break;
-    case H_Reverb+18  : rvb.FB_X=(s16)val;           break;
-    case H_Reverb+20  : rvb.IIR_DEST_A0=(s16)val;    break;
-    case H_Reverb+22  : rvb.IIR_DEST_A1=(s16)val;    break;
-    case H_Reverb+24  : rvb.ACC_SRC_A0=(s16)val;     break;
-    case H_Reverb+26  : rvb.ACC_SRC_A1=(s16)val;     break;
-    case H_Reverb+28  : rvb.ACC_SRC_B0=(s16)val;     break;
-    case H_Reverb+30  : rvb.ACC_SRC_B1=(s16)val;     break;
-    case H_Reverb+32  : rvb.IIR_SRC_A0=(s16)val;     break;
-    case H_Reverb+34  : rvb.IIR_SRC_A1=(s16)val;     break;
-    case H_Reverb+36  : rvb.IIR_DEST_B0=(s16)val;    break;
-    case H_Reverb+38  : rvb.IIR_DEST_B1=(s16)val;    break;
-    case H_Reverb+40  : rvb.ACC_SRC_C0=(s16)val;     break;
-    case H_Reverb+42  : rvb.ACC_SRC_C1=(s16)val;     break;
-    case H_Reverb+44  : rvb.ACC_SRC_D0=(s16)val;     break;
-    case H_Reverb+46  : rvb.ACC_SRC_D1=(s16)val;     break;
-    case H_Reverb+48  : rvb.IIR_SRC_B1=(s16)val;     break;
-    case H_Reverb+50  : rvb.IIR_SRC_B0=(s16)val;     break;
-    case H_Reverb+52  : rvb.MIX_DEST_A0=(s16)val;    break;
-    case H_Reverb+54  : rvb.MIX_DEST_A1=(s16)val;    break;
-    case H_Reverb+56  : rvb.MIX_DEST_B0=(s16)val;    break;
-    case H_Reverb+58  : rvb.MIX_DEST_B1=(s16)val;    break;
-    case H_Reverb+60  : rvb.IN_COEF_L=(s16)val;      break;
-    case H_Reverb+62  : rvb.IN_COEF_R=(s16)val;      break;
-   }
-
-}
-
-////////////////////////////////////////////////////////////////////////
-// READ REGISTER: called by main emu
-////////////////////////////////////////////////////////////////////////
-
-u16 SPUreadRegister(u32 reg)
-{
- const u32 r=reg&0xfff;
-
- if(r>=0x0c00 && r<0x0d80)
-  {
-   switch(r&0x0f)
-    {
-     case 0xC:                                          // get adsr vol
-      {
-       const int ch=(r>>4)-0xc0;
-       if(s_chan[ch].bNew) return 1;                   // we are started, but not processed? return 1
-       if(s_chan[ch].ADSRX.lVolume &&                  // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
-          !s_chan[ch].ADSRX.EnvelopeVol)                   
-        return 1;
-       return (u16)(s_chan[ch].ADSRX.EnvelopeVol>>16);
-      }
-
-     case 0xE:                                          // get loop address
-      {
-       const int ch=(r>>4)-0xc0;
-       if(s_chan[ch].pLoop==NULL) return 0;
-       return (u16)((s_chan[ch].pLoop-spuMemC)>>3);
-      }
-    }
-  }
-
- switch(r)
-  {
-    case H_SPUctrl:
-     return spuCtrl;
-
-    case H_SPUstat:
-     return spuStat;
-        
-    case H_SPUaddr:
-     return (u16)(spuAddr>>3);
-
-    case H_SPUdata:
-     {
-      u16 s=BFLIP16(spuMem[spuAddr>>1]);
-      spuAddr+=2;
-      if(spuAddr>0x7ffff) spuAddr=0;
-      return s;
-     }
-
-    case H_SPUirqAddr:
-     return spuIrq;
-
-    //case H_SPUIsOn1:
-    // return IsSoundOn(0,16);
-
-    //case H_SPUIsOn2:
-    // return IsSoundOn(16,24);
- 
-  }
-
- return regArea[(r-0xc00)>>1];
-}
- 
-////////////////////////////////////////////////////////////////////////
-// SOUND ON register write
-////////////////////////////////////////////////////////////////////////
-
-static void SoundOn(int start,int end,u16 val)     // SOUND ON PSX COMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if((val&1) && s_chan[ch].pStart)                    // mmm... start has to be set before key on !?!
-    {
-     s_chan[ch].bIgnoreLoop=0;
-     s_chan[ch].bNew=1;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// SOUND OFF register write
-////////////////////////////////////////////////////////////////////////
-
-static void SoundOff(int start,int end,u16 val)    // SOUND OFF PSX COMMAND
-{
- int ch;
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // && s_chan[i].bOn)  mmm...
-    {
-     s_chan[ch].bStop=1;
-    }                                                  
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// FMOD register write
-////////////////////////////////////////////////////////////////////////
-
-static void FModOn(int start,int end,u16 val)      // FMOD ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> fmod on/off
-    {
-     if(ch>0) 
-      {
-       s_chan[ch].bFMod=1;                             // --> sound channel
-       s_chan[ch-1].bFMod=2;                           // --> freq channel
-      }
-    }
-   else
-    {
-     s_chan[ch].bFMod=0;                               // --> turn off fmod
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// NOISE register write
-////////////////////////////////////////////////////////////////////////
-
-static void NoiseOn(int start,int end,u16 val)     // NOISE ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> noise on/off
-    {
-     s_chan[ch].bNoise=1;
-    }
-   else 
-    {
-     s_chan[ch].bNoise=0;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// LEFT VOLUME register write
-////////////////////////////////////////////////////////////////////////
-
-// please note: sweep is wrong.
-
-static void SetVolumeLR(int right, u8 ch,s16 vol)            // LEFT VOLUME
-{
- //if(vol&0xc000)
- //printf("%d %08x\n",right,vol);
- if(right)
-  s_chan[ch].iRightVolRaw=vol;
- else
-  s_chan[ch].iLeftVolRaw=vol;
-
- if(vol&0x8000)                                        // sweep?
-  {
-   s16 sInc=1;                                       // -> sweep up?
-   if(vol&0x2000) sInc=-1;                             // -> or down?
-   if(vol&0x1000) vol^=0xffff;                         // -> mmm... phase inverted? have to investigate this
-   vol=((vol&0x7f)+1)/2;                               // -> sweep: 0..127 -> 0..64
-   vol+=vol/(2*sInc);                                  // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
-   vol*=128;
-   vol&=0x3fff;
-   //puts("Sweep");
-  }
- else                                                  // no sweep:
-  {
-   if(vol&0x4000)
-    vol=(vol&0x3FFF)-0x4000;
-   else
-    vol&=0x3FFF;
-
-   //if(vol&0x4000)                                      // -> mmm... phase inverted? have to investigate this
-   // vol=0-(0x3fff-(vol&0x3fff));
-   //else
-   // vol&=0x3fff;
-  }
- if(right)
-  s_chan[ch].iRightVolume=vol;
- else
-  s_chan[ch].iLeftVolume=vol;                           // store volume
-}
-
-////////////////////////////////////////////////////////////////////////
-// PITCH register write
-////////////////////////////////////////////////////////////////////////
-
-static void SetPitch(int ch,u16 val)               // SET PITCH
-{
- int NP;
- if(val>0x3fff) NP=0x3fff;                             // get pitch val
- else           NP=val;
-
- s_chan[ch].iRawPitch=NP;
-
- NP=(44100L*NP)/4096L;                                 // calc frequency
- if(NP<1) NP=1;                                        // some security
- s_chan[ch].iActFreq=NP;                               // store frequency
-}
diff --git a/src/psf/peops/registers.cc b/src/psf/peops/registers.cc
new file mode 100644
index 000000000000..0651a838475f
--- /dev/null
+++ b/src/psf/peops/registers.cc
@@ -0,0 +1,499 @@
+/***************************************************************************
+                         registers.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+/* ChangeLog
+
+ February 8, 2004	-	xodnizel
+ - Fixed setting of reverb volume.  Just typecast val("u16") to s16.
+   Also adjusted the normal channel volume to be one less than what it was before when the
+   "phase invert" bit is set.  I'm assuming it's just in two's complement.
+
+ 2003/02/09 - kode54
+ - removed &0x3fff from reverb volume registers, fixes a few games,
+   hopefully won't be breaking anything
+
+ 2003/01/19 - Pete
+ - added Neill's reverb
+
+ 2003/01/06 - Pete
+ - added Neill's ADSR timings
+
+ 2002/05/15 - Pete
+ - generic cleanup for the Peops release
+
+*/
+
+#include "stdafx.h"
+
+#define _IN_REGISTERS
+
+#include "../peops/externals.h"
+#include "../peops/registers.h"
+#include "../peops/regs.h"
+
+static void SoundOn(int start,int end,u16 val);
+static void SoundOff(int start,int end,u16 val);
+static void FModOn(int start,int end,u16 val);
+static void NoiseOn(int start,int end,u16 val);
+static void SetVolumeLR(int right, u8 ch,s16 vol);
+static void SetPitch(int ch,u16 val);
+
+////////////////////////////////////////////////////////////////////////
+// WRITE REGISTERS: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+void SPUwriteRegister(u32 reg, u16 val)
+{
+ const u32 r=reg&0xfff;
+ regArea[(r-0xc00)>>1] = val;
+
+// printf("SPUwrite: r %x val %x\n", r, val);
+
+ if(r>=0x0c00 && r<0x0d80)                             // some channel info?
+  {
+   int ch=(r>>4)-0xc0;                                 // calc channel
+
+   //if(ch==20) printf("%08x: %04x\n",reg,val);
+
+   switch(r&0x0f)
+    {
+     //------------------------------------------------// r volume
+     case 0:
+       SetVolumeLR(0,(u8)ch,val);
+       break;
+     //------------------------------------------------// l volume
+     case 2:
+       SetVolumeLR(1,(u8)ch,val);
+       break;
+     //------------------------------------------------// pitch
+     case 4:
+       SetPitch(ch,val);
+       break;
+     //------------------------------------------------// start
+     case 6:
+       s_chan[ch].pStart=spuMemC+((u32) val<<3);
+       break;
+     //------------------------------------------------// level with pre-calcs
+     case 8:
+       {
+        const u32 lval=val; // DEBUG CHECK
+        //---------------------------------------------//
+        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
+        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
+        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
+        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
+        //---------------------------------------------//
+      }
+      break;
+     //------------------------------------------------// adsr times with pre-calcs
+     case 10:
+      {
+       const u32 lval=val; // DEBUG CHECK
+
+       //----------------------------------------------//
+       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
+       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
+       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
+       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
+       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
+       //----------------------------------------------//
+      }
+     break;
+     //------------------------------------------------// adsr volume... mmm have to investigate this
+     //case 0xC:
+     //  break;
+     //------------------------------------------------//
+     case 0xE:                                          // loop?
+       s_chan[ch].pLoop=spuMemC+((u32) val<<3);
+       s_chan[ch].bIgnoreLoop=1;
+       break;
+     //------------------------------------------------//
+    }
+   return;
+  }
+
+ switch(r)
+   {
+    //-------------------------------------------------//
+    case H_SPUaddr:
+      spuAddr = (u32) val<<3;
+      break;
+    //-------------------------------------------------//
+    case H_SPUdata:
+      spuMem[spuAddr>>1] = BFLIP16(val);
+      spuAddr+=2;
+      if(spuAddr>0x7ffff) spuAddr=0;
+      break;
+    //-------------------------------------------------//
+    case H_SPUctrl:
+      spuCtrl=val;
+      break;
+    //-------------------------------------------------//
+    case H_SPUstat:
+      spuStat=val & 0xf800;
+      break;
+    //-------------------------------------------------//
+    case H_SPUReverbAddr:
+      if(val==0xFFFF || val<=0x200)
+       {rvb.StartAddr=rvb.CurrAddr=0;}
+      else
+       {
+        const s32 iv=(u32)val<<2;
+        if(rvb.StartAddr!=iv)
+         {
+          rvb.StartAddr=(u32)val<<2;
+          rvb.CurrAddr=rvb.StartAddr;
+         }
+       }
+      break;
+    //-------------------------------------------------//
+    case H_SPUirqAddr:
+      spuIrq = val;
+      pSpuIrq=spuMemC+((u32) val<<3);
+      break;
+    //-------------------------------------------------//
+    /* Volume settings appear to be at least 15-bit unsigned in this case.
+       Definitely NOT 15-bit signed.  Probably 16-bit signed, so s16 type cast.
+       Check out "Chrono Cross:  Shadow's End Forest"
+    */
+    case H_SPUrvolL:
+      rvb.VolLeft=(s16)val;
+      //printf("%d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUrvolR:
+      rvb.VolRight=(s16)val;
+      //printf("%d\n",val);
+      break;
+    //-------------------------------------------------//
+
+/*
+    case H_ExtLeft:
+     //auxprintf("EL %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_ExtRight:
+     //auxprintf("ER %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUmvolL:
+     //auxprintf("ML %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUmvolR:
+     //auxprintf("MR %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUMute1:
+     //printf("M0 %04x\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUMute2:
+    // printf("M1 %04x\n",val);
+      break;
+*/
+    //-------------------------------------------------//
+    case H_SPUon1:
+      SoundOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+     case H_SPUon2:
+	// printf("Boop: %08x: %04x\n",reg,val);
+      SoundOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUoff1:
+      SoundOff(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUoff2:
+      SoundOff(16,24,val);
+	// printf("Boop: %08x: %04x\n",reg,val);
+      break;
+    //-------------------------------------------------//
+    case H_FMod1:
+      FModOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_FMod2:
+      FModOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_Noise1:
+      NoiseOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_Noise2:
+      NoiseOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_RVBon1:
+      rvb.Enabled&=~0xFFFF;
+      rvb.Enabled|=val;
+      break;
+
+    //-------------------------------------------------//
+    case H_RVBon2:
+      rvb.Enabled&=0xFFFF;
+      rvb.Enabled|=val<<16;
+      break;
+
+    //-------------------------------------------------//
+    case H_Reverb+0:
+      rvb.FB_SRC_A=val;
+      break;
+
+    case H_Reverb+2   : rvb.FB_SRC_B=(s16)val;       break;
+    case H_Reverb+4   : rvb.IIR_ALPHA=(s16)val;      break;
+    case H_Reverb+6   : rvb.ACC_COEF_A=(s16)val;     break;
+    case H_Reverb+8   : rvb.ACC_COEF_B=(s16)val;     break;
+    case H_Reverb+10  : rvb.ACC_COEF_C=(s16)val;     break;
+    case H_Reverb+12  : rvb.ACC_COEF_D=(s16)val;     break;
+    case H_Reverb+14  : rvb.IIR_COEF=(s16)val;       break;
+    case H_Reverb+16  : rvb.FB_ALPHA=(s16)val;       break;
+    case H_Reverb+18  : rvb.FB_X=(s16)val;           break;
+    case H_Reverb+20  : rvb.IIR_DEST_A0=(s16)val;    break;
+    case H_Reverb+22  : rvb.IIR_DEST_A1=(s16)val;    break;
+    case H_Reverb+24  : rvb.ACC_SRC_A0=(s16)val;     break;
+    case H_Reverb+26  : rvb.ACC_SRC_A1=(s16)val;     break;
+    case H_Reverb+28  : rvb.ACC_SRC_B0=(s16)val;     break;
+    case H_Reverb+30  : rvb.ACC_SRC_B1=(s16)val;     break;
+    case H_Reverb+32  : rvb.IIR_SRC_A0=(s16)val;     break;
+    case H_Reverb+34  : rvb.IIR_SRC_A1=(s16)val;     break;
+    case H_Reverb+36  : rvb.IIR_DEST_B0=(s16)val;    break;
+    case H_Reverb+38  : rvb.IIR_DEST_B1=(s16)val;    break;
+    case H_Reverb+40  : rvb.ACC_SRC_C0=(s16)val;     break;
+    case H_Reverb+42  : rvb.ACC_SRC_C1=(s16)val;     break;
+    case H_Reverb+44  : rvb.ACC_SRC_D0=(s16)val;     break;
+    case H_Reverb+46  : rvb.ACC_SRC_D1=(s16)val;     break;
+    case H_Reverb+48  : rvb.IIR_SRC_B1=(s16)val;     break;
+    case H_Reverb+50  : rvb.IIR_SRC_B0=(s16)val;     break;
+    case H_Reverb+52  : rvb.MIX_DEST_A0=(s16)val;    break;
+    case H_Reverb+54  : rvb.MIX_DEST_A1=(s16)val;    break;
+    case H_Reverb+56  : rvb.MIX_DEST_B0=(s16)val;    break;
+    case H_Reverb+58  : rvb.MIX_DEST_B1=(s16)val;    break;
+    case H_Reverb+60  : rvb.IN_COEF_L=(s16)val;      break;
+    case H_Reverb+62  : rvb.IN_COEF_R=(s16)val;      break;
+   }
+
+}
+
+////////////////////////////////////////////////////////////////////////
+// READ REGISTER: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+u16 SPUreadRegister(u32 reg)
+{
+ const u32 r=reg&0xfff;
+
+ if(r>=0x0c00 && r<0x0d80)
+  {
+   switch(r&0x0f)
+    {
+     case 0xC:                                          // get adsr vol
+      {
+       const int ch=(r>>4)-0xc0;
+       if(s_chan[ch].bNew) return 1;                   // we are started, but not processed? return 1
+       if(s_chan[ch].ADSRX.lVolume &&                  // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
+          !s_chan[ch].ADSRX.EnvelopeVol)
+        return 1;
+       return (u16)(s_chan[ch].ADSRX.EnvelopeVol>>16);
+      }
+
+     case 0xE:                                          // get loop address
+      {
+       const int ch=(r>>4)-0xc0;
+       if(s_chan[ch].pLoop==nullptr) return 0;
+       return (u16)((s_chan[ch].pLoop-spuMemC)>>3);
+      }
+    }
+  }
+
+ switch(r)
+  {
+    case H_SPUctrl:
+     return spuCtrl;
+
+    case H_SPUstat:
+     return spuStat;
+
+    case H_SPUaddr:
+     return (u16)(spuAddr>>3);
+
+    case H_SPUdata:
+     {
+      u16 s=BFLIP16(spuMem[spuAddr>>1]);
+      spuAddr+=2;
+      if(spuAddr>0x7ffff) spuAddr=0;
+      return s;
+     }
+
+    case H_SPUirqAddr:
+     return spuIrq;
+
+    //case H_SPUIsOn1:
+    // return IsSoundOn(0,16);
+
+    //case H_SPUIsOn2:
+    // return IsSoundOn(16,24);
+
+  }
+
+ return regArea[(r-0xc00)>>1];
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND ON register write
+////////////////////////////////////////////////////////////////////////
+
+static void SoundOn(int start,int end,u16 val)     // SOUND ON PSX COMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if((val&1) && s_chan[ch].pStart)                    // mmm... start has to be set before key on !?!
+    {
+     s_chan[ch].bIgnoreLoop=0;
+     s_chan[ch].bNew=1;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND OFF register write
+////////////////////////////////////////////////////////////////////////
+
+static void SoundOff(int start,int end,u16 val)    // SOUND OFF PSX COMMAND
+{
+ int ch;
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // && s_chan[i].bOn)  mmm...
+    {
+     s_chan[ch].bStop=1;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// FMOD register write
+////////////////////////////////////////////////////////////////////////
+
+static void FModOn(int start,int end,u16 val)      // FMOD ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> fmod on/off
+    {
+     if(ch>0)
+      {
+       s_chan[ch].bFMod=1;                             // --> sound channel
+       s_chan[ch-1].bFMod=2;                           // --> freq channel
+      }
+    }
+   else
+    {
+     s_chan[ch].bFMod=0;                               // --> turn off fmod
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// NOISE register write
+////////////////////////////////////////////////////////////////////////
+
+static void NoiseOn(int start,int end,u16 val)     // NOISE ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> noise on/off
+    {
+     s_chan[ch].bNoise=1;
+    }
+   else
+    {
+     s_chan[ch].bNoise=0;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// LEFT VOLUME register write
+////////////////////////////////////////////////////////////////////////
+
+// please note: sweep is wrong.
+
+static void SetVolumeLR(int right, u8 ch,s16 vol)            // LEFT VOLUME
+{
+ //if(vol&0xc000)
+ //printf("%d %08x\n",right,vol);
+ if(right)
+  s_chan[ch].iRightVolRaw=vol;
+ else
+  s_chan[ch].iLeftVolRaw=vol;
+
+ if(vol&0x8000)                                        // sweep?
+  {
+   s16 sInc=1;                                       // -> sweep up?
+   if(vol&0x2000) sInc=-1;                             // -> or down?
+   if(vol&0x1000) vol^=0xffff;                         // -> mmm... phase inverted? have to investigate this
+   vol=((vol&0x7f)+1)/2;                               // -> sweep: 0..127 -> 0..64
+   vol+=vol/(2*sInc);                                  // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
+   vol*=128;
+   vol&=0x3fff;
+   //puts("Sweep");
+  }
+ else                                                  // no sweep:
+  {
+   if(vol&0x4000)
+    vol=(vol&0x3FFF)-0x4000;
+   else
+    vol&=0x3FFF;
+
+   //if(vol&0x4000)                                      // -> mmm... phase inverted? have to investigate this
+   // vol=0-(0x3fff-(vol&0x3fff));
+   //else
+   // vol&=0x3fff;
+  }
+ if(right)
+  s_chan[ch].iRightVolume=vol;
+ else
+  s_chan[ch].iLeftVolume=vol;                           // store volume
+}
+
+////////////////////////////////////////////////////////////////////////
+// PITCH register write
+////////////////////////////////////////////////////////////////////////
+
+static void SetPitch(int ch,u16 val)               // SET PITCH
+{
+ int NP;
+ if(val>0x3fff) NP=0x3fff;                             // get pitch val
+ else           NP=val;
+
+ s_chan[ch].iRawPitch=NP;
+
+ NP=(44100L*NP)/4096L;                                 // calc frequency
+ if(NP<1) NP=1;                                        // some security
+ s_chan[ch].iActFreq=NP;                               // store frequency
+}
diff --git a/src/psf/peops/reverb.c b/src/psf/peops/reverb.c
deleted file mode 100644
index 681d56c55fbf..000000000000
--- a/src/psf/peops/reverb.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/***************************************************************************
-                          reverb.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2003/03/17 - xodnizel
-// - Implemented Neill's 44.1Khz-22050Hz downsampling data
-//   I also need to check if the ~4 sample delay doesn't screw any sounds
-//   up by making things too out of phase.  It could be fixed easily(elsewhere).
-//
-// 2003/01/19 - Pete
-// - added Neill's reverb (see at the end of file)
-//
-// 2002/12/26 - Pete
-// - adjusted reverb handling
-//
-// 2002/08/14 - Pete
-// - added extra reverb
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#define _IN_REVERB
-
-// will be included from spu.c
-#ifdef _IN_SPU
-
-////////////////////////////////////////////////////////////////////////
-// globals
-////////////////////////////////////////////////////////////////////////
-
-// REVERB info and timing vars...
-
-////////////////////////////////////////////////////////////////////////
-
-static inline s64 g_buffer(int iOff)                          // get_buffer content helper: takes care about wraps
-{
- s16 * p=(s16 *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr;
- while(iOff>0x3FFFF)       iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- return (int)(s16)BFLIP16(*(p+iOff));
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline void s_buffer(int iOff,int iVal)                // set_buffer content helper: takes care about wraps and clipping
-{
- s16 * p=(s16 *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr;
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;
- if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(s16)BFLIP16((s16)iVal);
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline void s_buffer1(int iOff,int iVal)                // set_buffer (+1 sample) content helper: takes care about wraps and clipping
-{
- s16 * p=(s16 *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr+1;
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(s16)BFLIP16((s16)iVal);
-}
-
-static inline void MixREVERBLeftRight(s32 *oleft, s32 *oright, s32 inleft, s32 inright)
-{
-   static s32 downbuf[2][8];
-   static s32 upbuf[2][8];
-   static int dbpos=0,ubpos=0;
-   static s32 downcoeffs[8]={ /* Symmetry is sexy. */
-				1283,5344,10895,15243,
-				15243,10895,5344,1283
-			       };
-   int x;
-
-   if(!rvb.StartAddr)                                  // reverb is off
-    {
-     rvb.iRVBLeft=rvb.iRVBRight=0;
-     return;
-    }
-
-   //if(inleft<-32767 || inleft>32767) printf("%d\n",inleft);
-   //if(inright<-32767 || inright>32767) printf("%d\n",inright);
-   downbuf[0][dbpos]=inleft;
-   downbuf[1][dbpos]=inright;
-   dbpos=(dbpos+1)&7;
-
-   if(dbpos&1)                                          // we work on every second left value: downsample to 22 khz
-    {
-     if(spuCtrl&0x80)                                  // -> reverb on? oki
-      {
-       int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
-       s32 INPUT_SAMPLE_L=0;
-       s32 INPUT_SAMPLE_R=0;
-
-       for(x=0;x<8;x++)
-       {
-        INPUT_SAMPLE_L+=(downbuf[0][(dbpos+x)&7]*downcoeffs[x])>>8; /* Lose insignificant
-							    digits to prevent
-							    overflow(check this) */
-        INPUT_SAMPLE_R+=(downbuf[1][(dbpos+x)&7]*downcoeffs[x])>>8;
-       }
-
-       INPUT_SAMPLE_L>>=(16-8);
-       INPUT_SAMPLE_R>>=(16-8);
-       {
-        const s64 IIR_INPUT_A0 = ((g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
-        const s64 IIR_INPUT_A1 = ((g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
-        const s64 IIR_INPUT_B0 = ((g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
-        const s64 IIR_INPUT_B1 = ((g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
-        const s64 IIR_A0 = ((IIR_INPUT_A0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))>>15);
-        const s64 IIR_A1 = ((IIR_INPUT_A1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))>>15);
-        const s64 IIR_B0 = ((IIR_INPUT_B0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))>>15);
-        const s64 IIR_B1 = ((IIR_INPUT_B1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))>>15);
-
-       s_buffer1(rvb.IIR_DEST_A0, IIR_A0);
-       s_buffer1(rvb.IIR_DEST_A1, IIR_A1);
-       s_buffer1(rvb.IIR_DEST_B0, IIR_B0);
-       s_buffer1(rvb.IIR_DEST_B1, IIR_B1);
-
-       ACC0 = ((g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)>>15) +
-              ((g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)>>15) +
-              ((g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)>>15) +
-              ((g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)>>15);
-       ACC1 = ((g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)>>15) +
-              ((g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)>>15) +
-              ((g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)>>15) +
-              ((g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)>>15);
-
-       FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);
-       FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);
-       FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);
-       FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);
-
-       s_buffer(rvb.MIX_DEST_A0, ACC0 - ((FB_A0 * rvb.FB_ALPHA)>>15));
-       s_buffer(rvb.MIX_DEST_A1, ACC1 - ((FB_A1 * rvb.FB_ALPHA)>>15));
-
-       s_buffer(rvb.MIX_DEST_B0, ((rvb.FB_ALPHA * ACC0)>>15) - ((FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B0 * rvb.FB_X)>>15));
-       s_buffer(rvb.MIX_DEST_B1, ((rvb.FB_ALPHA * ACC1)>>15) - ((FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B1 * rvb.FB_X)>>15));
-
-       rvb.iRVBLeft  = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;
-       rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;
-
-       rvb.iRVBLeft  = ((s64)rvb.iRVBLeft * rvb.VolLeft)  >> 14;
-       rvb.iRVBRight = ((s64)rvb.iRVBRight * rvb.VolRight) >> 14;
-
-       upbuf[0][ubpos]=rvb.iRVBLeft;
-       upbuf[1][ubpos]=rvb.iRVBRight;
-       ubpos=(ubpos+1)&7;
-       } // Bracket hack(et).
-      }
-     else                                              // -> reverb off
-      {
-       rvb.iRVBLeft=rvb.iRVBRight=0;
-       return;
-      }
-     rvb.CurrAddr++;
-     if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
-    }
-    else
-    {
-     upbuf[0][ubpos]=0;
-     upbuf[1][ubpos]=0;
-     ubpos=(ubpos+1)&7;
-    }
-   {
-    s32 retl=0,retr=0;
-    for(x=0;x<8;x++)
-    {
-     retl+=(upbuf[0][(ubpos+x)&7]*downcoeffs[x])>>8;
-     retr+=(upbuf[1][(ubpos+x)&7]*downcoeffs[x])>>8;
-    }
-    retl>>=(16-8-1); /* -1 To adjust for the null padding. */
-    retr>>=(16-8-1);
-
-    *oleft+=retl;
-    *oright+=retr;
-   }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-#endif
-
-/*
------------------------------------------------------------------------------
-PSX reverb hardware notes
-by Neill Corlett
------------------------------------------------------------------------------
-
-Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
-yadda yadda.
-
------------------------------------------------------------------------------
-
-Basics
-------
-
-- The reverb buffer is 22khz 16-bit mono PCM.
-- It starts at the reverb address given by 1DA2, extends to
-  the end of sound RAM, and wraps back to the 1DA2 address.
-
-Setting the address at 1DA2 resets the current reverb work address.
-
-This work address ALWAYS increments every 1/22050 sec., regardless of
-whether reverb is enabled (bit 7 of 1DAA set).
-
-And the contents of the reverb buffer ALWAYS play, scaled by the
-"reverberation depth left/right" volumes (1D84/1D86).
-(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
-
------------------------------------------------------------------------------
-
-Register names
---------------
-
-These are probably not their real names.
-These are probably not even correct names.
-We will use them anyway, because we can.
-
-1DC0: FB_SRC_A       (offset)
-1DC2: FB_SRC_B       (offset)
-1DC4: IIR_ALPHA      (coef.)
-1DC6: ACC_COEF_A     (coef.)
-1DC8: ACC_COEF_B     (coef.)
-1DCA: ACC_COEF_C     (coef.)
-1DCC: ACC_COEF_D     (coef.)
-1DCE: IIR_COEF       (coef.)
-1DD0: FB_ALPHA       (coef.)
-1DD2: FB_X           (coef.)
-1DD4: IIR_DEST_A0    (offset)
-1DD6: IIR_DEST_A1    (offset)
-1DD8: ACC_SRC_A0     (offset)
-1DDA: ACC_SRC_A1     (offset)
-1DDC: ACC_SRC_B0     (offset)
-1DDE: ACC_SRC_B1     (offset)
-1DE0: IIR_SRC_A0     (offset)
-1DE2: IIR_SRC_A1     (offset)
-1DE4: IIR_DEST_B0    (offset)
-1DE6: IIR_DEST_B1    (offset)
-1DE8: ACC_SRC_C0     (offset)
-1DEA: ACC_SRC_C1     (offset)
-1DEC: ACC_SRC_D0     (offset)
-1DEE: ACC_SRC_D1     (offset)
-1DF0: IIR_SRC_B1     (offset)
-1DF2: IIR_SRC_B0     (offset)
-1DF4: MIX_DEST_A0    (offset)
-1DF6: MIX_DEST_A1    (offset)
-1DF8: MIX_DEST_B0    (offset)
-1DFA: MIX_DEST_B1    (offset)
-1DFC: IN_COEF_L      (coef.)
-1DFE: IN_COEF_R      (coef.)
-
-The coefficients are signed fractional values.
--32768 would be -1.0
- 32768 would be  1.0 (if it were possible... the highest is of course 32767)
-
-The offsets are (byte/8) offsets into the reverb buffer.
-i.e. you multiply them by 8, you get byte offsets.
-You can also think of them as (samples/4) offsets.
-They appear to be signed.  They can be negative.
-None of the documented presets make them negative, though.
-
-Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.
-
------------------------------------------------------------------------------
-
-What it does
-------------
-
-We take all reverb sources:
-- regular channels that have the reverb bit on
-- cd and external sources, if their reverb bits are on
-and mix them into one stereo 44100hz signal.
-
-Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting
-algorithm here, but I haven't figured out the hysterically exact specifics.
-I use an 8-tap filter with these coefficients, which are nice but probably
-not the real ones:
-
-0.037828187894
-0.157538631280
-0.321159685278
-0.449322115345
-0.449322115345
-0.321159685278
-0.157538631280
-0.037828187894
-
-So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
-
-* IN MY EMULATION, I divide these by 2 to make it clip less.
-  (and of course the L/R output coefficients are adjusted to compensate)
-  The real thing appears to not do this.
-
-At every 22050hz tick:
-- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
-  steady-state algorithm described below
-- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
-  (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
-  L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
-  R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
-- Advance the current buffer position by 1 sample
-
-The wet out L and R are then upsampled to 44100hz and played at the
-"reverberation depth left/right" (1D84/1D86) volume, independent of the main
-volume.
-
------------------------------------------------------------------------------
-
-Reverb steady-state
--------------------
-
-The reverb steady-state algorithm is fairly clever, and of course by
-"clever" I mean "batshit insane".
-
-buffer[x] is relative to the current buffer position, not the beginning of
-the buffer.  Note that all buffer offsets must wrap around so they're
-contained within the reverb work area.
-
-Clipping is performed at the end... maybe also sooner, but definitely at
-the end.
-
-IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
-IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
-IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
-IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
-
-IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
-IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
-IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
-IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
-
-buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
-buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
-buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
-buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
-
-ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
-       buffer[ACC_SRC_B0] * ACC_COEF_B +
-       buffer[ACC_SRC_C0] * ACC_COEF_C +
-       buffer[ACC_SRC_D0] * ACC_COEF_D;
-ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
-       buffer[ACC_SRC_B1] * ACC_COEF_B +
-       buffer[ACC_SRC_C1] * ACC_COEF_C +
-       buffer[ACC_SRC_D1] * ACC_COEF_D;
-
-FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
-FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
-FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
-FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
-
-buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
-buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
-buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
-buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
-
------------------------------------------------------------------------------
-*/
-
diff --git a/src/psf/peops/reverb.cc b/src/psf/peops/reverb.cc
new file mode 100644
index 000000000000..681d56c55fbf
--- /dev/null
+++ b/src/psf/peops/reverb.cc
@@ -0,0 +1,383 @@
+/***************************************************************************
+                          reverb.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/03/17 - xodnizel
+// - Implemented Neill's 44.1Khz-22050Hz downsampling data
+//   I also need to check if the ~4 sample delay doesn't screw any sounds
+//   up by making things too out of phase.  It could be fixed easily(elsewhere).
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb (see at the end of file)
+//
+// 2002/12/26 - Pete
+// - adjusted reverb handling
+//
+// 2002/08/14 - Pete
+// - added extra reverb
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#define _IN_REVERB
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+// REVERB info and timing vars...
+
+////////////////////////////////////////////////////////////////////////
+
+static inline s64 g_buffer(int iOff)                          // get_buffer content helper: takes care about wraps
+{
+ s16 * p=(s16 *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr;
+ while(iOff>0x3FFFF)       iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ return (int)(s16)BFLIP16(*(p+iOff));
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline void s_buffer(int iOff,int iVal)                // set_buffer content helper: takes care about wraps and clipping
+{
+ s16 * p=(s16 *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr;
+ while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;
+ if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(s16)BFLIP16((s16)iVal);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline void s_buffer1(int iOff,int iVal)                // set_buffer (+1 sample) content helper: takes care about wraps and clipping
+{
+ s16 * p=(s16 *)spuMem;
+ iOff=(iOff*4)+rvb.CurrAddr+1;
+ while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
+ while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(s16)BFLIP16((s16)iVal);
+}
+
+static inline void MixREVERBLeftRight(s32 *oleft, s32 *oright, s32 inleft, s32 inright)
+{
+   static s32 downbuf[2][8];
+   static s32 upbuf[2][8];
+   static int dbpos=0,ubpos=0;
+   static s32 downcoeffs[8]={ /* Symmetry is sexy. */
+				1283,5344,10895,15243,
+				15243,10895,5344,1283
+			       };
+   int x;
+
+   if(!rvb.StartAddr)                                  // reverb is off
+    {
+     rvb.iRVBLeft=rvb.iRVBRight=0;
+     return;
+    }
+
+   //if(inleft<-32767 || inleft>32767) printf("%d\n",inleft);
+   //if(inright<-32767 || inright>32767) printf("%d\n",inright);
+   downbuf[0][dbpos]=inleft;
+   downbuf[1][dbpos]=inright;
+   dbpos=(dbpos+1)&7;
+
+   if(dbpos&1)                                          // we work on every second left value: downsample to 22 khz
+    {
+     if(spuCtrl&0x80)                                  // -> reverb on? oki
+      {
+       int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
+       s32 INPUT_SAMPLE_L=0;
+       s32 INPUT_SAMPLE_R=0;
+
+       for(x=0;x<8;x++)
+       {
+        INPUT_SAMPLE_L+=(downbuf[0][(dbpos+x)&7]*downcoeffs[x])>>8; /* Lose insignificant
+							    digits to prevent
+							    overflow(check this) */
+        INPUT_SAMPLE_R+=(downbuf[1][(dbpos+x)&7]*downcoeffs[x])>>8;
+       }
+
+       INPUT_SAMPLE_L>>=(16-8);
+       INPUT_SAMPLE_R>>=(16-8);
+       {
+        const s64 IIR_INPUT_A0 = ((g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
+        const s64 IIR_INPUT_A1 = ((g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
+        const s64 IIR_INPUT_B0 = ((g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
+        const s64 IIR_INPUT_B1 = ((g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
+        const s64 IIR_A0 = ((IIR_INPUT_A0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))>>15);
+        const s64 IIR_A1 = ((IIR_INPUT_A1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))>>15);
+        const s64 IIR_B0 = ((IIR_INPUT_B0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))>>15);
+        const s64 IIR_B1 = ((IIR_INPUT_B1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))>>15);
+
+       s_buffer1(rvb.IIR_DEST_A0, IIR_A0);
+       s_buffer1(rvb.IIR_DEST_A1, IIR_A1);
+       s_buffer1(rvb.IIR_DEST_B0, IIR_B0);
+       s_buffer1(rvb.IIR_DEST_B1, IIR_B1);
+
+       ACC0 = ((g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)>>15) +
+              ((g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)>>15) +
+              ((g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)>>15) +
+              ((g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)>>15);
+       ACC1 = ((g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)>>15) +
+              ((g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)>>15) +
+              ((g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)>>15) +
+              ((g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)>>15);
+
+       FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);
+       FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);
+       FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);
+       FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);
+
+       s_buffer(rvb.MIX_DEST_A0, ACC0 - ((FB_A0 * rvb.FB_ALPHA)>>15));
+       s_buffer(rvb.MIX_DEST_A1, ACC1 - ((FB_A1 * rvb.FB_ALPHA)>>15));
+
+       s_buffer(rvb.MIX_DEST_B0, ((rvb.FB_ALPHA * ACC0)>>15) - ((FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B0 * rvb.FB_X)>>15));
+       s_buffer(rvb.MIX_DEST_B1, ((rvb.FB_ALPHA * ACC1)>>15) - ((FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B1 * rvb.FB_X)>>15));
+
+       rvb.iRVBLeft  = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;
+       rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;
+
+       rvb.iRVBLeft  = ((s64)rvb.iRVBLeft * rvb.VolLeft)  >> 14;
+       rvb.iRVBRight = ((s64)rvb.iRVBRight * rvb.VolRight) >> 14;
+
+       upbuf[0][ubpos]=rvb.iRVBLeft;
+       upbuf[1][ubpos]=rvb.iRVBRight;
+       ubpos=(ubpos+1)&7;
+       } // Bracket hack(et).
+      }
+     else                                              // -> reverb off
+      {
+       rvb.iRVBLeft=rvb.iRVBRight=0;
+       return;
+      }
+     rvb.CurrAddr++;
+     if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
+    }
+    else
+    {
+     upbuf[0][ubpos]=0;
+     upbuf[1][ubpos]=0;
+     ubpos=(ubpos+1)&7;
+    }
+   {
+    s32 retl=0,retr=0;
+    for(x=0;x<8;x++)
+    {
+     retl+=(upbuf[0][(ubpos+x)&7]*downcoeffs[x])>>8;
+     retr+=(upbuf[1][(ubpos+x)&7]*downcoeffs[x])>>8;
+    }
+    retl>>=(16-8-1); /* -1 To adjust for the null padding. */
+    retr>>=(16-8-1);
+
+    *oleft+=retl;
+    *oright+=retr;
+   }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+/*
+-----------------------------------------------------------------------------
+PSX reverb hardware notes
+by Neill Corlett
+-----------------------------------------------------------------------------
+
+Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
+yadda yadda.
+
+-----------------------------------------------------------------------------
+
+Basics
+------
+
+- The reverb buffer is 22khz 16-bit mono PCM.
+- It starts at the reverb address given by 1DA2, extends to
+  the end of sound RAM, and wraps back to the 1DA2 address.
+
+Setting the address at 1DA2 resets the current reverb work address.
+
+This work address ALWAYS increments every 1/22050 sec., regardless of
+whether reverb is enabled (bit 7 of 1DAA set).
+
+And the contents of the reverb buffer ALWAYS play, scaled by the
+"reverberation depth left/right" volumes (1D84/1D86).
+(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
+
+-----------------------------------------------------------------------------
+
+Register names
+--------------
+
+These are probably not their real names.
+These are probably not even correct names.
+We will use them anyway, because we can.
+
+1DC0: FB_SRC_A       (offset)
+1DC2: FB_SRC_B       (offset)
+1DC4: IIR_ALPHA      (coef.)
+1DC6: ACC_COEF_A     (coef.)
+1DC8: ACC_COEF_B     (coef.)
+1DCA: ACC_COEF_C     (coef.)
+1DCC: ACC_COEF_D     (coef.)
+1DCE: IIR_COEF       (coef.)
+1DD0: FB_ALPHA       (coef.)
+1DD2: FB_X           (coef.)
+1DD4: IIR_DEST_A0    (offset)
+1DD6: IIR_DEST_A1    (offset)
+1DD8: ACC_SRC_A0     (offset)
+1DDA: ACC_SRC_A1     (offset)
+1DDC: ACC_SRC_B0     (offset)
+1DDE: ACC_SRC_B1     (offset)
+1DE0: IIR_SRC_A0     (offset)
+1DE2: IIR_SRC_A1     (offset)
+1DE4: IIR_DEST_B0    (offset)
+1DE6: IIR_DEST_B1    (offset)
+1DE8: ACC_SRC_C0     (offset)
+1DEA: ACC_SRC_C1     (offset)
+1DEC: ACC_SRC_D0     (offset)
+1DEE: ACC_SRC_D1     (offset)
+1DF0: IIR_SRC_B1     (offset)
+1DF2: IIR_SRC_B0     (offset)
+1DF4: MIX_DEST_A0    (offset)
+1DF6: MIX_DEST_A1    (offset)
+1DF8: MIX_DEST_B0    (offset)
+1DFA: MIX_DEST_B1    (offset)
+1DFC: IN_COEF_L      (coef.)
+1DFE: IN_COEF_R      (coef.)
+
+The coefficients are signed fractional values.
+-32768 would be -1.0
+ 32768 would be  1.0 (if it were possible... the highest is of course 32767)
+
+The offsets are (byte/8) offsets into the reverb buffer.
+i.e. you multiply them by 8, you get byte offsets.
+You can also think of them as (samples/4) offsets.
+They appear to be signed.  They can be negative.
+None of the documented presets make them negative, though.
+
+Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.
+
+-----------------------------------------------------------------------------
+
+What it does
+------------
+
+We take all reverb sources:
+- regular channels that have the reverb bit on
+- cd and external sources, if their reverb bits are on
+and mix them into one stereo 44100hz signal.
+
+Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting
+algorithm here, but I haven't figured out the hysterically exact specifics.
+I use an 8-tap filter with these coefficients, which are nice but probably
+not the real ones:
+
+0.037828187894
+0.157538631280
+0.321159685278
+0.449322115345
+0.449322115345
+0.321159685278
+0.157538631280
+0.037828187894
+
+So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
+
+* IN MY EMULATION, I divide these by 2 to make it clip less.
+  (and of course the L/R output coefficients are adjusted to compensate)
+  The real thing appears to not do this.
+
+At every 22050hz tick:
+- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
+  steady-state algorithm described below
+- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
+  (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
+  L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
+  R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
+- Advance the current buffer position by 1 sample
+
+The wet out L and R are then upsampled to 44100hz and played at the
+"reverberation depth left/right" (1D84/1D86) volume, independent of the main
+volume.
+
+-----------------------------------------------------------------------------
+
+Reverb steady-state
+-------------------
+
+The reverb steady-state algorithm is fairly clever, and of course by
+"clever" I mean "batshit insane".
+
+buffer[x] is relative to the current buffer position, not the beginning of
+the buffer.  Note that all buffer offsets must wrap around so they're
+contained within the reverb work area.
+
+Clipping is performed at the end... maybe also sooner, but definitely at
+the end.
+
+IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+
+IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
+IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
+IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
+IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
+
+buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
+buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
+buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
+buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
+
+ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
+       buffer[ACC_SRC_B0] * ACC_COEF_B +
+       buffer[ACC_SRC_C0] * ACC_COEF_C +
+       buffer[ACC_SRC_D0] * ACC_COEF_D;
+ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
+       buffer[ACC_SRC_B1] * ACC_COEF_B +
+       buffer[ACC_SRC_C1] * ACC_COEF_C +
+       buffer[ACC_SRC_D1] * ACC_COEF_D;
+
+FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
+FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
+FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
+FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
+
+buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
+buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
+buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
+buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/src/psf/peops/spu.c b/src/psf/peops/spu.c
deleted file mode 100644
index 0d6f7a638771..000000000000
--- a/src/psf/peops/spu.c
+++ /dev/null
@@ -1,673 +0,0 @@
-/***************************************************************************
-                            spu.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2003/03/01 - linuzappz
-// - libraryName changes using ALSA
-//
-// 2003/02/28 - Pete
-// - added option for type of interpolation
-// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile)
-// - added MONO support for MSWindows DirectSound
-//
-// 2003/02/20 - kode54
-// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault
-//
-// 2003/02/19 - kode54
-// - moved SPU IRQ handler and changed sample flag processing
-//
-// 2003/02/18 - kode54
-// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that
-//   ADSR timing is relative to the frequency at which a sample is played... I guess
-//   this remains to be seen, and I don't know whether ADSR is applied to noise channels...
-//
-// 2003/02/09 - kode54
-// - one-shot samples now process the end block before stopping
-// - in light of removing fmod hack, now processing ADSR on frequency channel as well
-//
-// 2003/02/08 - kode54
-// - replaced easy interpolation with gaussian
-// - removed fmod averaging hack
-// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :)
-//
-// 2003/02/08 - linuzappz
-// - small bugfix for one usleep that was 1 instead of 1000
-// - added iDisStereo for no stereo (Linux)
-//
-// 2003/01/22 - Pete
-// - added easy interpolation & small noise adjustments
-//
-// 2003/01/19 - Pete
-// - added Neill's reverb
-//
-// 2003/01/12 - Pete
-// - added recording window handlers
-//
-// 2003/01/06 - Pete
-// - added Neill's ADSR timings
-//
-// 2002/12/28 - Pete
-// - adjusted spu irq handling, fmod handling and loop handling
-//
-// 2002/08/14 - Pete
-// - added extra reverb
-//
-// 2002/06/08 - linuzappz
-// - SPUupdate changed for SPUasync
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#define _IN_SPU
-
-#include "../peops/stdafx.h"
-#include "../peops/externals.h"
-#include "../peops/regs.h"
-#include "../peops/registers.h"
-#include "../peops/spu.h"
-
-// Enable experimental silence skipping
-// Currently it is too aggressive, destroying the rhythm of some songs
-// See http://redmine.audacious-media-player.org/issues/201
-// #define ENABLE_SILENCE_SKIPPING
-
-void SPUirq(void) ;
-
-//#include "PsxMem.h"
-//#include "driver.h"
-
-////////////////////////////////////////////////////////////////////////
-// globals
-////////////////////////////////////////////////////////////////////////
-
-// psx buffer / addresses
-
-static u16  regArea[0x200];
-static u16  spuMem[256*1024];
-static u8 * spuMemC;
-static u8 * pSpuIrq=0;
-static u8 * pSpuBuffer;
-
-// user settings
-static int             iVolume;
-
-// MAIN infos struct for each channel
-
-static SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
-static REVERBInfo      rvb;
-
-static u32   dwNoiseVal=1;                          // global noise generator
-
-static u16  spuCtrl=0;                             // some vars to store psx reg infos
-static u16  spuStat=0;
-static u16  spuIrq=0;
-static u32  spuAddr=0xffffffff;                    // address into spu mem
-static int  bSPUIsOpen=0;
-
-static const int f[5][2] = {
-			{    0,  0  },
-                        {   60,  0  },
-                        {  115, -52 },
-                        {   98, -55 },
-                        {  122, -60 } };
-s16 * pS;
-static s32 ttemp;
-
-extern void psf2_update(unsigned char *samples, long lBytes);
-
-////////////////////////////////////////////////////////////////////////
-// CODE AREA
-////////////////////////////////////////////////////////////////////////
-
-// dirty inline func includes
-
-#include "../peops/reverb.c"
-#include "../peops/adsr.c"
-
-// Try this to increase speed.
-#include "../peops/registers.c"
-#include "../peops/dma.c"
-
-////////////////////////////////////////////////////////////////////////
-// helpers for so-called "gauss interpolation"
-
-#define gval0 (((int *)(&s_chan[ch].SB[29]))[gpos])
-#define gval(x) (((int *)(&s_chan[ch].SB[29]))[(gpos+x)&3])
-
-#include "gauss_i.h"
-
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// START SOUND... called by main thread to setup a new sound on a channel
-////////////////////////////////////////////////////////////////////////
-
-static inline void StartSound(int ch)
-{
- StartADSR(ch);
-
- s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
-
- s_chan[ch].s_1=0;                                     // init mixing vars
- s_chan[ch].s_2=0;
- s_chan[ch].iSBPos=28;
-
- s_chan[ch].bNew=0;                                    // init channel flags
- s_chan[ch].bStop=0;
- s_chan[ch].bOn=1;
-
- s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
- s_chan[ch].SB[30]=0;
-
- s_chan[ch].spos=0x40000L;s_chan[ch].SB[28]=0;  // -> start with more decoding
-}
-
-////////////////////////////////////////////////////////////////////////
-// MAIN SPU FUNCTION
-// here is the main job handler... thread, timer or direct func call
-// basically the whole sound processing is done in this fat func!
-////////////////////////////////////////////////////////////////////////
-
-static u32 sampcount;
-static u32 decaybegin;
-static u32 decayend;
-
-static u32 seektime;
-int psf_seek(u32 t)
-{
- seektime=t*441/10;
- if(seektime>sampcount) return(1);
- return(0);
-}
-
-// Counting to 65536 results in full volume offage.
-void setlength(s32 stop, s32 fade)
-{
- if(stop==~0)
- {
-  decaybegin=~0;
- }
- else
- {
-  stop=(stop*441)/10;
-  fade=(fade*441)/10;
-
-  decaybegin=stop;
-  decayend=stop+fade;
- }
-}
-
-#define CLIP(_x) {if(_x>32767) _x=32767; if(_x<-32767) _x=-32767;}
-int SPUasync(u32 cycles)
-{
- int volmul=iVolume;
- static s32 dosampies;
- s32 temp;
-
- ttemp+=cycles;
- dosampies=ttemp/384;
- if(!dosampies) return(1);
- ttemp-=dosampies*384;
- temp=dosampies;
-
- while(temp)
- {
-   s32 revLeft=0, revRight=0;
-   s32 sl=0, sr=0;
-   int ch,fa;
-
-   temp--;
-   //--------------------------------------------------//
-   //- main channel loop                              -//
-   //--------------------------------------------------//
-    {
-     for(ch=0;ch<MAXCHAN;ch++)                         // loop em all.
-      {
-       if(s_chan[ch].bNew) StartSound(ch);             // start new sound
-       if(!s_chan[ch].bOn) continue;                   // channel not playing? next
-
-
-       if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq)   // new psx frequency?
-        {
-         s_chan[ch].iUsedFreq=s_chan[ch].iActFreq;     // -> take it and calc steps
-         s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
-         if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
-        }
-
-         while(s_chan[ch].spos>=0x10000L)
-          {
-           if(s_chan[ch].iSBPos==28)                   // 28 reached?
-            {
-	     int predict_nr,shift_factor,flags,d,s;
-	     u8* start;unsigned int nSample;
-	     int s_1,s_2;
-
-             start=s_chan[ch].pCurr;                   // set up the current pos
-
-             if (start == (u8*)-1)          // special "stop" sign
-              {
-               s_chan[ch].bOn=0;                       // -> turn everything off
-               s_chan[ch].ADSRX.lVolume=0;
-               s_chan[ch].ADSRX.EnvelopeVol=0;
-               goto ENDX;                              // -> and done for this channel
-              }
-
-             s_chan[ch].iSBPos=0;	// Reset buffer play index.
-
-             //////////////////////////////////////////// spu irq handler here? mmm... do it later
-
-             s_1=s_chan[ch].s_1;
-             s_2=s_chan[ch].s_2;
-
-             predict_nr=(int)*start;start++;
-             shift_factor=predict_nr&0xf;
-             predict_nr >>= 4;
-             flags=(int)*start;start++;
-
-             // -------------------------------------- //
-	     // Decode new samples into s_chan[ch].SB[0 through 27]
-             for (nSample=0;nSample<28;start++)
-              {
-               d=(int)*start;
-               s=((d&0xf)<<12);
-               if(s&0x8000) s|=0xffff0000;
-
-               fa=(s >> shift_factor);
-               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
-               s_2=s_1;s_1=fa;
-               s=((d & 0xf0) << 8);
-
-               s_chan[ch].SB[nSample++]=fa;
-
-               if(s&0x8000) s|=0xffff0000;
-               fa=(s>>shift_factor);
-               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
-               s_2=s_1;s_1=fa;
-
-               s_chan[ch].SB[nSample++]=fa;
-              }
-
-             //////////////////////////////////////////// irq check
-
-             if(spuCtrl&0x40)         			// irq active?
-              {
-               if((pSpuIrq >  start-16 &&              // irq address reached?
-                   pSpuIrq <= start) ||
-                  ((flags&1) &&                        // special: irq on looping addr, when stop/loop flag is set
-                   (pSpuIrq >  s_chan[ch].pLoop-16 &&
-                    pSpuIrq <= s_chan[ch].pLoop)))
-               {
-		 //extern s32 spuirqvoodoo;
-                 s_chan[ch].iIrqDone=1;                // -> debug flag
-		 SPUirq();
-		//puts("IRQ");
-		 //if(spuirqvoodoo!=-1)
-		 //{
-		 // spuirqvoodoo=temp*384;
-		 // temp=0;
-		 //}
-                }
-              }
-
-             //////////////////////////////////////////// flag handler
-
-             if((flags&4) && (!s_chan[ch].bIgnoreLoop))
-              s_chan[ch].pLoop=start-16;               // loop adress
-
-             if(flags&1)                               // 1: stop/loop
-              {
-               // We play this block out first...
-               //if(!(flags&2))                          // 1+2: do loop... otherwise: stop
-               if(flags!=3 || s_chan[ch].pLoop==NULL)  // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
-                {                                      // and checking if pLoop is set avoids crashes, yeah
-                 start = (u8*)-1;
-                }
-               else
-                {
-                 start = s_chan[ch].pLoop;
-                }
-              }
-
-             s_chan[ch].pCurr=start;                   // store values for next cycle
-             s_chan[ch].s_1=s_1;
-             s_chan[ch].s_2=s_2;
-
-             ////////////////////////////////////////////
-            }
-
-           fa=s_chan[ch].SB[s_chan[ch].iSBPos++];      // get sample data
-
-           if((spuCtrl&0x4000)==0) fa=0;               // muted?
-	   else CLIP(fa);
-
-	    {
-	     int gpos;
-             gpos = s_chan[ch].SB[28];
-             gval0 = fa;
-             gpos = (gpos+1) & 3;
-             s_chan[ch].SB[28] = gpos;
-	    }
-           s_chan[ch].spos -= 0x10000L;
-          }
-
-         ////////////////////////////////////////////////
-         // noise handler... just produces some noise data
-         // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
-         // and sometimes the noise will be used as fmod modulation... pfff
-
-         if(s_chan[ch].bNoise)
-          {
-	   //puts("Noise");
-           if((dwNoiseVal<<=1)&0x80000000L)
-            {
-             dwNoiseVal^=0x0040001L;
-             fa=((dwNoiseVal>>2)&0x7fff);
-             fa=-fa;
-            }
-           else fa=(dwNoiseVal>>2)&0x7fff;
-
-           // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
-           fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1));
-           if(fa>32767L)  fa=32767L;
-           if(fa<-32767L) fa=-32767L;
-           s_chan[ch].iOldNoise=fa;
-
-          }                                            //----------------------------------------
-         else                                         // NO NOISE (NORMAL SAMPLE DATA) HERE
-          {
-             int vl, vr, gpos;
-             vl = (s_chan[ch].spos >> 6) & ~3;
-             gpos = s_chan[ch].SB[28];
-             vr=(gauss[vl]*gval0)>>9;
-             vr+=(gauss[vl+1]*gval(1))>>9;
-             vr+=(gauss[vl+2]*gval(2))>>9;
-             vr+=(gauss[vl+3]*gval(3))>>9;
-             fa = vr>>2;
-          }
-
-         s_chan[ch].sval = (MixADSR(ch) * fa)>>10;     // / 1023;  // add adsr
-         if(s_chan[ch].bFMod==2)                       // fmod freq channel
-         {
-           int NP=s_chan[ch+1].iRawPitch;
-           NP=((32768L+s_chan[ch].sval)*NP)>>15; ///32768L;
-
-           if(NP>0x3fff) NP=0x3fff;
-           if(NP<0x1)    NP=0x1;
-
-	   // mmmm... if I do this, all is screwed
-	  //           s_chan[ch+1].iRawPitch=NP;
-
-           NP=(44100L*NP)/(4096L);                     // calc frequency
-
-           s_chan[ch+1].iActFreq=NP;
-           s_chan[ch+1].iUsedFreq=NP;
-           s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
-           if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
-
-		// mmmm... set up freq decoding positions?
-		//           s_chan[ch+1].iSBPos=28;
-		//           s_chan[ch+1].spos=0x10000L;
-          }
-         else
-          {
-           //////////////////////////////////////////////
-           // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
-	   int tmpl,tmpr;
-
-		if (1) //ao_channel_enable[ch+PSF_1]) {
-		{
-			tmpl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14;
-			tmpr=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14;
-		} else {
-			tmpl = 0;
-			tmpr = 0;
-		}
-	   sl+=tmpl;
-	   sr+=tmpr;
-
-	   if(((rvb.Enabled>>ch)&1) && (spuCtrl&0x80))
-	   {
-	    revLeft+=tmpl;
-	    revRight+=tmpr;
-	   }
-          }
-
-         s_chan[ch].spos += s_chan[ch].sinc;
- ENDX:   ;
-      }
-    }
-
-  ///////////////////////////////////////////////////////
-  // mix all channels (including reverb) into one buffer
-  MixREVERBLeftRight(&sl,&sr,revLeft,revRight);
-//  printf("sampcount %d decaybegin %d decayend %d\n", sampcount, decaybegin, decayend);
-  if(sampcount>=decaybegin)
-  {
-   s32 dmul;
-   if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
-		      // for 13 hours?
-   {
-    if(sampcount>=decayend)
-    {
-	    psf2_update(NULL, 0);
-	    return(0);
-    }
-    dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
-    sl=(sl*dmul)>>8;
-    sr=(sr*dmul)>>8;
-   }
-  }
-
-  sampcount++;
-  sl=(sl*volmul)>>8;
-  sr=(sr*volmul)>>8;
-
-  //{
-  // static double asl=0;
-  // static double asr=0;
-
-  // asl+=(sl-asl)/5;
-  // asr+=(sl-asr)/5;
-
-   //sl-=asl;
-   //sr-=asr;
-
-  // if(sl>32767 || sl < -32767) printf("Left: %d, %f\n",sl,asl);
-  // if(sr>32767 || sr < -32767) printf("Right: %d, %f\n",sl,asl);
-  //}
-
-  if(sl>32767) sl=32767; if(sl<-32767) sl=-32767;
-  if(sr>32767) sr=32767; if(sr<-32767) sr=-32767;
-
-  *pS++=sl;
-  *pS++=sr;
- }
-
- if (seektime != 0 && sampcount < seektime)
- {
-   pS=(short *)pSpuBuffer;
- }
- else if ((((unsigned char *)pS)-((unsigned char *)pSpuBuffer)) == (735*4))
- {
-#ifdef ENABLE_SILENCE_SKIPPING
-   short *pSilenceIter = (short *)pSpuBuffer;
-   int iSilenceCount = 0;
-
-   for (; pSilenceIter < pS; pSilenceIter++)
-   {
-      if (*pSilenceIter == 0)
-        iSilenceCount++;
-
-      if (iSilenceCount > 20)
-        break;
-   }
-
-   if (iSilenceCount < 20)
-#endif
-     psf2_update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer);
-
-   pS=(short *)pSpuBuffer;
- }
-
- return(1);
-}
-
-#ifdef TIMEO
-static u64 begintime;
-static u64 gettime64(void)
-{
- struct timeval tv;
- u64 ret;
-
- gettimeofday(&tv,0);
- ret=tv.tv_sec;
- ret*=1000000;
- ret+=tv.tv_usec;
- return(ret);
-}
-#endif
-////////////////////////////////////////////////////////////////////////
-// INIT/EXIT STUFF
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SPUINIT: this func will be called first by the main emu
-////////////////////////////////////////////////////////////////////////
-
-int SPUinit(void)
-{
- spuMemC=(u8*)spuMem;                      // just small setup
- memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
- memset((void *)&rvb,0,sizeof(REVERBInfo));
- memset(regArea,0,sizeof(regArea));
- memset(spuMem,0,sizeof(spuMem));
- InitADSR();
- sampcount=ttemp=0;
- #ifdef TIMEO
- begintime=gettime64();
- #endif
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SETUPSTREAMS: init most of the spu buffers
-////////////////////////////////////////////////////////////////////////
-
-void SetupStreams(void)
-{
- int i;
-
- pSpuBuffer=(u8*)malloc(32768);            // alloc mixing buffer
- pS=(s16 *)pSpuBuffer;
-
- for(i=0;i<MAXCHAN;i++)                                // loop sound channels
-  {
-   s_chan[i].ADSRX.SustainLevel = 1024;                // -> init sustain
-   s_chan[i].iIrqDone=0;
-   s_chan[i].pLoop=spuMemC;
-   s_chan[i].pStart=spuMemC;
-   s_chan[i].pCurr=spuMemC;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// REMOVESTREAMS: free most buffer
-////////////////////////////////////////////////////////////////////////
-
-void RemoveStreams(void)
-{
- free(pSpuBuffer);                                     // free mixing buffer
- pSpuBuffer=NULL;
-
- #ifdef TIMEO
- {
-  u64 tmp;
-  tmp=gettime64();
-  tmp-=begintime;
-  if(tmp)
-   tmp=(u64)sampcount*1000000/tmp;
-  printf("%lld samples per second\n",tmp);
- }
- #endif
-}
-
-
-////////////////////////////////////////////////////////////////////////
-// SPUOPEN: called by main emu after init
-////////////////////////////////////////////////////////////////////////
-
-int SPUopen(void)
-{
- if(bSPUIsOpen) return 0;                              // security for some stupid main emus
- spuIrq=0;
-
- spuStat=spuCtrl=0;
- spuAddr=0xffffffff;
- dwNoiseVal=1;
-
- spuMemC=(u8*)spuMem;
- memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
- pSpuIrq=0;
-
- iVolume=255; //85;
- SetupStreams();                                       // prepare streaming
-
- bSPUIsOpen=1;
-
- return 1;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SPUCLOSE: called before shutdown
-////////////////////////////////////////////////////////////////////////
-
-int SPUclose(void)
-{
- if(!bSPUIsOpen) return 0;                             // some security
-
- bSPUIsOpen=0;                                         // no more open
-
- RemoveStreams();                                      // no more streaming
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SPUSHUTDOWN: called by main emu on final exit
-////////////////////////////////////////////////////////////////////////
-
-int SPUshutdown(void)
-{
- return 0;
-}
-
-void SPUinjectRAMImage(u16 *pIncoming)
-{
-	int i;
-
-	for (i = 0; i < (256*1024); i++)
-	{
-		spuMem[i] = pIncoming[i];
-	}
-}
diff --git a/src/psf/peops/spu.cc b/src/psf/peops/spu.cc
new file mode 100644
index 000000000000..1e79cbc62eae
--- /dev/null
+++ b/src/psf/peops/spu.cc
@@ -0,0 +1,671 @@
+/***************************************************************************
+                            spu.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/03/01 - linuzappz
+// - libraryName changes using ALSA
+//
+// 2003/02/28 - Pete
+// - added option for type of interpolation
+// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile)
+// - added MONO support for MSWindows DirectSound
+//
+// 2003/02/20 - kode54
+// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault
+//
+// 2003/02/19 - kode54
+// - moved SPU IRQ handler and changed sample flag processing
+//
+// 2003/02/18 - kode54
+// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that
+//   ADSR timing is relative to the frequency at which a sample is played... I guess
+//   this remains to be seen, and I don't know whether ADSR is applied to noise channels...
+//
+// 2003/02/09 - kode54
+// - one-shot samples now process the end block before stopping
+// - in light of removing fmod hack, now processing ADSR on frequency channel as well
+//
+// 2003/02/08 - kode54
+// - replaced easy interpolation with gaussian
+// - removed fmod averaging hack
+// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :)
+//
+// 2003/02/08 - linuzappz
+// - small bugfix for one usleep that was 1 instead of 1000
+// - added iDisStereo for no stereo (Linux)
+//
+// 2003/01/22 - Pete
+// - added easy interpolation & small noise adjustments
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb
+//
+// 2003/01/12 - Pete
+// - added recording window handlers
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/12/28 - Pete
+// - adjusted spu irq handling, fmod handling and loop handling
+//
+// 2002/08/14 - Pete
+// - added extra reverb
+//
+// 2002/06/08 - linuzappz
+// - SPUupdate changed for SPUasync
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#define _IN_SPU
+
+#include "../peops/stdafx.h"
+#include "../peops/externals.h"
+#include "../peops/regs.h"
+#include "../peops/registers.h"
+#include "../peops/spu.h"
+
+// Enable experimental silence skipping
+// Currently it is too aggressive, destroying the rhythm of some songs
+// See http://redmine.audacious-media-player.org/issues/201
+// #define ENABLE_SILENCE_SKIPPING
+
+void SPUirq(void) ;
+
+//#include "PsxMem.h"
+//#include "driver.h"
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+// psx buffer / addresses
+
+static u16  regArea[0x200];
+static u16  spuMem[256*1024];
+static u8 * spuMemC;
+static u8 * pSpuIrq=0;
+static u8 * pSpuBuffer;
+
+// user settings
+static int             iVolume;
+
+// MAIN infos struct for each channel
+
+static SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
+static REVERBInfo      rvb;
+
+static u32   dwNoiseVal=1;                          // global noise generator
+
+static u16  spuCtrl=0;                             // some vars to store psx reg infos
+static u16  spuStat=0;
+static u16  spuIrq=0;
+static u32  spuAddr=0xffffffff;                    // address into spu mem
+static int  bSPUIsOpen=0;
+
+static const int f[5][2] = {
+			{    0,  0  },
+                        {   60,  0  },
+                        {  115, -52 },
+                        {   98, -55 },
+                        {  122, -60 } };
+static s16 * pS;
+static s32 ttemp;
+
+////////////////////////////////////////////////////////////////////////
+// CODE AREA
+////////////////////////////////////////////////////////////////////////
+
+// dirty inline func includes
+
+#include "../peops/reverb.cc"
+#include "../peops/adsr.cc"
+
+// Try this to increase speed.
+#include "../peops/registers.cc"
+#include "../peops/dma.cc"
+
+////////////////////////////////////////////////////////////////////////
+// helpers for so-called "gauss interpolation"
+
+#define gval0 (((int *)(&s_chan[ch].SB[29]))[gpos])
+#define gval(x) (((int *)(&s_chan[ch].SB[29]))[(gpos+x)&3])
+
+#include "gauss_i.h"
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// START SOUND... called by main thread to setup a new sound on a channel
+////////////////////////////////////////////////////////////////////////
+
+static inline void StartSound(int ch)
+{
+ StartADSR(ch);
+
+ s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
+
+ s_chan[ch].s_1=0;                                     // init mixing vars
+ s_chan[ch].s_2=0;
+ s_chan[ch].iSBPos=28;
+
+ s_chan[ch].bNew=0;                                    // init channel flags
+ s_chan[ch].bStop=0;
+ s_chan[ch].bOn=1;
+
+ s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
+ s_chan[ch].SB[30]=0;
+
+ s_chan[ch].spos=0x40000L;s_chan[ch].SB[28]=0;  // -> start with more decoding
+}
+
+////////////////////////////////////////////////////////////////////////
+// MAIN SPU FUNCTION
+// here is the main job handler... thread, timer or direct func call
+// basically the whole sound processing is done in this fat func!
+////////////////////////////////////////////////////////////////////////
+
+static u32 sampcount;
+static u32 decaybegin;
+static u32 decayend;
+
+static u32 seektime;
+int psf_seek(u32 t)
+{
+ seektime=t*441/10;
+ if(seektime>sampcount) return(1);
+ return(0);
+}
+
+// Counting to 65536 results in full volume offage.
+void setlength(s32 stop, s32 fade)
+{
+ if(stop==~0)
+ {
+  decaybegin=~0;
+ }
+ else
+ {
+  stop=(stop*441)/10;
+  fade=(fade*441)/10;
+
+  decaybegin=stop;
+  decayend=stop+fade;
+ }
+}
+
+#define CLIP(_x) {if(_x>32767) _x=32767; if(_x<-32767) _x=-32767;}
+int SPUasync(u32 cycles, void (*update)(const void *, int))
+{
+ int volmul=iVolume;
+ static s32 dosampies;
+ s32 temp;
+
+ ttemp+=cycles;
+ dosampies=ttemp/384;
+ if(!dosampies) return(1);
+ ttemp-=dosampies*384;
+ temp=dosampies;
+
+ while(temp)
+ {
+   s32 revLeft=0, revRight=0;
+   s32 sl=0, sr=0;
+   int ch,fa;
+
+   temp--;
+   //--------------------------------------------------//
+   //- main channel loop                              -//
+   //--------------------------------------------------//
+    {
+     for(ch=0;ch<MAXCHAN;ch++)                         // loop em all.
+      {
+       if(s_chan[ch].bNew) StartSound(ch);             // start new sound
+       if(!s_chan[ch].bOn) continue;                   // channel not playing? next
+
+
+       if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq)   // new psx frequency?
+        {
+         s_chan[ch].iUsedFreq=s_chan[ch].iActFreq;     // -> take it and calc steps
+         s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
+         if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
+        }
+
+         while(s_chan[ch].spos>=0x10000L)
+          {
+           if(s_chan[ch].iSBPos==28)                   // 28 reached?
+            {
+	     int predict_nr,shift_factor,flags,d,s;
+	     u8* start;unsigned int nSample;
+	     int s_1,s_2;
+
+             start=s_chan[ch].pCurr;                   // set up the current pos
+
+             if (start == (u8*)-1)          // special "stop" sign
+              {
+               s_chan[ch].bOn=0;                       // -> turn everything off
+               s_chan[ch].ADSRX.lVolume=0;
+               s_chan[ch].ADSRX.EnvelopeVol=0;
+               goto ENDX;                              // -> and done for this channel
+              }
+
+             s_chan[ch].iSBPos=0;	// Reset buffer play index.
+
+             //////////////////////////////////////////// spu irq handler here? mmm... do it later
+
+             s_1=s_chan[ch].s_1;
+             s_2=s_chan[ch].s_2;
+
+             predict_nr=(int)*start;start++;
+             shift_factor=predict_nr&0xf;
+             predict_nr >>= 4;
+             flags=(int)*start;start++;
+
+             // -------------------------------------- //
+	     // Decode new samples into s_chan[ch].SB[0 through 27]
+             for (nSample=0;nSample<28;start++)
+              {
+               d=(int)*start;
+               s=((d&0xf)<<12);
+               if(s&0x8000) s|=0xffff0000;
+
+               fa=(s >> shift_factor);
+               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
+               s_2=s_1;s_1=fa;
+               s=((d & 0xf0) << 8);
+
+               s_chan[ch].SB[nSample++]=fa;
+
+               if(s&0x8000) s|=0xffff0000;
+               fa=(s>>shift_factor);
+               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
+               s_2=s_1;s_1=fa;
+
+               s_chan[ch].SB[nSample++]=fa;
+              }
+
+             //////////////////////////////////////////// irq check
+
+             if(spuCtrl&0x40)         			// irq active?
+              {
+               if((pSpuIrq >  start-16 &&              // irq address reached?
+                   pSpuIrq <= start) ||
+                  ((flags&1) &&                        // special: irq on looping addr, when stop/loop flag is set
+                   (pSpuIrq >  s_chan[ch].pLoop-16 &&
+                    pSpuIrq <= s_chan[ch].pLoop)))
+               {
+		 //extern s32 spuirqvoodoo;
+                 s_chan[ch].iIrqDone=1;                // -> debug flag
+		 SPUirq();
+		//puts("IRQ");
+		 //if(spuirqvoodoo!=-1)
+		 //{
+		 // spuirqvoodoo=temp*384;
+		 // temp=0;
+		 //}
+                }
+              }
+
+             //////////////////////////////////////////// flag handler
+
+             if((flags&4) && (!s_chan[ch].bIgnoreLoop))
+              s_chan[ch].pLoop=start-16;               // loop adress
+
+             if(flags&1)                               // 1: stop/loop
+              {
+               // We play this block out first...
+               //if(!(flags&2))                          // 1+2: do loop... otherwise: stop
+               if(flags!=3 || s_chan[ch].pLoop==nullptr)  // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
+                {                                      // and checking if pLoop is set avoids crashes, yeah
+                 start = (u8*)-1;
+                }
+               else
+                {
+                 start = s_chan[ch].pLoop;
+                }
+              }
+
+             s_chan[ch].pCurr=start;                   // store values for next cycle
+             s_chan[ch].s_1=s_1;
+             s_chan[ch].s_2=s_2;
+
+             ////////////////////////////////////////////
+            }
+
+           fa=s_chan[ch].SB[s_chan[ch].iSBPos++];      // get sample data
+
+           if((spuCtrl&0x4000)==0) fa=0;               // muted?
+	   else CLIP(fa);
+
+	    {
+	     int gpos;
+             gpos = s_chan[ch].SB[28];
+             gval0 = fa;
+             gpos = (gpos+1) & 3;
+             s_chan[ch].SB[28] = gpos;
+	    }
+           s_chan[ch].spos -= 0x10000L;
+          }
+
+         ////////////////////////////////////////////////
+         // noise handler... just produces some noise data
+         // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
+         // and sometimes the noise will be used as fmod modulation... pfff
+
+         if(s_chan[ch].bNoise)
+          {
+	   //puts("Noise");
+           if((dwNoiseVal<<=1)&0x80000000L)
+            {
+             dwNoiseVal^=0x0040001L;
+             fa=((dwNoiseVal>>2)&0x7fff);
+             fa=-fa;
+            }
+           else fa=(dwNoiseVal>>2)&0x7fff;
+
+           // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
+           fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1));
+           if(fa>32767L)  fa=32767L;
+           if(fa<-32767L) fa=-32767L;
+           s_chan[ch].iOldNoise=fa;
+
+          }                                            //----------------------------------------
+         else                                         // NO NOISE (NORMAL SAMPLE DATA) HERE
+          {
+             int vl, vr, gpos;
+             vl = (s_chan[ch].spos >> 6) & ~3;
+             gpos = s_chan[ch].SB[28];
+             vr=(gauss[vl]*gval0)>>9;
+             vr+=(gauss[vl+1]*gval(1))>>9;
+             vr+=(gauss[vl+2]*gval(2))>>9;
+             vr+=(gauss[vl+3]*gval(3))>>9;
+             fa = vr>>2;
+          }
+
+         s_chan[ch].sval = (MixADSR(ch) * fa)>>10;     // / 1023;  // add adsr
+         if(s_chan[ch].bFMod==2)                       // fmod freq channel
+         {
+           int NP=s_chan[ch+1].iRawPitch;
+           NP=((32768L+s_chan[ch].sval)*NP)>>15; ///32768L;
+
+           if(NP>0x3fff) NP=0x3fff;
+           if(NP<0x1)    NP=0x1;
+
+	   // mmmm... if I do this, all is screwed
+	  //           s_chan[ch+1].iRawPitch=NP;
+
+           NP=(44100L*NP)/(4096L);                     // calc frequency
+
+           s_chan[ch+1].iActFreq=NP;
+           s_chan[ch+1].iUsedFreq=NP;
+           s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
+           if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
+
+		// mmmm... set up freq decoding positions?
+		//           s_chan[ch+1].iSBPos=28;
+		//           s_chan[ch+1].spos=0x10000L;
+          }
+         else
+          {
+           //////////////////////////////////////////////
+           // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
+	   int tmpl,tmpr;
+
+		if (1) //ao_channel_enable[ch+PSF_1]) {
+		{
+			tmpl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14;
+			tmpr=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14;
+		} else {
+			tmpl = 0;
+			tmpr = 0;
+		}
+	   sl+=tmpl;
+	   sr+=tmpr;
+
+	   if(((rvb.Enabled>>ch)&1) && (spuCtrl&0x80))
+	   {
+	    revLeft+=tmpl;
+	    revRight+=tmpr;
+	   }
+          }
+
+         s_chan[ch].spos += s_chan[ch].sinc;
+ ENDX:   ;
+      }
+    }
+
+  ///////////////////////////////////////////////////////
+  // mix all channels (including reverb) into one buffer
+  MixREVERBLeftRight(&sl,&sr,revLeft,revRight);
+//  printf("sampcount %d decaybegin %d decayend %d\n", sampcount, decaybegin, decayend);
+  if(sampcount>=decaybegin)
+  {
+   s32 dmul;
+   if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
+		      // for 13 hours?
+   {
+    if(sampcount>=decayend)
+    {
+      update(nullptr, 0);
+      return(0);
+    }
+    dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
+    sl=(sl*dmul)>>8;
+    sr=(sr*dmul)>>8;
+   }
+  }
+
+  sampcount++;
+  sl=(sl*volmul)>>8;
+  sr=(sr*volmul)>>8;
+
+  //{
+  // static double asl=0;
+  // static double asr=0;
+
+  // asl+=(sl-asl)/5;
+  // asr+=(sl-asr)/5;
+
+   //sl-=asl;
+   //sr-=asr;
+
+  // if(sl>32767 || sl < -32767) printf("Left: %d, %f\n",sl,asl);
+  // if(sr>32767 || sr < -32767) printf("Right: %d, %f\n",sl,asl);
+  //}
+
+  if(sl>32767) sl=32767; if(sl<-32767) sl=-32767;
+  if(sr>32767) sr=32767; if(sr<-32767) sr=-32767;
+
+  *pS++=sl;
+  *pS++=sr;
+ }
+
+ if (seektime != 0 && sampcount < seektime)
+ {
+   pS=(short *)pSpuBuffer;
+ }
+ else if ((((unsigned char *)pS)-((unsigned char *)pSpuBuffer)) == (735*4))
+ {
+#ifdef ENABLE_SILENCE_SKIPPING
+   short *pSilenceIter = (short *)pSpuBuffer;
+   int iSilenceCount = 0;
+
+   for (; pSilenceIter < pS; pSilenceIter++)
+   {
+      if (*pSilenceIter == 0)
+        iSilenceCount++;
+
+      if (iSilenceCount > 20)
+        break;
+   }
+
+   if (iSilenceCount < 20)
+#endif
+     update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer);
+
+   pS=(short *)pSpuBuffer;
+ }
+
+ return(1);
+}
+
+#ifdef TIMEO
+static u64 begintime;
+static u64 gettime64(void)
+{
+ struct timeval tv;
+ u64 ret;
+
+ gettimeofday(&tv,0);
+ ret=tv.tv_sec;
+ ret*=1000000;
+ ret+=tv.tv_usec;
+ return(ret);
+}
+#endif
+////////////////////////////////////////////////////////////////////////
+// INIT/EXIT STUFF
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// SPUINIT: this func will be called first by the main emu
+////////////////////////////////////////////////////////////////////////
+
+int SPUinit(void)
+{
+ spuMemC=(u8*)spuMem;                      // just small setup
+ memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
+ memset((void *)&rvb,0,sizeof(REVERBInfo));
+ memset(regArea,0,sizeof(regArea));
+ memset(spuMem,0,sizeof(spuMem));
+ InitADSR();
+ sampcount=ttemp=0;
+ #ifdef TIMEO
+ begintime=gettime64();
+ #endif
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SETUPSTREAMS: init most of the spu buffers
+////////////////////////////////////////////////////////////////////////
+
+void SetupStreams(void)
+{
+ int i;
+
+ pSpuBuffer=(u8*)malloc(32768);            // alloc mixing buffer
+ pS=(s16 *)pSpuBuffer;
+
+ for(i=0;i<MAXCHAN;i++)                                // loop sound channels
+  {
+   s_chan[i].ADSRX.SustainLevel = 1024;                // -> init sustain
+   s_chan[i].iIrqDone=0;
+   s_chan[i].pLoop=spuMemC;
+   s_chan[i].pStart=spuMemC;
+   s_chan[i].pCurr=spuMemC;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// REMOVESTREAMS: free most buffer
+////////////////////////////////////////////////////////////////////////
+
+void RemoveStreams(void)
+{
+ free(pSpuBuffer);                                     // free mixing buffer
+ pSpuBuffer=nullptr;
+
+ #ifdef TIMEO
+ {
+  u64 tmp;
+  tmp=gettime64();
+  tmp-=begintime;
+  if(tmp)
+   tmp=(u64)sampcount*1000000/tmp;
+  printf("%lld samples per second\n",tmp);
+ }
+ #endif
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// SPUOPEN: called by main emu after init
+////////////////////////////////////////////////////////////////////////
+
+int SPUopen(void)
+{
+ if(bSPUIsOpen) return 0;                              // security for some stupid main emus
+ spuIrq=0;
+
+ spuStat=spuCtrl=0;
+ spuAddr=0xffffffff;
+ dwNoiseVal=1;
+
+ spuMemC=(u8*)spuMem;
+ memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
+ pSpuIrq=0;
+
+ iVolume=255; //85;
+ SetupStreams();                                       // prepare streaming
+
+ bSPUIsOpen=1;
+
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// SPUCLOSE: called before shutdown
+////////////////////////////////////////////////////////////////////////
+
+int SPUclose(void)
+{
+ if(!bSPUIsOpen) return 0;                             // some security
+
+ bSPUIsOpen=0;                                         // no more open
+
+ RemoveStreams();                                      // no more streaming
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SPUSHUTDOWN: called by main emu on final exit
+////////////////////////////////////////////////////////////////////////
+
+int SPUshutdown(void)
+{
+ return 0;
+}
+
+void SPUinjectRAMImage(u16 *pIncoming)
+{
+	int i;
+
+	for (i = 0; i < (256*1024); i++)
+	{
+		spuMem[i] = pIncoming[i];
+	}
+}
diff --git a/src/psf/peops/spu.h b/src/psf/peops/spu.h
index 3c2cee4143e3..647a7780495f 100644
--- a/src/psf/peops/spu.h
+++ b/src/psf/peops/spu.h
@@ -26,7 +26,7 @@
 
 void sexyd_update(unsigned char* pSound,long lBytes);
 
-int SPUasync(u32 cycles);
+int SPUasync(u32 cycles, void (*update)(const void *, int));
 void SPU_flushboot(void);
 int SPUinit(void);
 int SPUopen(void);
diff --git a/src/psf/peops2/License.txt b/src/psf/peops2/License.txt
index e51338c2caa9..e1e8495a4f3c 100644
--- a/src/psf/peops2/License.txt
+++ b/src/psf/peops2/License.txt
@@ -4,7 +4,8 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                          675 Mass Ave, Cambridge, MA 02139, USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
diff --git a/src/psf/peops2/adsr.c b/src/psf/peops2/adsr.c
deleted file mode 100644
index 57547ffefdc8..000000000000
--- a/src/psf/peops2/adsr.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/***************************************************************************
-                          adsr.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2003/05/14 - xodnizel
-// - removed stopping of reverb on sample end
-//
-// 2003/01/06 - Pete
-// - added Neill's ADSR timings
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_ADSR
-
-// will be included from spu.c
-#ifdef _IN_SPU
-
-////////////////////////////////////////////////////////////////////////
-// ADSR func
-////////////////////////////////////////////////////////////////////////
-
-unsigned long RateTable[160];
-
-void InitADSR(void)                                    // INIT ADSR
-{
- unsigned long r,rs,rd;int i;
-
- memset(RateTable,0,sizeof(unsigned long)*160);        // build the rate table according to Neill's rules (see at bottom of file)
-
- r=3;rs=1;rd=0;
-
- for(i=32;i<160;i++)                                   // we start at pos 32 with the real values... everything before is 0
-  {
-   if(r<0x3FFFFFFF)
-    {
-     r+=rs;
-     rd++;if(rd==5) {rd=1;rs*=2;}
-    }
-   if(r>0x3FFFFFFF) r=0x3FFFFFFF;
-
-   RateTable[i]=r;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void StartADSR(int ch)                          // MIX ADSR
-{
- s_chan[ch].ADSRX.lVolume=1;                           // and init some adsr vars
- s_chan[ch].ADSRX.State=0;
- s_chan[ch].ADSRX.EnvelopeVol=0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-int MixADSR(int ch)                             // MIX ADSR
-{
- if(s_chan[ch].bStop)                                  // should be stopped:
-  {                                                    // do release
-   if(s_chan[ch].ADSRX.ReleaseModeExp)
-    {
-     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
-      {
-       case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
-       case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
-       case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
-       case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
-       case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
-       case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
-       case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
-       case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
-      }
-    }
-   else
-    {
-     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
-    }
-
-   if(s_chan[ch].ADSRX.EnvelopeVol<0)
-    {
-     s_chan[ch].ADSRX.EnvelopeVol=0;
-     s_chan[ch].bOn=0;
-     //s_chan[ch].bReverb=0;
-     //s_chan[ch].bNoise=0;
-    }
-
-   s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-   return s_chan[ch].ADSRX.lVolume;
-  }
- else                                                  // not stopped yet?
-  {
-   if(s_chan[ch].ADSRX.State==0)                       // -> attack
-    {
-     if(s_chan[ch].ADSRX.AttackModeExp)
-      {
-       if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
-        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
-       else
-        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
-      }
-     else
-      {
-       s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
-      }
-
-     if(s_chan[ch].ADSRX.EnvelopeVol<0)
-      {
-       s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
-       s_chan[ch].ADSRX.State=1;
-      }
-
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-   //--------------------------------------------------//
-   if(s_chan[ch].ADSRX.State==1)                       // -> decay
-    {
-     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
-      {
-       case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
-       case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
-       case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
-       case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
-       case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
-       case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
-       case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
-       case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
-      }
-
-     if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
-     if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
-      {
-       s_chan[ch].ADSRX.State=2;
-      }
-
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-   //--------------------------------------------------//
-   if(s_chan[ch].ADSRX.State==2)                       // -> sustain
-    {
-     if(s_chan[ch].ADSRX.SustainIncrease)
-      {
-       if(s_chan[ch].ADSRX.SustainModeExp)
-        {
-         if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
-          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
-         else
-          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
-        }
-       else
-        {
-         s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
-        }
-
-       if(s_chan[ch].ADSRX.EnvelopeVol<0)
-        {
-         s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
-        }
-      }
-     else
-      {
-       if(s_chan[ch].ADSRX.SustainModeExp)
-        {
-         switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
-          {
-           case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
-           case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
-           case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
-           case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
-           case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
-           case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
-           case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
-           case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
-          }
-        }
-       else
-        {
-         s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
-        }
-
-       if(s_chan[ch].ADSRX.EnvelopeVol<0)
-        {
-         s_chan[ch].ADSRX.EnvelopeVol=0;
-        }
-      }
-     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
-     return s_chan[ch].ADSRX.lVolume;
-    }
-  }
- return 0;
-}
-
-#endif
-
-/*
-James Higgs ADSR investigations:
-
-PSX SPU Envelope Timings
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-First, here is an extract from doomed's SPU doc, which explains the basics
-of the SPU "volume envelope":
-
-*** doomed doc extract start ***
-
---------------------------------------------------------------------------
-Voices.
---------------------------------------------------------------------------
-The SPU has 24 hardware voices. These voices can be used to reproduce sample
-data, noise or can be used as frequency modulator on the next voice.
-Each voice has it's own programmable ADSR envelope filter. The main volume
-can be programmed independently for left and right output.
-
-The ADSR envelope filter works as follows:
-Ar = Attack rate, which specifies the speed at which the volume increases
-     from zero to it's maximum value, as soon as the note on is given. The
-     slope can be set to lineair or exponential.
-Dr = Decay rate specifies the speed at which the volume decreases to the
-     sustain level. Decay is always decreasing exponentially.
-Sl = Sustain level, base level from which sustain starts.
-Sr = Sustain rate is the rate at which the volume of the sustained note
-     increases or decreases. This can be either lineair or exponential.
-Rr = Release rate is the rate at which the volume of the note decreases
-     as soon as the note off is given.
-
-     lvl |
-       ^ |     /\Dr     __
-     Sl _| _  / _ \__---  \
-         |   /       ---__ \ Rr
-         |  /Ar       Sr  \ \
-         | /                \\
-         |/___________________\________
-                                  ->time
-
-The overal volume can also be set to sweep up or down lineairly or
-exponentially from it's current value. This can be done seperately
-for left and right.
-
-Relevant SPU registers:
--------------------------------------------------------------
-$1f801xx8         Attack/Decay/Sustain level
-bit  |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
-desc.|Am|         Ar         |Dr         |Sl         |
-
-Am       0        Attack mode Linear
-         1                    Exponential
-
-Ar       0-7f     attack rate
-Dr       0-f      decay rate
-Sl       0-f      sustain level
--------------------------------------------------------------
-$1f801xxa         Sustain rate, Release Rate.
-bit  |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
-desc.|Sm|Sd| 0|   Sr               |Rm|Rr            |
-
-Sm       0        sustain rate mode linear
-         1                          exponential
-Sd       0        sustain rate mode increase
-         1                          decrease
-Sr       0-7f     Sustain Rate
-Rm       0        Linear decrease
-         1        Exponential decrease
-Rr       0-1f     Release Rate
-
-Note: decay mode is always Expontial decrease, and thus cannot
-be set.
--------------------------------------------------------------
-$1f801xxc         Current ADSR volume
-bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
-desc.|ADSRvol                                        |
-
-ADSRvol           Returns the current envelope volume when
-                  read.
--- James' Note: return range: 0 -> 32767
-
-*** doomed doc extract end ***
-
-By using a small PSX proggie to visualise the envelope as it was played,
-the following results for envelope timing were obtained:
-
-1. Attack rate value (linear mode)
-
-   Attack value range: 0 -> 127
-
-   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |    | 80 |
-   -----------------------------------------------------------------
-   Frames | 11 | 21 | 42 | 84 | 169| 338| 676|    |2890|
-
-   Note: frames is no. of PAL frames to reach full volume (100%
-   amplitude)
-
-   Hmm, noticing that the time taken to reach full volume doubles
-   every time we add 4 to our attack value, we know the equation is
-   of form:
-             frames = k * 2 ^ (value / 4)
-
-   (You may ponder about envelope generator hardware at this point,
-   or maybe not... :)
-
-   By substituting some stuff and running some checks, we get:
-
-       k = 0.00257              (close enuf)
-
-   therefore,
-             frames = 0.00257 * 2 ^ (value / 4)
-   If you just happen to be writing an emulator, then you can probably
-   use an equation like:
-
-       %volume_increase_per_tick = 1 / frames
-
-
-   ------------------------------------
-   Pete:
-   ms=((1<<(value>>2))*514)/10000
-   ------------------------------------
-
-2. Decay rate value (only has log mode)
-
-   Decay value range: 0 -> 15
-
-   Value  |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
-   ------------------------------------------------
-   frames |    |    |    |    |  6 | 12 | 24 | 47 |
-
-   Note: frames here is no. of PAL frames to decay to 50% volume.
-
-   formula: frames = k * 2 ^ (value)
-
-   Substituting, we get: k = 0.00146
-
-   Further info on logarithmic nature:
-   frames to decay to sustain level 3  =  3 * frames to decay to
-   sustain level 9
-
-   Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
-   50% volume.
-
-   Frag it - just use linear approx.
-
-   ------------------------------------
-   Pete:
-   ms=((1<<value)*292)/10000
-   ------------------------------------
-
-
-3. Sustain rate value (linear mode)
-
-   Sustain rate range: 0 -> 127
-
-   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
-   -------------------------------------------
-   frames |  9 | 19 | 37 | 74 | 147| 293| 587|
-
-   Here, frames = no. of PAL frames for volume amplitude to go from 100%
-   to 0% (or vice-versa).
-
-   Same formula as for attack value, just a different value for k:
-
-   k = 0.00225
-
-   ie: frames = 0.00225 * 2 ^ (value / 4)
-
-   For emulation purposes:
-
-   %volume_increase_or_decrease_per_tick = 1 / frames
-
-   ------------------------------------
-   Pete:
-   ms=((1<<(value>>2))*450)/10000
-   ------------------------------------
-
-
-4. Release rate (linear mode)
-
-   Release rate range: 0 -> 31
-
-   Value  | 13 | 14 | 15 | 16 | 17 |
-   ---------------------------------------------------------------
-   frames | 18 | 36 | 73 | 146| 292|
-
-   Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
-   after "note-off" is triggered.
-
-   Formula: frames = k * 2 ^ (value)
-
-   And so: k = 0.00223
-
-   ------------------------------------
-   Pete:
-   ms=((1<<value)*446)/10000
-   ------------------------------------
-
-
-Other notes:
-
-Log stuff not figured out. You may get some clues from the "Decay rate"
-stuff above. For emu purposes it may not be important - use linear
-approx.
-
-To get timings in millisecs, multiply frames by 20.
-
-
-
-- James Higgs 17/6/2000
-james7780 at yahoo.com
-
-//---------------------------------------------------------------
-
-OLD adsr mixing according to james' rules... has to be called
-every one millisecond
-
-
- long v,v2,lT,l1,l2,l3;
-
- if(s_chan[ch].bStop)                                  // psx wants to stop? -> release phase
-  {
-   if(s_chan[ch].ADSR.ReleaseVal!=0)                   // -> release not 0: do release (if 0: stop right now)
-    {
-     if(!s_chan[ch].ADSR.ReleaseVol)                   // --> release just started? set up the release stuff
-      {
-       s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
-       s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
-       s_chan[ch].ADSR.ReleaseTime =                   // --> calc how long does it take to reach the wanted sus level
-         (s_chan[ch].ADSR.ReleaseTime*
-          s_chan[ch].ADSR.ReleaseVol)/1024;
-      }
-                                                       // -> NO release exp mode used (yet)
-     v=s_chan[ch].ADSR.ReleaseVol;                     // -> get last volume
-     lT=s_chan[ch].ADSR.lTime-                         // -> how much time is past?
-        s_chan[ch].ADSR.ReleaseStartTime;
-     l1=s_chan[ch].ADSR.ReleaseTime;
-
-     if(lT<l1)                                         // -> we still have to release
-      {
-       v=v-((v*lT)/l1);                                // --> calc new volume
-      }
-     else                                              // -> release is over: now really stop that sample
-      {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
-    }
-   else                                                // -> release IS 0: release at once
-    {
-     v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
-    }
-  }
- else
-  {//--------------------------------------------------// not in release phase:
-   v=1024;
-   lT=s_chan[ch].ADSR.lTime;
-   l1=s_chan[ch].ADSR.AttackTime;
-
-   if(lT<l1)                                           // attack
-    {                                                  // no exp mode used (yet)
-//     if(s_chan[ch].ADSR.AttackModeExp)
-//      {
-//       v=(v*lT)/l1;
-//      }
-//     else
-      {
-       v=(v*lT)/l1;
-      }
-     if(v==0) v=1;
-    }
-   else                                                // decay
-    {                                                  // should be exp, but who cares? ;)
-     l2=s_chan[ch].ADSR.DecayTime;
-     v2=s_chan[ch].ADSR.SustainLevel;
-
-     lT-=l1;
-     if(lT<l2)
-      {
-       v-=(((v-v2)*lT)/l2);
-      }
-     else                                              // sustain
-      {                                                // no exp mode used (yet)
-       l3=s_chan[ch].ADSR.SustainTime;
-       lT-=l2;
-       if(s_chan[ch].ADSR.SustainModeDec>0)
-        {
-         if(l3!=0) v2+=((v-v2)*lT)/l3;
-         else      v2=v;
-        }
-       else
-        {
-         if(l3!=0) v2-=(v2*lT)/l3;
-         else      v2=v;
-        }
-
-       if(v2>v)  v2=v;
-       if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
-
-       v=v2;
-      }
-    }
-  }
-
- //----------------------------------------------------//
- // ok, done for this channel, so increase time
-
- s_chan[ch].ADSR.lTime+=1;                             // 1 = 1.020408f ms;
-
- if(v>1024)     v=1024;                                // adjust volume
- if(v<0)        v=0;
- s_chan[ch].ADSR.lVolume=v;                            // store act volume
-
- return v;                                             // return the volume factor
-*/
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-
-/*
------------------------------------------------------------------------------
-Neill Corlett
-Playstation SPU envelope timing notes
------------------------------------------------------------------------------
-
-This is preliminary.  This may be wrong.  But the model described herein fits
-all of my experimental data, and it's just simple enough to sound right.
-
-ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
-The value returned by channel reg 0xC is (envelope_level>>16).
-
-Each sample, an increment or decrement value will be added to or
-subtracted from this envelope level.
-
-Create the rate log table.  The values double every 4 entries.
-   entry #0 = 4
-
-    4, 5, 6, 7,
-    8,10,12,14,
-   16,20,24,28, ...
-
-   entry #40 = 4096...
-   entry #44 = 8192...
-   entry #48 = 16384...
-   entry #52 = 32768...
-   entry #56 = 65536...
-
-increments and decrements are in terms of ratelogtable[n]
-n may exceed the table bounds (plan on n being between -32 and 127).
-table values are all clipped between 0x00000000 and 0x3FFFFFFF
-
-when you "voice on", the envelope is always fully reset.
-(yes, it may click. the real thing does this too.)
-
-envelope level begins at zero.
-
-each state happens for at least 1 cycle
-(transitions are not instantaneous)
-this may result in some oddness: if the decay rate is uberfast, it will cut
-the envelope from full down to half in one sample, potentially skipping over
-the sustain level
-
-ATTACK
-------
-- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
-  proceed to DECAY.
-
-Linear attack mode:
-- line extends upward to 0x7FFFFFFF
-- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
-
-Logarithmic attack mode:
-if envelope_level < 0x60000000:
-  - line extends upward to 0x60000000
-  - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
-else:
-  - line extends upward to 0x7FFFFFFF
-  - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
-
-DECAY
------
-- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
-  Do not clip to the sustain level.
-- current line ends at (envelope_level & 0x07FFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
-  1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
-  2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
-  3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
-  4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
-  5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
-  6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
-  7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
-  (note that this is the same as the release rate formula, except that
-   decay rates 10-1F aren't possible... those would be slower in theory)
-
-SUSTAIN
--------
-- no terminating condition except for voice off
-- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
-- Sd=1 (decrease) behavior:
-Linear sustain decrease:
-- line extends to 0x00000000
-- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
-Logarithmic sustain decrease:
-- current line ends at (envelope_level & 0x07FFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(Sr^0x7F)-0x1B+0]
-  1: ratelogtable[(Sr^0x7F)-0x1B+4]
-  2: ratelogtable[(Sr^0x7F)-0x1B+6]
-  3: ratelogtable[(Sr^0x7F)-0x1B+8]
-  4: ratelogtable[(Sr^0x7F)-0x1B+9]
-  5: ratelogtable[(Sr^0x7F)-0x1B+10]
-  6: ratelogtable[(Sr^0x7F)-0x1B+11]
-  7: ratelogtable[(Sr^0x7F)-0x1B+12]
-
-RELEASE
--------
-- if the envelope level has overflowed to negative, clip to 0 and QUIT.
-
-Linear release mode:
-- line extends to 0x00000000
-- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
-
-Logarithmic release mode:
-- line extends to (envelope_level & 0x0FFFFFFF)
-- decrement per sample depends on (envelope_level>>28)&0x7
-  0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
-  1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
-  2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
-  3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
-  4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
-  5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
-  6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
-  7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
-
------------------------------------------------------------------------------
-*/
-
diff --git a/src/psf/peops2/adsr.cc b/src/psf/peops2/adsr.cc
new file mode 100644
index 000000000000..57547ffefdc8
--- /dev/null
+++ b/src/psf/peops2/adsr.cc
@@ -0,0 +1,656 @@
+/***************************************************************************
+                          adsr.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/05/14 - xodnizel
+// - removed stopping of reverb on sample end
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_ADSR
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// ADSR func
+////////////////////////////////////////////////////////////////////////
+
+unsigned long RateTable[160];
+
+void InitADSR(void)                                    // INIT ADSR
+{
+ unsigned long r,rs,rd;int i;
+
+ memset(RateTable,0,sizeof(unsigned long)*160);        // build the rate table according to Neill's rules (see at bottom of file)
+
+ r=3;rs=1;rd=0;
+
+ for(i=32;i<160;i++)                                   // we start at pos 32 with the real values... everything before is 0
+  {
+   if(r<0x3FFFFFFF)
+    {
+     r+=rs;
+     rd++;if(rd==5) {rd=1;rs*=2;}
+    }
+   if(r>0x3FFFFFFF) r=0x3FFFFFFF;
+
+   RateTable[i]=r;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+void StartADSR(int ch)                          // MIX ADSR
+{
+ s_chan[ch].ADSRX.lVolume=1;                           // and init some adsr vars
+ s_chan[ch].ADSRX.State=0;
+ s_chan[ch].ADSRX.EnvelopeVol=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+int MixADSR(int ch)                             // MIX ADSR
+{
+ if(s_chan[ch].bStop)                                  // should be stopped:
+  {                                                    // do release
+   if(s_chan[ch].ADSRX.ReleaseModeExp)
+    {
+     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+      {
+       case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break;
+       case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break;
+       case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break;
+       case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break;
+       case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break;
+       case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break;
+       case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break;
+       case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break;
+      }
+    }
+   else
+    {
+     s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32];
+    }
+
+   if(s_chan[ch].ADSRX.EnvelopeVol<0)
+    {
+     s_chan[ch].ADSRX.EnvelopeVol=0;
+     s_chan[ch].bOn=0;
+     //s_chan[ch].bReverb=0;
+     //s_chan[ch].bNoise=0;
+    }
+
+   s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+   return s_chan[ch].ADSRX.lVolume;
+  }
+ else                                                  // not stopped yet?
+  {
+   if(s_chan[ch].ADSRX.State==0)                       // -> attack
+    {
+     if(s_chan[ch].ADSRX.AttackModeExp)
+      {
+       if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+       else
+        s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32];
+      }
+     else
+      {
+       s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32];
+      }
+
+     if(s_chan[ch].ADSRX.EnvelopeVol<0)
+      {
+       s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+       s_chan[ch].ADSRX.State=1;
+      }
+
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+   //--------------------------------------------------//
+   if(s_chan[ch].ADSRX.State==1)                       // -> decay
+    {
+     switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+      {
+       case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break;
+       case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break;
+       case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break;
+       case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break;
+       case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break;
+       case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break;
+       case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break;
+       case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break;
+      }
+
+     if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0;
+     if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel)
+      {
+       s_chan[ch].ADSRX.State=2;
+      }
+
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+   //--------------------------------------------------//
+   if(s_chan[ch].ADSRX.State==2)                       // -> sustain
+    {
+     if(s_chan[ch].ADSRX.SustainIncrease)
+      {
+       if(s_chan[ch].ADSRX.SustainModeExp)
+        {
+         if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000)
+          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+         else
+          s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32];
+        }
+       else
+        {
+         s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32];
+        }
+
+       if(s_chan[ch].ADSRX.EnvelopeVol<0)
+        {
+         s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF;
+        }
+      }
+     else
+      {
+       if(s_chan[ch].ADSRX.SustainModeExp)
+        {
+         switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7)
+          {
+           case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break;
+           case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break;
+           case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break;
+           case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break;
+           case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break;
+           case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break;
+           case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break;
+           case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break;
+          }
+        }
+       else
+        {
+         s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32];
+        }
+
+       if(s_chan[ch].ADSRX.EnvelopeVol<0)
+        {
+         s_chan[ch].ADSRX.EnvelopeVol=0;
+        }
+      }
+     s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21;
+     return s_chan[ch].ADSRX.lVolume;
+    }
+  }
+ return 0;
+}
+
+#endif
+
+/*
+James Higgs ADSR investigations:
+
+PSX SPU Envelope Timings
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+First, here is an extract from doomed's SPU doc, which explains the basics
+of the SPU "volume envelope":
+
+*** doomed doc extract start ***
+
+--------------------------------------------------------------------------
+Voices.
+--------------------------------------------------------------------------
+The SPU has 24 hardware voices. These voices can be used to reproduce sample
+data, noise or can be used as frequency modulator on the next voice.
+Each voice has it's own programmable ADSR envelope filter. The main volume
+can be programmed independently for left and right output.
+
+The ADSR envelope filter works as follows:
+Ar = Attack rate, which specifies the speed at which the volume increases
+     from zero to it's maximum value, as soon as the note on is given. The
+     slope can be set to lineair or exponential.
+Dr = Decay rate specifies the speed at which the volume decreases to the
+     sustain level. Decay is always decreasing exponentially.
+Sl = Sustain level, base level from which sustain starts.
+Sr = Sustain rate is the rate at which the volume of the sustained note
+     increases or decreases. This can be either lineair or exponential.
+Rr = Release rate is the rate at which the volume of the note decreases
+     as soon as the note off is given.
+
+     lvl |
+       ^ |     /\Dr     __
+     Sl _| _  / _ \__---  \
+         |   /       ---__ \ Rr
+         |  /Ar       Sr  \ \
+         | /                \\
+         |/___________________\________
+                                  ->time
+
+The overal volume can also be set to sweep up or down lineairly or
+exponentially from it's current value. This can be done seperately
+for left and right.
+
+Relevant SPU registers:
+-------------------------------------------------------------
+$1f801xx8         Attack/Decay/Sustain level
+bit  |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00|
+desc.|Am|         Ar         |Dr         |Sl         |
+
+Am       0        Attack mode Linear
+         1                    Exponential
+
+Ar       0-7f     attack rate
+Dr       0-f      decay rate
+Sl       0-f      sustain level
+-------------------------------------------------------------
+$1f801xxa         Sustain rate, Release Rate.
+bit  |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00|
+desc.|Sm|Sd| 0|   Sr               |Rm|Rr            |
+
+Sm       0        sustain rate mode linear
+         1                          exponential
+Sd       0        sustain rate mode increase
+         1                          decrease
+Sr       0-7f     Sustain Rate
+Rm       0        Linear decrease
+         1        Exponential decrease
+Rr       0-1f     Release Rate
+
+Note: decay mode is always Expontial decrease, and thus cannot
+be set.
+-------------------------------------------------------------
+$1f801xxc         Current ADSR volume
+bit  |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00|
+desc.|ADSRvol                                        |
+
+ADSRvol           Returns the current envelope volume when
+                  read.
+-- James' Note: return range: 0 -> 32767
+
+*** doomed doc extract end ***
+
+By using a small PSX proggie to visualise the envelope as it was played,
+the following results for envelope timing were obtained:
+
+1. Attack rate value (linear mode)
+
+   Attack value range: 0 -> 127
+
+   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |    | 80 |
+   -----------------------------------------------------------------
+   Frames | 11 | 21 | 42 | 84 | 169| 338| 676|    |2890|
+
+   Note: frames is no. of PAL frames to reach full volume (100%
+   amplitude)
+
+   Hmm, noticing that the time taken to reach full volume doubles
+   every time we add 4 to our attack value, we know the equation is
+   of form:
+             frames = k * 2 ^ (value / 4)
+
+   (You may ponder about envelope generator hardware at this point,
+   or maybe not... :)
+
+   By substituting some stuff and running some checks, we get:
+
+       k = 0.00257              (close enuf)
+
+   therefore,
+             frames = 0.00257 * 2 ^ (value / 4)
+   If you just happen to be writing an emulator, then you can probably
+   use an equation like:
+
+       %volume_increase_per_tick = 1 / frames
+
+
+   ------------------------------------
+   Pete:
+   ms=((1<<(value>>2))*514)/10000
+   ------------------------------------
+
+2. Decay rate value (only has log mode)
+
+   Decay value range: 0 -> 15
+
+   Value  |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
+   ------------------------------------------------
+   frames |    |    |    |    |  6 | 12 | 24 | 47 |
+
+   Note: frames here is no. of PAL frames to decay to 50% volume.
+
+   formula: frames = k * 2 ^ (value)
+
+   Substituting, we get: k = 0.00146
+
+   Further info on logarithmic nature:
+   frames to decay to sustain level 3  =  3 * frames to decay to
+   sustain level 9
+
+   Also no. of frames to 25% volume = roughly 1.85 * no. of frames to
+   50% volume.
+
+   Frag it - just use linear approx.
+
+   ------------------------------------
+   Pete:
+   ms=((1<<value)*292)/10000
+   ------------------------------------
+
+
+3. Sustain rate value (linear mode)
+
+   Sustain rate range: 0 -> 127
+
+   Value  | 48 | 52 | 56 | 60 | 64 | 68 | 72 |
+   -------------------------------------------
+   frames |  9 | 19 | 37 | 74 | 147| 293| 587|
+
+   Here, frames = no. of PAL frames for volume amplitude to go from 100%
+   to 0% (or vice-versa).
+
+   Same formula as for attack value, just a different value for k:
+
+   k = 0.00225
+
+   ie: frames = 0.00225 * 2 ^ (value / 4)
+
+   For emulation purposes:
+
+   %volume_increase_or_decrease_per_tick = 1 / frames
+
+   ------------------------------------
+   Pete:
+   ms=((1<<(value>>2))*450)/10000
+   ------------------------------------
+
+
+4. Release rate (linear mode)
+
+   Release rate range: 0 -> 31
+
+   Value  | 13 | 14 | 15 | 16 | 17 |
+   ---------------------------------------------------------------
+   frames | 18 | 36 | 73 | 146| 292|
+
+   Here, frames = no. of PAL frames to decay from 100% vol to 0% vol
+   after "note-off" is triggered.
+
+   Formula: frames = k * 2 ^ (value)
+
+   And so: k = 0.00223
+
+   ------------------------------------
+   Pete:
+   ms=((1<<value)*446)/10000
+   ------------------------------------
+
+
+Other notes:
+
+Log stuff not figured out. You may get some clues from the "Decay rate"
+stuff above. For emu purposes it may not be important - use linear
+approx.
+
+To get timings in millisecs, multiply frames by 20.
+
+
+
+- James Higgs 17/6/2000
+james7780 at yahoo.com
+
+//---------------------------------------------------------------
+
+OLD adsr mixing according to james' rules... has to be called
+every one millisecond
+
+
+ long v,v2,lT,l1,l2,l3;
+
+ if(s_chan[ch].bStop)                                  // psx wants to stop? -> release phase
+  {
+   if(s_chan[ch].ADSR.ReleaseVal!=0)                   // -> release not 0: do release (if 0: stop right now)
+    {
+     if(!s_chan[ch].ADSR.ReleaseVol)                   // --> release just started? set up the release stuff
+      {
+       s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime;
+       s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume;
+       s_chan[ch].ADSR.ReleaseTime =                   // --> calc how long does it take to reach the wanted sus level
+         (s_chan[ch].ADSR.ReleaseTime*
+          s_chan[ch].ADSR.ReleaseVol)/1024;
+      }
+                                                       // -> NO release exp mode used (yet)
+     v=s_chan[ch].ADSR.ReleaseVol;                     // -> get last volume
+     lT=s_chan[ch].ADSR.lTime-                         // -> how much time is past?
+        s_chan[ch].ADSR.ReleaseStartTime;
+     l1=s_chan[ch].ADSR.ReleaseTime;
+
+     if(lT<l1)                                         // -> we still have to release
+      {
+       v=v-((v*lT)/l1);                                // --> calc new volume
+      }
+     else                                              // -> release is over: now really stop that sample
+      {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+    }
+   else                                                // -> release IS 0: release at once
+    {
+     v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;
+    }
+  }
+ else
+  {//--------------------------------------------------// not in release phase:
+   v=1024;
+   lT=s_chan[ch].ADSR.lTime;
+   l1=s_chan[ch].ADSR.AttackTime;
+
+   if(lT<l1)                                           // attack
+    {                                                  // no exp mode used (yet)
+//     if(s_chan[ch].ADSR.AttackModeExp)
+//      {
+//       v=(v*lT)/l1;
+//      }
+//     else
+      {
+       v=(v*lT)/l1;
+      }
+     if(v==0) v=1;
+    }
+   else                                                // decay
+    {                                                  // should be exp, but who cares? ;)
+     l2=s_chan[ch].ADSR.DecayTime;
+     v2=s_chan[ch].ADSR.SustainLevel;
+
+     lT-=l1;
+     if(lT<l2)
+      {
+       v-=(((v-v2)*lT)/l2);
+      }
+     else                                              // sustain
+      {                                                // no exp mode used (yet)
+       l3=s_chan[ch].ADSR.SustainTime;
+       lT-=l2;
+       if(s_chan[ch].ADSR.SustainModeDec>0)
+        {
+         if(l3!=0) v2+=((v-v2)*lT)/l3;
+         else      v2=v;
+        }
+       else
+        {
+         if(l3!=0) v2-=(v2*lT)/l3;
+         else      v2=v;
+        }
+
+       if(v2>v)  v2=v;
+       if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;}
+
+       v=v2;
+      }
+    }
+  }
+
+ //----------------------------------------------------//
+ // ok, done for this channel, so increase time
+
+ s_chan[ch].ADSR.lTime+=1;                             // 1 = 1.020408f ms;
+
+ if(v>1024)     v=1024;                                // adjust volume
+ if(v<0)        v=0;
+ s_chan[ch].ADSR.lVolume=v;                            // store act volume
+
+ return v;                                             // return the volume factor
+*/
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+/*
+-----------------------------------------------------------------------------
+Neill Corlett
+Playstation SPU envelope timing notes
+-----------------------------------------------------------------------------
+
+This is preliminary.  This may be wrong.  But the model described herein fits
+all of my experimental data, and it's just simple enough to sound right.
+
+ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally.
+The value returned by channel reg 0xC is (envelope_level>>16).
+
+Each sample, an increment or decrement value will be added to or
+subtracted from this envelope level.
+
+Create the rate log table.  The values double every 4 entries.
+   entry #0 = 4
+
+    4, 5, 6, 7,
+    8,10,12,14,
+   16,20,24,28, ...
+
+   entry #40 = 4096...
+   entry #44 = 8192...
+   entry #48 = 16384...
+   entry #52 = 32768...
+   entry #56 = 65536...
+
+increments and decrements are in terms of ratelogtable[n]
+n may exceed the table bounds (plan on n being between -32 and 127).
+table values are all clipped between 0x00000000 and 0x3FFFFFFF
+
+when you "voice on", the envelope is always fully reset.
+(yes, it may click. the real thing does this too.)
+
+envelope level begins at zero.
+
+each state happens for at least 1 cycle
+(transitions are not instantaneous)
+this may result in some oddness: if the decay rate is uberfast, it will cut
+the envelope from full down to half in one sample, potentially skipping over
+the sustain level
+
+ATTACK
+------
+- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and
+  proceed to DECAY.
+
+Linear attack mode:
+- line extends upward to 0x7FFFFFFF
+- increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+
+Logarithmic attack mode:
+if envelope_level < 0x60000000:
+  - line extends upward to 0x60000000
+  - increment per sample is ratelogtable[(Ar^0x7F)-0x10]
+else:
+  - line extends upward to 0x7FFFFFFF
+  - increment per sample is ratelogtable[(Ar^0x7F)-0x18]
+
+DECAY
+-----
+- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN.
+  Do not clip to the sustain level.
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(4*(Dr^0x1F))-0x18+0]
+  1: ratelogtable[(4*(Dr^0x1F))-0x18+4]
+  2: ratelogtable[(4*(Dr^0x1F))-0x18+6]
+  3: ratelogtable[(4*(Dr^0x1F))-0x18+8]
+  4: ratelogtable[(4*(Dr^0x1F))-0x18+9]
+  5: ratelogtable[(4*(Dr^0x1F))-0x18+10]
+  6: ratelogtable[(4*(Dr^0x1F))-0x18+11]
+  7: ratelogtable[(4*(Dr^0x1F))-0x18+12]
+  (note that this is the same as the release rate formula, except that
+   decay rates 10-1F aren't possible... those would be slower in theory)
+
+SUSTAIN
+-------
+- no terminating condition except for voice off
+- Sd=0 (increase) behavior is identical to ATTACK for both log and linear.
+- Sd=1 (decrease) behavior:
+Linear sustain decrease:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F]
+Logarithmic sustain decrease:
+- current line ends at (envelope_level & 0x07FFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(Sr^0x7F)-0x1B+0]
+  1: ratelogtable[(Sr^0x7F)-0x1B+4]
+  2: ratelogtable[(Sr^0x7F)-0x1B+6]
+  3: ratelogtable[(Sr^0x7F)-0x1B+8]
+  4: ratelogtable[(Sr^0x7F)-0x1B+9]
+  5: ratelogtable[(Sr^0x7F)-0x1B+10]
+  6: ratelogtable[(Sr^0x7F)-0x1B+11]
+  7: ratelogtable[(Sr^0x7F)-0x1B+12]
+
+RELEASE
+-------
+- if the envelope level has overflowed to negative, clip to 0 and QUIT.
+
+Linear release mode:
+- line extends to 0x00000000
+- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C]
+
+Logarithmic release mode:
+- line extends to (envelope_level & 0x0FFFFFFF)
+- decrement per sample depends on (envelope_level>>28)&0x7
+  0: ratelogtable[(4*(Rr^0x1F))-0x18+0]
+  1: ratelogtable[(4*(Rr^0x1F))-0x18+4]
+  2: ratelogtable[(4*(Rr^0x1F))-0x18+6]
+  3: ratelogtable[(4*(Rr^0x1F))-0x18+8]
+  4: ratelogtable[(4*(Rr^0x1F))-0x18+9]
+  5: ratelogtable[(4*(Rr^0x1F))-0x18+10]
+  6: ratelogtable[(4*(Rr^0x1F))-0x18+11]
+  7: ratelogtable[(4*(Rr^0x1F))-0x18+12]
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/src/psf/peops2/dma.c b/src/psf/peops2/dma.c
deleted file mode 100644
index 62278cd30fb5..000000000000
--- a/src/psf/peops2/dma.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/***************************************************************************
-                            dma.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2004/04/04 - Pete
-// - changed plugin to emulate PS2 spu
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "../peops2/stdafx.h"
-
-#define _IN_DMA
-
-#include "../peops2/externals.h"
-#include "../peops2/registers.h"
-//#include "debug.h"
-
-extern uint32_t psx_ram[(2*1024*1024)/4];
-
-////////////////////////////////////////////////////////////////////////
-// READ DMA (many values)
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2readDMA4Mem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-   ram16[usPSXMem>>1]=spuMem[spuAddr2[0]];                  // spu addr 0 got by writeregister
-   usPSXMem+=2;
-   spuAddr2[0]++;                                     // inc spu addr
-   if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;             // wrap
-  }
-
- spuAddr2[0]+=0x20; //?????
-
-
- iSpuAsyncWait=0;
-
- // got from J.F. and Kanodin... is it needed?
- regArea[(PS2_C0_ADMAS)>>1]=0;                         // Auto DMA complete
- spuStat2[0]=0x80;                                     // DMA complete
-}
-
-EXPORT_GCC void CALLBACK SPU2readDMA7Mem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-   ram16[usPSXMem>>1]=spuMem[spuAddr2[1]];             // spu addr 1 got by writeregister
-   usPSXMem+=2;
-   spuAddr2[1]++;                                      // inc spu addr
-   if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;              // wrap
-  }
-
- spuAddr2[1]+=0x20; //?????
-
- iSpuAsyncWait=0;
-
- // got from J.F. and Kanodin... is it needed?
- regArea[(PS2_C1_ADMAS)>>1]=0;                         // Auto DMA complete
- spuStat2[1]=0x80;                                     // DMA complete
-}
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-
-// to investigate: do sound data updates by writedma affect spu
-// irqs? Will an irq be triggered, if new data is written to
-// the memory irq address?
-
-////////////////////////////////////////////////////////////////////////
-// WRITE DMA (many values)
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2writeDMA4Mem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-   spuMem[spuAddr2[0]] = ram16[usPSXMem>>1];                 // spu addr 0 got by writeregister
-   usPSXMem+=2;
-   spuAddr2[0]++;                                      // inc spu addr
-   if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;              // wrap
-  }
-
- iSpuAsyncWait=0;
-
- // got from J.F. and Kanodin... is it needed?
- spuStat2[0]=0x80;                                     // DMA complete
-}
-
-EXPORT_GCC void CALLBACK SPU2writeDMA7Mem(u32 usPSXMem,int iSize)
-{
- int i;
- u16 *ram16 = (u16 *)&psx_ram[0];
-
- for(i=0;i<iSize;i++)
-  {
-   spuMem[spuAddr2[1]] = ram16[usPSXMem>>1];           // spu addr 1 got by writeregister
-   spuAddr2[1]++;                                      // inc spu addr
-   if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;              // wrap
-  }
-
- iSpuAsyncWait=0;
-
- // got from J.F. and Kanodin... is it needed?
- spuStat2[1]=0x80;                                     // DMA complete
-}
-
-////////////////////////////////////////////////////////////////////////
-// INTERRUPTS
-////////////////////////////////////////////////////////////////////////
-
-void InterruptDMA4(void)
-{
-// taken from linuzappz NULL spu2
-//	spu2Rs16(CORE0_ATTR)&= ~0x30;
-//	spu2Rs16(REG__1B0) = 0;
-//	spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80;
-
- spuCtrl2[0]&=~0x30;
- regArea[(PS2_C0_ADMAS)>>1]=0;
- spuStat2[0]|=0x80;
-}
-
-EXPORT_GCC void CALLBACK SPU2interruptDMA4(void)
-{
- InterruptDMA4();
-}
-
-void InterruptDMA7(void)
-{
-// taken from linuzappz NULL spu2
-//	spu2Rs16(CORE1_ATTR)&= ~0x30;
-//	spu2Rs16(REG__5B0) = 0;
-//	spu2Rs16(SPU2_STATX_DREQ)|= 0x80;
-
- spuCtrl2[1]&=~0x30;
- regArea[(PS2_C1_ADMAS)>>1]=0;
- spuStat2[1]|=0x80;
-}
-
-EXPORT_GCC void CALLBACK SPU2interruptDMA7(void)
-{
- InterruptDMA7();
-}
-
diff --git a/src/psf/peops2/dma.cc b/src/psf/peops2/dma.cc
new file mode 100644
index 000000000000..ef24be7b377b
--- /dev/null
+++ b/src/psf/peops2/dma.cc
@@ -0,0 +1,175 @@
+/***************************************************************************
+                            dma.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed plugin to emulate PS2 spu
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "../peops2/stdafx.h"
+
+#define _IN_DMA
+
+#include "../peops2/externals.h"
+#include "../peops2/registers.h"
+//#include "debug.h"
+
+extern uint32_t psx_ram[(2*1024*1024)/4];
+
+////////////////////////////////////////////////////////////////////////
+// READ DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2readDMA4Mem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+   ram16[usPSXMem>>1]=spuMem[spuAddr2[0]];                  // spu addr 0 got by writeregister
+   usPSXMem+=2;
+   spuAddr2[0]++;                                     // inc spu addr
+   if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;             // wrap
+  }
+
+ spuAddr2[0]+=0x20; //?????
+
+
+ iSpuAsyncWait=0;
+
+ // got from J.F. and Kanodin... is it needed?
+ regArea[(PS2_C0_ADMAS)>>1]=0;                         // Auto DMA complete
+ spuStat2[0]=0x80;                                     // DMA complete
+}
+
+EXPORT_GCC void CALLBACK SPU2readDMA7Mem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+   ram16[usPSXMem>>1]=spuMem[spuAddr2[1]];             // spu addr 1 got by writeregister
+   usPSXMem+=2;
+   spuAddr2[1]++;                                      // inc spu addr
+   if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;              // wrap
+  }
+
+ spuAddr2[1]+=0x20; //?????
+
+ iSpuAsyncWait=0;
+
+ // got from J.F. and Kanodin... is it needed?
+ regArea[(PS2_C1_ADMAS)>>1]=0;                         // Auto DMA complete
+ spuStat2[1]=0x80;                                     // DMA complete
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+// to investigate: do sound data updates by writedma affect spu
+// irqs? Will an irq be triggered, if new data is written to
+// the memory irq address?
+
+////////////////////////////////////////////////////////////////////////
+// WRITE DMA (many values)
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2writeDMA4Mem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+   spuMem[spuAddr2[0]] = ram16[usPSXMem>>1];                 // spu addr 0 got by writeregister
+   usPSXMem+=2;
+   spuAddr2[0]++;                                      // inc spu addr
+   if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;              // wrap
+  }
+
+ iSpuAsyncWait=0;
+
+ // got from J.F. and Kanodin... is it needed?
+ spuStat2[0]=0x80;                                     // DMA complete
+}
+
+EXPORT_GCC void CALLBACK SPU2writeDMA7Mem(u32 usPSXMem,int iSize)
+{
+ int i;
+ u16 *ram16 = (u16 *)&psx_ram[0];
+
+ for(i=0;i<iSize;i++)
+  {
+   spuMem[spuAddr2[1]] = ram16[usPSXMem>>1];           // spu addr 1 got by writeregister
+   spuAddr2[1]++;                                      // inc spu addr
+   if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;              // wrap
+  }
+
+ iSpuAsyncWait=0;
+
+ // got from J.F. and Kanodin... is it needed?
+ spuStat2[1]=0x80;                                     // DMA complete
+}
+
+////////////////////////////////////////////////////////////////////////
+// INTERRUPTS
+////////////////////////////////////////////////////////////////////////
+
+void InterruptDMA4(void)
+{
+// taken from linuzappz nullptr spu2
+//	spu2Rs16(CORE0_ATTR)&= ~0x30;
+//	spu2Rs16(REG__1B0) = 0;
+//	spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80;
+
+ spuCtrl2[0]&=~0x30;
+ regArea[(PS2_C0_ADMAS)>>1]=0;
+ spuStat2[0]|=0x80;
+}
+
+EXPORT_GCC void CALLBACK SPU2interruptDMA4(void)
+{
+ InterruptDMA4();
+}
+
+void InterruptDMA7(void)
+{
+// taken from linuzappz nullptr spu2
+//	spu2Rs16(CORE1_ATTR)&= ~0x30;
+//	spu2Rs16(REG__5B0) = 0;
+//	spu2Rs16(SPU2_STATX_DREQ)|= 0x80;
+
+ spuCtrl2[1]&=~0x30;
+ regArea[(PS2_C1_ADMAS)>>1]=0;
+ spuStat2[1]|=0x80;
+}
+
+EXPORT_GCC void CALLBACK SPU2interruptDMA7(void)
+{
+ InterruptDMA7();
+}
+
diff --git a/src/psf/peops2/registers.c b/src/psf/peops2/registers.c
deleted file mode 100644
index bad9e1d36c57..000000000000
--- a/src/psf/peops2/registers.c
+++ /dev/null
@@ -1,1343 +0,0 @@
-/***************************************************************************
-                         registers.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2004/04/04 - Pete
-// - changed plugin to emulate PS2 spu
-//
-// 2003/02/09 - kode54
-// - removed &0x3fff from reverb volume registers, fixes a few games,
-//   hopefully won't be breaking anything
-//
-// 2003/01/19 - Pete
-// - added Neill's reverb
-//
-// 2003/01/06 - Pete
-// - added Neill's ADSR timings
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_REGISTERS
-
-#include "../peops2/externals.h"
-#include "../peops2/registers.h"
-#include "../peops2/regs.h"
-#include "../peops2/reverb.h"
-
-/*
-// adsr time values (in ms) by James Higgs ... see the end of
-// the adsr.c source for details
-
-#define ATTACK_MS     514L
-#define DECAYHALF_MS  292L
-#define DECAY_MS      584L
-#define SUSTAIN_MS    450L
-#define RELEASE_MS    446L
-*/
-
-// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines
-#define ATTACK_MS      494L
-#define DECAYHALF_MS   286L
-#define DECAY_MS       572L
-#define SUSTAIN_MS     441L
-#define RELEASE_MS     437L
-
-// Prototypes
-void SetVolumeL(unsigned char ch,short vol);
-void SetVolumeR(unsigned char ch,short vol);
-void ReverbOn(int start,int end,unsigned short val,int iRight);
-void SetReverbAddr(int core);
-void VolumeOn(int start,int end,unsigned short val,int iRight);
-
-////////////////////////////////////////////////////////////////////////
-// WRITE REGISTERS: called by main emu
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val)
-{
- long r=reg&0xffff;
-
- regArea[r>>1] = val;
-
-//	printf("SPU2: %04x to %08x\n", val, reg);
-
- if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580))  // some channel info?
-  {
-   int ch=(r>>4)&0x1f;
-   if(r>=0x400) ch+=24;
-
-   switch(r&0x0f)
-    {
-     //------------------------------------------------// r volume
-     case 0:
-       SetVolumeL((unsigned char)ch,val);
-       break;
-     //------------------------------------------------// l volume
-     case 2:
-       SetVolumeR((unsigned char)ch,val);
-       break;
-     //------------------------------------------------// pitch
-     case 4:
-       SetPitch(ch,val);
-       break;
-     //------------------------------------------------// level with pre-calcs
-     case 6:
-       {
-        const unsigned long lval=val;unsigned long lx;
-        //---------------------------------------------//
-        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
-        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
-        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
-        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
-        //---------------------------------------------//
-        if(!iDebugMode) break;
-        //---------------------------------------------// stuff below is only for debug mode
-
-        s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0;        //0x007f
-
-        lx=(((lval>>8) & 0x007f)>>2);                  // attack time to run from 0 to 100% volume
-        lx = (lx < 31) ? lx : 31;                      // no overflow on shift!
-        if(lx)
-         {
-          lx = (1<<lx);
-          if(lx<2147483) lx=(lx*ATTACK_MS)/10000L;     // another overflow check
-          else           lx=(lx/10000L)*ATTACK_MS;
-          if(!lx) lx=1;
-         }
-        s_chan[ch].ADSR.AttackTime=lx;
-
-        s_chan[ch].ADSR.SustainLevel=                 // our adsr vol runs from 0 to 1024, so scale the sustain level
-         (1024*((lval) & 0x000f))/15;
-
-        lx=(lval>>4) & 0x000f;                         // decay:
-        if(lx)                                         // our const decay value is time it takes from 100% to 0% of volume
-         {
-          lx = ((1<<(lx))*DECAY_MS)/10000L;
-          if(!lx) lx=1;
-         }
-        s_chan[ch].ADSR.DecayTime =                   // so calc how long does it take to run from 100% to the wanted sus level
-         (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
-       }
-      break;
-     //------------------------------------------------// adsr times with pre-calcs
-     case 8:
-      {
-       const unsigned long lval=val;unsigned long lx;
-
-       //----------------------------------------------//
-       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
-       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
-       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
-       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
-       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
-       //----------------------------------------------//
-       if(!iDebugMode) break;
-       //----------------------------------------------// stuff below is only for debug mode
-
-       s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
-       s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;
-
-       lx=((((lval>>6) & 0x007f)>>2));                 // sustain time... often very high
-       lx = (lx < 31) ? lx : 31;                       // values are used to hold the volume
-       if(lx)                                          // until a sound stop occurs
-        {                                              // the highest value we reach (due to
-         lx = (1<<lx);                                 // overflow checking) is:
-         if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L;     // 94704 seconds = 1578 minutes = 26 hours...
-         else           lx=(lx/10000L)*SUSTAIN_MS;     // should be enuff... if the stop doesn't
-         if(!lx) lx=1;                                 // come in this time span, I don't care :)
-        }
-       s_chan[ch].ADSR.SustainTime = lx;
-
-       lx=(lval & 0x001f);
-       s_chan[ch].ADSR.ReleaseVal     =lx;
-       if(lx)                                          // release time from 100% to 0%
-        {                                              // note: the release time will be
-         lx = (1<<lx);                                 // adjusted when a stop is coming,
-         if(lx<2147483) lx=(lx*RELEASE_MS)/10000L;     // so at this time the adsr vol will
-         else           lx=(lx/10000L)*RELEASE_MS;     // run from (current volume) to 0%
-         if(!lx) lx=1;
-        }
-       s_chan[ch].ADSR.ReleaseTime=lx;
-
-       if(lval & 0x4000)                               // add/dec flag
-            s_chan[ch].ADSR.SustainModeDec=-1;
-       else s_chan[ch].ADSR.SustainModeDec=1;
-      }
-     break;
-     //------------------------------------------------//
-    }
-
-   iSpuAsyncWait=0;
-
-   return;
-  }
-
- if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0))  // some channel info?
-  {
-   int ch=0;
-   if(r>=0x400) {ch=24;r-=0x400;}
-
-   ch+=(r-0x1c0)/12;
-   r-=(ch%24)*12;
-   switch(r)
-    {
-     //------------------------------------------------//
-     case 0x1C0:
-      s_chan[ch].iStartAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iStartAdr&0xFFFF);
-      s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
-      break;
-     case 0x1C2:
-      s_chan[ch].iStartAdr=(s_chan[ch].iStartAdr & 0xF0000) | (val & 0xFFFF);
-      s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
-      break;
-     //------------------------------------------------//
-     case 0x1C4:
-      s_chan[ch].iLoopAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iLoopAdr&0xFFFF);
-      s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
-      s_chan[ch].bIgnoreLoop=1;
-      break;
-     case 0x1C6:
-      s_chan[ch].iLoopAdr=(s_chan[ch].iLoopAdr & 0xF0000) | (val & 0xFFFF);
-      s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
-      s_chan[ch].bIgnoreLoop=1;
-      break;
-     //------------------------------------------------//
-     case 0x1C8:
-      // unused... check if it gets written as well
-      s_chan[ch].iNextAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iNextAdr&0xFFFF);
-      break;
-     case 0x1CA:
-      // unused... check if it gets written as well
-      s_chan[ch].iNextAdr=(s_chan[ch].iNextAdr & 0xF0000) | (val & 0xFFFF);
-      break;
-     //------------------------------------------------//
-    }
-
-   iSpuAsyncWait=0;
-
-   return;
-  }
-
- switch(r)
-   {
-    //-------------------------------------------------//
-    case PS2_C0_SPUaddr_Hi:
-      spuAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuAddr2[0]&0xFFFF);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUaddr_Lo:
-      spuAddr2[0] = (spuAddr2[0] & 0xF0000) | (val & 0xFFFF);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUaddr_Hi:
-      spuAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuAddr2[1]&0xFFFF);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUaddr_Lo:
-      spuAddr2[1] = (spuAddr2[1] & 0xF0000) | (val & 0xFFFF);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUdata:
-      spuMem[spuAddr2[0]] = val;
-      spuAddr2[0]++;
-      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUdata:
-      spuMem[spuAddr2[1]] = val;
-      spuAddr2[1]++;
-      if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_ATTR:
-      spuCtrl2[0]=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_ATTR:
-      spuCtrl2[1]=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUstat:
-      spuStat2[0]=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUstat:
-      spuStat2[1]=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_ReverbAddr_Hi:
-      spuRvbAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[0]&0xFFFF);
-      SetReverbAddr(0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_ReverbAddr_Lo:
-      spuRvbAddr2[0] = (spuRvbAddr2[0] & 0xF0000) | (val & 0xFFFF);
-      SetReverbAddr(0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_ReverbAEnd_Hi:
-      spuRvbAEnd2[0] = (((unsigned long)val&0xf)<<16)|(/*spuRvbAEnd2[0]&*/0xFFFF);
-      rvb[0].EndAddr=spuRvbAEnd2[0];
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_ReverbAEnd_Hi:
-      spuRvbAEnd2[1] = (((unsigned long)val&0xf)<<16)|(/*spuRvbAEnd2[1]&*/0xFFFF);
-      rvb[1].EndAddr=spuRvbAEnd2[1];
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_ReverbAddr_Hi:
-      spuRvbAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[1]&0xFFFF);
-      SetReverbAddr(1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_ReverbAddr_Lo:
-      spuRvbAddr2[1] = (spuRvbAddr2[1] & 0xF0000) | (val & 0xFFFF);
-      SetReverbAddr(1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUirqAddr_Hi:
-      spuIrq2[0] = (((unsigned long)val&0xf)<<16)|(spuIrq2[0]&0xFFFF);
-      pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUirqAddr_Lo:
-      spuIrq2[0] = (spuIrq2[0] & 0xF0000) | (val & 0xFFFF);
-      pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUirqAddr_Hi:
-      spuIrq2[1] = (((unsigned long)val&0xf)<<16)|(spuIrq2[1]&0xFFFF);
-      pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUirqAddr_Lo:
-      spuIrq2[1] = (spuIrq2[1] & 0xF0000) | (val & 0xFFFF);
-      pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUrvolL:
-      rvb[0].VolLeft=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUrvolR:
-      rvb[0].VolRight=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUrvolL:
-      rvb[1].VolLeft=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUrvolR:
-      rvb[1].VolRight=val;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUon1:
-      SoundOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUon2:
-      SoundOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUon1:
-      SoundOn(24,40,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUon2:
-      SoundOn(40,48,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUoff1:
-      SoundOff(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUoff2:
-      SoundOff(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUoff1:
-      SoundOff(24,40,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUoff2:
-      SoundOff(40,48,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_SPUend1:
-    case PS2_C0_SPUend2:
-      if(val) dwEndChannel2[0]=0;
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_SPUend1:
-    case PS2_C1_SPUend2:
-      if(val) dwEndChannel2[1]=0;
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_FMod1:
-      FModOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_FMod2:
-      FModOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_FMod1:
-      FModOn(24,40,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_FMod2:
-      FModOn(40,48,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_Noise1:
-      NoiseOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_Noise2:
-      NoiseOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_Noise1:
-      NoiseOn(24,40,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_Noise2:
-      NoiseOn(40,48,val);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_DryL1:
-      VolumeOn(0,16,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_DryL2:
-      VolumeOn(16,24,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_DryL1:
-      VolumeOn(24,40,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_DryL2:
-      VolumeOn(40,48,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_DryR1:
-      VolumeOn(0,16,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_DryR2:
-      VolumeOn(16,24,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_DryR1:
-      VolumeOn(24,40,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_DryR2:
-      VolumeOn(40,48,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_RVBon1_L:
-      ReverbOn(0,16,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_RVBon2_L:
-      ReverbOn(16,24,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_RVBon1_L:
-      ReverbOn(24,40,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_RVBon2_L:
-      ReverbOn(40,48,val,0);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_RVBon1_R:
-      ReverbOn(0,16,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_RVBon2_R:
-      ReverbOn(16,24,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_RVBon1_R:
-      ReverbOn(24,40,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C1_RVBon2_R:
-      ReverbOn(40,48,val,1);
-      break;
-    //-------------------------------------------------//
-    case PS2_C0_Reverb+0:
-      rvb[0].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_A&0xFFFF);
-      break;
-    case PS2_C0_Reverb+2:
-      rvb[0].FB_SRC_A=(rvb[0].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+4:
-      rvb[0].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_B&0xFFFF);
-      break;
-    case PS2_C0_Reverb+6:
-      rvb[0].FB_SRC_B=(rvb[0].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+8:
-      rvb[0].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+10:
-      rvb[0].IIR_DEST_A0=(rvb[0].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+12:
-      rvb[0].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+14:
-      rvb[0].IIR_DEST_A1=(rvb[0].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+16:
-      rvb[0].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+18:
-      rvb[0].ACC_SRC_A0=(rvb[0].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+20:
-      rvb[0].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+22:
-      rvb[0].ACC_SRC_A1=(rvb[0].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+24:
-      rvb[0].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+26:
-      rvb[0].ACC_SRC_B0=(rvb[0].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+28:
-      rvb[0].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+30:
-      rvb[0].ACC_SRC_B1=(rvb[0].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+32:
-      rvb[0].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+34:
-      rvb[0].IIR_SRC_A0=(rvb[0].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+36:
-      rvb[0].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+38:
-      rvb[0].IIR_SRC_A1=(rvb[0].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+40:
-      rvb[0].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+42:
-      rvb[0].IIR_DEST_B0=(rvb[0].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+44:
-      rvb[0].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+46:
-      rvb[0].IIR_DEST_B1=(rvb[0].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+48:
-      rvb[0].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+50:
-      rvb[0].ACC_SRC_C0=(rvb[0].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+52:
-      rvb[0].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+54:
-      rvb[0].ACC_SRC_C1=(rvb[0].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+56:
-      rvb[0].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+58:
-      rvb[0].ACC_SRC_D0=(rvb[0].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+60:
-      rvb[0].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+62:
-      rvb[0].ACC_SRC_D1=(rvb[0].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+64:
-      rvb[0].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+66:
-      rvb[0].IIR_SRC_B1=(rvb[0].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+68:
-      rvb[0].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+70:
-      rvb[0].IIR_SRC_B0=(rvb[0].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+72:
-      rvb[0].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+74:
-      rvb[0].MIX_DEST_A0=(rvb[0].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+76:
-      rvb[0].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+78:
-      rvb[0].MIX_DEST_A1=(rvb[0].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+80:
-      rvb[0].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B0&0xFFFF);
-      break;
-    case PS2_C0_Reverb+82:
-      rvb[0].MIX_DEST_B0=(rvb[0].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_Reverb+84:
-      rvb[0].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B1&0xFFFF);
-      break;
-    case PS2_C0_Reverb+86:
-      rvb[0].MIX_DEST_B1=(rvb[0].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C0_ReverbX+0:  rvb[0].IIR_ALPHA=(short)val;      break;
-    case PS2_C0_ReverbX+2:  rvb[0].ACC_COEF_A=(short)val;     break;
-    case PS2_C0_ReverbX+4:  rvb[0].ACC_COEF_B=(short)val;     break;
-    case PS2_C0_ReverbX+6:  rvb[0].ACC_COEF_C=(short)val;     break;
-    case PS2_C0_ReverbX+8:  rvb[0].ACC_COEF_D=(short)val;     break;
-    case PS2_C0_ReverbX+10: rvb[0].IIR_COEF=(short)val;       break;
-    case PS2_C0_ReverbX+12: rvb[0].FB_ALPHA=(short)val;       break;
-    case PS2_C0_ReverbX+14: rvb[0].FB_X=(short)val;           break;
-    case PS2_C0_ReverbX+16: rvb[0].IN_COEF_L=(short)val;      break;
-    case PS2_C0_ReverbX+18: rvb[0].IN_COEF_R=(short)val;      break;
-    //-------------------------------------------------//
-    case PS2_C1_Reverb+0:
-      rvb[1].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_A&0xFFFF);
-      break;
-    case PS2_C1_Reverb+2:
-      rvb[1].FB_SRC_A=(rvb[1].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+4:
-      rvb[1].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_B&0xFFFF);
-      break;
-    case PS2_C1_Reverb+6:
-      rvb[1].FB_SRC_B=(rvb[1].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+8:
-      rvb[1].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+10:
-      rvb[1].IIR_DEST_A0=(rvb[1].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+12:
-      rvb[1].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+14:
-      rvb[1].IIR_DEST_A1=(rvb[1].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+16:
-      rvb[1].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+18:
-      rvb[1].ACC_SRC_A0=(rvb[1].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+20:
-      rvb[1].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+22:
-      rvb[1].ACC_SRC_A1=(rvb[1].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+24:
-      rvb[1].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+26:
-      rvb[1].ACC_SRC_B0=(rvb[1].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+28:
-      rvb[1].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+30:
-      rvb[1].ACC_SRC_B1=(rvb[1].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+32:
-      rvb[1].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+34:
-      rvb[1].IIR_SRC_A0=(rvb[1].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+36:
-      rvb[1].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+38:
-      rvb[1].IIR_SRC_A1=(rvb[1].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+40:
-      rvb[1].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+42:
-      rvb[1].IIR_DEST_B0=(rvb[1].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+44:
-      rvb[1].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+46:
-      rvb[1].IIR_DEST_B1=(rvb[1].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+48:
-      rvb[1].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+50:
-      rvb[1].ACC_SRC_C0=(rvb[1].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+52:
-      rvb[1].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+54:
-      rvb[1].ACC_SRC_C1=(rvb[1].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+56:
-      rvb[1].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+58:
-      rvb[1].ACC_SRC_D0=(rvb[1].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+60:
-      rvb[1].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+62:
-      rvb[1].ACC_SRC_D1=(rvb[1].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+64:
-      rvb[1].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+66:
-      rvb[1].IIR_SRC_B1=(rvb[1].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+68:
-      rvb[1].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+70:
-      rvb[1].IIR_SRC_B0=(rvb[1].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+72:
-      rvb[1].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+74:
-      rvb[1].MIX_DEST_A0=(rvb[1].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+76:
-      rvb[1].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+78:
-      rvb[1].MIX_DEST_A1=(rvb[1].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+80:
-      rvb[1].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B0&0xFFFF);
-      break;
-    case PS2_C1_Reverb+82:
-      rvb[1].MIX_DEST_B0=(rvb[1].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_Reverb+84:
-      rvb[1].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B1&0xFFFF);
-      break;
-    case PS2_C1_Reverb+86:
-      rvb[1].MIX_DEST_B1=(rvb[1].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
-      break;
-    case PS2_C1_ReverbX+0:  rvb[1].IIR_ALPHA=(short)val;      break;
-    case PS2_C1_ReverbX+2:  rvb[1].ACC_COEF_A=(short)val;     break;
-    case PS2_C1_ReverbX+4:  rvb[1].ACC_COEF_B=(short)val;     break;
-    case PS2_C1_ReverbX+6:  rvb[1].ACC_COEF_C=(short)val;     break;
-    case PS2_C1_ReverbX+8:  rvb[1].ACC_COEF_D=(short)val;     break;
-    case PS2_C1_ReverbX+10: rvb[1].IIR_COEF=(short)val;       break;
-    case PS2_C1_ReverbX+12: rvb[1].FB_ALPHA=(short)val;       break;
-    case PS2_C1_ReverbX+14: rvb[1].FB_X=(short)val;           break;
-    case PS2_C1_ReverbX+16: rvb[1].IN_COEF_L=(short)val;      break;
-    case PS2_C1_ReverbX+18: rvb[1].IN_COEF_R=(short)val;      break;
-   }
-
- iSpuAsyncWait=0;
-
-}
-
-////////////////////////////////////////////////////////////////////////
-// READ REGISTER: called by main emu
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg)
-{
- long r=reg&0xffff;
-
-#ifdef _WINDOWS
-// if(iDebugMode==1) logprintf("R_REG %X\r\n",reg&0xFFFF);
-#endif
-
- iSpuAsyncWait=0;
-
- if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580))  // some channel info?
-  {
-   switch(r&0x0f)
-    {
-     //------------------------------------------------// env value
-     case 10:
-      {
-       int ch=(r>>4)&0x1f;
-       if(r>=0x400) ch+=24;
-       if(s_chan[ch].bNew) return 1;                   // we are started, but not processed? return 1
-       if(s_chan[ch].ADSRX.lVolume &&                  // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
-          !s_chan[ch].ADSRX.EnvelopeVol)
-        return 1;
-       return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16);
-      }break;
-    }
-  }
-
- if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0))  // some channel info?
-  {
-   int ch=0;unsigned long rx=r;
-   if(rx>=0x400) {ch=24;rx-=0x400;}
-
-   ch+=(rx-0x1c0)/12;
-   rx-=(ch%24)*12;
-
-   switch(rx)
-    {
-     //------------------------------------------------//
-     case 0x1C4:
-      return (((s_chan[ch].pLoop-spuMemC)>>17)&0xF);
-      break;
-     case 0x1C6:
-      return (((s_chan[ch].pLoop-spuMemC)>>1)&0xFFFF);
-      break;
-     //------------------------------------------------//
-     case 0x1C8:
-      return (((s_chan[ch].pCurr-spuMemC)>>17)&0xF);
-      break;
-     case 0x1CA:
-      return (((s_chan[ch].pCurr-spuMemC)>>1)&0xFFFF);
-      break;
-     //------------------------------------------------//
-    }
-  }
-
- switch(r)
-  {
-   //--------------------------------------------------//
-   case PS2_C0_SPUend1:
-     return (unsigned short)((dwEndChannel2[0]&0xFFFF));
-   case PS2_C0_SPUend2:
-     return (unsigned short)((dwEndChannel2[0]>>16));
-   //--------------------------------------------------//
-   case PS2_C1_SPUend1:
-     return (unsigned short)((dwEndChannel2[1]&0xFFFF));
-   case PS2_C1_SPUend2:
-     return (unsigned short)((dwEndChannel2[1]>>16));
-   //--------------------------------------------------//
-   case PS2_C0_ATTR:
-     return spuCtrl2[0];
-     break;
-   //--------------------------------------------------//
-   case PS2_C1_ATTR:
-     return spuCtrl2[1];
-     break;
-   //--------------------------------------------------//
-   case PS2_C0_SPUstat:
-     return spuStat2[0];
-     break;
-   //--------------------------------------------------//
-   case PS2_C1_SPUstat:
-     return spuStat2[1];
-     break;
-   //--------------------------------------------------//
-   case PS2_C0_SPUdata:
-     {
-      unsigned short s=spuMem[spuAddr2[0]];
-      spuAddr2[0]++;
-      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
-      return s;
-     }
-   //--------------------------------------------------//
-   case PS2_C1_SPUdata:
-     {
-      unsigned short s=spuMem[spuAddr2[1]];
-      spuAddr2[1]++;
-      if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
-      return s;
-     }
-   //--------------------------------------------------//
-   case PS2_C0_SPUaddr_Hi:
-     return (unsigned short)((spuAddr2[0]>>16)&0xF);
-     break;
-   case PS2_C0_SPUaddr_Lo:
-     return (unsigned short)((spuAddr2[0]&0xFFFF));
-     break;
-   //--------------------------------------------------//
-   case PS2_C1_SPUaddr_Hi:
-     return (unsigned short)((spuAddr2[1]>>16)&0xF);
-     break;
-   case PS2_C1_SPUaddr_Lo:
-     return (unsigned short)((spuAddr2[1]&0xFFFF));
-     break;
-   //--------------------------------------------------//
-  }
-
- return regArea[r>>1];
-}
-
-EXPORT_GCC void CALLBACK SPU2writePS1Port(unsigned long reg, unsigned short val)
-{
- const u32 r=reg&0xfff;
-
- if(r>=0xc00 && r<0xd80)	// channel info
- {
- 	SPU2write(r-0xc00, val);
- 	return;
- }
-
- switch(r)
-   {
-    //-------------------------------------------------//
-    case H_SPUaddr:
-      spuAddr2[0] = (u32) val<<2;
-      break;
-    //-------------------------------------------------//
-    case H_SPUdata:
-      spuMem[spuAddr2[0]] = BFLIP16(val);
-      spuAddr2[0]++;
-      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
-      break;
-    //-------------------------------------------------//
-    case H_SPUctrl:
-//      spuCtrl=val;
-      break;
-    //-------------------------------------------------//
-    case H_SPUstat:
-      spuStat2[0]=val & 0xf800;
-      break;
-    //-------------------------------------------------//
-    case H_SPUReverbAddr:
-      spuRvbAddr2[0] = val;
-      SetReverbAddr(0);
-      break;
-    //-------------------------------------------------//
-    case H_SPUirqAddr:
-      spuIrq2[0] = val<<2;
-      pSpuIrq[0]=spuMemC+((u32) val<<1);
-      break;
-    //-------------------------------------------------//
-    /* Volume settings appear to be at least 15-bit unsigned in this case.
-       Definitely NOT 15-bit signed.  Probably 16-bit signed, so s16 type cast.
-       Check out "Chrono Cross:  Shadow's End Forest"
-    */
-    case H_SPUrvolL:
-      rvb[0].VolLeft=(s16)val;
-      //printf("%d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUrvolR:
-      rvb[0].VolRight=(s16)val;
-      //printf("%d\n",val);
-      break;
-    //-------------------------------------------------//
-
-/*
-    case H_ExtLeft:
-     //auxprintf("EL %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_ExtRight:
-     //auxprintf("ER %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUmvolL:
-     //auxprintf("ML %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUmvolR:
-     //auxprintf("MR %d\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUMute1:
-     //printf("M0 %04x\n",val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUMute2:
-    // printf("M1 %04x\n",val);
-      break;
-*/
-    //-------------------------------------------------//
-    case H_SPUon1:
-      SoundOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-     case H_SPUon2:
-      //printf("Boop: %08x: %04x\n",reg,val);
-      SoundOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUoff1:
-      SoundOff(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_SPUoff2:
-      SoundOff(16,24,val);
-	// printf("Boop: %08x: %04x\n",reg,val);
-      break;
-    //-------------------------------------------------//
-    case H_FMod1:
-      FModOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_FMod2:
-      FModOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_Noise1:
-      NoiseOn(0,16,val);
-      break;
-    //-------------------------------------------------//
-    case H_Noise2:
-      NoiseOn(16,24,val);
-      break;
-    //-------------------------------------------------//
-    case H_RVBon1:
-      ReverbOn(0,16,val,0);
-      break;
-
-    //-------------------------------------------------//
-    case H_RVBon2:
-      ReverbOn(16,24,val,0);
-      break;
-
-    //-------------------------------------------------//
-    case H_Reverb+0:
-      rvb[0].FB_SRC_A=val;
-      break;
-
-    case H_Reverb+2   : rvb[0].FB_SRC_B=(s16)val;       break;
-    case H_Reverb+4   : rvb[0].IIR_ALPHA=(s16)val;      break;
-    case H_Reverb+6   : rvb[0].ACC_COEF_A=(s16)val;     break;
-    case H_Reverb+8   : rvb[0].ACC_COEF_B=(s16)val;     break;
-    case H_Reverb+10  : rvb[0].ACC_COEF_C=(s16)val;     break;
-    case H_Reverb+12  : rvb[0].ACC_COEF_D=(s16)val;     break;
-    case H_Reverb+14  : rvb[0].IIR_COEF=(s16)val;       break;
-    case H_Reverb+16  : rvb[0].FB_ALPHA=(s16)val;       break;
-    case H_Reverb+18  : rvb[0].FB_X=(s16)val;           break;
-    case H_Reverb+20  : rvb[0].IIR_DEST_A0=(s16)val;    break;
-    case H_Reverb+22  : rvb[0].IIR_DEST_A1=(s16)val;    break;
-    case H_Reverb+24  : rvb[0].ACC_SRC_A0=(s16)val;     break;
-    case H_Reverb+26  : rvb[0].ACC_SRC_A1=(s16)val;     break;
-    case H_Reverb+28  : rvb[0].ACC_SRC_B0=(s16)val;     break;
-    case H_Reverb+30  : rvb[0].ACC_SRC_B1=(s16)val;     break;
-    case H_Reverb+32  : rvb[0].IIR_SRC_A0=(s16)val;     break;
-    case H_Reverb+34  : rvb[0].IIR_SRC_A1=(s16)val;     break;
-    case H_Reverb+36  : rvb[0].IIR_DEST_B0=(s16)val;    break;
-    case H_Reverb+38  : rvb[0].IIR_DEST_B1=(s16)val;    break;
-    case H_Reverb+40  : rvb[0].ACC_SRC_C0=(s16)val;     break;
-    case H_Reverb+42  : rvb[0].ACC_SRC_C1=(s16)val;     break;
-    case H_Reverb+44  : rvb[0].ACC_SRC_D0=(s16)val;     break;
-    case H_Reverb+46  : rvb[0].ACC_SRC_D1=(s16)val;     break;
-    case H_Reverb+48  : rvb[0].IIR_SRC_B1=(s16)val;     break;
-    case H_Reverb+50  : rvb[0].IIR_SRC_B0=(s16)val;     break;
-    case H_Reverb+52  : rvb[0].MIX_DEST_A0=(s16)val;    break;
-    case H_Reverb+54  : rvb[0].MIX_DEST_A1=(s16)val;    break;
-    case H_Reverb+56  : rvb[0].MIX_DEST_B0=(s16)val;    break;
-    case H_Reverb+58  : rvb[0].MIX_DEST_B1=(s16)val;    break;
-    case H_Reverb+60  : rvb[0].IN_COEF_L=(s16)val;      break;
-    case H_Reverb+62  : rvb[0].IN_COEF_R=(s16)val;      break;
-   }
-}
-
-EXPORT_GCC unsigned short CALLBACK SPU2readPS1Port(unsigned long reg)
-{
- const u32 r=reg&0xfff;
-
- if(r>=0x0c00 && r<0x0d80)
-  {
-  	return SPU2read(r-0xc00);
-  }
-
- switch(r)
-  {
-//    case H_SPUctrl:
-//     return spuCtrl;
-     break;
-
-    case H_SPUstat:
-     return spuStat2[0];
-     break;
-
-    case H_SPUaddr:
-     return (u16)(spuAddr2[0]>>2);
-     break;
-
-    case H_SPUdata:
-     {
-      u16 s=BFLIP16(spuMem[spuAddr2[0]]);
-      spuAddr2[0]++;
-      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
-      return s;
-     }
-     break;
-
-    case H_SPUirqAddr:
-     return spuIrq2[0]>>2;
-     break;
-  }
-
-  return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SOUND ON register write
-////////////////////////////////////////////////////////////////////////
-
-void SoundOn(int start,int end,unsigned short val)     // SOUND ON PSX COMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if((val&1) && s_chan[ch].pStart)                    // mmm... start has to be set before key on !?!
-    {
-     s_chan[ch].bIgnoreLoop=0;
-     s_chan[ch].bNew=1;
-     dwNewChannel2[ch/24]|=(1<<(ch%24));               // bitfield for faster testing
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// SOUND OFF register write
-////////////////////////////////////////////////////////////////////////
-
-void SoundOff(int start,int end,unsigned short val)    // SOUND OFF PSX COMMAND
-{
- int ch;
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // && s_chan[i].bOn)  mmm...
-    {
-     s_chan[ch].bStop=1;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// FMOD register write
-////////////////////////////////////////////////////////////////////////
-
-void FModOn(int start,int end,unsigned short val)      // FMOD ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> fmod on/off
-    {
-     if(ch>0)
-      {
-       s_chan[ch].bFMod=1;                             // --> sound channel
-       s_chan[ch-1].bFMod=2;                           // --> freq channel
-      }
-    }
-   else
-    {
-     s_chan[ch].bFMod=0;                               // --> turn off fmod
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// NOISE register write
-////////////////////////////////////////////////////////////////////////
-
-void NoiseOn(int start,int end,unsigned short val)     // NOISE ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> noise on/off
-    {
-     s_chan[ch].bNoise=1;
-    }
-   else
-    {
-     s_chan[ch].bNoise=0;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// LEFT VOLUME register write
-////////////////////////////////////////////////////////////////////////
-
-// please note: sweep and phase invert are wrong... but I've never seen
-// them used
-
-void SetVolumeL(unsigned char ch,short vol)            // LEFT VOLUME
-{
- s_chan[ch].iLeftVolRaw=vol;
-
- if(vol&0x8000)                                        // sweep?
-  {
-   short sInc=1;                                       // -> sweep up?
-   if(vol&0x2000) sInc=-1;                             // -> or down?
-   if(vol&0x1000) vol^=0xffff;                         // -> mmm... phase inverted? have to investigate this
-   vol=((vol&0x7f)+1)/2;                               // -> sweep: 0..127 -> 0..64
-   vol+=vol/(2*sInc);                                  // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
-   vol*=128;
-  }
- else                                                  // no sweep:
-  {
-   if(vol&0x4000)                                      // -> mmm... phase inverted? have to investigate this
-    //vol^=0xffff;
-    vol=0x3fff-(vol&0x3fff);
-  }
-
- vol&=0x3fff;
- s_chan[ch].iLeftVolume=vol;                           // store volume
-}
-
-////////////////////////////////////////////////////////////////////////
-// RIGHT VOLUME register write
-////////////////////////////////////////////////////////////////////////
-
-void SetVolumeR(unsigned char ch,short vol)            // RIGHT VOLUME
-{
- s_chan[ch].iRightVolRaw=vol;
-
- if(vol&0x8000)                                        // comments... see above :)
-  {
-   short sInc=1;
-   if(vol&0x2000) sInc=-1;
-   if(vol&0x1000) vol^=0xffff;
-   vol=((vol&0x7f)+1)/2;
-   vol+=vol/(2*sInc);
-   vol*=128;
-  }
- else
-  {
-   if(vol&0x4000) //vol=vol^=0xffff;
-    vol=0x3fff-(vol&0x3fff);
-  }
-
- vol&=0x3fff;
- s_chan[ch].iRightVolume=vol;
-}
-
-////////////////////////////////////////////////////////////////////////
-// PITCH register write
-////////////////////////////////////////////////////////////////////////
-
-void SetPitch(int ch,unsigned short val)               // SET PITCH
-{
- int NP;
- double intr;
-
- if(val>0x3fff) NP=0x3fff;                             // get pitch val
- else           NP=val;
-
- intr = (double)48000.0f / (double)44100.0f * (double)NP;
- NP = (uint32_t)intr;
-
- s_chan[ch].iRawPitch=NP;
-
- NP=(44100L*NP)/4096L;                                 // calc frequency
-
- if(NP<1) NP=1;                                        // some security
- s_chan[ch].iActFreq=NP;                               // store frequency
-}
-
-////////////////////////////////////////////////////////////////////////
-// REVERB register write
-////////////////////////////////////////////////////////////////////////
-
-void ReverbOn(int start,int end,unsigned short val,int iRight)  // REVERB ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> reverb on/off
-    {
-     if(iRight) s_chan[ch].bReverbR=1;
-     else       s_chan[ch].bReverbL=1;
-    }
-   else
-    {
-     if(iRight) s_chan[ch].bReverbR=0;
-     else       s_chan[ch].bReverbL=0;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// REVERB START register write
-////////////////////////////////////////////////////////////////////////
-
-void SetReverbAddr(int core)
-{
- long val=spuRvbAddr2[core];
-
- if(rvb[core].StartAddr!=val)
-  {
-   if(val<=0x27ff)
-    {
-     rvb[core].StartAddr=rvb[core].CurrAddr=0;
-    }
-   else
-    {
-     rvb[core].StartAddr=val;
-     rvb[core].CurrAddr=rvb[core].StartAddr;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// DRY LEFT/RIGHT per voice switches
-////////////////////////////////////////////////////////////////////////
-
-void VolumeOn(int start,int end,unsigned short val,int iRight)  // VOLUME ON PSX COMMAND
-{
- int ch;
-
- for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
-  {
-   if(val&1)                                           // -> reverb on/off
-    {
-     if(iRight) s_chan[ch].bVolumeR=1;
-     else       s_chan[ch].bVolumeL=1;
-    }
-   else
-    {
-     if(iRight) s_chan[ch].bVolumeR=0;
-     else       s_chan[ch].bVolumeL=0;
-    }
-  }
-}
-
-
diff --git a/src/psf/peops2/registers.cc b/src/psf/peops2/registers.cc
new file mode 100644
index 000000000000..bad9e1d36c57
--- /dev/null
+++ b/src/psf/peops2/registers.cc
@@ -0,0 +1,1343 @@
+/***************************************************************************
+                         registers.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed plugin to emulate PS2 spu
+//
+// 2003/02/09 - kode54
+// - removed &0x3fff from reverb volume registers, fixes a few games,
+//   hopefully won't be breaking anything
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_REGISTERS
+
+#include "../peops2/externals.h"
+#include "../peops2/registers.h"
+#include "../peops2/regs.h"
+#include "../peops2/reverb.h"
+
+/*
+// adsr time values (in ms) by James Higgs ... see the end of
+// the adsr.c source for details
+
+#define ATTACK_MS     514L
+#define DECAYHALF_MS  292L
+#define DECAY_MS      584L
+#define SUSTAIN_MS    450L
+#define RELEASE_MS    446L
+*/
+
+// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines
+#define ATTACK_MS      494L
+#define DECAYHALF_MS   286L
+#define DECAY_MS       572L
+#define SUSTAIN_MS     441L
+#define RELEASE_MS     437L
+
+// Prototypes
+void SetVolumeL(unsigned char ch,short vol);
+void SetVolumeR(unsigned char ch,short vol);
+void ReverbOn(int start,int end,unsigned short val,int iRight);
+void SetReverbAddr(int core);
+void VolumeOn(int start,int end,unsigned short val,int iRight);
+
+////////////////////////////////////////////////////////////////////////
+// WRITE REGISTERS: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val)
+{
+ long r=reg&0xffff;
+
+ regArea[r>>1] = val;
+
+//	printf("SPU2: %04x to %08x\n", val, reg);
+
+ if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580))  // some channel info?
+  {
+   int ch=(r>>4)&0x1f;
+   if(r>=0x400) ch+=24;
+
+   switch(r&0x0f)
+    {
+     //------------------------------------------------// r volume
+     case 0:
+       SetVolumeL((unsigned char)ch,val);
+       break;
+     //------------------------------------------------// l volume
+     case 2:
+       SetVolumeR((unsigned char)ch,val);
+       break;
+     //------------------------------------------------// pitch
+     case 4:
+       SetPitch(ch,val);
+       break;
+     //------------------------------------------------// level with pre-calcs
+     case 6:
+       {
+        const unsigned long lval=val;unsigned long lx;
+        //---------------------------------------------//
+        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0;
+        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
+        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
+        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
+        //---------------------------------------------//
+        if(!iDebugMode) break;
+        //---------------------------------------------// stuff below is only for debug mode
+
+        s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0;        //0x007f
+
+        lx=(((lval>>8) & 0x007f)>>2);                  // attack time to run from 0 to 100% volume
+        lx = (lx < 31) ? lx : 31;                      // no overflow on shift!
+        if(lx)
+         {
+          lx = (1<<lx);
+          if(lx<2147483) lx=(lx*ATTACK_MS)/10000L;     // another overflow check
+          else           lx=(lx/10000L)*ATTACK_MS;
+          if(!lx) lx=1;
+         }
+        s_chan[ch].ADSR.AttackTime=lx;
+
+        s_chan[ch].ADSR.SustainLevel=                 // our adsr vol runs from 0 to 1024, so scale the sustain level
+         (1024*((lval) & 0x000f))/15;
+
+        lx=(lval>>4) & 0x000f;                         // decay:
+        if(lx)                                         // our const decay value is time it takes from 100% to 0% of volume
+         {
+          lx = ((1<<(lx))*DECAY_MS)/10000L;
+          if(!lx) lx=1;
+         }
+        s_chan[ch].ADSR.DecayTime =                   // so calc how long does it take to run from 100% to the wanted sus level
+         (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024;
+       }
+      break;
+     //------------------------------------------------// adsr times with pre-calcs
+     case 8:
+      {
+       const unsigned long lval=val;unsigned long lx;
+
+       //----------------------------------------------//
+       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
+       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
+       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
+       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
+       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
+       //----------------------------------------------//
+       if(!iDebugMode) break;
+       //----------------------------------------------// stuff below is only for debug mode
+
+       s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0;
+       s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0;
+
+       lx=((((lval>>6) & 0x007f)>>2));                 // sustain time... often very high
+       lx = (lx < 31) ? lx : 31;                       // values are used to hold the volume
+       if(lx)                                          // until a sound stop occurs
+        {                                              // the highest value we reach (due to
+         lx = (1<<lx);                                 // overflow checking) is:
+         if(lx<2147483) lx=(lx*SUSTAIN_MS)/10000L;     // 94704 seconds = 1578 minutes = 26 hours...
+         else           lx=(lx/10000L)*SUSTAIN_MS;     // should be enuff... if the stop doesn't
+         if(!lx) lx=1;                                 // come in this time span, I don't care :)
+        }
+       s_chan[ch].ADSR.SustainTime = lx;
+
+       lx=(lval & 0x001f);
+       s_chan[ch].ADSR.ReleaseVal     =lx;
+       if(lx)                                          // release time from 100% to 0%
+        {                                              // note: the release time will be
+         lx = (1<<lx);                                 // adjusted when a stop is coming,
+         if(lx<2147483) lx=(lx*RELEASE_MS)/10000L;     // so at this time the adsr vol will
+         else           lx=(lx/10000L)*RELEASE_MS;     // run from (current volume) to 0%
+         if(!lx) lx=1;
+        }
+       s_chan[ch].ADSR.ReleaseTime=lx;
+
+       if(lval & 0x4000)                               // add/dec flag
+            s_chan[ch].ADSR.SustainModeDec=-1;
+       else s_chan[ch].ADSR.SustainModeDec=1;
+      }
+     break;
+     //------------------------------------------------//
+    }
+
+   iSpuAsyncWait=0;
+
+   return;
+  }
+
+ if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0))  // some channel info?
+  {
+   int ch=0;
+   if(r>=0x400) {ch=24;r-=0x400;}
+
+   ch+=(r-0x1c0)/12;
+   r-=(ch%24)*12;
+   switch(r)
+    {
+     //------------------------------------------------//
+     case 0x1C0:
+      s_chan[ch].iStartAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iStartAdr&0xFFFF);
+      s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
+      break;
+     case 0x1C2:
+      s_chan[ch].iStartAdr=(s_chan[ch].iStartAdr & 0xF0000) | (val & 0xFFFF);
+      s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1);
+      break;
+     //------------------------------------------------//
+     case 0x1C4:
+      s_chan[ch].iLoopAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iLoopAdr&0xFFFF);
+      s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
+      s_chan[ch].bIgnoreLoop=1;
+      break;
+     case 0x1C6:
+      s_chan[ch].iLoopAdr=(s_chan[ch].iLoopAdr & 0xF0000) | (val & 0xFFFF);
+      s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1);
+      s_chan[ch].bIgnoreLoop=1;
+      break;
+     //------------------------------------------------//
+     case 0x1C8:
+      // unused... check if it gets written as well
+      s_chan[ch].iNextAdr=(((unsigned long)val&0xf)<<16)|(s_chan[ch].iNextAdr&0xFFFF);
+      break;
+     case 0x1CA:
+      // unused... check if it gets written as well
+      s_chan[ch].iNextAdr=(s_chan[ch].iNextAdr & 0xF0000) | (val & 0xFFFF);
+      break;
+     //------------------------------------------------//
+    }
+
+   iSpuAsyncWait=0;
+
+   return;
+  }
+
+ switch(r)
+   {
+    //-------------------------------------------------//
+    case PS2_C0_SPUaddr_Hi:
+      spuAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuAddr2[0]&0xFFFF);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUaddr_Lo:
+      spuAddr2[0] = (spuAddr2[0] & 0xF0000) | (val & 0xFFFF);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUaddr_Hi:
+      spuAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuAddr2[1]&0xFFFF);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUaddr_Lo:
+      spuAddr2[1] = (spuAddr2[1] & 0xF0000) | (val & 0xFFFF);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUdata:
+      spuMem[spuAddr2[0]] = val;
+      spuAddr2[0]++;
+      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUdata:
+      spuMem[spuAddr2[1]] = val;
+      spuAddr2[1]++;
+      if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_ATTR:
+      spuCtrl2[0]=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_ATTR:
+      spuCtrl2[1]=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUstat:
+      spuStat2[0]=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUstat:
+      spuStat2[1]=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_ReverbAddr_Hi:
+      spuRvbAddr2[0] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[0]&0xFFFF);
+      SetReverbAddr(0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_ReverbAddr_Lo:
+      spuRvbAddr2[0] = (spuRvbAddr2[0] & 0xF0000) | (val & 0xFFFF);
+      SetReverbAddr(0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_ReverbAEnd_Hi:
+      spuRvbAEnd2[0] = (((unsigned long)val&0xf)<<16)|(/*spuRvbAEnd2[0]&*/0xFFFF);
+      rvb[0].EndAddr=spuRvbAEnd2[0];
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_ReverbAEnd_Hi:
+      spuRvbAEnd2[1] = (((unsigned long)val&0xf)<<16)|(/*spuRvbAEnd2[1]&*/0xFFFF);
+      rvb[1].EndAddr=spuRvbAEnd2[1];
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_ReverbAddr_Hi:
+      spuRvbAddr2[1] = (((unsigned long)val&0xf)<<16)|(spuRvbAddr2[1]&0xFFFF);
+      SetReverbAddr(1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_ReverbAddr_Lo:
+      spuRvbAddr2[1] = (spuRvbAddr2[1] & 0xF0000) | (val & 0xFFFF);
+      SetReverbAddr(1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUirqAddr_Hi:
+      spuIrq2[0] = (((unsigned long)val&0xf)<<16)|(spuIrq2[0]&0xFFFF);
+      pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUirqAddr_Lo:
+      spuIrq2[0] = (spuIrq2[0] & 0xF0000) | (val & 0xFFFF);
+      pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUirqAddr_Hi:
+      spuIrq2[1] = (((unsigned long)val&0xf)<<16)|(spuIrq2[1]&0xFFFF);
+      pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUirqAddr_Lo:
+      spuIrq2[1] = (spuIrq2[1] & 0xF0000) | (val & 0xFFFF);
+      pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUrvolL:
+      rvb[0].VolLeft=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUrvolR:
+      rvb[0].VolRight=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUrvolL:
+      rvb[1].VolLeft=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUrvolR:
+      rvb[1].VolRight=val;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUon1:
+      SoundOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUon2:
+      SoundOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUon1:
+      SoundOn(24,40,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUon2:
+      SoundOn(40,48,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUoff1:
+      SoundOff(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUoff2:
+      SoundOff(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUoff1:
+      SoundOff(24,40,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUoff2:
+      SoundOff(40,48,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_SPUend1:
+    case PS2_C0_SPUend2:
+      if(val) dwEndChannel2[0]=0;
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_SPUend1:
+    case PS2_C1_SPUend2:
+      if(val) dwEndChannel2[1]=0;
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_FMod1:
+      FModOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_FMod2:
+      FModOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_FMod1:
+      FModOn(24,40,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_FMod2:
+      FModOn(40,48,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_Noise1:
+      NoiseOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_Noise2:
+      NoiseOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_Noise1:
+      NoiseOn(24,40,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_Noise2:
+      NoiseOn(40,48,val);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_DryL1:
+      VolumeOn(0,16,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_DryL2:
+      VolumeOn(16,24,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_DryL1:
+      VolumeOn(24,40,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_DryL2:
+      VolumeOn(40,48,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_DryR1:
+      VolumeOn(0,16,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_DryR2:
+      VolumeOn(16,24,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_DryR1:
+      VolumeOn(24,40,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_DryR2:
+      VolumeOn(40,48,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_RVBon1_L:
+      ReverbOn(0,16,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_RVBon2_L:
+      ReverbOn(16,24,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_RVBon1_L:
+      ReverbOn(24,40,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_RVBon2_L:
+      ReverbOn(40,48,val,0);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_RVBon1_R:
+      ReverbOn(0,16,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_RVBon2_R:
+      ReverbOn(16,24,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_RVBon1_R:
+      ReverbOn(24,40,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C1_RVBon2_R:
+      ReverbOn(40,48,val,1);
+      break;
+    //-------------------------------------------------//
+    case PS2_C0_Reverb+0:
+      rvb[0].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_A&0xFFFF);
+      break;
+    case PS2_C0_Reverb+2:
+      rvb[0].FB_SRC_A=(rvb[0].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+4:
+      rvb[0].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[0].FB_SRC_B&0xFFFF);
+      break;
+    case PS2_C0_Reverb+6:
+      rvb[0].FB_SRC_B=(rvb[0].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+8:
+      rvb[0].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+10:
+      rvb[0].IIR_DEST_A0=(rvb[0].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+12:
+      rvb[0].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_A1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+14:
+      rvb[0].IIR_DEST_A1=(rvb[0].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+16:
+      rvb[0].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+18:
+      rvb[0].ACC_SRC_A0=(rvb[0].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+20:
+      rvb[0].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_A1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+22:
+      rvb[0].ACC_SRC_A1=(rvb[0].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+24:
+      rvb[0].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+26:
+      rvb[0].ACC_SRC_B0=(rvb[0].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+28:
+      rvb[0].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_B1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+30:
+      rvb[0].ACC_SRC_B1=(rvb[0].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+32:
+      rvb[0].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+34:
+      rvb[0].IIR_SRC_A0=(rvb[0].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+36:
+      rvb[0].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_A1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+38:
+      rvb[0].IIR_SRC_A1=(rvb[0].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+40:
+      rvb[0].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+42:
+      rvb[0].IIR_DEST_B0=(rvb[0].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+44:
+      rvb[0].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_DEST_B1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+46:
+      rvb[0].IIR_DEST_B1=(rvb[0].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+48:
+      rvb[0].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+50:
+      rvb[0].ACC_SRC_C0=(rvb[0].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+52:
+      rvb[0].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_C1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+54:
+      rvb[0].ACC_SRC_C1=(rvb[0].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+56:
+      rvb[0].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+58:
+      rvb[0].ACC_SRC_D0=(rvb[0].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+60:
+      rvb[0].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[0].ACC_SRC_D1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+62:
+      rvb[0].ACC_SRC_D1=(rvb[0].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+64:
+      rvb[0].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+66:
+      rvb[0].IIR_SRC_B1=(rvb[0].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+68:
+      rvb[0].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].IIR_SRC_B0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+70:
+      rvb[0].IIR_SRC_B0=(rvb[0].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+72:
+      rvb[0].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+74:
+      rvb[0].MIX_DEST_A0=(rvb[0].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+76:
+      rvb[0].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_A1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+78:
+      rvb[0].MIX_DEST_A1=(rvb[0].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+80:
+      rvb[0].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B0&0xFFFF);
+      break;
+    case PS2_C0_Reverb+82:
+      rvb[0].MIX_DEST_B0=(rvb[0].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_Reverb+84:
+      rvb[0].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[0].MIX_DEST_B1&0xFFFF);
+      break;
+    case PS2_C0_Reverb+86:
+      rvb[0].MIX_DEST_B1=(rvb[0].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C0_ReverbX+0:  rvb[0].IIR_ALPHA=(short)val;      break;
+    case PS2_C0_ReverbX+2:  rvb[0].ACC_COEF_A=(short)val;     break;
+    case PS2_C0_ReverbX+4:  rvb[0].ACC_COEF_B=(short)val;     break;
+    case PS2_C0_ReverbX+6:  rvb[0].ACC_COEF_C=(short)val;     break;
+    case PS2_C0_ReverbX+8:  rvb[0].ACC_COEF_D=(short)val;     break;
+    case PS2_C0_ReverbX+10: rvb[0].IIR_COEF=(short)val;       break;
+    case PS2_C0_ReverbX+12: rvb[0].FB_ALPHA=(short)val;       break;
+    case PS2_C0_ReverbX+14: rvb[0].FB_X=(short)val;           break;
+    case PS2_C0_ReverbX+16: rvb[0].IN_COEF_L=(short)val;      break;
+    case PS2_C0_ReverbX+18: rvb[0].IN_COEF_R=(short)val;      break;
+    //-------------------------------------------------//
+    case PS2_C1_Reverb+0:
+      rvb[1].FB_SRC_A=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_A&0xFFFF);
+      break;
+    case PS2_C1_Reverb+2:
+      rvb[1].FB_SRC_A=(rvb[1].FB_SRC_A & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+4:
+      rvb[1].FB_SRC_B=(((unsigned long)val&0xf)<<16)|(rvb[1].FB_SRC_B&0xFFFF);
+      break;
+    case PS2_C1_Reverb+6:
+      rvb[1].FB_SRC_B=(rvb[1].FB_SRC_B & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+8:
+      rvb[1].IIR_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+10:
+      rvb[1].IIR_DEST_A0=(rvb[1].IIR_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+12:
+      rvb[1].IIR_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_A1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+14:
+      rvb[1].IIR_DEST_A1=(rvb[1].IIR_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+16:
+      rvb[1].ACC_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+18:
+      rvb[1].ACC_SRC_A0=(rvb[1].ACC_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+20:
+      rvb[1].ACC_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_A1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+22:
+      rvb[1].ACC_SRC_A1=(rvb[1].ACC_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+24:
+      rvb[1].ACC_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+26:
+      rvb[1].ACC_SRC_B0=(rvb[1].ACC_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+28:
+      rvb[1].ACC_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_B1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+30:
+      rvb[1].ACC_SRC_B1=(rvb[1].ACC_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+32:
+      rvb[1].IIR_SRC_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+34:
+      rvb[1].IIR_SRC_A0=(rvb[1].IIR_SRC_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+36:
+      rvb[1].IIR_SRC_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_A1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+38:
+      rvb[1].IIR_SRC_A1=(rvb[1].IIR_SRC_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+40:
+      rvb[1].IIR_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+42:
+      rvb[1].IIR_DEST_B0=(rvb[1].IIR_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+44:
+      rvb[1].IIR_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_DEST_B1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+46:
+      rvb[1].IIR_DEST_B1=(rvb[1].IIR_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+48:
+      rvb[1].ACC_SRC_C0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+50:
+      rvb[1].ACC_SRC_C0=(rvb[1].ACC_SRC_C0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+52:
+      rvb[1].ACC_SRC_C1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_C1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+54:
+      rvb[1].ACC_SRC_C1=(rvb[1].ACC_SRC_C1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+56:
+      rvb[1].ACC_SRC_D0=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+58:
+      rvb[1].ACC_SRC_D0=(rvb[1].ACC_SRC_D0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+60:
+      rvb[1].ACC_SRC_D1=(((unsigned long)val&0xf)<<16)|(rvb[1].ACC_SRC_D1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+62:
+      rvb[1].ACC_SRC_D1=(rvb[1].ACC_SRC_D1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+64:
+      rvb[1].IIR_SRC_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+66:
+      rvb[1].IIR_SRC_B1=(rvb[1].IIR_SRC_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+68:
+      rvb[1].IIR_SRC_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].IIR_SRC_B0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+70:
+      rvb[1].IIR_SRC_B0=(rvb[1].IIR_SRC_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+72:
+      rvb[1].MIX_DEST_A0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+74:
+      rvb[1].MIX_DEST_A0=(rvb[1].MIX_DEST_A0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+76:
+      rvb[1].MIX_DEST_A1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_A1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+78:
+      rvb[1].MIX_DEST_A1=(rvb[1].MIX_DEST_A1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+80:
+      rvb[1].MIX_DEST_B0=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B0&0xFFFF);
+      break;
+    case PS2_C1_Reverb+82:
+      rvb[1].MIX_DEST_B0=(rvb[1].MIX_DEST_B0 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_Reverb+84:
+      rvb[1].MIX_DEST_B1=(((unsigned long)val&0xf)<<16)|(rvb[1].MIX_DEST_B1&0xFFFF);
+      break;
+    case PS2_C1_Reverb+86:
+      rvb[1].MIX_DEST_B1=(rvb[1].MIX_DEST_B1 & 0xF0000) | ((val) & 0xFFFF);
+      break;
+    case PS2_C1_ReverbX+0:  rvb[1].IIR_ALPHA=(short)val;      break;
+    case PS2_C1_ReverbX+2:  rvb[1].ACC_COEF_A=(short)val;     break;
+    case PS2_C1_ReverbX+4:  rvb[1].ACC_COEF_B=(short)val;     break;
+    case PS2_C1_ReverbX+6:  rvb[1].ACC_COEF_C=(short)val;     break;
+    case PS2_C1_ReverbX+8:  rvb[1].ACC_COEF_D=(short)val;     break;
+    case PS2_C1_ReverbX+10: rvb[1].IIR_COEF=(short)val;       break;
+    case PS2_C1_ReverbX+12: rvb[1].FB_ALPHA=(short)val;       break;
+    case PS2_C1_ReverbX+14: rvb[1].FB_X=(short)val;           break;
+    case PS2_C1_ReverbX+16: rvb[1].IN_COEF_L=(short)val;      break;
+    case PS2_C1_ReverbX+18: rvb[1].IN_COEF_R=(short)val;      break;
+   }
+
+ iSpuAsyncWait=0;
+
+}
+
+////////////////////////////////////////////////////////////////////////
+// READ REGISTER: called by main emu
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg)
+{
+ long r=reg&0xffff;
+
+#ifdef _WINDOWS
+// if(iDebugMode==1) logprintf("R_REG %X\r\n",reg&0xFFFF);
+#endif
+
+ iSpuAsyncWait=0;
+
+ if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580))  // some channel info?
+  {
+   switch(r&0x0f)
+    {
+     //------------------------------------------------// env value
+     case 10:
+      {
+       int ch=(r>>4)&0x1f;
+       if(r>=0x400) ch+=24;
+       if(s_chan[ch].bNew) return 1;                   // we are started, but not processed? return 1
+       if(s_chan[ch].ADSRX.lVolume &&                  // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
+          !s_chan[ch].ADSRX.EnvelopeVol)
+        return 1;
+       return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16);
+      }break;
+    }
+  }
+
+ if((r>=0x01c0 && r<0x02E0)||(r>=0x05c0 && r<0x06E0))  // some channel info?
+  {
+   int ch=0;unsigned long rx=r;
+   if(rx>=0x400) {ch=24;rx-=0x400;}
+
+   ch+=(rx-0x1c0)/12;
+   rx-=(ch%24)*12;
+
+   switch(rx)
+    {
+     //------------------------------------------------//
+     case 0x1C4:
+      return (((s_chan[ch].pLoop-spuMemC)>>17)&0xF);
+      break;
+     case 0x1C6:
+      return (((s_chan[ch].pLoop-spuMemC)>>1)&0xFFFF);
+      break;
+     //------------------------------------------------//
+     case 0x1C8:
+      return (((s_chan[ch].pCurr-spuMemC)>>17)&0xF);
+      break;
+     case 0x1CA:
+      return (((s_chan[ch].pCurr-spuMemC)>>1)&0xFFFF);
+      break;
+     //------------------------------------------------//
+    }
+  }
+
+ switch(r)
+  {
+   //--------------------------------------------------//
+   case PS2_C0_SPUend1:
+     return (unsigned short)((dwEndChannel2[0]&0xFFFF));
+   case PS2_C0_SPUend2:
+     return (unsigned short)((dwEndChannel2[0]>>16));
+   //--------------------------------------------------//
+   case PS2_C1_SPUend1:
+     return (unsigned short)((dwEndChannel2[1]&0xFFFF));
+   case PS2_C1_SPUend2:
+     return (unsigned short)((dwEndChannel2[1]>>16));
+   //--------------------------------------------------//
+   case PS2_C0_ATTR:
+     return spuCtrl2[0];
+     break;
+   //--------------------------------------------------//
+   case PS2_C1_ATTR:
+     return spuCtrl2[1];
+     break;
+   //--------------------------------------------------//
+   case PS2_C0_SPUstat:
+     return spuStat2[0];
+     break;
+   //--------------------------------------------------//
+   case PS2_C1_SPUstat:
+     return spuStat2[1];
+     break;
+   //--------------------------------------------------//
+   case PS2_C0_SPUdata:
+     {
+      unsigned short s=spuMem[spuAddr2[0]];
+      spuAddr2[0]++;
+      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
+      return s;
+     }
+   //--------------------------------------------------//
+   case PS2_C1_SPUdata:
+     {
+      unsigned short s=spuMem[spuAddr2[1]];
+      spuAddr2[1]++;
+      if(spuAddr2[1]>0xfffff) spuAddr2[1]=0;
+      return s;
+     }
+   //--------------------------------------------------//
+   case PS2_C0_SPUaddr_Hi:
+     return (unsigned short)((spuAddr2[0]>>16)&0xF);
+     break;
+   case PS2_C0_SPUaddr_Lo:
+     return (unsigned short)((spuAddr2[0]&0xFFFF));
+     break;
+   //--------------------------------------------------//
+   case PS2_C1_SPUaddr_Hi:
+     return (unsigned short)((spuAddr2[1]>>16)&0xF);
+     break;
+   case PS2_C1_SPUaddr_Lo:
+     return (unsigned short)((spuAddr2[1]&0xFFFF));
+     break;
+   //--------------------------------------------------//
+  }
+
+ return regArea[r>>1];
+}
+
+EXPORT_GCC void CALLBACK SPU2writePS1Port(unsigned long reg, unsigned short val)
+{
+ const u32 r=reg&0xfff;
+
+ if(r>=0xc00 && r<0xd80)	// channel info
+ {
+ 	SPU2write(r-0xc00, val);
+ 	return;
+ }
+
+ switch(r)
+   {
+    //-------------------------------------------------//
+    case H_SPUaddr:
+      spuAddr2[0] = (u32) val<<2;
+      break;
+    //-------------------------------------------------//
+    case H_SPUdata:
+      spuMem[spuAddr2[0]] = BFLIP16(val);
+      spuAddr2[0]++;
+      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
+      break;
+    //-------------------------------------------------//
+    case H_SPUctrl:
+//      spuCtrl=val;
+      break;
+    //-------------------------------------------------//
+    case H_SPUstat:
+      spuStat2[0]=val & 0xf800;
+      break;
+    //-------------------------------------------------//
+    case H_SPUReverbAddr:
+      spuRvbAddr2[0] = val;
+      SetReverbAddr(0);
+      break;
+    //-------------------------------------------------//
+    case H_SPUirqAddr:
+      spuIrq2[0] = val<<2;
+      pSpuIrq[0]=spuMemC+((u32) val<<1);
+      break;
+    //-------------------------------------------------//
+    /* Volume settings appear to be at least 15-bit unsigned in this case.
+       Definitely NOT 15-bit signed.  Probably 16-bit signed, so s16 type cast.
+       Check out "Chrono Cross:  Shadow's End Forest"
+    */
+    case H_SPUrvolL:
+      rvb[0].VolLeft=(s16)val;
+      //printf("%d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUrvolR:
+      rvb[0].VolRight=(s16)val;
+      //printf("%d\n",val);
+      break;
+    //-------------------------------------------------//
+
+/*
+    case H_ExtLeft:
+     //auxprintf("EL %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_ExtRight:
+     //auxprintf("ER %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUmvolL:
+     //auxprintf("ML %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUmvolR:
+     //auxprintf("MR %d\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUMute1:
+     //printf("M0 %04x\n",val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUMute2:
+    // printf("M1 %04x\n",val);
+      break;
+*/
+    //-------------------------------------------------//
+    case H_SPUon1:
+      SoundOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+     case H_SPUon2:
+      //printf("Boop: %08x: %04x\n",reg,val);
+      SoundOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUoff1:
+      SoundOff(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_SPUoff2:
+      SoundOff(16,24,val);
+	// printf("Boop: %08x: %04x\n",reg,val);
+      break;
+    //-------------------------------------------------//
+    case H_FMod1:
+      FModOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_FMod2:
+      FModOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_Noise1:
+      NoiseOn(0,16,val);
+      break;
+    //-------------------------------------------------//
+    case H_Noise2:
+      NoiseOn(16,24,val);
+      break;
+    //-------------------------------------------------//
+    case H_RVBon1:
+      ReverbOn(0,16,val,0);
+      break;
+
+    //-------------------------------------------------//
+    case H_RVBon2:
+      ReverbOn(16,24,val,0);
+      break;
+
+    //-------------------------------------------------//
+    case H_Reverb+0:
+      rvb[0].FB_SRC_A=val;
+      break;
+
+    case H_Reverb+2   : rvb[0].FB_SRC_B=(s16)val;       break;
+    case H_Reverb+4   : rvb[0].IIR_ALPHA=(s16)val;      break;
+    case H_Reverb+6   : rvb[0].ACC_COEF_A=(s16)val;     break;
+    case H_Reverb+8   : rvb[0].ACC_COEF_B=(s16)val;     break;
+    case H_Reverb+10  : rvb[0].ACC_COEF_C=(s16)val;     break;
+    case H_Reverb+12  : rvb[0].ACC_COEF_D=(s16)val;     break;
+    case H_Reverb+14  : rvb[0].IIR_COEF=(s16)val;       break;
+    case H_Reverb+16  : rvb[0].FB_ALPHA=(s16)val;       break;
+    case H_Reverb+18  : rvb[0].FB_X=(s16)val;           break;
+    case H_Reverb+20  : rvb[0].IIR_DEST_A0=(s16)val;    break;
+    case H_Reverb+22  : rvb[0].IIR_DEST_A1=(s16)val;    break;
+    case H_Reverb+24  : rvb[0].ACC_SRC_A0=(s16)val;     break;
+    case H_Reverb+26  : rvb[0].ACC_SRC_A1=(s16)val;     break;
+    case H_Reverb+28  : rvb[0].ACC_SRC_B0=(s16)val;     break;
+    case H_Reverb+30  : rvb[0].ACC_SRC_B1=(s16)val;     break;
+    case H_Reverb+32  : rvb[0].IIR_SRC_A0=(s16)val;     break;
+    case H_Reverb+34  : rvb[0].IIR_SRC_A1=(s16)val;     break;
+    case H_Reverb+36  : rvb[0].IIR_DEST_B0=(s16)val;    break;
+    case H_Reverb+38  : rvb[0].IIR_DEST_B1=(s16)val;    break;
+    case H_Reverb+40  : rvb[0].ACC_SRC_C0=(s16)val;     break;
+    case H_Reverb+42  : rvb[0].ACC_SRC_C1=(s16)val;     break;
+    case H_Reverb+44  : rvb[0].ACC_SRC_D0=(s16)val;     break;
+    case H_Reverb+46  : rvb[0].ACC_SRC_D1=(s16)val;     break;
+    case H_Reverb+48  : rvb[0].IIR_SRC_B1=(s16)val;     break;
+    case H_Reverb+50  : rvb[0].IIR_SRC_B0=(s16)val;     break;
+    case H_Reverb+52  : rvb[0].MIX_DEST_A0=(s16)val;    break;
+    case H_Reverb+54  : rvb[0].MIX_DEST_A1=(s16)val;    break;
+    case H_Reverb+56  : rvb[0].MIX_DEST_B0=(s16)val;    break;
+    case H_Reverb+58  : rvb[0].MIX_DEST_B1=(s16)val;    break;
+    case H_Reverb+60  : rvb[0].IN_COEF_L=(s16)val;      break;
+    case H_Reverb+62  : rvb[0].IN_COEF_R=(s16)val;      break;
+   }
+}
+
+EXPORT_GCC unsigned short CALLBACK SPU2readPS1Port(unsigned long reg)
+{
+ const u32 r=reg&0xfff;
+
+ if(r>=0x0c00 && r<0x0d80)
+  {
+  	return SPU2read(r-0xc00);
+  }
+
+ switch(r)
+  {
+//    case H_SPUctrl:
+//     return spuCtrl;
+     break;
+
+    case H_SPUstat:
+     return spuStat2[0];
+     break;
+
+    case H_SPUaddr:
+     return (u16)(spuAddr2[0]>>2);
+     break;
+
+    case H_SPUdata:
+     {
+      u16 s=BFLIP16(spuMem[spuAddr2[0]]);
+      spuAddr2[0]++;
+      if(spuAddr2[0]>0xfffff) spuAddr2[0]=0;
+      return s;
+     }
+     break;
+
+    case H_SPUirqAddr:
+     return spuIrq2[0]>>2;
+     break;
+  }
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND ON register write
+////////////////////////////////////////////////////////////////////////
+
+void SoundOn(int start,int end,unsigned short val)     // SOUND ON PSX COMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if((val&1) && s_chan[ch].pStart)                    // mmm... start has to be set before key on !?!
+    {
+     s_chan[ch].bIgnoreLoop=0;
+     s_chan[ch].bNew=1;
+     dwNewChannel2[ch/24]|=(1<<(ch%24));               // bitfield for faster testing
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// SOUND OFF register write
+////////////////////////////////////////////////////////////////////////
+
+void SoundOff(int start,int end,unsigned short val)    // SOUND OFF PSX COMMAND
+{
+ int ch;
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // && s_chan[i].bOn)  mmm...
+    {
+     s_chan[ch].bStop=1;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// FMOD register write
+////////////////////////////////////////////////////////////////////////
+
+void FModOn(int start,int end,unsigned short val)      // FMOD ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> fmod on/off
+    {
+     if(ch>0)
+      {
+       s_chan[ch].bFMod=1;                             // --> sound channel
+       s_chan[ch-1].bFMod=2;                           // --> freq channel
+      }
+    }
+   else
+    {
+     s_chan[ch].bFMod=0;                               // --> turn off fmod
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// NOISE register write
+////////////////////////////////////////////////////////////////////////
+
+void NoiseOn(int start,int end,unsigned short val)     // NOISE ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> noise on/off
+    {
+     s_chan[ch].bNoise=1;
+    }
+   else
+    {
+     s_chan[ch].bNoise=0;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// LEFT VOLUME register write
+////////////////////////////////////////////////////////////////////////
+
+// please note: sweep and phase invert are wrong... but I've never seen
+// them used
+
+void SetVolumeL(unsigned char ch,short vol)            // LEFT VOLUME
+{
+ s_chan[ch].iLeftVolRaw=vol;
+
+ if(vol&0x8000)                                        // sweep?
+  {
+   short sInc=1;                                       // -> sweep up?
+   if(vol&0x2000) sInc=-1;                             // -> or down?
+   if(vol&0x1000) vol^=0xffff;                         // -> mmm... phase inverted? have to investigate this
+   vol=((vol&0x7f)+1)/2;                               // -> sweep: 0..127 -> 0..64
+   vol+=vol/(2*sInc);                                  // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
+   vol*=128;
+  }
+ else                                                  // no sweep:
+  {
+   if(vol&0x4000)                                      // -> mmm... phase inverted? have to investigate this
+    //vol^=0xffff;
+    vol=0x3fff-(vol&0x3fff);
+  }
+
+ vol&=0x3fff;
+ s_chan[ch].iLeftVolume=vol;                           // store volume
+}
+
+////////////////////////////////////////////////////////////////////////
+// RIGHT VOLUME register write
+////////////////////////////////////////////////////////////////////////
+
+void SetVolumeR(unsigned char ch,short vol)            // RIGHT VOLUME
+{
+ s_chan[ch].iRightVolRaw=vol;
+
+ if(vol&0x8000)                                        // comments... see above :)
+  {
+   short sInc=1;
+   if(vol&0x2000) sInc=-1;
+   if(vol&0x1000) vol^=0xffff;
+   vol=((vol&0x7f)+1)/2;
+   vol+=vol/(2*sInc);
+   vol*=128;
+  }
+ else
+  {
+   if(vol&0x4000) //vol=vol^=0xffff;
+    vol=0x3fff-(vol&0x3fff);
+  }
+
+ vol&=0x3fff;
+ s_chan[ch].iRightVolume=vol;
+}
+
+////////////////////////////////////////////////////////////////////////
+// PITCH register write
+////////////////////////////////////////////////////////////////////////
+
+void SetPitch(int ch,unsigned short val)               // SET PITCH
+{
+ int NP;
+ double intr;
+
+ if(val>0x3fff) NP=0x3fff;                             // get pitch val
+ else           NP=val;
+
+ intr = (double)48000.0f / (double)44100.0f * (double)NP;
+ NP = (uint32_t)intr;
+
+ s_chan[ch].iRawPitch=NP;
+
+ NP=(44100L*NP)/4096L;                                 // calc frequency
+
+ if(NP<1) NP=1;                                        // some security
+ s_chan[ch].iActFreq=NP;                               // store frequency
+}
+
+////////////////////////////////////////////////////////////////////////
+// REVERB register write
+////////////////////////////////////////////////////////////////////////
+
+void ReverbOn(int start,int end,unsigned short val,int iRight)  // REVERB ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> reverb on/off
+    {
+     if(iRight) s_chan[ch].bReverbR=1;
+     else       s_chan[ch].bReverbL=1;
+    }
+   else
+    {
+     if(iRight) s_chan[ch].bReverbR=0;
+     else       s_chan[ch].bReverbL=0;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// REVERB START register write
+////////////////////////////////////////////////////////////////////////
+
+void SetReverbAddr(int core)
+{
+ long val=spuRvbAddr2[core];
+
+ if(rvb[core].StartAddr!=val)
+  {
+   if(val<=0x27ff)
+    {
+     rvb[core].StartAddr=rvb[core].CurrAddr=0;
+    }
+   else
+    {
+     rvb[core].StartAddr=val;
+     rvb[core].CurrAddr=rvb[core].StartAddr;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// DRY LEFT/RIGHT per voice switches
+////////////////////////////////////////////////////////////////////////
+
+void VolumeOn(int start,int end,unsigned short val,int iRight)  // VOLUME ON PSX COMMAND
+{
+ int ch;
+
+ for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
+  {
+   if(val&1)                                           // -> reverb on/off
+    {
+     if(iRight) s_chan[ch].bVolumeR=1;
+     else       s_chan[ch].bVolumeL=1;
+    }
+   else
+    {
+     if(iRight) s_chan[ch].bVolumeR=0;
+     else       s_chan[ch].bVolumeL=0;
+    }
+  }
+}
+
+
diff --git a/src/psf/peops2/reverb.c b/src/psf/peops2/reverb.c
deleted file mode 100644
index 068dc9575a3a..000000000000
--- a/src/psf/peops2/reverb.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/***************************************************************************
-                          reverb.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2004/04/04 - Pete
-// - changed to SPU2 functionality
-//
-// 2003/01/19 - Pete
-// - added Neill's reverb (see at the end of file)
-//
-// 2002/12/26 - Pete
-// - adjusted reverb handling
-//
-// 2002/08/14 - Pete
-// - added extra reverb
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_REVERB
-
-// will be included from spu.c
-#ifdef _IN_SPU
-
-////////////////////////////////////////////////////////////////////////
-// globals
-////////////////////////////////////////////////////////////////////////
-
-// REVERB info and timing vars...
-
-int *          sRVBPlay[2];
-int *          sRVBEnd[2];
-int *          sRVBStart[2];
-
-////////////////////////////////////////////////////////////////////////
-// START REVERB
-////////////////////////////////////////////////////////////////////////
-
-void StartREVERB(int ch)
-{
- int core=ch/24;
-
- if((s_chan[ch].bReverbL || s_chan[ch].bReverbR) && (spuCtrl2[core]&0x80))       // reverb possible?
-  {
-   if(iUseReverb==1) s_chan[ch].bRVBActive=1;
-  }
- else s_chan[ch].bRVBActive=0;                         // else -> no reverb
-}
-
-////////////////////////////////////////////////////////////////////////
-// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf
-////////////////////////////////////////////////////////////////////////
-
-static inline void InitREVERB(void)
-{
- if(iUseReverb==1)
-  {
-   memset(sRVBStart[0],0,NSSIZE*2*4);
-   memset(sRVBStart[1],0,NSSIZE*2*4);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// STORE REVERB
-////////////////////////////////////////////////////////////////////////
-
-void StoreREVERB(int ch,int ns)
-{
- int core=ch/24;
-
- if(iUseReverb==0) return;
- else
- if(iUseReverb==1) // -------------------------------- // Neil's reverb
-  {
-   const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume*s_chan[ch].bReverbL)/0x4000;
-   const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume*s_chan[ch].bReverbR)/0x4000;
-
-   ns<<=1;
-
-   *(sRVBStart[core]+ns)  +=iRxl;                      // -> we mix all active reverb channels into an extra buffer
-   *(sRVBStart[core]+ns+1)+=iRxr;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline int g_buffer(int iOff,int core)                   // get_buffer content helper: takes care about wraps
-{
- short * p=(short *)spuMem;
- iOff=(iOff)+rvb[core].CurrAddr;
- while(iOff>rvb[core].EndAddr)   iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
- while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
- return (int)*(p+iOff);
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline void s_buffer(int iOff,int iVal,int core)        // set_buffer content helper: takes care about wraps and clipping
-{
- short * p=(short *)spuMem;
- iOff=(iOff)+rvb[core].CurrAddr;
- while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
- while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(short)iVal;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-static inline void s_buffer1(int iOff,int iVal,int core)      // set_buffer (+1 sample) content helper: takes care about wraps and clipping
-{
- short * p=(short *)spuMem;
- iOff=(iOff)+rvb[core].CurrAddr+1;
- while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
- while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(short)iVal;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-int MixREVERBLeft(int ns,int core)
-{
- if(iUseReverb==1)
-  {
-   if(!rvb[core].StartAddr || !rvb[core].EndAddr ||
-      rvb[core].StartAddr>=rvb[core].EndAddr)          // reverb is off
-    {
-     rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
-     return 0;
-    }
-
-   rvb[core].iCnt++;
-
-   if(rvb[core].iCnt&1)                                // we work on every second left value: downsample to 22 khz
-    {
-     if((spuCtrl2[core]&0x80))                         // -> reverb on? oki
-      {
-       int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
-
-       const int INPUT_SAMPLE_L=*(sRVBStart[core]+(ns<<1));
-       const int INPUT_SAMPLE_R=*(sRVBStart[core]+(ns<<1)+1);
-
-       const int IIR_INPUT_A0 = (g_buffer(rvb[core].IIR_SRC_A0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
-       const int IIR_INPUT_A1 = (g_buffer(rvb[core].IIR_SRC_A1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
-       const int IIR_INPUT_B0 = (g_buffer(rvb[core].IIR_SRC_B0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
-       const int IIR_INPUT_B1 = (g_buffer(rvb[core].IIR_SRC_B1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
-
-       const int IIR_A0 = (IIR_INPUT_A0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
-       const int IIR_A1 = (IIR_INPUT_A1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
-       const int IIR_B0 = (IIR_INPUT_B0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
-       const int IIR_B1 = (IIR_INPUT_B1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
-
-       s_buffer1(rvb[core].IIR_DEST_A0, IIR_A0,core);
-       s_buffer1(rvb[core].IIR_DEST_A1, IIR_A1,core);
-       s_buffer1(rvb[core].IIR_DEST_B0, IIR_B0,core);
-       s_buffer1(rvb[core].IIR_DEST_B1, IIR_B1,core);
-
-       ACC0 = (g_buffer(rvb[core].ACC_SRC_A0,core) * rvb[core].ACC_COEF_A)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_B0,core) * rvb[core].ACC_COEF_B)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_C0,core) * rvb[core].ACC_COEF_C)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_D0,core) * rvb[core].ACC_COEF_D)/32768L;
-       ACC1 = (g_buffer(rvb[core].ACC_SRC_A1,core) * rvb[core].ACC_COEF_A)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_B1,core) * rvb[core].ACC_COEF_B)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_C1,core) * rvb[core].ACC_COEF_C)/32768L +
-              (g_buffer(rvb[core].ACC_SRC_D1,core) * rvb[core].ACC_COEF_D)/32768L;
-
-       FB_A0 = g_buffer(rvb[core].MIX_DEST_A0 - rvb[core].FB_SRC_A,core);
-       FB_A1 = g_buffer(rvb[core].MIX_DEST_A1 - rvb[core].FB_SRC_A,core);
-       FB_B0 = g_buffer(rvb[core].MIX_DEST_B0 - rvb[core].FB_SRC_B,core);
-       FB_B1 = g_buffer(rvb[core].MIX_DEST_B1 - rvb[core].FB_SRC_B,core);
-
-       s_buffer(rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * rvb[core].FB_ALPHA)/32768L,core);
-       s_buffer(rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * rvb[core].FB_ALPHA)/32768L,core);
-
-       s_buffer(rvb[core].MIX_DEST_B0, (rvb[core].FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb[core].FB_X)/32768L,core);
-       s_buffer(rvb[core].MIX_DEST_B1, (rvb[core].FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb[core].FB_X)/32768L,core);
-
-       rvb[core].iLastRVBLeft  = rvb[core].iRVBLeft;
-       rvb[core].iLastRVBRight = rvb[core].iRVBRight;
-
-       rvb[core].iRVBLeft  = (g_buffer(rvb[core].MIX_DEST_A0,core)+g_buffer(rvb[core].MIX_DEST_B0,core))/3;
-       rvb[core].iRVBRight = (g_buffer(rvb[core].MIX_DEST_A1,core)+g_buffer(rvb[core].MIX_DEST_B1,core))/3;
-
-       rvb[core].iRVBLeft  = (rvb[core].iRVBLeft  * rvb[core].VolLeft)  / 0x4000;
-       rvb[core].iRVBRight = (rvb[core].iRVBRight * rvb[core].VolRight) / 0x4000;
-
-       rvb[core].CurrAddr++;
-       if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
-
-       return rvb[core].iLastRVBLeft+(rvb[core].iRVBLeft-rvb[core].iLastRVBLeft)/2;
-      }
-     else                                              // -> reverb off
-      {
-       rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
-      }
-
-     rvb[core].CurrAddr++;
-     if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
-    }
-
-   return rvb[core].iLastRVBLeft;
-  }
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-int MixREVERBRight(int core)
-{
- if(iUseReverb==1)                                     // Neill's reverb:
-  {
-   int i=rvb[core].iLastRVBRight+(rvb[core].iRVBRight-rvb[core].iLastRVBRight)/2;
-   rvb[core].iLastRVBRight=rvb[core].iRVBRight;
-   return i;                                           // -> just return the last right reverb val (little bit scaled by the previous right val)
-  }
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-#endif
-
-/*
------------------------------------------------------------------------------
-PSX reverb hardware notes
-by Neill Corlett
------------------------------------------------------------------------------
-
-Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
-yadda yadda.
-
------------------------------------------------------------------------------
-
-Basics
-------
-
-- The reverb buffer is 22khz 16-bit mono PCM.
-- It starts at the reverb address given by 1DA2, extends to
-  the end of sound RAM, and wraps back to the 1DA2 address.
-
-Setting the address at 1DA2 resets the current reverb work address.
-
-This work address ALWAYS increments every 1/22050 sec., regardless of
-whether reverb is enabled (bit 7 of 1DAA set).
-
-And the contents of the reverb buffer ALWAYS play, scaled by the
-"reverberation depth left/right" volumes (1D84/1D86).
-(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
-
------------------------------------------------------------------------------
-
-Register names
---------------
-
-These are probably not their real names.
-These are probably not even correct names.
-We will use them anyway, because we can.
-
-1DC0: FB_SRC_A       (offset)
-1DC2: FB_SRC_B       (offset)
-1DC4: IIR_ALPHA      (coef.)
-1DC6: ACC_COEF_A     (coef.)
-1DC8: ACC_COEF_B     (coef.)
-1DCA: ACC_COEF_C     (coef.)
-1DCC: ACC_COEF_D     (coef.)
-1DCE: IIR_COEF       (coef.)
-1DD0: FB_ALPHA       (coef.)
-1DD2: FB_X           (coef.)
-1DD4: IIR_DEST_A0    (offset)
-1DD6: IIR_DEST_A1    (offset)
-1DD8: ACC_SRC_A0     (offset)
-1DDA: ACC_SRC_A1     (offset)
-1DDC: ACC_SRC_B0     (offset)
-1DDE: ACC_SRC_B1     (offset)
-1DE0: IIR_SRC_A0     (offset)
-1DE2: IIR_SRC_A1     (offset)
-1DE4: IIR_DEST_B0    (offset)
-1DE6: IIR_DEST_B1    (offset)
-1DE8: ACC_SRC_C0     (offset)
-1DEA: ACC_SRC_C1     (offset)
-1DEC: ACC_SRC_D0     (offset)
-1DEE: ACC_SRC_D1     (offset)
-1DF0: IIR_SRC_B1     (offset)
-1DF2: IIR_SRC_B0     (offset)
-1DF4: MIX_DEST_A0    (offset)
-1DF6: MIX_DEST_A1    (offset)
-1DF8: MIX_DEST_B0    (offset)
-1DFA: MIX_DEST_B1    (offset)
-1DFC: IN_COEF_L      (coef.)
-1DFE: IN_COEF_R      (coef.)
-
-The coefficients are signed fractional values.
--32768 would be -1.0
- 32768 would be  1.0 (if it were possible... the highest is of course 32767)
-
-The offsets are (byte/8) offsets into the reverb buffer.
-i.e. you multiply them by 8, you get byte offsets.
-You can also think of them as (samples/4) offsets.
-They appear to be signed.  They can be negative.
-None of the documented presets make them negative, though.
-
-Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.
-
------------------------------------------------------------------------------
-
-What it does
-------------
-
-We take all reverb sources:
-- regular channels that have the reverb bit on
-- cd and external sources, if their reverb bits are on
-and mix them into one stereo 44100hz signal.
-
-Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting
-algorithm here, but I haven't figured out the hysterically exact specifics.
-I use an 8-tap filter with these coefficients, which are nice but probably
-not the real ones:
-
-0.037828187894
-0.157538631280
-0.321159685278
-0.449322115345
-0.449322115345
-0.321159685278
-0.157538631280
-0.037828187894
-
-So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
-
-* IN MY EMULATION, I divide these by 2 to make it clip less.
-  (and of course the L/R output coefficients are adjusted to compensate)
-  The real thing appears to not do this.
-
-At every 22050hz tick:
-- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
-  steady-state algorithm described below
-- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
-  (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
-  L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
-  R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
-- Advance the current buffer position by 1 sample
-
-The wet out L and R are then upsampled to 44100hz and played at the
-"reverberation depth left/right" (1D84/1D86) volume, independent of the main
-volume.
-
------------------------------------------------------------------------------
-
-Reverb steady-state
--------------------
-
-The reverb steady-state algorithm is fairly clever, and of course by
-"clever" I mean "batshit insane".
-
-buffer[x] is relative to the current buffer position, not the beginning of
-the buffer.  Note that all buffer offsets must wrap around so they're
-contained within the reverb work area.
-
-Clipping is performed at the end... maybe also sooner, but definitely at
-the end.
-
-IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
-IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
-IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
-IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
-
-IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
-IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
-IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
-IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
-
-buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
-buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
-buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
-buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
-
-ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
-       buffer[ACC_SRC_B0] * ACC_COEF_B +
-       buffer[ACC_SRC_C0] * ACC_COEF_C +
-       buffer[ACC_SRC_D0] * ACC_COEF_D;
-ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
-       buffer[ACC_SRC_B1] * ACC_COEF_B +
-       buffer[ACC_SRC_C1] * ACC_COEF_C +
-       buffer[ACC_SRC_D1] * ACC_COEF_D;
-
-FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
-FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
-FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
-FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
-
-buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
-buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
-buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
-buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
-
------------------------------------------------------------------------------
-*/
-
diff --git a/src/psf/peops2/reverb.cc b/src/psf/peops2/reverb.cc
new file mode 100644
index 000000000000..068dc9575a3a
--- /dev/null
+++ b/src/psf/peops2/reverb.cc
@@ -0,0 +1,420 @@
+/***************************************************************************
+                          reverb.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2004/04/04 - Pete
+// - changed to SPU2 functionality
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb (see at the end of file)
+//
+// 2002/12/26 - Pete
+// - adjusted reverb handling
+//
+// 2002/08/14 - Pete
+// - added extra reverb
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_REVERB
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+// REVERB info and timing vars...
+
+int *          sRVBPlay[2];
+int *          sRVBEnd[2];
+int *          sRVBStart[2];
+
+////////////////////////////////////////////////////////////////////////
+// START REVERB
+////////////////////////////////////////////////////////////////////////
+
+void StartREVERB(int ch)
+{
+ int core=ch/24;
+
+ if((s_chan[ch].bReverbL || s_chan[ch].bReverbR) && (spuCtrl2[core]&0x80))       // reverb possible?
+  {
+   if(iUseReverb==1) s_chan[ch].bRVBActive=1;
+  }
+ else s_chan[ch].bRVBActive=0;                         // else -> no reverb
+}
+
+////////////////////////////////////////////////////////////////////////
+// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf
+////////////////////////////////////////////////////////////////////////
+
+static inline void InitREVERB(void)
+{
+ if(iUseReverb==1)
+  {
+   memset(sRVBStart[0],0,NSSIZE*2*4);
+   memset(sRVBStart[1],0,NSSIZE*2*4);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// STORE REVERB
+////////////////////////////////////////////////////////////////////////
+
+void StoreREVERB(int ch,int ns)
+{
+ int core=ch/24;
+
+ if(iUseReverb==0) return;
+ else
+ if(iUseReverb==1) // -------------------------------- // Neil's reverb
+  {
+   const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume*s_chan[ch].bReverbL)/0x4000;
+   const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume*s_chan[ch].bReverbR)/0x4000;
+
+   ns<<=1;
+
+   *(sRVBStart[core]+ns)  +=iRxl;                      // -> we mix all active reverb channels into an extra buffer
+   *(sRVBStart[core]+ns+1)+=iRxr;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline int g_buffer(int iOff,int core)                   // get_buffer content helper: takes care about wraps
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff)+rvb[core].CurrAddr;
+ while(iOff>rvb[core].EndAddr)   iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
+ while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
+ return (int)*(p+iOff);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline void s_buffer(int iOff,int iVal,int core)        // set_buffer content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff)+rvb[core].CurrAddr;
+ while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
+ while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+static inline void s_buffer1(int iOff,int iVal,int core)      // set_buffer (+1 sample) content helper: takes care about wraps and clipping
+{
+ short * p=(short *)spuMem;
+ iOff=(iOff)+rvb[core].CurrAddr+1;
+ while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1));
+ while(iOff<rvb[core].StartAddr) iOff=rvb[core].EndAddr-(rvb[core].StartAddr-iOff);
+ if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
+ *(p+iOff)=(short)iVal;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+int MixREVERBLeft(int ns,int core)
+{
+ if(iUseReverb==1)
+  {
+   if(!rvb[core].StartAddr || !rvb[core].EndAddr ||
+      rvb[core].StartAddr>=rvb[core].EndAddr)          // reverb is off
+    {
+     rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
+     return 0;
+    }
+
+   rvb[core].iCnt++;
+
+   if(rvb[core].iCnt&1)                                // we work on every second left value: downsample to 22 khz
+    {
+     if((spuCtrl2[core]&0x80))                         // -> reverb on? oki
+      {
+       int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
+
+       const int INPUT_SAMPLE_L=*(sRVBStart[core]+(ns<<1));
+       const int INPUT_SAMPLE_R=*(sRVBStart[core]+(ns<<1)+1);
+
+       const int IIR_INPUT_A0 = (g_buffer(rvb[core].IIR_SRC_A0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
+       const int IIR_INPUT_A1 = (g_buffer(rvb[core].IIR_SRC_A1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
+       const int IIR_INPUT_B0 = (g_buffer(rvb[core].IIR_SRC_B0,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/32768L;
+       const int IIR_INPUT_B1 = (g_buffer(rvb[core].IIR_SRC_B1,core) * rvb[core].IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/32768L;
+
+       const int IIR_A0 = (IIR_INPUT_A0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
+       const int IIR_A1 = (IIR_INPUT_A1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_A1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
+       const int IIR_B0 = (IIR_INPUT_B0 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B0,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
+       const int IIR_B1 = (IIR_INPUT_B1 * rvb[core].IIR_ALPHA)/32768L + (g_buffer(rvb[core].IIR_DEST_B1,core) * (32768L - rvb[core].IIR_ALPHA))/32768L;
+
+       s_buffer1(rvb[core].IIR_DEST_A0, IIR_A0,core);
+       s_buffer1(rvb[core].IIR_DEST_A1, IIR_A1,core);
+       s_buffer1(rvb[core].IIR_DEST_B0, IIR_B0,core);
+       s_buffer1(rvb[core].IIR_DEST_B1, IIR_B1,core);
+
+       ACC0 = (g_buffer(rvb[core].ACC_SRC_A0,core) * rvb[core].ACC_COEF_A)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_B0,core) * rvb[core].ACC_COEF_B)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_C0,core) * rvb[core].ACC_COEF_C)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_D0,core) * rvb[core].ACC_COEF_D)/32768L;
+       ACC1 = (g_buffer(rvb[core].ACC_SRC_A1,core) * rvb[core].ACC_COEF_A)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_B1,core) * rvb[core].ACC_COEF_B)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_C1,core) * rvb[core].ACC_COEF_C)/32768L +
+              (g_buffer(rvb[core].ACC_SRC_D1,core) * rvb[core].ACC_COEF_D)/32768L;
+
+       FB_A0 = g_buffer(rvb[core].MIX_DEST_A0 - rvb[core].FB_SRC_A,core);
+       FB_A1 = g_buffer(rvb[core].MIX_DEST_A1 - rvb[core].FB_SRC_A,core);
+       FB_B0 = g_buffer(rvb[core].MIX_DEST_B0 - rvb[core].FB_SRC_B,core);
+       FB_B1 = g_buffer(rvb[core].MIX_DEST_B1 - rvb[core].FB_SRC_B,core);
+
+       s_buffer(rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * rvb[core].FB_ALPHA)/32768L,core);
+       s_buffer(rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * rvb[core].FB_ALPHA)/32768L,core);
+
+       s_buffer(rvb[core].MIX_DEST_B0, (rvb[core].FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb[core].FB_X)/32768L,core);
+       s_buffer(rvb[core].MIX_DEST_B1, (rvb[core].FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb[core].FB_X)/32768L,core);
+
+       rvb[core].iLastRVBLeft  = rvb[core].iRVBLeft;
+       rvb[core].iLastRVBRight = rvb[core].iRVBRight;
+
+       rvb[core].iRVBLeft  = (g_buffer(rvb[core].MIX_DEST_A0,core)+g_buffer(rvb[core].MIX_DEST_B0,core))/3;
+       rvb[core].iRVBRight = (g_buffer(rvb[core].MIX_DEST_A1,core)+g_buffer(rvb[core].MIX_DEST_B1,core))/3;
+
+       rvb[core].iRVBLeft  = (rvb[core].iRVBLeft  * rvb[core].VolLeft)  / 0x4000;
+       rvb[core].iRVBRight = (rvb[core].iRVBRight * rvb[core].VolRight) / 0x4000;
+
+       rvb[core].CurrAddr++;
+       if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
+
+       return rvb[core].iLastRVBLeft+(rvb[core].iRVBLeft-rvb[core].iLastRVBLeft)/2;
+      }
+     else                                              // -> reverb off
+      {
+       rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
+      }
+
+     rvb[core].CurrAddr++;
+     if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
+    }
+
+   return rvb[core].iLastRVBLeft;
+  }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+int MixREVERBRight(int core)
+{
+ if(iUseReverb==1)                                     // Neill's reverb:
+  {
+   int i=rvb[core].iLastRVBRight+(rvb[core].iRVBRight-rvb[core].iLastRVBRight)/2;
+   rvb[core].iLastRVBRight=rvb[core].iRVBRight;
+   return i;                                           // -> just return the last right reverb val (little bit scaled by the previous right val)
+  }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+/*
+-----------------------------------------------------------------------------
+PSX reverb hardware notes
+by Neill Corlett
+-----------------------------------------------------------------------------
+
+Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
+yadda yadda.
+
+-----------------------------------------------------------------------------
+
+Basics
+------
+
+- The reverb buffer is 22khz 16-bit mono PCM.
+- It starts at the reverb address given by 1DA2, extends to
+  the end of sound RAM, and wraps back to the 1DA2 address.
+
+Setting the address at 1DA2 resets the current reverb work address.
+
+This work address ALWAYS increments every 1/22050 sec., regardless of
+whether reverb is enabled (bit 7 of 1DAA set).
+
+And the contents of the reverb buffer ALWAYS play, scaled by the
+"reverberation depth left/right" volumes (1D84/1D86).
+(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
+
+-----------------------------------------------------------------------------
+
+Register names
+--------------
+
+These are probably not their real names.
+These are probably not even correct names.
+We will use them anyway, because we can.
+
+1DC0: FB_SRC_A       (offset)
+1DC2: FB_SRC_B       (offset)
+1DC4: IIR_ALPHA      (coef.)
+1DC6: ACC_COEF_A     (coef.)
+1DC8: ACC_COEF_B     (coef.)
+1DCA: ACC_COEF_C     (coef.)
+1DCC: ACC_COEF_D     (coef.)
+1DCE: IIR_COEF       (coef.)
+1DD0: FB_ALPHA       (coef.)
+1DD2: FB_X           (coef.)
+1DD4: IIR_DEST_A0    (offset)
+1DD6: IIR_DEST_A1    (offset)
+1DD8: ACC_SRC_A0     (offset)
+1DDA: ACC_SRC_A1     (offset)
+1DDC: ACC_SRC_B0     (offset)
+1DDE: ACC_SRC_B1     (offset)
+1DE0: IIR_SRC_A0     (offset)
+1DE2: IIR_SRC_A1     (offset)
+1DE4: IIR_DEST_B0    (offset)
+1DE6: IIR_DEST_B1    (offset)
+1DE8: ACC_SRC_C0     (offset)
+1DEA: ACC_SRC_C1     (offset)
+1DEC: ACC_SRC_D0     (offset)
+1DEE: ACC_SRC_D1     (offset)
+1DF0: IIR_SRC_B1     (offset)
+1DF2: IIR_SRC_B0     (offset)
+1DF4: MIX_DEST_A0    (offset)
+1DF6: MIX_DEST_A1    (offset)
+1DF8: MIX_DEST_B0    (offset)
+1DFA: MIX_DEST_B1    (offset)
+1DFC: IN_COEF_L      (coef.)
+1DFE: IN_COEF_R      (coef.)
+
+The coefficients are signed fractional values.
+-32768 would be -1.0
+ 32768 would be  1.0 (if it were possible... the highest is of course 32767)
+
+The offsets are (byte/8) offsets into the reverb buffer.
+i.e. you multiply them by 8, you get byte offsets.
+You can also think of them as (samples/4) offsets.
+They appear to be signed.  They can be negative.
+None of the documented presets make them negative, though.
+
+Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.
+
+-----------------------------------------------------------------------------
+
+What it does
+------------
+
+We take all reverb sources:
+- regular channels that have the reverb bit on
+- cd and external sources, if their reverb bits are on
+and mix them into one stereo 44100hz signal.
+
+Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting
+algorithm here, but I haven't figured out the hysterically exact specifics.
+I use an 8-tap filter with these coefficients, which are nice but probably
+not the real ones:
+
+0.037828187894
+0.157538631280
+0.321159685278
+0.449322115345
+0.449322115345
+0.321159685278
+0.157538631280
+0.037828187894
+
+So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
+
+* IN MY EMULATION, I divide these by 2 to make it clip less.
+  (and of course the L/R output coefficients are adjusted to compensate)
+  The real thing appears to not do this.
+
+At every 22050hz tick:
+- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
+  steady-state algorithm described below
+- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
+  (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
+  L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
+  R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
+- Advance the current buffer position by 1 sample
+
+The wet out L and R are then upsampled to 44100hz and played at the
+"reverberation depth left/right" (1D84/1D86) volume, independent of the main
+volume.
+
+-----------------------------------------------------------------------------
+
+Reverb steady-state
+-------------------
+
+The reverb steady-state algorithm is fairly clever, and of course by
+"clever" I mean "batshit insane".
+
+buffer[x] is relative to the current buffer position, not the beginning of
+the buffer.  Note that all buffer offsets must wrap around so they're
+contained within the reverb work area.
+
+Clipping is performed at the end... maybe also sooner, but definitely at
+the end.
+
+IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
+IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
+
+IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
+IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
+IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
+IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
+
+buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
+buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
+buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
+buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
+
+ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
+       buffer[ACC_SRC_B0] * ACC_COEF_B +
+       buffer[ACC_SRC_C0] * ACC_COEF_C +
+       buffer[ACC_SRC_D0] * ACC_COEF_D;
+ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
+       buffer[ACC_SRC_B1] * ACC_COEF_B +
+       buffer[ACC_SRC_C1] * ACC_COEF_C +
+       buffer[ACC_SRC_D1] * ACC_COEF_D;
+
+FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
+FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
+FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
+FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
+
+buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
+buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
+buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
+buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
+
+-----------------------------------------------------------------------------
+*/
+
diff --git a/src/psf/peops2/spu.c b/src/psf/peops2/spu.c
deleted file mode 100644
index 958d5c0dfb22..000000000000
--- a/src/psf/peops2/spu.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-/***************************************************************************
-                            spu.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2005/08/29 - Pete
-// - changed to 48Khz output
-//
-// 2004/12/25 - Pete
-// - inc'd version for pcsx2-0.7
-//
-// 2004/04/18 - Pete
-// - changed all kind of things in the plugin
-//
-// 2004/04/04 - Pete
-// - changed plugin to emulate PS2 spu
-//
-// 2003/04/07 - Eric
-// - adjusted cubic interpolation algorithm
-//
-// 2003/03/16 - Eric
-// - added cubic interpolation
-//
-// 2003/03/01 - linuzappz
-// - libraryName changes using ALSA
-//
-// 2003/02/28 - Pete
-// - added option for type of interpolation
-// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile)
-// - added MONO support for MSWindows DirectSound
-//
-// 2003/02/20 - kode54
-// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault
-//
-// 2003/02/19 - kode54
-// - moved SPU IRQ handler and changed sample flag processing
-//
-// 2003/02/18 - kode54
-// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that
-//   ADSR timing is relative to the frequency at which a sample is played... I guess
-//   this remains to be seen, and I don't know whether ADSR is applied to noise channels...
-//
-// 2003/02/09 - kode54
-// - one-shot samples now process the end block before stopping
-// - in light of removing fmod hack, now processing ADSR on frequency channel as well
-//
-// 2003/02/08 - kode54
-// - replaced easy interpolation with gaussian
-// - removed fmod averaging hack
-// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :)
-//
-// 2003/02/08 - linuzappz
-// - small bugfix for one usleep that was 1 instead of 1000
-// - added iDisStereo for no stereo (Linux)
-//
-// 2003/01/22 - Pete
-// - added easy interpolation & small noise adjustments
-//
-// 2003/01/19 - Pete
-// - added Neill's reverb
-//
-// 2003/01/12 - Pete
-// - added recording window handlers
-//
-// 2003/01/06 - Pete
-// - added Neill's ADSR timings
-//
-// 2002/12/28 - Pete
-// - adjusted spu irq handling, fmod handling and loop handling
-//
-// 2002/08/14 - Pete
-// - added extra reverb
-//
-// 2002/06/08 - linuzappz
-// - SPUupdate changed for SPUasync
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_SPU
-
-#include "../peops2/externals.h"
-#include "../peops2/regs.h"
-#include "../peops2/dma.h"
-
-////////////////////////////////////////////////////////////////////////
-// globals
-////////////////////////////////////////////////////////////////////////
-
-// psx buffer / addresses
-
-unsigned short  regArea[32*1024];
-unsigned short  spuMem[1*1024*1024];
-unsigned char * spuMemC;
-unsigned char * pSpuIrq[2];
-unsigned char * pSpuBuffer;
-
-// user settings
-
-int             iUseXA=0;
-int             iXAPitch=1;
-int             iUseTimer=2;
-int             iSPUIRQWait=1;
-int             iDebugMode=0;
-int             iRecordMode=0;
-int             iUseReverb=1;
-int             iUseInterpolation=2;
-
-// MAIN infos struct for each channel
-
-SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
-REVERBInfo      rvb[2];
-
-unsigned long   dwNoiseVal=1;                          // global noise generator
-
-unsigned short  spuCtrl2[2];                           // some vars to store psx reg infos
-unsigned short  spuStat2[2];
-unsigned long   spuIrq2[2];
-unsigned long   spuAddr2[2];                           // address into spu mem
-unsigned long   spuRvbAddr2[2];
-unsigned long   spuRvbAEnd2[2];
-int             bEndThread=0;                          // thread handlers
-int             bThreadEnded=0;
-int             bSpuInit=0;
-int             bSPUIsOpen=0;
-
-unsigned long dwNewChannel2[2];                        // flags for faster testing, if new channel starts
-unsigned long dwEndChannel2[2];
-
-// UNUSED IN PS2 YET
-void (CALLBACK *irqCallback)(void)=0;                  // func of main emu, called on spu irq
-void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
-
-// certain globals (were local before, but with the new timeproc I need em global)
-
-const int f[5][2] = {   {    0,  0  },
-                        {   60,  0  },
-                        {  115, -52 },
-                        {   98, -55 },
-                        {  122, -60 } };
-int SSumR[NSSIZE];
-int SSumL[NSSIZE];
-int iCycle=0;
-short * pS;
-
-static int lastch=-1;      // last channel processed on spu irq in timer mode
-static int iSecureStart=0; // secure start counter
-
-extern void psf2_update(unsigned char *samples, long lBytes, void *data);
-
-////////////////////////////////////////////////////////////////////////
-// CODE AREA
-////////////////////////////////////////////////////////////////////////
-
-// dirty inline func includes
-
-#include "reverb.c"
-#include "adsr.c"
-
-////////////////////////////////////////////////////////////////////////
-// helpers for simple interpolation
-
-//
-// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm
-//
-// instead of having n equal sample values in a row like:
-//       ____
-//           |____
-//
-// we compare the current delta change with the next delta change.
-//
-// if curr_delta is positive,
-//
-//  - and next delta is smaller (or changing direction):
-//         \.
-//          -__
-//
-//  - and next delta significant (at least twice) bigger:
-//         --_
-//            \.
-//
-//  - and next delta is nearly same:
-//          \.
-//           \.
-//
-//
-// if curr_delta is negative,
-//
-//  - and next delta is smaller (or changing direction):
-//          _--
-//         /
-//
-//  - and next delta significant (at least twice) bigger:
-//            /
-//         __-
-//
-//  - and next delta is nearly same:
-//           /
-//          /
-//
-
-
-static inline void InterpolateUp(int ch)
-{
- if(s_chan[ch].SB[32]==1)                              // flag == 1? calc step and set flag... and don't change the value in this pass
-  {
-   const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29];  // curr delta to next val
-   const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30];  // and next delta to next-next val :)
-
-   s_chan[ch].SB[32]=0;
-
-   if(id1>0)                                           // curr delta positive
-    {
-     if(id2<id1)
-      {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
-     else
-     if(id2<(id1<<1))
-      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
-     else
-      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
-    }
-   else                                                // curr delta negative
-    {
-     if(id2>id1)
-      {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
-     else
-     if(id2>(id1<<1))
-      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
-     else
-      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
-    }
-  }
- else
- if(s_chan[ch].SB[32]==2)                              // flag 1: calc step and set flag... and don't change the value in this pass
-  {
-   s_chan[ch].SB[32]=0;
-
-   s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L;
-   if(s_chan[ch].sinc<=0x8000)
-        s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1));
-   else s_chan[ch].SB[29]+=s_chan[ch].SB[28];
-  }
- else                                                  // no flags? add bigger val (if possible), calc smaller step, set flag1
-  s_chan[ch].SB[29]+=s_chan[ch].SB[28];
-}
-
-//
-// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm
-//
-
-static inline void InterpolateDown(int ch)
-{
- if(s_chan[ch].sinc>=0x20000L)                                 // we would skip at least one val?
-  {
-   s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight
-   if(s_chan[ch].sinc>=0x30000L)                               // we would skip even more vals?
-    s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// helpers for gauss interpolation
-
-#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos])
-#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3])
-
-#include "gauss_i.h"
-
-////////////////////////////////////////////////////////////////////////
-
-//#include "xa.c"
-
-////////////////////////////////////////////////////////////////////////
-// START SOUND... called by main thread to setup a new sound on a channel
-////////////////////////////////////////////////////////////////////////
-
-static inline void StartSound(int ch)
-{
- dwNewChannel2[ch/24]&=~(1<<(ch%24));                  // clear new channel bit
- dwEndChannel2[ch/24]&=~(1<<(ch%24));                  // clear end channel bit
-
- StartADSR(ch);
- StartREVERB(ch);
-
- s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
-
- s_chan[ch].s_1=0;                                     // init mixing vars
- s_chan[ch].s_2=0;
- s_chan[ch].iSBPos=28;
-
- s_chan[ch].bNew=0;                                    // init channel flags
- s_chan[ch].bStop=0;
- s_chan[ch].bOn=1;
-
- s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
- s_chan[ch].SB[30]=0;
-
- if(iUseInterpolation>=2)                              // gauss interpolation?
-      {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;}  // -> start with more decoding
- else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;}  // -> no/simple interpolation starts with one 44100 decoding
-}
-
-////////////////////////////////////////////////////////////////////////
-// MAIN SPU FUNCTION
-// here is the main job handler... thread, timer or direct func call
-// basically the whole sound processing is done in this fat func!
-////////////////////////////////////////////////////////////////////////
-
-static u32 sampcount;
-static u32 decaybegin;
-static u32 decayend;
-
-static u32 seektime;
-int psf2_seek(u32 t)
-{
- seektime=t*441/10;
- if(seektime>sampcount) return(1);
- return(0);
-}
-
-// Counting to 65536 results in full volume offage.
-void setlength2(s32 stop, s32 fade)
-{
- seektime = 0;
- if(stop==~0)
- {
-  decaybegin=~0;
- }
- else
- {
-  stop=(stop*441)/10;
-  fade=(fade*441)/10;
-
-  decaybegin=stop;
-  decayend=stop+fade;
- }
-}
-// 5 ms waiting phase, if buffer is full and no new sound has to get started
-// .. can be made smaller (smallest val: 1 ms), but bigger waits give
-// better performance
-
-#define PAUSE_W 5
-#define PAUSE_L 5000
-
-////////////////////////////////////////////////////////////////////////
-
-int iSpuAsyncWait=0;
-
-static void *MAINThread(int samp2run, void *data)
-{
- int s_1,s_2,fa;
- unsigned char * start;unsigned int nSample;
- int ch,predict_nr,shift_factor,flags,d,d2,s;
- int gpos,bIRQReturn=0;
-
-// while(!bEndThread)                                    // until we are shutting down
-  {
-   //--------------------------------------------------//
-   // ok, at the beginning we are looking if there is
-   // enuff free place in the dsound/oss buffer to
-   // fill in new data, or if there is a new channel to start.
-   // if not, we wait (thread) or return (timer/spuasync)
-   // until enuff free place is available/a new channel gets
-   // started
-
-   if(dwNewChannel2[0] || dwNewChannel2[1])            // new channel should start immedately?
-    {                                                  // (at least one bit 0 ... MAXCHANNEL is set?)
-     iSecureStart++;                                   // -> set iSecure
-     if(iSecureStart>5) iSecureStart=0;                //    (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance)
-    }
-   else iSecureStart=0;                                // 0: no new channel should start
-
-/*	if (!iSecureStart)
-	{
-	     iSecureStart=0;                                   // reset secure
-	     return;
-	}*/
-
-#if 0
-   while(!iSecureStart && !bEndThread) // &&               // no new start? no thread end?
-//         (SoundGetBytesBuffered()>TESTSIZE))           // and still enuff data in sound buffer?
-    {
-     iSecureStart=0;                                   // reset secure
-
-     if(iUseTimer) return 0;                           // linux no-thread mode? bye
-
-     if(dwNewChannel2[0] || dwNewChannel2[1])
-      iSecureStart=1;                                  // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop
-    }
-#endif
-
-   //--------------------------------------------------// continue from irq handling in timer mode?
-
-   if(lastch>=0)                                       // will be -1 if no continue is pending
-    {
-     ch=lastch; lastch=-1;                  // -> setup all kind of vars to continue
-     goto GOON;                                        // -> directly jump to the continue point
-    }
-
-   //--------------------------------------------------//
-   //- main channel loop                              -//
-   //--------------------------------------------------//
-    {
-     for(ch=0;ch<MAXCHAN;ch++)                         // loop em all... we will collect 1 ms of sound of each playing channel
-      {
-       if(s_chan[ch].bNew) StartSound(ch);             // start new sound
-       if(!s_chan[ch].bOn) continue;                   // channel not playing? next
-
-       if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq)   // new psx frequency?
-        {
-         s_chan[ch].iUsedFreq=s_chan[ch].iActFreq;     // -> take it and calc steps
-         s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
-         if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
-         if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag
-        }
-//       ns=0;
-//       while(ns<NSSIZE)                                // loop until 1 ms of data is reached
-        {
-         while(s_chan[ch].spos>=0x10000L)
-          {
-           if(s_chan[ch].iSBPos==28)                   // 28 reached?
-            {
-             start=s_chan[ch].pCurr;                   // set up the current pos
-
-             if (start == (unsigned char*)-1)          // special "stop" sign
-              {
-               s_chan[ch].bOn=0;                       // -> turn everything off
-               s_chan[ch].ADSRX.lVolume=0;
-               s_chan[ch].ADSRX.EnvelopeVol=0;
-               goto ENDX;                              // -> and done for this channel
-              }
-
-             s_chan[ch].iSBPos=0;
-
-             //////////////////////////////////////////// spu irq handler here? mmm... do it later
-
-             s_1=s_chan[ch].s_1;
-             s_2=s_chan[ch].s_2;
-
-             predict_nr=(int)*start;start++;
-             shift_factor=predict_nr&0xf;
-             predict_nr >>= 4;
-             flags=(int)*start;start++;
-
-             // -------------------------------------- //
-
-             for (nSample=0;nSample<28;start++)
-              {
-               d=(int)*start;
-               s=((d&0xf)<<12);
-               if(s&0x8000) s|=0xffff0000;
-
-               fa=(s >> shift_factor);
-               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
-               s_2=s_1;s_1=fa;
-               s=((d & 0xf0) << 8);
-
-               s_chan[ch].SB[nSample++]=fa;
-
-               if(s&0x8000) s|=0xffff0000;
-               fa=(s>>shift_factor);
-               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
-               s_2=s_1;s_1=fa;
-
-               s_chan[ch].SB[nSample++]=fa;
-              }
-
-             //////////////////////////////////////////// irq check
-
-             if(spuCtrl2[ch/24]&0x40)                  // some irq active?
-              {
-               if((pSpuIrq[ch/24] >  start-16 &&       // irq address reached?
-                   pSpuIrq[ch/24] <= start) ||
-                  ((flags&1) &&                        // special: irq on looping addr, when stop/loop flag is set
-                   (pSpuIrq[ch/24] >  s_chan[ch].pLoop-16 &&
-                    pSpuIrq[ch/24] <= s_chan[ch].pLoop)))
-                {
-                 s_chan[ch].iIrqDone=1;                // -> debug flag
-
-                 if(irqCallback) irqCallback();        // -> call main emu (not supported in SPU2 right now)
-                 else
-                  {
-                   if(ch<24) InterruptDMA4();            // -> let's see what is happening if we call our irqs instead ;)
-                   else      InterruptDMA7();
-                  }
-
-                 if(iSPUIRQWait)                       // -> option: wait after irq for main emu
-                  {
-                   iSpuAsyncWait=1;
-                   bIRQReturn=1;
-                  }
-                }
-              }
-
-             //////////////////////////////////////////// flag handler
-
-             if((flags&4) && (!s_chan[ch].bIgnoreLoop))
-              s_chan[ch].pLoop=start-16;               // loop adress
-
-             if(flags&1)                               // 1: stop/loop
-              {
-               dwEndChannel2[ch/24]|=(1<<(ch%24));
-
-               // We play this block out first...
-               //if(!(flags&2)|| s_chan[ch].pLoop==NULL)
-                                                       // 1+2: do loop... otherwise: stop
-               if(flags!=3 || s_chan[ch].pLoop==NULL)  // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
-                {                                      // and checking if pLoop is set avoids crashes, yeah
-                 start = (unsigned char*)-1;
-                }
-               else
-                {
-                 start = s_chan[ch].pLoop;
-                }
-              }
-
-             s_chan[ch].pCurr=start;                   // store values for next cycle
-             s_chan[ch].s_1=s_1;
-             s_chan[ch].s_2=s_2;
-
-             ////////////////////////////////////////////
-
-             if(bIRQReturn)                            // special return for "spu irq - wait for cpu action"
-              {
-               bIRQReturn=0;
-                {
-                 lastch=ch;
-//                 lastns=ns;	// changemeback
-
-                 return NULL;
-                }
-              }
-
-             ////////////////////////////////////////////
-
-GOON: ;
-
-            }
-
-           fa=s_chan[ch].SB[s_chan[ch].iSBPos++];      // get sample data
-
-//           if((spuCtrl2[ch/24]&0x4000)==0) fa=0;       // muted?
-//           else                                        // else adjust
-            {
-             if(fa>32767L)  fa=32767L;
-             if(fa<-32767L) fa=-32767L;
-            }
-
-           if(iUseInterpolation>=2)                    // gauss/cubic interpolation
-            {
-             gpos = s_chan[ch].SB[28];
-             gval0 = fa;
-             gpos = (gpos+1) & 3;
-             s_chan[ch].SB[28] = gpos;
-            }
-           else
-           if(iUseInterpolation==1)                    // simple interpolation
-            {
-             s_chan[ch].SB[28] = 0;
-             s_chan[ch].SB[29] = s_chan[ch].SB[30];    // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour'
-             s_chan[ch].SB[30] = s_chan[ch].SB[31];
-             s_chan[ch].SB[31] = fa;
-             s_chan[ch].SB[32] = 1;                    // -> flag: calc new interolation
-            }
-           else s_chan[ch].SB[29]=fa;                  // no interpolation
-
-           s_chan[ch].spos -= 0x10000L;
-          }
-
-         ////////////////////////////////////////////////
-         // noise handler... just produces some noise data
-         // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
-         // and sometimes the noise will be used as fmod modulation... pfff
-
-         if(s_chan[ch].bNoise)
-          {
-           if((dwNoiseVal<<=1)&0x80000000L)
-            {
-             dwNoiseVal^=0x0040001L;
-             fa=((dwNoiseVal>>2)&0x7fff);
-             fa=-fa;
-            }
-           else fa=(dwNoiseVal>>2)&0x7fff;
-
-           // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
-           fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[ch/24]&0x3f00)>>9))+1));
-           if(fa>32767L)  fa=32767L;
-           if(fa<-32767L) fa=-32767L;
-           s_chan[ch].iOldNoise=fa;
-
-           if(iUseInterpolation<2)                     // no gauss/cubic interpolation?
-            s_chan[ch].SB[29] = fa;                    // -> store noise val in "current sample" slot
-          }                                            //----------------------------------------
-         else                                          // NO NOISE (NORMAL SAMPLE DATA) HERE
-          {//------------------------------------------//
-           if(iUseInterpolation==3)                    // cubic interpolation
-            {
-             long xd;
-             xd = ((s_chan[ch].spos) >> 1)+1;
-             gpos = s_chan[ch].SB[28];
-
-             fa  = gval(3) - 3*gval(2) + 3*gval(1) - gval0;
-             fa *= (xd - (2<<15)) / 6;
-             fa >>= 15;
-             fa += gval(2) - gval(1) - gval(1) + gval0;
-             fa *= (xd - (1<<15)) >> 1;
-             fa >>= 15;
-             fa += gval(1) - gval0;
-             fa *= xd;
-             fa >>= 15;
-             fa = fa + gval0;
-            }
-           //------------------------------------------//
-           else
-           if(iUseInterpolation==2)                    // gauss interpolation
-            {
-             int vl, vr;
-             vl = (s_chan[ch].spos >> 6) & ~3;
-             gpos = s_chan[ch].SB[28];
-             vr=(gauss[vl]*gval0)&~2047;
-             vr+=(gauss[vl+1]*gval(1))&~2047;
-             vr+=(gauss[vl+2]*gval(2))&~2047;
-             vr+=(gauss[vl+3]*gval(3))&~2047;
-             fa = vr>>11;
-/*
-             vr=(gauss[vl]*gval0)>>9;
-             vr+=(gauss[vl+1]*gval(1))>>9;
-             vr+=(gauss[vl+2]*gval(2))>>9;
-             vr+=(gauss[vl+3]*gval(3))>>9;
-             fa = vr>>2;
-*/
-            }
-           //------------------------------------------//
-           else
-           if(iUseInterpolation==1)                    // simple interpolation
-            {
-             if(s_chan[ch].sinc<0x10000L)              // -> upsampling?
-                  InterpolateUp(ch);                   // --> interpolate up
-             else InterpolateDown(ch);                 // --> else down
-             fa=s_chan[ch].SB[29];
-            }
-           //------------------------------------------//
-           else fa=s_chan[ch].SB[29];                  // no interpolation
-          }
-
-         s_chan[ch].sval = (MixADSR(ch) * fa) / 1023;  // add adsr
-
-         if(s_chan[ch].bFMod==2)                       // fmod freq channel
-          {
-           int NP=s_chan[ch+1].iRawPitch;
-           double intr;
-
-           NP=((32768L+s_chan[ch].sval)*NP)/32768L;    // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :)
-
-           if(NP>0x3fff) NP=0x3fff;
-           if(NP<0x1)    NP=0x1;
-
-	   intr = (double)48000.0f / (double)44100.0f * (double)NP;
-           NP = (uint32_t)intr;
-
-           NP=(44100L*NP)/(4096L);                     // calc frequency
-
-           s_chan[ch+1].iActFreq=NP;
-           s_chan[ch+1].iUsedFreq=NP;
-           s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
-           if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
-           if(iUseInterpolation==1)                    // freq change in sipmle interpolation mode
-            s_chan[ch+1].SB[32]=1;
-
-// mmmm... set up freq decoding positions?
-//           s_chan[ch+1].iSBPos=28;
-//           s_chan[ch+1].spos=0x10000L;
-          }
-         else
-          {
-           //////////////////////////////////////////////
-           // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
-
-           if(s_chan[ch].iMute)
-            s_chan[ch].sval=0;                         // debug mute
-           else
-            {
-             if(s_chan[ch].bVolumeL)
-              SSumL[0]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
-             if(s_chan[ch].bVolumeR)
-              SSumR[0]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
-            }
-
-           //////////////////////////////////////////////
-           // now let us store sound data for reverb
-
-           if(s_chan[ch].bRVBActive) StoreREVERB(ch,0);
-          }
-
-         ////////////////////////////////////////////////
-         // ok, go on until 1 ms data of this channel is collected
-
-         s_chan[ch].spos += s_chan[ch].sinc;
-
-        }
-ENDX:   ;
-      }
-    }
-
-  //---------------------------------------------------//
-  //- here we have another 1 ms of sound data
-  //---------------------------------------------------//
-
-  ///////////////////////////////////////////////////////
-  // mix all channels (including reverb) into one buffer
-
-    SSumL[0]+=MixREVERBLeft(0,0);
-    SSumL[0]+=MixREVERBLeft(0,1);
-    SSumR[0]+=MixREVERBRight(0);
-    SSumR[0]+=MixREVERBRight(1);
-
-    d=SSumL[0];SSumL[0]=0;
-    d2=SSumR[0];SSumR[0]=0;
-
-    if(d<-32767) d=-32767;if(d>32767) d=32767;
-    if(d2<-32767) d2=-32767;if(d2>32767) d2=32767;
-
-    if(sampcount>=decaybegin)
-    {
-	s32 dmul;
-	if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
-		      // for 13 hours?
-    	{
-		if(sampcount>=decayend)
-		{
-			psf2_update(NULL, 0, data);
-		        return(0);
-		}
-
-		dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
-		d=(d*dmul)>>8;
-		d2=(d2*dmul)>>8;
-	}
-    }
-    sampcount++;
-
-    *pS++=d;
-    *pS++=d2;
-
-    InitREVERB();
-
-  //////////////////////////////////////////////////////
-  // feed the sound
-  // wanna have around 1/60 sec (16.666 ms) updates
-	if (seektime != 0 && sampcount < seektime)
-	{
-		pS=(short *)pSpuBuffer;
-	}
-	else if ((((unsigned char *)pS)-((unsigned char *)pSpuBuffer)) == (735*4))
-	{
-		short *pSilenceIter = (short *)pSpuBuffer;
-		int iSilenceCount = 0;
-
-		for (; pSilenceIter < pS; pSilenceIter++)
-		{
-			if (*pSilenceIter == 0)
-				iSilenceCount++;
-
-			if (iSilenceCount > 20)
-				break;
-		}
-
-		if (iSilenceCount < 20)
-		    	psf2_update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer, data);
-
-	        pS=(short *)pSpuBuffer;
-	}
- }
-
- // end of big main loop...
-
- bThreadEnded=1;
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SPU ASYNC... even newer epsxe func
-//  1 time every 'cycle' cycles... harhar
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle, void *data)
-{
- if(iSpuAsyncWait)
-  {
-   iSpuAsyncWait++;
-   if(iSpuAsyncWait<=64) return;
-   iSpuAsyncWait=0;
-  }
- MAINThread(0, data);                                      // -> linux high-compat mode
-}
-
-////////////////////////////////////////////////////////////////////////
-// INIT/EXIT STUFF
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SPUINIT: this func will be called first by the main emu
-////////////////////////////////////////////////////////////////////////
-
-
-EXPORT_GCC long CALLBACK SPU2init(void)
-{
- spuMemC=(unsigned char *)spuMem;                      // just small setup
- memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
- memset(rvb,0,2*sizeof(REVERBInfo));
-
- sampcount = 0;
-
- InitADSR();
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SETUPTIMER: init of certain buffers and threads/timers
-////////////////////////////////////////////////////////////////////////
-
-static void SetupTimer(void)
-{
- memset(SSumR,0,NSSIZE*sizeof(int));                   // init some mixing buffers
- memset(SSumL,0,NSSIZE*sizeof(int));
- pS=(short *)pSpuBuffer;                               // setup soundbuffer pointer
-
- bEndThread=0;                                         // init thread vars
- bThreadEnded=0;
- bSpuInit=1;                                           // flag: we are inited
-}
-
-////////////////////////////////////////////////////////////////////////
-// REMOVETIMER: kill threads/timers
-////////////////////////////////////////////////////////////////////////
-
-static void RemoveTimer(void)
-{
- bEndThread=1;                                         // raise flag to end thread
- bThreadEnded=0;                                       // no more spu is running
- bSpuInit=0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SETUPSTREAMS: init most of the spu buffers
-////////////////////////////////////////////////////////////////////////
-
-static void SetupStreams(void)
-{
- int i;
-
- pSpuBuffer=(unsigned char *)malloc(32768);            // alloc mixing buffer
-
- i=NSSIZE*2;
-
- sRVBStart[0] = (int *)malloc(i*4);                    // alloc reverb buffer
- memset(sRVBStart[0],0,i*4);
- sRVBEnd[0]  = sRVBStart[0] + i;
- sRVBPlay[0] = sRVBStart[0];
- sRVBStart[1] = (int *)malloc(i*4);                    // alloc reverb buffer
- memset(sRVBStart[1],0,i*4);
- sRVBEnd[1]  = sRVBStart[1] + i;
- sRVBPlay[1] = sRVBStart[1];
-
- for(i=0;i<MAXCHAN;i++)                                // loop sound channels
-  {
-// we don't use mutex sync... not needed, would only
-// slow us down:
-//   s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL);
-   s_chan[i].ADSRX.SustainLevel = 1024;                // -> init sustain
-   s_chan[i].iMute=0;
-   s_chan[i].iIrqDone=0;
-   s_chan[i].pLoop=spuMemC;
-   s_chan[i].pStart=spuMemC;
-   s_chan[i].pCurr=spuMemC;
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// REMOVESTREAMS: free most buffer
-////////////////////////////////////////////////////////////////////////
-
-static void RemoveStreams(void)
-{
- free(pSpuBuffer);                                     // free mixing buffer
- pSpuBuffer=NULL;
- free(sRVBStart[0]);                                   // free reverb buffer
- sRVBStart[0]=0;
- free(sRVBStart[1]);                                   // free reverb buffer
- sRVBStart[1]=0;
-
-/*
- int i;
- for(i=0;i<MAXCHAN;i++)
-  {
-   WaitForSingleObject(s_chan[i].hMutex,2000);
-   ReleaseMutex(s_chan[i].hMutex);
-   if(s_chan[i].hMutex)
-    {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;}
-  }
-*/
-}
-
-
-////////////////////////////////////////////////////////////////////////
-// SPUOPEN: called by main emu after init
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC long CALLBACK SPU2open(void *pDsp)
-{
- if(bSPUIsOpen) return 0;                              // security for some stupid main emus
-
- iUseXA=0;                                             // just small setup
- bEndThread=0;
- bThreadEnded=0;
- spuMemC=(unsigned char *)spuMem;
- memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
- pSpuIrq[0]=0;
- pSpuIrq[1]=0;
- iSPUIRQWait=1;
- dwNewChannel2[0]=0;
- dwNewChannel2[1]=0;
- dwEndChannel2[0]=0;
- dwEndChannel2[1]=0;
- spuCtrl2[0]=0;
- spuCtrl2[1]=0;
- spuStat2[0]=0;
- spuStat2[1]=0;
- spuIrq2[0]=0;
- spuIrq2[1]=0;
- spuAddr2[0]=0xffffffff;
- spuAddr2[1]=0xffffffff;
- spuRvbAddr2[0]=0;
- spuRvbAddr2[1]=0;
- spuRvbAEnd2[0]=0;
- spuRvbAEnd2[1]=0;
-
-// ReadConfig();                                         // read user stuff
-
-// SetupSound();                                         // setup midas (before init!)
-
- SetupStreams();                                       // prepare streaming
-
- SetupTimer();                                         // timer for feeding data
-
- bSPUIsOpen=1;
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SPUCLOSE: called before shutdown
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2close(void)
-{
- if(!bSPUIsOpen) return;                               // some security
-
- bSPUIsOpen=0;                                         // no more open
-
- RemoveTimer();                                        // no more feeding
-
-// RemoveSound();                                        // no more sound handling
-
- RemoveStreams();                                      // no more streaming
-}
-
-////////////////////////////////////////////////////////////////////////
-// SPUSHUTDOWN: called by main emu on final exit
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC void CALLBACK SPU2shutdown(void)
-{
- return;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SPUTEST: we don't test, we are always fine ;)
-////////////////////////////////////////////////////////////////////////
-
-EXPORT_GCC long CALLBACK SPU2test(void)
-{
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// SETUP CALLBACKS
-// this functions will be called once,
-// passes a callback that should be called on SPU-IRQ/cdda volume change
-////////////////////////////////////////////////////////////////////////
-
-// not used yet
-EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void))
-{
- irqCallback = callback;
-}
-
-// not used yet
-EXPORT_GCC void CALLBACK SPU2registerCallback(void (CALLBACK *callback)(void))
-{
- irqCallback = callback;
-}
-
-// not used yet
-EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short))
-{
- cddavCallback = CDDAVcallback;
-}
diff --git a/src/psf/peops2/spu.cc b/src/psf/peops2/spu.cc
new file mode 100644
index 000000000000..b5d0b3bdbad5
--- /dev/null
+++ b/src/psf/peops2/spu.cc
@@ -0,0 +1,1034 @@
+/***************************************************************************
+                            spu.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2005/08/29 - Pete
+// - changed to 48Khz output
+//
+// 2004/12/25 - Pete
+// - inc'd version for pcsx2-0.7
+//
+// 2004/04/18 - Pete
+// - changed all kind of things in the plugin
+//
+// 2004/04/04 - Pete
+// - changed plugin to emulate PS2 spu
+//
+// 2003/04/07 - Eric
+// - adjusted cubic interpolation algorithm
+//
+// 2003/03/16 - Eric
+// - added cubic interpolation
+//
+// 2003/03/01 - linuzappz
+// - libraryName changes using ALSA
+//
+// 2003/02/28 - Pete
+// - added option for type of interpolation
+// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile)
+// - added MONO support for MSWindows DirectSound
+//
+// 2003/02/20 - kode54
+// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault
+//
+// 2003/02/19 - kode54
+// - moved SPU IRQ handler and changed sample flag processing
+//
+// 2003/02/18 - kode54
+// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that
+//   ADSR timing is relative to the frequency at which a sample is played... I guess
+//   this remains to be seen, and I don't know whether ADSR is applied to noise channels...
+//
+// 2003/02/09 - kode54
+// - one-shot samples now process the end block before stopping
+// - in light of removing fmod hack, now processing ADSR on frequency channel as well
+//
+// 2003/02/08 - kode54
+// - replaced easy interpolation with gaussian
+// - removed fmod averaging hack
+// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :)
+//
+// 2003/02/08 - linuzappz
+// - small bugfix for one usleep that was 1 instead of 1000
+// - added iDisStereo for no stereo (Linux)
+//
+// 2003/01/22 - Pete
+// - added easy interpolation & small noise adjustments
+//
+// 2003/01/19 - Pete
+// - added Neill's reverb
+//
+// 2003/01/12 - Pete
+// - added recording window handlers
+//
+// 2003/01/06 - Pete
+// - added Neill's ADSR timings
+//
+// 2002/12/28 - Pete
+// - adjusted spu irq handling, fmod handling and loop handling
+//
+// 2002/08/14 - Pete
+// - added extra reverb
+//
+// 2002/06/08 - linuzappz
+// - SPUupdate changed for SPUasync
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_SPU
+
+#include "../peops2/externals.h"
+#include "../peops2/regs.h"
+#include "../peops2/dma.h"
+
+////////////////////////////////////////////////////////////////////////
+// globals
+////////////////////////////////////////////////////////////////////////
+
+// psx buffer / addresses
+
+unsigned short  regArea[32*1024];
+unsigned short  spuMem[1*1024*1024];
+unsigned char * spuMemC;
+unsigned char * pSpuIrq[2];
+unsigned char * pSpuBuffer;
+
+// user settings
+
+int             iUseXA=0;
+int             iXAPitch=1;
+int             iUseTimer=2;
+int             iSPUIRQWait=1;
+int             iDebugMode=0;
+int             iRecordMode=0;
+int             iUseReverb=1;
+int             iUseInterpolation=2;
+
+// MAIN infos struct for each channel
+
+SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
+REVERBInfo      rvb[2];
+
+unsigned long   dwNoiseVal=1;                          // global noise generator
+
+unsigned short  spuCtrl2[2];                           // some vars to store psx reg infos
+unsigned short  spuStat2[2];
+unsigned long   spuIrq2[2];
+unsigned long   spuAddr2[2];                           // address into spu mem
+unsigned long   spuRvbAddr2[2];
+unsigned long   spuRvbAEnd2[2];
+int             bEndThread=0;                          // thread handlers
+int             bThreadEnded=0;
+int             bSpuInit=0;
+int             bSPUIsOpen=0;
+
+unsigned long dwNewChannel2[2];                        // flags for faster testing, if new channel starts
+unsigned long dwEndChannel2[2];
+
+// UNUSED IN PS2 YET
+void (CALLBACK *irqCallback)(void)=0;                  // func of main emu, called on spu irq
+void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
+
+// certain globals (were local before, but with the new timeproc I need em global)
+
+const int f[5][2] = {   {    0,  0  },
+                        {   60,  0  },
+                        {  115, -52 },
+                        {   98, -55 },
+                        {  122, -60 } };
+int SSumR[NSSIZE];
+int SSumL[NSSIZE];
+int iCycle=0;
+short * pS;
+
+static int lastch=-1;      // last channel processed on spu irq in timer mode
+static int iSecureStart=0; // secure start counter
+
+////////////////////////////////////////////////////////////////////////
+// CODE AREA
+////////////////////////////////////////////////////////////////////////
+
+// dirty inline func includes
+
+#include "reverb.cc"
+#include "adsr.cc"
+
+////////////////////////////////////////////////////////////////////////
+// helpers for simple interpolation
+
+//
+// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm
+//
+// instead of having n equal sample values in a row like:
+//       ____
+//           |____
+//
+// we compare the current delta change with the next delta change.
+//
+// if curr_delta is positive,
+//
+//  - and next delta is smaller (or changing direction):
+//         \.
+//          -__
+//
+//  - and next delta significant (at least twice) bigger:
+//         --_
+//            \.
+//
+//  - and next delta is nearly same:
+//          \.
+//           \.
+//
+//
+// if curr_delta is negative,
+//
+//  - and next delta is smaller (or changing direction):
+//          _--
+//         /
+//
+//  - and next delta significant (at least twice) bigger:
+//            /
+//         __-
+//
+//  - and next delta is nearly same:
+//           /
+//          /
+//
+
+
+static inline void InterpolateUp(int ch)
+{
+ if(s_chan[ch].SB[32]==1)                              // flag == 1? calc step and set flag... and don't change the value in this pass
+  {
+   const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29];  // curr delta to next val
+   const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30];  // and next delta to next-next val :)
+
+   s_chan[ch].SB[32]=0;
+
+   if(id1>0)                                           // curr delta positive
+    {
+     if(id2<id1)
+      {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
+     else
+     if(id2<(id1<<1))
+      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
+     else
+      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
+    }
+   else                                                // curr delta negative
+    {
+     if(id2>id1)
+      {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
+     else
+     if(id2>(id1<<1))
+      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
+     else
+      s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
+    }
+  }
+ else
+ if(s_chan[ch].SB[32]==2)                              // flag 1: calc step and set flag... and don't change the value in this pass
+  {
+   s_chan[ch].SB[32]=0;
+
+   s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L;
+   if(s_chan[ch].sinc<=0x8000)
+        s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1));
+   else s_chan[ch].SB[29]+=s_chan[ch].SB[28];
+  }
+ else                                                  // no flags? add bigger val (if possible), calc smaller step, set flag1
+  s_chan[ch].SB[29]+=s_chan[ch].SB[28];
+}
+
+//
+// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm
+//
+
+static inline void InterpolateDown(int ch)
+{
+ if(s_chan[ch].sinc>=0x20000L)                                 // we would skip at least one val?
+  {
+   s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight
+   if(s_chan[ch].sinc>=0x30000L)                               // we would skip even more vals?
+    s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// helpers for gauss interpolation
+
+#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos])
+#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3])
+
+#include "gauss_i.h"
+
+////////////////////////////////////////////////////////////////////////
+
+//#include "xa.c"
+
+////////////////////////////////////////////////////////////////////////
+// START SOUND... called by main thread to setup a new sound on a channel
+////////////////////////////////////////////////////////////////////////
+
+static inline void StartSound(int ch)
+{
+ dwNewChannel2[ch/24]&=~(1<<(ch%24));                  // clear new channel bit
+ dwEndChannel2[ch/24]&=~(1<<(ch%24));                  // clear end channel bit
+
+ StartADSR(ch);
+ StartREVERB(ch);
+
+ s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
+
+ s_chan[ch].s_1=0;                                     // init mixing vars
+ s_chan[ch].s_2=0;
+ s_chan[ch].iSBPos=28;
+
+ s_chan[ch].bNew=0;                                    // init channel flags
+ s_chan[ch].bStop=0;
+ s_chan[ch].bOn=1;
+
+ s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
+ s_chan[ch].SB[30]=0;
+
+ if(iUseInterpolation>=2)                              // gauss interpolation?
+      {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;}  // -> start with more decoding
+ else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;}  // -> no/simple interpolation starts with one 44100 decoding
+}
+
+////////////////////////////////////////////////////////////////////////
+// MAIN SPU FUNCTION
+// here is the main job handler... thread, timer or direct func call
+// basically the whole sound processing is done in this fat func!
+////////////////////////////////////////////////////////////////////////
+
+static u32 sampcount;
+static u32 decaybegin;
+static u32 decayend;
+
+static u32 seektime;
+int psf2_seek(u32 t)
+{
+ seektime=t*441/10;
+ if(seektime>sampcount) return(1);
+ return(0);
+}
+
+// Counting to 65536 results in full volume offage.
+void setlength2(s32 stop, s32 fade)
+{
+ seektime = 0;
+ if(stop==~0)
+ {
+  decaybegin=~0;
+ }
+ else
+ {
+  stop=(stop*441)/10;
+  fade=(fade*441)/10;
+
+  decaybegin=stop;
+  decayend=stop+fade;
+ }
+}
+// 5 ms waiting phase, if buffer is full and no new sound has to get started
+// .. can be made smaller (smallest val: 1 ms), but bigger waits give
+// better performance
+
+#define PAUSE_W 5
+#define PAUSE_L 5000
+
+////////////////////////////////////////////////////////////////////////
+
+int iSpuAsyncWait=0;
+
+static void *MAINThread(void (*update)(const void *, int))
+{
+ int s_1,s_2,fa;
+ unsigned char * start;unsigned int nSample;
+ int ch,predict_nr,shift_factor,flags,d,d2,s;
+ int gpos,bIRQReturn=0;
+
+// while(!bEndThread)                                    // until we are shutting down
+  {
+   //--------------------------------------------------//
+   // ok, at the beginning we are looking if there is
+   // enuff free place in the dsound/oss buffer to
+   // fill in new data, or if there is a new channel to start.
+   // if not, we wait (thread) or return (timer/spuasync)
+   // until enuff free place is available/a new channel gets
+   // started
+
+   if(dwNewChannel2[0] || dwNewChannel2[1])            // new channel should start immedately?
+    {                                                  // (at least one bit 0 ... MAXCHANNEL is set?)
+     iSecureStart++;                                   // -> set iSecure
+     if(iSecureStart>5) iSecureStart=0;                //    (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance)
+    }
+   else iSecureStart=0;                                // 0: no new channel should start
+
+/* if (!iSecureStart)
+    {
+     iSecureStart=0;                                   // reset secure
+     return;
+    }*/
+
+#if 0
+   while(!iSecureStart && !bEndThread) // &&               // no new start? no thread end?
+//         (SoundGetBytesBuffered()>TESTSIZE))           // and still enuff data in sound buffer?
+    {
+     iSecureStart=0;                                   // reset secure
+
+     if(iUseTimer) return 0;                           // linux no-thread mode? bye
+
+     if(dwNewChannel2[0] || dwNewChannel2[1])
+      iSecureStart=1;                                  // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop
+    }
+#endif
+
+   //--------------------------------------------------// continue from irq handling in timer mode?
+
+   if(lastch>=0)                                       // will be -1 if no continue is pending
+    {
+     ch=lastch; lastch=-1;                  // -> setup all kind of vars to continue
+     goto GOON;                                        // -> directly jump to the continue point
+    }
+
+   //--------------------------------------------------//
+   //- main channel loop                              -//
+   //--------------------------------------------------//
+    {
+     for(ch=0;ch<MAXCHAN;ch++)                         // loop em all... we will collect 1 ms of sound of each playing channel
+      {
+       if(s_chan[ch].bNew) StartSound(ch);             // start new sound
+       if(!s_chan[ch].bOn) continue;                   // channel not playing? next
+
+       if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq)   // new psx frequency?
+        {
+         s_chan[ch].iUsedFreq=s_chan[ch].iActFreq;     // -> take it and calc steps
+         s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
+         if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
+         if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag
+        }
+//       ns=0;
+//       while(ns<NSSIZE)                                // loop until 1 ms of data is reached
+        {
+         while(s_chan[ch].spos>=0x10000L)
+          {
+           if(s_chan[ch].iSBPos==28)                   // 28 reached?
+            {
+             start=s_chan[ch].pCurr;                   // set up the current pos
+
+             if (start == (unsigned char*)-1)          // special "stop" sign
+              {
+               s_chan[ch].bOn=0;                       // -> turn everything off
+               s_chan[ch].ADSRX.lVolume=0;
+               s_chan[ch].ADSRX.EnvelopeVol=0;
+               goto ENDX;                              // -> and done for this channel
+              }
+
+             s_chan[ch].iSBPos=0;
+
+             //////////////////////////////////////////// spu irq handler here? mmm... do it later
+
+             s_1=s_chan[ch].s_1;
+             s_2=s_chan[ch].s_2;
+
+             predict_nr=(int)*start;start++;
+             shift_factor=predict_nr&0xf;
+             predict_nr >>= 4;
+             flags=(int)*start;start++;
+
+             // -------------------------------------- //
+
+             for (nSample=0;nSample<28;start++)
+              {
+               d=(int)*start;
+               s=((d&0xf)<<12);
+               if(s&0x8000) s|=0xffff0000;
+
+               fa=(s >> shift_factor);
+               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
+               s_2=s_1;s_1=fa;
+               s=((d & 0xf0) << 8);
+
+               s_chan[ch].SB[nSample++]=fa;
+
+               if(s&0x8000) s|=0xffff0000;
+               fa=(s>>shift_factor);
+               fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
+               s_2=s_1;s_1=fa;
+
+               s_chan[ch].SB[nSample++]=fa;
+              }
+
+             //////////////////////////////////////////// irq check
+
+             if(spuCtrl2[ch/24]&0x40)                  // some irq active?
+              {
+               if((pSpuIrq[ch/24] >  start-16 &&       // irq address reached?
+                   pSpuIrq[ch/24] <= start) ||
+                  ((flags&1) &&                        // special: irq on looping addr, when stop/loop flag is set
+                   (pSpuIrq[ch/24] >  s_chan[ch].pLoop-16 &&
+                    pSpuIrq[ch/24] <= s_chan[ch].pLoop)))
+                {
+                 s_chan[ch].iIrqDone=1;                // -> debug flag
+
+                 if(irqCallback) irqCallback();        // -> call main emu (not supported in SPU2 right now)
+                 else
+                  {
+                   if(ch<24) InterruptDMA4();            // -> let's see what is happening if we call our irqs instead ;)
+                   else      InterruptDMA7();
+                  }
+
+                 if(iSPUIRQWait)                       // -> option: wait after irq for main emu
+                  {
+                   iSpuAsyncWait=1;
+                   bIRQReturn=1;
+                  }
+                }
+              }
+
+             //////////////////////////////////////////// flag handler
+
+             if((flags&4) && (!s_chan[ch].bIgnoreLoop))
+              s_chan[ch].pLoop=start-16;               // loop adress
+
+             if(flags&1)                               // 1: stop/loop
+              {
+               dwEndChannel2[ch/24]|=(1<<(ch%24));
+
+               // We play this block out first...
+               //if(!(flags&2)|| s_chan[ch].pLoop==nullptr)
+                                                       // 1+2: do loop... otherwise: stop
+               if(flags!=3 || s_chan[ch].pLoop==nullptr)  // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
+                {                                      // and checking if pLoop is set avoids crashes, yeah
+                 start = (unsigned char*)-1;
+                }
+               else
+                {
+                 start = s_chan[ch].pLoop;
+                }
+              }
+
+             s_chan[ch].pCurr=start;                   // store values for next cycle
+             s_chan[ch].s_1=s_1;
+             s_chan[ch].s_2=s_2;
+
+             ////////////////////////////////////////////
+
+             if(bIRQReturn)                            // special return for "spu irq - wait for cpu action"
+              {
+               bIRQReturn=0;
+                {
+                 lastch=ch;
+//                 lastns=ns;   // changemeback
+
+                 return nullptr;
+                }
+              }
+
+             ////////////////////////////////////////////
+
+GOON: ;
+
+            }
+
+           fa=s_chan[ch].SB[s_chan[ch].iSBPos++];      // get sample data
+
+//           if((spuCtrl2[ch/24]&0x4000)==0) fa=0;       // muted?
+//           else                                        // else adjust
+            {
+             if(fa>32767L)  fa=32767L;
+             if(fa<-32767L) fa=-32767L;
+            }
+
+           if(iUseInterpolation>=2)                    // gauss/cubic interpolation
+            {
+             gpos = s_chan[ch].SB[28];
+             gval0 = fa;
+             gpos = (gpos+1) & 3;
+             s_chan[ch].SB[28] = gpos;
+            }
+           else
+           if(iUseInterpolation==1)                    // simple interpolation
+            {
+             s_chan[ch].SB[28] = 0;
+             s_chan[ch].SB[29] = s_chan[ch].SB[30];    // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour'
+             s_chan[ch].SB[30] = s_chan[ch].SB[31];
+             s_chan[ch].SB[31] = fa;
+             s_chan[ch].SB[32] = 1;                    // -> flag: calc new interolation
+            }
+           else s_chan[ch].SB[29]=fa;                  // no interpolation
+
+           s_chan[ch].spos -= 0x10000L;
+          }
+
+         ////////////////////////////////////////////////
+         // noise handler... just produces some noise data
+         // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
+         // and sometimes the noise will be used as fmod modulation... pfff
+
+         if(s_chan[ch].bNoise)
+          {
+           if((dwNoiseVal<<=1)&0x80000000L)
+            {
+             dwNoiseVal^=0x0040001L;
+             fa=((dwNoiseVal>>2)&0x7fff);
+             fa=-fa;
+            }
+           else fa=(dwNoiseVal>>2)&0x7fff;
+
+           // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
+           fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[ch/24]&0x3f00)>>9))+1));
+           if(fa>32767L)  fa=32767L;
+           if(fa<-32767L) fa=-32767L;
+           s_chan[ch].iOldNoise=fa;
+
+           if(iUseInterpolation<2)                     // no gauss/cubic interpolation?
+            s_chan[ch].SB[29] = fa;                    // -> store noise val in "current sample" slot
+          }                                            //----------------------------------------
+         else                                          // NO NOISE (NORMAL SAMPLE DATA) HERE
+          {//------------------------------------------//
+           if(iUseInterpolation==3)                    // cubic interpolation
+            {
+             long xd;
+             xd = ((s_chan[ch].spos) >> 1)+1;
+             gpos = s_chan[ch].SB[28];
+
+             fa  = gval(3) - 3*gval(2) + 3*gval(1) - gval0;
+             fa *= (xd - (2<<15)) / 6;
+             fa >>= 15;
+             fa += gval(2) - gval(1) - gval(1) + gval0;
+             fa *= (xd - (1<<15)) >> 1;
+             fa >>= 15;
+             fa += gval(1) - gval0;
+             fa *= xd;
+             fa >>= 15;
+             fa = fa + gval0;
+            }
+           //------------------------------------------//
+           else
+           if(iUseInterpolation==2)                    // gauss interpolation
+            {
+             int vl, vr;
+             vl = (s_chan[ch].spos >> 6) & ~3;
+             gpos = s_chan[ch].SB[28];
+             vr=(gauss[vl]*gval0)&~2047;
+             vr+=(gauss[vl+1]*gval(1))&~2047;
+             vr+=(gauss[vl+2]*gval(2))&~2047;
+             vr+=(gauss[vl+3]*gval(3))&~2047;
+             fa = vr>>11;
+/*
+             vr=(gauss[vl]*gval0)>>9;
+             vr+=(gauss[vl+1]*gval(1))>>9;
+             vr+=(gauss[vl+2]*gval(2))>>9;
+             vr+=(gauss[vl+3]*gval(3))>>9;
+             fa = vr>>2;
+*/
+            }
+           //------------------------------------------//
+           else
+           if(iUseInterpolation==1)                    // simple interpolation
+            {
+             if(s_chan[ch].sinc<0x10000L)              // -> upsampling?
+                  InterpolateUp(ch);                   // --> interpolate up
+             else InterpolateDown(ch);                 // --> else down
+             fa=s_chan[ch].SB[29];
+            }
+           //------------------------------------------//
+           else fa=s_chan[ch].SB[29];                  // no interpolation
+          }
+
+         s_chan[ch].sval = (MixADSR(ch) * fa) / 1023;  // add adsr
+
+         if(s_chan[ch].bFMod==2)                       // fmod freq channel
+          {
+           int NP=s_chan[ch+1].iRawPitch;
+           double intr;
+
+           NP=((32768L+s_chan[ch].sval)*NP)/32768L;    // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :)
+
+           if(NP>0x3fff) NP=0x3fff;
+           if(NP<0x1)    NP=0x1;
+
+           intr = (double)48000.0f / (double)44100.0f * (double)NP;
+           NP = (uint32_t)intr;
+
+           NP=(44100L*NP)/(4096L);                     // calc frequency
+
+           s_chan[ch+1].iActFreq=NP;
+           s_chan[ch+1].iUsedFreq=NP;
+           s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
+           if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
+           if(iUseInterpolation==1)                    // freq change in sipmle interpolation mode
+            s_chan[ch+1].SB[32]=1;
+
+// mmmm... set up freq decoding positions?
+//           s_chan[ch+1].iSBPos=28;
+//           s_chan[ch+1].spos=0x10000L;
+          }
+         else
+          {
+           //////////////////////////////////////////////
+           // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
+
+           if(s_chan[ch].iMute)
+            s_chan[ch].sval=0;                         // debug mute
+           else
+            {
+             if(s_chan[ch].bVolumeL)
+              SSumL[0]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
+             if(s_chan[ch].bVolumeR)
+              SSumR[0]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
+            }
+
+           //////////////////////////////////////////////
+           // now let us store sound data for reverb
+
+           if(s_chan[ch].bRVBActive) StoreREVERB(ch,0);
+          }
+
+         ////////////////////////////////////////////////
+         // ok, go on until 1 ms data of this channel is collected
+
+         s_chan[ch].spos += s_chan[ch].sinc;
+
+        }
+ENDX:   ;
+      }
+    }
+
+  //---------------------------------------------------//
+  //- here we have another 1 ms of sound data
+  //---------------------------------------------------//
+
+  ///////////////////////////////////////////////////////
+  // mix all channels (including reverb) into one buffer
+
+    SSumL[0]+=MixREVERBLeft(0,0);
+    SSumL[0]+=MixREVERBLeft(0,1);
+    SSumR[0]+=MixREVERBRight(0);
+    SSumR[0]+=MixREVERBRight(1);
+
+    d=SSumL[0];SSumL[0]=0;
+    d2=SSumR[0];SSumR[0]=0;
+
+    if(d<-32767) d=-32767;if(d>32767) d=32767;
+    if(d2<-32767) d2=-32767;if(d2>32767) d2=32767;
+
+    if(sampcount>=decaybegin)
+     {
+      s32 dmul;
+      if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
+                         // for 13 hours?
+       {
+        if(sampcount>=decayend)
+         {
+          update(nullptr, 0);
+          return(0);
+         }
+
+        dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
+        d=(d*dmul)>>8;
+        d2=(d2*dmul)>>8;
+       }
+     }
+    sampcount++;
+
+    *pS++=d;
+    *pS++=d2;
+
+    InitREVERB();
+
+  //////////////////////////////////////////////////////
+  // feed the sound
+  // wanna have around 1/60 sec (16.666 ms) updates
+  if(seektime != 0 && sampcount < seektime)
+   {
+    pS=(short *)pSpuBuffer;
+   }
+  else if((((u8*)pS)-((u8*)pSpuBuffer)) == (735*4))
+   {
+    short *pSilenceIter = (short *)pSpuBuffer;
+    int iSilenceCount = 0;
+
+    for(; pSilenceIter < pS; pSilenceIter++)
+     {
+      if(*pSilenceIter == 0)
+       iSilenceCount++;
+
+      if(iSilenceCount > 20)
+       break;
+     }
+
+    if(iSilenceCount < 20)
+     update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer);
+
+    pS=(short *)pSpuBuffer;
+   }
+ }
+
+ // end of big main loop...
+
+ bThreadEnded=1;
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// SPU ASYNC... even newer epsxe func
+//  1 time every 'cycle' cycles... harhar
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2async(void (*update)(const void *, int))
+{
+ if(iSpuAsyncWait)
+  {
+   iSpuAsyncWait++;
+   if(iSpuAsyncWait<=64) return;
+   iSpuAsyncWait=0;
+  }
+ MAINThread(update);                                      // -> linux high-compat mode
+}
+
+////////////////////////////////////////////////////////////////////////
+// INIT/EXIT STUFF
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// SPUINIT: this func will be called first by the main emu
+////////////////////////////////////////////////////////////////////////
+
+
+EXPORT_GCC long CALLBACK SPU2init(void)
+{
+ spuMemC=(unsigned char *)spuMem;                      // just small setup
+ memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
+ memset(rvb,0,2*sizeof(REVERBInfo));
+
+ sampcount = 0;
+
+ InitADSR();
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SETUPTIMER: init of certain buffers and threads/timers
+////////////////////////////////////////////////////////////////////////
+
+static void SetupTimer(void)
+{
+ memset(SSumR,0,NSSIZE*sizeof(int));                   // init some mixing buffers
+ memset(SSumL,0,NSSIZE*sizeof(int));
+ pS=(short *)pSpuBuffer;                               // setup soundbuffer pointer
+
+ bEndThread=0;                                         // init thread vars
+ bThreadEnded=0;
+ bSpuInit=1;                                           // flag: we are inited
+}
+
+////////////////////////////////////////////////////////////////////////
+// REMOVETIMER: kill threads/timers
+////////////////////////////////////////////////////////////////////////
+
+static void RemoveTimer(void)
+{
+ bEndThread=1;                                         // raise flag to end thread
+ bThreadEnded=0;                                       // no more spu is running
+ bSpuInit=0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SETUPSTREAMS: init most of the spu buffers
+////////////////////////////////////////////////////////////////////////
+
+static void SetupStreams(void)
+{
+ int i;
+
+ pSpuBuffer=(unsigned char *)malloc(32768);            // alloc mixing buffer
+
+ i=NSSIZE*2;
+
+ sRVBStart[0] = (int *)malloc(i*4);                    // alloc reverb buffer
+ memset(sRVBStart[0],0,i*4);
+ sRVBEnd[0]  = sRVBStart[0] + i;
+ sRVBPlay[0] = sRVBStart[0];
+ sRVBStart[1] = (int *)malloc(i*4);                    // alloc reverb buffer
+ memset(sRVBStart[1],0,i*4);
+ sRVBEnd[1]  = sRVBStart[1] + i;
+ sRVBPlay[1] = sRVBStart[1];
+
+ for(i=0;i<MAXCHAN;i++)                                // loop sound channels
+  {
+// we don't use mutex sync... not needed, would only
+// slow us down:
+//   s_chan[i].hMutex=CreateMutex(nullptr,false,nullptr);
+   s_chan[i].ADSRX.SustainLevel = 1024;                // -> init sustain
+   s_chan[i].iMute=0;
+   s_chan[i].iIrqDone=0;
+   s_chan[i].pLoop=spuMemC;
+   s_chan[i].pStart=spuMemC;
+   s_chan[i].pCurr=spuMemC;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// REMOVESTREAMS: free most buffer
+////////////////////////////////////////////////////////////////////////
+
+static void RemoveStreams(void)
+{
+ free(pSpuBuffer);                                     // free mixing buffer
+ pSpuBuffer=nullptr;
+ free(sRVBStart[0]);                                   // free reverb buffer
+ sRVBStart[0]=0;
+ free(sRVBStart[1]);                                   // free reverb buffer
+ sRVBStart[1]=0;
+
+/*
+ int i;
+ for(i=0;i<MAXCHAN;i++)
+  {
+   WaitForSingleObject(s_chan[i].hMutex,2000);
+   ReleaseMutex(s_chan[i].hMutex);
+   if(s_chan[i].hMutex)
+    {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;}
+  }
+*/
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// SPUOPEN: called by main emu after init
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC long CALLBACK SPU2open(void *pDsp)
+{
+ if(bSPUIsOpen) return 0;                              // security for some stupid main emus
+
+ iUseXA=0;                                             // just small setup
+ bEndThread=0;
+ bThreadEnded=0;
+ spuMemC=(unsigned char *)spuMem;
+ memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
+ pSpuIrq[0]=0;
+ pSpuIrq[1]=0;
+ iSPUIRQWait=1;
+ dwNewChannel2[0]=0;
+ dwNewChannel2[1]=0;
+ dwEndChannel2[0]=0;
+ dwEndChannel2[1]=0;
+ spuCtrl2[0]=0;
+ spuCtrl2[1]=0;
+ spuStat2[0]=0;
+ spuStat2[1]=0;
+ spuIrq2[0]=0;
+ spuIrq2[1]=0;
+ spuAddr2[0]=0xffffffff;
+ spuAddr2[1]=0xffffffff;
+ spuRvbAddr2[0]=0;
+ spuRvbAddr2[1]=0;
+ spuRvbAEnd2[0]=0;
+ spuRvbAEnd2[1]=0;
+
+// ReadConfig();                                         // read user stuff
+
+// SetupSound();                                         // setup midas (before init!)
+
+ SetupStreams();                                       // prepare streaming
+
+ SetupTimer();                                         // timer for feeding data
+
+ bSPUIsOpen=1;
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// SPUCLOSE: called before shutdown
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2close(void)
+{
+ if(!bSPUIsOpen) return;                               // some security
+
+ bSPUIsOpen=0;                                         // no more open
+
+ RemoveTimer();                                        // no more feeding
+
+// RemoveSound();                                        // no more sound handling
+
+ RemoveStreams();                                      // no more streaming
+}
+
+////////////////////////////////////////////////////////////////////////
+// SPUSHUTDOWN: called by main emu on final exit
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC void CALLBACK SPU2shutdown(void)
+{
+ return;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SPUTEST: we don't test, we are always fine ;)
+////////////////////////////////////////////////////////////////////////
+
+EXPORT_GCC long CALLBACK SPU2test(void)
+{
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SETUP CALLBACKS
+// this functions will be called once,
+// passes a callback that should be called on SPU-IRQ/cdda volume change
+////////////////////////////////////////////////////////////////////////
+
+// not used yet
+EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void))
+{
+ irqCallback = callback;
+}
+
+// not used yet
+EXPORT_GCC void CALLBACK SPU2registerCallback(void (CALLBACK *callback)(void))
+{
+ irqCallback = callback;
+}
+
+// not used yet
+EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short))
+{
+ cddavCallback = CDDAVcallback;
+}
diff --git a/src/psf/peops2/spu.h b/src/psf/peops2/spu.h
index 94615d378134..30b4fb1b4b41 100644
--- a/src/psf/peops2/spu.h
+++ b/src/psf/peops2/spu.h
@@ -34,6 +34,6 @@ EXPORT_GCC void CALLBACK SPU2playADPCMchannel(xa_decode_t *xap);
 
 EXPORT_GCC long CALLBACK SPU2init(void);
 EXPORT_GCC long CALLBACK SPU2open(void *pDsp);
-EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle);
+EXPORT_GCC void CALLBACK SPU2async(void (*update)(const void *, int));
 EXPORT_GCC void CALLBACK SPU2close(void);
 EXPORT_GCC int  CALLBACK psf2_seek(u32 t);
diff --git a/src/psf/peops2/xa.c b/src/psf/peops2/xa.c
deleted file mode 100644
index ea48cdf83227..000000000000
--- a/src/psf/peops2/xa.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/***************************************************************************
-                            xa.c  -  description
-                             -------------------
-    begin                : Wed May 15 2002
-    copyright            : (C) 2002 by Pete Bernert
-    email                : BlackDove at addcom.de
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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. See also the license.txt file for *
- *   additional informations.                                              *
- *                                                                         *
- ***************************************************************************/
-
-//*************************************************************************//
-// History of changes:
-//
-// 2003/02/18 - kode54
-// - added gaussian interpolation
-//
-// 2002/05/15 - Pete
-// - generic cleanup for the Peops release
-//
-//*************************************************************************//
-
-#include "stdafx.h"
-
-#define _IN_XA
-
-// will be included from spu.c
-#ifdef _IN_SPU
-
-////////////////////////////////////////////////////////////////////////
-// XA GLOBALS
-////////////////////////////////////////////////////////////////////////
-
-xa_decode_t   * xapGlobal=0;
-
-unsigned long * XAFeed  = NULL;
-unsigned long * XAPlay  = NULL;
-unsigned long * XAStart = NULL;
-unsigned long * XAEnd   = NULL;
-
-unsigned long   XARepeat  = 0;
-unsigned long   XALastVal = 0;
-
-int             iLeftXAVol  = 32767;
-int             iRightXAVol = 32767;
-
-static int gauss_ptr = 0;
-static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
-#define gvall0 gauss_window[gauss_ptr]
-#define gvall(x) gauss_window[(gauss_ptr+x)&3]
-#define gvalr0 gauss_window[4+gauss_ptr]
-#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)]
-
-////////////////////////////////////////////////////////////////////////
-// MIX XA
-////////////////////////////////////////////////////////////////////////
-
-inline void MixXA(void)
-{
- int ns;
-
- for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++)
-  {
-   XALastVal=*XAPlay++;
-   if(XAPlay==XAEnd) XAPlay=XAStart;
-   SSumL[ns]+=(((short)(XALastVal&0xffff))       * iLeftXAVol)/32767;
-   SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
-  }
-
- if(XAPlay==XAFeed && XARepeat)
-  {
-   XARepeat--;
-   for(;ns<NSSIZE;ns++)
-    {
-     SSumL[ns]+=(((short)(XALastVal&0xffff))       * iLeftXAVol)/32767;
-     SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////////
-// FEED XA
-////////////////////////////////////////////////////////////////////////
-
-inline void FeedXA(xa_decode_t *xap)
-{
- int sinc,spos,i,iSize,iPlace,vl,vr;
-
- if(!bSPUIsOpen) return;
-
- xapGlobal = xap;                                      // store info for save states
- XARepeat  = 100;                                      // set up repeat
-
- iSize=((44100*xap->nsamples)/xap->freq);              // get size
- if(!iSize) return;                                    // none? bye
-
- if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed;               // how much space in my buf?
- else              iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
-
- if(iPlace==0) return;                                 // no place at all
-
- //----------------------------------------------------//
- if(iXAPitch)                                          // pitch change option?
-  {
-   static DWORD dwLT=0;
-   static DWORD dwFPS=0;
-   static int   iFPSCnt=0;
-   static int   iLastSize=0;
-   static DWORD dwL1=0;
-   DWORD dw=timeGetTime(),dw1,dw2;
-
-   iPlace=iSize;
-
-   dwFPS+=dw-dwLT;iFPSCnt++;
-
-   dwLT=dw;
-
-   if(iFPSCnt>=10)
-    {
-     if(!dwFPS) dwFPS=1;
-     dw1=1000000/dwFPS;
-     if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
-     else dwL1=dw1;
-     dw2=(xap->freq*100/xap->nsamples);
-     if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
-     else
-      {
-       iLastSize=iSize*dw2/dw1;
-       if(iLastSize>iPlace) iLastSize=iPlace;
-       iSize=iLastSize;
-      }
-     iFPSCnt=0;dwFPS=0;
-    }
-   else
-    {
-     if(iLastSize) iSize=iLastSize;
-    }
-  }
- //----------------------------------------------------//
-
- spos=0x10000L;
- sinc = (xap->nsamples << 16) / iSize;                 // calc freq by num / size
-
- if(xap->stereo)
-  {
-   unsigned long * pS=(unsigned long *)xap->pcm;
-   unsigned long l=0;
-
-   if(iXAPitch)
-    {
-     long l1,l2;short s;
-     for(i=0;i<iSize;i++)
-      {
-       if(iUseInterpolation==2)
-        {
-         while(spos>=0x10000L)
-          {
-           l = *pS++;
-           gauss_window[gauss_ptr] = (short)LOWWORD(l);
-           gauss_window[4+gauss_ptr] = (short)HIGHWORD(l);
-           gauss_ptr = (gauss_ptr+1) & 3;
-           spos -= 0x10000L;
-          }
-         vl = (spos >> 6) & ~3;
-         vr=(gauss[vl]*gvall0)&~2047;
-         vr+=(gauss[vl+1]*gvall(1))&~2047;
-         vr+=(gauss[vl+2]*gvall(2))&~2047;
-         vr+=(gauss[vl+3]*gvall(3))&~2047;
-         l= (vr >> 11) & 0xffff;
-         vr=(gauss[vl]*gvalr0)&~2047;
-         vr+=(gauss[vl+1]*gvalr(1))&~2047;
-         vr+=(gauss[vl+2]*gvalr(2))&~2047;
-         vr+=(gauss[vl+3]*gvalr(3))&~2047;
-         l |= vr << 5;
-        }
-       else
-        {
-         while(spos>=0x10000L)
-          {
-           l = *pS++;
-           spos -= 0x10000L;
-          }
-        }
-
-       s=(short)LOWWORD(l);
-       l1=s;
-       l1=(l1*iPlace)/iSize;
-       if(l1<-32767) l1=-32767;
-       if(l1> 32767) l1=32767;
-       s=(short)HIGHWORD(l);
-       l2=s;
-       l2=(l2*iPlace)/iSize;
-       if(l2<-32767) l2=-32767;
-       if(l2> 32767) l2=32767;
-       l=(l1&0xffff)|(l2<<16);
-
-       *XAFeed++=l;
-
-       if(XAFeed==XAEnd) XAFeed=XAStart;
-       if(XAFeed==XAPlay)
-        {
-         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
-         break;
-        }
-
-       spos += sinc;
-      }
-    }
-   else
-    {
-     for(i=0;i<iSize;i++)
-      {
-       if(iUseInterpolation==2)
-        {
-         while(spos>=0x10000L)
-          {
-           l = *pS++;
-           gauss_window[gauss_ptr] = (short)LOWWORD(l);
-           gauss_window[4+gauss_ptr] = (short)HIGHWORD(l);
-           gauss_ptr = (gauss_ptr+1) & 3;
-           spos -= 0x10000L;
-          }
-         vl = (spos >> 6) & ~3;
-         vr=(gauss[vl]*gvall0)&~2047;
-         vr+=(gauss[vl+1]*gvall(1))&~2047;
-         vr+=(gauss[vl+2]*gvall(2))&~2047;
-         vr+=(gauss[vl+3]*gvall(3))&~2047;
-         l= (vr >> 11) & 0xffff;
-         vr=(gauss[vl]*gvalr0)&~2047;
-         vr+=(gauss[vl+1]*gvalr(1))&~2047;
-         vr+=(gauss[vl+2]*gvalr(2))&~2047;
-         vr+=(gauss[vl+3]*gvalr(3))&~2047;
-         l |= vr << 5;
-        }
-       else
-        {
-         while(spos>=0x10000L)
-          {
-           l = *pS++;
-           spos -= 0x10000L;
-          }
-        }
-
-       *XAFeed++=l;
-
-       if(XAFeed==XAEnd) XAFeed=XAStart;
-       if(XAFeed==XAPlay)
-        {
-         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
-         break;
-        }
-
-       spos += sinc;
-      }
-    }
-  }
- else
-  {
-   unsigned short * pS=(unsigned short *)xap->pcm;
-   unsigned long l;short s=0;
-
-   if(iXAPitch)
-    {
-     long l1;
-     for(i=0;i<iSize;i++)
-      {
-       if(iUseInterpolation==2)
-        {
-         while(spos>=0x10000L)
-          {
-           gauss_window[gauss_ptr] = (short)*pS++;
-           gauss_ptr = (gauss_ptr+1) & 3;
-           spos -= 0x10000L;
-          }
-         vl = (spos >> 6) & ~3;
-         vr=(gauss[vl]*gvall0)&~2047;
-         vr+=(gauss[vl+1]*gvall(1))&~2047;
-         vr+=(gauss[vl+2]*gvall(2))&~2047;
-         vr+=(gauss[vl+3]*gvall(3))&~2047;
-         l1=s= vr >> 11;
-         l1 &= 0xffff;
-        }
-       else
-        {
-         while(spos>=0x10000L)
-          {
-           s = *pS++;
-           spos -= 0x10000L;
-          }
-         l1=s;
-        }
-
-       l1=(l1*iPlace)/iSize;
-       if(l1<-32767) l1=-32767;
-       if(l1> 32767) l1=32767;
-       l=(l1&0xffff)|(l1<<16);
-       *XAFeed++=l;
-
-       if(XAFeed==XAEnd) XAFeed=XAStart;
-       if(XAFeed==XAPlay)
-        {
-         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
-         break;
-        }
-
-       spos += sinc;
-      }
-    }
-   else
-    {
-     for(i=0;i<iSize;i++)
-      {
-       if(iUseInterpolation==2)
-        {
-         while(spos>=0x10000L)
-          {
-           gauss_window[gauss_ptr] = (short)*pS++;
-           gauss_ptr = (gauss_ptr+1) & 3;
-           spos -= 0x10000L;
-          }
-         vl = (spos >> 6) & ~3;
-         vr=(gauss[vl]*gvall0)&~2047;
-         vr+=(gauss[vl+1]*gvall(1))&~2047;
-         vr+=(gauss[vl+2]*gvall(2))&~2047;
-         vr+=(gauss[vl+3]*gvall(3))&~2047;
-         l=s= vr >> 11;
-         l &= 0xffff;
-        }
-       else
-        {
-         while(spos>=0x10000L)
-          {
-           s = *pS++;
-           spos -= 0x10000L;
-          }
-         l=s;
-        }
-
-       *XAFeed++=(l|(l<<16));
-
-       if(XAFeed==XAEnd) XAFeed=XAStart;
-       if(XAFeed==XAPlay)
-        {
-         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
-         break;
-        }
-
-       spos += sinc;
-      }
-    }
-  }
-}
-
-#endif
-
diff --git a/src/psf/peops2/xa.cc b/src/psf/peops2/xa.cc
new file mode 100644
index 000000000000..4d0ba317bc45
--- /dev/null
+++ b/src/psf/peops2/xa.cc
@@ -0,0 +1,363 @@
+/***************************************************************************
+                            xa.c  -  description
+                             -------------------
+    begin                : Wed May 15 2002
+    copyright            : (C) 2002 by Pete Bernert
+    email                : BlackDove at addcom.de
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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. See also the license.txt file for *
+ *   additional informations.                                              *
+ *                                                                         *
+ ***************************************************************************/
+
+//*************************************************************************//
+// History of changes:
+//
+// 2003/02/18 - kode54
+// - added gaussian interpolation
+//
+// 2002/05/15 - Pete
+// - generic cleanup for the Peops release
+//
+//*************************************************************************//
+
+#include "stdafx.h"
+
+#define _IN_XA
+
+// will be included from spu.c
+#ifdef _IN_SPU
+
+////////////////////////////////////////////////////////////////////////
+// XA GLOBALS
+////////////////////////////////////////////////////////////////////////
+
+xa_decode_t   * xapGlobal=0;
+
+unsigned long * XAFeed  = nullptr;
+unsigned long * XAPlay  = nullptr;
+unsigned long * XAStart = nullptr;
+unsigned long * XAEnd   = nullptr;
+
+unsigned long   XARepeat  = 0;
+unsigned long   XALastVal = 0;
+
+int             iLeftXAVol  = 32767;
+int             iRightXAVol = 32767;
+
+static int gauss_ptr = 0;
+static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+#define gvall0 gauss_window[gauss_ptr]
+#define gvall(x) gauss_window[(gauss_ptr+x)&3]
+#define gvalr0 gauss_window[4+gauss_ptr]
+#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)]
+
+////////////////////////////////////////////////////////////////////////
+// MIX XA
+////////////////////////////////////////////////////////////////////////
+
+inline void MixXA(void)
+{
+ int ns;
+
+ for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++)
+  {
+   XALastVal=*XAPlay++;
+   if(XAPlay==XAEnd) XAPlay=XAStart;
+   SSumL[ns]+=(((short)(XALastVal&0xffff))       * iLeftXAVol)/32767;
+   SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
+  }
+
+ if(XAPlay==XAFeed && XARepeat)
+  {
+   XARepeat--;
+   for(;ns<NSSIZE;ns++)
+    {
+     SSumL[ns]+=(((short)(XALastVal&0xffff))       * iLeftXAVol)/32767;
+     SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////////
+// FEED XA
+////////////////////////////////////////////////////////////////////////
+
+inline void FeedXA(xa_decode_t *xap)
+{
+ int sinc,spos,i,iSize,iPlace,vl,vr;
+
+ if(!bSPUIsOpen) return;
+
+ xapGlobal = xap;                                      // store info for save states
+ XARepeat  = 100;                                      // set up repeat
+
+ iSize=((44100*xap->nsamples)/xap->freq);              // get size
+ if(!iSize) return;                                    // none? bye
+
+ if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed;               // how much space in my buf?
+ else              iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
+
+ if(iPlace==0) return;                                 // no place at all
+
+ //----------------------------------------------------//
+ if(iXAPitch)                                          // pitch change option?
+  {
+   static DWORD dwLT=0;
+   static DWORD dwFPS=0;
+   static int   iFPSCnt=0;
+   static int   iLastSize=0;
+   static DWORD dwL1=0;
+   DWORD dw=timeGetTime(),dw1,dw2;
+
+   iPlace=iSize;
+
+   dwFPS+=dw-dwLT;iFPSCnt++;
+
+   dwLT=dw;
+
+   if(iFPSCnt>=10)
+    {
+     if(!dwFPS) dwFPS=1;
+     dw1=1000000/dwFPS;
+     if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
+     else dwL1=dw1;
+     dw2=(xap->freq*100/xap->nsamples);
+     if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
+     else
+      {
+       iLastSize=iSize*dw2/dw1;
+       if(iLastSize>iPlace) iLastSize=iPlace;
+       iSize=iLastSize;
+      }
+     iFPSCnt=0;dwFPS=0;
+    }
+   else
+    {
+     if(iLastSize) iSize=iLastSize;
+    }
+  }
+ //----------------------------------------------------//
+
+ spos=0x10000L;
+ sinc = (xap->nsamples << 16) / iSize;                 // calc freq by num / size
+
+ if(xap->stereo)
+  {
+   unsigned long * pS=(unsigned long *)xap->pcm;
+   unsigned long l=0;
+
+   if(iXAPitch)
+    {
+     long l1,l2;short s;
+     for(i=0;i<iSize;i++)
+      {
+       if(iUseInterpolation==2)
+        {
+         while(spos>=0x10000L)
+          {
+           l = *pS++;
+           gauss_window[gauss_ptr] = (short)LOWWORD(l);
+           gauss_window[4+gauss_ptr] = (short)HIGHWORD(l);
+           gauss_ptr = (gauss_ptr+1) & 3;
+           spos -= 0x10000L;
+          }
+         vl = (spos >> 6) & ~3;
+         vr=(gauss[vl]*gvall0)&~2047;
+         vr+=(gauss[vl+1]*gvall(1))&~2047;
+         vr+=(gauss[vl+2]*gvall(2))&~2047;
+         vr+=(gauss[vl+3]*gvall(3))&~2047;
+         l= (vr >> 11) & 0xffff;
+         vr=(gauss[vl]*gvalr0)&~2047;
+         vr+=(gauss[vl+1]*gvalr(1))&~2047;
+         vr+=(gauss[vl+2]*gvalr(2))&~2047;
+         vr+=(gauss[vl+3]*gvalr(3))&~2047;
+         l |= vr << 5;
+        }
+       else
+        {
+         while(spos>=0x10000L)
+          {
+           l = *pS++;
+           spos -= 0x10000L;
+          }
+        }
+
+       s=(short)LOWWORD(l);
+       l1=s;
+       l1=(l1*iPlace)/iSize;
+       if(l1<-32767) l1=-32767;
+       if(l1> 32767) l1=32767;
+       s=(short)HIGHWORD(l);
+       l2=s;
+       l2=(l2*iPlace)/iSize;
+       if(l2<-32767) l2=-32767;
+       if(l2> 32767) l2=32767;
+       l=(l1&0xffff)|(l2<<16);
+
+       *XAFeed++=l;
+
+       if(XAFeed==XAEnd) XAFeed=XAStart;
+       if(XAFeed==XAPlay)
+        {
+         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+         break;
+        }
+
+       spos += sinc;
+      }
+    }
+   else
+    {
+     for(i=0;i<iSize;i++)
+      {
+       if(iUseInterpolation==2)
+        {
+         while(spos>=0x10000L)
+          {
+           l = *pS++;
+           gauss_window[gauss_ptr] = (short)LOWWORD(l);
+           gauss_window[4+gauss_ptr] = (short)HIGHWORD(l);
+           gauss_ptr = (gauss_ptr+1) & 3;
+           spos -= 0x10000L;
+          }
+         vl = (spos >> 6) & ~3;
+         vr=(gauss[vl]*gvall0)&~2047;
+         vr+=(gauss[vl+1]*gvall(1))&~2047;
+         vr+=(gauss[vl+2]*gvall(2))&~2047;
+         vr+=(gauss[vl+3]*gvall(3))&~2047;
+         l= (vr >> 11) & 0xffff;
+         vr=(gauss[vl]*gvalr0)&~2047;
+         vr+=(gauss[vl+1]*gvalr(1))&~2047;
+         vr+=(gauss[vl+2]*gvalr(2))&~2047;
+         vr+=(gauss[vl+3]*gvalr(3))&~2047;
+         l |= vr << 5;
+        }
+       else
+        {
+         while(spos>=0x10000L)
+          {
+           l = *pS++;
+           spos -= 0x10000L;
+          }
+        }
+
+       *XAFeed++=l;
+
+       if(XAFeed==XAEnd) XAFeed=XAStart;
+       if(XAFeed==XAPlay)
+        {
+         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+         break;
+        }
+
+       spos += sinc;
+      }
+    }
+  }
+ else
+  {
+   unsigned short * pS=(unsigned short *)xap->pcm;
+   unsigned long l;short s=0;
+
+   if(iXAPitch)
+    {
+     long l1;
+     for(i=0;i<iSize;i++)
+      {
+       if(iUseInterpolation==2)
+        {
+         while(spos>=0x10000L)
+          {
+           gauss_window[gauss_ptr] = (short)*pS++;
+           gauss_ptr = (gauss_ptr+1) & 3;
+           spos -= 0x10000L;
+          }
+         vl = (spos >> 6) & ~3;
+         vr=(gauss[vl]*gvall0)&~2047;
+         vr+=(gauss[vl+1]*gvall(1))&~2047;
+         vr+=(gauss[vl+2]*gvall(2))&~2047;
+         vr+=(gauss[vl+3]*gvall(3))&~2047;
+         l1=s= vr >> 11;
+         l1 &= 0xffff;
+        }
+       else
+        {
+         while(spos>=0x10000L)
+          {
+           s = *pS++;
+           spos -= 0x10000L;
+          }
+         l1=s;
+        }
+
+       l1=(l1*iPlace)/iSize;
+       if(l1<-32767) l1=-32767;
+       if(l1> 32767) l1=32767;
+       l=(l1&0xffff)|(l1<<16);
+       *XAFeed++=l;
+
+       if(XAFeed==XAEnd) XAFeed=XAStart;
+       if(XAFeed==XAPlay)
+        {
+         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+         break;
+        }
+
+       spos += sinc;
+      }
+    }
+   else
+    {
+     for(i=0;i<iSize;i++)
+      {
+       if(iUseInterpolation==2)
+        {
+         while(spos>=0x10000L)
+          {
+           gauss_window[gauss_ptr] = (short)*pS++;
+           gauss_ptr = (gauss_ptr+1) & 3;
+           spos -= 0x10000L;
+          }
+         vl = (spos >> 6) & ~3;
+         vr=(gauss[vl]*gvall0)&~2047;
+         vr+=(gauss[vl+1]*gvall(1))&~2047;
+         vr+=(gauss[vl+2]*gvall(2))&~2047;
+         vr+=(gauss[vl+3]*gvall(3))&~2047;
+         l=s= vr >> 11;
+         l &= 0xffff;
+        }
+       else
+        {
+         while(spos>=0x10000L)
+          {
+           s = *pS++;
+           spos -= 0x10000L;
+          }
+         l=s;
+        }
+
+       *XAFeed++=(l|(l<<16));
+
+       if(XAFeed==XAEnd) XAFeed=XAStart;
+       if(XAFeed==XAPlay)
+        {
+         if(XAPlay!=XAStart) XAFeed=XAPlay-1;
+         break;
+        }
+
+       spos += sinc;
+      }
+    }
+  }
+}
+
+#endif
+
diff --git a/src/psf/plugin.c b/src/psf/plugin.c
deleted file mode 100644
index 88e7499f91d8..000000000000
--- a/src/psf/plugin.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-	Audio Overload SDK - main driver.  for demonstration only, not user friendly!
-
-	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include "ao.h"
-#include "corlett.h"
-#include "eng_protos.h"
-
-typedef enum {
-    ENG_NONE = 0,
-    ENG_PSF1,
-    ENG_PSF2,
-    ENG_SPX,
-    ENG_COUNT
-} PSFEngine;
-
-typedef struct {
-    int32_t (*start)(uint8_t *buffer, uint32_t length);
-    int32_t (*stop)(void);
-    int32_t (*seek)(uint32_t);
-    int32_t (*execute)(void);
-} PSFEngineFunctors;
-
-static PSFEngineFunctors psf_functor_map[ENG_COUNT] = {
-    {NULL, NULL, NULL, NULL},
-    {psf_start, psf_stop, psf_seek, psf_execute},
-    {psf2_start, psf2_stop, psf2_seek, psf2_execute},
-    {spx_start, spx_stop, psf_seek, spx_execute},
-};
-
-static PSFEngineFunctors *f;
-static const char *dirpath;
-
-bool_t stop_flag = FALSE;
-
-static PSFEngine psf_probe(uint8_t *buffer)
-{
-	if (!memcmp(buffer, "PSF\x01", 4))
-		return ENG_PSF1;
-
-	if (!memcmp(buffer, "PSF\x02", 4))
-		return ENG_PSF2;
-
-	if (!memcmp(buffer, "SPU", 3))
-		return ENG_SPX;
-
-	if (!memcmp(buffer, "SPX", 3))
-		return ENG_SPX;
-
-	return ENG_NONE;
-}
-
-/* ao_get_lib: called to load secondary files */
-int ao_get_lib(char *filename, uint8_t **buffer, uint64_t *length)
-{
-	void *filebuf;
-	int64_t size;
-
-	SPRINTF(path2, "%s/%s", dirpath, filename);
-	vfs_file_get_contents(path2, &filebuf, &size);
-
-	*buffer = filebuf;
-	*length = (uint64_t)size;
-
-	return AO_SUCCESS;
-}
-
-Tuple *psf2_tuple(const char *filename, VFSFile *file)
-{
-	Tuple *t;
-	corlett_t *c;
-	void *buf;
-	int64_t sz;
-
-	vfs_file_get_contents (filename, & buf, & sz);
-
-	if (!buf)
-		return NULL;
-
-	if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS)
-		return NULL;
-
-	t = tuple_new_from_filename(filename);
-
-	tuple_set_int(t, FIELD_LENGTH, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1);
-	tuple_set_str(t, FIELD_ARTIST, c->inf_artist);
-	tuple_set_str(t, FIELD_ALBUM, c->inf_game);
-	tuple_set_str(t, FIELD_TITLE, c->inf_title);
-	tuple_set_str(t, FIELD_COPYRIGHT, c->inf_copy);
-	tuple_set_str(t, FIELD_QUALITY, _("sequenced"));
-	tuple_set_str(t, FIELD_CODEC, "PlayStation 1/2 Audio");
-
-	free(c);
-	free(buf);
-
-	return t;
-}
-
-static bool_t psf2_play(const char * filename, VFSFile * file)
-{
-	void *buffer;
-	int64_t size;
-	PSFEngine eng;
-	bool_t error = FALSE;
-
-	const char * slash = strrchr (filename, '/');
-	if (! slash)
-		return FALSE;
-
-	SNCOPY (dirbuf, filename, slash + 1 - filename);
-	dirpath = dirbuf;
-
-	vfs_file_get_contents (filename, & buffer, & size);
-
-	eng = psf_probe(buffer);
-	if (eng == ENG_NONE || eng == ENG_COUNT)
-	{
-		free(buffer);
-		return FALSE;
-	}
-
-	f = &psf_functor_map[eng];
-	if (f->start(buffer, size) != AO_SUCCESS)
-	{
-		free(buffer);
-		return FALSE;
-	}
-
-	aud_input_open_audio(FMT_S16_NE, 44100, 2);
-
-	aud_input_set_bitrate(44100*2*2*8);
-
-	stop_flag = FALSE;
-
-	f->execute();
-	f->stop();
-
-	f = NULL;
-	dirpath = NULL;
-	free(buffer);
-
-	return ! error;
-}
-
-void psf2_update(unsigned char *buffer, long count)
-{
-	if (! buffer || aud_input_check_stop ())
-	{
-		stop_flag = TRUE;
-		return;
-	}
-
-	int seek = aud_input_check_seek ();
-
-	if (seek >= 0)
-	{
-		f->seek (seek);
-		return;
-	}
-
-	aud_input_write_audio (buffer, count);
-}
-
-int psf2_is_our_fd(const char *filename, VFSFile *file)
-{
-	uint8_t magic[4];
-	if (vfs_fread(magic, 1, 4, file) < 4)
-		return FALSE;
-
-	return (psf_probe(magic) != ENG_NONE);
-}
-
-static const char *psf2_fmts[] = { "psf", "minipsf", "psf2", "minipsf2", "spu", "spx", NULL };
-
-AUD_INPUT_PLUGIN
-(
-	.name = N_("OpenPSF PSF1/PSF2 Decoder"),
-	.domain = PACKAGE,
-	.play = psf2_play,
-	.probe_for_tuple = psf2_tuple,
-	.is_our_file_from_vfs = psf2_is_our_fd,
-	.extensions = psf2_fmts,
-)
diff --git a/src/psf/plugin.cc b/src/psf/plugin.cc
new file mode 100644
index 000000000000..1975d76568f3
--- /dev/null
+++ b/src/psf/plugin.cc
@@ -0,0 +1,215 @@
+/*
+	Audio Overload SDK - main driver.  for demonstration only, not user friendly!
+
+	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+
+#include "ao.h"
+#include "corlett.h"
+#include "eng_protos.h"
+
+class PSFPlugin : public InputPlugin
+{
+public:
+	static const char *const exts[];
+
+	static constexpr PluginInfo info = {
+		N_("OpenPSF PSF1/PSF2 Decoder"),
+		PACKAGE
+	};
+
+	static constexpr auto iinfo = InputInfo()
+		.with_exts(exts);
+
+	constexpr PSFPlugin() : InputPlugin(info, iinfo) {}
+
+	bool is_our_file(const char *filename, VFSFile &file);
+	Tuple read_tuple(const char *filename, VFSFile &file);
+	bool play(const char *filename, VFSFile &file);
+
+protected:
+	static void update(const void *data, int bytes);
+};
+
+EXPORT PSFPlugin aud_plugin_instance;
+
+typedef enum {
+	ENG_NONE = 0,
+	ENG_PSF1,
+	ENG_PSF2,
+	ENG_SPX,
+	ENG_COUNT
+} PSFEngine;
+
+typedef struct {
+	int32_t (*start)(uint8_t *buffer, uint32_t length);
+	int32_t (*stop)(void);
+	int32_t (*seek)(uint32_t);
+	int32_t (*execute)(void (*update)(const void *, int));
+} PSFEngineFunctors;
+
+static PSFEngineFunctors psf_functor_map[ENG_COUNT] = {
+	{nullptr, nullptr, nullptr, nullptr},
+	{psf_start, psf_stop, psf_seek, psf_execute},
+	{psf2_start, psf2_stop, psf2_seek, psf2_execute},
+	{spx_start, spx_stop, psf_seek, spx_execute},
+};
+
+static PSFEngineFunctors *f;
+static String dirpath;
+
+bool stop_flag = false;
+
+static PSFEngine psf_probe(const char *buf, int len)
+{
+	if (len < 4)
+		return ENG_NONE;
+
+	if (!memcmp(buf, "PSF\x01", 4))
+		return ENG_PSF1;
+
+	if (!memcmp(buf, "PSF\x02", 4))
+		return ENG_PSF2;
+
+	if (!memcmp(buf, "SPU", 3))
+		return ENG_SPX;
+
+	if (!memcmp(buf, "SPX", 3))
+		return ENG_SPX;
+
+	return ENG_NONE;
+}
+
+/* ao_get_lib: called to load secondary files */
+Index<char> ao_get_lib(char *filename)
+{
+	VFSFile file(filename_build({dirpath, filename}), "r");
+	return file ? file.read_all() : Index<char>();
+}
+
+Tuple PSFPlugin::read_tuple(const char *filename, VFSFile &file)
+{
+	Tuple t;
+	corlett_t *c;
+
+	Index<char> buf = file.read_all ();
+
+	if (!buf.len())
+		return t;
+
+	if (corlett_decode((uint8_t *)buf.begin(), buf.len(), nullptr, nullptr, &c) != AO_SUCCESS)
+		return t;
+
+	t.set_filename (filename);
+
+	t.set_int (Tuple::Length, psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade));
+	t.set_str (Tuple::Artist, c->inf_artist);
+	t.set_str (Tuple::Album, c->inf_game);
+	t.set_str (Tuple::Title, c->inf_title);
+	t.set_str (Tuple::Copyright, c->inf_copy);
+	t.set_str (Tuple::Quality, _("sequenced"));
+	t.set_str (Tuple::Codec, "PlayStation 1/2 Audio");
+
+	free(c);
+
+	return t;
+}
+
+bool PSFPlugin::play(const char *filename, VFSFile &file)
+{
+	bool error = false;
+
+	const char * slash = strrchr (filename, '/');
+	if (! slash)
+		return false;
+
+	dirpath = String (str_copy (filename, slash + 1 - filename));
+
+	Index<char> buf = file.read_all ();
+
+	PSFEngine eng = psf_probe(buf.begin(), buf.len());
+	if (eng == ENG_NONE || eng == ENG_COUNT)
+	{
+		error = true;
+		goto cleanup;
+	}
+
+	f = &psf_functor_map[eng];
+	if (f->start((uint8_t *)buf.begin(), buf.len()) != AO_SUCCESS)
+	{
+		error = true;
+		goto cleanup;
+	}
+
+	set_stream_bitrate(44100*2*2*8);
+	open_audio(FMT_S16_NE, 44100, 2);
+
+	stop_flag = false;
+
+	f->execute(update);
+	f->stop();
+
+cleanup:
+	f = nullptr;
+	dirpath = String ();
+
+	return ! error;
+}
+
+void PSFPlugin::update(const void *data, int bytes)
+{
+	if (!data || check_stop())
+	{
+		stop_flag = true;
+		return;
+	}
+
+	int seek = check_seek();
+
+	if (seek >= 0)
+	{
+		f->seek(seek);
+		return;
+	}
+
+	write_audio(data, bytes);
+}
+
+bool PSFPlugin::is_our_file(const char *filename, VFSFile &file)
+{
+	char magic[4];
+	if (file.fread (magic, 1, 4) < 4)
+		return false;
+
+	return (psf_probe(magic, 4) != ENG_NONE);
+}
+
+const char *const PSFPlugin::exts[] = { "psf", "minipsf", "psf2", "minipsf2", "spu", "spx", nullptr };
diff --git a/src/psf/psx.c b/src/psf/psx.c
deleted file mode 100644
index 9b2efe48984c..000000000000
--- a/src/psf/psx.c
+++ /dev/null
@@ -1,3005 +0,0 @@
-/*
- * Sony CXD8530AQ/CXD8530BQ/CXD8530CQ/CXD8661R
- *
- * PSX CPU emulator for the MAME project written by smf
- * Thanks to Farfetch'd for information on the delay slot bug
- *
- * The PSX CPU is a custom r3000a with a built in
- * geometry transform engine, no mmu & no data cache.
- *
- * There is a stall circuit for load delays, but
- * it doesn't work if the load occurs in a branch
- * delay slot.
- *
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include "ao.h"
-#include "cpuintrf.h"
-#include "psx.h"
-
-#define EXC_INT ( 0 )
-#define EXC_ADEL ( 4 )
-#define EXC_ADES ( 5 )
-#define EXC_SYS ( 8 )
-#define EXC_BP ( 9 )
-#define EXC_RI ( 10 )
-#define EXC_CPU ( 11 )
-#define EXC_OVF ( 12 )
-
-#define CP0_RANDOM ( 1 )
-#define CP0_BADVADDR ( 8 )
-#define CP0_SR ( 12 )
-#define CP0_CAUSE ( 13 )
-#define CP0_EPC ( 14 )
-#define CP0_PRID ( 15 )
-
-#define SR_IEC ( 1L << 0 )
-#define SR_KUC ( 1L << 1 )
-#define SR_ISC ( 1L << 16 )
-#define SR_SWC ( 1L << 17 )
-#define SR_TS  ( 1L << 21 )
-#define SR_BEV ( 1L << 22 )
-#define SR_RE ( 1L << 25 )
-#define SR_CU0 ( 1L << 28 )
-#define SR_CU1 ( 1L << 29 )
-#define SR_CU2 ( 1L << 30 )
-#define SR_CU3 ( 1L << 31 )
-
-#define CAUSE_EXC ( 31L << 2 )
-#define CAUSE_IP ( 255L << 8 )
-#define CAUSE_IP2 ( 1L << 10 )
-#define CAUSE_IP3 ( 1L << 11 )
-#define CAUSE_IP4 ( 1L << 12 )
-#define CAUSE_IP5 ( 1L << 13 )
-#define CAUSE_IP6 ( 1L << 14 )
-#define CAUSE_IP7 ( 1L << 15 )
-#define CAUSE_CE ( 3L << 28 )
-#define CAUSE_CE0 ( 0L << 28 )
-#define CAUSE_CE1 ( 1L << 28 )
-#define CAUSE_CE2 ( 2L << 28 )
-#define CAUSE_BD ( 1L << 31 )
-
-extern void psx_bios_hle(uint32_t pc);
-extern void psx_iop_call(uint32_t pc, uint32_t callnum);
-extern uint8_t program_read_byte_32le(offs_t address);
-extern uint16_t program_read_word_32le(offs_t address);
-extern uint32_t program_read_dword_32le(offs_t address);
-extern void program_write_byte_32le(offs_t address, uint8_t data);
-extern void program_write_word_32le(offs_t address, uint16_t data);
-extern void program_write_dword_32le(offs_t address, uint32_t data);
-
-static uint8_t mips_reg_layout[] =
-{
-	MIPS_PC, -1,
-	MIPS_DELAYV, MIPS_DELAYR, -1,
-	MIPS_HI, MIPS_LO, -1,
-	-1,
-	MIPS_R0, MIPS_R1, -1,
-	MIPS_R2, MIPS_R3, -1,
-	MIPS_R4, MIPS_R5, -1,
-	MIPS_R6, MIPS_R7, -1,
-	MIPS_R8, MIPS_R9, -1,
-	MIPS_R10, MIPS_R11, -1,
-	MIPS_R12, MIPS_R13, -1,
-	MIPS_R14, MIPS_R15, -1,
-	MIPS_R16, MIPS_R17, -1,
-	MIPS_R18, MIPS_R19, -1,
-	MIPS_R20, MIPS_R21, -1,
-	MIPS_R22, MIPS_R23, -1,
-	MIPS_R24, MIPS_R25, -1,
-	MIPS_R26, MIPS_R27, -1,
-	MIPS_R28, MIPS_R29, -1,
-	MIPS_R30, MIPS_R31, -1,
-	-1,
-	MIPS_CP0R0, MIPS_CP0R1, -1,
-	MIPS_CP0R2, MIPS_CP0R3, -1,
-	MIPS_CP0R4, MIPS_CP0R5, -1,
-	MIPS_CP0R6, MIPS_CP0R7, -1,
-	MIPS_CP0R8, MIPS_CP0R9, -1,
-	MIPS_CP0R10, MIPS_CP0R11, -1,
-	MIPS_CP0R12, MIPS_CP0R13, -1,
-	MIPS_CP0R14, MIPS_CP0R15, -1,
-	MIPS_CP0R16, MIPS_CP0R17, -1,
-	MIPS_CP0R18, MIPS_CP0R19, -1,
-	MIPS_CP0R20, MIPS_CP0R21, -1,
-	MIPS_CP0R22, MIPS_CP0R23, -1,
-	MIPS_CP0R24, MIPS_CP0R25, -1,
-	MIPS_CP0R26, MIPS_CP0R27, -1,
-	MIPS_CP0R28, MIPS_CP0R29, -1,
-	MIPS_CP0R30, MIPS_CP0R31, -1,
-	-1,
-	MIPS_CP2DR0, MIPS_CP2DR1, -1,
-	MIPS_CP2DR2, MIPS_CP2DR3, -1,
-	MIPS_CP2DR4, MIPS_CP2DR5, -1,
-	MIPS_CP2DR6, MIPS_CP2DR7, -1,
-	MIPS_CP2DR8, MIPS_CP2DR9, -1,
-	MIPS_CP2DR10, MIPS_CP2DR11, -1,
-	MIPS_CP2DR12, MIPS_CP2DR13, -1,
-	MIPS_CP2DR14, MIPS_CP2DR15, -1,
-	MIPS_CP2DR16, MIPS_CP2DR17, -1,
-	MIPS_CP2DR18, MIPS_CP2DR19, -1,
-	MIPS_CP2DR20, MIPS_CP2DR21, -1,
-	MIPS_CP2DR22, MIPS_CP2DR23, -1,
-	MIPS_CP2DR24, MIPS_CP2DR25, -1,
-	MIPS_CP2DR26, MIPS_CP2DR27, -1,
-	MIPS_CP2DR28, MIPS_CP2DR29, -1,
-	MIPS_CP2DR30, MIPS_CP2DR31, -1,
-	-1,
-	MIPS_CP2CR0, MIPS_CP2CR1, -1,
-	MIPS_CP2CR2, MIPS_CP2CR3, -1,
-	MIPS_CP2CR4, MIPS_CP2CR5, -1,
-	MIPS_CP2CR6, MIPS_CP2CR7, -1,
-	MIPS_CP2CR8, MIPS_CP2CR9, -1,
-	MIPS_CP2CR10, MIPS_CP2CR11, -1,
-	MIPS_CP2CR12, MIPS_CP2CR13, -1,
-	MIPS_CP2CR14, MIPS_CP2CR15, -1,
-	MIPS_CP2CR16, MIPS_CP2CR17, -1,
-	MIPS_CP2CR18, MIPS_CP2CR19, -1,
-	MIPS_CP2CR20, MIPS_CP2CR21, -1,
-	MIPS_CP2CR22, MIPS_CP2CR23, -1,
-	MIPS_CP2CR24, MIPS_CP2CR25, -1,
-	MIPS_CP2CR26, MIPS_CP2CR27, -1,
-	MIPS_CP2CR28, MIPS_CP2CR29, -1,
-	MIPS_CP2CR30, MIPS_CP2CR31,
-	0
-};
-
-static uint8_t mips_win_layout[] = {
-	45, 0,35,13,	/* register window (top right) */
-	 0, 0,44,13,	/* disassembler window (left, upper) */
-	 0,14,44, 8,	/* memory #1 window (left, middle) */
-	45,14,35, 8,	/* memory #2 window (lower) */
-	 0,23,80, 1 	/* command line window (bottom rows) */
-};
-
-#define REGPC ( 32 )
-
-typedef struct
-{
-	uint32_t op;
-	uint32_t pc;
-	uint32_t prevpc;
-	uint32_t delayv;
-	uint32_t delayr;
-	uint32_t hi;
-	uint32_t lo;
-	uint32_t r[ 32 ];
-	uint32_t cp0r[ 32 ];
-	PAIR cp2cr[ 32 ];
-	PAIR cp2dr[ 32 ];
-	int (*irq_callback)(int irqline);
-} mips_cpu_context;
-
-static mips_cpu_context mipscpu;
-
-static int mips_ICount = 0;
-
-static uint32_t mips_mtc0_writemask[]=
-{
-	0xffffffff, /* INDEX */
-	0x00000000, /* RANDOM */
-	0xffffff00, /* ENTRYLO */
-	0x00000000,
-	0xffe00000, /* CONTEXT */
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000, /* BADVADDR */
-	0x00000000,
-	0xffffffc0, /* ENTRYHI */
-	0x00000000,
-	0xf27fff3f, /* SR */
-	0x00000300, /* CAUSE */
-	0x00000000, /* EPC */
-	0x00000000, /* PRID */
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-#if 1
-void GTELOG(const char *a,...)
-{
-	va_list va;
-	char s_text[ 1024 ];
-	va_start( va, a );
-	vsprintf( s_text, a, va );
-	va_end( va );
-	logerror( "%08x: GTE: %08x %s\n", mipscpu.pc, INS_COFUN( mipscpu.op ), s_text );
-}
-#else
-static inline void GTELOG(const char *a, ...) {}
-#endif
-
-static uint32_t getcp2dr( int n_reg );
-static void setcp2dr( int n_reg, uint32_t n_value );
-static uint32_t getcp2cr( int n_reg );
-static void setcp2cr( int n_reg, uint32_t n_value );
-static void docop2( int gteop );
-static void mips_exception( int exception );
-
-void mips_stop( void )
-{
-#ifdef MAME_DEBUG
-	extern int debug_key_pressed;
-	debug_key_pressed = 1;
-	CALL_MAME_DEBUG;
-#endif
-}
-
-static inline void mips_set_cp0r( int reg, uint32_t value )
-{
-	mipscpu.cp0r[ reg ] = value;
-	if( reg == CP0_SR || reg == CP0_CAUSE )
-	{
-		if( ( mipscpu.cp0r[ CP0_SR ] & SR_IEC ) != 0 && ( mipscpu.cp0r[ CP0_SR ] & mipscpu.cp0r[ CP0_CAUSE ] & CAUSE_IP ) != 0 )
-		{
-			mips_exception( EXC_INT );
-		}
-		else if( mipscpu.delayr != REGPC && ( mipscpu.pc & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-		{
-			mips_exception( EXC_ADEL );
-			mips_set_cp0r( CP0_BADVADDR, mipscpu.pc );
-		}
-	}
-}
-
-static inline void mips_commit_delayed_load( void )
-{
-	if( mipscpu.delayr != 0 )
-	{
-		mipscpu.r[ mipscpu.delayr ] = mipscpu.delayv;
-		mipscpu.delayr = 0;
-		mipscpu.delayv = 0;
-	}
-}
-
-static inline void mips_delayed_branch( uint32_t n_adr )
-{
-	if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-	{
-		mips_exception( EXC_ADEL );
-		mips_set_cp0r( CP0_BADVADDR, n_adr );
-	}
-	else
-	{
-		mips_commit_delayed_load();
-		mipscpu.delayr = REGPC;
-		mipscpu.delayv = n_adr;
-		mipscpu.pc += 4;
-	}
-}
-
-static inline void mips_set_pc( unsigned val )
-{
-	mipscpu.pc = val;
-	change_pc( val );
-	mipscpu.delayr = 0;
-	mipscpu.delayv = 0;
-}
-
-static inline void mips_advance_pc( void )
-{
-	if( mipscpu.delayr == REGPC )
-	{
-		mips_set_pc( mipscpu.delayv );
-	}
-	else
-	{
-		mips_commit_delayed_load();
-		mipscpu.pc += 4;
-	}
-}
-
-static inline void mips_load( uint32_t n_r, uint32_t n_v )
-{
-	mips_advance_pc();
-	if( n_r != 0 )
-	{
-		mipscpu.r[ n_r ] = n_v;
-	}
-}
-
-static inline void mips_delayed_load( uint32_t n_r, uint32_t n_v )
-{
-	if( mipscpu.delayr == REGPC )
-	{
-		mips_set_pc( mipscpu.delayv );
-		mipscpu.delayr = n_r;
-		mipscpu.delayv = n_v;
-	}
-	else
-	{
-		mips_commit_delayed_load();
-		mipscpu.pc += 4;
-		if( n_r != 0 )
-		{
-			mipscpu.r[ n_r ] = n_v;
-		}
-	}
-}
-
-static void mips_exception( int exception )
-{
-	mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~0x3f ) | ( ( mipscpu.cp0r[ CP0_SR ] << 2 ) & 0x3f ) );
-	if( mipscpu.delayr == REGPC )
-	{
-		mips_set_cp0r( CP0_EPC, mipscpu.pc - 4 );
-		mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_EXC ) | CAUSE_BD | ( exception << 2 ) );
-	}
-	else
-	{
-		mips_commit_delayed_load();
-		mips_set_cp0r( CP0_EPC, mipscpu.pc );
-		mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~( CAUSE_EXC | CAUSE_BD ) ) | ( exception << 2 ) );
-	}
-	if( mipscpu.cp0r[ CP0_SR ] & SR_BEV )
-	{
-		mips_set_pc( 0xbfc00180 );
-	}
-	else
-	{
-		mips_set_pc( 0x80000080 );
-	}
-}
-
-void mips_init( void )
-{
-#if 0
-	int cpu = cpu_getactivecpu();
-
-	state_save_register_UINT32( "psxcpu", cpu, "op", &mipscpu.op, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "pc", &mipscpu.pc, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "delayv", &mipscpu.delayv, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "delayr", &mipscpu.delayr, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "hi", &mipscpu.hi, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "lo", &mipscpu.lo, 1 );
-	state_save_register_UINT32( "psxcpu", cpu, "r", &mipscpu.r[ 0 ], 32 );
-	state_save_register_UINT32( "psxcpu", cpu, "cp0r", &mipscpu.cp0r[ 0 ], 32 );
-	state_save_register_UINT32( "psxcpu", cpu, "cp2cr", &mipscpu.cp2cr[ 0 ].d, 32 );
-	state_save_register_UINT32( "psxcpu", cpu, "cp2dr", &mipscpu.cp2dr[ 0 ].d, 32 );
-#endif
-}
-
-void mips_reset( void *param )
-{
-	mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~( SR_TS | SR_SWC | SR_KUC | SR_IEC ) ) | SR_BEV );
-	mips_set_cp0r( CP0_RANDOM, 63 ); /* todo: */
-	mips_set_cp0r( CP0_PRID, 0x00000200 ); /* todo: */
-	mips_set_pc( 0xbfc00000 );
-	mipscpu.prevpc = 0xffffffff;
-}
-
-static void mips_exit( void )
-{
-}
-
-void mips_shorten_frame(void)
-{
-	mips_ICount = 0;
-}
-
-void psx_hw_runcounters(void);
-
-int psxcpu_verbose = 0;
-
-int mips_execute( int cycles )
-{
-	uint32_t n_res;
-
-	mips_ICount = cycles;
-	do
-	{
-//		CALL_MAME_DEBUG;
-
-//		psx_hw_runcounters();
-
-		mipscpu.op = cpu_readop32( mipscpu.pc );
-
-#if 0
-		while (mipscpu.prevpc == mipscpu.pc)
-		{
-			psx_hw_runcounters();
-			mips_ICount--;
-
-			if (mips_ICount == 0) return cycles;
-		}
-#endif
-
-		// if we're not in a delay slot, update
-		// if we're in a delay slot and the delay instruction is not NOP, update
-		if (( mipscpu.delayr == 0 ) || ((mipscpu.delayr != 0) && (mipscpu.op != 0)))
-		{
-			mipscpu.prevpc = mipscpu.pc;
-		}
-#if 0
-		if (1) //psxcpu_verbose)
-		{
-			printf("[%08x: %08x] [SP %08x RA %08x V0 %08x V1 %08x A0 %08x S0 %08x S1 %08x]\n", mipscpu.pc, mipscpu.op, mipscpu.r[29], mipscpu.r[31], mipscpu.r[2], mipscpu.r[3], mipscpu.r[4], mipscpu.r[ 16 ], mipscpu.r[ 17 ]);
-//			psxcpu_verbose--;
-		}
-#endif
-		switch( INS_OP( mipscpu.op ) )
-		{
-		case OP_SPECIAL:
-			switch( INS_FUNCT( mipscpu.op ) )
-			{
-			case FUNCT_HLECALL:
-//				printf("HLECALL, PC = %08x\n", mipscpu.pc);
-				psx_bios_hle(mipscpu.pc);
-				break;
-			case FUNCT_SLL:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] << INS_SHAMT( mipscpu.op ) );
-				break;
-			case FUNCT_SRL:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] >> INS_SHAMT( mipscpu.op ) );
-				break;
-			case FUNCT_SRA:
-				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] >> INS_SHAMT( mipscpu.op ) );
-				break;
-			case FUNCT_SLLV:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] << ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
-				break;
-			case FUNCT_SRLV:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] >> ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
-				break;
-			case FUNCT_SRAV:
-				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] >> ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
-				break;
-			case FUNCT_JR:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					mips_delayed_branch( mipscpu.r[ INS_RS( mipscpu.op ) ] );
-				}
-				break;
-			case FUNCT_JALR:
-				n_res = mipscpu.pc + 8;
-				mips_delayed_branch( mipscpu.r[ INS_RS( mipscpu.op ) ] );
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mipscpu.r[ INS_RD( mipscpu.op ) ] = n_res;
-				}
-				break;
-			case FUNCT_SYSCALL:
-				mips_exception( EXC_SYS );
-				break;
-			case FUNCT_BREAK:
-				printf("BREAK!\n");
-				exit(-1);
-//				mips_exception( EXC_BP );
-				mips_advance_pc();
-				break;
-			case FUNCT_MFHI:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.hi );
-				break;
-			case FUNCT_MTHI:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					mips_advance_pc();
-					mipscpu.hi = mipscpu.r[ INS_RS( mipscpu.op ) ];
-				}
-				break;
-			case FUNCT_MFLO:
-				mips_load( INS_RD( mipscpu.op ),  mipscpu.lo );
-				break;
-			case FUNCT_MTLO:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					mips_advance_pc();
-					mipscpu.lo = mipscpu.r[ INS_RS( mipscpu.op ) ];
-				}
-				break;
-			case FUNCT_MULT:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					int64_t n_res64;
-					n_res64 = MUL_64_32_32( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ], (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-					mipscpu.lo = LO32_32_64( n_res64 );
-					mipscpu.hi = HI32_32_64( n_res64 );
-				}
-				break;
-			case FUNCT_MULTU:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					uint64_t n_res64;
-					n_res64 = MUL_U64_U32_U32( mipscpu.r[ INS_RS( mipscpu.op ) ], mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-					mipscpu.lo = LO32_U32_U64( n_res64 );
-					mipscpu.hi = HI32_U32_U64( n_res64 );
-				}
-				break;
-			case FUNCT_DIV:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					uint32_t n_div;
-					uint32_t n_mod;
-					if( mipscpu.r[ INS_RT( mipscpu.op ) ] != 0 )
-					{
-						n_div = (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] / (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ];
-						n_mod = (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] % (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ];
-						mips_advance_pc();
-						mipscpu.lo = n_div;
-						mipscpu.hi = n_mod;
-					}
-					else
-					{
-						mips_advance_pc();
-					}
-				}
-				break;
-			case FUNCT_DIVU:
-				if( INS_RD( mipscpu.op ) != 0 )
-				{
-					mips_exception( EXC_RI );
-				}
-				else
-				{
-					uint32_t n_div;
-					uint32_t n_mod;
-					if( mipscpu.r[ INS_RT( mipscpu.op ) ] != 0 )
-					{
-						n_div = mipscpu.r[ INS_RS( mipscpu.op ) ] / mipscpu.r[ INS_RT( mipscpu.op ) ];
-						n_mod = mipscpu.r[ INS_RS( mipscpu.op ) ] % mipscpu.r[ INS_RT( mipscpu.op ) ];
-						mips_advance_pc();
-						mipscpu.lo = n_div;
-						mipscpu.hi = n_mod;
-					}
-					else
-					{
-						mips_advance_pc();
-					}
-				}
-				break;
-			case FUNCT_ADD:
-				{
-					n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] + mipscpu.r[ INS_RT( mipscpu.op ) ];
-					if( (int32_t)( ~( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
-					{
-						mips_exception( EXC_OVF );
-					}
-					else
-					{
-						mips_load( INS_RD( mipscpu.op ), n_res );
-					}
-				}
-				break;
-			case FUNCT_ADDU:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] + mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_SUB:
-				n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] - mipscpu.r[ INS_RT( mipscpu.op ) ];
-				if( (int32_t)( ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
-				{
-					mips_exception( EXC_OVF );
-				}
-				else
-				{
-					mips_load( INS_RD( mipscpu.op ), n_res );
-				}
-				break;
-			case FUNCT_SUBU:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] - mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_AND:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] & mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_OR:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] | mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_XOR:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_NOR:
-				mips_load( INS_RD( mipscpu.op ), ~( mipscpu.r[ INS_RS( mipscpu.op ) ] | mipscpu.r[ INS_RT( mipscpu.op ) ] ) );
-				break;
-			case FUNCT_SLT:
-				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			case FUNCT_SLTU:
-				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] < mipscpu.r[ INS_RT( mipscpu.op ) ] );
-				break;
-			default:
-				mips_exception( EXC_RI );
-				break;
-			}
-			break;
-		case OP_REGIMM:
-			switch( INS_RT( mipscpu.op ) )
-			{
-			case RT_BLTZ:
-				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < 0 )
-				{
-					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-				}
-				else
-				{
-					mips_advance_pc();
-				}
-				break;
-			case RT_BGEZ:
-				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] >= 0 )
-				{
-					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-				}
-				else
-				{
-					mips_advance_pc();
-				}
-				break;
-			case RT_BLTZAL:
-				n_res = mipscpu.pc + 8;
-				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < 0 )
-				{
-					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-				}
-				else
-				{
-					mips_advance_pc();
-				}
-				mipscpu.r[ 31 ] = n_res;
-				break;
-			case RT_BGEZAL:
-				n_res = mipscpu.pc + 8;
-				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] >= 0 )
-				{
-					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-				}
-				else
-				{
-					mips_advance_pc();
-				}
-				mipscpu.r[ 31 ] = n_res;
-				break;
-			}
-			break;
-		case OP_J:
-			mips_delayed_branch( ( ( mipscpu.pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( mipscpu.op ) << 2 ) );
-			break;
-		case OP_JAL:
-			n_res = mipscpu.pc + 8;
-			mips_delayed_branch( ( ( mipscpu.pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( mipscpu.op ) << 2 ) );
-			mipscpu.r[ 31 ] = n_res;
-			break;
-		case OP_BEQ:
-			if( mipscpu.r[ INS_RS( mipscpu.op ) ] == mipscpu.r[ INS_RT( mipscpu.op ) ] )
-			{
-				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-			}
-			else
-			{
-				mips_advance_pc();
-			}
-			break;
-		case OP_BNE:
-			if( mipscpu.r[ INS_RS( mipscpu.op ) ] != mipscpu.r[ INS_RT( mipscpu.op ) ] )
-			{
-				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-			}
-			else
-			{
-				mips_advance_pc();
-			}
-			break;
-		case OP_BLEZ:
-			if( INS_RT( mipscpu.op ) != 0 )
-			{
-				mips_exception( EXC_RI );
-			}
-			else if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] <= 0 )
-			{
-				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-			}
-			else
-			{
-				mips_advance_pc();
-			}
-			break;
-		case OP_BGTZ:
-			if( INS_RT( mipscpu.op ) != 0 )
-			{
-				mips_exception( EXC_RI );
-			}
-			else if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] > 0 )
-			{
-				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
-			}
-			else
-			{
-				mips_advance_pc();
-			}
-			break;
-		case OP_ADDI:
-			{
-				uint32_t n_imm;
-				n_imm = MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] + n_imm;
-				if( (int32_t)( ~( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_imm ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
-				{
-					mips_exception( EXC_OVF );
-				}
-				else
-				{
-					mips_load( INS_RT( mipscpu.op ), n_res );
-				}
-			}
-			break;
-		case OP_ADDIU:
-			if (INS_RT( mipscpu.op ) == 0)
-			{
-				psx_iop_call(mipscpu.pc, INS_IMMEDIATE(mipscpu.op));
-				mips_advance_pc();
-			}
-			else
-			{
-				mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
-			}
-			break;
-		case OP_SLTI:
-			mips_load( INS_RT( mipscpu.op ), (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
-			break;
-		case OP_SLTIU:
-			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] < (uint32_t)MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
-			break;
-		case OP_ANDI:
-			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] & INS_IMMEDIATE( mipscpu.op ) );
-			break;
-		case OP_ORI:
-			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] | INS_IMMEDIATE( mipscpu.op ) );
-			break;
-		case OP_XORI:
-			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] ^ INS_IMMEDIATE( mipscpu.op ) );
-			break;
-		case OP_LUI:
-			mips_load( INS_RT( mipscpu.op ), INS_IMMEDIATE( mipscpu.op ) << 16 );
-			break;
-		case OP_COP0:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) != 0 && ( mipscpu.cp0r[ CP0_SR ] & SR_CU0 ) == 0 )
-			{
-				mips_exception( EXC_CPU );
-				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE0 );
-			}
-			else
-			{
-				switch( INS_RS( mipscpu.op ) )
-				{
-				case RS_MFC:
-					mips_delayed_load( INS_RT( mipscpu.op ), mipscpu.cp0r[ INS_RD( mipscpu.op ) ] );
-					break;
-				case RS_CFC:
-					/* todo: */
-					logerror( "%08x: COP0 CFC not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_MTC:
-					n_res = ( mipscpu.cp0r[ INS_RD( mipscpu.op ) ] & ~mips_mtc0_writemask[ INS_RD( mipscpu.op ) ] ) |
-						( mipscpu.r[ INS_RT( mipscpu.op ) ] & mips_mtc0_writemask[ INS_RD( mipscpu.op ) ] );
-					mips_advance_pc();
-					mips_set_cp0r( INS_RD( mipscpu.op ), n_res );
-					break;
-				case RS_CTC:
-					/* todo: */
-					logerror( "%08x: COP0 CTC not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_BC:
-					switch( INS_RT( mipscpu.op ) )
-					{
-					case RT_BCF:
-						/* todo: */
-						logerror( "%08x: COP0 BCF not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					case RT_BCT:
-						/* todo: */
-						logerror( "%08x: COP0 BCT not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				default:
-					switch( INS_CO( mipscpu.op ) )
-					{
-					case 1:
-						switch( INS_CF( mipscpu.op ) )
-						{
-						case CF_RFE:
-							mips_advance_pc();
-							mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~0xf ) | ( ( mipscpu.cp0r[ CP0_SR ] >> 2 ) & 0xf ) );
-							break;
-						default:
-							/* todo: */
-							logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-							mips_stop();
-							mips_advance_pc();
-							break;
-						}
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				}
-			}
-			break;
-		case OP_COP1:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
-			{
-				mips_exception( EXC_CPU );
-				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE1 );
-			}
-			else
-			{
-				switch( INS_RS( mipscpu.op ) )
-				{
-				case RS_MFC:
-					/* todo: */
-					logerror( "%08x: COP1 BCT not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_CFC:
-					/* todo: */
-					logerror( "%08x: COP1 CFC not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_MTC:
-					/* todo: */
-					logerror( "%08x: COP1 MTC not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_CTC:
-					/* todo: */
-					logerror( "%08x: COP1 CTC not supported\n", mipscpu.pc );
-					mips_stop();
-					mips_advance_pc();
-					break;
-				case RS_BC:
-					switch( INS_RT( mipscpu.op ) )
-					{
-					case RT_BCF:
-						/* todo: */
-						logerror( "%08x: COP1 BCF not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					case RT_BCT:
-						/* todo: */
-						logerror( "%08x: COP1 BCT not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				default:
-					switch( INS_CO( mipscpu.op ) )
-					{
-					case 1:
-						/* todo: */
-						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				}
-			}
-			break;
-		case OP_COP2:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
-			{
-				mips_exception( EXC_CPU );
-				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
-			}
-			else
-			{
-				switch( INS_RS( mipscpu.op ) )
-				{
-				case RS_MFC:
-					mips_delayed_load( INS_RT( mipscpu.op ), getcp2dr( INS_RD( mipscpu.op ) ) );
-					break;
-				case RS_CFC:
-					mips_delayed_load( INS_RT( mipscpu.op ), getcp2cr( INS_RD( mipscpu.op ) ) );
-					break;
-				case RS_MTC:
-					setcp2dr( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-					break;
-				case RS_CTC:
-					setcp2cr( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-					break;
-				case RS_BC:
-					switch( INS_RT( mipscpu.op ) )
-					{
-					case RT_BCF:
-						/* todo: */
-						logerror( "%08x: COP2 BCF not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					case RT_BCT:
-						/* todo: */
-						logerror( "%08x: COP2 BCT not supported\n", mipscpu.pc );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP2 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				default:
-					switch( INS_CO( mipscpu.op ) )
-					{
-					case 1:
-						docop2( INS_COFUN( mipscpu.op ) );
-						mips_advance_pc();
-						break;
-					default:
-						/* todo: */
-						logerror( "%08x: COP2 unknown command %08x\n", mipscpu.pc, mipscpu.op );
-						mips_stop();
-						mips_advance_pc();
-						break;
-					}
-					break;
-				}
-			}
-			break;
-		case OP_LB:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LB SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_BYTE_EXTEND( program_read_byte_32le( n_adr ^ 3 ) ) );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_BYTE_EXTEND( program_read_byte_32le( n_adr ) ) );
-				}
-			}
-			break;
-		case OP_LH:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LH SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_WORD_EXTEND( program_read_word_32le( n_adr ^ 2 ) ) );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_WORD_EXTEND( program_read_word_32le( n_adr ) ) );
-				}
-			}
-			break;
-		case OP_LWL:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LWL SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x00ffffff ) | ( (uint32_t)program_read_byte_32le( n_adr + 3 ) << 24 );
-						break;
-					case 1:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x0000ffff ) | ( (uint32_t)program_read_word_32le( n_adr + 1 ) << 16 );
-						break;
-					case 2:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x000000ff ) | ( (uint32_t)program_read_byte_32le( n_adr - 1 ) << 8 ) | ( (uint32_t)program_read_word_32le( n_adr ) << 16 );
-						break;
-					default:
-						n_res = program_read_dword_32le( n_adr - 3 );
-						break;
-					}
-					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x00ffffff ) | ( (uint32_t)program_read_byte_32le( n_adr ) << 24 );
-						break;
-					case 1:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x0000ffff ) | ( (uint32_t)program_read_word_32le( n_adr - 1 ) << 16 );
-						break;
-					case 2:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x000000ff ) | ( (uint32_t)program_read_word_32le( n_adr - 2 ) << 8 ) | ( (uint32_t)program_read_byte_32le( n_adr ) << 24 );
-						break;
-					default:
-						n_res = program_read_dword_32le( n_adr - 3 );
-						break;
-					}
-					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
-				}
-			}
-			break;
-		case OP_LW:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LW SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-#if 0
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-				{
-					printf("ADEL\n");
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-#endif
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), program_read_dword_32le( n_adr ) );
-				}
-			}
-			break;
-		case OP_LBU:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LBU SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), program_read_byte_32le( n_adr ^ 3 ) );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), program_read_byte_32le( n_adr ) );
-				}
-			}
-			break;
-		case OP_LHU:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LHU SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), program_read_word_32le( n_adr ^ 2 ) );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					mips_delayed_load( INS_RT( mipscpu.op ), program_read_word_32le( n_adr ) );
-				}
-			}
-			break;
-		case OP_LWR:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LWR SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 3:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffffff00 ) | program_read_byte_32le( n_adr - 3 );
-						break;
-					case 2:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffff0000 ) | program_read_word_32le( n_adr - 2 );
-						break;
-					case 1:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xff000000 ) | program_read_word_32le( n_adr - 1 ) | ( (uint32_t)program_read_byte_32le( n_adr + 1 ) << 16 );
-						break;
-					default:
-						n_res = program_read_dword_32le( n_adr );
-						break;
-					}
-					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 3:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffffff00 ) | program_read_byte_32le( n_adr );
-						break;
-					case 2:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffff0000 ) | program_read_word_32le( n_adr );
-						break;
-					case 1:
-						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xff000000 ) | program_read_byte_32le( n_adr ) | ( (uint32_t)program_read_word_32le( n_adr + 1 ) << 8 );
-						break;
-					default:
-						n_res = program_read_dword_32le( n_adr );
-						break;
-					}
-					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
-				}
-			}
-			break;
-		case OP_SB:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: SB SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_byte_32le( n_adr ^ 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_SH:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: SH SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_word_32le( n_adr ^ 2, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_SWL:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				printf("SR_ISC not supported\n");
-				logerror( "%08x: SWL SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					printf("permission violation?\n");
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						program_write_byte_32le( n_adr + 3, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
-						break;
-					case 1:
-						program_write_word_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
-						break;
-					case 2:
-						program_write_byte_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
-						program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
-						break;
-					case 3:
-						program_write_dword_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					}
-					mips_advance_pc();
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					printf("permission violation 2\n");
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
-						break;
-					case 1:
-						program_write_word_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
-						break;
-					case 2:
-						program_write_word_32le( n_adr - 2, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
-						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
-						break;
-					case 3:
-						program_write_dword_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					}
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_SW:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-/* used by bootstrap
-				logerror( "%08x: SW SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-*/
-				mips_advance_pc();
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if(0) // ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_SWR:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: SWR SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					case 1:
-						program_write_word_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						program_write_byte_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
-						break;
-					case 2:
-						program_write_word_32le( n_adr - 2, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					case 3:
-						program_write_byte_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					}
-					mips_advance_pc();
-				}
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					switch( n_adr & 3 )
-					{
-					case 0:
-						program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					case 1:
-						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						program_write_word_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
-						break;
-					case 2:
-						program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					case 3:
-						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
-						break;
-					}
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_LWC1:
-			/* todo: */
-			logerror( "%08x: COP1 LWC not supported\n", mipscpu.pc );
-			mips_stop();
-			mips_advance_pc();
-			break;
-		case OP_LWC2:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
-			{
-				mips_exception( EXC_CPU );
-				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: LWC2 SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-				{
-					mips_exception( EXC_ADEL );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					/* todo: delay? */
-					setcp2dr( INS_RT( mipscpu.op ), program_read_dword_32le( n_adr ) );
-					mips_advance_pc();
-				}
-			}
-			break;
-		case OP_SWC1:
-			/* todo: */
-			logerror( "%08x: COP1 SWC not supported\n", mipscpu.pc );
-			mips_stop();
-			mips_advance_pc();
-			break;
-		case OP_SWC2:
-			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
-			{
-				mips_exception( EXC_CPU );
-				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
-			}
-			else if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
-			{
-				/* todo: */
-				logerror( "%08x: SWC2 SR_ISC not supported\n", mipscpu.pc );
-				mips_stop();
-				mips_advance_pc();
-			}
-			else
-			{
-				uint32_t n_adr;
-				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
-				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
-				{
-					mips_exception( EXC_ADES );
-					mips_set_cp0r( CP0_BADVADDR, n_adr );
-				}
-				else
-				{
-					program_write_dword_32le( n_adr, getcp2dr( INS_RT( mipscpu.op ) ) );
-					mips_advance_pc();
-				}
-			}
-			break;
-		default:
-			printf( "%08x: unknown opcode %08x (prev %08x, RA %08x)\n", mipscpu.pc, mipscpu.op, mipscpu.prevpc,  mipscpu.r[31] );
-			mips_stop();
-			mips_exception( EXC_RI );
-  			break;
-		}
-		mips_ICount--;
-	} while( mips_ICount > 0 );
-
-	return cycles - mips_ICount;
-}
-
-static void mips_get_context( void *dst )
-{
-	if( dst )
-	{
-		*(mips_cpu_context *)dst = mipscpu;
-	}
-}
-
-static void mips_set_context( void *src )
-{
-	if( src )
-	{
-		mipscpu = *(mips_cpu_context *)src;
-		change_pc( mipscpu.pc );
-	}
-}
-
-static void set_irq_line( int irqline, int state )
-{
-	uint32_t ip;
-
-	switch( irqline )
-	{
-	case MIPS_IRQ0:
-		ip = CAUSE_IP2;
-		break;
-	case MIPS_IRQ1:
-		ip = CAUSE_IP3;
-		break;
-	case MIPS_IRQ2:
-		ip = CAUSE_IP4;
-		break;
-	case MIPS_IRQ3:
-		ip = CAUSE_IP5;
-		break;
-	case MIPS_IRQ4:
-		ip = CAUSE_IP6;
-		break;
-	case MIPS_IRQ5:
-		ip = CAUSE_IP7;
-		break;
-	default:
-		return;
-	}
-
-	switch( state )
-	{
-	case CLEAR_LINE:
-		mips_set_cp0r( CP0_CAUSE, mipscpu.cp0r[ CP0_CAUSE ] & ~ip );
-		break;
-	case ASSERT_LINE:
-		mips_set_cp0r( CP0_CAUSE, mipscpu.cp0r[ CP0_CAUSE ] |= ip );
-		if( mipscpu.irq_callback )
-		{
-			/* HOLD_LINE interrupts are not supported by the architecture.
-			By acknowledging the interupt here they are treated like PULSE_LINE
-			interrupts, so if the interrupt isn't enabled it will be ignored.
-			There is also a problem with PULSE_LINE interrupts as the interrupt
-			pending bits aren't latched the emulated code won't know what caused
-			the interrupt. */
-			(*mipscpu.irq_callback)( irqline );
-		}
-		break;
-	}
-}
-
-/****************************************************************************
- * Return a formatted string for a register
- ****************************************************************************/
-
-offs_t mips_dasm( char *buffer, offs_t pc )
-{
-	offs_t ret;
-	change_pc( pc );
-#ifdef MAME_DEBUG
-	ret = DasmMIPS( buffer, pc );
-#else
-	sprintf( buffer, "$%08x", cpu_readop32( pc ) );
-	ret = 4;
-#endif
-	change_pc( mipscpu.pc );
-	return ret;
-}
-
-/* preliminary gte code */
-
-#define VXY0 ( mipscpu.cp2dr[ 0 ].d )
-#define VX0  ( mipscpu.cp2dr[ 0 ].w.l )
-#define VY0  ( mipscpu.cp2dr[ 0 ].w.h )
-#define VZ0  ( mipscpu.cp2dr[ 1 ].w.l )
-#define VXY1 ( mipscpu.cp2dr[ 2 ].d )
-#define VX1  ( mipscpu.cp2dr[ 2 ].w.l )
-#define VY1  ( mipscpu.cp2dr[ 2 ].w.h )
-#define VZ1  ( mipscpu.cp2dr[ 3 ].w.l )
-#define VXY2 ( mipscpu.cp2dr[ 4 ].d )
-#define VX2  ( mipscpu.cp2dr[ 4 ].w.l )
-#define VY2  ( mipscpu.cp2dr[ 4 ].w.h )
-#define VZ2  ( mipscpu.cp2dr[ 5 ].w.l )
-#define RGB  ( mipscpu.cp2dr[ 6 ].d )
-#define R    ( mipscpu.cp2dr[ 6 ].b.l )
-#define G    ( mipscpu.cp2dr[ 6 ].b.h )
-#define B    ( mipscpu.cp2dr[ 6 ].b.h2 )
-#define CODE ( mipscpu.cp2dr[ 6 ].b.h3 )
-#define OTZ  ( mipscpu.cp2dr[ 7 ].w.l )
-#define IR0  ( mipscpu.cp2dr[ 8 ].d )
-#define IR1  ( mipscpu.cp2dr[ 9 ].d )
-#define IR2  ( mipscpu.cp2dr[ 10 ].d )
-#define IR3  ( mipscpu.cp2dr[ 11 ].d )
-#define SXY0 ( mipscpu.cp2dr[ 12 ].d )
-#define SX0  ( mipscpu.cp2dr[ 12 ].w.l )
-#define SY0  ( mipscpu.cp2dr[ 12 ].w.h )
-#define SXY1 ( mipscpu.cp2dr[ 13 ].d )
-#define SX1  ( mipscpu.cp2dr[ 13 ].w.l )
-#define SY1  ( mipscpu.cp2dr[ 13 ].w.h )
-#define SXY2 ( mipscpu.cp2dr[ 14 ].d )
-#define SX2  ( mipscpu.cp2dr[ 14 ].w.l )
-#define SY2  ( mipscpu.cp2dr[ 14 ].w.h )
-#define SXYP ( mipscpu.cp2dr[ 15 ].d )
-#define SXP  ( mipscpu.cp2dr[ 15 ].w.l )
-#define SYP  ( mipscpu.cp2dr[ 15 ].w.h )
-#define SZ0  ( mipscpu.cp2dr[ 16 ].w.l )
-#define SZ1  ( mipscpu.cp2dr[ 17 ].w.l )
-#define SZ2  ( mipscpu.cp2dr[ 18 ].w.l )
-#define SZ3  ( mipscpu.cp2dr[ 19 ].w.l )
-#define RGB0 ( mipscpu.cp2dr[ 20 ].d )
-#define R0   ( mipscpu.cp2dr[ 20 ].b.l )
-#define G0   ( mipscpu.cp2dr[ 20 ].b.h )
-#define B0   ( mipscpu.cp2dr[ 20 ].b.h2 )
-#define CD0  ( mipscpu.cp2dr[ 20 ].b.h3 )
-#define RGB1 ( mipscpu.cp2dr[ 21 ].d )
-#define R1   ( mipscpu.cp2dr[ 21 ].b.l )
-#define G1   ( mipscpu.cp2dr[ 21 ].b.h )
-#define B1   ( mipscpu.cp2dr[ 21 ].b.h2 )
-#define CD1  ( mipscpu.cp2dr[ 21 ].b.h3 )
-#define RGB2 ( mipscpu.cp2dr[ 22 ].d )
-#define R2   ( mipscpu.cp2dr[ 22 ].b.l )
-#define G2   ( mipscpu.cp2dr[ 22 ].b.h )
-#define B2   ( mipscpu.cp2dr[ 22 ].b.h2 )
-#define CD2  ( mipscpu.cp2dr[ 22 ].b.h3 )
-#define RES1 ( mipscpu.cp2dr[ 23 ].d )
-#define MAC0 ( mipscpu.cp2dr[ 24 ].d )
-#define MAC1 ( mipscpu.cp2dr[ 25 ].d )
-#define MAC2 ( mipscpu.cp2dr[ 26 ].d )
-#define MAC3 ( mipscpu.cp2dr[ 27 ].d )
-#define IRGB ( mipscpu.cp2dr[ 28 ].d )
-#define ORGB ( mipscpu.cp2dr[ 29 ].d )
-#define LZCS ( mipscpu.cp2dr[ 30 ].d )
-#define LZCR ( mipscpu.cp2dr[ 31 ].d )
-
-#define D1  ( mipscpu.cp2cr[ 0 ].d )
-#define R11 ( mipscpu.cp2cr[ 0 ].w.l )
-#define R12 ( mipscpu.cp2cr[ 0 ].w.h )
-#define R13 ( mipscpu.cp2cr[ 1 ].w.l )
-#define R21 ( mipscpu.cp2cr[ 1 ].w.h )
-#define D2  ( mipscpu.cp2cr[ 2 ].d )
-#define R22 ( mipscpu.cp2cr[ 2 ].w.l )
-#define R23 ( mipscpu.cp2cr[ 2 ].w.h )
-#define R31 ( mipscpu.cp2cr[ 3 ].w.l )
-#define R32 ( mipscpu.cp2cr[ 3 ].w.h )
-#define D3  ( mipscpu.cp2cr[ 4 ].d )
-#define R33 ( mipscpu.cp2cr[ 4 ].w.l )
-#define TRX ( mipscpu.cp2cr[ 5 ].d )
-#define TRY ( mipscpu.cp2cr[ 6 ].d )
-#define TRZ ( mipscpu.cp2cr[ 7 ].d )
-#define L11 ( mipscpu.cp2cr[ 8 ].w.l )
-#define L12 ( mipscpu.cp2cr[ 8 ].w.h )
-#define L13 ( mipscpu.cp2cr[ 9 ].w.l )
-#define L21 ( mipscpu.cp2cr[ 9 ].w.h )
-#define L22 ( mipscpu.cp2cr[ 10 ].w.l )
-#define L23 ( mipscpu.cp2cr[ 10 ].w.h )
-#define L31 ( mipscpu.cp2cr[ 11 ].w.l )
-#define L32 ( mipscpu.cp2cr[ 11 ].w.h )
-#define L33 ( mipscpu.cp2cr[ 12 ].w.l )
-#define RBK ( mipscpu.cp2cr[ 13 ].d )
-#define GBK ( mipscpu.cp2cr[ 14 ].d )
-#define BBK ( mipscpu.cp2cr[ 15 ].d )
-#define LR1 ( mipscpu.cp2cr[ 16 ].w.l )
-#define LR2 ( mipscpu.cp2cr[ 16 ].w.h )
-#define LR3 ( mipscpu.cp2cr[ 17 ].w.l )
-#define LG1 ( mipscpu.cp2cr[ 17 ].w.h )
-#define LG2 ( mipscpu.cp2cr[ 18 ].w.l )
-#define LG3 ( mipscpu.cp2cr[ 18 ].w.h )
-#define LB1 ( mipscpu.cp2cr[ 19 ].w.l )
-#define LB2 ( mipscpu.cp2cr[ 19 ].w.h )
-#define LB3 ( mipscpu.cp2cr[ 20 ].w.l )
-#define RFC ( mipscpu.cp2cr[ 21 ].d )
-#define GFC ( mipscpu.cp2cr[ 22 ].d )
-#define BFC ( mipscpu.cp2cr[ 23 ].d )
-#define OFX ( mipscpu.cp2cr[ 24 ].d )
-#define OFY ( mipscpu.cp2cr[ 25 ].d )
-#define H   ( mipscpu.cp2cr[ 26 ].w.l )
-#define DQA ( mipscpu.cp2cr[ 27 ].w.l )
-#define DQB ( mipscpu.cp2cr[ 28 ].d )
-#define ZSF3 ( mipscpu.cp2cr[ 29 ].w.l )
-#define ZSF4 ( mipscpu.cp2cr[ 30 ].w.l )
-#define FLAG ( mipscpu.cp2cr[ 31 ].d )
-
-static uint32_t getcp2dr( int n_reg )
-{
-	if( n_reg == 1 || n_reg == 3 || n_reg == 5 || n_reg == 8 || n_reg == 9 || n_reg == 10 || n_reg == 11 )
-	{
-		mipscpu.cp2dr[ n_reg ].d = (int32_t)(int16_t)mipscpu.cp2dr[ n_reg ].d;
-	}
-	else if( n_reg == 17 || n_reg == 18 || n_reg == 19 )
-	{
-		mipscpu.cp2dr[ n_reg ].d = (uint32_t)(uint16_t)mipscpu.cp2dr[ n_reg ].d;
-	}
-	else if( n_reg == 29 )
-	{
-		ORGB = ( ( IR1 >> 7 ) & 0x1f ) | ( ( IR2 >> 2 ) & 0x3e0 ) | ( ( IR3 << 3 ) & 0x7c00 );
-	}
-	GTELOG( "get CP2DR%u=%08x", n_reg, mipscpu.cp2dr[ n_reg ].d );
-	return mipscpu.cp2dr[ n_reg ].d;
-}
-
-static void setcp2dr( int n_reg, uint32_t n_value )
-{
-	GTELOG( "set CP2DR%u=%08x", n_reg, n_value );
-	mipscpu.cp2dr[ n_reg ].d = n_value;
-
-	if( n_reg == 15 )
-	{
-		SXY0 = SXY1;
-		SXY1 = SXY2;
-		SXY2 = SXYP;
-	}
-	else if( n_reg == 28 )
-	{
-		IR1 = ( IRGB & 0x1f ) << 4;
-		IR2 = ( IRGB & 0x3e0 ) >> 1;
-		IR3 = ( IRGB & 0x7c00 ) >> 6;
-	}
-	else if( n_reg == 30 )
-	{
-		uint32_t n_lzcs = LZCS;
-		uint32_t n_lzcr = 0;
-
-		if( ( n_lzcs & 0x80000000 ) == 0 )
-		{
-			n_lzcs = ~n_lzcs;
-		}
-		while( ( n_lzcs & 0x80000000 ) != 0 )
-		{
-			n_lzcr++;
-			n_lzcs <<= 1;
-		}
-		LZCR = n_lzcr;
-	}
-}
-
-static uint32_t getcp2cr( int n_reg )
-{
-	GTELOG( "get CP2CR%u=%08x", n_reg, mipscpu.cp2cr[ n_reg ].d );
-	return mipscpu.cp2cr[ n_reg ].d;
-}
-
-static void setcp2cr( int n_reg, uint32_t n_value )
-{
-	GTELOG( "set CP2CR%u=%08x", n_reg, n_value );
-	mipscpu.cp2cr[ n_reg ].d = n_value;
-}
-
-static inline int32_t LIM( int32_t n_value, int32_t n_max, int32_t n_min, uint32_t n_flag )
-{
-	if( n_value > n_max )
-	{
-		FLAG |= n_flag;
-		return n_max;
-	}
-	else if( n_value < n_min )
-	{
-		FLAG |= n_flag;
-		return n_min;
-	}
-	return n_value;
-}
-
-static inline int64_t BOUNDS( int64_t n_value, int64_t n_max, int n_maxflag, int64_t n_min, int n_minflag )
-{
-	if( n_value > n_max )
-	{
-		FLAG |= n_maxflag;
-	}
-	else if( n_value < n_min )
-	{
-		FLAG |= n_minflag;
-	}
-	return n_value;
-}
-
-#define A1( a ) BOUNDS( ( a ), 0x7fffffff, 30, -(int64_t)0x80000000, ( 1 << 27 ) )
-#define A2( a ) BOUNDS( ( a ), 0x7fffffff, 29, -(int64_t)0x80000000, ( 1 << 26 ) )
-#define A3( a ) BOUNDS( ( a ), 0x7fffffff, 28, -(int64_t)0x80000000, ( 1 << 25 ) )
-#define Lm_B1( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 24 ) )
-#define Lm_B2( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 23 ) )
-#define Lm_B3( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 22 ) )
-#define Lm_C1( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 21 ) )
-#define Lm_C2( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 20 ) )
-#define Lm_C3( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 19 ) )
-#define Lm_D( a ) LIM( ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) )
-
-static inline uint32_t Lm_E( uint32_t n_z )
-{
-	if( n_z <= H / 2 )
-	{
-		n_z = H / 2;
-		FLAG |= ( 1 << 31 ) | ( 1 << 17 );
-	}
-	if( n_z == 0 )
-	{
-		n_z = 1;
-	}
-	return n_z;
-}
-
-#define F( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 16 ), -(int64_t)0x80000000, ( 1 << 31 ) | ( 1 << 15 ) )
-#define Lm_G1( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) )
-#define Lm_G2( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) )
-#define Lm_H( a ) LIM( ( a ), 0xfff, 0x000, ( 1 << 12 ) )
-
-static void docop2( int gteop )
-{
-	int n_sf;
-	int n_v;
-	int n_lm;
-	int n_pass;
-	uint16_t n_v1;
-	uint16_t n_v2;
-	uint16_t n_v3;
-	const uint16_t **p_n_mx;
-	const uint32_t **p_n_cv;
-	static const uint16_t n_zm = 0;
-	static const uint32_t n_zc = 0;
-	static const uint16_t *p_n_vx[] = { &VX0, &VX1, &VX2 };
-	static const uint16_t *p_n_vy[] = { &VY0, &VY1, &VY2 };
-	static const uint16_t *p_n_vz[] = { &VZ0, &VZ1, &VZ2 };
-	static const uint16_t *p_n_rm[] = { &R11, &R12, &R13, &R21, &R22, &R23, &R31, &R32, &R33 };
-	static const uint16_t *p_n_lm[] = { &L11, &L12, &L13, &L21, &L22, &L23, &L31, &L32, &L33 };
-	static const uint16_t *p_n_cm[] = { &LR1, &LR2, &LR3, &LG1, &LG2, &LG3, &LB1, &LB2, &LB3 };
-	static const uint16_t *p_n_zm[] = { &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm };
-	static const uint16_t **p_p_n_mx[] = { p_n_rm, p_n_lm, p_n_cm, p_n_zm };
-	static const uint32_t *p_n_tr[] = { &TRX, &TRY, &TRZ };
-	static const uint32_t *p_n_bk[] = { &RBK, &GBK, &BBK };
-	static const uint32_t *p_n_fc[] = { &RFC, &GFC, &BFC };
-	static const uint32_t *p_n_zc[] = { &n_zc, &n_zc, &n_zc };
-	static const uint32_t **p_p_n_cv[] = { p_n_tr, p_n_bk, p_n_fc, p_n_zc };
-
-	switch( GTE_FUNCT( gteop ) )
-	{
-	case 0x01:
-		if( gteop == 0x0180001 )
-		{
-			GTELOG( "RTPS" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int32_t)TRX << 12 ) + ( (int16_t)R11 * (int16_t)VX0 ) + ( (int16_t)R12 * (int16_t)VY0 ) + ( (int16_t)R13 * (int16_t)VZ0 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)(int32_t)TRY << 12 ) + ( (int16_t)R21 * (int16_t)VX0 ) + ( (int16_t)R22 * (int16_t)VY0 ) + ( (int16_t)R23 * (int16_t)VZ0 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)(int32_t)TRZ << 12 ) + ( (int16_t)R31 * (int16_t)VX0 ) + ( (int16_t)R32 * (int16_t)VY0 ) + ( (int16_t)R33 * (int16_t)VZ0 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			SZ0 = SZ1;
-			SZ1 = SZ2;
-			SZ2 = SZ3;
-			SZ3 = Lm_D( (int32_t)MAC3 );
-			SXY0 = SXY1;
-			SXY1 = SXY2;
-			SX2 = Lm_G1( F( (int64_t)(int32_t)OFX + ( (int64_t)(int16_t)IR1 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 );
-			SY2 = Lm_G2( F( (int64_t)(int32_t)OFY + ( (int64_t)(int16_t)IR2 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 );
-			MAC0 = F( (int64_t)(int32_t)DQB + ( (int64_t)(int16_t)DQA * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) );
-			IR0 = Lm_H( (int32_t)MAC0 >> 12 );
-			return;
-		}
-		break;
-	case 0x06:
-		if( gteop == 0x0400006 ||
-			gteop == 0x1400006 ||
-			gteop == 0x0155cc6 )
-		{
-			GTELOG( "NCLIP" );
-			FLAG = 0;
-
-			MAC0 = F( ( (int64_t)(int16_t)SX0 * (int16_t)SY1 ) + ( (int16_t)SX1 * (int16_t)SY2 ) + ( (int16_t)SX2 * (int16_t)SY0 ) - ( (int16_t)SX0 * (int16_t)SY2 ) - ( (int16_t)SX1 * (int16_t)SY0 ) - ( (int16_t)SX2 * (int16_t)SY1 ) );
-			return;
-		}
-		break;
-	case 0x0c:
-		if( GTE_OP( gteop ) == 0x17 )
-		{
-			GTELOG( "OP" );
-			n_sf = 12 * GTE_SF( gteop );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int32_t)D2 * (int16_t)IR3 ) - ( (int64_t)(int32_t)D3 * (int16_t)IR2 ) ) >> n_sf );
-			MAC2 = A2( ( ( (int64_t)(int32_t)D3 * (int16_t)IR1 ) - ( (int64_t)(int32_t)D1 * (int16_t)IR3 ) ) >> n_sf );
-			MAC3 = A3( ( ( (int64_t)(int32_t)D1 * (int16_t)IR2 ) - ( (int64_t)(int32_t)D2 * (int16_t)IR1 ) ) >> n_sf );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			return;
-		}
-		break;
-	case 0x10:
-		if( gteop == 0x0780010 )
-		{
-			GTELOG( "DPCS" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)R << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - ( R << 4 ), 0 ) ) ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)G << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - ( G << 4 ), 0 ) ) ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)B << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - ( B << 4 ), 0 ) ) ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x11:
-		if( gteop == 0x0980011 )
-		{
-			GTELOG( "INTPL" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int16_t)IR1 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - (int16_t)IR1, 0 ) ) ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)(int16_t)IR2 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - (int16_t)IR2, 0 ) ) ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)(int16_t)IR3 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - (int16_t)IR3, 0 ) ) ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 );
-			return;
-		}
-		break;
-	case 0x12:
-		if( GTE_OP( gteop ) == 0x04 )
-		{
-			GTELOG( "MVMVA" );
-			n_sf = 12 * GTE_SF( gteop );
-			p_n_mx = p_p_n_mx[ GTE_MX( gteop ) ];
-			n_v = GTE_V( gteop );
-			if( n_v < 3 )
-			{
-				n_v1 = *p_n_vx[ n_v ];
-				n_v2 = *p_n_vy[ n_v ];
-				n_v3 = *p_n_vz[ n_v ];
-			}
-			else
-			{
-				n_v1 = IR1;
-				n_v2 = IR2;
-				n_v3 = IR3;
-			}
-			p_n_cv = p_p_n_cv[ GTE_CV( gteop ) ];
-			n_lm = GTE_LM( gteop );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int32_t)*p_n_cv[ 0 ] << 12 ) + ( (int16_t)*p_n_mx[ 0 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 1 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 2 ] * (int16_t)n_v3 ) ) >> n_sf );
-			MAC2 = A2( ( ( (int64_t)(int32_t)*p_n_cv[ 1 ] << 12 ) + ( (int16_t)*p_n_mx[ 3 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 4 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 5 ] * (int16_t)n_v3 ) ) >> n_sf );
-			MAC3 = A3( ( ( (int64_t)(int32_t)*p_n_cv[ 2 ] << 12 ) + ( (int16_t)*p_n_mx[ 6 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 7 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 8 ] * (int16_t)n_v3 ) ) >> n_sf );
-
-			IR1 = Lm_B1( (int32_t)MAC1, n_lm );
-			IR2 = Lm_B2( (int32_t)MAC2, n_lm );
-			IR3 = Lm_B3( (int32_t)MAC3, n_lm );
-			return;
-		}
-		break;
-	case 0x13:
-		if( gteop == 0x0e80413 )
-		{
-			GTELOG( "NCDS" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
-			MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
-			MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x14:
-		if( gteop == 0x1280414 )
-		{
-			GTELOG( "CDP" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-			IR1 = Lm_B1( MAC1, 1 );
-			IR2 = Lm_B2( MAC2, 1 );
-			IR3 = Lm_B3( MAC3, 1 );
-			MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
-			MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
-			MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
-			IR1 = Lm_B1( MAC1, 1 );
-			IR2 = Lm_B2( MAC2, 1 );
-			IR3 = Lm_B3( MAC3, 1 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x16:
-		if( gteop == 0x0f80416 )
-		{
-			GTELOG( "NCDT" );
-			FLAG = 0;
-
-			for( n_v = 0; n_v < 3; n_v++ )
-			{
-				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
-				MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
-				MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				CD0 = CD1;
-				CD1 = CD2;
-				CD2 = CODE;
-				R0 = R1;
-				R1 = R2;
-				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-				G0 = G1;
-				G1 = G2;
-				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-				B0 = B1;
-				B1 = B2;
-				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			}
-			return;
-		}
-		break;
-	case 0x1b:
-		if( gteop == 0x108041b )
-		{
-			GTELOG( "NCCS" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
-			MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
-			MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x1c:
-		if( gteop == 0x138041c )
-		{
-			GTELOG( "CC" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-			IR1 = Lm_B1( MAC1, 1 );
-			IR2 = Lm_B2( MAC2, 1 );
-			IR3 = Lm_B3( MAC3, 1 );
-			MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
-			MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
-			MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
-			IR1 = Lm_B1( MAC1, 1 );
-			IR2 = Lm_B2( MAC2, 1 );
-			IR3 = Lm_B3( MAC3, 1 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x1e:
-		if( gteop == 0x0c8041e )
-		{
-			GTELOG( "NCS" );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-			IR1 = Lm_B1( (int32_t)MAC1, 1 );
-			IR2 = Lm_B2( (int32_t)MAC2, 1 );
-			IR3 = Lm_B3( (int32_t)MAC3, 1 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x20:
-		if( gteop == 0x0d80420 )
-		{
-			GTELOG( "NCT" );
-			FLAG = 0;
-
-			for( n_v = 0; n_v < 3; n_v++ )
-			{
-				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				CD0 = CD1;
-				CD1 = CD2;
-				CD2 = CODE;
-				R0 = R1;
-				R1 = R2;
-				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-				G0 = G1;
-				G1 = G2;
-				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-				B0 = B1;
-				B1 = B2;
-				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			}
-			return;
-		}
-		break;
-	case 0x28:
-		if( GTE_OP( gteop ) == 0x0a && GTE_LM( gteop ) == 1 )
-		{
-			GTELOG( "SQR" );
-			n_sf = 12 * GTE_SF( gteop );
-			FLAG = 0;
-
-			MAC1 = A1( ( (int64_t)(int16_t)IR1 * (int16_t)IR1 ) >> n_sf );
-			MAC2 = A2( ( (int64_t)(int16_t)IR2 * (int16_t)IR2 ) >> n_sf );
-			MAC3 = A3( ( (int64_t)(int16_t)IR3 * (int16_t)IR3 ) >> n_sf );
-			IR1 = Lm_B1( MAC1, 1 );
-			IR2 = Lm_B2( MAC2, 1 );
-			IR3 = Lm_B3( MAC3, 1 );
-			return;
-		}
-		break;
-	// DCPL 0x29
-	case 0x2a:
-		if( gteop == 0x0f8002a )
-		{
-			GTELOG( "DPCT" );
-			FLAG = 0;
-
-			for( n_pass = 0; n_pass < 3; n_pass++ )
-			{
-				MAC1 = A1( ( ( (int64_t)R0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - ( R0 << 4 ), 0 ) ) ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)G0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - ( G0 << 4 ), 0 ) ) ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)B0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - ( B0 << 4 ), 0 ) ) ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 0 );
-				IR2 = Lm_B2( (int32_t)MAC2, 0 );
-				IR3 = Lm_B3( (int32_t)MAC3, 0 );
-				CD0 = CD1;
-				CD1 = CD2;
-				CD2 = CODE;
-				R0 = R1;
-				R1 = R2;
-				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-				G0 = G1;
-				G1 = G2;
-				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-				B0 = B1;
-				B1 = B2;
-				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			}
-			return;
-		}
-		break;
-	case 0x2d:
-		if( gteop == 0x158002d )
-		{
-			GTELOG( "AVSZ3" );
-			FLAG = 0;
-
-			MAC0 = F( ( (int64_t)(int16_t)ZSF3 * SZ1 ) + ( (int16_t)ZSF3 * SZ2 ) + ( (int16_t)ZSF3 * SZ3 ) );
-			OTZ = Lm_D( (int32_t)MAC0 >> 12 );
-			return;
-		}
-		break;
-	case 0x2e:
-		if( gteop == 0x168002e )
-		{
-			GTELOG( "AVSZ4" );
-			FLAG = 0;
-
-			MAC0 = F( ( (int64_t)(int16_t)ZSF4 * SZ0 ) + ( (int16_t)ZSF4 * SZ1 ) + ( (int16_t)ZSF4 * SZ2 ) + ( (int16_t)ZSF4 * SZ3 ) );
-			OTZ = Lm_D( (int32_t)MAC0 >> 12 );
-			return;
-		}
-		break;
-	case 0x30:
-		if( gteop == 0x0280030 )
-		{
-			GTELOG( "RTPT" );
-			FLAG = 0;
-
-			for( n_v = 0; n_v < 3; n_v++ )
-			{
-				MAC1 = A1( ( ( (int64_t)(int32_t)TRX << 12 ) + ( (int16_t)R11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)(int32_t)TRY << 12 ) + ( (int16_t)R21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)(int32_t)TRZ << 12 ) + ( (int16_t)R31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 0 );
-				IR2 = Lm_B2( (int32_t)MAC2, 0 );
-				IR3 = Lm_B3( (int32_t)MAC3, 0 );
-				SZ0 = SZ1;
-				SZ1 = SZ2;
-				SZ2 = SZ3;
-				SZ3 = Lm_D( (int32_t)MAC3 );
-				SXY0 = SXY1;
-				SXY1 = SXY2;
-				SX2 = Lm_G1( F( ( (int64_t)(int32_t)OFX + ( (int64_t)(int16_t)IR1 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 ) );
-				SY2 = Lm_G2( F( ( (int64_t)(int32_t)OFY + ( (int64_t)(int16_t)IR2 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 ) );
-				MAC0 = F( (int64_t)(int32_t)DQB + ( (int64_t)(int16_t)DQA * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) );
-				IR0 = Lm_H( (int32_t)MAC0 >> 12 );
-			}
-			return;
-		}
-		break;
-	case 0x3d:
-		if( GTE_OP( gteop ) == 0x09 ||
-			GTE_OP( gteop ) == 0x19 )
-		{
-			GTELOG( "GPF" );
-			n_sf = 12 * GTE_SF( gteop );
-			FLAG = 0;
-
-			MAC1 = A1( ( (int64_t)(int16_t)IR0 * (int16_t)IR1 ) >> n_sf );
-			MAC2 = A2( ( (int64_t)(int16_t)IR0 * (int16_t)IR2 ) >> n_sf );
-			MAC3 = A3( ( (int64_t)(int16_t)IR0 * (int16_t)IR3 ) >> n_sf );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x3e:
-		if( GTE_OP( gteop ) == 0x1a )
-		{
-			GTELOG( "GPL" );
-			n_sf = 12 * GTE_SF( gteop );
-			FLAG = 0;
-
-			MAC1 = A1( ( ( (int64_t)(int32_t)MAC1 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR1 ) ) >> n_sf );
-			MAC2 = A2( ( ( (int64_t)(int32_t)MAC2 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR2 ) ) >> n_sf );
-			MAC3 = A3( ( ( (int64_t)(int32_t)MAC3 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR3 ) ) >> n_sf );
-			IR1 = Lm_B1( (int32_t)MAC1, 0 );
-			IR2 = Lm_B2( (int32_t)MAC2, 0 );
-			IR3 = Lm_B3( (int32_t)MAC3, 0 );
-			CD0 = CD1;
-			CD1 = CD2;
-			CD2 = CODE;
-			R0 = R1;
-			R1 = R2;
-			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-			G0 = G1;
-			G1 = G2;
-			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-			B0 = B1;
-			B1 = B2;
-			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			return;
-		}
-		break;
-	case 0x3f:
-		if( gteop == 0x108043f ||
-			gteop == 0x118043f )
-		{
-			GTELOG( "NCCT" );
-			FLAG = 0;
-
-			for( n_v = 0; n_v < 3; n_v++ )
-			{
-				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
-				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
-				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
-				MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
-				MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
-				IR1 = Lm_B1( (int32_t)MAC1, 1 );
-				IR2 = Lm_B2( (int32_t)MAC2, 1 );
-				IR3 = Lm_B3( (int32_t)MAC3, 1 );
-				CD0 = CD1;
-				CD1 = CD2;
-				CD2 = CODE;
-				R0 = R1;
-				R1 = R2;
-				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
-				G0 = G1;
-				G1 = G2;
-				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
-				B0 = B1;
-				B1 = B2;
-				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
-			}
-			return;
-		}
-		break;
-	}
-//	usrintf_showmessage_secs( 1, "unknown GTE op %08x", gteop );
-	logerror( "%08x: unknown GTE op %08x\n", mipscpu.pc, gteop );
-	mips_stop();
-}
-
-/**************************************************************************
- * Generic set_info
- **************************************************************************/
-
-void mips_set_info(uint32_t state, union cpuinfo *info)
-{
-	switch (state)
-	{
-		/* --- the following bits of info are set as 64-bit signed integers --- */
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0:		set_irq_line(MIPS_IRQ0, info->i);		break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1:		set_irq_line(MIPS_IRQ1, info->i);		break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2:		set_irq_line(MIPS_IRQ2, info->i);		break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3:		set_irq_line(MIPS_IRQ3, info->i);		break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4:		set_irq_line(MIPS_IRQ4, info->i);		break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5:		set_irq_line(MIPS_IRQ5, info->i);		break;
-
-		case CPUINFO_INT_PC:							mips_set_pc( info->i );					break;
-		case CPUINFO_INT_REGISTER + MIPS_PC:			mips_set_pc( info->i );					break;
-		case CPUINFO_INT_SP:							/* no stack */							break;
-		case CPUINFO_INT_REGISTER + MIPS_DELAYV:		mipscpu.delayv = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_DELAYR:		if( info->i <= REGPC ) mipscpu.delayr = info->i; break;
-		case CPUINFO_INT_REGISTER + MIPS_HI:			mipscpu.hi = info->i;					break;
-		case CPUINFO_INT_REGISTER + MIPS_LO:			mipscpu.lo = info->i;					break;
-		case CPUINFO_INT_REGISTER + MIPS_R0:			mipscpu.r[ 0 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R1:			mipscpu.r[ 1 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R2:			mipscpu.r[ 2 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R3:			mipscpu.r[ 3 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R4:			mipscpu.r[ 4 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R5:			mipscpu.r[ 5 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R6:			mipscpu.r[ 6 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R7:			mipscpu.r[ 7 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R8:			mipscpu.r[ 8 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R9:			mipscpu.r[ 9 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R10:			mipscpu.r[ 10 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R11:			mipscpu.r[ 11 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R12:			mipscpu.r[ 12 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R13:			mipscpu.r[ 13 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R14:			mipscpu.r[ 14 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R15:			mipscpu.r[ 15 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R16:			mipscpu.r[ 16 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R17:			mipscpu.r[ 17 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R18:			mipscpu.r[ 18 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R19:			mipscpu.r[ 19 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R20:			mipscpu.r[ 20 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R21:			mipscpu.r[ 21 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R22:			mipscpu.r[ 22 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R23:			mipscpu.r[ 23 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R24:			mipscpu.r[ 24 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R25:			mipscpu.r[ 25 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R26:			mipscpu.r[ 26 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R27:			mipscpu.r[ 27 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R28:			mipscpu.r[ 28 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R29:			mipscpu.r[ 29 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R30:			mipscpu.r[ 30 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_R31:			mipscpu.r[ 31 ] = info->i;				break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R0:			mips_set_cp0r( 0, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R1:			mips_set_cp0r( 1, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R2:			mips_set_cp0r( 2, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R3:			mips_set_cp0r( 3, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R4:			mips_set_cp0r( 4, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R5:			mips_set_cp0r( 5, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R6:			mips_set_cp0r( 6, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R7:			mips_set_cp0r( 7, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R8:			mips_set_cp0r( 8, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R9:			mips_set_cp0r( 9, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R10:		mips_set_cp0r( 10, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R11:		mips_set_cp0r( 11, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R12:		mips_set_cp0r( 12, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R13:		mips_set_cp0r( 13, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R14:		mips_set_cp0r( 14, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R15:		mips_set_cp0r( 15, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R16:		mips_set_cp0r( 16, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R17:		mips_set_cp0r( 17, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R18:		mips_set_cp0r( 18, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R19:		mips_set_cp0r( 19, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R20:		mips_set_cp0r( 20, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R21:		mips_set_cp0r( 21, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R22:		mips_set_cp0r( 22, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R23:		mips_set_cp0r( 23, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R24:		mips_set_cp0r( 24, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R25:		mips_set_cp0r( 25, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R26:		mips_set_cp0r( 26, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R27:		mips_set_cp0r( 27, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R28:		mips_set_cp0r( 28, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R29:		mips_set_cp0r( 29, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R30:		mips_set_cp0r( 30, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R31:		mips_set_cp0r( 31, info->i );			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR0:		mipscpu.cp2dr[ 0 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR1:		mipscpu.cp2dr[ 1 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR2:		mipscpu.cp2dr[ 2 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR3:		mipscpu.cp2dr[ 3 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR4:		mipscpu.cp2dr[ 4 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR5:		mipscpu.cp2dr[ 5 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR6:		mipscpu.cp2dr[ 6 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR7:		mipscpu.cp2dr[ 7 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR8:		mipscpu.cp2dr[ 8 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR9:		mipscpu.cp2dr[ 9 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR10:		mipscpu.cp2dr[ 10 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR11:		mipscpu.cp2dr[ 11 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR12:		mipscpu.cp2dr[ 12 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR13:		mipscpu.cp2dr[ 13 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR14:		mipscpu.cp2dr[ 14 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR15:		mipscpu.cp2dr[ 15 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR16:		mipscpu.cp2dr[ 16 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR17:		mipscpu.cp2dr[ 17 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR18:		mipscpu.cp2dr[ 18 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR19:		mipscpu.cp2dr[ 19 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR20:		mipscpu.cp2dr[ 20 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR21:		mipscpu.cp2dr[ 21 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR22:		mipscpu.cp2dr[ 22 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR23:		mipscpu.cp2dr[ 23 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR24:		mipscpu.cp2dr[ 24 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR25:		mipscpu.cp2dr[ 25 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR26:		mipscpu.cp2dr[ 26 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR27:		mipscpu.cp2dr[ 27 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR28:		mipscpu.cp2dr[ 28 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR29:		mipscpu.cp2dr[ 29 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR30:		mipscpu.cp2dr[ 30 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR31:		mipscpu.cp2dr[ 31 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR0:		mipscpu.cp2cr[ 0 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR1:		mipscpu.cp2cr[ 1 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR2:		mipscpu.cp2cr[ 2 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR3:		mipscpu.cp2cr[ 3 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR4:		mipscpu.cp2cr[ 4 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR5:		mipscpu.cp2cr[ 5 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR6:		mipscpu.cp2cr[ 6 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR7:		mipscpu.cp2cr[ 7 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR8:		mipscpu.cp2cr[ 8 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR9:		mipscpu.cp2cr[ 9 ].d = info->i;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR10:		mipscpu.cp2cr[ 10 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR11:		mipscpu.cp2cr[ 11 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR12:		mipscpu.cp2cr[ 12 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR13:		mipscpu.cp2cr[ 13 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR14:		mipscpu.cp2cr[ 14 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR15:		mipscpu.cp2cr[ 15 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR16:		mipscpu.cp2cr[ 16 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR17:		mipscpu.cp2cr[ 17 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR18:		mipscpu.cp2cr[ 18 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR19:		mipscpu.cp2cr[ 19 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR20:		mipscpu.cp2cr[ 20 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR21:		mipscpu.cp2cr[ 21 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR22:		mipscpu.cp2cr[ 22 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR23:		mipscpu.cp2cr[ 23 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR24:		mipscpu.cp2cr[ 24 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR25:		mipscpu.cp2cr[ 25 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR26:		mipscpu.cp2cr[ 26 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR27:		mipscpu.cp2cr[ 27 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR28:		mipscpu.cp2cr[ 28 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR29:		mipscpu.cp2cr[ 29 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR30:		mipscpu.cp2cr[ 30 ].d = info->i;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR31:		mipscpu.cp2cr[ 31 ].d = info->i;		break;
-
-		/* --- the following bits of info are set as pointers to data or functions --- */
-		case CPUINFO_PTR_IRQ_CALLBACK:					mipscpu.irq_callback = info->irqcallback;			break;
-	}
-}
-
-
-
-/**************************************************************************
- * Generic get_info
- **************************************************************************/
-
-void mips_get_info(uint32_t state, union cpuinfo *info)
-{
-	switch (state)
-	{
-		/* --- the following bits of info are returned as 64-bit signed integers --- */
-		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(mipscpu);				break;
-		case CPUINFO_INT_INPUT_LINES:					info->i = 6;							break;
-		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
-		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
-		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
-		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 4;							break;
-		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 4;							break;
-		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
-		case CPUINFO_INT_MAX_CYCLES:					info->i = 40;							break;
-
-		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 32;					break;
-		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32;					break;
-		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
-		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
-		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
-		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
-		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 0;					break;
-		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 0;					break;
-		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
-
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break;
-		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break;
-
-		case CPUINFO_INT_PREVIOUSPC:					/* not implemented */					break;
-
-		case CPUINFO_INT_PC:							info->i = mipscpu.pc;					break;
-		case CPUINFO_INT_REGISTER + MIPS_PC:			info->i = mipscpu.pc;					break;
-		case CPUINFO_INT_SP:
-			/* because there is no hardware stack and the pipeline causes the cpu to execute the
-			instruction after a subroutine call before the subroutine is executed there is little
-			chance of cmd_step_over() in mamedbg.c working. */
-								info->i = 0;													break;
-		case CPUINFO_INT_REGISTER + MIPS_DELAYV:		info->i = mipscpu.delayv;				break;
-		case CPUINFO_INT_REGISTER + MIPS_DELAYR:		info->i = mipscpu.delayr;				break;
-		case CPUINFO_INT_REGISTER + MIPS_HI:			info->i = mipscpu.hi;					break;
-		case CPUINFO_INT_REGISTER + MIPS_LO:			info->i = mipscpu.lo;					break;
-		case CPUINFO_INT_REGISTER + MIPS_R0:			info->i = mipscpu.r[ 0 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R1:			info->i = mipscpu.r[ 1 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R2:			info->i = mipscpu.r[ 2 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R3:			info->i = mipscpu.r[ 3 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R4:			info->i = mipscpu.r[ 4 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R5:			info->i = mipscpu.r[ 5 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R6:			info->i = mipscpu.r[ 6 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R7:			info->i = mipscpu.r[ 7 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R8:			info->i = mipscpu.r[ 8 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R9:			info->i = mipscpu.r[ 9 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R10:			info->i = mipscpu.r[ 10 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R11:			info->i = mipscpu.r[ 11 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R12:			info->i = mipscpu.r[ 12 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R13:			info->i = mipscpu.r[ 13 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R14:			info->i = mipscpu.r[ 14 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R15:			info->i = mipscpu.r[ 15 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R16:			info->i = mipscpu.r[ 16 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R17:			info->i = mipscpu.r[ 17 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R18:			info->i = mipscpu.r[ 18 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R19:			info->i = mipscpu.r[ 19 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R20:			info->i = mipscpu.r[ 20 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R21:			info->i = mipscpu.r[ 21 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R22:			info->i = mipscpu.r[ 22 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R23:			info->i = mipscpu.r[ 23 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R24:			info->i = mipscpu.r[ 24 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R25:			info->i = mipscpu.r[ 25 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R26:			info->i = mipscpu.r[ 26 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R27:			info->i = mipscpu.r[ 27 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R28:			info->i = mipscpu.r[ 28 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R29:			info->i = mipscpu.r[ 29 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R30:			info->i = mipscpu.r[ 30 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_R31:			info->i = mipscpu.r[ 31 ];				break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R0:			info->i = mipscpu.cp0r[ 0 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R1:			info->i = mipscpu.cp0r[ 1 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R2:			info->i = mipscpu.cp0r[ 2 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R3:			info->i = mipscpu.cp0r[ 3 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R4:			info->i = mipscpu.cp0r[ 4 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R5:			info->i = mipscpu.cp0r[ 5 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R6:			info->i = mipscpu.cp0r[ 6 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R7:			info->i = mipscpu.cp0r[ 7 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R8:			info->i = mipscpu.cp0r[ 8 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R9:			info->i = mipscpu.cp0r[ 9 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R10:		info->i = mipscpu.cp0r[ 10 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R11:		info->i = mipscpu.cp0r[ 11 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R12:		info->i = mipscpu.cp0r[ 12 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R13:		info->i = mipscpu.cp0r[ 13 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R14:		info->i = mipscpu.cp0r[ 14 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R15:		info->i = mipscpu.cp0r[ 15 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R16:		info->i = mipscpu.cp0r[ 16 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R17:		info->i = mipscpu.cp0r[ 17 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R18:		info->i = mipscpu.cp0r[ 18 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R19:		info->i = mipscpu.cp0r[ 19 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R20:		info->i = mipscpu.cp0r[ 20 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R21:		info->i = mipscpu.cp0r[ 21 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R22:		info->i = mipscpu.cp0r[ 22 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R23:		info->i = mipscpu.cp0r[ 23 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R24:		info->i = mipscpu.cp0r[ 24 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R25:		info->i = mipscpu.cp0r[ 25 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R26:		info->i = mipscpu.cp0r[ 26 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R27:		info->i = mipscpu.cp0r[ 27 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R28:		info->i = mipscpu.cp0r[ 28 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R29:		info->i = mipscpu.cp0r[ 29 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R30:		info->i = mipscpu.cp0r[ 30 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP0R31:		info->i = mipscpu.cp0r[ 31 ];			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR0:		info->i = mipscpu.cp2dr[ 0 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR1:		info->i = mipscpu.cp2dr[ 1 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR2:		info->i = mipscpu.cp2dr[ 2 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR3:		info->i = mipscpu.cp2dr[ 3 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR4:		info->i = mipscpu.cp2dr[ 4 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR5:		info->i = mipscpu.cp2dr[ 5 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR6:		info->i = mipscpu.cp2dr[ 6 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR7:		info->i = mipscpu.cp2dr[ 7 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR8:		info->i = mipscpu.cp2dr[ 8 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR9:		info->i = mipscpu.cp2dr[ 9 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR10:		info->i = mipscpu.cp2dr[ 10 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR11:		info->i = mipscpu.cp2dr[ 11 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR12:		info->i = mipscpu.cp2dr[ 12 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR13:		info->i = mipscpu.cp2dr[ 13 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR14:		info->i = mipscpu.cp2dr[ 14 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR15:		info->i = mipscpu.cp2dr[ 15 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR16:		info->i = mipscpu.cp2dr[ 16 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR17:		info->i = mipscpu.cp2dr[ 17 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR18:		info->i = mipscpu.cp2dr[ 18 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR19:		info->i = mipscpu.cp2dr[ 19 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR20:		info->i = mipscpu.cp2dr[ 20 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR21:		info->i = mipscpu.cp2dr[ 21 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR22:		info->i = mipscpu.cp2dr[ 22 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR23:		info->i = mipscpu.cp2dr[ 23 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR24:		info->i = mipscpu.cp2dr[ 24 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR25:		info->i = mipscpu.cp2dr[ 25 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR26:		info->i = mipscpu.cp2dr[ 26 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR27:		info->i = mipscpu.cp2dr[ 27 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR28:		info->i = mipscpu.cp2dr[ 28 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR29:		info->i = mipscpu.cp2dr[ 29 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR30:		info->i = mipscpu.cp2dr[ 30 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2DR31:		info->i = mipscpu.cp2dr[ 31 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR0:		info->i = mipscpu.cp2cr[ 0 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR1:		info->i = mipscpu.cp2cr[ 1 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR2:		info->i = mipscpu.cp2cr[ 2 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR3:		info->i = mipscpu.cp2cr[ 3 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR4:		info->i = mipscpu.cp2cr[ 4 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR5:		info->i = mipscpu.cp2cr[ 5 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR6:		info->i = mipscpu.cp2cr[ 6 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR7:		info->i = mipscpu.cp2cr[ 7 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR8:		info->i = mipscpu.cp2cr[ 8 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR9:		info->i = mipscpu.cp2cr[ 9 ].d;			break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR10:		info->i = mipscpu.cp2cr[ 10 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR11:		info->i = mipscpu.cp2cr[ 11 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR12:		info->i = mipscpu.cp2cr[ 12 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR13:		info->i = mipscpu.cp2cr[ 13 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR14:		info->i = mipscpu.cp2cr[ 14 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR15:		info->i = mipscpu.cp2cr[ 15 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR16:		info->i = mipscpu.cp2cr[ 16 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR17:		info->i = mipscpu.cp2cr[ 17 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR18:		info->i = mipscpu.cp2cr[ 18 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR19:		info->i = mipscpu.cp2cr[ 19 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR20:		info->i = mipscpu.cp2cr[ 20 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR21:		info->i = mipscpu.cp2cr[ 21 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR22:		info->i = mipscpu.cp2cr[ 22 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR23:		info->i = mipscpu.cp2cr[ 23 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR24:		info->i = mipscpu.cp2cr[ 24 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR25:		info->i = mipscpu.cp2cr[ 25 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR26:		info->i = mipscpu.cp2cr[ 26 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR27:		info->i = mipscpu.cp2cr[ 27 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR28:		info->i = mipscpu.cp2cr[ 28 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR29:		info->i = mipscpu.cp2cr[ 29 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR30:		info->i = mipscpu.cp2cr[ 30 ].d;		break;
-		case CPUINFO_INT_REGISTER + MIPS_CP2CR31:		info->i = mipscpu.cp2cr[ 31 ].d;		break;
-
-		/* --- the following bits of info are returned as pointers to data or functions --- */
-		case CPUINFO_PTR_SET_INFO:						info->setinfo = mips_set_info;			break;
-		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = mips_get_context;	break;
-		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = mips_set_context;	break;
-		case CPUINFO_PTR_INIT:							info->init = mips_init;					break;
-		case CPUINFO_PTR_RESET:							info->reset = mips_reset;				break;
-		case CPUINFO_PTR_EXIT:							info->exit = mips_exit;					break;
-		case CPUINFO_PTR_EXECUTE:						info->execute = mips_execute;			break;
-		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
-		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = mips_dasm;			break;
-		case CPUINFO_PTR_IRQ_CALLBACK:					info->irqcallback = mipscpu.irq_callback; break;
-		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &mips_ICount;			break;
-		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = mips_reg_layout;				break;
-		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = mips_win_layout;				break;
-	}
-}
-
-uint32_t mips_get_cause(void)
-{
-	return mipscpu.cp0r[ CP0_CAUSE ];
-}
-
-uint32_t mips_get_status(void)
-{
-	return mipscpu.cp0r[ CP0_SR ];
-}
-
-void mips_set_status(uint32_t status)
-{
-	mipscpu.cp0r[ CP0_SR ] = status;
-}
-
-uint32_t mips_get_ePC(void)
-{
-	return mipscpu.cp0r[ CP0_EPC ];
-}
-
-int mips_get_icount(void)
-{
-	return mips_ICount;
-}
-
-void mips_set_icount(int count)
-{
-	mips_ICount = count;
-}
-
-
-#if (HAS_PSXCPU)
-/**************************************************************************
- * CPU-specific set_info
- **************************************************************************/
-
-void psxcpu_get_info(uint32_t state, union cpuinfo *info)
-{
-	switch (state)
-	{
-		/* --- the following bits of info are returned as NULL-terminated strings --- */
-//		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "PSX CPU"); break;
-
-		default:
-			mips_get_info(state, info);
-			break;
-	}
-}
-#endif
diff --git a/src/psf/psx.cc b/src/psf/psx.cc
new file mode 100644
index 000000000000..d4b44ec73e61
--- /dev/null
+++ b/src/psf/psx.cc
@@ -0,0 +1,3005 @@
+/*
+ * Sony CXD8530AQ/CXD8530BQ/CXD8530CQ/CXD8661R
+ *
+ * PSX CPU emulator for the MAME project written by smf
+ * Thanks to Farfetch'd for information on the delay slot bug
+ *
+ * The PSX CPU is a custom r3000a with a built in
+ * geometry transform engine, no mmu & no data cache.
+ *
+ * There is a stall circuit for load delays, but
+ * it doesn't work if the load occurs in a branch
+ * delay slot.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "ao.h"
+#include "cpuintrf.h"
+#include "psx.h"
+
+#define EXC_INT ( 0 )
+#define EXC_ADEL ( 4 )
+#define EXC_ADES ( 5 )
+#define EXC_SYS ( 8 )
+#define EXC_BP ( 9 )
+#define EXC_RI ( 10 )
+#define EXC_CPU ( 11 )
+#define EXC_OVF ( 12 )
+
+#define CP0_RANDOM ( 1 )
+#define CP0_BADVADDR ( 8 )
+#define CP0_SR ( 12 )
+#define CP0_CAUSE ( 13 )
+#define CP0_EPC ( 14 )
+#define CP0_PRID ( 15 )
+
+#define SR_IEC ( 1L << 0 )
+#define SR_KUC ( 1L << 1 )
+#define SR_ISC ( 1L << 16 )
+#define SR_SWC ( 1L << 17 )
+#define SR_TS  ( 1L << 21 )
+#define SR_BEV ( 1L << 22 )
+#define SR_RE ( 1L << 25 )
+#define SR_CU0 ( 1L << 28 )
+#define SR_CU1 ( 1L << 29 )
+#define SR_CU2 ( 1L << 30 )
+#define SR_CU3 ( 1L << 31 )
+
+#define CAUSE_EXC ( 31L << 2 )
+#define CAUSE_IP ( 255L << 8 )
+#define CAUSE_IP2 ( 1L << 10 )
+#define CAUSE_IP3 ( 1L << 11 )
+#define CAUSE_IP4 ( 1L << 12 )
+#define CAUSE_IP5 ( 1L << 13 )
+#define CAUSE_IP6 ( 1L << 14 )
+#define CAUSE_IP7 ( 1L << 15 )
+#define CAUSE_CE ( 3L << 28 )
+#define CAUSE_CE0 ( 0L << 28 )
+#define CAUSE_CE1 ( 1L << 28 )
+#define CAUSE_CE2 ( 2L << 28 )
+#define CAUSE_BD ( 1L << 31 )
+
+extern void psx_bios_hle(uint32_t pc);
+extern void psx_iop_call(uint32_t pc, uint32_t callnum);
+extern uint8_t program_read_byte_32le(offs_t address);
+extern uint16_t program_read_word_32le(offs_t address);
+extern uint32_t program_read_dword_32le(offs_t address);
+extern void program_write_byte_32le(offs_t address, uint8_t data);
+extern void program_write_word_32le(offs_t address, uint16_t data);
+extern void program_write_dword_32le(offs_t address, uint32_t data);
+
+static uint8_t mips_reg_layout[] =
+{
+	MIPS_PC, 0xFF,
+	MIPS_DELAYV, MIPS_DELAYR, 0xFF,
+	MIPS_HI, MIPS_LO, 0xFF,
+	0xFF,
+	MIPS_R0, MIPS_R1, 0xFF,
+	MIPS_R2, MIPS_R3, 0xFF,
+	MIPS_R4, MIPS_R5, 0xFF,
+	MIPS_R6, MIPS_R7, 0xFF,
+	MIPS_R8, MIPS_R9, 0xFF,
+	MIPS_R10, MIPS_R11, 0xFF,
+	MIPS_R12, MIPS_R13, 0xFF,
+	MIPS_R14, MIPS_R15, 0xFF,
+	MIPS_R16, MIPS_R17, 0xFF,
+	MIPS_R18, MIPS_R19, 0xFF,
+	MIPS_R20, MIPS_R21, 0xFF,
+	MIPS_R22, MIPS_R23, 0xFF,
+	MIPS_R24, MIPS_R25, 0xFF,
+	MIPS_R26, MIPS_R27, 0xFF,
+	MIPS_R28, MIPS_R29, 0xFF,
+	MIPS_R30, MIPS_R31, 0xFF,
+	0xFF,
+	MIPS_CP0R0, MIPS_CP0R1, 0xFF,
+	MIPS_CP0R2, MIPS_CP0R3, 0xFF,
+	MIPS_CP0R4, MIPS_CP0R5, 0xFF,
+	MIPS_CP0R6, MIPS_CP0R7, 0xFF,
+	MIPS_CP0R8, MIPS_CP0R9, 0xFF,
+	MIPS_CP0R10, MIPS_CP0R11, 0xFF,
+	MIPS_CP0R12, MIPS_CP0R13, 0xFF,
+	MIPS_CP0R14, MIPS_CP0R15, 0xFF,
+	MIPS_CP0R16, MIPS_CP0R17, 0xFF,
+	MIPS_CP0R18, MIPS_CP0R19, 0xFF,
+	MIPS_CP0R20, MIPS_CP0R21, 0xFF,
+	MIPS_CP0R22, MIPS_CP0R23, 0xFF,
+	MIPS_CP0R24, MIPS_CP0R25, 0xFF,
+	MIPS_CP0R26, MIPS_CP0R27, 0xFF,
+	MIPS_CP0R28, MIPS_CP0R29, 0xFF,
+	MIPS_CP0R30, MIPS_CP0R31, 0xFF,
+	0xFF,
+	MIPS_CP2DR0, MIPS_CP2DR1, 0xFF,
+	MIPS_CP2DR2, MIPS_CP2DR3, 0xFF,
+	MIPS_CP2DR4, MIPS_CP2DR5, 0xFF,
+	MIPS_CP2DR6, MIPS_CP2DR7, 0xFF,
+	MIPS_CP2DR8, MIPS_CP2DR9, 0xFF,
+	MIPS_CP2DR10, MIPS_CP2DR11, 0xFF,
+	MIPS_CP2DR12, MIPS_CP2DR13, 0xFF,
+	MIPS_CP2DR14, MIPS_CP2DR15, 0xFF,
+	MIPS_CP2DR16, MIPS_CP2DR17, 0xFF,
+	MIPS_CP2DR18, MIPS_CP2DR19, 0xFF,
+	MIPS_CP2DR20, MIPS_CP2DR21, 0xFF,
+	MIPS_CP2DR22, MIPS_CP2DR23, 0xFF,
+	MIPS_CP2DR24, MIPS_CP2DR25, 0xFF,
+	MIPS_CP2DR26, MIPS_CP2DR27, 0xFF,
+	MIPS_CP2DR28, MIPS_CP2DR29, 0xFF,
+	MIPS_CP2DR30, MIPS_CP2DR31, 0xFF,
+	0xFF,
+	MIPS_CP2CR0, MIPS_CP2CR1, 0xFF,
+	MIPS_CP2CR2, MIPS_CP2CR3, 0xFF,
+	MIPS_CP2CR4, MIPS_CP2CR5, 0xFF,
+	MIPS_CP2CR6, MIPS_CP2CR7, 0xFF,
+	MIPS_CP2CR8, MIPS_CP2CR9, 0xFF,
+	MIPS_CP2CR10, MIPS_CP2CR11, 0xFF,
+	MIPS_CP2CR12, MIPS_CP2CR13, 0xFF,
+	MIPS_CP2CR14, MIPS_CP2CR15, 0xFF,
+	MIPS_CP2CR16, MIPS_CP2CR17, 0xFF,
+	MIPS_CP2CR18, MIPS_CP2CR19, 0xFF,
+	MIPS_CP2CR20, MIPS_CP2CR21, 0xFF,
+	MIPS_CP2CR22, MIPS_CP2CR23, 0xFF,
+	MIPS_CP2CR24, MIPS_CP2CR25, 0xFF,
+	MIPS_CP2CR26, MIPS_CP2CR27, 0xFF,
+	MIPS_CP2CR28, MIPS_CP2CR29, 0xFF,
+	MIPS_CP2CR30, MIPS_CP2CR31,
+	0
+};
+
+static uint8_t mips_win_layout[] = {
+	45, 0,35,13,	/* register window (top right) */
+	 0, 0,44,13,	/* disassembler window (left, upper) */
+	 0,14,44, 8,	/* memory #1 window (left, middle) */
+	45,14,35, 8,	/* memory #2 window (lower) */
+	 0,23,80, 1 	/* command line window (bottom rows) */
+};
+
+#define REGPC ( 32 )
+
+typedef struct
+{
+	uint32_t op;
+	uint32_t pc;
+	uint32_t prevpc;
+	uint32_t delayv;
+	uint32_t delayr;
+	uint32_t hi;
+	uint32_t lo;
+	uint32_t r[ 32 ];
+	uint32_t cp0r[ 32 ];
+	PAIR cp2cr[ 32 ];
+	PAIR cp2dr[ 32 ];
+	int (*irq_callback)(int irqline);
+} mips_cpu_context;
+
+static mips_cpu_context mipscpu;
+
+static int mips_ICount = 0;
+
+static uint32_t mips_mtc0_writemask[]=
+{
+	0xffffffff, /* INDEX */
+	0x00000000, /* RANDOM */
+	0xffffff00, /* ENTRYLO */
+	0x00000000,
+	0xffe00000, /* CONTEXT */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000, /* BADVADDR */
+	0x00000000,
+	0xffffffc0, /* ENTRYHI */
+	0x00000000,
+	0xf27fff3f, /* SR */
+	0x00000300, /* CAUSE */
+	0x00000000, /* EPC */
+	0x00000000, /* PRID */
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+#if 1
+void GTELOG(const char *a,...)
+{
+	va_list va;
+	char s_text[ 1024 ];
+	va_start( va, a );
+	vsprintf( s_text, a, va );
+	va_end( va );
+	logerror( "%08x: GTE: %08x %s\n", mipscpu.pc, INS_COFUN( mipscpu.op ), s_text );
+}
+#else
+static inline void GTELOG(const char *a, ...) {}
+#endif
+
+static uint32_t getcp2dr( int n_reg );
+static void setcp2dr( int n_reg, uint32_t n_value );
+static uint32_t getcp2cr( int n_reg );
+static void setcp2cr( int n_reg, uint32_t n_value );
+static void docop2( int gteop );
+static void mips_exception( int exception );
+
+void mips_stop( void )
+{
+#ifdef MAME_DEBUG
+	extern int debug_key_pressed;
+	debug_key_pressed = 1;
+	CALL_MAME_DEBUG;
+#endif
+}
+
+static inline void mips_set_cp0r( int reg, uint32_t value )
+{
+	mipscpu.cp0r[ reg ] = value;
+	if( reg == CP0_SR || reg == CP0_CAUSE )
+	{
+		if( ( mipscpu.cp0r[ CP0_SR ] & SR_IEC ) != 0 && ( mipscpu.cp0r[ CP0_SR ] & mipscpu.cp0r[ CP0_CAUSE ] & CAUSE_IP ) != 0 )
+		{
+			mips_exception( EXC_INT );
+		}
+		else if( mipscpu.delayr != REGPC && ( mipscpu.pc & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+		{
+			mips_exception( EXC_ADEL );
+			mips_set_cp0r( CP0_BADVADDR, mipscpu.pc );
+		}
+	}
+}
+
+static inline void mips_commit_delayed_load( void )
+{
+	if( mipscpu.delayr != 0 )
+	{
+		mipscpu.r[ mipscpu.delayr ] = mipscpu.delayv;
+		mipscpu.delayr = 0;
+		mipscpu.delayv = 0;
+	}
+}
+
+static inline void mips_delayed_branch( uint32_t n_adr )
+{
+	if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+	{
+		mips_exception( EXC_ADEL );
+		mips_set_cp0r( CP0_BADVADDR, n_adr );
+	}
+	else
+	{
+		mips_commit_delayed_load();
+		mipscpu.delayr = REGPC;
+		mipscpu.delayv = n_adr;
+		mipscpu.pc += 4;
+	}
+}
+
+static inline void mips_set_pc( unsigned val )
+{
+	mipscpu.pc = val;
+	change_pc( val );
+	mipscpu.delayr = 0;
+	mipscpu.delayv = 0;
+}
+
+static inline void mips_advance_pc( void )
+{
+	if( mipscpu.delayr == REGPC )
+	{
+		mips_set_pc( mipscpu.delayv );
+	}
+	else
+	{
+		mips_commit_delayed_load();
+		mipscpu.pc += 4;
+	}
+}
+
+static inline void mips_load( uint32_t n_r, uint32_t n_v )
+{
+	mips_advance_pc();
+	if( n_r != 0 )
+	{
+		mipscpu.r[ n_r ] = n_v;
+	}
+}
+
+static inline void mips_delayed_load( uint32_t n_r, uint32_t n_v )
+{
+	if( mipscpu.delayr == REGPC )
+	{
+		mips_set_pc( mipscpu.delayv );
+		mipscpu.delayr = n_r;
+		mipscpu.delayv = n_v;
+	}
+	else
+	{
+		mips_commit_delayed_load();
+		mipscpu.pc += 4;
+		if( n_r != 0 )
+		{
+			mipscpu.r[ n_r ] = n_v;
+		}
+	}
+}
+
+static void mips_exception( int exception )
+{
+	mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~0x3f ) | ( ( mipscpu.cp0r[ CP0_SR ] << 2 ) & 0x3f ) );
+	if( mipscpu.delayr == REGPC )
+	{
+		mips_set_cp0r( CP0_EPC, mipscpu.pc - 4 );
+		mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_EXC ) | CAUSE_BD | ( exception << 2 ) );
+	}
+	else
+	{
+		mips_commit_delayed_load();
+		mips_set_cp0r( CP0_EPC, mipscpu.pc );
+		mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~( CAUSE_EXC | CAUSE_BD ) ) | ( exception << 2 ) );
+	}
+	if( mipscpu.cp0r[ CP0_SR ] & SR_BEV )
+	{
+		mips_set_pc( 0xbfc00180 );
+	}
+	else
+	{
+		mips_set_pc( 0x80000080 );
+	}
+}
+
+void mips_init( void )
+{
+#if 0
+	int cpu = cpu_getactivecpu();
+
+	state_save_register_UINT32( "psxcpu", cpu, "op", &mipscpu.op, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "pc", &mipscpu.pc, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "delayv", &mipscpu.delayv, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "delayr", &mipscpu.delayr, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "hi", &mipscpu.hi, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "lo", &mipscpu.lo, 1 );
+	state_save_register_UINT32( "psxcpu", cpu, "r", &mipscpu.r[ 0 ], 32 );
+	state_save_register_UINT32( "psxcpu", cpu, "cp0r", &mipscpu.cp0r[ 0 ], 32 );
+	state_save_register_UINT32( "psxcpu", cpu, "cp2cr", &mipscpu.cp2cr[ 0 ].d, 32 );
+	state_save_register_UINT32( "psxcpu", cpu, "cp2dr", &mipscpu.cp2dr[ 0 ].d, 32 );
+#endif
+}
+
+void mips_reset( void *param )
+{
+	mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~( SR_TS | SR_SWC | SR_KUC | SR_IEC ) ) | SR_BEV );
+	mips_set_cp0r( CP0_RANDOM, 63 ); /* todo: */
+	mips_set_cp0r( CP0_PRID, 0x00000200 ); /* todo: */
+	mips_set_pc( 0xbfc00000 );
+	mipscpu.prevpc = 0xffffffff;
+}
+
+static void mips_exit( void )
+{
+}
+
+void mips_shorten_frame(void)
+{
+	mips_ICount = 0;
+}
+
+void psx_hw_runcounters(void);
+
+int psxcpu_verbose = 0;
+
+int mips_execute( int cycles )
+{
+	uint32_t n_res;
+
+	mips_ICount = cycles;
+	do
+	{
+//		CALL_MAME_DEBUG;
+
+//		psx_hw_runcounters();
+
+		mipscpu.op = cpu_readop32( mipscpu.pc );
+
+#if 0
+		while (mipscpu.prevpc == mipscpu.pc)
+		{
+			psx_hw_runcounters();
+			mips_ICount--;
+
+			if (mips_ICount == 0) return cycles;
+		}
+#endif
+
+		// if we're not in a delay slot, update
+		// if we're in a delay slot and the delay instruction is not NOP, update
+		if (( mipscpu.delayr == 0 ) || ((mipscpu.delayr != 0) && (mipscpu.op != 0)))
+		{
+			mipscpu.prevpc = mipscpu.pc;
+		}
+#if 0
+		if (1) //psxcpu_verbose)
+		{
+			printf("[%08x: %08x] [SP %08x RA %08x V0 %08x V1 %08x A0 %08x S0 %08x S1 %08x]\n", mipscpu.pc, mipscpu.op, mipscpu.r[29], mipscpu.r[31], mipscpu.r[2], mipscpu.r[3], mipscpu.r[4], mipscpu.r[ 16 ], mipscpu.r[ 17 ]);
+//			psxcpu_verbose--;
+		}
+#endif
+		switch( INS_OP( mipscpu.op ) )
+		{
+		case OP_SPECIAL:
+			switch( INS_FUNCT( mipscpu.op ) )
+			{
+			case FUNCT_HLECALL:
+//				printf("HLECALL, PC = %08x\n", mipscpu.pc);
+				psx_bios_hle(mipscpu.pc);
+				break;
+			case FUNCT_SLL:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] << INS_SHAMT( mipscpu.op ) );
+				break;
+			case FUNCT_SRL:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] >> INS_SHAMT( mipscpu.op ) );
+				break;
+			case FUNCT_SRA:
+				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] >> INS_SHAMT( mipscpu.op ) );
+				break;
+			case FUNCT_SLLV:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] << ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
+				break;
+			case FUNCT_SRLV:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] >> ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
+				break;
+			case FUNCT_SRAV:
+				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] >> ( mipscpu.r[ INS_RS( mipscpu.op ) ] & 31 ) );
+				break;
+			case FUNCT_JR:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					mips_delayed_branch( mipscpu.r[ INS_RS( mipscpu.op ) ] );
+				}
+				break;
+			case FUNCT_JALR:
+				n_res = mipscpu.pc + 8;
+				mips_delayed_branch( mipscpu.r[ INS_RS( mipscpu.op ) ] );
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mipscpu.r[ INS_RD( mipscpu.op ) ] = n_res;
+				}
+				break;
+			case FUNCT_SYSCALL:
+				mips_exception( EXC_SYS );
+				break;
+			case FUNCT_BREAK:
+				printf("BREAK!\n");
+				exit(-1);
+//				mips_exception( EXC_BP );
+				mips_advance_pc();
+				break;
+			case FUNCT_MFHI:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.hi );
+				break;
+			case FUNCT_MTHI:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					mips_advance_pc();
+					mipscpu.hi = mipscpu.r[ INS_RS( mipscpu.op ) ];
+				}
+				break;
+			case FUNCT_MFLO:
+				mips_load( INS_RD( mipscpu.op ),  mipscpu.lo );
+				break;
+			case FUNCT_MTLO:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					mips_advance_pc();
+					mipscpu.lo = mipscpu.r[ INS_RS( mipscpu.op ) ];
+				}
+				break;
+			case FUNCT_MULT:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					int64_t n_res64;
+					n_res64 = MUL_64_32_32( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ], (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+					mipscpu.lo = LO32_32_64( n_res64 );
+					mipscpu.hi = HI32_32_64( n_res64 );
+				}
+				break;
+			case FUNCT_MULTU:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					uint64_t n_res64;
+					n_res64 = MUL_U64_U32_U32( mipscpu.r[ INS_RS( mipscpu.op ) ], mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+					mipscpu.lo = LO32_U32_U64( n_res64 );
+					mipscpu.hi = HI32_U32_U64( n_res64 );
+				}
+				break;
+			case FUNCT_DIV:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					uint32_t n_div;
+					uint32_t n_mod;
+					if( mipscpu.r[ INS_RT( mipscpu.op ) ] != 0 )
+					{
+						n_div = (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] / (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ];
+						n_mod = (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] % (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ];
+						mips_advance_pc();
+						mipscpu.lo = n_div;
+						mipscpu.hi = n_mod;
+					}
+					else
+					{
+						mips_advance_pc();
+					}
+				}
+				break;
+			case FUNCT_DIVU:
+				if( INS_RD( mipscpu.op ) != 0 )
+				{
+					mips_exception( EXC_RI );
+				}
+				else
+				{
+					uint32_t n_div;
+					uint32_t n_mod;
+					if( mipscpu.r[ INS_RT( mipscpu.op ) ] != 0 )
+					{
+						n_div = mipscpu.r[ INS_RS( mipscpu.op ) ] / mipscpu.r[ INS_RT( mipscpu.op ) ];
+						n_mod = mipscpu.r[ INS_RS( mipscpu.op ) ] % mipscpu.r[ INS_RT( mipscpu.op ) ];
+						mips_advance_pc();
+						mipscpu.lo = n_div;
+						mipscpu.hi = n_mod;
+					}
+					else
+					{
+						mips_advance_pc();
+					}
+				}
+				break;
+			case FUNCT_ADD:
+				{
+					n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] + mipscpu.r[ INS_RT( mipscpu.op ) ];
+					if( (int32_t)( ~( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
+					{
+						mips_exception( EXC_OVF );
+					}
+					else
+					{
+						mips_load( INS_RD( mipscpu.op ), n_res );
+					}
+				}
+				break;
+			case FUNCT_ADDU:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] + mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_SUB:
+				n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] - mipscpu.r[ INS_RT( mipscpu.op ) ];
+				if( (int32_t)( ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
+				{
+					mips_exception( EXC_OVF );
+				}
+				else
+				{
+					mips_load( INS_RD( mipscpu.op ), n_res );
+				}
+				break;
+			case FUNCT_SUBU:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] - mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_AND:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] & mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_OR:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] | mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_XOR:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] ^ mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_NOR:
+				mips_load( INS_RD( mipscpu.op ), ~( mipscpu.r[ INS_RS( mipscpu.op ) ] | mipscpu.r[ INS_RT( mipscpu.op ) ] ) );
+				break;
+			case FUNCT_SLT:
+				mips_load( INS_RD( mipscpu.op ), (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < (int32_t)mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			case FUNCT_SLTU:
+				mips_load( INS_RD( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] < mipscpu.r[ INS_RT( mipscpu.op ) ] );
+				break;
+			default:
+				mips_exception( EXC_RI );
+				break;
+			}
+			break;
+		case OP_REGIMM:
+			switch( INS_RT( mipscpu.op ) )
+			{
+			case RT_BLTZ:
+				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < 0 )
+				{
+					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+				}
+				else
+				{
+					mips_advance_pc();
+				}
+				break;
+			case RT_BGEZ:
+				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] >= 0 )
+				{
+					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+				}
+				else
+				{
+					mips_advance_pc();
+				}
+				break;
+			case RT_BLTZAL:
+				n_res = mipscpu.pc + 8;
+				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < 0 )
+				{
+					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+				}
+				else
+				{
+					mips_advance_pc();
+				}
+				mipscpu.r[ 31 ] = n_res;
+				break;
+			case RT_BGEZAL:
+				n_res = mipscpu.pc + 8;
+				if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] >= 0 )
+				{
+					mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+				}
+				else
+				{
+					mips_advance_pc();
+				}
+				mipscpu.r[ 31 ] = n_res;
+				break;
+			}
+			break;
+		case OP_J:
+			mips_delayed_branch( ( ( mipscpu.pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( mipscpu.op ) << 2 ) );
+			break;
+		case OP_JAL:
+			n_res = mipscpu.pc + 8;
+			mips_delayed_branch( ( ( mipscpu.pc + 4 ) & 0xf0000000 ) + ( INS_TARGET( mipscpu.op ) << 2 ) );
+			mipscpu.r[ 31 ] = n_res;
+			break;
+		case OP_BEQ:
+			if( mipscpu.r[ INS_RS( mipscpu.op ) ] == mipscpu.r[ INS_RT( mipscpu.op ) ] )
+			{
+				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+			}
+			else
+			{
+				mips_advance_pc();
+			}
+			break;
+		case OP_BNE:
+			if( mipscpu.r[ INS_RS( mipscpu.op ) ] != mipscpu.r[ INS_RT( mipscpu.op ) ] )
+			{
+				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+			}
+			else
+			{
+				mips_advance_pc();
+			}
+			break;
+		case OP_BLEZ:
+			if( INS_RT( mipscpu.op ) != 0 )
+			{
+				mips_exception( EXC_RI );
+			}
+			else if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] <= 0 )
+			{
+				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+			}
+			else
+			{
+				mips_advance_pc();
+			}
+			break;
+		case OP_BGTZ:
+			if( INS_RT( mipscpu.op ) != 0 )
+			{
+				mips_exception( EXC_RI );
+			}
+			else if( (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] > 0 )
+			{
+				mips_delayed_branch( mipscpu.pc + 4 + ( MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) << 2 ) );
+			}
+			else
+			{
+				mips_advance_pc();
+			}
+			break;
+		case OP_ADDI:
+			{
+				uint32_t n_imm;
+				n_imm = MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				n_res = mipscpu.r[ INS_RS( mipscpu.op ) ] + n_imm;
+				if( (int32_t)( ~( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_imm ) & ( mipscpu.r[ INS_RS( mipscpu.op ) ] ^ n_res ) ) < 0 )
+				{
+					mips_exception( EXC_OVF );
+				}
+				else
+				{
+					mips_load( INS_RT( mipscpu.op ), n_res );
+				}
+			}
+			break;
+		case OP_ADDIU:
+			if (INS_RT( mipscpu.op ) == 0)
+			{
+				psx_iop_call(mipscpu.pc, INS_IMMEDIATE(mipscpu.op));
+				mips_advance_pc();
+			}
+			else
+			{
+				mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
+			}
+			break;
+		case OP_SLTI:
+			mips_load( INS_RT( mipscpu.op ), (int32_t)mipscpu.r[ INS_RS( mipscpu.op ) ] < MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
+			break;
+		case OP_SLTIU:
+			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] < (uint32_t)MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) ) );
+			break;
+		case OP_ANDI:
+			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] & INS_IMMEDIATE( mipscpu.op ) );
+			break;
+		case OP_ORI:
+			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] | INS_IMMEDIATE( mipscpu.op ) );
+			break;
+		case OP_XORI:
+			mips_load( INS_RT( mipscpu.op ), mipscpu.r[ INS_RS( mipscpu.op ) ] ^ INS_IMMEDIATE( mipscpu.op ) );
+			break;
+		case OP_LUI:
+			mips_load( INS_RT( mipscpu.op ), INS_IMMEDIATE( mipscpu.op ) << 16 );
+			break;
+		case OP_COP0:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) != 0 && ( mipscpu.cp0r[ CP0_SR ] & SR_CU0 ) == 0 )
+			{
+				mips_exception( EXC_CPU );
+				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE0 );
+			}
+			else
+			{
+				switch( INS_RS( mipscpu.op ) )
+				{
+				case RS_MFC:
+					mips_delayed_load( INS_RT( mipscpu.op ), mipscpu.cp0r[ INS_RD( mipscpu.op ) ] );
+					break;
+				case RS_CFC:
+					/* todo: */
+					logerror( "%08x: COP0 CFC not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_MTC:
+					n_res = ( mipscpu.cp0r[ INS_RD( mipscpu.op ) ] & ~mips_mtc0_writemask[ INS_RD( mipscpu.op ) ] ) |
+						( mipscpu.r[ INS_RT( mipscpu.op ) ] & mips_mtc0_writemask[ INS_RD( mipscpu.op ) ] );
+					mips_advance_pc();
+					mips_set_cp0r( INS_RD( mipscpu.op ), n_res );
+					break;
+				case RS_CTC:
+					/* todo: */
+					logerror( "%08x: COP0 CTC not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_BC:
+					switch( INS_RT( mipscpu.op ) )
+					{
+					case RT_BCF:
+						/* todo: */
+						logerror( "%08x: COP0 BCF not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					case RT_BCT:
+						/* todo: */
+						logerror( "%08x: COP0 BCT not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				default:
+					switch( INS_CO( mipscpu.op ) )
+					{
+					case 1:
+						switch( INS_CF( mipscpu.op ) )
+						{
+						case CF_RFE:
+							mips_advance_pc();
+							mips_set_cp0r( CP0_SR, ( mipscpu.cp0r[ CP0_SR ] & ~0xf ) | ( ( mipscpu.cp0r[ CP0_SR ] >> 2 ) & 0xf ) );
+							break;
+						default:
+							/* todo: */
+							logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+							mips_stop();
+							mips_advance_pc();
+							break;
+						}
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP0 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				}
+			}
+			break;
+		case OP_COP1:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
+			{
+				mips_exception( EXC_CPU );
+				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE1 );
+			}
+			else
+			{
+				switch( INS_RS( mipscpu.op ) )
+				{
+				case RS_MFC:
+					/* todo: */
+					logerror( "%08x: COP1 BCT not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_CFC:
+					/* todo: */
+					logerror( "%08x: COP1 CFC not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_MTC:
+					/* todo: */
+					logerror( "%08x: COP1 MTC not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_CTC:
+					/* todo: */
+					logerror( "%08x: COP1 CTC not supported\n", mipscpu.pc );
+					mips_stop();
+					mips_advance_pc();
+					break;
+				case RS_BC:
+					switch( INS_RT( mipscpu.op ) )
+					{
+					case RT_BCF:
+						/* todo: */
+						logerror( "%08x: COP1 BCF not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					case RT_BCT:
+						/* todo: */
+						logerror( "%08x: COP1 BCT not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				default:
+					switch( INS_CO( mipscpu.op ) )
+					{
+					case 1:
+						/* todo: */
+						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP1 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				}
+			}
+			break;
+		case OP_COP2:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
+			{
+				mips_exception( EXC_CPU );
+				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
+			}
+			else
+			{
+				switch( INS_RS( mipscpu.op ) )
+				{
+				case RS_MFC:
+					mips_delayed_load( INS_RT( mipscpu.op ), getcp2dr( INS_RD( mipscpu.op ) ) );
+					break;
+				case RS_CFC:
+					mips_delayed_load( INS_RT( mipscpu.op ), getcp2cr( INS_RD( mipscpu.op ) ) );
+					break;
+				case RS_MTC:
+					setcp2dr( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+					break;
+				case RS_CTC:
+					setcp2cr( INS_RD( mipscpu.op ), mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+					break;
+				case RS_BC:
+					switch( INS_RT( mipscpu.op ) )
+					{
+					case RT_BCF:
+						/* todo: */
+						logerror( "%08x: COP2 BCF not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					case RT_BCT:
+						/* todo: */
+						logerror( "%08x: COP2 BCT not supported\n", mipscpu.pc );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP2 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				default:
+					switch( INS_CO( mipscpu.op ) )
+					{
+					case 1:
+						docop2( INS_COFUN( mipscpu.op ) );
+						mips_advance_pc();
+						break;
+					default:
+						/* todo: */
+						logerror( "%08x: COP2 unknown command %08x\n", mipscpu.pc, mipscpu.op );
+						mips_stop();
+						mips_advance_pc();
+						break;
+					}
+					break;
+				}
+			}
+			break;
+		case OP_LB:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LB SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_BYTE_EXTEND( program_read_byte_32le( n_adr ^ 3 ) ) );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_BYTE_EXTEND( program_read_byte_32le( n_adr ) ) );
+				}
+			}
+			break;
+		case OP_LH:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LH SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_WORD_EXTEND( program_read_word_32le( n_adr ^ 2 ) ) );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), MIPS_WORD_EXTEND( program_read_word_32le( n_adr ) ) );
+				}
+			}
+			break;
+		case OP_LWL:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LWL SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x00ffffff ) | ( (uint32_t)program_read_byte_32le( n_adr + 3 ) << 24 );
+						break;
+					case 1:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x0000ffff ) | ( (uint32_t)program_read_word_32le( n_adr + 1 ) << 16 );
+						break;
+					case 2:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x000000ff ) | ( (uint32_t)program_read_byte_32le( n_adr - 1 ) << 8 ) | ( (uint32_t)program_read_word_32le( n_adr ) << 16 );
+						break;
+					default:
+						n_res = program_read_dword_32le( n_adr - 3 );
+						break;
+					}
+					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x00ffffff ) | ( (uint32_t)program_read_byte_32le( n_adr ) << 24 );
+						break;
+					case 1:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x0000ffff ) | ( (uint32_t)program_read_word_32le( n_adr - 1 ) << 16 );
+						break;
+					case 2:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0x000000ff ) | ( (uint32_t)program_read_word_32le( n_adr - 2 ) << 8 ) | ( (uint32_t)program_read_byte_32le( n_adr ) << 24 );
+						break;
+					default:
+						n_res = program_read_dword_32le( n_adr - 3 );
+						break;
+					}
+					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
+				}
+			}
+			break;
+		case OP_LW:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LW SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+#if 0
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+				{
+					printf("ADEL\n");
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+#endif
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), program_read_dword_32le( n_adr ) );
+				}
+			}
+			break;
+		case OP_LBU:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LBU SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), program_read_byte_32le( n_adr ^ 3 ) );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), program_read_byte_32le( n_adr ) );
+				}
+			}
+			break;
+		case OP_LHU:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LHU SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), program_read_word_32le( n_adr ^ 2 ) );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					mips_delayed_load( INS_RT( mipscpu.op ), program_read_word_32le( n_adr ) );
+				}
+			}
+			break;
+		case OP_LWR:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LWR SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 3:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffffff00 ) | program_read_byte_32le( n_adr - 3 );
+						break;
+					case 2:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffff0000 ) | program_read_word_32le( n_adr - 2 );
+						break;
+					case 1:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xff000000 ) | program_read_word_32le( n_adr - 1 ) | ( (uint32_t)program_read_byte_32le( n_adr + 1 ) << 16 );
+						break;
+					default:
+						n_res = program_read_dword_32le( n_adr );
+						break;
+					}
+					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 3:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffffff00 ) | program_read_byte_32le( n_adr );
+						break;
+					case 2:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xffff0000 ) | program_read_word_32le( n_adr );
+						break;
+					case 1:
+						n_res = ( mipscpu.r[ INS_RT( mipscpu.op ) ] & 0xff000000 ) | program_read_byte_32le( n_adr ) | ( (uint32_t)program_read_word_32le( n_adr + 1 ) << 8 );
+						break;
+					default:
+						n_res = program_read_dword_32le( n_adr );
+						break;
+					}
+					mips_delayed_load( INS_RT( mipscpu.op ), n_res );
+				}
+			}
+			break;
+		case OP_SB:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: SB SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_byte_32le( n_adr ^ 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_SH:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: SH SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_word_32le( n_adr ^ 2, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 1 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_SWL:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				printf("SR_ISC not supported\n");
+				logerror( "%08x: SWL SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					printf("permission violation?\n");
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						program_write_byte_32le( n_adr + 3, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
+						break;
+					case 1:
+						program_write_word_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
+						break;
+					case 2:
+						program_write_byte_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
+						program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
+						break;
+					case 3:
+						program_write_dword_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					}
+					mips_advance_pc();
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					printf("permission violation 2\n");
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
+						break;
+					case 1:
+						program_write_word_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
+						break;
+					case 2:
+						program_write_word_32le( n_adr - 2, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
+						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 24 );
+						break;
+					case 3:
+						program_write_dword_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					}
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_SW:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+/* used by bootstrap
+				logerror( "%08x: SW SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+*/
+				mips_advance_pc();
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if(0) // ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_SWR:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: SWR SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & ( SR_RE | SR_KUC ) ) == ( SR_RE | SR_KUC ) )
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					case 1:
+						program_write_word_32le( n_adr - 1, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						program_write_byte_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 16 );
+						break;
+					case 2:
+						program_write_word_32le( n_adr - 2, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					case 3:
+						program_write_byte_32le( n_adr - 3, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					}
+					mips_advance_pc();
+				}
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					switch( n_adr & 3 )
+					{
+					case 0:
+						program_write_dword_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					case 1:
+						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						program_write_word_32le( n_adr + 1, mipscpu.r[ INS_RT( mipscpu.op ) ] >> 8 );
+						break;
+					case 2:
+						program_write_word_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					case 3:
+						program_write_byte_32le( n_adr, mipscpu.r[ INS_RT( mipscpu.op ) ] );
+						break;
+					}
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_LWC1:
+			/* todo: */
+			logerror( "%08x: COP1 LWC not supported\n", mipscpu.pc );
+			mips_stop();
+			mips_advance_pc();
+			break;
+		case OP_LWC2:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
+			{
+				mips_exception( EXC_CPU );
+				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: LWC2 SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+				{
+					mips_exception( EXC_ADEL );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					/* todo: delay? */
+					setcp2dr( INS_RT( mipscpu.op ), program_read_dword_32le( n_adr ) );
+					mips_advance_pc();
+				}
+			}
+			break;
+		case OP_SWC1:
+			/* todo: */
+			logerror( "%08x: COP1 SWC not supported\n", mipscpu.pc );
+			mips_stop();
+			mips_advance_pc();
+			break;
+		case OP_SWC2:
+			if( ( mipscpu.cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
+			{
+				mips_exception( EXC_CPU );
+				mips_set_cp0r( CP0_CAUSE, ( mipscpu.cp0r[ CP0_CAUSE ] & ~CAUSE_CE ) | CAUSE_CE2 );
+			}
+			else if( ( mipscpu.cp0r[ CP0_SR ] & SR_ISC ) != 0 )
+			{
+				/* todo: */
+				logerror( "%08x: SWC2 SR_ISC not supported\n", mipscpu.pc );
+				mips_stop();
+				mips_advance_pc();
+			}
+			else
+			{
+				uint32_t n_adr;
+				n_adr = mipscpu.r[ INS_RS( mipscpu.op ) ] + MIPS_WORD_EXTEND( INS_IMMEDIATE( mipscpu.op ) );
+				if( ( n_adr & ( ( ( mipscpu.cp0r[ CP0_SR ] & SR_KUC ) << 30 ) | 3 ) ) != 0 )
+				{
+					mips_exception( EXC_ADES );
+					mips_set_cp0r( CP0_BADVADDR, n_adr );
+				}
+				else
+				{
+					program_write_dword_32le( n_adr, getcp2dr( INS_RT( mipscpu.op ) ) );
+					mips_advance_pc();
+				}
+			}
+			break;
+		default:
+			printf( "%08x: unknown opcode %08x (prev %08x, RA %08x)\n", mipscpu.pc, mipscpu.op, mipscpu.prevpc,  mipscpu.r[31] );
+			mips_stop();
+			mips_exception( EXC_RI );
+  			break;
+		}
+		mips_ICount--;
+	} while( mips_ICount > 0 );
+
+	return cycles - mips_ICount;
+}
+
+static void mips_get_context( void *dst )
+{
+	if( dst )
+	{
+		*(mips_cpu_context *)dst = mipscpu;
+	}
+}
+
+static void mips_set_context( void *src )
+{
+	if( src )
+	{
+		mipscpu = *(mips_cpu_context *)src;
+		change_pc( mipscpu.pc );
+	}
+}
+
+static void set_irq_line( int irqline, int state )
+{
+	uint32_t ip;
+
+	switch( irqline )
+	{
+	case MIPS_IRQ0:
+		ip = CAUSE_IP2;
+		break;
+	case MIPS_IRQ1:
+		ip = CAUSE_IP3;
+		break;
+	case MIPS_IRQ2:
+		ip = CAUSE_IP4;
+		break;
+	case MIPS_IRQ3:
+		ip = CAUSE_IP5;
+		break;
+	case MIPS_IRQ4:
+		ip = CAUSE_IP6;
+		break;
+	case MIPS_IRQ5:
+		ip = CAUSE_IP7;
+		break;
+	default:
+		return;
+	}
+
+	switch( state )
+	{
+	case CLEAR_LINE:
+		mips_set_cp0r( CP0_CAUSE, mipscpu.cp0r[ CP0_CAUSE ] & ~ip );
+		break;
+	case ASSERT_LINE:
+		mips_set_cp0r( CP0_CAUSE, mipscpu.cp0r[ CP0_CAUSE ] |= ip );
+		if( mipscpu.irq_callback )
+		{
+			/* HOLD_LINE interrupts are not supported by the architecture.
+			By acknowledging the interupt here they are treated like PULSE_LINE
+			interrupts, so if the interrupt isn't enabled it will be ignored.
+			There is also a problem with PULSE_LINE interrupts as the interrupt
+			pending bits aren't latched the emulated code won't know what caused
+			the interrupt. */
+			(*mipscpu.irq_callback)( irqline );
+		}
+		break;
+	}
+}
+
+/****************************************************************************
+ * Return a formatted string for a register
+ ****************************************************************************/
+
+offs_t mips_dasm( char *buffer, offs_t pc )
+{
+	offs_t ret;
+	change_pc( pc );
+#ifdef MAME_DEBUG
+	ret = DasmMIPS( buffer, pc );
+#else
+	sprintf( buffer, "$%08x", cpu_readop32( pc ) );
+	ret = 4;
+#endif
+	change_pc( mipscpu.pc );
+	return ret;
+}
+
+/* preliminary gte code */
+
+#define VXY0 ( mipscpu.cp2dr[ 0 ].d )
+#define VX0  ( mipscpu.cp2dr[ 0 ].w.l )
+#define VY0  ( mipscpu.cp2dr[ 0 ].w.h )
+#define VZ0  ( mipscpu.cp2dr[ 1 ].w.l )
+#define VXY1 ( mipscpu.cp2dr[ 2 ].d )
+#define VX1  ( mipscpu.cp2dr[ 2 ].w.l )
+#define VY1  ( mipscpu.cp2dr[ 2 ].w.h )
+#define VZ1  ( mipscpu.cp2dr[ 3 ].w.l )
+#define VXY2 ( mipscpu.cp2dr[ 4 ].d )
+#define VX2  ( mipscpu.cp2dr[ 4 ].w.l )
+#define VY2  ( mipscpu.cp2dr[ 4 ].w.h )
+#define VZ2  ( mipscpu.cp2dr[ 5 ].w.l )
+#define RGB  ( mipscpu.cp2dr[ 6 ].d )
+#define R    ( mipscpu.cp2dr[ 6 ].b.l )
+#define G    ( mipscpu.cp2dr[ 6 ].b.h )
+#define B    ( mipscpu.cp2dr[ 6 ].b.h2 )
+#define CODE ( mipscpu.cp2dr[ 6 ].b.h3 )
+#define OTZ  ( mipscpu.cp2dr[ 7 ].w.l )
+#define IR0  ( mipscpu.cp2dr[ 8 ].d )
+#define IR1  ( mipscpu.cp2dr[ 9 ].d )
+#define IR2  ( mipscpu.cp2dr[ 10 ].d )
+#define IR3  ( mipscpu.cp2dr[ 11 ].d )
+#define SXY0 ( mipscpu.cp2dr[ 12 ].d )
+#define SX0  ( mipscpu.cp2dr[ 12 ].w.l )
+#define SY0  ( mipscpu.cp2dr[ 12 ].w.h )
+#define SXY1 ( mipscpu.cp2dr[ 13 ].d )
+#define SX1  ( mipscpu.cp2dr[ 13 ].w.l )
+#define SY1  ( mipscpu.cp2dr[ 13 ].w.h )
+#define SXY2 ( mipscpu.cp2dr[ 14 ].d )
+#define SX2  ( mipscpu.cp2dr[ 14 ].w.l )
+#define SY2  ( mipscpu.cp2dr[ 14 ].w.h )
+#define SXYP ( mipscpu.cp2dr[ 15 ].d )
+#define SXP  ( mipscpu.cp2dr[ 15 ].w.l )
+#define SYP  ( mipscpu.cp2dr[ 15 ].w.h )
+#define SZ0  ( mipscpu.cp2dr[ 16 ].w.l )
+#define SZ1  ( mipscpu.cp2dr[ 17 ].w.l )
+#define SZ2  ( mipscpu.cp2dr[ 18 ].w.l )
+#define SZ3  ( mipscpu.cp2dr[ 19 ].w.l )
+#define RGB0 ( mipscpu.cp2dr[ 20 ].d )
+#define R0   ( mipscpu.cp2dr[ 20 ].b.l )
+#define G0   ( mipscpu.cp2dr[ 20 ].b.h )
+#define B0   ( mipscpu.cp2dr[ 20 ].b.h2 )
+#define CD0  ( mipscpu.cp2dr[ 20 ].b.h3 )
+#define RGB1 ( mipscpu.cp2dr[ 21 ].d )
+#define R1   ( mipscpu.cp2dr[ 21 ].b.l )
+#define G1   ( mipscpu.cp2dr[ 21 ].b.h )
+#define B1   ( mipscpu.cp2dr[ 21 ].b.h2 )
+#define CD1  ( mipscpu.cp2dr[ 21 ].b.h3 )
+#define RGB2 ( mipscpu.cp2dr[ 22 ].d )
+#define R2   ( mipscpu.cp2dr[ 22 ].b.l )
+#define G2   ( mipscpu.cp2dr[ 22 ].b.h )
+#define B2   ( mipscpu.cp2dr[ 22 ].b.h2 )
+#define CD2  ( mipscpu.cp2dr[ 22 ].b.h3 )
+#define RES1 ( mipscpu.cp2dr[ 23 ].d )
+#define MAC0 ( mipscpu.cp2dr[ 24 ].d )
+#define MAC1 ( mipscpu.cp2dr[ 25 ].d )
+#define MAC2 ( mipscpu.cp2dr[ 26 ].d )
+#define MAC3 ( mipscpu.cp2dr[ 27 ].d )
+#define IRGB ( mipscpu.cp2dr[ 28 ].d )
+#define ORGB ( mipscpu.cp2dr[ 29 ].d )
+#define LZCS ( mipscpu.cp2dr[ 30 ].d )
+#define LZCR ( mipscpu.cp2dr[ 31 ].d )
+
+#define D1  ( mipscpu.cp2cr[ 0 ].d )
+#define R11 ( mipscpu.cp2cr[ 0 ].w.l )
+#define R12 ( mipscpu.cp2cr[ 0 ].w.h )
+#define R13 ( mipscpu.cp2cr[ 1 ].w.l )
+#define R21 ( mipscpu.cp2cr[ 1 ].w.h )
+#define D2  ( mipscpu.cp2cr[ 2 ].d )
+#define R22 ( mipscpu.cp2cr[ 2 ].w.l )
+#define R23 ( mipscpu.cp2cr[ 2 ].w.h )
+#define R31 ( mipscpu.cp2cr[ 3 ].w.l )
+#define R32 ( mipscpu.cp2cr[ 3 ].w.h )
+#define D3  ( mipscpu.cp2cr[ 4 ].d )
+#define R33 ( mipscpu.cp2cr[ 4 ].w.l )
+#define TRX ( mipscpu.cp2cr[ 5 ].d )
+#define TRY ( mipscpu.cp2cr[ 6 ].d )
+#define TRZ ( mipscpu.cp2cr[ 7 ].d )
+#define L11 ( mipscpu.cp2cr[ 8 ].w.l )
+#define L12 ( mipscpu.cp2cr[ 8 ].w.h )
+#define L13 ( mipscpu.cp2cr[ 9 ].w.l )
+#define L21 ( mipscpu.cp2cr[ 9 ].w.h )
+#define L22 ( mipscpu.cp2cr[ 10 ].w.l )
+#define L23 ( mipscpu.cp2cr[ 10 ].w.h )
+#define L31 ( mipscpu.cp2cr[ 11 ].w.l )
+#define L32 ( mipscpu.cp2cr[ 11 ].w.h )
+#define L33 ( mipscpu.cp2cr[ 12 ].w.l )
+#define RBK ( mipscpu.cp2cr[ 13 ].d )
+#define GBK ( mipscpu.cp2cr[ 14 ].d )
+#define BBK ( mipscpu.cp2cr[ 15 ].d )
+#define LR1 ( mipscpu.cp2cr[ 16 ].w.l )
+#define LR2 ( mipscpu.cp2cr[ 16 ].w.h )
+#define LR3 ( mipscpu.cp2cr[ 17 ].w.l )
+#define LG1 ( mipscpu.cp2cr[ 17 ].w.h )
+#define LG2 ( mipscpu.cp2cr[ 18 ].w.l )
+#define LG3 ( mipscpu.cp2cr[ 18 ].w.h )
+#define LB1 ( mipscpu.cp2cr[ 19 ].w.l )
+#define LB2 ( mipscpu.cp2cr[ 19 ].w.h )
+#define LB3 ( mipscpu.cp2cr[ 20 ].w.l )
+#define RFC ( mipscpu.cp2cr[ 21 ].d )
+#define GFC ( mipscpu.cp2cr[ 22 ].d )
+#define BFC ( mipscpu.cp2cr[ 23 ].d )
+#define OFX ( mipscpu.cp2cr[ 24 ].d )
+#define OFY ( mipscpu.cp2cr[ 25 ].d )
+#define H   ( mipscpu.cp2cr[ 26 ].w.l )
+#define DQA ( mipscpu.cp2cr[ 27 ].w.l )
+#define DQB ( mipscpu.cp2cr[ 28 ].d )
+#define ZSF3 ( mipscpu.cp2cr[ 29 ].w.l )
+#define ZSF4 ( mipscpu.cp2cr[ 30 ].w.l )
+#define FLAG ( mipscpu.cp2cr[ 31 ].d )
+
+static uint32_t getcp2dr( int n_reg )
+{
+	if( n_reg == 1 || n_reg == 3 || n_reg == 5 || n_reg == 8 || n_reg == 9 || n_reg == 10 || n_reg == 11 )
+	{
+		mipscpu.cp2dr[ n_reg ].d = (int32_t)(int16_t)mipscpu.cp2dr[ n_reg ].d;
+	}
+	else if( n_reg == 17 || n_reg == 18 || n_reg == 19 )
+	{
+		mipscpu.cp2dr[ n_reg ].d = (uint32_t)(uint16_t)mipscpu.cp2dr[ n_reg ].d;
+	}
+	else if( n_reg == 29 )
+	{
+		ORGB = ( ( IR1 >> 7 ) & 0x1f ) | ( ( IR2 >> 2 ) & 0x3e0 ) | ( ( IR3 << 3 ) & 0x7c00 );
+	}
+	GTELOG( "get CP2DR%u=%08x", n_reg, mipscpu.cp2dr[ n_reg ].d );
+	return mipscpu.cp2dr[ n_reg ].d;
+}
+
+static void setcp2dr( int n_reg, uint32_t n_value )
+{
+	GTELOG( "set CP2DR%u=%08x", n_reg, n_value );
+	mipscpu.cp2dr[ n_reg ].d = n_value;
+
+	if( n_reg == 15 )
+	{
+		SXY0 = SXY1;
+		SXY1 = SXY2;
+		SXY2 = SXYP;
+	}
+	else if( n_reg == 28 )
+	{
+		IR1 = ( IRGB & 0x1f ) << 4;
+		IR2 = ( IRGB & 0x3e0 ) >> 1;
+		IR3 = ( IRGB & 0x7c00 ) >> 6;
+	}
+	else if( n_reg == 30 )
+	{
+		uint32_t n_lzcs = LZCS;
+		uint32_t n_lzcr = 0;
+
+		if( ( n_lzcs & 0x80000000 ) == 0 )
+		{
+			n_lzcs = ~n_lzcs;
+		}
+		while( ( n_lzcs & 0x80000000 ) != 0 )
+		{
+			n_lzcr++;
+			n_lzcs <<= 1;
+		}
+		LZCR = n_lzcr;
+	}
+}
+
+static uint32_t getcp2cr( int n_reg )
+{
+	GTELOG( "get CP2CR%u=%08x", n_reg, mipscpu.cp2cr[ n_reg ].d );
+	return mipscpu.cp2cr[ n_reg ].d;
+}
+
+static void setcp2cr( int n_reg, uint32_t n_value )
+{
+	GTELOG( "set CP2CR%u=%08x", n_reg, n_value );
+	mipscpu.cp2cr[ n_reg ].d = n_value;
+}
+
+static inline int32_t LIM( int32_t n_value, int32_t n_max, int32_t n_min, uint32_t n_flag )
+{
+	if( n_value > n_max )
+	{
+		FLAG |= n_flag;
+		return n_max;
+	}
+	else if( n_value < n_min )
+	{
+		FLAG |= n_flag;
+		return n_min;
+	}
+	return n_value;
+}
+
+static inline int64_t BOUNDS( int64_t n_value, int64_t n_max, int n_maxflag, int64_t n_min, int n_minflag )
+{
+	if( n_value > n_max )
+	{
+		FLAG |= n_maxflag;
+	}
+	else if( n_value < n_min )
+	{
+		FLAG |= n_minflag;
+	}
+	return n_value;
+}
+
+#define A1( a ) BOUNDS( ( a ), 0x7fffffff, 30, -(int64_t)0x80000000, ( 1 << 27 ) )
+#define A2( a ) BOUNDS( ( a ), 0x7fffffff, 29, -(int64_t)0x80000000, ( 1 << 26 ) )
+#define A3( a ) BOUNDS( ( a ), 0x7fffffff, 28, -(int64_t)0x80000000, ( 1 << 25 ) )
+#define Lm_B1( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 24 ) )
+#define Lm_B2( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 31 ) | ( 1 << 23 ) )
+#define Lm_B3( a, l ) LIM( ( a ), 0x7fff, -0x8000 * !l, ( 1 << 22 ) )
+#define Lm_C1( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 21 ) )
+#define Lm_C2( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 20 ) )
+#define Lm_C3( a ) LIM( ( a ), 0x00ff, 0x0000, ( 1 << 19 ) )
+#define Lm_D( a ) LIM( ( a ), 0xffff, 0x0000, ( 1 << 31 ) | ( 1 << 18 ) )
+
+static inline uint32_t Lm_E( uint32_t n_z )
+{
+	if( n_z <= H / 2 )
+	{
+		n_z = H / 2;
+		FLAG |= ( 1 << 31 ) | ( 1 << 17 );
+	}
+	if( n_z == 0 )
+	{
+		n_z = 1;
+	}
+	return n_z;
+}
+
+#define F( a ) BOUNDS( ( a ), 0x7fffffff, ( 1 << 31 ) | ( 1 << 16 ), -(int64_t)0x80000000, ( 1 << 31 ) | ( 1 << 15 ) )
+#define Lm_G1( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 14 ) )
+#define Lm_G2( a ) LIM( ( a ), 0x3ff, -0x400, ( 1 << 31 ) | ( 1 << 13 ) )
+#define Lm_H( a ) LIM( ( a ), 0xfff, 0x000, ( 1 << 12 ) )
+
+static void docop2( int gteop )
+{
+	int n_sf;
+	int n_v;
+	int n_lm;
+	int n_pass;
+	uint16_t n_v1;
+	uint16_t n_v2;
+	uint16_t n_v3;
+	const uint16_t **p_n_mx;
+	const uint32_t **p_n_cv;
+	static const uint16_t n_zm = 0;
+	static const uint32_t n_zc = 0;
+	static const uint16_t *p_n_vx[] = { &VX0, &VX1, &VX2 };
+	static const uint16_t *p_n_vy[] = { &VY0, &VY1, &VY2 };
+	static const uint16_t *p_n_vz[] = { &VZ0, &VZ1, &VZ2 };
+	static const uint16_t *p_n_rm[] = { &R11, &R12, &R13, &R21, &R22, &R23, &R31, &R32, &R33 };
+	static const uint16_t *p_n_lm[] = { &L11, &L12, &L13, &L21, &L22, &L23, &L31, &L32, &L33 };
+	static const uint16_t *p_n_cm[] = { &LR1, &LR2, &LR3, &LG1, &LG2, &LG3, &LB1, &LB2, &LB3 };
+	static const uint16_t *p_n_zm[] = { &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm, &n_zm };
+	static const uint16_t **p_p_n_mx[] = { p_n_rm, p_n_lm, p_n_cm, p_n_zm };
+	static const uint32_t *p_n_tr[] = { &TRX, &TRY, &TRZ };
+	static const uint32_t *p_n_bk[] = { &RBK, &GBK, &BBK };
+	static const uint32_t *p_n_fc[] = { &RFC, &GFC, &BFC };
+	static const uint32_t *p_n_zc[] = { &n_zc, &n_zc, &n_zc };
+	static const uint32_t **p_p_n_cv[] = { p_n_tr, p_n_bk, p_n_fc, p_n_zc };
+
+	switch( GTE_FUNCT( gteop ) )
+	{
+	case 0x01:
+		if( gteop == 0x0180001 )
+		{
+			GTELOG( "RTPS" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int32_t)TRX << 12 ) + ( (int16_t)R11 * (int16_t)VX0 ) + ( (int16_t)R12 * (int16_t)VY0 ) + ( (int16_t)R13 * (int16_t)VZ0 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)(int32_t)TRY << 12 ) + ( (int16_t)R21 * (int16_t)VX0 ) + ( (int16_t)R22 * (int16_t)VY0 ) + ( (int16_t)R23 * (int16_t)VZ0 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)(int32_t)TRZ << 12 ) + ( (int16_t)R31 * (int16_t)VX0 ) + ( (int16_t)R32 * (int16_t)VY0 ) + ( (int16_t)R33 * (int16_t)VZ0 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			SZ0 = SZ1;
+			SZ1 = SZ2;
+			SZ2 = SZ3;
+			SZ3 = Lm_D( (int32_t)MAC3 );
+			SXY0 = SXY1;
+			SXY1 = SXY2;
+			SX2 = Lm_G1( F( (int64_t)(int32_t)OFX + ( (int64_t)(int16_t)IR1 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 );
+			SY2 = Lm_G2( F( (int64_t)(int32_t)OFY + ( (int64_t)(int16_t)IR2 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 );
+			MAC0 = F( (int64_t)(int32_t)DQB + ( (int64_t)(int16_t)DQA * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) );
+			IR0 = Lm_H( (int32_t)MAC0 >> 12 );
+			return;
+		}
+		break;
+	case 0x06:
+		if( gteop == 0x0400006 ||
+			gteop == 0x1400006 ||
+			gteop == 0x0155cc6 )
+		{
+			GTELOG( "NCLIP" );
+			FLAG = 0;
+
+			MAC0 = F( ( (int64_t)(int16_t)SX0 * (int16_t)SY1 ) + ( (int16_t)SX1 * (int16_t)SY2 ) + ( (int16_t)SX2 * (int16_t)SY0 ) - ( (int16_t)SX0 * (int16_t)SY2 ) - ( (int16_t)SX1 * (int16_t)SY0 ) - ( (int16_t)SX2 * (int16_t)SY1 ) );
+			return;
+		}
+		break;
+	case 0x0c:
+		if( GTE_OP( gteop ) == 0x17 )
+		{
+			GTELOG( "OP" );
+			n_sf = 12 * GTE_SF( gteop );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int32_t)D2 * (int16_t)IR3 ) - ( (int64_t)(int32_t)D3 * (int16_t)IR2 ) ) >> n_sf );
+			MAC2 = A2( ( ( (int64_t)(int32_t)D3 * (int16_t)IR1 ) - ( (int64_t)(int32_t)D1 * (int16_t)IR3 ) ) >> n_sf );
+			MAC3 = A3( ( ( (int64_t)(int32_t)D1 * (int16_t)IR2 ) - ( (int64_t)(int32_t)D2 * (int16_t)IR1 ) ) >> n_sf );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			return;
+		}
+		break;
+	case 0x10:
+		if( gteop == 0x0780010 )
+		{
+			GTELOG( "DPCS" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)R << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - ( R << 4 ), 0 ) ) ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)G << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - ( G << 4 ), 0 ) ) ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)B << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - ( B << 4 ), 0 ) ) ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x11:
+		if( gteop == 0x0980011 )
+		{
+			GTELOG( "INTPL" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int16_t)IR1 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - (int16_t)IR1, 0 ) ) ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)(int16_t)IR2 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - (int16_t)IR2, 0 ) ) ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)(int16_t)IR3 << 12 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - (int16_t)IR3, 0 ) ) ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 );
+			return;
+		}
+		break;
+	case 0x12:
+		if( GTE_OP( gteop ) == 0x04 )
+		{
+			GTELOG( "MVMVA" );
+			n_sf = 12 * GTE_SF( gteop );
+			p_n_mx = p_p_n_mx[ GTE_MX( gteop ) ];
+			n_v = GTE_V( gteop );
+			if( n_v < 3 )
+			{
+				n_v1 = *p_n_vx[ n_v ];
+				n_v2 = *p_n_vy[ n_v ];
+				n_v3 = *p_n_vz[ n_v ];
+			}
+			else
+			{
+				n_v1 = IR1;
+				n_v2 = IR2;
+				n_v3 = IR3;
+			}
+			p_n_cv = p_p_n_cv[ GTE_CV( gteop ) ];
+			n_lm = GTE_LM( gteop );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int32_t)*p_n_cv[ 0 ] << 12 ) + ( (int16_t)*p_n_mx[ 0 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 1 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 2 ] * (int16_t)n_v3 ) ) >> n_sf );
+			MAC2 = A2( ( ( (int64_t)(int32_t)*p_n_cv[ 1 ] << 12 ) + ( (int16_t)*p_n_mx[ 3 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 4 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 5 ] * (int16_t)n_v3 ) ) >> n_sf );
+			MAC3 = A3( ( ( (int64_t)(int32_t)*p_n_cv[ 2 ] << 12 ) + ( (int16_t)*p_n_mx[ 6 ] * (int16_t)n_v1 ) + ( (int16_t)*p_n_mx[ 7 ] * (int16_t)n_v2 ) + ( (int16_t)*p_n_mx[ 8 ] * (int16_t)n_v3 ) ) >> n_sf );
+
+			IR1 = Lm_B1( (int32_t)MAC1, n_lm );
+			IR2 = Lm_B2( (int32_t)MAC2, n_lm );
+			IR3 = Lm_B3( (int32_t)MAC3, n_lm );
+			return;
+		}
+		break;
+	case 0x13:
+		if( gteop == 0x0e80413 )
+		{
+			GTELOG( "NCDS" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+			MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+			MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x14:
+		if( gteop == 0x1280414 )
+		{
+			GTELOG( "CDP" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+			IR1 = Lm_B1( MAC1, 1 );
+			IR2 = Lm_B2( MAC2, 1 );
+			IR3 = Lm_B3( MAC3, 1 );
+			MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+			MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+			MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+			IR1 = Lm_B1( MAC1, 1 );
+			IR2 = Lm_B2( MAC2, 1 );
+			IR3 = Lm_B3( MAC3, 1 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x16:
+		if( gteop == 0x0f80416 )
+		{
+			GTELOG( "NCDT" );
+			FLAG = 0;
+
+			for( n_v = 0; n_v < 3; n_v++ )
+			{
+				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				MAC1 = A1( ( ( ( (int64_t)R << 4 ) * (int16_t)IR1 ) + ( (int16_t)IR0 * Lm_B1( (int32_t)RFC - ( ( R * (int16_t)IR1 ) >> 8 ), 0 ) ) ) >> 12 );
+				MAC2 = A2( ( ( ( (int64_t)G << 4 ) * (int16_t)IR2 ) + ( (int16_t)IR0 * Lm_B2( (int32_t)GFC - ( ( G * (int16_t)IR2 ) >> 8 ), 0 ) ) ) >> 12 );
+				MAC3 = A3( ( ( ( (int64_t)B << 4 ) * (int16_t)IR3 ) + ( (int16_t)IR0 * Lm_B3( (int32_t)BFC - ( ( B * (int16_t)IR3 ) >> 8 ), 0 ) ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				CD0 = CD1;
+				CD1 = CD2;
+				CD2 = CODE;
+				R0 = R1;
+				R1 = R2;
+				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+				G0 = G1;
+				G1 = G2;
+				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+				B0 = B1;
+				B1 = B2;
+				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			}
+			return;
+		}
+		break;
+	case 0x1b:
+		if( gteop == 0x108041b )
+		{
+			GTELOG( "NCCS" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
+			MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
+			MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x1c:
+		if( gteop == 0x138041c )
+		{
+			GTELOG( "CC" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+			IR1 = Lm_B1( MAC1, 1 );
+			IR2 = Lm_B2( MAC2, 1 );
+			IR3 = Lm_B3( MAC3, 1 );
+			MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
+			MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
+			MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
+			IR1 = Lm_B1( MAC1, 1 );
+			IR2 = Lm_B2( MAC2, 1 );
+			IR3 = Lm_B3( MAC3, 1 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x1e:
+		if( gteop == 0x0c8041e )
+		{
+			GTELOG( "NCS" );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)VX0 ) + ( (int16_t)L12 * (int16_t)VY0 ) + ( (int16_t)L13 * (int16_t)VZ0 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)VX0 ) + ( (int16_t)L22 * (int16_t)VY0 ) + ( (int16_t)L23 * (int16_t)VZ0 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)VX0 ) + ( (int16_t)L32 * (int16_t)VY0 ) + ( (int16_t)L33 * (int16_t)VZ0 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+			MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+			MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+			IR1 = Lm_B1( (int32_t)MAC1, 1 );
+			IR2 = Lm_B2( (int32_t)MAC2, 1 );
+			IR3 = Lm_B3( (int32_t)MAC3, 1 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x20:
+		if( gteop == 0x0d80420 )
+		{
+			GTELOG( "NCT" );
+			FLAG = 0;
+
+			for( n_v = 0; n_v < 3; n_v++ )
+			{
+				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				CD0 = CD1;
+				CD1 = CD2;
+				CD2 = CODE;
+				R0 = R1;
+				R1 = R2;
+				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+				G0 = G1;
+				G1 = G2;
+				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+				B0 = B1;
+				B1 = B2;
+				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			}
+			return;
+		}
+		break;
+	case 0x28:
+		if( GTE_OP( gteop ) == 0x0a && GTE_LM( gteop ) == 1 )
+		{
+			GTELOG( "SQR" );
+			n_sf = 12 * GTE_SF( gteop );
+			FLAG = 0;
+
+			MAC1 = A1( ( (int64_t)(int16_t)IR1 * (int16_t)IR1 ) >> n_sf );
+			MAC2 = A2( ( (int64_t)(int16_t)IR2 * (int16_t)IR2 ) >> n_sf );
+			MAC3 = A3( ( (int64_t)(int16_t)IR3 * (int16_t)IR3 ) >> n_sf );
+			IR1 = Lm_B1( MAC1, 1 );
+			IR2 = Lm_B2( MAC2, 1 );
+			IR3 = Lm_B3( MAC3, 1 );
+			return;
+		}
+		break;
+	// DCPL 0x29
+	case 0x2a:
+		if( gteop == 0x0f8002a )
+		{
+			GTELOG( "DPCT" );
+			FLAG = 0;
+
+			for( n_pass = 0; n_pass < 3; n_pass++ )
+			{
+				MAC1 = A1( ( ( (int64_t)R0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)RFC - ( R0 << 4 ), 0 ) ) ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)G0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)GFC - ( G0 << 4 ), 0 ) ) ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)B0 << 16 ) + ( (int64_t)(int16_t)IR0 * ( Lm_B1( (int32_t)BFC - ( B0 << 4 ), 0 ) ) ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 0 );
+				IR2 = Lm_B2( (int32_t)MAC2, 0 );
+				IR3 = Lm_B3( (int32_t)MAC3, 0 );
+				CD0 = CD1;
+				CD1 = CD2;
+				CD2 = CODE;
+				R0 = R1;
+				R1 = R2;
+				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+				G0 = G1;
+				G1 = G2;
+				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+				B0 = B1;
+				B1 = B2;
+				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			}
+			return;
+		}
+		break;
+	case 0x2d:
+		if( gteop == 0x158002d )
+		{
+			GTELOG( "AVSZ3" );
+			FLAG = 0;
+
+			MAC0 = F( ( (int64_t)(int16_t)ZSF3 * SZ1 ) + ( (int16_t)ZSF3 * SZ2 ) + ( (int16_t)ZSF3 * SZ3 ) );
+			OTZ = Lm_D( (int32_t)MAC0 >> 12 );
+			return;
+		}
+		break;
+	case 0x2e:
+		if( gteop == 0x168002e )
+		{
+			GTELOG( "AVSZ4" );
+			FLAG = 0;
+
+			MAC0 = F( ( (int64_t)(int16_t)ZSF4 * SZ0 ) + ( (int16_t)ZSF4 * SZ1 ) + ( (int16_t)ZSF4 * SZ2 ) + ( (int16_t)ZSF4 * SZ3 ) );
+			OTZ = Lm_D( (int32_t)MAC0 >> 12 );
+			return;
+		}
+		break;
+	case 0x30:
+		if( gteop == 0x0280030 )
+		{
+			GTELOG( "RTPT" );
+			FLAG = 0;
+
+			for( n_v = 0; n_v < 3; n_v++ )
+			{
+				MAC1 = A1( ( ( (int64_t)(int32_t)TRX << 12 ) + ( (int16_t)R11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)(int32_t)TRY << 12 ) + ( (int16_t)R21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)(int32_t)TRZ << 12 ) + ( (int16_t)R31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)R32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)R33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 0 );
+				IR2 = Lm_B2( (int32_t)MAC2, 0 );
+				IR3 = Lm_B3( (int32_t)MAC3, 0 );
+				SZ0 = SZ1;
+				SZ1 = SZ2;
+				SZ2 = SZ3;
+				SZ3 = Lm_D( (int32_t)MAC3 );
+				SXY0 = SXY1;
+				SXY1 = SXY2;
+				SX2 = Lm_G1( F( ( (int64_t)(int32_t)OFX + ( (int64_t)(int16_t)IR1 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 ) );
+				SY2 = Lm_G2( F( ( (int64_t)(int32_t)OFY + ( (int64_t)(int16_t)IR2 * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) ) >> 16 ) );
+				MAC0 = F( (int64_t)(int32_t)DQB + ( (int64_t)(int16_t)DQA * ( ( (uint32_t)H << 16 ) / Lm_E( SZ3 ) ) ) );
+				IR0 = Lm_H( (int32_t)MAC0 >> 12 );
+			}
+			return;
+		}
+		break;
+	case 0x3d:
+		if( GTE_OP( gteop ) == 0x09 ||
+			GTE_OP( gteop ) == 0x19 )
+		{
+			GTELOG( "GPF" );
+			n_sf = 12 * GTE_SF( gteop );
+			FLAG = 0;
+
+			MAC1 = A1( ( (int64_t)(int16_t)IR0 * (int16_t)IR1 ) >> n_sf );
+			MAC2 = A2( ( (int64_t)(int16_t)IR0 * (int16_t)IR2 ) >> n_sf );
+			MAC3 = A3( ( (int64_t)(int16_t)IR0 * (int16_t)IR3 ) >> n_sf );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x3e:
+		if( GTE_OP( gteop ) == 0x1a )
+		{
+			GTELOG( "GPL" );
+			n_sf = 12 * GTE_SF( gteop );
+			FLAG = 0;
+
+			MAC1 = A1( ( ( (int64_t)(int32_t)MAC1 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR1 ) ) >> n_sf );
+			MAC2 = A2( ( ( (int64_t)(int32_t)MAC2 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR2 ) ) >> n_sf );
+			MAC3 = A3( ( ( (int64_t)(int32_t)MAC3 << n_sf ) + ( (int16_t)IR0 * (int16_t)IR3 ) ) >> n_sf );
+			IR1 = Lm_B1( (int32_t)MAC1, 0 );
+			IR2 = Lm_B2( (int32_t)MAC2, 0 );
+			IR3 = Lm_B3( (int32_t)MAC3, 0 );
+			CD0 = CD1;
+			CD1 = CD2;
+			CD2 = CODE;
+			R0 = R1;
+			R1 = R2;
+			R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+			G0 = G1;
+			G1 = G2;
+			G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+			B0 = B1;
+			B1 = B2;
+			B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			return;
+		}
+		break;
+	case 0x3f:
+		if( gteop == 0x108043f ||
+			gteop == 0x118043f )
+		{
+			GTELOG( "NCCT" );
+			FLAG = 0;
+
+			for( n_v = 0; n_v < 3; n_v++ )
+			{
+				MAC1 = A1( ( ( (int64_t)(int16_t)L11 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L12 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L13 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)(int16_t)L21 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L22 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L23 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)(int16_t)L31 * (int16_t)*p_n_vx[ n_v ] ) + ( (int16_t)L32 * (int16_t)*p_n_vy[ n_v ] ) + ( (int16_t)L33 * (int16_t)*p_n_vz[ n_v ] ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				MAC1 = A1( ( ( (int64_t)RBK << 12 ) + ( (int16_t)LR1 * (int16_t)IR1 ) + ( (int16_t)LR2 * (int16_t)IR2 ) + ( (int16_t)LR3 * (int16_t)IR3 ) ) >> 12 );
+				MAC2 = A2( ( ( (int64_t)GBK << 12 ) + ( (int16_t)LG1 * (int16_t)IR1 ) + ( (int16_t)LG2 * (int16_t)IR2 ) + ( (int16_t)LG3 * (int16_t)IR3 ) ) >> 12 );
+				MAC3 = A3( ( ( (int64_t)BBK << 12 ) + ( (int16_t)LB1 * (int16_t)IR1 ) + ( (int16_t)LB2 * (int16_t)IR2 ) + ( (int16_t)LB3 * (int16_t)IR3 ) ) >> 12 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				MAC1 = A1( ( (int64_t)R * (int16_t)IR1 ) >> 8 );
+				MAC2 = A2( ( (int64_t)G * (int16_t)IR2 ) >> 8 );
+				MAC3 = A3( ( (int64_t)B * (int16_t)IR3 ) >> 8 );
+				IR1 = Lm_B1( (int32_t)MAC1, 1 );
+				IR2 = Lm_B2( (int32_t)MAC2, 1 );
+				IR3 = Lm_B3( (int32_t)MAC3, 1 );
+				CD0 = CD1;
+				CD1 = CD2;
+				CD2 = CODE;
+				R0 = R1;
+				R1 = R2;
+				R2 = Lm_C1( (int32_t)MAC1 >> 4 );
+				G0 = G1;
+				G1 = G2;
+				G2 = Lm_C2( (int32_t)MAC2 >> 4 );
+				B0 = B1;
+				B1 = B2;
+				B2 = Lm_C3( (int32_t)MAC3 >> 4 );
+			}
+			return;
+		}
+		break;
+	}
+//	usrintf_showmessage_secs( 1, "unknown GTE op %08x", gteop );
+	logerror( "%08x: unknown GTE op %08x\n", mipscpu.pc, gteop );
+	mips_stop();
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+void mips_set_info(uint32_t state, union cpuinfo *info)
+{
+	switch (state)
+	{
+		/* --- the following bits of info are set as 64-bit signed integers --- */
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0:		set_irq_line(MIPS_IRQ0, info->i);		break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1:		set_irq_line(MIPS_IRQ1, info->i);		break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2:		set_irq_line(MIPS_IRQ2, info->i);		break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3:		set_irq_line(MIPS_IRQ3, info->i);		break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4:		set_irq_line(MIPS_IRQ4, info->i);		break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5:		set_irq_line(MIPS_IRQ5, info->i);		break;
+
+		case CPUINFO_INT_PC:							mips_set_pc( info->i );					break;
+		case CPUINFO_INT_REGISTER + MIPS_PC:			mips_set_pc( info->i );					break;
+		case CPUINFO_INT_SP:							/* no stack */							break;
+		case CPUINFO_INT_REGISTER + MIPS_DELAYV:		mipscpu.delayv = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_DELAYR:		if( info->i <= REGPC ) mipscpu.delayr = info->i; break;
+		case CPUINFO_INT_REGISTER + MIPS_HI:			mipscpu.hi = info->i;					break;
+		case CPUINFO_INT_REGISTER + MIPS_LO:			mipscpu.lo = info->i;					break;
+		case CPUINFO_INT_REGISTER + MIPS_R0:			mipscpu.r[ 0 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R1:			mipscpu.r[ 1 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R2:			mipscpu.r[ 2 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R3:			mipscpu.r[ 3 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R4:			mipscpu.r[ 4 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R5:			mipscpu.r[ 5 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R6:			mipscpu.r[ 6 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R7:			mipscpu.r[ 7 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R8:			mipscpu.r[ 8 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R9:			mipscpu.r[ 9 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R10:			mipscpu.r[ 10 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R11:			mipscpu.r[ 11 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R12:			mipscpu.r[ 12 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R13:			mipscpu.r[ 13 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R14:			mipscpu.r[ 14 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R15:			mipscpu.r[ 15 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R16:			mipscpu.r[ 16 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R17:			mipscpu.r[ 17 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R18:			mipscpu.r[ 18 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R19:			mipscpu.r[ 19 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R20:			mipscpu.r[ 20 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R21:			mipscpu.r[ 21 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R22:			mipscpu.r[ 22 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R23:			mipscpu.r[ 23 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R24:			mipscpu.r[ 24 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R25:			mipscpu.r[ 25 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R26:			mipscpu.r[ 26 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R27:			mipscpu.r[ 27 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R28:			mipscpu.r[ 28 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R29:			mipscpu.r[ 29 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R30:			mipscpu.r[ 30 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_R31:			mipscpu.r[ 31 ] = info->i;				break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R0:			mips_set_cp0r( 0, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R1:			mips_set_cp0r( 1, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R2:			mips_set_cp0r( 2, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R3:			mips_set_cp0r( 3, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R4:			mips_set_cp0r( 4, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R5:			mips_set_cp0r( 5, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R6:			mips_set_cp0r( 6, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R7:			mips_set_cp0r( 7, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R8:			mips_set_cp0r( 8, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R9:			mips_set_cp0r( 9, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R10:		mips_set_cp0r( 10, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R11:		mips_set_cp0r( 11, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R12:		mips_set_cp0r( 12, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R13:		mips_set_cp0r( 13, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R14:		mips_set_cp0r( 14, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R15:		mips_set_cp0r( 15, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R16:		mips_set_cp0r( 16, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R17:		mips_set_cp0r( 17, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R18:		mips_set_cp0r( 18, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R19:		mips_set_cp0r( 19, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R20:		mips_set_cp0r( 20, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R21:		mips_set_cp0r( 21, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R22:		mips_set_cp0r( 22, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R23:		mips_set_cp0r( 23, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R24:		mips_set_cp0r( 24, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R25:		mips_set_cp0r( 25, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R26:		mips_set_cp0r( 26, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R27:		mips_set_cp0r( 27, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R28:		mips_set_cp0r( 28, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R29:		mips_set_cp0r( 29, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R30:		mips_set_cp0r( 30, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R31:		mips_set_cp0r( 31, info->i );			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR0:		mipscpu.cp2dr[ 0 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR1:		mipscpu.cp2dr[ 1 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR2:		mipscpu.cp2dr[ 2 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR3:		mipscpu.cp2dr[ 3 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR4:		mipscpu.cp2dr[ 4 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR5:		mipscpu.cp2dr[ 5 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR6:		mipscpu.cp2dr[ 6 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR7:		mipscpu.cp2dr[ 7 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR8:		mipscpu.cp2dr[ 8 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR9:		mipscpu.cp2dr[ 9 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR10:		mipscpu.cp2dr[ 10 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR11:		mipscpu.cp2dr[ 11 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR12:		mipscpu.cp2dr[ 12 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR13:		mipscpu.cp2dr[ 13 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR14:		mipscpu.cp2dr[ 14 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR15:		mipscpu.cp2dr[ 15 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR16:		mipscpu.cp2dr[ 16 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR17:		mipscpu.cp2dr[ 17 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR18:		mipscpu.cp2dr[ 18 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR19:		mipscpu.cp2dr[ 19 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR20:		mipscpu.cp2dr[ 20 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR21:		mipscpu.cp2dr[ 21 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR22:		mipscpu.cp2dr[ 22 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR23:		mipscpu.cp2dr[ 23 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR24:		mipscpu.cp2dr[ 24 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR25:		mipscpu.cp2dr[ 25 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR26:		mipscpu.cp2dr[ 26 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR27:		mipscpu.cp2dr[ 27 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR28:		mipscpu.cp2dr[ 28 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR29:		mipscpu.cp2dr[ 29 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR30:		mipscpu.cp2dr[ 30 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR31:		mipscpu.cp2dr[ 31 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR0:		mipscpu.cp2cr[ 0 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR1:		mipscpu.cp2cr[ 1 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR2:		mipscpu.cp2cr[ 2 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR3:		mipscpu.cp2cr[ 3 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR4:		mipscpu.cp2cr[ 4 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR5:		mipscpu.cp2cr[ 5 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR6:		mipscpu.cp2cr[ 6 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR7:		mipscpu.cp2cr[ 7 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR8:		mipscpu.cp2cr[ 8 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR9:		mipscpu.cp2cr[ 9 ].d = info->i;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR10:		mipscpu.cp2cr[ 10 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR11:		mipscpu.cp2cr[ 11 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR12:		mipscpu.cp2cr[ 12 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR13:		mipscpu.cp2cr[ 13 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR14:		mipscpu.cp2cr[ 14 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR15:		mipscpu.cp2cr[ 15 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR16:		mipscpu.cp2cr[ 16 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR17:		mipscpu.cp2cr[ 17 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR18:		mipscpu.cp2cr[ 18 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR19:		mipscpu.cp2cr[ 19 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR20:		mipscpu.cp2cr[ 20 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR21:		mipscpu.cp2cr[ 21 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR22:		mipscpu.cp2cr[ 22 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR23:		mipscpu.cp2cr[ 23 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR24:		mipscpu.cp2cr[ 24 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR25:		mipscpu.cp2cr[ 25 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR26:		mipscpu.cp2cr[ 26 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR27:		mipscpu.cp2cr[ 27 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR28:		mipscpu.cp2cr[ 28 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR29:		mipscpu.cp2cr[ 29 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR30:		mipscpu.cp2cr[ 30 ].d = info->i;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR31:		mipscpu.cp2cr[ 31 ].d = info->i;		break;
+
+		/* --- the following bits of info are set as pointers to data or functions --- */
+		case CPUINFO_PTR_IRQ_CALLBACK:					mipscpu.irq_callback = info->irqcallback;			break;
+	}
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void mips_get_info(uint32_t state, union cpuinfo *info)
+{
+	switch (state)
+	{
+		/* --- the following bits of info are returned as 64-bit signed integers --- */
+		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(mipscpu);				break;
+		case CPUINFO_INT_INPUT_LINES:					info->i = 6;							break;
+		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
+		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
+		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 1;							break;
+		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 4;							break;
+		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 4;							break;
+		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
+		case CPUINFO_INT_MAX_CYCLES:					info->i = 40;							break;
+
+		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 32;					break;
+		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32;					break;
+		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
+		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
+		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
+		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
+		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 0;					break;
+		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 0;					break;
+		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
+
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ0:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ1:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ2:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ3:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ4:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break;
+		case CPUINFO_INT_INPUT_STATE + MIPS_IRQ5:		info->i = (mipscpu.cp0r[ CP0_CAUSE ] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break;
+
+		case CPUINFO_INT_PREVIOUSPC:					/* not implemented */					break;
+
+		case CPUINFO_INT_PC:							info->i = mipscpu.pc;					break;
+		case CPUINFO_INT_REGISTER + MIPS_PC:			info->i = mipscpu.pc;					break;
+		case CPUINFO_INT_SP:
+			/* because there is no hardware stack and the pipeline causes the cpu to execute the
+			instruction after a subroutine call before the subroutine is executed there is little
+			chance of cmd_step_over() in mamedbg.c working. */
+								info->i = 0;													break;
+		case CPUINFO_INT_REGISTER + MIPS_DELAYV:		info->i = mipscpu.delayv;				break;
+		case CPUINFO_INT_REGISTER + MIPS_DELAYR:		info->i = mipscpu.delayr;				break;
+		case CPUINFO_INT_REGISTER + MIPS_HI:			info->i = mipscpu.hi;					break;
+		case CPUINFO_INT_REGISTER + MIPS_LO:			info->i = mipscpu.lo;					break;
+		case CPUINFO_INT_REGISTER + MIPS_R0:			info->i = mipscpu.r[ 0 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R1:			info->i = mipscpu.r[ 1 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R2:			info->i = mipscpu.r[ 2 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R3:			info->i = mipscpu.r[ 3 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R4:			info->i = mipscpu.r[ 4 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R5:			info->i = mipscpu.r[ 5 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R6:			info->i = mipscpu.r[ 6 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R7:			info->i = mipscpu.r[ 7 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R8:			info->i = mipscpu.r[ 8 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R9:			info->i = mipscpu.r[ 9 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R10:			info->i = mipscpu.r[ 10 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R11:			info->i = mipscpu.r[ 11 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R12:			info->i = mipscpu.r[ 12 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R13:			info->i = mipscpu.r[ 13 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R14:			info->i = mipscpu.r[ 14 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R15:			info->i = mipscpu.r[ 15 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R16:			info->i = mipscpu.r[ 16 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R17:			info->i = mipscpu.r[ 17 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R18:			info->i = mipscpu.r[ 18 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R19:			info->i = mipscpu.r[ 19 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R20:			info->i = mipscpu.r[ 20 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R21:			info->i = mipscpu.r[ 21 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R22:			info->i = mipscpu.r[ 22 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R23:			info->i = mipscpu.r[ 23 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R24:			info->i = mipscpu.r[ 24 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R25:			info->i = mipscpu.r[ 25 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R26:			info->i = mipscpu.r[ 26 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R27:			info->i = mipscpu.r[ 27 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R28:			info->i = mipscpu.r[ 28 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R29:			info->i = mipscpu.r[ 29 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R30:			info->i = mipscpu.r[ 30 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_R31:			info->i = mipscpu.r[ 31 ];				break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R0:			info->i = mipscpu.cp0r[ 0 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R1:			info->i = mipscpu.cp0r[ 1 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R2:			info->i = mipscpu.cp0r[ 2 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R3:			info->i = mipscpu.cp0r[ 3 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R4:			info->i = mipscpu.cp0r[ 4 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R5:			info->i = mipscpu.cp0r[ 5 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R6:			info->i = mipscpu.cp0r[ 6 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R7:			info->i = mipscpu.cp0r[ 7 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R8:			info->i = mipscpu.cp0r[ 8 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R9:			info->i = mipscpu.cp0r[ 9 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R10:		info->i = mipscpu.cp0r[ 10 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R11:		info->i = mipscpu.cp0r[ 11 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R12:		info->i = mipscpu.cp0r[ 12 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R13:		info->i = mipscpu.cp0r[ 13 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R14:		info->i = mipscpu.cp0r[ 14 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R15:		info->i = mipscpu.cp0r[ 15 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R16:		info->i = mipscpu.cp0r[ 16 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R17:		info->i = mipscpu.cp0r[ 17 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R18:		info->i = mipscpu.cp0r[ 18 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R19:		info->i = mipscpu.cp0r[ 19 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R20:		info->i = mipscpu.cp0r[ 20 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R21:		info->i = mipscpu.cp0r[ 21 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R22:		info->i = mipscpu.cp0r[ 22 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R23:		info->i = mipscpu.cp0r[ 23 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R24:		info->i = mipscpu.cp0r[ 24 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R25:		info->i = mipscpu.cp0r[ 25 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R26:		info->i = mipscpu.cp0r[ 26 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R27:		info->i = mipscpu.cp0r[ 27 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R28:		info->i = mipscpu.cp0r[ 28 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R29:		info->i = mipscpu.cp0r[ 29 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R30:		info->i = mipscpu.cp0r[ 30 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP0R31:		info->i = mipscpu.cp0r[ 31 ];			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR0:		info->i = mipscpu.cp2dr[ 0 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR1:		info->i = mipscpu.cp2dr[ 1 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR2:		info->i = mipscpu.cp2dr[ 2 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR3:		info->i = mipscpu.cp2dr[ 3 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR4:		info->i = mipscpu.cp2dr[ 4 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR5:		info->i = mipscpu.cp2dr[ 5 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR6:		info->i = mipscpu.cp2dr[ 6 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR7:		info->i = mipscpu.cp2dr[ 7 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR8:		info->i = mipscpu.cp2dr[ 8 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR9:		info->i = mipscpu.cp2dr[ 9 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR10:		info->i = mipscpu.cp2dr[ 10 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR11:		info->i = mipscpu.cp2dr[ 11 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR12:		info->i = mipscpu.cp2dr[ 12 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR13:		info->i = mipscpu.cp2dr[ 13 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR14:		info->i = mipscpu.cp2dr[ 14 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR15:		info->i = mipscpu.cp2dr[ 15 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR16:		info->i = mipscpu.cp2dr[ 16 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR17:		info->i = mipscpu.cp2dr[ 17 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR18:		info->i = mipscpu.cp2dr[ 18 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR19:		info->i = mipscpu.cp2dr[ 19 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR20:		info->i = mipscpu.cp2dr[ 20 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR21:		info->i = mipscpu.cp2dr[ 21 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR22:		info->i = mipscpu.cp2dr[ 22 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR23:		info->i = mipscpu.cp2dr[ 23 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR24:		info->i = mipscpu.cp2dr[ 24 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR25:		info->i = mipscpu.cp2dr[ 25 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR26:		info->i = mipscpu.cp2dr[ 26 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR27:		info->i = mipscpu.cp2dr[ 27 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR28:		info->i = mipscpu.cp2dr[ 28 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR29:		info->i = mipscpu.cp2dr[ 29 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR30:		info->i = mipscpu.cp2dr[ 30 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2DR31:		info->i = mipscpu.cp2dr[ 31 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR0:		info->i = mipscpu.cp2cr[ 0 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR1:		info->i = mipscpu.cp2cr[ 1 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR2:		info->i = mipscpu.cp2cr[ 2 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR3:		info->i = mipscpu.cp2cr[ 3 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR4:		info->i = mipscpu.cp2cr[ 4 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR5:		info->i = mipscpu.cp2cr[ 5 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR6:		info->i = mipscpu.cp2cr[ 6 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR7:		info->i = mipscpu.cp2cr[ 7 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR8:		info->i = mipscpu.cp2cr[ 8 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR9:		info->i = mipscpu.cp2cr[ 9 ].d;			break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR10:		info->i = mipscpu.cp2cr[ 10 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR11:		info->i = mipscpu.cp2cr[ 11 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR12:		info->i = mipscpu.cp2cr[ 12 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR13:		info->i = mipscpu.cp2cr[ 13 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR14:		info->i = mipscpu.cp2cr[ 14 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR15:		info->i = mipscpu.cp2cr[ 15 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR16:		info->i = mipscpu.cp2cr[ 16 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR17:		info->i = mipscpu.cp2cr[ 17 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR18:		info->i = mipscpu.cp2cr[ 18 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR19:		info->i = mipscpu.cp2cr[ 19 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR20:		info->i = mipscpu.cp2cr[ 20 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR21:		info->i = mipscpu.cp2cr[ 21 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR22:		info->i = mipscpu.cp2cr[ 22 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR23:		info->i = mipscpu.cp2cr[ 23 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR24:		info->i = mipscpu.cp2cr[ 24 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR25:		info->i = mipscpu.cp2cr[ 25 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR26:		info->i = mipscpu.cp2cr[ 26 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR27:		info->i = mipscpu.cp2cr[ 27 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR28:		info->i = mipscpu.cp2cr[ 28 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR29:		info->i = mipscpu.cp2cr[ 29 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR30:		info->i = mipscpu.cp2cr[ 30 ].d;		break;
+		case CPUINFO_INT_REGISTER + MIPS_CP2CR31:		info->i = mipscpu.cp2cr[ 31 ].d;		break;
+
+		/* --- the following bits of info are returned as pointers to data or functions --- */
+		case CPUINFO_PTR_SET_INFO:						info->setinfo = mips_set_info;			break;
+		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = mips_get_context;	break;
+		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = mips_set_context;	break;
+		case CPUINFO_PTR_INIT:							info->init = mips_init;					break;
+		case CPUINFO_PTR_RESET:							info->reset = mips_reset;				break;
+		case CPUINFO_PTR_EXIT:							info->exit = mips_exit;					break;
+		case CPUINFO_PTR_EXECUTE:						info->execute = mips_execute;			break;
+		case CPUINFO_PTR_BURN:							info->burn = nullptr;						break;
+		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = mips_dasm;			break;
+		case CPUINFO_PTR_IRQ_CALLBACK:					info->irqcallback = mipscpu.irq_callback; break;
+		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &mips_ICount;			break;
+		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = mips_reg_layout;				break;
+		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = mips_win_layout;				break;
+	}
+}
+
+uint32_t mips_get_cause(void)
+{
+	return mipscpu.cp0r[ CP0_CAUSE ];
+}
+
+uint32_t mips_get_status(void)
+{
+	return mipscpu.cp0r[ CP0_SR ];
+}
+
+void mips_set_status(uint32_t status)
+{
+	mipscpu.cp0r[ CP0_SR ] = status;
+}
+
+uint32_t mips_get_ePC(void)
+{
+	return mipscpu.cp0r[ CP0_EPC ];
+}
+
+int mips_get_icount(void)
+{
+	return mips_ICount;
+}
+
+void mips_set_icount(int count)
+{
+	mips_ICount = count;
+}
+
+
+#if (HAS_PSXCPU)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void psxcpu_get_info(uint32_t state, union cpuinfo *info)
+{
+	switch (state)
+	{
+		/* --- the following bits of info are returned as nullptr-terminated strings --- */
+//		case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "PSX CPU"); break;
+
+		default:
+			mips_get_info(state, info);
+			break;
+	}
+}
+#endif
diff --git a/src/psf/psx_hw.c b/src/psf/psx_hw.c
deleted file mode 100644
index 9fdfd6d1b47a..000000000000
--- a/src/psf/psx_hw.c
+++ /dev/null
@@ -1,3543 +0,0 @@
-/*
-	Audio Overload SDK - PSX and IOP hardware emulation
-
-	Copyright (c) 2007 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
-    psx_hw.c - Minimal PSX/IOP hardware glue/emulation/whatever
-
-    supported: main RAM (2 MB, mirrored to fill an 8 MB space like on real HW)
-               DMA channel 4 (SPURAM) in both directions (including completion IRQ)
-	       VBL IRQ
-	       Root counters 2 and 3 including completion events and IRQs
-	       Some BIOS services including exception handling (via HLE)
-	       HLE emulation of IOP operating system, including multithreading
-	       SPU(2), SPU(2)RAM (via PEOpS)
-
-
-
-    Special notes:
-    PSF1
-    	- Chocobo's Dungeon 2 contains an illegal code sequence (patched)
-
-    PSF2
-	- Shadow Hearts assumes that the wave buffer alloc will go to 0x80060000 and the sequence buffer to 0x80170000.
-	  Our memory management doesn't work out that way, so we have to (wait for it) cheese it.
-*/
-
-#include <stdio.h>
-#include <glib.h>
-
-#include "ao.h"
-#include "cpuintrf.h"
-#include "psx.h"
-
-#define DEBUG_HLE_BIOS	(0)		// debug PS1 HLE BIOS
-#define DEBUG_SPU	(0)		// debug PS1 SPU read/write
-#define DEBUG_SPU2	(0)		// debug PS2 SPU read/write
-#define DEBUG_HLE_IOP	(0)		// debug PS2 IOP OS calls
-#define DEBUG_UNK_RW	(0)		// debug unknown reads/writes
-#define DEBUG_THREADING (0)		// debug PS2 IOP threading
-
-#define LE32(x) GUINT32_FROM_LE(x)
-
-extern void mips_get_info(uint32_t state, union cpuinfo *info);
-extern void mips_set_info(uint32_t state, union cpuinfo *info);
-extern int psxcpu_verbose;
-extern uint16_t SPUreadRegister(uint32_t reg);
-extern void SPUwriteRegister(uint32_t reg, uint16_t val);
-extern void SPUwriteDMAMem(uint32_t usPSXMem,int iSize);
-extern void SPUreadDMAMem(uint32_t usPSXMem,int iSize);
-extern void mips_shorten_frame(void);
-extern int mips_execute( int cycles );
-extern uint32_t psf2_load_file(char *file, uint8_t *buf, uint32_t buflen);
-extern uint32_t psf2_load_elf(uint8_t *start, uint32_t len);
-void psx_hw_runcounters(void);
-int mips_get_icount(void);
-void mips_set_icount(int count);
-
-extern int psf_refresh;
-
-// SPU2
-extern void SPU2write(unsigned long reg, unsigned short val);
-extern unsigned short SPU2read(unsigned long reg);
-extern void SPU2readDMA4Mem(uint32_t usPSXMem,int iSize);
-extern void SPU2writeDMA4Mem(uint32_t usPSXMem,int iSize);
-extern void SPU2readDMA7Mem(uint32_t usPSXMem,int iSize);
-extern void SPU2writeDMA7Mem(uint32_t usPSXMem,int iSize);
-extern void SPU2interruptDMA4(void);
-extern void SPU2interruptDMA7(void);
-
-#define MAX_FILE_SLOTS	(32)
-
-static volatile int softcall_target = 0;
-static int filestat[MAX_FILE_SLOTS];
-static uint8_t *filedata[MAX_FILE_SLOTS];
-static uint32_t filesize[MAX_FILE_SLOTS], filepos[MAX_FILE_SLOTS];
-uint32_t psf2_get_loadaddr(void);
-void psf2_set_loadaddr(uint32_t new);
-static void call_irq_routine(uint32_t routine, uint32_t parameter);
-static int intr_susp = 0;
-
-static uint64_t sys_time;
-static int timerexp = 0;
-
-typedef struct
-{
-	char name[10];
-	uint32_t dispatch;
-} ExternLibEntries;
-
-static int32_t iNumLibs;
-static ExternLibEntries	reglibs[32];
-
-typedef struct
-{
-	uint32_t type;
-	uint32_t value;
-	uint32_t param;
-	int    inUse;
-} EventFlag;
-
-static int32_t iNumFlags;
-static EventFlag evflags[32];
-
-typedef struct
-{
-	uint32_t attr;
-	uint32_t option;
-	int32_t init;
-	int32_t current;
-	int32_t max;
-	int32_t threadsWaiting;
-	int32_t inuse;
-} Semaphore;
-
-#define SEMA_MAX	(64)
-
-static int32_t iNumSema;
-static Semaphore semaphores[SEMA_MAX];
-
-// thread states
-enum
-{
-	TS_RUNNING = 0,		// now running
-	TS_READY,		// ready to run
-	TS_WAITEVFLAG,		// waiting on an event flag
-	TS_WAITSEMA,		// waiting on a semaphore
-	TS_WAITDELAY,		// waiting on a time delay
-	TS_SLEEPING,		// sleeping
-	TS_CREATED,		// newly created, hasn't run yet
-
-	TS_MAXSTATE
-};
-
-typedef struct
-{
-	int32_t  iState;		// state of thread
-
-	uint32_t flags;		// flags
-	uint32_t routine;		// start of code for the thread
-	uint32_t stackloc;	// stack location in IOP RAM
-	uint32_t stacksize;	// stack size
-	uint32_t refCon;		// user value passed in at CreateThread time
-
-	uint32_t waitparm;	// what we're waiting on if in one the TS_WAIT* states
-
-	uint32_t save_regs[37];	// CPU registers belonging to this thread
-} Thread;
-
-static int32_t iNumThreads, iCurThread;
-static Thread threads[32];
-
-#if DEBUG_THREADING
-static char *_ThreadStateNames[TS_MAXSTATE] = { "RUNNING", "READY", "WAITEVFLAG", "WAITSEMA", "WAITDELAY", "SLEEPING", "CREATED" };
-#endif
-
-#if DEBUG_HLE_IOP
-static char *seek_types[3] = { "SEEK_SET", "SEEK_CUR", "SEEK_END" };
-#endif
-
-typedef struct
-{
-	int32_t  iActive;
-	uint32_t count;
-	uint32_t target;
-	uint32_t source;
-	uint32_t prescale;
-	uint32_t handler;
-	uint32_t hparam;
-	uint32_t mode;
-} IOPTimer;
-
-static IOPTimer iop_timers[8];
-static int32_t iNumTimers;
-
-typedef struct
-{
-	uint32_t count;
-	uint32_t mode;
-	uint32_t target;
-	uint32_t sysclock;
-	uint32_t interrupt;
-} Counter;
-
-static Counter root_cnts[4];	// 4 of the bastards
-
-#define CLOCK_DIV	(8)	// 33 MHz / this = what we run the R3000 at to keep the CPU usage not insane
-
-// counter modes
-#define RC_EN		(0x0001)	// halt
-#define RC_RESET	(0x0008)	// automatically wrap
-#define RC_IQ1		(0x0010)	// IRQ when target reached
-#define RC_IQ2		(0x0040)	// IRQ when target reached (pSX treats same as IQ1?)
-#define RC_CLC		(0x0100)	// counter uses direct system clock
-#define RC_DIV8		(0x0200)	// (counter 2 only) system clock/8
-
-typedef struct
-{
-	uint32_t desc;
-	int32_t status;
-	int32_t mode;
-	uint32_t fhandler;
-} EvtCtrlBlk[32];
-
-static EvtCtrlBlk *Event;
-static EvtCtrlBlk *CounterEvent;
-
-// Sony event states
-#define EvStUNUSED	0x0000
-#define EvStWAIT	0x1000
-#define EvStACTIVE	0x2000
-#define EvStALREADY 	0x4000
-
-// Sony event modes
-#define EvMdINTR	0x1000
-#define EvMdNOINTR	0x2000
-
-// PSX main RAM
-uint32_t psx_ram[(2*1024*1024)/4];
-uint32_t psx_scratch[0x400];
-// backup image to restart songs
-uint32_t initial_ram[(2*1024*1024)/4];
-uint32_t initial_scratch[0x400];
-
-static uint32_t spu_delay, dma_icr, irq_data, irq_mask, dma_timer, WAI;
-static uint32_t dma4_madr, dma4_bcr, dma4_chcr, dma4_delay;
-static uint32_t dma7_madr, dma7_bcr, dma7_chcr, dma7_delay;
-static uint32_t dma4_cb, dma7_cb, dma4_fval, dma4_flag, dma7_fval, dma7_flag;
-static uint32_t irq9_cb, irq9_fval, irq9_flag;
-
-// take a snapshot of the CPU state for a thread
-static void FreezeThread(int32_t iThread, int flag)
-{
-	int i;
-	union cpuinfo mipsinfo;
-
-	#if DEBUG_THREADING
-//	printf("IOP: FreezeThread(%d)\n", iThread);
-	#endif
-
-	for (i = 0; i < 32; i++)
-	{
-		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
-		threads[iThread].save_regs[i] = mipsinfo.i;
-	}
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-	threads[iThread].save_regs[32] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-	threads[iThread].save_regs[33] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
-	threads[iThread].save_regs[35] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
-	threads[iThread].save_regs[36] = mipsinfo.i;
-
-
-	// if a thread is freezing itself due to a IOP syscall, we must save the RA as the PC
-	// to come back to or else the syscall will recurse
-	if (flag)
-	{
-		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-	}
-	else
-	{
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-	}
-	threads[iThread].save_regs[34] = mipsinfo.i;
-
-	#if DEBUG_THREADING
-	{
-		char buffer[256];
-
-		DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]);
-
-		printf("IOP: FreezeThread(%d) => %08x  [%s]\n", iThread, threads[iThread].save_regs[34], buffer);
-	}
-	#endif
-
-	// if thread was running, now it's ready
-	if (threads[iThread].iState == TS_RUNNING)
-	{
-		threads[iThread].iState = TS_READY;
-	}
-}
-
-// restore the CPU state from a thread's snapshot
-static void ThawThread(int32_t iThread)
-{
-	int i;
-	union cpuinfo mipsinfo;
-
-	// the first time a thread is put on the CPU,
-	// some special setup is required
-	if (threads[iThread].iState == TS_CREATED)
-	{
-		// PC = starting routine
-		threads[iThread].save_regs[34] = threads[iThread].routine-4;	// compensate for weird delay slot effects
-		// SP = thread's stack area
-		threads[iThread].save_regs[29] = (threads[iThread].stackloc + threads[iThread].stacksize) - 16;
-		threads[iThread].save_regs[29] |= 0x80000000;
-
-		threads[iThread].save_regs[35] = threads[iThread].save_regs[36] = 0;
-
-		#if DEBUG_THREADING
-//		printf("IOP: Initial setup for thread %d => PC %x SP %x\n", iThread, threads[iThread].save_regs[34]+4, threads[iThread].save_regs[29]);
-		#endif
-	}
-
-	#if DEBUG_THREADING
-	{
-		char buffer[256];
-
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-		DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]);
-
-		printf("IOP: ThawThread(%d) => %08x  [%s] (wake %d)\n", iThread, threads[iThread].save_regs[34], buffer, wakecount);
-	}
-	#endif
-
-	for (i = 0; i < 32; i++)
-	{
-		mipsinfo.i = threads[iThread].save_regs[i];
-		mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
-	}
-
-	mipsinfo.i = threads[iThread].save_regs[32];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-	mipsinfo.i = threads[iThread].save_regs[33];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-	mipsinfo.i = threads[iThread].save_regs[34];
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-	mipsinfo.i = threads[iThread].save_regs[35];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
-	mipsinfo.i = threads[iThread].save_regs[36];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
-
-	threads[iThread].iState = TS_RUNNING;
-}
-
-// find a new thread to run
-static void ps2_reschedule(void)
-{
-	int i, starti, iNextThread;
-
-	iNextThread = -1;
-
-	// see if any thread other than the current one is ready to run
-	i = iCurThread+1;
-	if (i >= iNumThreads)
-	{
-		i = 0;
-	}
-
-	starti = i;
-
-	// starting with the next thread after this one,
-	// see who wants to run
-	while (i < iNumThreads)
-	{
-		if (i != iCurThread)
-		{
-			if (threads[i].iState == TS_READY)
-			{
-			  	iNextThread = i;
-				break;
-			}
-		}
-
-		i++;
-	}
-
-	// if we started above thread 0 and didn't pick one,
-	// go around and try from zero
-	if ((starti > 0) && (iNextThread == -1))
-	{
-		for (i = 0; i < iNumThreads; i++)
-		{
-			if (i != iCurThread)
-			{
-				if (threads[i].iState == TS_READY)
-				{
-				  	iNextThread = i;
-					break;
-				}
-			}
-		}
-	}
-
-	if (iNextThread != -1)
-	{
-		#if DEBUG_THREADING
-		for (i = 0; i < iNumThreads; i++)
-		{
-			printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]);
-		}
-		#endif
-
-		if (iCurThread != -1)
-		{
-			FreezeThread(iCurThread, 0);
-		}
-		ThawThread(iNextThread);
-		iCurThread = iNextThread;
-		threads[iCurThread].iState = TS_RUNNING;
-	}
-	else
-	{
-		// no thread to switch to, is the current one still running?
-		if (iCurThread != -1)
-		{
-			if (threads[iCurThread].iState != TS_RUNNING)
-			{
-				#if DEBUG_THREADING
-				printf("IOP: no threads to run\n");
-
-				for (i = 0; i < iNumThreads; i++)
-				{
-					printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]);
-				}
-				#endif
-
-				mips_shorten_frame();	// kill the CPU
-				iCurThread = -1;	// no threads are active
-			}
-		}
-		else
-		{
-			mips_shorten_frame();	// kill the CPU
-			iCurThread = -1;	// no threads are active
-		}
-	}
-}
-
-static void psx_irq_update(void)
-{
-	union cpuinfo mipsinfo;
-
-	if ((irq_data & irq_mask) != 0)
-	{	// assert the line
-		WAI = 0;
-		mipsinfo.i = ASSERT_LINE;
-		mips_set_info( CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo );
-	}
-	else
-	{
-		// clear the line
-		mipsinfo.i = CLEAR_LINE;
-		mips_set_info( CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo );
-	}
-}
-
-void psx_irq_set(uint32_t irq)
-{
-	irq_data |= irq;
-
-	psx_irq_update();
-}
-
-static uint32_t gpu_stat = 0;
-
-uint32_t psx_hw_read(offs_t offset, uint32_t mem_mask)
-{
-	if (offset >= 0x00000000 && offset <= 0x007fffff)
-	{
-		offset &= 0x1fffff;
-		return LE32(psx_ram[offset>>2]);
-	}
-
-	if (offset >= 0x80000000 && offset <= 0x807fffff)
-	{
-		offset &= 0x1fffff;
-		return LE32(psx_ram[offset>>2]);
-	}
-
-	if (offset == 0xbfc00180 || offset == 0xbfc00184)	// exception vector
-	{
-		return FUNCT_HLECALL;
-	}
-
-	if (offset == 0x1f801014)
-	{
-		return spu_delay;
-	}
-
-	if (offset == 0xbf801014)
-	{
-		return spu_delay;
-	}
-
-	if (offset == 0x1f801814)
-	{
-		gpu_stat ^= 0xffffffff;
-		return gpu_stat;
-	}
-
-	if (offset >= 0x1f801c00 && offset <= 0x1f801dff)
-	{
-		if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00))
-		{
-			#if DEBUG_SPU
-			printf("SPU: readRegister(%x)\n", offset);
-			#endif
-			return SPUreadRegister(offset) & ~mem_mask;
-		}
-		else if (mem_mask == 0x0000ffff)
-		{
-			#if DEBUG_SPU
-			printf("SPU: readRegister(%x)\n", offset);
-			#endif
-			return SPUreadRegister(offset)<<16;
-		}
-		else printf("SPU: read unknown mask %08x\n", mem_mask);
-	}
-
-	if (offset >= 0xbf900000 && offset <= 0xbf9007ff)
-	{
-		if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00))
-		{
-			return SPU2read(offset) & ~mem_mask;
-		}
-		else if (mem_mask == 0x0000ffff)
-		{
-			return SPU2read(offset)<<16;
-		}
-		else if (mem_mask == 0)
-		{
-			return SPU2read(offset) | SPU2read(offset+2)<<16;
-		}
-		else printf("SPU2: read unknown mask %08x\n", mem_mask);
-	}
-
-	if (offset >= 0x1f801100 && offset <= 0x1f801128)
-	{
-		int cnt = (offset>>4) & 0xf;
-
-		switch (offset & 0xf)
-		{
-			case 0:
-//				printf("RC: read counter %d count = %x\n", cnt, root_cnts[cnt].count);
-				return root_cnts[cnt].count;
-				break;
-			case 4:
-//				printf("RC: read counter %d mode\n", cnt);
-				return root_cnts[cnt].mode;
-				break;
-			case 8:
-//				printf("RC: read counter %d target\n", cnt);
-				return root_cnts[cnt].target;
-				break;
-		}
-
-		return 0;
-	}
-
-	if (offset == 0x1f8010f4)
-	{
-		return dma_icr;
-	}
-	else if (offset == 0x1f801070)
-	{
-//		printf("Read IRQ_data %x (mask %08x)\n", irq_data, mem_mask);
-		return irq_data;
-	}
-	else if (offset == 0x1f801074)
-	{
-		return irq_mask;
-	}
-
-/*	if (offset == 0xbf801508)
-	{
-		return dma7_bcr;
-	}*/
-
-	if (offset == 0xbf920344)
-	{
-		return 0x80808080;
-	}
-
-	#if DEBUG_UNK_RW
-	{
-		union cpuinfo mipsinfo;
-
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-		printf("Unknown read: %08x, mask %08x (PC=%x)\n", offset&~3, mem_mask, mipsinfo.i);
-	}
-	#endif
-	return 0;
-}
-
-static void psx_dma4(uint32_t madr, uint32_t bcr, uint32_t chcr)
-{
-	if (chcr == 0x01000201)	// cpu to SPU
-	{
-		#if DEBUG_SPU
-		printf("DMA4: RAM %08x to SPU\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 2;
-		SPUwriteDMAMem(madr&0x1fffff, bcr);
-	}
-	else
-	{
-		#if DEBUG_SPU
-		printf("DMA4: SPU to RAM %08x\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 2;
-		SPUreadDMAMem(madr&0x1fffff, bcr);
-	}
-}
-
-static void ps2_dma4(uint32_t madr, uint32_t bcr, uint32_t chcr)
-{
-	if (chcr == 0x01000201)	// cpu to SPU2
-	{
-		#if DEBUG_HLE_IOP
-		printf("DMA4: RAM %08x to SPU2\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
-		SPU2writeDMA4Mem(madr&0x1fffff, bcr);
-	}
-	else
-	{
-		#if DEBUG_HLE_IOP
-		printf("DMA4: SPU2 to RAM %08x\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
-		SPU2readDMA4Mem(madr&0x1fffff, bcr);
-	}
-
-	dma4_delay = 80;
-}
-
-static void ps2_dma7(uint32_t madr, uint32_t bcr, uint32_t chcr)
-{
-	if ((chcr == 0x01000201) || (chcr == 0x00100010) || (chcr == 0x000f0010) || (chcr == 0x00010010))	// cpu to SPU2
-	{
-		#if DEBUG_HLE_IOP
-		printf("DMA7: RAM %08x to SPU2\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
-		SPU2writeDMA7Mem(madr&0x1fffff, bcr);
-	}
-	else
-	{
-		#if DEBUG_HLE_IOP
-		printf("DMA7: SPU2 to RAM %08x\n", madr);
-		#endif
-		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
-//		SPU2readDMA7Mem(madr&0x1fffff, bcr);
-	}
-
-	dma7_delay = 80;
-}
-
-void psx_hw_write(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
-	union cpuinfo mipsinfo;
-
-	if (offset >= 0x00000000 && offset <= 0x007fffff)
-	{
-		offset &= 0x1fffff;
-//		if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset);
-
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-
-		psx_ram[offset>>2] &= LE32(mem_mask);
-		psx_ram[offset>>2] |= LE32(data);
-		return;
-	}
-
-	if (offset >= 0x80000000 && offset <= 0x807fffff)
-	{
-		offset &= 0x1fffff;
-//		if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset);
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-		psx_ram[offset>>2] &= LE32(mem_mask);
-		psx_ram[offset>>2] |= LE32(data);
-		return;
-	}
-
-	if (offset == 0x1f801014 || offset == 0xbf801014)
-	{
-		spu_delay &= mem_mask;
-		spu_delay |= data;
-		return;
-	}
-
-	if (offset >= 0x1f801c00 && offset <= 0x1f801dff)
-	{
-		if (mem_mask == 0xffff0000)
-		{
-			SPUwriteRegister(offset, data);
-			return;
-		}
-		else if (mem_mask == 0x0000ffff)
-		{
-			SPUwriteRegister(offset, data>>16);
-			return;
-		}
-		else printf("SPU: write unknown mask %08x\n", mem_mask);
-	}
-
-	if (offset >= 0xbf900000 && offset <= 0xbf9007ff)
-	{
-		if (mem_mask == 0xffff0000)
-		{
-			SPU2write(offset, data);
-			return;
-		}
-		else if (mem_mask == 0x0000ffff)
-		{
-			SPU2write(offset, data>>16);
-			return;
-		}
-		else if (mem_mask == 0)
-		{
-			SPU2write(offset, data & 0xffff);
-			SPU2write(offset+2, data>>16);
-			return;
-		}
-		else printf("SPU2: write unknown mask %08x\n", mem_mask);
-	}
-
-	if (offset >= 0x1f801100 && offset <= 0x1f801128)
-	{
-		int cnt = (offset>>4) & 0xf;
-
-		switch (offset & 0xf)
-		{
-			case 0:
-				root_cnts[cnt].count = data;
-//				printf("RC: counter %d count = %x\n", cnt, data);
-				break;
-			case 4:
-				root_cnts[cnt].mode = data;
-//				printf("RC: counter %d mode = %x\n", cnt, data);
-				break;
-			case 8:
-				root_cnts[cnt].target = data;
-//				printf("RC: counter %d target = %x\n", cnt, data);
-				break;
-		}
-
-		return;
-	}
-
-	// DMA4
-	if (offset == 0x1f8010c0)
-	{
-		dma4_madr = data;
-		return;
-	}
-	else if (offset == 0x1f8010c4)
-	{
-		dma4_bcr = data;
-		return;
-	}
-	else if (offset == 0x1f8010c8)
-	{
-		dma4_chcr = data;
-		psx_dma4(dma4_madr, dma4_bcr, dma4_chcr);
-
-		if (dma_icr & (1 << (16+4)))
-		{
-			dma_timer = 3;
-		}
-		return;
-	}
-	else if (offset == 0x1f8010f4)
-	{
-		dma_icr = ( dma_icr & mem_mask ) |
-			  ( ~mem_mask & 0x80000000 & dma_icr) |
-			  ( ~data & ~mem_mask & 0x7f000000 & dma_icr) |
-			  ( data & ~mem_mask & 0x00ffffff);
-
-		if ((dma_icr & 0x7f000000) != 0)
-		{
-			dma_icr &= ~0x80000000;
-		}
-
-		return;
-	}
-	else if (offset == 0x1f801070)
-	{
-		irq_data = (irq_data & mem_mask) | (irq_data & irq_mask & data);
-		psx_irq_update();
-		return;
-	}
-	else if (offset == 0x1f801074)
-	{
-		irq_mask &= mem_mask;
-		irq_mask |= data;
-		psx_irq_update();
-		return;
-	}
-
-	// PS2 DMA4
-	if (offset == 0xbf8010c0)
-	{
-		dma4_madr = data;
-		return;
-	}
-	else if (offset == 0xbf8010c8)
-	{
-		dma4_chcr = data;
-		ps2_dma4(dma4_madr, dma4_bcr, dma4_chcr);
-
-		if (dma_icr & (1 << (16+4)))
-		{
-			dma_timer = 3;
-		}
-		return;
-	}
-
-	if (offset == 0xbf8010c4 || offset == 0xbf8010c6)
-	{
-		dma4_bcr &= mem_mask;
-		dma4_bcr |= data;
-		return;
-	}
-
-	// PS2 DMA7
-	if (offset == 0xbf801500)
-	{
-		dma7_madr = data;
-		return;
-	}
-	else if (offset == 0xbf801504)
-	{
-		dma7_chcr = data;
-		ps2_dma7(dma7_madr, dma7_bcr, dma7_chcr);
-		return;
-	}
-
-	if (offset == 0xbf801508 || offset == 0xbf80150a)
-	{
-		dma7_bcr &= mem_mask;
-		dma7_bcr |= data;
-		return;
-	}
-
-	#if DEBUG_UNK_RW
-	{
-		union cpuinfo mipsinfo;
-
-		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-		printf("Unknown write: %08x to %08x, mask %08x (PC=%x)\n", data, offset&~3, mem_mask, mipsinfo.i);
-	}
-	#endif
-}
-
-// called per sample, 1/44100th of a second (768 clock cycles)
-void psx_hw_slice(void)
-{
-	psx_hw_runcounters();
-
-	if (!WAI)
-		mips_execute(768/CLOCK_DIV);
-
-	if (dma_timer)
-	{
-		dma_timer--;
-		if (dma_timer == 0)
-		{
-			dma_icr |= (1 << (24+4));
-			psx_irq_set(0x0008);
-		}
-	}
-}
-
-void ps2_hw_slice(void)
-{
-	int i = 0;
-
-	timerexp = 0;
-	psx_hw_runcounters();
-
-	if (iCurThread != -1)
-	{
-		mips_execute(836/CLOCK_DIV);
-	}
-	else	// no thread, don't run CPU, just update counters
-	{
-		if (timerexp)
-		{
-			ps2_reschedule();
-
-			if (iCurThread != -1)
-			{
-				mips_execute((836/CLOCK_DIV)-i);
-				i = (836/CLOCK_DIV);
-			}
-		}
-	}
-}
-
-static int fcnt = 0;
-
-void psx_hw_frame(void)
-{
-	if (psf_refresh == 50)
-	{
-		fcnt++;;
-
-		if (fcnt < 6)
-		{
-			psx_irq_set(1);
-		}
-		else
-		{
-			fcnt = 0;
-		}
-	}
-	else	// NTSC
-	{
-		psx_irq_set(1);
-	}
-}
-
-void ps2_hw_frame(void)
-{
-	ps2_reschedule();
-}
-
-// BIOS HLE
-
-// heap block struct offsets
-enum
-{
-	BLK_STAT = 0,
-	BLK_SIZE = 4,
-	BLK_FD = 8,
-	BLK_BK = 12
-};
-
-static uint32_t heap_addr, entry_int = 0;
-
-extern uint32_t mips_get_cause(void);
-extern uint32_t mips_get_status(void);
-extern void mips_set_status(uint32_t status);
-extern uint32_t mips_get_ePC(void);
-
-static uint32_t irq_regs[37];
-
-static int irq_mutex = 0;
-
-static void call_irq_routine(uint32_t routine, uint32_t parameter)
-{
-	int j, oldICount;
-	union cpuinfo mipsinfo;
-
-	if (!irq_mutex)
-	{
-		irq_mutex = 1;
-	}
-	else
-	{
-		printf("IOP: ERROR!  IRQ reentry!\n");
-		return;
-	}
-
-	// save regs for IRQ
-	for (j = 0; j < 32; j++)
-	{
-		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo);
-		irq_regs[j] = mipsinfo.i;
-	}
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-	irq_regs[32] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-	irq_regs[33] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_PC, &mipsinfo);
-	irq_regs[34] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
-	irq_regs[35] = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
-	irq_regs[36] = mipsinfo.i;
-
-	// PC = timer handler routine
-	mipsinfo.i = routine;
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-	// parameter in a0
-	mipsinfo.i = parameter;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-
-	// RA = a trap address we can set
-	mipsinfo.i = 0x80001000;
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-
-	// make sure we're set
-	psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
-
-	softcall_target = 0;
-	oldICount = mips_get_icount();
-	while (!softcall_target)
-	{
-		mips_execute(10);
-	}
-	mips_set_icount(oldICount);
-
-	// restore IRQ regs
-	for (j = 0; j < 32; j++)
-	{
-		mipsinfo.i = irq_regs[j];
-		mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo);
-	}
-
-	mipsinfo.i = irq_regs[32];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-	mipsinfo.i = irq_regs[33];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-	mipsinfo.i = irq_regs[34];
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-	mipsinfo.i = irq_regs[35];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
-	mipsinfo.i = irq_regs[36];
-	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
-
-	irq_mutex = 0;
-}
-
-void psx_bios_exception(uint32_t pc)
-{
-	uint32_t a0, status;
-	union cpuinfo mipsinfo;
-	int i, oldICount;
-
-//	printf("bios_exception: cause %x\n", mips_get_cause() & 0x3c);
-
-	// get a0
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-	a0 = mipsinfo.i;
-
-	switch (mips_get_cause() & 0x3c)
-	{
-		case 0:	// IRQ
-//			printf("IRQ: %x, mask %x\n", irq_data, irq_mask);
-			// save all regs
-			for (i = 0; i < 32; i++)
-			{
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
-				irq_regs[i] = mipsinfo.i;
-			}
-			mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-			irq_regs[32] = mipsinfo.i;
-			mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-			irq_regs[33] = mipsinfo.i;
-
-			// check BIOS-driven interrupts
-			if (irq_data & 1)	// VSync
-			{
-				if (CounterEvent[3][1].status == LE32(EvStACTIVE))
-				{
-					// run the handler
-					mipsinfo.i = LE32(CounterEvent[3][1].fhandler);
-//	       				printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC());
-//	       				printf("VBL running handler @ %x\n", mipsinfo.i);
-					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-					mipsinfo.i = 0x80001000;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-
-					// make sure we're set
-					psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
-
-					softcall_target = 0;
-					oldICount = mips_get_icount();
-					while (!softcall_target)
-					{
-						mips_execute(10);
-					}
-					mips_set_icount(oldICount);
-
-//	       				printf("Exiting softcall handler\n");
-
-					irq_data &= ~1;		// clear the VBL IRQ if we handled it
-				}
-			}
-			else if (irq_data & 0x70)	// root counters
-			{
-				for (i = 0; i < 4; i++)
-				{
-					if (irq_data & (1 << (i+4)))
-					{
-						if (CounterEvent[i][1].status == LE32(EvStACTIVE))
-						{
-							// run the handler
-							mipsinfo.i = LE32(CounterEvent[i][1].fhandler);
-//							printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC());
-//							printf("Counter %d running handler @ %x\n", i, mipsinfo.i);
-							mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-							mipsinfo.i = 0x80001000;
-							mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-
-							// make sure we're set
-							psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
-
-							softcall_target = 0;
-							oldICount = mips_get_icount();
-							while (!softcall_target)
-							{
-								mips_execute(10);
-							}
-							mips_set_icount(oldICount);
-
-//							printf("Exiting softcall handler\n");
-							irq_data &= ~(1 << (i+4));
-						}
-						else
-						{
-//							printf("CEvt %d not active\n", i);
-						}
-					}
-				}
-			}
-
-			if (entry_int)
-			{
-				psx_hw_write(0x1f801070, 0xffffffff, 0);
-
-				a0 = entry_int;
-
-//				printf("taking entry_int\n");
-
-				// RA (and PC)
-				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+0)/4]);
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-				// SP
-				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+4)/4]);
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
-				// FP
-				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+8)/4]);
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
-
-				// S0-S7 are next
-				for (i = 0; i < 8; i++)
-				{
-					mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+12+(i*4))/4]);
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo);
-				}
-
-				// GP
-				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+44)/4]);
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
-
-				// v0 = 1
-				mipsinfo.i = 1;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-			}
-			else
-			{
-				psx_hw_write(0x1f801070, 0, 0xffff0000);
-
-				// note: the entry_int won't be bailing us out here, so do it ourselves
-				for (i = 0; i < 32; i++)
-				{
-					mipsinfo.i = irq_regs[i];
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
-				}
-
-				mipsinfo.i = irq_regs[32];
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-				mipsinfo.i = irq_regs[33];
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-				mipsinfo.i = mips_get_ePC();
-				mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-				status = mips_get_status();
-				status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
-				mips_set_status(status);
-			}
-			break;
-
-		case 0x20:	// syscall
-			// syscall always farks with the status, so get it now
-			status = mips_get_status();
-
-			switch (a0)
-			{
-				case 1: // EnterCritical
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: EnterCritical\n");
-					#endif
-					status &= ~0x0404;
-					break;
-
-				case 2:	// ExitCritical
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: ExitCritical\n");
-					#endif
-					status |= 0x0404;
-					break;
-
-				default:
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: Unknown syscall %x\n", a0);
-					#endif
-					break;
-			}
-
-			// PC = ePC + 4
-			mipsinfo.i = mips_get_ePC() + 4;
-			mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-			// and update the status accordingly
-			status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
-			mips_set_status(status);
-			break;
-
-		default:
-			#if DEBUG_HLE_BIOS
-			printf("HLEBIOS: Unknown exception %x\n", mips_get_cause());
-			#endif
-			break;
-	}
-}
-
-static uint32_t calc_ev(uint32_t a0)
-{
-	uint32_t ev;
-
-	ev = (a0 >> 24) & 0xf;
-	if (ev == 0xf)
-	{
-		ev = 0x5;
-	}
-	ev *= 32;
-	ev += (a0 & 0x1f);
-
-	return ev;
-}
-
-static uint32_t calc_spec(uint32_t a1)
-{
-	uint32_t spec = 0;
-	int i;
-
-	if (a1 == 0x301)
-	{
-		spec = 16;
-	}
-	else if (a1 == 0x302)
-	{
-		spec = 17;
-	}
-	else
-	{
-		for (i = 0; i < 16; i++)
-		{
-			if (a1 & (1<<i))
-			{
-				spec = i;
-				break;
-			}
-		}
-	}
-
-	return spec;
-}
-
-void psx_hw_init(void)
-{
-	timerexp = 0;
-
-	memset(filestat, 0, sizeof(filestat));
-	memset(filedata, 0, sizeof(filedata));
-
-	dma4_cb = dma7_cb = 0;
-
-	sys_time = 0;
-
-	// clear registered libraries table
-	memset(reglibs, 0, sizeof(reglibs));
-	iNumLibs = 0;
-
-	memset(evflags, 0, sizeof(evflags));
-	iNumFlags = 0;
-
-	memset(threads, 0, sizeof(threads));
-	iNumThreads = 1;	// we always have at least one thread
-
-	memset(semaphores, 0, sizeof(semaphores));
-	iNumSema = 0;
-
-	// set the initial thread to "RUNNING"
-	threads[0].iState = TS_RUNNING;
-	iCurThread = 0;
-
-	memset(iop_timers, 0, sizeof(iop_timers));
-	iNumTimers = 0;
-
-	// set PS1 BIOS HLE breakpoints
-	psx_ram[0xa0/4] = LE32(FUNCT_HLECALL);
-	psx_ram[0xb0/4] = LE32(FUNCT_HLECALL);
-	psx_ram[0xc0/4] = LE32(FUNCT_HLECALL);
-
-	Event = (EvtCtrlBlk *)&psx_ram[0x1000/4];
-	CounterEvent = (Event + (32*2));
-
-	dma_icr = 0;
-	spu_delay = 0;
-	irq_data = 0;
-	irq_mask = 0;
-	softcall_target = 0;
-	gpu_stat = 0;
-	dma4_madr = dma4_bcr = dma4_chcr = 0;
-	heap_addr = 0;
-	entry_int = 0;
-
-	WAI = 0;
-
-	root_cnts[0].mode = RC_EN;
-	root_cnts[1].mode = RC_EN;
-	root_cnts[2].mode = RC_EN;
-	root_cnts[0].sysclock = 0;
-	root_cnts[1].sysclock = 0;
-	root_cnts[2].sysclock = 0;
-
-	root_cnts[3].mode = (RC_RESET | RC_IQ1 | RC_IQ2);
-	root_cnts[3].sysclock = 0;
-	root_cnts[3].target = 1;
-	root_cnts[3].interrupt = 1;
-}
-
-void psx_bios_hle(uint32_t pc)
-{
-	uint32_t subcall, status;
-	union cpuinfo mipsinfo;
-	uint32_t a0, a1, a2, a3;
-	int i;
-
-	if ((pc == 0) || (pc == 0x80000000))  	 	// IOP "null" state
-	{
-		#if DEBUG_HLE_IOP
-		printf("IOP 'null' state\n");
-		#endif
-//		ao_song_done = 1;
-		return;
-	}
-
-	if (pc == 0xbfc00180 || pc == 0xbfc00184)	// exception, not BIOS call
-	{
-		psx_bios_exception(pc);
-		return;
-	}
-
-	if (pc == 0x80001000)
-	{
-//		printf("hit softcall target\n");
-		softcall_target = 1;
-		return;
-	}
-
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R9, &mipsinfo);
-
-	subcall = mipsinfo.i & 0xff;
-
-	// most calls have a0/a1 as parameters, so prefetch them
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-	a0 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
-	a1 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo);
-	a2 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo);
-	a3 = mipsinfo.i;
-
-//	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-//	printf("HLEBIOS: return is %08x\n", mipsinfo.i);
-
-	switch (pc)
-	{
-		case 0xa0:	// a0 syscalls
-			switch (subcall)
-			{
-				case 0x13:	// setjmp
-					// RA
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					psx_ram[((a0&0x1fffff)+0)/4] = LE32(mipsinfo.i);
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: setjmp(%08x) => PC %08x\n", a0, mipsinfo.i);
-					#endif
-					// SP
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
-					psx_ram[((a0&0x1fffff)+4)/4] = LE32(mipsinfo.i);
-					// FP
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
-					psx_ram[((a0&0x1fffff)+8)/4] = LE32(mipsinfo.i);
-
-					// S0-S7 are next
-					for (i = 0; i < 8; i++)
-					{
-						mips_get_info(CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo);
-						psx_ram[((a0&0x1fffff)+12+(i*4))/4] = LE32(mipsinfo.i);
-					}
-
-					// GP
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
-					psx_ram[((a0&0x1fffff)+44)/4] = LE32(mipsinfo.i);
-
-					// v0 = 0
-					mipsinfo.i = 0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					break;
-
-				case 0x18:	// strncmp
-					{
-						uint8_t *dst, *src;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: strncmp(%08x, %08x, %d)\n", a0, a1, a2);
-						#endif
-
-						dst = (uint8_t *)psx_ram;
-						src = (uint8_t *)psx_ram;
-						dst += (a0 & 0x1fffff);
-						src += (a1 & 0x1fffff);
-
-						// v0 = result
-						mipsinfo.i = strncmp((char *)dst, (char *)src, a2);
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x19:	// strcpy
-					{
-						uint8_t *dst, *src;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: strcpy(%08x, %08x)\n", a0, a1);
-						#endif
-
-						dst = (uint8_t *)psx_ram;
-						src = (uint8_t *)psx_ram;
-						dst += (a0 & 0x1fffff);
-						src += (a1 & 0x1fffff);
-
-						while (*src)
-						{
-							*dst = *src;
-							dst++;
-							src++;
-						}
-
-						// v0 = a0
-						mipsinfo.i = a0;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x28:	// bzero
-					{
-						uint8_t *dst;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: bzero(%08x, %08x)\n", a0, a1);
-						#endif
-
-						dst = (uint8_t *)psx_ram;
-						dst += (a0 & 0x1fffff);
-						memset(dst, 0, a1);
-					}
-					break;
-
-				case 0x2a:	// memcpy
-					{
-						uint8_t *dst, *src;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: memcpy(%08x, %08x, %08x)\n", a0, a1, a2);
-						#endif
-
-						dst = (uint8_t *)psx_ram;
-						src = (uint8_t *)psx_ram;
-						dst += (a0 & 0x1fffff);
-						src += (a1 & 0x1fffff);
-
-						while (a2)
-						{
-							*dst = *src;
-							dst++;
-							src++;
-							a2--;
-						}
-
-						// v0 = a0
-						mipsinfo.i = a0;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x2b:	// memset
-					{
-						uint8_t *dst;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: memset(%08x, %08x, %08x)\n", a0, a1, a2);
-						#endif
-
-						dst = (uint8_t *)psx_ram;
-						dst += (a0 & 0x1fffff);
-
-						while (a2)
-						{
-							*dst = a1;
-							dst++;
-							a2--;
-						}
-
-						// v0 = a0
-						mipsinfo.i = a0;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x2f:	// rand
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: rand\n");
-					#endif
-
-					// v0 = result
-					mipsinfo.i = 1 + (int)(32767.0*rand()/(RAND_MAX+1.0));
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					break;
-
-				case 0x30:	// srand
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: srand(%x)\n", a0);
-					#endif
-					srand(a0);
-					break;
-
-				case 0x33:	// malloc
-					{
-						uint32_t chunk, fd;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: malloc(%x)\n", a0);
-						#endif
-
-						chunk = heap_addr;
-
-						// find a free block that's big enough
-						while ((a0 > LE32(psx_ram[(chunk+BLK_SIZE)/4])) ||
-						       (LE32(psx_ram[(chunk+BLK_STAT)/4]) ==  1))
-						{
-							chunk = LE32(psx_ram[(chunk+BLK_FD)]);
-						}
-
-						// split free block
-						fd = chunk + 16 + a0;	// free block starts after block record and allocation size
-						psx_ram[(fd+BLK_STAT)/4] = psx_ram[(chunk+BLK_STAT)/4];
-						psx_ram[(fd+BLK_SIZE)/4] = LE32(LE32(psx_ram[(chunk+BLK_SIZE)/4]) - a0);
-						psx_ram[(fd+BLK_FD)/4] = psx_ram[(chunk+BLK_FD)/4];
-						psx_ram[(fd+BLK_BK)/4] = chunk;
-
-						psx_ram[(chunk+BLK_STAT)/4] = LE32(1);
-						psx_ram[(chunk+BLK_SIZE)/4] = LE32(a0);
-						psx_ram[(chunk+BLK_FD)/4] = LE32(fd);
-
-						mipsinfo.i = chunk + 16;
-						mipsinfo.i |= 0x80000000;
-						#if DEBUG_HLE_BIOS
-						printf("== %08x\n", mipsinfo.i);
-						#endif
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x39:	// InitHeap
-					// heap address in A0, length in A1
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: InitHeap(%08x, %08x)\n", a0, a1);
-					#endif
-
-					heap_addr = a0 & 0x3fffffff;
-
-					psx_ram[(heap_addr+BLK_STAT)/4] = LE32(0);
-					psx_ram[(heap_addr+BLK_FD)/4] = LE32(0);
-					psx_ram[(heap_addr+BLK_BK)/4] = LE32(0);
-
-					// if heap size out of range, clamp it
-					if (((a0 & 0x1fffff) + a1) >= 2*1024*1024)
-					{
-						psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(0x1ffffc - (a0 & 0x1fffff));
-					}
-					else
-					{
-						psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(a1);
-					}
-					break;
-
-				case 0x3f:	// printf
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: printf(%08x) = %s\n", a0, &psx_ram[(a0&0x1fffff)/4]);
-					#endif
-					break;
-
-				case 0x72:	//__96_remove
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: __96_remove\n");
-					#endif
-					break;
-
-				default:
-					#if DEBUG_HLE_BIOS
-					printf("Unknown BIOS A0 call = %x\n", subcall);
-					#endif
-					break;
-			}
-			break;
-
-		case 0xb0:	// b0 syscalls
-			switch (subcall)
-			{
-				case 0x07:	// DeliverEvent
-					{
-						int ev, spec;
-
-
-						ev = calc_ev(a0);
-						spec = calc_spec(a1);
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: DeliverEvent(ev %d, spec %d)\n", ev, spec);
-						#endif
-
-						if (Event[ev][spec].status != LE32(EvStACTIVE))
-						{
-							#if DEBUG_HLE_BIOS
-							printf("event not active\n");
-							#endif
-							return;
-						}
-
-						// if interrupt mode, do the call
-						if (Event[ev][spec].mode == LE32(EvMdINTR))
-						{
-							#if DEBUG_HLE_BIOS
-							printf("INTR type, need to call handler %x\n", LE32(Event[ev][spec].fhandler));
-							#endif
-						}
-						else
-						{
-							Event[ev][spec].status = LE32(EvStALREADY);
-						}
-					}
-					break;
-
-				case 0x08:	// OpenEvent
-					{
-						int ev, spec;
-
-						ev = calc_ev(a0);
-						spec = calc_spec(a1);
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: OpenEvent(%08x, %08x, %08x, %08x) = ev %d spec %d\n", a0, a1, a2, a3, ev, spec);
-						if (ev >= 64 && ev <= 68)
-						{
-							printf("HLEBIOS: event %d maps to root counter %d\n", ev, ev-64);
-						}
-						#endif
-
-						Event[ev][spec].status = LE32(EvStWAIT);
-						Event[ev][spec].mode = LE32(a2);
-						Event[ev][spec].fhandler = LE32(a3);
-
-						// v0 = ev | spec<<8;
-						mipsinfo.i = ev | (spec<<8);
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x0a:	// WaitEvent
-					{
-						int ev, spec;
-
-						ev = a0 & 0xff;
-						spec = (a0 >> 8) & 0xff;
-
-						mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: WaitEvent(ev %d spec %d) PC=%x\n", ev, spec, mipsinfo.i);
-						#endif
-
-						Event[ev][spec].status = LE32(EvStACTIVE);
-
-						// v0 = 1
-						mipsinfo.i = 1;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-
-						WAI = 1;
-						mips_shorten_frame();
-					}
-					break;
-
-				case 0x0b:	// TestEvent
-					{
-						int ev, spec;
-
-						ev   = a0 & 0xff;
-						spec = (a0 >> 8) & 0xff;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: TestEvent(ev %d spec %d)\n", ev, spec);
-						#endif
-
-						// v0 = (is event ready?)
-						if (Event[ev][spec].status == LE32(EvStALREADY))
-						{
-							Event[ev][spec].status = LE32(EvStACTIVE);
-							mipsinfo.i = 1;
-						}
-						else
-						{
-							mipsinfo.i = 0;
-						}
-
-						WAI = 1;
-
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-
-						// it looks like this sets v1 to something non-zero too
-						// (code in Crash 2 & 3 actually relies on that behavior)
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R3, &mipsinfo);
-					}
-					break;
-
-				case 0x0c:	// EnableEvent
-					{
-						int ev, spec;
-
-						ev = a0 & 0xff;
-						spec = (a0 >> 8) & 0xff;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: EnableEvent(ev %d spec %d)\n", ev, spec);
-						#endif
-
-						Event[ev][spec].status = LE32(EvStACTIVE);
-
-						// v0 = 1
-						mipsinfo.i = 1;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x0d:	// DisableEvent
-					{
-						int ev, spec;
-
-						ev = a0 & 0xff;
-						spec = (a0 >> 8) & 0xff;
-
-						#if DEBUG_HLE_BIOS
-						printf("HLEBIOS: DisableEvent(ev %d spec %d)\n", ev, spec);
-						#endif
-
-						Event[ev][spec].status = LE32(EvStWAIT);
-
-						// v0 = 1
-						mipsinfo.i = 1;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-					}
-					break;
-
-				case 0x17:	// ReturnFromException
-					for (i = 0; i < 32; i++)
-					{
-						mipsinfo.i = irq_regs[i];
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
-					}
-
-					mipsinfo.i = irq_regs[32];
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
-					mipsinfo.i = irq_regs[33];
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
-					mipsinfo.i = mips_get_ePC();
-//					printf("ReturnFromException: IRQ state %x\n", irq_data & irq_mask);
-//					printf("HLEBIOS: ReturnFromException, cause = %08x, PC = %08x\n", mips_get_cause(), mipsinfo.i);
-					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-					status = mips_get_status();
-					status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
-					mips_set_status(status);
-					return;	// force return to avoid PC=RA below
-					break;
-
-				case 0x19:	// HookEntryInt
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: HookEntryInt(%08x)\n", a0);
-					#endif
-					entry_int = a0;
-					break;
-
-				case 0x3f:	// puts
-//					printf("HLEBIOS: puts\n");
-					break;
-
-				case 0x5b:	// ChangeClearPAD
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: ChangeClearPAD\n");
-					#endif
-					break;
-
-				default:
-					#if DEBUG_HLE_BIOS
-					printf("Unknown BIOS B0 call = %x\n", subcall);
-					#endif
-					break;
-			}
-			break;
-
-		case 0xc0:	// c0 syscalls
-			switch (subcall)
-			{
-				case 0xa:	// ChangeClearRCnt
-					#if DEBUG_HLE_BIOS
-					printf("HLEBIOS: ChangeClearRCnt(%08x, %08x)\n", a0, a1);
-					#endif
-
-					// v0 = (a0*4)+0x8600
-					mipsinfo.i = LE32(psx_ram[((a0<<2) + 0x8600)/4]);
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-
-					// (a0*4)+0x8600 = a1;
-					psx_ram[((a0<<2) + 0x8600)/4] = LE32(a1);
-					break;
-
-				default:
-					#if DEBUG_HLE_BIOS
-					printf("Unknown BIOS C0 call = %x\n", subcall);
-					#endif
-					break;
-			}
-			break;
-	}
-
-	// PC = RA
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-}
-
-// root counters
-
-void psx_hw_runcounters(void)
-{
-	int i;
-
-	// don't process any IRQ sources when interrupts are suspended
-	if (!intr_susp)
-	{
-		if (dma4_delay)
-		{
-			dma4_delay--;
-
-			if (dma4_delay == 0)
-			{
-				SPU2interruptDMA4();
-
-				if (dma4_cb)
-				{
-					call_irq_routine(dma4_cb, dma4_flag);
-				}
-			}
-		}
-
-		if (dma7_delay)
-		{
-			dma7_delay--;
-
-			if (dma7_delay == 0)
-			{
-				SPU2interruptDMA7();
-
-				if (dma7_cb)
-				{
-					call_irq_routine(dma7_cb, dma7_flag);
-				}
-			}
-		}
-
-		for (i = 0; i < iNumThreads; i++)
-		{
-			if (threads[i].iState == TS_WAITDELAY)
-			{
-				if (threads[i].waitparm > CLOCK_DIV)
-				{
-					threads[i].waitparm -= CLOCK_DIV;
-				}
-				else	// time's up
-				{
-					threads[i].waitparm = 0;
-					threads[i].iState = TS_READY;
-
-					timerexp = 1;
-
-					ps2_reschedule();
-				}
-			}
-		}
-
-		sys_time += 836;
-
-		if (iNumTimers > 0)
-		{
-			for (i = 0; i < iNumTimers; i++)
-			{
-				if (iop_timers[i].iActive > 0)
-				{
-					iop_timers[i].count += 836;
-					if (iop_timers[i].count >= iop_timers[i].target)
-					{
-						iop_timers[i].count -= iop_timers[i].target;
-
-	//					printf("Timer %d: handler = %08x, param = %08x\n", i, iop_timers[i].handler, iop_timers[i].hparam);
-						call_irq_routine(iop_timers[i].handler, iop_timers[i].hparam);
-
-						timerexp = 1;
-					}
-				}
-			}
-		}
-	}
-
-// PS1 root counters
-	for (i = 0; i < 4; i++)
-	{
-		if ((!(root_cnts[i].mode & RC_EN)) && (root_cnts[i].mode != 0))
-		{
-			if (root_cnts[i].mode & RC_DIV8)
-			{
-				root_cnts[i].count += 768/8;
-			}
-			else
-			{
-				root_cnts[i].count += 768;
-			}
-
-			if (root_cnts[i].count >= root_cnts[i].target)
-			{
-				if (!(root_cnts[i].mode & RC_RESET))
-				{
-					root_cnts[i].mode |= RC_EN;
-				}
-				else
-				{
-					root_cnts[i].count %= root_cnts[i].target;
-				}
-
-				psx_irq_set(1<<(4+i));
-			}
-		}
-	}
-}
-
-// PEOpS callbacks
-
-void SPUirq(void)
-{
-//	psx_irq_set(0x200);
-}
-
-// PSXCPU callbacks
-
-uint8_t program_read_byte_32le(offs_t address)
-{
-	switch (address & 0x3)
-	{
-		case 0:
-			return psx_hw_read(address, 0xffffff00);
-			break;
-		case 1:
-			return psx_hw_read(address, 0xffff00ff)>>8;
-			break;
-		case 2:
-			return psx_hw_read(address, 0xff00ffff)>>16;
-			break;
-		case 3:
-			return psx_hw_read(address, 0x00ffffff)>>24;
-			break;
-	}
-
-	return psx_hw_read(address, 0xffffff00);
-}
-
-uint16_t program_read_word_32le(offs_t address)
-{
-	if (address & 2)
-		return psx_hw_read(address, 0x0000ffff)>>16;
-
-	return psx_hw_read(address, 0xffff0000);
-}
-
-uint32_t program_read_dword_32le(offs_t address)
-{
-	return psx_hw_read(address, 0);
-}
-
-void program_write_byte_32le(offs_t address, uint8_t data)
-{
-	switch (address & 0x3)
-	{
-		case 0:
-			psx_hw_write(address, data, 0xffffff00);
-			break;
-		case 1:
-			psx_hw_write(address, data<<8, 0xffff00ff);
-			break;
-		case 2:
-			psx_hw_write(address, data<<16, 0xff00ffff);
-			break;
-		case 3:
-			psx_hw_write(address, data<<24, 0x00ffffff);
-			break;
-	}
-}
-
-void program_write_word_32le(offs_t address, uint16_t data)
-{
-	if (address & 2)
-	{
-		psx_hw_write(address, data<<16, 0x0000ffff);
-		return;
-	}
-
-	psx_hw_write(address, data, 0xffff0000);
-}
-
-void program_write_dword_32le(offs_t address, uint32_t data)
-{
-	psx_hw_write(address, data, 0);
-}
-
-// sprintf replacement
-static void iop_sprintf(char *out, char *fmt, uint32_t pstart)
-{
-	char temp[64], tfmt[64];
-	char *cf, *pstr;
-	union cpuinfo mipsinfo;
-	int curparm, fp, isnum;
-
-	curparm = pstart;
-	cf = fmt;
-
-	while (*cf != '\0')
-	{
-		if (*cf != '%')
-		{
-			if (*cf == 27)
-			{
-				*out++ = '[';
-				*out++ = 'E';
-				*out++ = 'S';
-				*out++ = 'C';
-				*out = ']';
-			}
-			else
-			{
-				*out = *cf;
-			}
-			out++;
-			cf++;
-		}
-		else	// got format
-		{
-			cf++;
-
-			tfmt[0] = '%';
-			fp = 1;
-			while (((*cf >= '0') && (*cf <= '9')) || (*cf == '.'))
-			{
-				tfmt[fp] = *cf;
-				fp++;
-				cf++;
-			}
-
-			tfmt[fp] = *cf;
-			tfmt[fp+1] = '\0';
-
-			isnum = 0;
-			switch (*cf)
-			{
-				case 'x':
-				case 'X':
-				case 'd':
-				case 'D':
-				case 'c':
-				case 'C':
-				case 'u':
-				case 'U':
-					isnum = 1;
-					break;
-			}
-
-//			printf("]]] temp format: [%s] [%d]\n", tfmt, isnum);
-
-			if (isnum)
-			{
-				mips_get_info(curparm, &mipsinfo);
-//				printf("parameter %d = %x\n", curparm-pstart, mipsinfo.i);
-				curparm++;
-				sprintf(temp, tfmt, (int32_t)mipsinfo.i);
-			}
-			else
-			{
-				mips_get_info(curparm, &mipsinfo);
-				curparm++;
-
-				pstr = (char *)psx_ram;
-				pstr += (mipsinfo.i & 0x1fffff);
-
-				sprintf(temp, tfmt, pstr);
-			}
-
-			pstr = &temp[0];
-			while (*pstr != '\0')
-			{
-				*out = *pstr;
-				out++;
-				pstr++;
-			}
-
-			cf++;
-		}
-	}
-
-	*out = '\0';
-}
-
-// PS2 IOP callbacks
-void psx_iop_call(uint32_t pc, uint32_t callnum)
-{
-	uint32_t scan;
-	char *mname, *str1, name[9], out[512];
-	uint32_t a0, a1, a2, a3;
-	union cpuinfo mipsinfo;
-	int i;
-
-//	printf("IOP call @ %08x\n", pc);
-
-	// prefetch parameters
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-	a0 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
-	a1 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo);
-	a2 = mipsinfo.i;
-	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo);
-	a3 = mipsinfo.i;
-
-	scan = (pc&0x0fffffff)/4;
-	while ((psx_ram[scan] != LE32(0x41e00000)) && (scan >= (0x10000/4)))
-	{
-		scan--;
-	}
-
-	if (psx_ram[scan] != LE32(0x41e00000))
-	{
-		printf("FATAL ERROR: couldn't find IOP link signature\n");
-		return;
-	}
-
-	scan += 3;	// skip zero and version
-	memcpy(name, &psx_ram[scan], 8);
-	name[8] = '\0';
-
-//	printf("IOP: call module [%s] service %d (PC=%08x)\n", name, callnum, pc);
-
-	if (!strcmp(name, "stdio"))
-	{
-		switch (callnum)
-		{
-			case 4:	// printf
-				mname = (char *)psx_ram;
-				mname += a0 & 0x1fffff;
-				mname += (a0 & 3);
-
-				iop_sprintf(out, mname, CPUINFO_INT_REGISTER + MIPS_R5);	// a1 is first parm
-
-			/*	if (out[strlen(out)-1] != '\n')
-				{
-					strcat(out, "\n");
-				}*/
-
-				#if DEBUG_HLE_IOP
-				printf("%s", out);
-				#endif
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "sifman"))
-	{
-		switch (callnum)
-		{
-			case 5:	// sceSifInit
-				#if DEBUG_HLE_IOP
-				printf("IOP: sceSifInit()\n");
-				#endif
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 7: // sceSifSetDma
-				#if DEBUG_HLE_IOP
-				printf("IOP: sceSifSetDma(%08x %08x)\n", a0, a1);
-				#endif
-
-				mipsinfo.i = 1;	// nonzero = success
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 8:	// sceSifDmaStat
-				#if DEBUG_HLE_IOP
-				printf("IOP: sceSifDmaStat(%08x)\n", a0);
-				#endif
-
-				mipsinfo.i = -1;	// dma completed
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 29: // sceSifCheckInit
-				#if DEBUG_HLE_IOP
-				printf("IOP: sceSifCheckInit()\n");
-				#endif
-
-				mipsinfo.i = 1;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "thbase"))
-	{
-		uint32_t newAlloc;
-
-		switch (callnum)
-		{
-			case 4:	// CreateThread
-				#if DEBUG_THREADING
-				printf("IOP: CreateThread(%08x)\n", a0);
-				#endif
-				a0 &= 0x1fffff;
-				a0 /= 4;
-				#if DEBUG_THREADING
-				printf("   : flags %x routine %08x pri %x stacksize %d refCon %08x\n",
-					psx_ram[a0], psx_ram[a0+1], psx_ram[a0+2], psx_ram[a0+3], psx_ram[a0+4]);
-				#endif
-
-				newAlloc = psf2_get_loadaddr();
-				// force 16-byte alignment
-				if (newAlloc & 0xf)
-				{
-					newAlloc &= ~0xf;
-					newAlloc += 16;
-				}
-				psf2_set_loadaddr(newAlloc + LE32(psx_ram[a0+3]));
-
-				threads[iNumThreads].iState = TS_CREATED;
-				threads[iNumThreads].stackloc = newAlloc;
-				threads[iNumThreads].flags = LE32(psx_ram[a0]);
-				threads[iNumThreads].routine = LE32(psx_ram[a0+2]);
-				threads[iNumThreads].stacksize = LE32(psx_ram[a0+3]);
-				threads[iNumThreads].refCon = LE32(psx_ram[a0+4]);
-
-				mipsinfo.i = iNumThreads;
-				iNumThreads++;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 6:	// StartThread
-				#if DEBUG_THREADING
-				printf("IOP: StartThread(%d %d)\n", a0, a1);
-				#endif
-
-				FreezeThread(iCurThread, 1);
-				ThawThread(a0);
-				iCurThread = a0;
-				break;
-
-			case 20:// GetThreadID
-				#if DEBUG_THREADING
-				printf("IOP: GetThreadId()\n");
-				#endif
-
-				mipsinfo.i = iCurThread;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 24:// SleepThread
-				#if DEBUG_THREADING
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: SleepThread() [curThread %d, PC=%x]\n", iCurThread, mipsinfo.i);
-				#endif
-
-				FreezeThread(iCurThread, 1);
-				threads[iCurThread].iState = TS_SLEEPING;
-				iCurThread = -1;
-
-				ps2_reschedule();
-				break;
-
-			case 25:// WakeupThread
-				#if DEBUG_THREADING
-				printf("IOP: WakeupThread(%d)\n", a0);
-				#endif
-
-				// set thread to "ready to go"
-				threads[a0].iState = TS_READY;
-				break;
-
-			case 26:// iWakeupThread
-				#if DEBUG_THREADING
-				printf("IOP: iWakeupThread(%d)\n", a0);
-				#endif
-
-				// set thread to "ready to go" if it's not running
-				if (threads[a0].iState != TS_RUNNING)
-				{
-					threads[a0].iState = TS_READY;
-				}
-				break;
-
-			case 33:// DelayThread
-				{
-					double dTicks;
-
-					#if DEBUG_THREADING
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					printf("IOP: DelayThread(%d) (PC=%x) [curthread = %d]\n", a0, mipsinfo.i, iCurThread);
-					#endif
-
-					if (a0 < 100)
-					{
-						a0 = 100;
-					}
-					dTicks = (double)a0;
-
-					FreezeThread(iCurThread, 1);
-					threads[iCurThread].iState = TS_WAITDELAY;
-					dTicks /= (double)1000000.0;
-					dTicks *= (double)36864000.0;	// 768*48000 = IOP native-mode clock rate
-					threads[iCurThread].waitparm = (uint32_t)dTicks;
-					iCurThread = -1;
-
-					ps2_reschedule();
-				}
-				break;
-
-			case 34://GetSystemTime
-				#if DEBUG_HLE_IOP
-				printf("IOP: GetSystemTime(%x)\n", a0);
-				#endif
-
-				a0 &= 0x1fffff;
-				a0 /= 4;
-
-				psx_ram[a0] = LE32(sys_time & 0xffffffff);  	// low
-				psx_ram[a0+1] = LE32(sys_time >> 32);	// high
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 39:// USec2SysClock
-				{
-					uint64_t dTicks = (uint64_t)a0;
-					uint32_t hi, lo;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: USec2SysClock(%d %08x)\n", a0, a1);
-					#endif
-
-					dTicks *= (uint64_t)36864000;
-					dTicks /= (uint64_t)1000000;
-
-					hi = dTicks>>32;
-					lo = dTicks & 0xffffffff;
-
-					psx_ram[((a1 & 0x1fffff)/4)] = LE32(lo);
-					psx_ram[((a1 & 0x1fffff)/4)+1] = LE32(hi);
-
-					mipsinfo.i = 0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			case 40://SysClock2USec
-				{
-					uint64_t temp;
-					uint32_t seconds, usec;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: SysClock2USec(%08x %08x %08x)\n", a0, a1, a2);
-					#endif
-
-					a0 &= 0x1fffff;
-					a1 &= 0x1fffff;
-					a2 &= 0x1fffff;
-					a0 /= 4;
-					a1 /= 4;
-					a2 /= 4;
-
-					temp = LE32(psx_ram[a0]);
-					temp |= (uint64_t)LE32(psx_ram[a0+1])<<32;
-
-					temp *= (uint64_t)1000000;
-					temp /= (uint64_t)36864000;
-
-					// temp now is USec
-					seconds = (temp / 1000000) & 0xffffffff;
-					usec = (temp % 1000000) & 0xffffffff;
-
-					psx_ram[a1] = LE32(seconds);
-					psx_ram[a2] = LE32(usec);
-				}
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "thevent"))
-	{
-		switch (callnum)
-		{
-			case 4:	// CreateEventFlag
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				#if DEBUG_HLE_IOP
-				printf("IOP: CreateEventFlag(%08x) (PC=%x)\n", a0, mipsinfo.i);
-				#endif
-
-				a0 &= 0x1fffff;
-				a0 /= 4;
-
-				evflags[iNumFlags].type = LE32(psx_ram[a0]);
-				evflags[iNumFlags].value = LE32(psx_ram[a0+1]);
-				evflags[iNumFlags].param = LE32(psx_ram[a0+2]);
-				evflags[iNumFlags].inUse = 1;
-
-				#if DEBUG_HLE_IOP
-				printf("     Flag %02d: type %d init %08x param %08x\n", iNumFlags, evflags[iNumFlags].type, evflags[iNumFlags].value, evflags[iNumFlags].param);
-				#endif
-
-				mipsinfo.i = iNumFlags+1;
-				iNumFlags++;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 6: // SetEventFlag
-				a0--;
-				#if DEBUG_HLE_IOP
-				printf("IOP: SetEventFlag(%d %08x)\n", a0, a1);
-				#endif
-
-				evflags[a0].value |= a1;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 7: // iSetEventFlag
-				a0--;
-				#if DEBUG_HLE_IOP
-				printf("IOP: iSetEventFlag(%08x %08x)\n", a0, a1);
-				#endif
-
-				evflags[a0].value |= a1;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-
-				for (i=0; i < iNumThreads; i++)
-				{
-					if ((threads[i].iState == TS_WAITEVFLAG) && (threads[i].waitparm == a0))
-					{
-						threads[i].iState = TS_READY;
-					}
-				}
-				break;
-
-			case 8:	// ClearEventFlag
-				a0--;
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				#if DEBUG_HLE_IOP
-				printf("IOP: ClearEventFlag(%d %08x) (PC=%x)\n", a0, a1, mipsinfo.i);
-				#endif
-
-				evflags[a0].value &= a1;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 9: // iClearEventFlag
-				a0--;
-				#if DEBUG_HLE_IOP
-				printf("IOP: iClearEventFlag(%d %08x)\n", a0, a1);
-				#endif
-
-				evflags[a0].value &= a1;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 10:// WaitEventFlag
-				a0--;
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: WaitEventFlag(%d %08x %d %08x PC=%x)\n", a0, a1, a2, a3, mipsinfo.i);
-				#endif
-
-				// if we're not set, freeze this thread
-				if (!(evflags[a0].value & a1))
-				{
-					FreezeThread(iCurThread, 1);
-					threads[iCurThread].iState = TS_WAITEVFLAG;
-					threads[iCurThread].waitparm = a0;
-					iCurThread = -1;
-
-					ps2_reschedule();
-				}
-				else
-				{
-					mipsinfo.i = 0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "thsemap"))
-	{
-		int foundthread;
-
-		switch (callnum)
-		{
-			case 4:	// CreateSema
-				#if DEBUG_HLE_IOP
-				printf("IOP: CreateSema(%08x)\n", a0);
-				#endif
-
-				mipsinfo.i = -1;
-				for (i = 0; i < SEMA_MAX; i++)
-				{
-					if (!semaphores[i].inuse)
-					{
-						mipsinfo.i = i;
-						break;
-					}
-				}
-
-				if (mipsinfo.i == -1)
-				{
-					printf("IOP: out of semaphores!\n");
-				}
-
-				a0 &= 0x7fffffff;
-				a0 /= 4;
-
-//				printf("Sema %d Parms: %08x %08x %08x %08x\n", mipsinfo.i, psx_ram[a0], psx_ram[a0+1], psx_ram[a0+2], psx_ram[a0+3]);
-
-				if (mipsinfo.i != -1)
-				{
-					semaphores[mipsinfo.i].attr = LE32(psx_ram[a0]);
-					semaphores[mipsinfo.i].option = LE32(psx_ram[a0+1]);
-					semaphores[mipsinfo.i].init = LE32(psx_ram[a0+2]);
-					semaphores[mipsinfo.i].max = LE32(psx_ram[a0+3]);
-
-					semaphores[mipsinfo.i].current = semaphores[mipsinfo.i].init;
-
-					semaphores[mipsinfo.i].inuse = 1;
-				}
-
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 6: // SignalSema
-				#if DEBUG_HLE_IOP
-				printf("IOP: SignalSema(%d) (current %d)\n", a0, semaphores[a0].current);
-				#endif
-
-				foundthread = 0;
-				for (i=0; i < iNumThreads; i++)
-				{
-					if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0))
-					{
-						threads[i].iState = TS_READY;
-						semaphores[a0].threadsWaiting--;
-						foundthread = 1;
-						break;
-					}
-				}
-
-				mipsinfo.i = 0;
-
-				if (!foundthread)
-				{
-					if (semaphores[a0].current < semaphores[a0].max)
-					{
-						semaphores[a0].current++;
-					}
-					else
-					{
-						mipsinfo.i = -420;	// semaphore overflow
-					}
-				}
-
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 7: // iSignalSema
-				#if DEBUG_HLE_IOP
-				printf("IOP: iSignalSema(%d)\n", a0);
-				#endif
-
-				foundthread = 0;
-				for (i=0; i < iNumThreads; i++)
-				{
-					if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0))
-					{
-						threads[i].iState = TS_READY;
-						semaphores[a0].threadsWaiting--;
-						foundthread = 1;
-						break;
-					}
-				}
-
-				mipsinfo.i = 0;
-
-				if (!foundthread)
-				{
-					if (semaphores[a0].current < semaphores[a0].max)
-					{
-						semaphores[a0].current++;
-					}
-					else
-					{
-						mipsinfo.i = -420;	// semaphore overflow
-					}
-				}
-
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 8: // WaitSema
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: WaitSema(%d) (cnt %d) (th %d) (PC=%x)\n", a0, iCurThread, semaphores[a0].current, mipsinfo.i);
-				#endif
-
-				if (semaphores[a0].current > 0)
-				{
-					semaphores[a0].current--;
-				}
-				else
-				{
-					FreezeThread(iCurThread, 1);
-					threads[iCurThread].iState = TS_WAITSEMA;
-					threads[iCurThread].waitparm = a0;
-					ps2_reschedule();
-				}
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "timrman"))
-	{
-		switch (callnum)
-		{
-			case 4:	// AllocHardTimer
-				#if DEBUG_HLE_IOP
-				printf("IOP: AllocHardTimer(%d %d %d)\n", a0, a1, a2);
-				#endif
-				// source, size, prescale
-
-				if (a1 != 32)
-				{
-					printf("IOP: AllocHardTimer doesn't support 16-bit timers!\n");
-				}
-
-				iop_timers[iNumTimers].source = a0;
-				iop_timers[iNumTimers].prescale = a2;
-
-				mipsinfo.i = iNumTimers+1;
-				iNumTimers++;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 6: // FreeHardTimer
-				#if DEBUG_HLE_IOP
-				printf("IOP: FreeHardTimer(%d)\n", a0);
-				#endif
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 10:// GetTimerCounter
-				mipsinfo.i = iop_timers[a0-1].count;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 20: // SetTimerHandler
-				#if DEBUG_HLE_IOP
-				printf("IOP: SetTimerHandler(%d %d %08x %08x)\n", a0, a1, a2, a3);
-				#endif
-				// id, compare, handler, common (last is param for handler)
-
-				iop_timers[a0-1].target = a1;
-				iop_timers[a0-1].handler = a2;
-				iop_timers[a0-1].hparam = a3;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 22: // SetupHardTimer
-				#if DEBUG_HLE_IOP
-				printf("IOP: SetupHardTimer(%d %d %d %d)\n", a0, a1, a2, a3);
-				#endif
-				// id, source, mode, prescale
-
-				iop_timers[a0-1].source = a1;
-				iop_timers[a0-1].mode = a2;
-				iop_timers[a0-1].prescale = a3;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 23: // StartHardTimer
-				#if DEBUG_HLE_IOP
-				printf("IOP: StartHardTimer(%d)\n", a0);
-				#endif
-
-				iop_timers[a0-1].iActive = 1;
-				iop_timers[a0-1].count = 0;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 24: // StopHardTimer
-				#if DEBUG_HLE_IOP
-				printf("IOP: StopHardTimer(%d)\n", a0);
-				#endif
-
-				iop_timers[a0-1].iActive = 0;
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "sysclib"))
-	{
-		switch (callnum)
-		{
-			case 12:	// memcpy
-				{
-					uint8_t *dst, *src;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: memcpy(%08x, %08x, %d)\n", a0, a1, a2);
-					#endif
-
-					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
-					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
-					// get exact byte alignment
-					dst += a0 % 4;
-					src += a1 % 4;
-
-					while (a2)
-					{
-						*dst = *src;
-						dst++;
-						src++;
-						a2--;
-					}
-
-					// v0 = a0
-					mipsinfo.i = a0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			case 13:	// memmove
-				{
-					uint8_t *dst, *src;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: memmove(%08x, %08x, %d)\n", a0, a1, a2);
-					#endif
-
-					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
-					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
-					// get exact byte alignment
-					dst += a0 % 4;
-					src += a1 % 4;
-
-					dst += a2 - 1;
-					src += a2 - 1;
-
-					while (a2)
-					{
-						*dst = *src;
-						dst--;
-						src--;
-						a2--;
-					}
-
-					// v0 = a0
-					mipsinfo.i = a0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			case 14:	// memset
-				{
-					uint8_t *dst;
-
-					#if DEBUG_HLE_IOP
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					printf("IOP: memset(%08x, %02x, %d) [PC=%x]\n", a0, a1, a2, mipsinfo.i);
-					#endif
-
-					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
-					dst += (a0 & 3);
-
-					memset(dst, a1, a2);
-				}
-				break;
-
-			case 17:	// bzero
-				{
-					uint8_t *dst;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: bzero(%08x, %08x)\n", a0, a1);
-					#endif
-
-					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
-					dst += (a0 & 3);
-					memset(dst, 0, a1);
-				}
-				break;
-
-			case 19:	// sprintf
-				mname = (char *)psx_ram;
-				str1 = (char *)psx_ram;
-				mname += a0 & 0x1fffff;
-				str1 += a1 & 0x1fffff;
-
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: sprintf(%08x, %s, ...) [PC=%08x]\n", a0, str1, (uint32_t)mipsinfo.i);
-				printf("%x %x %x %x\n", a0, a1, a2, a3);
-				#endif
-
-				iop_sprintf(mname, str1, CPUINFO_INT_REGISTER + MIPS_R6);	// a2 is first parameter
-
-				#if DEBUG_HLE_IOP
-				printf("     = [%s]\n", mname);
-				#endif
-				break;
-
-			case 23:	// strcpy
-				{
-					uint8_t *dst, *src;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: strcpy(%08x, %08x)\n", a0, a1);
-					#endif
-
-					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
-					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
-					// get exact byte alignment
-					dst += a0 % 4;
-					src += a1 % 4;
-
-					while (*src != '\0')
-					{
-						*dst = *src;
-						dst++;
-						src++;
-					}
-					*dst = '\0';
-
-					// v0 = a0
-					mipsinfo.i = a0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			case 27:	// strlen
-				{
-					char *dst;
-
-					#if DEBUG_HLE_IOP
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					printf("IOP: strlen(%08x) [PC=%x]\n", a0, mipsinfo.i);
-					#endif
-
-					dst = (char *)&psx_ram[(a0&0x1fffff)/4];
-					dst += (a0 & 3);
-					mipsinfo.i = strlen(dst);
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-			case 30:	// strncpy
-				{
-					char *dst, *src;
-
-					#if DEBUG_HLE_IOP
-					printf("IOP: strncpy(%08x, %08x, %d)\n", a0, a1, a2);
-					#endif
-
-					dst = (char *)&psx_ram[(a0&0x1fffff)/4];
-					src = (char *)&psx_ram[(a1&0x1fffff)/4];
-					// get exact byte alignment
-					dst += a0 % 4;
-					src += a1 % 4;
-
-					while ((*src != '\0') && (a2 > 0))
-					{
-						*dst = *src;
-						dst++;
-						src++;
-						a2--;
-					}
-					*dst = '\0';
-
-					// v0 = a0
-					mipsinfo.i = a0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				}
-				break;
-
-
-			case 36:	// strtol
-				mname = (char *)&psx_ram[(a0 & 0x1fffff)/4];
-				mname += (a0 & 3);
-
-				if (a1)
-				{
-					printf("IOP: Unhandled strtol with non-NULL second parm\n");
-				}
-
-				mipsinfo.i = strtol(mname, NULL, a2);
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "intrman"))
-	{
-		switch (callnum)
-		{
-			case 4:	// RegisterIntrHandler
-				#if DEBUG_HLE_IOP
-				printf("IOP: RegisterIntrHandler(%d %08x %08x %08x)\n", a0, a1, a2, a3);
-				#endif
-
-				if (a0 == 9)
-				{
-					irq9_fval = a1;
-					irq9_cb = a2;
-					irq9_flag = a3;
-				}
-
-				// DMA4?
-				if (a0 == 36)
-				{
-					dma4_fval = a1;
-					dma4_cb = a2;
-					dma4_flag = a3;
-				}
-
-				// DMA7?
-				if (a0 == 40)
-				{
-					dma7_fval = a1;
-					dma7_cb = a2;
-					dma7_flag = a3;
-				}
-				break;
-
-			case 5:	// ReleaseIntrHandler
-				#if DEBUG_HLE_IOP
-				printf("IOP: ReleaseIntrHandler(%d)\n", a0);
-				#endif
-				break;
-
-			case 6:	// EnableIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: EnableIntr(%d)\n", a0);
-				#endif
-				break;
-
-			case 7:	// DisableIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: DisableIntr(%d)\n", a0);
-				#endif
-				break;
-
-			case 8: // CpuDisableIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: CpuDisableIntr(%d)\n", a0);
-				#endif
-				break;
-
-			case 9: // CpuEnableIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: CpuEnableIntr(%d)\n", a0);
-				#endif
-				break;
-
-			case 17:	// CpuSuspendIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: CpuSuspendIntr\n");
-				#endif
-
-				// if already suspended, return an error code
-				if (intr_susp)
-				{
-					mipsinfo.i = -102;
-				}
-				else
-				{
-					mipsinfo.i = 0;
-				}
-				intr_susp = 1;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 18:	// CpuResumeIntr
-				#if DEBUG_HLE_IOP
-				printf("IOP: CpuResumeIntr\n");
-				#endif
-				intr_susp = 0;
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 23:	// QueryIntrContext
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: QueryIntrContext(PC=%x)\n", mipsinfo.i);
-				#endif
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "loadcore"))
-	{
-		switch (callnum)
-		{
-			case 5: // FlushDcache
-				#if DEBUG_HLE_IOP
-				printf("IOP: FlushDcache()\n");
-				#endif
-				break;
-
-			case 6:	// RegisterLibraryEntries
-				a0 &= 0x1fffff;
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: RegisterLibraryEntries(%08x) (PC=%x)\n", a0, mipsinfo.i);
-				#endif
-
-				if (psx_ram[a0/4] == LE32(0x41c00000))
-				{
-					a0 += 3*4;
-					memcpy(&reglibs[iNumLibs].name, &psx_ram[a0/4], 8);
-					reglibs[iNumLibs].name[8] = '\0';
-					#if DEBUG_HLE_IOP
-					printf("Lib name [%s]\n", &reglibs[iNumLibs].name);
-					#endif
-					a0 += 2*4;
-					reglibs[iNumLibs].dispatch = a0;
-					iNumLibs++;
-				}
-				else
-				{
-					printf("ERROR: Entry table signature missing\n");
-
-				}
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "sysmem"))
-	{
-		uint32_t newAlloc;
-
-		switch (callnum)
-		{
-			case 4:	// AllocMemory
-				newAlloc = psf2_get_loadaddr();
-				// make sure we're 16-byte aligned
-				if (newAlloc & 15)
-				{
-					newAlloc &= ~15;
-					newAlloc += 16;
-				}
-
-				if (a1 & 15)
-				{
-					a1 &= ~15;
-					a1 += 16;
-				}
-
-				psf2_set_loadaddr(newAlloc + a1);
-
-				#if DEBUG_HLE_IOP
-				printf("IOP: AllocMemory(%d, %d, %x) = %08x\n", a0, a1, a2, newAlloc|0x80000000);
-				#endif
-
-				mipsinfo.i = newAlloc; // | 0x80000000;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 5:	// FreeMemory
-				#if DEBUG_HLE_IOP
-				printf("IOP: FreeMemory(%x)\n", a0);
-				#endif
-				break;
-
-			case 7:	// QueryMaxFreeMemSize
-				#if DEBUG_HLE_IOP
-				printf("IOP: QueryMaxFreeMemSize\n");
-				#endif
-
-				mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr();
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 8:	// QueryTotalFreeMemSize
-				#if DEBUG_HLE_IOP
-				printf("IOP: QueryTotalFreeMemSize\n");
-				#endif
-
-				mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr();
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 14: // Kprintf
-				mname = (char *)psx_ram;
-				mname += a0 & 0x1fffff;
-				mname += (a0 & 3);
-
-				iop_sprintf(out, mname, CPUINFO_INT_REGISTER + MIPS_R5);	// a1 is first parm
-
-				if (out[strlen(out)-1] != '\n')
-				{
-					strcat(out, "\n");
-				}
-
-				// filter out ESC characters
-				{
-					int ch;
-
-					for (ch = 0; ch < strlen(out); ch++)
-					{
-						if (out[ch] == 27)
-						{
-							out[ch] = ']';
-						}
-					}
-				}
-
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("KTTY: %s [PC=%x]\n", out, mipsinfo.i);
-				#endif
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-	}
-	else if (!strcmp(name, "modload"))
-	{
-		uint8_t *tempmem;
-		uint32_t newAlloc;
-
-		switch (callnum)
-		{
-			case 7:	// LoadStartModule
-				mname = (char *)&psx_ram[(a0 & 0x1fffff)/4];
-				mname += 8;
-				str1 = (char *)&psx_ram[(a2 & 0x1fffff)/4];
-				#if DEBUG_HLE_IOP
-				printf("LoadStartModule: %s\n", mname);
-				#endif
-
-				// get 2k for our parameters
-				newAlloc = psf2_get_loadaddr();
-				// force 16-byte alignment
-				if (newAlloc & 0xf)
-				{
-					newAlloc &= ~0xf;
-					newAlloc += 16;
-				}
-				psf2_set_loadaddr(newAlloc + 2048);
-
-				tempmem = (uint8_t *)malloc(2*1024*1024);
-				if (psf2_load_file(mname, tempmem, 2*1024*1024) != 0xffffffff)
-				{
-					uint32_t start;
-					int i;
-
-					start = psf2_load_elf(tempmem, 2*1024*1024);
-
-					if (start != 0xffffffff)
-					{
-						uint32_t args[20], numargs = 1, argofs;
-						uint8_t *argwalk = (uint8_t *)psx_ram;
-
-						argwalk += (a2 & 0x1fffff);
-
-						args[0] = a0;	// program name is argc[0]
-
-						argofs = 0;
-
-						if (a1 > 0)
-						{
-							args[numargs] = a2;
-							numargs++;
-
-							while (a1)
-							{
-								if ((*argwalk == 0) && (a1 > 1))
-								{
-									args[numargs] = a2 + argofs + 1;
-									numargs++;
-								}
-								argwalk++;
-								argofs++;
-								a1--;
-							}
-						}
-
-						for (i = 0; i < numargs; i++)
-						{
-							#if DEBUG_HLE_IOP
-//							printf("Arg %d: %08x [%s]\n", i, args[i], &argbase[args[i]-a2]);
-							#endif
-							psx_ram[(newAlloc/4)+i] = LE32(args[i]);
-						}
-
-						// set argv and argc
-						mipsinfo.i = numargs;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
-						mipsinfo.i = 0x80000000 | newAlloc;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
-
-						// leave RA alone, PC = module start
-						// (NOTE: we get called in the delay slot!)
-						mipsinfo.i = start - 4;
-						mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-					}
-				}
-				free(tempmem);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-				break;
-		}
-
-	}
-	else if (!strcmp(name, "ioman"))
-	{
-		switch (callnum)
-		{
-			case 4:	// open
-				{
-					int i, slot2use;
-
-					slot2use = -1;
-					for (i = 0; i < MAX_FILE_SLOTS; i++)
-					{
-						if (filestat[i] == 0)
-						{
-							slot2use = i;
-							break;
-						}
-					}
-
-					if (slot2use == -1)
-					{
-						printf("IOP: out of file slots!\n");
-						mipsinfo.i = 0xffffffff;
-						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-						return;
-					}
-
-					mname = (char *)psx_ram;
-					mname += (a0 & 0x1fffff);
-
-					if (!strncmp(mname, "aofile:", 7))
-					{
-						mname += 8;
-					}
-					else if (!strncmp(mname, "hefile:", 7))
-					{
-						mname += 8;
-					}
-					else if (!strncmp(mname, "host0:", 6))
-					{
-						mname += 7;
-					}
-
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					#if DEBUG_HLE_IOP
-					printf("IOP: open(\"%s\") (PC=%08x)\n", mname, mipsinfo.i);
-					#endif
-
-					filedata[slot2use] = malloc(6*1024*1024);
-					filesize[slot2use] = psf2_load_file(mname, filedata[slot2use], 6*1024*1024);
-					filepos[slot2use] = 0;
-					filestat[slot2use] = 1;
-
-					if (filesize[slot2use] == 0xffffffff)
-					{
-						mipsinfo.i = filesize[slot2use];
-					}
-					else
-					{
-						mipsinfo.i = slot2use;
-					}
-				}
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 5:	// close
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: close(%d) (PC=%08x)\n", a0, mipsinfo.i);
-				#endif
-				free(filedata[a0]);
-				filedata[a0] = (uint8_t *)NULL;
-				filepos[a0] = 0;
-				filesize[a0] = 0;
-				filestat[a0] = 0;
-				break;
-
-			case 6:	// read
-				#if DEBUG_HLE_IOP
-				printf("IOP: read(%x %x %d) [pos %d size %d]\n", a0, a1, a2, filepos[a0], filesize[a0]);
-				#endif
-
-				if (filepos[a0] >= filesize[a0])
-				{
-					mipsinfo.i = 0;
-				}
-				else
-				{
-					uint8_t *rp;
-
-					if ((filepos[a0] + a2) > filesize[a0])
-					{
-						a2 = filesize[a0] - filepos[a0];
-					}
-
-					rp = (uint8_t *)psx_ram;
-					rp += (a1 & 0x1fffff);
-					memcpy(rp, &filedata[a0][filepos[a0]], a2);
-
-					filepos[a0] += a2;
-					mipsinfo.i = a2;
-				}
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 8:	// lseek
-				#if DEBUG_HLE_IOP
-				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-				printf("IOP: lseek(%d, %d, %s) (PC=%08x)\n", a0, a1, seek_types[a2], mipsinfo.i);
-				#endif
-
-				switch (a2)
-				{
-					case 0:	// SEEK_SET
-						if (a1 <= filesize[a0])
-						{
-							filepos[a0] = a1;
-						}
-						break;
-					case 1:	// SEEK_CUR
-						if ((a1 + filepos[a0]) < filesize[a0])
-						{
-							filepos[a0] += a1;
-						}
-						break;
-					case 2:	// SEEK_END
-						filepos[a0] = filesize[a0] - a1;
-						break;
-				}
-
-				mipsinfo.i = filepos[a0];
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 20:	// AddDrv
-				#if DEBUG_HLE_IOP
-				printf("IOP: AddDrv(%x)\n", a0);
-				#endif
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			case 21:	// DelDrv
-				#if DEBUG_HLE_IOP
-				printf("IOP: DelDrv(%x)\n", a0);
-				#endif
-
-				mipsinfo.i = 0;
-				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
-				break;
-
-			default:
-				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-		}
-	}
-	else
-	{
-		int lib;
-
-		if (iNumLibs > 0)
-		{
-			for (lib = 0; lib < iNumLibs; lib++)
-			{
-				if (!strcmp(name, reglibs[lib].name))
-				{
-					#if DEBUG_HLE_IOP
-					uint32_t PC;
-
-					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
-					PC = mipsinfo.i;
-					#endif
-
-					// zap the delay slot handling
-					mipsinfo.i = 0;
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
-					mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
-
-					mipsinfo.i = LE32(psx_ram[(reglibs[lib].dispatch/4) + callnum]);
-
-					// (NOTE: we get called in the delay slot!)
-					#if DEBUG_HLE_IOP
-					printf("IOP: Calling %s (%d) service %d => %08x (parms %08x %08x %08x %08x) (PC=%x)\n",
-							 reglibs[lib].name,
-							 lib,
-							 callnum,
-							 (uint32_t)mipsinfo.i,
-							 a0, a1, a2, a3, PC);
-					#endif
-
-					#if 0
-					if (!strcmp(reglibs[lib].name, "ssd"))
-					{
-						if (callnum == 37)
-						{
-							psxcpu_verbose = 4096;
-						}
-					}
-					#endif
-
-					mipsinfo.i -= 4;
-					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
-
-					return;
-				}
-			}
-		}
-
-		printf("IOP: Unhandled service %d for module %s\n", callnum, name);
-	}
-}
-
diff --git a/src/psf/psx_hw.cc b/src/psf/psx_hw.cc
new file mode 100644
index 000000000000..94de88d6fb8d
--- /dev/null
+++ b/src/psf/psx_hw.cc
@@ -0,0 +1,3542 @@
+/*
+	Audio Overload SDK - PSX and IOP hardware emulation
+
+	Copyright (c) 2007 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+    psx_hw.c - Minimal PSX/IOP hardware glue/emulation/whatever
+
+    supported: main RAM (2 MB, mirrored to fill an 8 MB space like on real HW)
+               DMA channel 4 (SPURAM) in both directions (including completion IRQ)
+	       VBL IRQ
+	       Root counters 2 and 3 including completion events and IRQs
+	       Some BIOS services including exception handling (via HLE)
+	       HLE emulation of IOP operating system, including multithreading
+	       SPU(2), SPU(2)RAM (via PEOpS)
+
+
+
+    Special notes:
+    PSF1
+    	- Chocobo's Dungeon 2 contains an illegal code sequence (patched)
+
+    PSF2
+	- Shadow Hearts assumes that the wave buffer alloc will go to 0x80060000 and the sequence buffer to 0x80170000.
+	  Our memory management doesn't work out that way, so we have to (wait for it) cheese it.
+*/
+
+#include <stdio.h>
+
+#include "ao.h"
+#include "cpuintrf.h"
+#include "psx.h"
+
+#define DEBUG_HLE_BIOS	(0)		// debug PS1 HLE BIOS
+#define DEBUG_SPU	(0)		// debug PS1 SPU read/write
+#define DEBUG_SPU2	(0)		// debug PS2 SPU read/write
+#define DEBUG_HLE_IOP	(0)		// debug PS2 IOP OS calls
+#define DEBUG_UNK_RW	(0)		// debug unknown reads/writes
+#define DEBUG_THREADING (0)		// debug PS2 IOP threading
+
+#define LE32(x) FROM_LE32(x)
+
+extern void mips_get_info(uint32_t state, union cpuinfo *info);
+extern void mips_set_info(uint32_t state, union cpuinfo *info);
+extern int psxcpu_verbose;
+extern uint16_t SPUreadRegister(uint32_t reg);
+extern void SPUwriteRegister(uint32_t reg, uint16_t val);
+extern void SPUwriteDMAMem(uint32_t usPSXMem,int iSize);
+extern void SPUreadDMAMem(uint32_t usPSXMem,int iSize);
+extern void mips_shorten_frame(void);
+extern int mips_execute( int cycles );
+extern uint32_t psf2_load_file(const char *file, uint8_t *buf, uint32_t buflen);
+extern uint32_t psf2_load_elf(uint8_t *start, uint32_t len);
+void psx_hw_runcounters(void);
+int mips_get_icount(void);
+void mips_set_icount(int count);
+
+extern int psf_refresh;
+
+// SPU2
+extern void SPU2write(unsigned long reg, unsigned short val);
+extern unsigned short SPU2read(unsigned long reg);
+extern void SPU2readDMA4Mem(uint32_t usPSXMem,int iSize);
+extern void SPU2writeDMA4Mem(uint32_t usPSXMem,int iSize);
+extern void SPU2readDMA7Mem(uint32_t usPSXMem,int iSize);
+extern void SPU2writeDMA7Mem(uint32_t usPSXMem,int iSize);
+extern void SPU2interruptDMA4(void);
+extern void SPU2interruptDMA7(void);
+
+#define MAX_FILE_SLOTS	(32)
+
+static volatile int softcall_target = 0;
+static int filestat[MAX_FILE_SLOTS];
+static uint8_t *filedata[MAX_FILE_SLOTS];
+static uint32_t filesize[MAX_FILE_SLOTS], filepos[MAX_FILE_SLOTS];
+uint32_t psf2_get_loadaddr(void);
+void psf2_set_loadaddr(uint32_t addr);
+static void call_irq_routine(uint32_t routine, uint32_t parameter);
+static int intr_susp = 0;
+
+static uint64_t sys_time;
+static int timerexp = 0;
+
+typedef struct
+{
+	char name[10];
+	uint32_t dispatch;
+} ExternLibEntries;
+
+static int32_t iNumLibs;
+static ExternLibEntries	reglibs[32];
+
+typedef struct
+{
+	uint32_t type;
+	uint32_t value;
+	uint32_t param;
+	int    inUse;
+} EventFlag;
+
+static int32_t iNumFlags;
+static EventFlag evflags[32];
+
+typedef struct
+{
+	uint32_t attr;
+	uint32_t option;
+	int32_t init;
+	int32_t current;
+	int32_t max;
+	int32_t threadsWaiting;
+	int32_t inuse;
+} Semaphore;
+
+#define SEMA_MAX	(64)
+
+static int32_t iNumSema;
+static Semaphore semaphores[SEMA_MAX];
+
+// thread states
+enum
+{
+	TS_RUNNING = 0,		// now running
+	TS_READY,		// ready to run
+	TS_WAITEVFLAG,		// waiting on an event flag
+	TS_WAITSEMA,		// waiting on a semaphore
+	TS_WAITDELAY,		// waiting on a time delay
+	TS_SLEEPING,		// sleeping
+	TS_CREATED,		// newly created, hasn't run yet
+
+	TS_MAXSTATE
+};
+
+typedef struct
+{
+	int32_t  iState;		// state of thread
+
+	uint32_t flags;		// flags
+	uint32_t routine;		// start of code for the thread
+	uint32_t stackloc;	// stack location in IOP RAM
+	uint32_t stacksize;	// stack size
+	uint32_t refCon;		// user value passed in at CreateThread time
+
+	uint32_t waitparm;	// what we're waiting on if in one the TS_WAIT* states
+
+	uint32_t save_regs[37];	// CPU registers belonging to this thread
+} Thread;
+
+static int32_t iNumThreads, iCurThread;
+static Thread threads[32];
+
+#if DEBUG_THREADING
+static char *_ThreadStateNames[TS_MAXSTATE] = { "RUNNING", "READY", "WAITEVFLAG", "WAITSEMA", "WAITDELAY", "SLEEPING", "CREATED" };
+#endif
+
+#if DEBUG_HLE_IOP
+static char *seek_types[3] = { "SEEK_SET", "SEEK_CUR", "SEEK_END" };
+#endif
+
+typedef struct
+{
+	int32_t  iActive;
+	uint32_t count;
+	uint32_t target;
+	uint32_t source;
+	uint32_t prescale;
+	uint32_t handler;
+	uint32_t hparam;
+	uint32_t mode;
+} IOPTimer;
+
+static IOPTimer iop_timers[8];
+static int32_t iNumTimers;
+
+typedef struct
+{
+	uint32_t count;
+	uint32_t mode;
+	uint32_t target;
+	uint32_t sysclock;
+	uint32_t interrupt;
+} Counter;
+
+static Counter root_cnts[4];	// 4 of the bastards
+
+#define CLOCK_DIV	(8)	// 33 MHz / this = what we run the R3000 at to keep the CPU usage not insane
+
+// counter modes
+#define RC_EN		(0x0001)	// halt
+#define RC_RESET	(0x0008)	// automatically wrap
+#define RC_IQ1		(0x0010)	// IRQ when target reached
+#define RC_IQ2		(0x0040)	// IRQ when target reached (pSX treats same as IQ1?)
+#define RC_CLC		(0x0100)	// counter uses direct system clock
+#define RC_DIV8		(0x0200)	// (counter 2 only) system clock/8
+
+typedef struct
+{
+	uint32_t desc;
+	int32_t status;
+	int32_t mode;
+	uint32_t fhandler;
+} EvtCtrlBlk[32];
+
+static EvtCtrlBlk *Event;
+static EvtCtrlBlk *CounterEvent;
+
+// Sony event states
+#define EvStUNUSED	0x0000
+#define EvStWAIT	0x1000
+#define EvStACTIVE	0x2000
+#define EvStALREADY 	0x4000
+
+// Sony event modes
+#define EvMdINTR	0x1000
+#define EvMdNOINTR	0x2000
+
+// PSX main RAM
+uint32_t psx_ram[(2*1024*1024)/4];
+uint32_t psx_scratch[0x400];
+// backup image to restart songs
+uint32_t initial_ram[(2*1024*1024)/4];
+uint32_t initial_scratch[0x400];
+
+static uint32_t spu_delay, dma_icr, irq_data, irq_mask, dma_timer, WAI;
+static uint32_t dma4_madr, dma4_bcr, dma4_chcr, dma4_delay;
+static uint32_t dma7_madr, dma7_bcr, dma7_chcr, dma7_delay;
+static uint32_t dma4_cb, dma7_cb, dma4_fval, dma4_flag, dma7_fval, dma7_flag;
+static uint32_t irq9_cb, irq9_fval, irq9_flag;
+
+// take a snapshot of the CPU state for a thread
+static void FreezeThread(int32_t iThread, int flag)
+{
+	int i;
+	union cpuinfo mipsinfo;
+
+	#if DEBUG_THREADING
+//	printf("IOP: FreezeThread(%d)\n", iThread);
+	#endif
+
+	for (i = 0; i < 32; i++)
+	{
+		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
+		threads[iThread].save_regs[i] = mipsinfo.i;
+	}
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+	threads[iThread].save_regs[32] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+	threads[iThread].save_regs[33] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
+	threads[iThread].save_regs[35] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
+	threads[iThread].save_regs[36] = mipsinfo.i;
+
+
+	// if a thread is freezing itself due to a IOP syscall, we must save the RA as the PC
+	// to come back to or else the syscall will recurse
+	if (flag)
+	{
+		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+	}
+	else
+	{
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+	}
+	threads[iThread].save_regs[34] = mipsinfo.i;
+
+	#if DEBUG_THREADING
+	{
+		char buffer[256];
+
+		DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]);
+
+		printf("IOP: FreezeThread(%d) => %08x  [%s]\n", iThread, threads[iThread].save_regs[34], buffer);
+	}
+	#endif
+
+	// if thread was running, now it's ready
+	if (threads[iThread].iState == TS_RUNNING)
+	{
+		threads[iThread].iState = TS_READY;
+	}
+}
+
+// restore the CPU state from a thread's snapshot
+static void ThawThread(int32_t iThread)
+{
+	int i;
+	union cpuinfo mipsinfo;
+
+	// the first time a thread is put on the CPU,
+	// some special setup is required
+	if (threads[iThread].iState == TS_CREATED)
+	{
+		// PC = starting routine
+		threads[iThread].save_regs[34] = threads[iThread].routine-4;	// compensate for weird delay slot effects
+		// SP = thread's stack area
+		threads[iThread].save_regs[29] = (threads[iThread].stackloc + threads[iThread].stacksize) - 16;
+		threads[iThread].save_regs[29] |= 0x80000000;
+
+		threads[iThread].save_regs[35] = threads[iThread].save_regs[36] = 0;
+
+		#if DEBUG_THREADING
+//		printf("IOP: Initial setup for thread %d => PC %x SP %x\n", iThread, threads[iThread].save_regs[34]+4, threads[iThread].save_regs[29]);
+		#endif
+	}
+
+	#if DEBUG_THREADING
+	{
+		char buffer[256];
+
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+		DasmMIPS(buffer, mipsinfo.i, &psx_ram[(mipsinfo.i & 0x7fffffff)/4]);
+
+		printf("IOP: ThawThread(%d) => %08x  [%s] (wake %d)\n", iThread, threads[iThread].save_regs[34], buffer, wakecount);
+	}
+	#endif
+
+	for (i = 0; i < 32; i++)
+	{
+		mipsinfo.i = threads[iThread].save_regs[i];
+		mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
+	}
+
+	mipsinfo.i = threads[iThread].save_regs[32];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+	mipsinfo.i = threads[iThread].save_regs[33];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+	mipsinfo.i = threads[iThread].save_regs[34];
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+	mipsinfo.i = threads[iThread].save_regs[35];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
+	mipsinfo.i = threads[iThread].save_regs[36];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
+
+	threads[iThread].iState = TS_RUNNING;
+}
+
+// find a new thread to run
+static void ps2_reschedule(void)
+{
+	int i, starti, iNextThread;
+
+	iNextThread = -1;
+
+	// see if any thread other than the current one is ready to run
+	i = iCurThread+1;
+	if (i >= iNumThreads)
+	{
+		i = 0;
+	}
+
+	starti = i;
+
+	// starting with the next thread after this one,
+	// see who wants to run
+	while (i < iNumThreads)
+	{
+		if (i != iCurThread)
+		{
+			if (threads[i].iState == TS_READY)
+			{
+			  	iNextThread = i;
+				break;
+			}
+		}
+
+		i++;
+	}
+
+	// if we started above thread 0 and didn't pick one,
+	// go around and try from zero
+	if ((starti > 0) && (iNextThread == -1))
+	{
+		for (i = 0; i < iNumThreads; i++)
+		{
+			if (i != iCurThread)
+			{
+				if (threads[i].iState == TS_READY)
+				{
+				  	iNextThread = i;
+					break;
+				}
+			}
+		}
+	}
+
+	if (iNextThread != -1)
+	{
+		#if DEBUG_THREADING
+		for (i = 0; i < iNumThreads; i++)
+		{
+			printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]);
+		}
+		#endif
+
+		if (iCurThread != -1)
+		{
+			FreezeThread(iCurThread, 0);
+		}
+		ThawThread(iNextThread);
+		iCurThread = iNextThread;
+		threads[iCurThread].iState = TS_RUNNING;
+	}
+	else
+	{
+		// no thread to switch to, is the current one still running?
+		if (iCurThread != -1)
+		{
+			if (threads[iCurThread].iState != TS_RUNNING)
+			{
+				#if DEBUG_THREADING
+				printf("IOP: no threads to run\n");
+
+				for (i = 0; i < iNumThreads; i++)
+				{
+					printf("Thread %02d: %s\n", i, _ThreadStateNames[threads[i].iState]);
+				}
+				#endif
+
+				mips_shorten_frame();	// kill the CPU
+				iCurThread = -1;	// no threads are active
+			}
+		}
+		else
+		{
+			mips_shorten_frame();	// kill the CPU
+			iCurThread = -1;	// no threads are active
+		}
+	}
+}
+
+static void psx_irq_update(void)
+{
+	union cpuinfo mipsinfo;
+
+	if ((irq_data & irq_mask) != 0)
+	{	// assert the line
+		WAI = 0;
+		mipsinfo.i = ASSERT_LINE;
+		mips_set_info( CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo );
+	}
+	else
+	{
+		// clear the line
+		mipsinfo.i = CLEAR_LINE;
+		mips_set_info( CPUINFO_INT_INPUT_STATE + MIPS_IRQ0, &mipsinfo );
+	}
+}
+
+void psx_irq_set(uint32_t irq)
+{
+	irq_data |= irq;
+
+	psx_irq_update();
+}
+
+static uint32_t gpu_stat = 0;
+
+uint32_t psx_hw_read(offs_t offset, uint32_t mem_mask)
+{
+	if (offset >= 0x00000000 && offset <= 0x007fffff)
+	{
+		offset &= 0x1fffff;
+		return LE32(psx_ram[offset>>2]);
+	}
+
+	if (offset >= 0x80000000 && offset <= 0x807fffff)
+	{
+		offset &= 0x1fffff;
+		return LE32(psx_ram[offset>>2]);
+	}
+
+	if (offset == 0xbfc00180 || offset == 0xbfc00184)	// exception vector
+	{
+		return FUNCT_HLECALL;
+	}
+
+	if (offset == 0x1f801014)
+	{
+		return spu_delay;
+	}
+
+	if (offset == 0xbf801014)
+	{
+		return spu_delay;
+	}
+
+	if (offset == 0x1f801814)
+	{
+		gpu_stat ^= 0xffffffff;
+		return gpu_stat;
+	}
+
+	if (offset >= 0x1f801c00 && offset <= 0x1f801dff)
+	{
+		if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00))
+		{
+			#if DEBUG_SPU
+			printf("SPU: readRegister(%x)\n", offset);
+			#endif
+			return SPUreadRegister(offset) & ~mem_mask;
+		}
+		else if (mem_mask == 0x0000ffff)
+		{
+			#if DEBUG_SPU
+			printf("SPU: readRegister(%x)\n", offset);
+			#endif
+			return SPUreadRegister(offset)<<16;
+		}
+		else printf("SPU: read unknown mask %08x\n", mem_mask);
+	}
+
+	if (offset >= 0xbf900000 && offset <= 0xbf9007ff)
+	{
+		if ((mem_mask == 0xffff0000) || (mem_mask == 0xffffff00))
+		{
+			return SPU2read(offset) & ~mem_mask;
+		}
+		else if (mem_mask == 0x0000ffff)
+		{
+			return SPU2read(offset)<<16;
+		}
+		else if (mem_mask == 0)
+		{
+			return SPU2read(offset) | SPU2read(offset+2)<<16;
+		}
+		else printf("SPU2: read unknown mask %08x\n", mem_mask);
+	}
+
+	if (offset >= 0x1f801100 && offset <= 0x1f801128)
+	{
+		int cnt = (offset>>4) & 0xf;
+
+		switch (offset & 0xf)
+		{
+			case 0:
+//				printf("RC: read counter %d count = %x\n", cnt, root_cnts[cnt].count);
+				return root_cnts[cnt].count;
+				break;
+			case 4:
+//				printf("RC: read counter %d mode\n", cnt);
+				return root_cnts[cnt].mode;
+				break;
+			case 8:
+//				printf("RC: read counter %d target\n", cnt);
+				return root_cnts[cnt].target;
+				break;
+		}
+
+		return 0;
+	}
+
+	if (offset == 0x1f8010f4)
+	{
+		return dma_icr;
+	}
+	else if (offset == 0x1f801070)
+	{
+//		printf("Read IRQ_data %x (mask %08x)\n", irq_data, mem_mask);
+		return irq_data;
+	}
+	else if (offset == 0x1f801074)
+	{
+		return irq_mask;
+	}
+
+/*	if (offset == 0xbf801508)
+	{
+		return dma7_bcr;
+	}*/
+
+	if (offset == 0xbf920344)
+	{
+		return 0x80808080;
+	}
+
+	#if DEBUG_UNK_RW
+	{
+		union cpuinfo mipsinfo;
+
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+		printf("Unknown read: %08x, mask %08x (PC=%x)\n", offset&~3, mem_mask, mipsinfo.i);
+	}
+	#endif
+	return 0;
+}
+
+static void psx_dma4(uint32_t madr, uint32_t bcr, uint32_t chcr)
+{
+	if (chcr == 0x01000201)	// cpu to SPU
+	{
+		#if DEBUG_SPU
+		printf("DMA4: RAM %08x to SPU\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 2;
+		SPUwriteDMAMem(madr&0x1fffff, bcr);
+	}
+	else
+	{
+		#if DEBUG_SPU
+		printf("DMA4: SPU to RAM %08x\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 2;
+		SPUreadDMAMem(madr&0x1fffff, bcr);
+	}
+}
+
+static void ps2_dma4(uint32_t madr, uint32_t bcr, uint32_t chcr)
+{
+	if (chcr == 0x01000201)	// cpu to SPU2
+	{
+		#if DEBUG_HLE_IOP
+		printf("DMA4: RAM %08x to SPU2\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
+		SPU2writeDMA4Mem(madr&0x1fffff, bcr);
+	}
+	else
+	{
+		#if DEBUG_HLE_IOP
+		printf("DMA4: SPU2 to RAM %08x\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
+		SPU2readDMA4Mem(madr&0x1fffff, bcr);
+	}
+
+	dma4_delay = 80;
+}
+
+static void ps2_dma7(uint32_t madr, uint32_t bcr, uint32_t chcr)
+{
+	if ((chcr == 0x01000201) || (chcr == 0x00100010) || (chcr == 0x000f0010) || (chcr == 0x00010010))	// cpu to SPU2
+	{
+		#if DEBUG_HLE_IOP
+		printf("DMA7: RAM %08x to SPU2\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
+		SPU2writeDMA7Mem(madr&0x1fffff, bcr);
+	}
+	else
+	{
+		#if DEBUG_HLE_IOP
+		printf("DMA7: SPU2 to RAM %08x\n", madr);
+		#endif
+		bcr = (bcr>>16) * (bcr & 0xffff) * 4;
+//		SPU2readDMA7Mem(madr&0x1fffff, bcr);
+	}
+
+	dma7_delay = 80;
+}
+
+void psx_hw_write(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+	union cpuinfo mipsinfo;
+
+	if (offset >= 0x00000000 && offset <= 0x007fffff)
+	{
+		offset &= 0x1fffff;
+//		if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset);
+
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+
+		psx_ram[offset>>2] &= LE32(mem_mask);
+		psx_ram[offset>>2] |= LE32(data);
+		return;
+	}
+
+	if (offset >= 0x80000000 && offset <= 0x807fffff)
+	{
+		offset &= 0x1fffff;
+//		if (offset < 0x10000) printf("Write %x to kernel @ %x\n", data, offset);
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+		psx_ram[offset>>2] &= LE32(mem_mask);
+		psx_ram[offset>>2] |= LE32(data);
+		return;
+	}
+
+	if (offset == 0x1f801014 || offset == 0xbf801014)
+	{
+		spu_delay &= mem_mask;
+		spu_delay |= data;
+		return;
+	}
+
+	if (offset >= 0x1f801c00 && offset <= 0x1f801dff)
+	{
+		if (mem_mask == 0xffff0000)
+		{
+			SPUwriteRegister(offset, data);
+			return;
+		}
+		else if (mem_mask == 0x0000ffff)
+		{
+			SPUwriteRegister(offset, data>>16);
+			return;
+		}
+		else printf("SPU: write unknown mask %08x\n", mem_mask);
+	}
+
+	if (offset >= 0xbf900000 && offset <= 0xbf9007ff)
+	{
+		if (mem_mask == 0xffff0000)
+		{
+			SPU2write(offset, data);
+			return;
+		}
+		else if (mem_mask == 0x0000ffff)
+		{
+			SPU2write(offset, data>>16);
+			return;
+		}
+		else if (mem_mask == 0)
+		{
+			SPU2write(offset, data & 0xffff);
+			SPU2write(offset+2, data>>16);
+			return;
+		}
+		else printf("SPU2: write unknown mask %08x\n", mem_mask);
+	}
+
+	if (offset >= 0x1f801100 && offset <= 0x1f801128)
+	{
+		int cnt = (offset>>4) & 0xf;
+
+		switch (offset & 0xf)
+		{
+			case 0:
+				root_cnts[cnt].count = data;
+//				printf("RC: counter %d count = %x\n", cnt, data);
+				break;
+			case 4:
+				root_cnts[cnt].mode = data;
+//				printf("RC: counter %d mode = %x\n", cnt, data);
+				break;
+			case 8:
+				root_cnts[cnt].target = data;
+//				printf("RC: counter %d target = %x\n", cnt, data);
+				break;
+		}
+
+		return;
+	}
+
+	// DMA4
+	if (offset == 0x1f8010c0)
+	{
+		dma4_madr = data;
+		return;
+	}
+	else if (offset == 0x1f8010c4)
+	{
+		dma4_bcr = data;
+		return;
+	}
+	else if (offset == 0x1f8010c8)
+	{
+		dma4_chcr = data;
+		psx_dma4(dma4_madr, dma4_bcr, dma4_chcr);
+
+		if (dma_icr & (1 << (16+4)))
+		{
+			dma_timer = 3;
+		}
+		return;
+	}
+	else if (offset == 0x1f8010f4)
+	{
+		dma_icr = ( dma_icr & mem_mask ) |
+			  ( ~mem_mask & 0x80000000 & dma_icr) |
+			  ( ~data & ~mem_mask & 0x7f000000 & dma_icr) |
+			  ( data & ~mem_mask & 0x00ffffff);
+
+		if ((dma_icr & 0x7f000000) != 0)
+		{
+			dma_icr &= ~0x80000000;
+		}
+
+		return;
+	}
+	else if (offset == 0x1f801070)
+	{
+		irq_data = (irq_data & mem_mask) | (irq_data & irq_mask & data);
+		psx_irq_update();
+		return;
+	}
+	else if (offset == 0x1f801074)
+	{
+		irq_mask &= mem_mask;
+		irq_mask |= data;
+		psx_irq_update();
+		return;
+	}
+
+	// PS2 DMA4
+	if (offset == 0xbf8010c0)
+	{
+		dma4_madr = data;
+		return;
+	}
+	else if (offset == 0xbf8010c8)
+	{
+		dma4_chcr = data;
+		ps2_dma4(dma4_madr, dma4_bcr, dma4_chcr);
+
+		if (dma_icr & (1 << (16+4)))
+		{
+			dma_timer = 3;
+		}
+		return;
+	}
+
+	if (offset == 0xbf8010c4 || offset == 0xbf8010c6)
+	{
+		dma4_bcr &= mem_mask;
+		dma4_bcr |= data;
+		return;
+	}
+
+	// PS2 DMA7
+	if (offset == 0xbf801500)
+	{
+		dma7_madr = data;
+		return;
+	}
+	else if (offset == 0xbf801504)
+	{
+		dma7_chcr = data;
+		ps2_dma7(dma7_madr, dma7_bcr, dma7_chcr);
+		return;
+	}
+
+	if (offset == 0xbf801508 || offset == 0xbf80150a)
+	{
+		dma7_bcr &= mem_mask;
+		dma7_bcr |= data;
+		return;
+	}
+
+	#if DEBUG_UNK_RW
+	{
+		union cpuinfo mipsinfo;
+
+		mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+		printf("Unknown write: %08x to %08x, mask %08x (PC=%x)\n", data, offset&~3, mem_mask, mipsinfo.i);
+	}
+	#endif
+}
+
+// called per sample, 1/44100th of a second (768 clock cycles)
+void psx_hw_slice(void)
+{
+	psx_hw_runcounters();
+
+	if (!WAI)
+		mips_execute(768/CLOCK_DIV);
+
+	if (dma_timer)
+	{
+		dma_timer--;
+		if (dma_timer == 0)
+		{
+			dma_icr |= (1 << (24+4));
+			psx_irq_set(0x0008);
+		}
+	}
+}
+
+void ps2_hw_slice(void)
+{
+	int i = 0;
+
+	timerexp = 0;
+	psx_hw_runcounters();
+
+	if (iCurThread != -1)
+	{
+		mips_execute(836/CLOCK_DIV);
+	}
+	else	// no thread, don't run CPU, just update counters
+	{
+		if (timerexp)
+		{
+			ps2_reschedule();
+
+			if (iCurThread != -1)
+			{
+				mips_execute((836/CLOCK_DIV)-i);
+				i = (836/CLOCK_DIV);
+			}
+		}
+	}
+}
+
+static int fcnt = 0;
+
+void psx_hw_frame(void)
+{
+	if (psf_refresh == 50)
+	{
+		fcnt++;;
+
+		if (fcnt < 6)
+		{
+			psx_irq_set(1);
+		}
+		else
+		{
+			fcnt = 0;
+		}
+	}
+	else	// NTSC
+	{
+		psx_irq_set(1);
+	}
+}
+
+void ps2_hw_frame(void)
+{
+	ps2_reschedule();
+}
+
+// BIOS HLE
+
+// heap block struct offsets
+enum
+{
+	BLK_STAT = 0,
+	BLK_SIZE = 4,
+	BLK_FD = 8,
+	BLK_BK = 12
+};
+
+static uint32_t heap_addr, entry_int = 0;
+
+extern uint32_t mips_get_cause(void);
+extern uint32_t mips_get_status(void);
+extern void mips_set_status(uint32_t status);
+extern uint32_t mips_get_ePC(void);
+
+static uint32_t irq_regs[37];
+
+static int irq_mutex = 0;
+
+static void call_irq_routine(uint32_t routine, uint32_t parameter)
+{
+	int j, oldICount;
+	union cpuinfo mipsinfo;
+
+	if (!irq_mutex)
+	{
+		irq_mutex = 1;
+	}
+	else
+	{
+		printf("IOP: ERROR!  IRQ reentry!\n");
+		return;
+	}
+
+	// save regs for IRQ
+	for (j = 0; j < 32; j++)
+	{
+		mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo);
+		irq_regs[j] = mipsinfo.i;
+	}
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+	irq_regs[32] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+	irq_regs[33] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_PC, &mipsinfo);
+	irq_regs[34] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
+	irq_regs[35] = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
+	irq_regs[36] = mipsinfo.i;
+
+	// PC = timer handler routine
+	mipsinfo.i = routine;
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+	// parameter in a0
+	mipsinfo.i = parameter;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+
+	// RA = a trap address we can set
+	mipsinfo.i = 0x80001000;
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+
+	// make sure we're set
+	psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
+
+	softcall_target = 0;
+	oldICount = mips_get_icount();
+	while (!softcall_target)
+	{
+		mips_execute(10);
+	}
+	mips_set_icount(oldICount);
+
+	// restore IRQ regs
+	for (j = 0; j < 32; j++)
+	{
+		mipsinfo.i = irq_regs[j];
+		mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + j, &mipsinfo);
+	}
+
+	mipsinfo.i = irq_regs[32];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+	mipsinfo.i = irq_regs[33];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+	mipsinfo.i = irq_regs[34];
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+	mipsinfo.i = irq_regs[35];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
+	mipsinfo.i = irq_regs[36];
+	mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
+
+	irq_mutex = 0;
+}
+
+void psx_bios_exception(uint32_t pc)
+{
+	uint32_t a0, status;
+	union cpuinfo mipsinfo;
+	int i, oldICount;
+
+//	printf("bios_exception: cause %x\n", mips_get_cause() & 0x3c);
+
+	// get a0
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+	a0 = mipsinfo.i;
+
+	switch (mips_get_cause() & 0x3c)
+	{
+		case 0:	// IRQ
+//			printf("IRQ: %x, mask %x\n", irq_data, irq_mask);
+			// save all regs
+			for (i = 0; i < 32; i++)
+			{
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
+				irq_regs[i] = mipsinfo.i;
+			}
+			mips_get_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+			irq_regs[32] = mipsinfo.i;
+			mips_get_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+			irq_regs[33] = mipsinfo.i;
+
+			// check BIOS-driven interrupts
+			if (irq_data & 1)	// VSync
+			{
+				if (CounterEvent[3][1].status == LE32(EvStACTIVE))
+				{
+					// run the handler
+					mipsinfo.i = LE32(CounterEvent[3][1].fhandler);
+//	       				printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC());
+//	       				printf("VBL running handler @ %x\n", mipsinfo.i);
+					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+					mipsinfo.i = 0x80001000;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+
+					// make sure we're set
+					psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
+
+					softcall_target = 0;
+					oldICount = mips_get_icount();
+					while (!softcall_target)
+					{
+						mips_execute(10);
+					}
+					mips_set_icount(oldICount);
+
+//	       				printf("Exiting softcall handler\n");
+
+					irq_data &= ~1;		// clear the VBL IRQ if we handled it
+				}
+			}
+			else if (irq_data & 0x70)	// root counters
+			{
+				for (i = 0; i < 4; i++)
+				{
+					if (irq_data & (1 << (i+4)))
+					{
+						if (CounterEvent[i][1].status == LE32(EvStACTIVE))
+						{
+							// run the handler
+							mipsinfo.i = LE32(CounterEvent[i][1].fhandler);
+//							printf("Cause = %x, ePC = %x\n", mips_get_cause(), mips_get_ePC());
+//							printf("Counter %d running handler @ %x\n", i, mipsinfo.i);
+							mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+							mipsinfo.i = 0x80001000;
+							mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+
+							// make sure we're set
+							psx_ram[0x1000/4] = LE32(FUNCT_HLECALL);
+
+							softcall_target = 0;
+							oldICount = mips_get_icount();
+							while (!softcall_target)
+							{
+								mips_execute(10);
+							}
+							mips_set_icount(oldICount);
+
+//							printf("Exiting softcall handler\n");
+							irq_data &= ~(1 << (i+4));
+						}
+						else
+						{
+//							printf("CEvt %d not active\n", i);
+						}
+					}
+				}
+			}
+
+			if (entry_int)
+			{
+				psx_hw_write(0x1f801070, 0xffffffff, 0);
+
+				a0 = entry_int;
+
+//				printf("taking entry_int\n");
+
+				// RA (and PC)
+				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+0)/4]);
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+				// SP
+				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+4)/4]);
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
+				// FP
+				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+8)/4]);
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
+
+				// S0-S7 are next
+				for (i = 0; i < 8; i++)
+				{
+					mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+12+(i*4))/4]);
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo);
+				}
+
+				// GP
+				mipsinfo.i = LE32(psx_ram[((a0&0x1fffff)+44)/4]);
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
+
+				// v0 = 1
+				mipsinfo.i = 1;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+			}
+			else
+			{
+				psx_hw_write(0x1f801070, 0, 0xffff0000);
+
+				// note: the entry_int won't be bailing us out here, so do it ourselves
+				for (i = 0; i < 32; i++)
+				{
+					mipsinfo.i = irq_regs[i];
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
+				}
+
+				mipsinfo.i = irq_regs[32];
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+				mipsinfo.i = irq_regs[33];
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+				mipsinfo.i = mips_get_ePC();
+				mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+				status = mips_get_status();
+				status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
+				mips_set_status(status);
+			}
+			break;
+
+		case 0x20:	// syscall
+			// syscall always farks with the status, so get it now
+			status = mips_get_status();
+
+			switch (a0)
+			{
+				case 1: // EnterCritical
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: EnterCritical\n");
+					#endif
+					status &= ~0x0404;
+					break;
+
+				case 2:	// ExitCritical
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: ExitCritical\n");
+					#endif
+					status |= 0x0404;
+					break;
+
+				default:
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: Unknown syscall %x\n", a0);
+					#endif
+					break;
+			}
+
+			// PC = ePC + 4
+			mipsinfo.i = mips_get_ePC() + 4;
+			mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+			// and update the status accordingly
+			status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
+			mips_set_status(status);
+			break;
+
+		default:
+			#if DEBUG_HLE_BIOS
+			printf("HLEBIOS: Unknown exception %x\n", mips_get_cause());
+			#endif
+			break;
+	}
+}
+
+static uint32_t calc_ev(uint32_t a0)
+{
+	uint32_t ev;
+
+	ev = (a0 >> 24) & 0xf;
+	if (ev == 0xf)
+	{
+		ev = 0x5;
+	}
+	ev *= 32;
+	ev += (a0 & 0x1f);
+
+	return ev;
+}
+
+static uint32_t calc_spec(uint32_t a1)
+{
+	uint32_t spec = 0;
+	int i;
+
+	if (a1 == 0x301)
+	{
+		spec = 16;
+	}
+	else if (a1 == 0x302)
+	{
+		spec = 17;
+	}
+	else
+	{
+		for (i = 0; i < 16; i++)
+		{
+			if (a1 & (1<<i))
+			{
+				spec = i;
+				break;
+			}
+		}
+	}
+
+	return spec;
+}
+
+void psx_hw_init(void)
+{
+	timerexp = 0;
+
+	memset(filestat, 0, sizeof(filestat));
+	memset(filedata, 0, sizeof(filedata));
+
+	dma4_cb = dma7_cb = 0;
+
+	sys_time = 0;
+
+	// clear registered libraries table
+	memset(reglibs, 0, sizeof(reglibs));
+	iNumLibs = 0;
+
+	memset(evflags, 0, sizeof(evflags));
+	iNumFlags = 0;
+
+	memset(threads, 0, sizeof(threads));
+	iNumThreads = 1;	// we always have at least one thread
+
+	memset(semaphores, 0, sizeof(semaphores));
+	iNumSema = 0;
+
+	// set the initial thread to "RUNNING"
+	threads[0].iState = TS_RUNNING;
+	iCurThread = 0;
+
+	memset(iop_timers, 0, sizeof(iop_timers));
+	iNumTimers = 0;
+
+	// set PS1 BIOS HLE breakpoints
+	psx_ram[0xa0/4] = LE32(FUNCT_HLECALL);
+	psx_ram[0xb0/4] = LE32(FUNCT_HLECALL);
+	psx_ram[0xc0/4] = LE32(FUNCT_HLECALL);
+
+	Event = (EvtCtrlBlk *)&psx_ram[0x1000/4];
+	CounterEvent = (Event + (32*2));
+
+	dma_icr = 0;
+	spu_delay = 0;
+	irq_data = 0;
+	irq_mask = 0;
+	softcall_target = 0;
+	gpu_stat = 0;
+	dma4_madr = dma4_bcr = dma4_chcr = 0;
+	heap_addr = 0;
+	entry_int = 0;
+
+	WAI = 0;
+
+	root_cnts[0].mode = RC_EN;
+	root_cnts[1].mode = RC_EN;
+	root_cnts[2].mode = RC_EN;
+	root_cnts[0].sysclock = 0;
+	root_cnts[1].sysclock = 0;
+	root_cnts[2].sysclock = 0;
+
+	root_cnts[3].mode = (RC_RESET | RC_IQ1 | RC_IQ2);
+	root_cnts[3].sysclock = 0;
+	root_cnts[3].target = 1;
+	root_cnts[3].interrupt = 1;
+}
+
+void psx_bios_hle(uint32_t pc)
+{
+	uint32_t subcall, status;
+	union cpuinfo mipsinfo;
+	uint32_t a0, a1, a2, a3;
+	int i;
+
+	if ((pc == 0) || (pc == 0x80000000))  	 	// IOP "null" state
+	{
+		#if DEBUG_HLE_IOP
+		printf("IOP 'null' state\n");
+		#endif
+//		ao_song_done = 1;
+		return;
+	}
+
+	if (pc == 0xbfc00180 || pc == 0xbfc00184)	// exception, not BIOS call
+	{
+		psx_bios_exception(pc);
+		return;
+	}
+
+	if (pc == 0x80001000)
+	{
+//		printf("hit softcall target\n");
+		softcall_target = 1;
+		return;
+	}
+
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R9, &mipsinfo);
+
+	subcall = mipsinfo.i & 0xff;
+
+	// most calls have a0/a1 as parameters, so prefetch them
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+	a0 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
+	a1 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo);
+	a2 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo);
+	a3 = mipsinfo.i;
+
+//	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+//	printf("HLEBIOS: return is %08x\n", mipsinfo.i);
+
+	switch (pc)
+	{
+		case 0xa0:	// a0 syscalls
+			switch (subcall)
+			{
+				case 0x13:	// setjmp
+					// RA
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					psx_ram[((a0&0x1fffff)+0)/4] = LE32(mipsinfo.i);
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: setjmp(%08x) => PC %08x\n", a0, mipsinfo.i);
+					#endif
+					// SP
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
+					psx_ram[((a0&0x1fffff)+4)/4] = LE32(mipsinfo.i);
+					// FP
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
+					psx_ram[((a0&0x1fffff)+8)/4] = LE32(mipsinfo.i);
+
+					// S0-S7 are next
+					for (i = 0; i < 8; i++)
+					{
+						mips_get_info(CPUINFO_INT_REGISTER + MIPS_R16 + i, &mipsinfo);
+						psx_ram[((a0&0x1fffff)+12+(i*4))/4] = LE32(mipsinfo.i);
+					}
+
+					// GP
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
+					psx_ram[((a0&0x1fffff)+44)/4] = LE32(mipsinfo.i);
+
+					// v0 = 0
+					mipsinfo.i = 0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					break;
+
+				case 0x18:	// strncmp
+					{
+						uint8_t *dst, *src;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: strncmp(%08x, %08x, %d)\n", a0, a1, a2);
+						#endif
+
+						dst = (uint8_t *)psx_ram;
+						src = (uint8_t *)psx_ram;
+						dst += (a0 & 0x1fffff);
+						src += (a1 & 0x1fffff);
+
+						// v0 = result
+						mipsinfo.i = strncmp((char *)dst, (char *)src, a2);
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x19:	// strcpy
+					{
+						uint8_t *dst, *src;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: strcpy(%08x, %08x)\n", a0, a1);
+						#endif
+
+						dst = (uint8_t *)psx_ram;
+						src = (uint8_t *)psx_ram;
+						dst += (a0 & 0x1fffff);
+						src += (a1 & 0x1fffff);
+
+						while (*src)
+						{
+							*dst = *src;
+							dst++;
+							src++;
+						}
+
+						// v0 = a0
+						mipsinfo.i = a0;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x28:	// bzero
+					{
+						uint8_t *dst;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: bzero(%08x, %08x)\n", a0, a1);
+						#endif
+
+						dst = (uint8_t *)psx_ram;
+						dst += (a0 & 0x1fffff);
+						memset(dst, 0, a1);
+					}
+					break;
+
+				case 0x2a:	// memcpy
+					{
+						uint8_t *dst, *src;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: memcpy(%08x, %08x, %08x)\n", a0, a1, a2);
+						#endif
+
+						dst = (uint8_t *)psx_ram;
+						src = (uint8_t *)psx_ram;
+						dst += (a0 & 0x1fffff);
+						src += (a1 & 0x1fffff);
+
+						while (a2)
+						{
+							*dst = *src;
+							dst++;
+							src++;
+							a2--;
+						}
+
+						// v0 = a0
+						mipsinfo.i = a0;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x2b:	// memset
+					{
+						uint8_t *dst;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: memset(%08x, %08x, %08x)\n", a0, a1, a2);
+						#endif
+
+						dst = (uint8_t *)psx_ram;
+						dst += (a0 & 0x1fffff);
+
+						while (a2)
+						{
+							*dst = a1;
+							dst++;
+							a2--;
+						}
+
+						// v0 = a0
+						mipsinfo.i = a0;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x2f:	// rand
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: rand\n");
+					#endif
+
+					// v0 = result
+					mipsinfo.i = 1 + (int)(32767.0*rand()/(RAND_MAX+1.0));
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					break;
+
+				case 0x30:	// srand
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: srand(%x)\n", a0);
+					#endif
+					srand(a0);
+					break;
+
+				case 0x33:	// malloc
+					{
+						uint32_t chunk, fd;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: malloc(%x)\n", a0);
+						#endif
+
+						chunk = heap_addr;
+
+						// find a free block that's big enough
+						while ((a0 > LE32(psx_ram[(chunk+BLK_SIZE)/4])) ||
+						       (LE32(psx_ram[(chunk+BLK_STAT)/4]) ==  1))
+						{
+							chunk = LE32(psx_ram[(chunk+BLK_FD)]);
+						}
+
+						// split free block
+						fd = chunk + 16 + a0;	// free block starts after block record and allocation size
+						psx_ram[(fd+BLK_STAT)/4] = psx_ram[(chunk+BLK_STAT)/4];
+						psx_ram[(fd+BLK_SIZE)/4] = LE32(LE32(psx_ram[(chunk+BLK_SIZE)/4]) - a0);
+						psx_ram[(fd+BLK_FD)/4] = psx_ram[(chunk+BLK_FD)/4];
+						psx_ram[(fd+BLK_BK)/4] = chunk;
+
+						psx_ram[(chunk+BLK_STAT)/4] = LE32(1);
+						psx_ram[(chunk+BLK_SIZE)/4] = LE32(a0);
+						psx_ram[(chunk+BLK_FD)/4] = LE32(fd);
+
+						mipsinfo.i = chunk + 16;
+						mipsinfo.i |= 0x80000000;
+						#if DEBUG_HLE_BIOS
+						printf("== %08x\n", mipsinfo.i);
+						#endif
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x39:	// InitHeap
+					// heap address in A0, length in A1
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: InitHeap(%08x, %08x)\n", a0, a1);
+					#endif
+
+					heap_addr = a0 & 0x3fffffff;
+
+					psx_ram[(heap_addr+BLK_STAT)/4] = LE32(0);
+					psx_ram[(heap_addr+BLK_FD)/4] = LE32(0);
+					psx_ram[(heap_addr+BLK_BK)/4] = LE32(0);
+
+					// if heap size out of range, clamp it
+					if (((a0 & 0x1fffff) + a1) >= 2*1024*1024)
+					{
+						psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(0x1ffffc - (a0 & 0x1fffff));
+					}
+					else
+					{
+						psx_ram[(heap_addr+BLK_SIZE)/4] = LE32(a1);
+					}
+					break;
+
+				case 0x3f:	// printf
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: printf(%08x) = %s\n", a0, &psx_ram[(a0&0x1fffff)/4]);
+					#endif
+					break;
+
+				case 0x72:	//__96_remove
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: __96_remove\n");
+					#endif
+					break;
+
+				default:
+					#if DEBUG_HLE_BIOS
+					printf("Unknown BIOS A0 call = %x\n", subcall);
+					#endif
+					break;
+			}
+			break;
+
+		case 0xb0:	// b0 syscalls
+			switch (subcall)
+			{
+				case 0x07:	// DeliverEvent
+					{
+						int ev, spec;
+
+
+						ev = calc_ev(a0);
+						spec = calc_spec(a1);
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: DeliverEvent(ev %d, spec %d)\n", ev, spec);
+						#endif
+
+						if (Event[ev][spec].status != LE32(EvStACTIVE))
+						{
+							#if DEBUG_HLE_BIOS
+							printf("event not active\n");
+							#endif
+							return;
+						}
+
+						// if interrupt mode, do the call
+						if (Event[ev][spec].mode == LE32(EvMdINTR))
+						{
+							#if DEBUG_HLE_BIOS
+							printf("INTR type, need to call handler %x\n", LE32(Event[ev][spec].fhandler));
+							#endif
+						}
+						else
+						{
+							Event[ev][spec].status = LE32(EvStALREADY);
+						}
+					}
+					break;
+
+				case 0x08:	// OpenEvent
+					{
+						int ev, spec;
+
+						ev = calc_ev(a0);
+						spec = calc_spec(a1);
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: OpenEvent(%08x, %08x, %08x, %08x) = ev %d spec %d\n", a0, a1, a2, a3, ev, spec);
+						if (ev >= 64 && ev <= 68)
+						{
+							printf("HLEBIOS: event %d maps to root counter %d\n", ev, ev-64);
+						}
+						#endif
+
+						Event[ev][spec].status = LE32(EvStWAIT);
+						Event[ev][spec].mode = LE32(a2);
+						Event[ev][spec].fhandler = LE32(a3);
+
+						// v0 = ev | spec<<8;
+						mipsinfo.i = ev | (spec<<8);
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x0a:	// WaitEvent
+					{
+						int ev, spec;
+
+						ev = a0 & 0xff;
+						spec = (a0 >> 8) & 0xff;
+
+						mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: WaitEvent(ev %d spec %d) PC=%x\n", ev, spec, mipsinfo.i);
+						#endif
+
+						Event[ev][spec].status = LE32(EvStACTIVE);
+
+						// v0 = 1
+						mipsinfo.i = 1;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+
+						WAI = 1;
+						mips_shorten_frame();
+					}
+					break;
+
+				case 0x0b:	// TestEvent
+					{
+						int ev, spec;
+
+						ev   = a0 & 0xff;
+						spec = (a0 >> 8) & 0xff;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: TestEvent(ev %d spec %d)\n", ev, spec);
+						#endif
+
+						// v0 = (is event ready?)
+						if (Event[ev][spec].status == LE32(EvStALREADY))
+						{
+							Event[ev][spec].status = LE32(EvStACTIVE);
+							mipsinfo.i = 1;
+						}
+						else
+						{
+							mipsinfo.i = 0;
+						}
+
+						WAI = 1;
+
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+
+						// it looks like this sets v1 to something non-zero too
+						// (code in Crash 2 & 3 actually relies on that behavior)
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R3, &mipsinfo);
+					}
+					break;
+
+				case 0x0c:	// EnableEvent
+					{
+						int ev, spec;
+
+						ev = a0 & 0xff;
+						spec = (a0 >> 8) & 0xff;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: EnableEvent(ev %d spec %d)\n", ev, spec);
+						#endif
+
+						Event[ev][spec].status = LE32(EvStACTIVE);
+
+						// v0 = 1
+						mipsinfo.i = 1;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x0d:	// DisableEvent
+					{
+						int ev, spec;
+
+						ev = a0 & 0xff;
+						spec = (a0 >> 8) & 0xff;
+
+						#if DEBUG_HLE_BIOS
+						printf("HLEBIOS: DisableEvent(ev %d spec %d)\n", ev, spec);
+						#endif
+
+						Event[ev][spec].status = LE32(EvStWAIT);
+
+						// v0 = 1
+						mipsinfo.i = 1;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+					}
+					break;
+
+				case 0x17:	// ReturnFromException
+					for (i = 0; i < 32; i++)
+					{
+						mipsinfo.i = irq_regs[i];
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R0 + i, &mipsinfo);
+					}
+
+					mipsinfo.i = irq_regs[32];
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_HI, &mipsinfo);
+					mipsinfo.i = irq_regs[33];
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_LO, &mipsinfo);
+					mipsinfo.i = mips_get_ePC();
+//					printf("ReturnFromException: IRQ state %x\n", irq_data & irq_mask);
+//					printf("HLEBIOS: ReturnFromException, cause = %08x, PC = %08x\n", mips_get_cause(), mipsinfo.i);
+					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+					status = mips_get_status();
+					status = (status & 0xfffffff0) | ((status & 0x3c)>>2);
+					mips_set_status(status);
+					return;	// force return to avoid PC=RA below
+					break;
+
+				case 0x19:	// HookEntryInt
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: HookEntryInt(%08x)\n", a0);
+					#endif
+					entry_int = a0;
+					break;
+
+				case 0x3f:	// puts
+//					printf("HLEBIOS: puts\n");
+					break;
+
+				case 0x5b:	// ChangeClearPAD
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: ChangeClearPAD\n");
+					#endif
+					break;
+
+				default:
+					#if DEBUG_HLE_BIOS
+					printf("Unknown BIOS B0 call = %x\n", subcall);
+					#endif
+					break;
+			}
+			break;
+
+		case 0xc0:	// c0 syscalls
+			switch (subcall)
+			{
+				case 0xa:	// ChangeClearRCnt
+					#if DEBUG_HLE_BIOS
+					printf("HLEBIOS: ChangeClearRCnt(%08x, %08x)\n", a0, a1);
+					#endif
+
+					// v0 = (a0*4)+0x8600
+					mipsinfo.i = LE32(psx_ram[((a0<<2) + 0x8600)/4]);
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+
+					// (a0*4)+0x8600 = a1;
+					psx_ram[((a0<<2) + 0x8600)/4] = LE32(a1);
+					break;
+
+				default:
+					#if DEBUG_HLE_BIOS
+					printf("Unknown BIOS C0 call = %x\n", subcall);
+					#endif
+					break;
+			}
+			break;
+	}
+
+	// PC = RA
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+	mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+}
+
+// root counters
+
+void psx_hw_runcounters(void)
+{
+	int i;
+
+	// don't process any IRQ sources when interrupts are suspended
+	if (!intr_susp)
+	{
+		if (dma4_delay)
+		{
+			dma4_delay--;
+
+			if (dma4_delay == 0)
+			{
+				SPU2interruptDMA4();
+
+				if (dma4_cb)
+				{
+					call_irq_routine(dma4_cb, dma4_flag);
+				}
+			}
+		}
+
+		if (dma7_delay)
+		{
+			dma7_delay--;
+
+			if (dma7_delay == 0)
+			{
+				SPU2interruptDMA7();
+
+				if (dma7_cb)
+				{
+					call_irq_routine(dma7_cb, dma7_flag);
+				}
+			}
+		}
+
+		for (i = 0; i < iNumThreads; i++)
+		{
+			if (threads[i].iState == TS_WAITDELAY)
+			{
+				if (threads[i].waitparm > CLOCK_DIV)
+				{
+					threads[i].waitparm -= CLOCK_DIV;
+				}
+				else	// time's up
+				{
+					threads[i].waitparm = 0;
+					threads[i].iState = TS_READY;
+
+					timerexp = 1;
+
+					ps2_reschedule();
+				}
+			}
+		}
+
+		sys_time += 836;
+
+		if (iNumTimers > 0)
+		{
+			for (i = 0; i < iNumTimers; i++)
+			{
+				if (iop_timers[i].iActive > 0)
+				{
+					iop_timers[i].count += 836;
+					if (iop_timers[i].count >= iop_timers[i].target)
+					{
+						iop_timers[i].count -= iop_timers[i].target;
+
+	//					printf("Timer %d: handler = %08x, param = %08x\n", i, iop_timers[i].handler, iop_timers[i].hparam);
+						call_irq_routine(iop_timers[i].handler, iop_timers[i].hparam);
+
+						timerexp = 1;
+					}
+				}
+			}
+		}
+	}
+
+// PS1 root counters
+	for (i = 0; i < 4; i++)
+	{
+		if ((!(root_cnts[i].mode & RC_EN)) && (root_cnts[i].mode != 0))
+		{
+			if (root_cnts[i].mode & RC_DIV8)
+			{
+				root_cnts[i].count += 768/8;
+			}
+			else
+			{
+				root_cnts[i].count += 768;
+			}
+
+			if (root_cnts[i].count >= root_cnts[i].target)
+			{
+				if (!(root_cnts[i].mode & RC_RESET))
+				{
+					root_cnts[i].mode |= RC_EN;
+				}
+				else
+				{
+					root_cnts[i].count %= root_cnts[i].target;
+				}
+
+				psx_irq_set(1<<(4+i));
+			}
+		}
+	}
+}
+
+// PEOpS callbacks
+
+void SPUirq(void)
+{
+//	psx_irq_set(0x200);
+}
+
+// PSXCPU callbacks
+
+uint8_t program_read_byte_32le(offs_t address)
+{
+	switch (address & 0x3)
+	{
+		case 0:
+			return psx_hw_read(address, 0xffffff00);
+			break;
+		case 1:
+			return psx_hw_read(address, 0xffff00ff)>>8;
+			break;
+		case 2:
+			return psx_hw_read(address, 0xff00ffff)>>16;
+			break;
+		case 3:
+			return psx_hw_read(address, 0x00ffffff)>>24;
+			break;
+	}
+
+	return psx_hw_read(address, 0xffffff00);
+}
+
+uint16_t program_read_word_32le(offs_t address)
+{
+	if (address & 2)
+		return psx_hw_read(address, 0x0000ffff)>>16;
+
+	return psx_hw_read(address, 0xffff0000);
+}
+
+uint32_t program_read_dword_32le(offs_t address)
+{
+	return psx_hw_read(address, 0);
+}
+
+void program_write_byte_32le(offs_t address, uint8_t data)
+{
+	switch (address & 0x3)
+	{
+		case 0:
+			psx_hw_write(address, data, 0xffffff00);
+			break;
+		case 1:
+			psx_hw_write(address, data<<8, 0xffff00ff);
+			break;
+		case 2:
+			psx_hw_write(address, data<<16, 0xff00ffff);
+			break;
+		case 3:
+			psx_hw_write(address, data<<24, 0x00ffffff);
+			break;
+	}
+}
+
+void program_write_word_32le(offs_t address, uint16_t data)
+{
+	if (address & 2)
+	{
+		psx_hw_write(address, data<<16, 0x0000ffff);
+		return;
+	}
+
+	psx_hw_write(address, data, 0xffff0000);
+}
+
+void program_write_dword_32le(offs_t address, uint32_t data)
+{
+	psx_hw_write(address, data, 0);
+}
+
+// sprintf replacement
+static void iop_sprintf(char *out, char *fmt, uint32_t pstart)
+{
+	char temp[64], tfmt[64];
+	char *cf, *pstr;
+	union cpuinfo mipsinfo;
+	int curparm, fp, isnum;
+
+	curparm = pstart;
+	cf = fmt;
+
+	while (*cf != '\0')
+	{
+		if (*cf != '%')
+		{
+			if (*cf == 27)
+			{
+				*out++ = '[';
+				*out++ = 'E';
+				*out++ = 'S';
+				*out++ = 'C';
+				*out = ']';
+			}
+			else
+			{
+				*out = *cf;
+			}
+			out++;
+			cf++;
+		}
+		else	// got format
+		{
+			cf++;
+
+			tfmt[0] = '%';
+			fp = 1;
+			while (((*cf >= '0') && (*cf <= '9')) || (*cf == '.'))
+			{
+				tfmt[fp] = *cf;
+				fp++;
+				cf++;
+			}
+
+			tfmt[fp] = *cf;
+			tfmt[fp+1] = '\0';
+
+			isnum = 0;
+			switch (*cf)
+			{
+				case 'x':
+				case 'X':
+				case 'd':
+				case 'D':
+				case 'c':
+				case 'C':
+				case 'u':
+				case 'U':
+					isnum = 1;
+					break;
+			}
+
+//			printf("]]] temp format: [%s] [%d]\n", tfmt, isnum);
+
+			if (isnum)
+			{
+				mips_get_info(curparm, &mipsinfo);
+//				printf("parameter %d = %x\n", curparm-pstart, mipsinfo.i);
+				curparm++;
+				sprintf(temp, tfmt, (int32_t)mipsinfo.i);
+			}
+			else
+			{
+				mips_get_info(curparm, &mipsinfo);
+				curparm++;
+
+				pstr = (char *)psx_ram;
+				pstr += (mipsinfo.i & 0x1fffff);
+
+				sprintf(temp, tfmt, pstr);
+			}
+
+			pstr = &temp[0];
+			while (*pstr != '\0')
+			{
+				*out = *pstr;
+				out++;
+				pstr++;
+			}
+
+			cf++;
+		}
+	}
+
+	*out = '\0';
+}
+
+// PS2 IOP callbacks
+void psx_iop_call(uint32_t pc, uint32_t callnum)
+{
+	uint32_t scan;
+	char *mname, *str1, name[9], out[512];
+	uint32_t a0, a1, a2, a3;
+	union cpuinfo mipsinfo;
+	int i;
+
+//	printf("IOP call @ %08x\n", pc);
+
+	// prefetch parameters
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+	a0 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
+	a1 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R6, &mipsinfo);
+	a2 = mipsinfo.i;
+	mips_get_info(CPUINFO_INT_REGISTER + MIPS_R7, &mipsinfo);
+	a3 = mipsinfo.i;
+
+	scan = (pc&0x0fffffff)/4;
+	while ((psx_ram[scan] != LE32(0x41e00000)) && (scan >= (0x10000/4)))
+	{
+		scan--;
+	}
+
+	if (psx_ram[scan] != LE32(0x41e00000))
+	{
+		printf("FATAL ERROR: couldn't find IOP link signature\n");
+		return;
+	}
+
+	scan += 3;	// skip zero and version
+	memcpy(name, &psx_ram[scan], 8);
+	name[8] = '\0';
+
+//	printf("IOP: call module [%s] service %d (PC=%08x)\n", name, callnum, pc);
+
+	if (!strcmp(name, "stdio"))
+	{
+		switch (callnum)
+		{
+			case 4:	// printf
+				mname = (char *)psx_ram;
+				mname += a0 & 0x1fffff;
+				mname += (a0 & 3);
+
+				iop_sprintf(out, mname, CPUINFO_INT_REGISTER + MIPS_R5);	// a1 is first parm
+
+			/*	if (out[strlen(out)-1] != '\n')
+				{
+					strcat(out, "\n");
+				}*/
+
+				#if DEBUG_HLE_IOP
+				printf("%s", out);
+				#endif
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "sifman"))
+	{
+		switch (callnum)
+		{
+			case 5:	// sceSifInit
+				#if DEBUG_HLE_IOP
+				printf("IOP: sceSifInit()\n");
+				#endif
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 7: // sceSifSetDma
+				#if DEBUG_HLE_IOP
+				printf("IOP: sceSifSetDma(%08x %08x)\n", a0, a1);
+				#endif
+
+				mipsinfo.i = 1;	// nonzero = success
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 8:	// sceSifDmaStat
+				#if DEBUG_HLE_IOP
+				printf("IOP: sceSifDmaStat(%08x)\n", a0);
+				#endif
+
+				mipsinfo.i = -1;	// dma completed
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 29: // sceSifCheckInit
+				#if DEBUG_HLE_IOP
+				printf("IOP: sceSifCheckInit()\n");
+				#endif
+
+				mipsinfo.i = 1;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "thbase"))
+	{
+		uint32_t newAlloc;
+
+		switch (callnum)
+		{
+			case 4:	// CreateThread
+				#if DEBUG_THREADING
+				printf("IOP: CreateThread(%08x)\n", a0);
+				#endif
+				a0 &= 0x1fffff;
+				a0 /= 4;
+				#if DEBUG_THREADING
+				printf("   : flags %x routine %08x pri %x stacksize %d refCon %08x\n",
+					psx_ram[a0], psx_ram[a0+1], psx_ram[a0+2], psx_ram[a0+3], psx_ram[a0+4]);
+				#endif
+
+				newAlloc = psf2_get_loadaddr();
+				// force 16-byte alignment
+				if (newAlloc & 0xf)
+				{
+					newAlloc &= ~0xf;
+					newAlloc += 16;
+				}
+				psf2_set_loadaddr(newAlloc + LE32(psx_ram[a0+3]));
+
+				threads[iNumThreads].iState = TS_CREATED;
+				threads[iNumThreads].stackloc = newAlloc;
+				threads[iNumThreads].flags = LE32(psx_ram[a0]);
+				threads[iNumThreads].routine = LE32(psx_ram[a0+2]);
+				threads[iNumThreads].stacksize = LE32(psx_ram[a0+3]);
+				threads[iNumThreads].refCon = LE32(psx_ram[a0+4]);
+
+				mipsinfo.i = iNumThreads;
+				iNumThreads++;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 6:	// StartThread
+				#if DEBUG_THREADING
+				printf("IOP: StartThread(%d %d)\n", a0, a1);
+				#endif
+
+				FreezeThread(iCurThread, 1);
+				ThawThread(a0);
+				iCurThread = a0;
+				break;
+
+			case 20:// GetThreadID
+				#if DEBUG_THREADING
+				printf("IOP: GetThreadId()\n");
+				#endif
+
+				mipsinfo.i = iCurThread;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 24:// SleepThread
+				#if DEBUG_THREADING
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: SleepThread() [curThread %d, PC=%x]\n", iCurThread, mipsinfo.i);
+				#endif
+
+				FreezeThread(iCurThread, 1);
+				threads[iCurThread].iState = TS_SLEEPING;
+				iCurThread = -1;
+
+				ps2_reschedule();
+				break;
+
+			case 25:// WakeupThread
+				#if DEBUG_THREADING
+				printf("IOP: WakeupThread(%d)\n", a0);
+				#endif
+
+				// set thread to "ready to go"
+				threads[a0].iState = TS_READY;
+				break;
+
+			case 26:// iWakeupThread
+				#if DEBUG_THREADING
+				printf("IOP: iWakeupThread(%d)\n", a0);
+				#endif
+
+				// set thread to "ready to go" if it's not running
+				if (threads[a0].iState != TS_RUNNING)
+				{
+					threads[a0].iState = TS_READY;
+				}
+				break;
+
+			case 33:// DelayThread
+				{
+					double dTicks;
+
+					#if DEBUG_THREADING
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					printf("IOP: DelayThread(%d) (PC=%x) [curthread = %d]\n", a0, mipsinfo.i, iCurThread);
+					#endif
+
+					if (a0 < 100)
+					{
+						a0 = 100;
+					}
+					dTicks = (double)a0;
+
+					FreezeThread(iCurThread, 1);
+					threads[iCurThread].iState = TS_WAITDELAY;
+					dTicks /= (double)1000000.0;
+					dTicks *= (double)36864000.0;	// 768*48000 = IOP native-mode clock rate
+					threads[iCurThread].waitparm = (uint32_t)dTicks;
+					iCurThread = -1;
+
+					ps2_reschedule();
+				}
+				break;
+
+			case 34://GetSystemTime
+				#if DEBUG_HLE_IOP
+				printf("IOP: GetSystemTime(%x)\n", a0);
+				#endif
+
+				a0 &= 0x1fffff;
+				a0 /= 4;
+
+				psx_ram[a0] = LE32(sys_time & 0xffffffff);  	// low
+				psx_ram[a0+1] = LE32(sys_time >> 32);	// high
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 39:// USec2SysClock
+				{
+					uint64_t dTicks = (uint64_t)a0;
+					uint32_t hi, lo;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: USec2SysClock(%d %08x)\n", a0, a1);
+					#endif
+
+					dTicks *= (uint64_t)36864000;
+					dTicks /= (uint64_t)1000000;
+
+					hi = dTicks>>32;
+					lo = dTicks & 0xffffffff;
+
+					psx_ram[((a1 & 0x1fffff)/4)] = LE32(lo);
+					psx_ram[((a1 & 0x1fffff)/4)+1] = LE32(hi);
+
+					mipsinfo.i = 0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			case 40://SysClock2USec
+				{
+					uint64_t temp;
+					uint32_t seconds, usec;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: SysClock2USec(%08x %08x %08x)\n", a0, a1, a2);
+					#endif
+
+					a0 &= 0x1fffff;
+					a1 &= 0x1fffff;
+					a2 &= 0x1fffff;
+					a0 /= 4;
+					a1 /= 4;
+					a2 /= 4;
+
+					temp = LE32(psx_ram[a0]);
+					temp |= (uint64_t)LE32(psx_ram[a0+1])<<32;
+
+					temp *= (uint64_t)1000000;
+					temp /= (uint64_t)36864000;
+
+					// temp now is USec
+					seconds = (temp / 1000000) & 0xffffffff;
+					usec = (temp % 1000000) & 0xffffffff;
+
+					psx_ram[a1] = LE32(seconds);
+					psx_ram[a2] = LE32(usec);
+				}
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "thevent"))
+	{
+		switch (callnum)
+		{
+			case 4:	// CreateEventFlag
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				#if DEBUG_HLE_IOP
+				printf("IOP: CreateEventFlag(%08x) (PC=%x)\n", a0, mipsinfo.i);
+				#endif
+
+				a0 &= 0x1fffff;
+				a0 /= 4;
+
+				evflags[iNumFlags].type = LE32(psx_ram[a0]);
+				evflags[iNumFlags].value = LE32(psx_ram[a0+1]);
+				evflags[iNumFlags].param = LE32(psx_ram[a0+2]);
+				evflags[iNumFlags].inUse = 1;
+
+				#if DEBUG_HLE_IOP
+				printf("     Flag %02d: type %d init %08x param %08x\n", iNumFlags, evflags[iNumFlags].type, evflags[iNumFlags].value, evflags[iNumFlags].param);
+				#endif
+
+				mipsinfo.i = iNumFlags+1;
+				iNumFlags++;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 6: // SetEventFlag
+				a0--;
+				#if DEBUG_HLE_IOP
+				printf("IOP: SetEventFlag(%d %08x)\n", a0, a1);
+				#endif
+
+				evflags[a0].value |= a1;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 7: // iSetEventFlag
+				a0--;
+				#if DEBUG_HLE_IOP
+				printf("IOP: iSetEventFlag(%08x %08x)\n", a0, a1);
+				#endif
+
+				evflags[a0].value |= a1;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+
+				for (i=0; i < iNumThreads; i++)
+				{
+					if ((threads[i].iState == TS_WAITEVFLAG) && (threads[i].waitparm == a0))
+					{
+						threads[i].iState = TS_READY;
+					}
+				}
+				break;
+
+			case 8:	// ClearEventFlag
+				a0--;
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				#if DEBUG_HLE_IOP
+				printf("IOP: ClearEventFlag(%d %08x) (PC=%x)\n", a0, a1, mipsinfo.i);
+				#endif
+
+				evflags[a0].value &= a1;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 9: // iClearEventFlag
+				a0--;
+				#if DEBUG_HLE_IOP
+				printf("IOP: iClearEventFlag(%d %08x)\n", a0, a1);
+				#endif
+
+				evflags[a0].value &= a1;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 10:// WaitEventFlag
+				a0--;
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: WaitEventFlag(%d %08x %d %08x PC=%x)\n", a0, a1, a2, a3, mipsinfo.i);
+				#endif
+
+				// if we're not set, freeze this thread
+				if (!(evflags[a0].value & a1))
+				{
+					FreezeThread(iCurThread, 1);
+					threads[iCurThread].iState = TS_WAITEVFLAG;
+					threads[iCurThread].waitparm = a0;
+					iCurThread = -1;
+
+					ps2_reschedule();
+				}
+				else
+				{
+					mipsinfo.i = 0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "thsemap"))
+	{
+		int foundthread;
+
+		switch (callnum)
+		{
+			case 4:	// CreateSema
+				#if DEBUG_HLE_IOP
+				printf("IOP: CreateSema(%08x)\n", a0);
+				#endif
+
+				mipsinfo.i = -1;
+				for (i = 0; i < SEMA_MAX; i++)
+				{
+					if (!semaphores[i].inuse)
+					{
+						mipsinfo.i = i;
+						break;
+					}
+				}
+
+				if (mipsinfo.i == -1)
+				{
+					printf("IOP: out of semaphores!\n");
+				}
+
+				a0 &= 0x7fffffff;
+				a0 /= 4;
+
+//				printf("Sema %d Parms: %08x %08x %08x %08x\n", mipsinfo.i, psx_ram[a0], psx_ram[a0+1], psx_ram[a0+2], psx_ram[a0+3]);
+
+				if (mipsinfo.i != -1)
+				{
+					semaphores[mipsinfo.i].attr = LE32(psx_ram[a0]);
+					semaphores[mipsinfo.i].option = LE32(psx_ram[a0+1]);
+					semaphores[mipsinfo.i].init = LE32(psx_ram[a0+2]);
+					semaphores[mipsinfo.i].max = LE32(psx_ram[a0+3]);
+
+					semaphores[mipsinfo.i].current = semaphores[mipsinfo.i].init;
+
+					semaphores[mipsinfo.i].inuse = 1;
+				}
+
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 6: // SignalSema
+				#if DEBUG_HLE_IOP
+				printf("IOP: SignalSema(%d) (current %d)\n", a0, semaphores[a0].current);
+				#endif
+
+				foundthread = 0;
+				for (i=0; i < iNumThreads; i++)
+				{
+					if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0))
+					{
+						threads[i].iState = TS_READY;
+						semaphores[a0].threadsWaiting--;
+						foundthread = 1;
+						break;
+					}
+				}
+
+				mipsinfo.i = 0;
+
+				if (!foundthread)
+				{
+					if (semaphores[a0].current < semaphores[a0].max)
+					{
+						semaphores[a0].current++;
+					}
+					else
+					{
+						mipsinfo.i = -420;	// semaphore overflow
+					}
+				}
+
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 7: // iSignalSema
+				#if DEBUG_HLE_IOP
+				printf("IOP: iSignalSema(%d)\n", a0);
+				#endif
+
+				foundthread = 0;
+				for (i=0; i < iNumThreads; i++)
+				{
+					if ((threads[i].iState == TS_WAITSEMA) && (threads[i].waitparm == a0))
+					{
+						threads[i].iState = TS_READY;
+						semaphores[a0].threadsWaiting--;
+						foundthread = 1;
+						break;
+					}
+				}
+
+				mipsinfo.i = 0;
+
+				if (!foundthread)
+				{
+					if (semaphores[a0].current < semaphores[a0].max)
+					{
+						semaphores[a0].current++;
+					}
+					else
+					{
+						mipsinfo.i = -420;	// semaphore overflow
+					}
+				}
+
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 8: // WaitSema
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: WaitSema(%d) (cnt %d) (th %d) (PC=%x)\n", a0, iCurThread, semaphores[a0].current, mipsinfo.i);
+				#endif
+
+				if (semaphores[a0].current > 0)
+				{
+					semaphores[a0].current--;
+				}
+				else
+				{
+					FreezeThread(iCurThread, 1);
+					threads[iCurThread].iState = TS_WAITSEMA;
+					threads[iCurThread].waitparm = a0;
+					ps2_reschedule();
+				}
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "timrman"))
+	{
+		switch (callnum)
+		{
+			case 4:	// AllocHardTimer
+				#if DEBUG_HLE_IOP
+				printf("IOP: AllocHardTimer(%d %d %d)\n", a0, a1, a2);
+				#endif
+				// source, size, prescale
+
+				if (a1 != 32)
+				{
+					printf("IOP: AllocHardTimer doesn't support 16-bit timers!\n");
+				}
+
+				iop_timers[iNumTimers].source = a0;
+				iop_timers[iNumTimers].prescale = a2;
+
+				mipsinfo.i = iNumTimers+1;
+				iNumTimers++;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 6: // FreeHardTimer
+				#if DEBUG_HLE_IOP
+				printf("IOP: FreeHardTimer(%d)\n", a0);
+				#endif
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 10:// GetTimerCounter
+				mipsinfo.i = iop_timers[a0-1].count;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 20: // SetTimerHandler
+				#if DEBUG_HLE_IOP
+				printf("IOP: SetTimerHandler(%d %d %08x %08x)\n", a0, a1, a2, a3);
+				#endif
+				// id, compare, handler, common (last is param for handler)
+
+				iop_timers[a0-1].target = a1;
+				iop_timers[a0-1].handler = a2;
+				iop_timers[a0-1].hparam = a3;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 22: // SetupHardTimer
+				#if DEBUG_HLE_IOP
+				printf("IOP: SetupHardTimer(%d %d %d %d)\n", a0, a1, a2, a3);
+				#endif
+				// id, source, mode, prescale
+
+				iop_timers[a0-1].source = a1;
+				iop_timers[a0-1].mode = a2;
+				iop_timers[a0-1].prescale = a3;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 23: // StartHardTimer
+				#if DEBUG_HLE_IOP
+				printf("IOP: StartHardTimer(%d)\n", a0);
+				#endif
+
+				iop_timers[a0-1].iActive = 1;
+				iop_timers[a0-1].count = 0;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 24: // StopHardTimer
+				#if DEBUG_HLE_IOP
+				printf("IOP: StopHardTimer(%d)\n", a0);
+				#endif
+
+				iop_timers[a0-1].iActive = 0;
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "sysclib"))
+	{
+		switch (callnum)
+		{
+			case 12:	// memcpy
+				{
+					uint8_t *dst, *src;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: memcpy(%08x, %08x, %d)\n", a0, a1, a2);
+					#endif
+
+					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
+					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
+					// get exact byte alignment
+					dst += a0 % 4;
+					src += a1 % 4;
+
+					while (a2)
+					{
+						*dst = *src;
+						dst++;
+						src++;
+						a2--;
+					}
+
+					// v0 = a0
+					mipsinfo.i = a0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			case 13:	// memmove
+				{
+					uint8_t *dst, *src;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: memmove(%08x, %08x, %d)\n", a0, a1, a2);
+					#endif
+
+					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
+					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
+					// get exact byte alignment
+					dst += a0 % 4;
+					src += a1 % 4;
+
+					dst += a2 - 1;
+					src += a2 - 1;
+
+					while (a2)
+					{
+						*dst = *src;
+						dst--;
+						src--;
+						a2--;
+					}
+
+					// v0 = a0
+					mipsinfo.i = a0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			case 14:	// memset
+				{
+					uint8_t *dst;
+
+					#if DEBUG_HLE_IOP
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					printf("IOP: memset(%08x, %02x, %d) [PC=%x]\n", a0, a1, a2, mipsinfo.i);
+					#endif
+
+					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
+					dst += (a0 & 3);
+
+					memset(dst, a1, a2);
+				}
+				break;
+
+			case 17:	// bzero
+				{
+					uint8_t *dst;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: bzero(%08x, %08x)\n", a0, a1);
+					#endif
+
+					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
+					dst += (a0 & 3);
+					memset(dst, 0, a1);
+				}
+				break;
+
+			case 19:	// sprintf
+				mname = (char *)psx_ram;
+				str1 = (char *)psx_ram;
+				mname += a0 & 0x1fffff;
+				str1 += a1 & 0x1fffff;
+
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: sprintf(%08x, %s, ...) [PC=%08x]\n", a0, str1, (uint32_t)mipsinfo.i);
+				printf("%x %x %x %x\n", a0, a1, a2, a3);
+				#endif
+
+				iop_sprintf(mname, str1, CPUINFO_INT_REGISTER + MIPS_R6);	// a2 is first parameter
+
+				#if DEBUG_HLE_IOP
+				printf("     = [%s]\n", mname);
+				#endif
+				break;
+
+			case 23:	// strcpy
+				{
+					uint8_t *dst, *src;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: strcpy(%08x, %08x)\n", a0, a1);
+					#endif
+
+					dst = (uint8_t *)&psx_ram[(a0&0x1fffff)/4];
+					src = (uint8_t *)&psx_ram[(a1&0x1fffff)/4];
+					// get exact byte alignment
+					dst += a0 % 4;
+					src += a1 % 4;
+
+					while (*src != '\0')
+					{
+						*dst = *src;
+						dst++;
+						src++;
+					}
+					*dst = '\0';
+
+					// v0 = a0
+					mipsinfo.i = a0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			case 27:	// strlen
+				{
+					char *dst;
+
+					#if DEBUG_HLE_IOP
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					printf("IOP: strlen(%08x) [PC=%x]\n", a0, mipsinfo.i);
+					#endif
+
+					dst = (char *)&psx_ram[(a0&0x1fffff)/4];
+					dst += (a0 & 3);
+					mipsinfo.i = strlen(dst);
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+			case 30:	// strncpy
+				{
+					char *dst, *src;
+
+					#if DEBUG_HLE_IOP
+					printf("IOP: strncpy(%08x, %08x, %d)\n", a0, a1, a2);
+					#endif
+
+					dst = (char *)&psx_ram[(a0&0x1fffff)/4];
+					src = (char *)&psx_ram[(a1&0x1fffff)/4];
+					// get exact byte alignment
+					dst += a0 % 4;
+					src += a1 % 4;
+
+					while ((*src != '\0') && (a2 > 0))
+					{
+						*dst = *src;
+						dst++;
+						src++;
+						a2--;
+					}
+					*dst = '\0';
+
+					// v0 = a0
+					mipsinfo.i = a0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				}
+				break;
+
+
+			case 36:	// strtol
+				mname = (char *)&psx_ram[(a0 & 0x1fffff)/4];
+				mname += (a0 & 3);
+
+				if (a1)
+				{
+					printf("IOP: Unhandled strtol with non-nullptr second parm\n");
+				}
+
+				mipsinfo.i = strtol(mname, nullptr, a2);
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "intrman"))
+	{
+		switch (callnum)
+		{
+			case 4:	// RegisterIntrHandler
+				#if DEBUG_HLE_IOP
+				printf("IOP: RegisterIntrHandler(%d %08x %08x %08x)\n", a0, a1, a2, a3);
+				#endif
+
+				if (a0 == 9)
+				{
+					irq9_fval = a1;
+					irq9_cb = a2;
+					irq9_flag = a3;
+				}
+
+				// DMA4?
+				if (a0 == 36)
+				{
+					dma4_fval = a1;
+					dma4_cb = a2;
+					dma4_flag = a3;
+				}
+
+				// DMA7?
+				if (a0 == 40)
+				{
+					dma7_fval = a1;
+					dma7_cb = a2;
+					dma7_flag = a3;
+				}
+				break;
+
+			case 5:	// ReleaseIntrHandler
+				#if DEBUG_HLE_IOP
+				printf("IOP: ReleaseIntrHandler(%d)\n", a0);
+				#endif
+				break;
+
+			case 6:	// EnableIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: EnableIntr(%d)\n", a0);
+				#endif
+				break;
+
+			case 7:	// DisableIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: DisableIntr(%d)\n", a0);
+				#endif
+				break;
+
+			case 8: // CpuDisableIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: CpuDisableIntr(%d)\n", a0);
+				#endif
+				break;
+
+			case 9: // CpuEnableIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: CpuEnableIntr(%d)\n", a0);
+				#endif
+				break;
+
+			case 17:	// CpuSuspendIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: CpuSuspendIntr\n");
+				#endif
+
+				// if already suspended, return an error code
+				if (intr_susp)
+				{
+					mipsinfo.i = -102;
+				}
+				else
+				{
+					mipsinfo.i = 0;
+				}
+				intr_susp = 1;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 18:	// CpuResumeIntr
+				#if DEBUG_HLE_IOP
+				printf("IOP: CpuResumeIntr\n");
+				#endif
+				intr_susp = 0;
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 23:	// QueryIntrContext
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: QueryIntrContext(PC=%x)\n", mipsinfo.i);
+				#endif
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "loadcore"))
+	{
+		switch (callnum)
+		{
+			case 5: // FlushDcache
+				#if DEBUG_HLE_IOP
+				printf("IOP: FlushDcache()\n");
+				#endif
+				break;
+
+			case 6:	// RegisterLibraryEntries
+				a0 &= 0x1fffff;
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: RegisterLibraryEntries(%08x) (PC=%x)\n", a0, mipsinfo.i);
+				#endif
+
+				if (psx_ram[a0/4] == LE32(0x41c00000))
+				{
+					a0 += 3*4;
+					memcpy(&reglibs[iNumLibs].name, &psx_ram[a0/4], 8);
+					reglibs[iNumLibs].name[8] = '\0';
+					#if DEBUG_HLE_IOP
+					printf("Lib name [%s]\n", &reglibs[iNumLibs].name);
+					#endif
+					a0 += 2*4;
+					reglibs[iNumLibs].dispatch = a0;
+					iNumLibs++;
+				}
+				else
+				{
+					printf("ERROR: Entry table signature missing\n");
+
+				}
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "sysmem"))
+	{
+		uint32_t newAlloc;
+
+		switch (callnum)
+		{
+			case 4:	// AllocMemory
+				newAlloc = psf2_get_loadaddr();
+				// make sure we're 16-byte aligned
+				if (newAlloc & 15)
+				{
+					newAlloc &= ~15;
+					newAlloc += 16;
+				}
+
+				if (a1 & 15)
+				{
+					a1 &= ~15;
+					a1 += 16;
+				}
+
+				psf2_set_loadaddr(newAlloc + a1);
+
+				#if DEBUG_HLE_IOP
+				printf("IOP: AllocMemory(%d, %d, %x) = %08x\n", a0, a1, a2, newAlloc|0x80000000);
+				#endif
+
+				mipsinfo.i = newAlloc; // | 0x80000000;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 5:	// FreeMemory
+				#if DEBUG_HLE_IOP
+				printf("IOP: FreeMemory(%x)\n", a0);
+				#endif
+				break;
+
+			case 7:	// QueryMaxFreeMemSize
+				#if DEBUG_HLE_IOP
+				printf("IOP: QueryMaxFreeMemSize\n");
+				#endif
+
+				mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr();
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 8:	// QueryTotalFreeMemSize
+				#if DEBUG_HLE_IOP
+				printf("IOP: QueryTotalFreeMemSize\n");
+				#endif
+
+				mipsinfo.i = (2*1024*1024) - psf2_get_loadaddr();
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 14: // Kprintf
+				mname = (char *)psx_ram;
+				mname += a0 & 0x1fffff;
+				mname += (a0 & 3);
+
+				iop_sprintf(out, mname, CPUINFO_INT_REGISTER + MIPS_R5);	// a1 is first parm
+
+				if (out[strlen(out)-1] != '\n')
+				{
+					strcat(out, "\n");
+				}
+
+				// filter out ESC characters
+				{
+					int ch;
+
+					for (ch = 0; ch < strlen(out); ch++)
+					{
+						if (out[ch] == 27)
+						{
+							out[ch] = ']';
+						}
+					}
+				}
+
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("KTTY: %s [PC=%x]\n", out, mipsinfo.i);
+				#endif
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+	}
+	else if (!strcmp(name, "modload"))
+	{
+		uint8_t *tempmem;
+		uint32_t newAlloc;
+
+		switch (callnum)
+		{
+			case 7:	// LoadStartModule
+				mname = (char *)&psx_ram[(a0 & 0x1fffff)/4];
+				mname += 8;
+				str1 = (char *)&psx_ram[(a2 & 0x1fffff)/4];
+				#if DEBUG_HLE_IOP
+				printf("LoadStartModule: %s\n", mname);
+				#endif
+
+				// get 2k for our parameters
+				newAlloc = psf2_get_loadaddr();
+				// force 16-byte alignment
+				if (newAlloc & 0xf)
+				{
+					newAlloc &= ~0xf;
+					newAlloc += 16;
+				}
+				psf2_set_loadaddr(newAlloc + 2048);
+
+				tempmem = (uint8_t *)malloc(2*1024*1024);
+				if (psf2_load_file(mname, tempmem, 2*1024*1024) != 0xffffffff)
+				{
+					uint32_t start;
+					int i;
+
+					start = psf2_load_elf(tempmem, 2*1024*1024);
+
+					if (start != 0xffffffff)
+					{
+						uint32_t args[20], numargs = 1, argofs;
+						uint8_t *argwalk = (uint8_t *)psx_ram;
+
+						argwalk += (a2 & 0x1fffff);
+
+						args[0] = a0;	// program name is argc[0]
+
+						argofs = 0;
+
+						if (a1 > 0)
+						{
+							args[numargs] = a2;
+							numargs++;
+
+							while (a1)
+							{
+								if ((*argwalk == 0) && (a1 > 1))
+								{
+									args[numargs] = a2 + argofs + 1;
+									numargs++;
+								}
+								argwalk++;
+								argofs++;
+								a1--;
+							}
+						}
+
+						for (i = 0; i < numargs; i++)
+						{
+							#if DEBUG_HLE_IOP
+//							printf("Arg %d: %08x [%s]\n", i, args[i], &argbase[args[i]-a2]);
+							#endif
+							psx_ram[(newAlloc/4)+i] = LE32(args[i]);
+						}
+
+						// set argv and argc
+						mipsinfo.i = numargs;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R4, &mipsinfo);
+						mipsinfo.i = 0x80000000 | newAlloc;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R5, &mipsinfo);
+
+						// leave RA alone, PC = module start
+						// (NOTE: we get called in the delay slot!)
+						mipsinfo.i = start - 4;
+						mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+					}
+				}
+				free(tempmem);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+				break;
+		}
+
+	}
+	else if (!strcmp(name, "ioman"))
+	{
+		switch (callnum)
+		{
+			case 4:	// open
+				{
+					int i, slot2use;
+
+					slot2use = -1;
+					for (i = 0; i < MAX_FILE_SLOTS; i++)
+					{
+						if (filestat[i] == 0)
+						{
+							slot2use = i;
+							break;
+						}
+					}
+
+					if (slot2use == -1)
+					{
+						printf("IOP: out of file slots!\n");
+						mipsinfo.i = 0xffffffff;
+						mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+						return;
+					}
+
+					mname = (char *)psx_ram;
+					mname += (a0 & 0x1fffff);
+
+					if (!strncmp(mname, "aofile:", 7))
+					{
+						mname += 8;
+					}
+					else if (!strncmp(mname, "hefile:", 7))
+					{
+						mname += 8;
+					}
+					else if (!strncmp(mname, "host0:", 6))
+					{
+						mname += 7;
+					}
+
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					#if DEBUG_HLE_IOP
+					printf("IOP: open(\"%s\") (PC=%08x)\n", mname, mipsinfo.i);
+					#endif
+
+					filedata[slot2use] = (uint8_t *) malloc(6*1024*1024);
+					filesize[slot2use] = psf2_load_file(mname, filedata[slot2use], 6*1024*1024);
+					filepos[slot2use] = 0;
+					filestat[slot2use] = 1;
+
+					if (filesize[slot2use] == 0xffffffff)
+					{
+						mipsinfo.i = filesize[slot2use];
+					}
+					else
+					{
+						mipsinfo.i = slot2use;
+					}
+				}
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 5:	// close
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: close(%d) (PC=%08x)\n", a0, mipsinfo.i);
+				#endif
+				free(filedata[a0]);
+				filedata[a0] = (uint8_t *)nullptr;
+				filepos[a0] = 0;
+				filesize[a0] = 0;
+				filestat[a0] = 0;
+				break;
+
+			case 6:	// read
+				#if DEBUG_HLE_IOP
+				printf("IOP: read(%x %x %d) [pos %d size %d]\n", a0, a1, a2, filepos[a0], filesize[a0]);
+				#endif
+
+				if (filepos[a0] >= filesize[a0])
+				{
+					mipsinfo.i = 0;
+				}
+				else
+				{
+					uint8_t *rp;
+
+					if ((filepos[a0] + a2) > filesize[a0])
+					{
+						a2 = filesize[a0] - filepos[a0];
+					}
+
+					rp = (uint8_t *)psx_ram;
+					rp += (a1 & 0x1fffff);
+					memcpy(rp, &filedata[a0][filepos[a0]], a2);
+
+					filepos[a0] += a2;
+					mipsinfo.i = a2;
+				}
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 8:	// lseek
+				#if DEBUG_HLE_IOP
+				mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+				printf("IOP: lseek(%d, %d, %s) (PC=%08x)\n", a0, a1, seek_types[a2], mipsinfo.i);
+				#endif
+
+				switch (a2)
+				{
+					case 0:	// SEEK_SET
+						if (a1 <= filesize[a0])
+						{
+							filepos[a0] = a1;
+						}
+						break;
+					case 1:	// SEEK_CUR
+						if ((a1 + filepos[a0]) < filesize[a0])
+						{
+							filepos[a0] += a1;
+						}
+						break;
+					case 2:	// SEEK_END
+						filepos[a0] = filesize[a0] - a1;
+						break;
+				}
+
+				mipsinfo.i = filepos[a0];
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 20:	// AddDrv
+				#if DEBUG_HLE_IOP
+				printf("IOP: AddDrv(%x)\n", a0);
+				#endif
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			case 21:	// DelDrv
+				#if DEBUG_HLE_IOP
+				printf("IOP: DelDrv(%x)\n", a0);
+				#endif
+
+				mipsinfo.i = 0;
+				mips_set_info(CPUINFO_INT_REGISTER + MIPS_R2, &mipsinfo);
+				break;
+
+			default:
+				printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+		}
+	}
+	else
+	{
+		int lib;
+
+		if (iNumLibs > 0)
+		{
+			for (lib = 0; lib < iNumLibs; lib++)
+			{
+				if (!strcmp(name, reglibs[lib].name))
+				{
+					#if DEBUG_HLE_IOP
+					uint32_t PC;
+
+					mips_get_info(CPUINFO_INT_REGISTER + MIPS_R31, &mipsinfo);
+					PC = mipsinfo.i;
+					#endif
+
+					// zap the delay slot handling
+					mipsinfo.i = 0;
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYV, &mipsinfo);
+					mips_set_info(CPUINFO_INT_REGISTER + MIPS_DELAYR, &mipsinfo);
+
+					mipsinfo.i = LE32(psx_ram[(reglibs[lib].dispatch/4) + callnum]);
+
+					// (NOTE: we get called in the delay slot!)
+					#if DEBUG_HLE_IOP
+					printf("IOP: Calling %s (%d) service %d => %08x (parms %08x %08x %08x %08x) (PC=%x)\n",
+							 reglibs[lib].name,
+							 lib,
+							 callnum,
+							 (uint32_t)mipsinfo.i,
+							 a0, a1, a2, a3, PC);
+					#endif
+
+					#if 0
+					if (!strcmp(reglibs[lib].name, "ssd"))
+					{
+						if (callnum == 37)
+						{
+							psxcpu_verbose = 4096;
+						}
+					}
+					#endif
+
+					mipsinfo.i -= 4;
+					mips_set_info(CPUINFO_INT_PC, &mipsinfo);
+
+					return;
+				}
+			}
+		}
+
+		printf("IOP: Unhandled service %d for module %s\n", callnum, name);
+	}
+}
+
diff --git a/src/pulse_audio/Makefile b/src/pulse_audio/Makefile
index ff029982d57e..831fc89f1ee8 100644
--- a/src/pulse_audio/Makefile
+++ b/src/pulse_audio/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = pulse_audio${PLUGIN_SUFFIX}
 
-SRCS = pulse_audio.c
+SRCS = pulse_audio.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
 LIBS += -lpulse
diff --git a/src/pulse_audio/pulse_audio.c b/src/pulse_audio/pulse_audio.c
deleted file mode 100644
index 3fc4e05edee1..000000000000
--- a/src/pulse_audio/pulse_audio.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/***
-  This file is part of xmms-pulse.
-
-  xmms-pulse 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.
-
-  xmms-pulse is distributed in the hope that 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 xmms-pulse; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
-  USA.
-***/
-
-#include <stdio.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include <pulse/pulseaudio.h>
-
-#include <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-
-#define ERROR(...) do {fprintf (stderr, "pulseaudio: " __VA_ARGS__); putchar ('\n');} while (0)
-
-static pa_context *context = NULL;
-static pa_stream *stream = NULL;
-static pa_threaded_mainloop *mainloop = NULL;
-
-static pa_cvolume volume;
-static int volume_valid = 0;
-
-static int do_trigger = 0;
-static int64_t written;
-static int flush_time;
-static int bytes_per_second;
-
-static int connected = 0;
-
-static pa_time_event *volume_time_event = NULL;
-
-#define CHECK_DEAD_GOTO(label, warn) do { \
-if (!mainloop || \
-    !context || pa_context_get_state(context) != PA_CONTEXT_READY || \
-    !stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \
-        if (warn) \
-            AUDDBG("Connection died: %s", context ? pa_strerror(pa_context_errno(context)) : "NULL"); \
-        goto label; \
-    }  \
-} while(0);
-
-#define CHECK_CONNECTED(retval) \
-do { \
-    if (!connected) return retval; \
-} while (0);
-
-static void info_cb(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) {
-    assert(c);
-
-    if (!i)
-        return;
-
-    volume = i->volume;
-    volume_valid = 1;
-}
-
-static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) {
-    pa_operation *o;
-
-    assert(c);
-
-    if (!stream ||
-        index != pa_stream_get_index(stream) ||
-        (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
-         t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)))
-        return;
-
-    if (!(o = pa_context_get_sink_input_info(c, index, info_cb, NULL))) {
-        AUDDBG("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(c)));
-        return;
-    }
-
-    pa_operation_unref(o);
-}
-
-static void context_state_cb(pa_context *c, void *userdata) {
-    assert(c);
-
-    switch (pa_context_get_state(c)) {
-        case PA_CONTEXT_READY:
-        case PA_CONTEXT_TERMINATED:
-        case PA_CONTEXT_FAILED:
-            pa_threaded_mainloop_signal(mainloop, 0);
-            break;
-
-        case PA_CONTEXT_UNCONNECTED:
-        case PA_CONTEXT_CONNECTING:
-        case PA_CONTEXT_AUTHORIZING:
-        case PA_CONTEXT_SETTING_NAME:
-            break;
-    }
-}
-
-static void stream_state_cb(pa_stream *s, void * userdata) {
-    assert(s);
-
-    switch (pa_stream_get_state(s)) {
-
-        case PA_STREAM_READY:
-        case PA_STREAM_FAILED:
-        case PA_STREAM_TERMINATED:
-            pa_threaded_mainloop_signal(mainloop, 0);
-            break;
-
-        case PA_STREAM_UNCONNECTED:
-        case PA_STREAM_CREATING:
-            break;
-    }
-}
-
-static void stream_success_cb(pa_stream *s, int success, void *userdata) {
-    assert(s);
-
-    if (userdata)
-        *(int*) userdata = success;
-
-    pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void context_success_cb(pa_context *c, int success, void *userdata) {
-    assert(c);
-
-    if (userdata)
-        *(int*) userdata = success;
-
-    pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
-    assert(s);
-
-    pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void stream_latency_update_cb(pa_stream *s, void *userdata) {
-    assert(s);
-
-    pa_threaded_mainloop_signal(mainloop, 0);
-}
-
-static void pulse_get_volume (int * l, int * r)
-{
-    * l = * r = 0;
-
-    if (! connected || ! volume_valid)
-        return;
-
-    pa_threaded_mainloop_lock (mainloop);
-    CHECK_DEAD_GOTO (fail, 1);
-
-    if (volume.channels == 2)
-    {
-        * l = (volume.values[0] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
-        * r = (volume.values[1] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
-    }
-    else
-        * l = * r = (pa_cvolume_avg (& volume) * 100 + PA_VOLUME_NORM / 2) /
-         PA_VOLUME_NORM;
-
-fail:
-    pa_threaded_mainloop_unlock (mainloop);
-}
-
-static void volume_time_cb(pa_mainloop_api *api, pa_time_event *e, const struct timeval *tv, void *userdata) {
-    pa_operation *o;
-
-    if (!(o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL)))
-        AUDDBG("pa_context_set_sink_input_volume() failed: %s", pa_strerror(pa_context_errno(context)));
-    else
-        pa_operation_unref(o);
-
-    /* We don't wait for completion of this command */
-
-    api->time_free(volume_time_event);
-    volume_time_event = NULL;
-}
-
-static void pulse_set_volume(int l, int r) {
-
-    if (! connected)
-        return;
-
-    pa_threaded_mainloop_lock (mainloop);
-    CHECK_DEAD_GOTO (fail, 1);
-
-    /* sanitize output volumes. */
-    l = CLAMP(l, 0, 100);
-    r = CLAMP(r, 0, 100);
-
-    if (!volume_valid || volume.channels !=  1) {
-        volume.values[0] = ((pa_volume_t) l * PA_VOLUME_NORM + 50) / 100;
-        volume.values[1] = ((pa_volume_t) r * PA_VOLUME_NORM + 50) / 100;
-        volume.channels = 2;
-    } else {
-        volume.values[0] = ((pa_volume_t) MAX (l, r) * PA_VOLUME_NORM + 50) / 100;
-        volume.channels = 1;
-    }
-
-    volume_valid = 1;
-
-    if (connected && !volume_time_event) {
-        struct timeval tv;
-        pa_mainloop_api *api = pa_threaded_mainloop_get_api(mainloop);
-        volume_time_event = api->time_new(api, pa_timeval_add(pa_gettimeofday(&tv), 100000), volume_time_cb, NULL);
-    }
-
-fail:
-    if (connected)
-        pa_threaded_mainloop_unlock(mainloop);
-}
-
-static void pulse_pause (bool_t b)
-{
-    pa_operation *o = NULL;
-    int success = 0;
-
-    CHECK_CONNECTED();
-
-    pa_threaded_mainloop_lock(mainloop);
-    CHECK_DEAD_GOTO(fail, 1);
-
-    if (!(o = pa_stream_cork(stream, b, stream_success_cb, &success))) {
-        AUDDBG("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto fail;
-    }
-
-    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-        CHECK_DEAD_GOTO(fail, 1);
-        pa_threaded_mainloop_wait(mainloop);
-    }
-
-    if (!success)
-        AUDDBG("pa_stream_cork() failed: %s", pa_strerror(pa_context_errno(context)));
-
-fail:
-
-    if (o)
-        pa_operation_unref(o);
-
-    pa_threaded_mainloop_unlock(mainloop);
-}
-
-static int pulse_free(void) {
-    size_t l = 0;
-    pa_operation *o = NULL;
-
-    CHECK_CONNECTED(0);
-
-    pa_threaded_mainloop_lock(mainloop);
-    CHECK_DEAD_GOTO(fail, 1);
-
-    if ((l = pa_stream_writable_size(stream)) == (size_t) -1) {
-        AUDDBG("pa_stream_writable_size() failed: %s", pa_strerror(pa_context_errno(context)));
-        l = 0;
-        goto fail;
-    }
-
-    /* If this function is called twice with no pulse_write() call in
-     * between this means we should trigger the playback */
-    if (do_trigger) {
-        int success = 0;
-
-        if (!(o = pa_stream_trigger(stream, stream_success_cb, &success))) {
-            AUDDBG("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context)));
-            goto fail;
-        }
-
-        while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-            CHECK_DEAD_GOTO(fail, 1);
-            pa_threaded_mainloop_wait(mainloop);
-        }
-
-        if (!success)
-            AUDDBG("pa_stream_trigger() failed: %s", pa_strerror(pa_context_errno(context)));
-    }
-
-fail:
-    if (o)
-        pa_operation_unref(o);
-
-    pa_threaded_mainloop_unlock(mainloop);
-
-    do_trigger = !!l;
-    return (int) l;
-}
-
-static int pulse_get_output_time (void)
-{
-    int time = 0;
-
-    CHECK_CONNECTED(0);
-
-    pa_threaded_mainloop_lock(mainloop);
-
-    time = written * (int64_t) 1000 / bytes_per_second;
-
-    pa_usec_t usec;
-    int neg;
-    if (pa_stream_get_latency (stream, & usec, & neg) == PA_OK)
-        time -= usec / 1000;
-
-    /* fix for AUDPLUG-308: pa_stream_get_latency() still returns positive even
-     * immediately after a flush; fix the result so that we don't return less
-     * than the flush time */
-    if (time < flush_time)
-        time = flush_time;
-
-    pa_threaded_mainloop_unlock(mainloop);
-
-    return time;
-}
-
-static void pulse_drain(void) {
-    pa_operation *o = NULL;
-    int success = 0;
-
-    CHECK_CONNECTED();
-
-    pa_threaded_mainloop_lock(mainloop);
-    CHECK_DEAD_GOTO(fail, 0);
-
-    if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) {
-        AUDDBG("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto fail;
-    }
-
-    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-        CHECK_DEAD_GOTO(fail, 1);
-        pa_threaded_mainloop_wait(mainloop);
-    }
-
-    if (!success)
-        AUDDBG("pa_stream_drain() failed: %s", pa_strerror(pa_context_errno(context)));
-
-fail:
-    if (o)
-        pa_operation_unref(o);
-
-    pa_threaded_mainloop_unlock(mainloop);
-}
-
-static void pulse_flush(int time) {
-    pa_operation *o = NULL;
-    int success = 0;
-
-    CHECK_CONNECTED();
-
-    pa_threaded_mainloop_lock(mainloop);
-    CHECK_DEAD_GOTO(fail, 1);
-
-    written = time * (int64_t) bytes_per_second / 1000;
-    flush_time = time;
-
-    if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) {
-        AUDDBG("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto fail;
-    }
-
-    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-        CHECK_DEAD_GOTO(fail, 1);
-        pa_threaded_mainloop_wait(mainloop);
-    }
-
-    if (!success)
-        AUDDBG("pa_stream_flush() failed: %s", pa_strerror(pa_context_errno(context)));
-
-fail:
-    if (o)
-        pa_operation_unref(o);
-
-    pa_threaded_mainloop_unlock(mainloop);
-}
-
-static void pulse_write(void* ptr, int length) {
-    int writeoffs, remain, writable;
-
-    CHECK_CONNECTED();
-
-    pa_threaded_mainloop_lock(mainloop);
-    CHECK_DEAD_GOTO(fail, 1);
-
-    /* break large fragments into smaller fragments. --nenolod */
-    for (writeoffs = 0, remain = length;
-         writeoffs < length;
-         writeoffs += writable, remain -= writable)
-    {
-         void * pptr = (char *) ptr + writeoffs;
-
-         writable = length - writeoffs;
-         size_t fragsize = pa_stream_writable_size(stream);
-
-         /* don't write more than what PA is willing to handle right now. */
-         if (writable > fragsize)
-             writable = fragsize;
-
-         if (pa_stream_write(stream, pptr, writable, NULL, PA_SEEK_RELATIVE, 0) < 0) {
-             AUDDBG("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context)));
-             goto fail;
-         }
-    }
-
-    do_trigger = 0;
-    written += length;
-
-fail:
-    pa_threaded_mainloop_unlock(mainloop);
-}
-
-static void pulse_close(void)
-{
-    connected = 0;
-
-    if (mainloop)
-        pa_threaded_mainloop_stop(mainloop);
-
-    if (stream) {
-        pa_stream_disconnect(stream);
-        pa_stream_unref(stream);
-        stream = NULL;
-    }
-
-    if (context) {
-        pa_context_disconnect(context);
-        pa_context_unref(context);
-        context = NULL;
-    }
-
-    if (mainloop) {
-        pa_threaded_mainloop_free(mainloop);
-        mainloop = NULL;
-    }
-
-    volume_time_event = NULL;
-    volume_valid = 0;
-}
-
-static int pulse_open(int fmt, int rate, int nch) {
-    pa_sample_spec ss;
-    pa_operation *o = NULL;
-    int success;
-
-    assert(!mainloop);
-    assert(!context);
-    assert(!stream);
-    assert(!connected);
-
-    switch(fmt)
-    {
-        case FMT_U8:
-            ss.format = PA_SAMPLE_U8;
-            break;
-        case FMT_S16_LE:
-            ss.format = PA_SAMPLE_S16LE;
-            break;
-        case FMT_S16_BE:
-            ss.format = PA_SAMPLE_S16BE;
-            break;
-
-#ifdef PA_SAMPLE_S24_32LE
-        case FMT_S24_LE:
-            ss.format = PA_SAMPLE_S24_32LE;
-            break;
-        case FMT_S24_BE:
-            ss.format = PA_SAMPLE_S24_32BE;
-            break;
-#endif
-
-#ifdef PA_SAMPLE_S32LE
-        case FMT_S32_LE:
-            ss.format = PA_SAMPLE_S32LE;
-            break;
-        case FMT_S32_BE:
-            ss.format = PA_SAMPLE_S32BE;
-            break;
-#endif
-
-	case FMT_FLOAT:
-            ss.format = PA_SAMPLE_FLOAT32NE;
-            break;
-        default:
-            return FALSE;
-    }
-    ss.rate = rate;
-    ss.channels = nch;
-
-    if (!pa_sample_spec_valid(&ss))
-        return FALSE;
-
-    if (!(mainloop = pa_threaded_mainloop_new())) {
-        ERROR ("Failed to allocate main loop");
-        goto fail;
-    }
-
-    pa_threaded_mainloop_lock(mainloop);
-
-    if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) {
-        ERROR ("Failed to allocate context");
-        goto unlock_and_fail;
-    }
-
-    pa_context_set_state_callback(context, context_state_cb, NULL);
-    pa_context_set_subscribe_callback(context, subscribe_cb, NULL);
-
-    if (pa_context_connect(context, NULL, 0, NULL) < 0) {
-        ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    if (pa_threaded_mainloop_start(mainloop) < 0) {
-        ERROR ("Failed to start main loop");
-        goto unlock_and_fail;
-    }
-
-    /* Wait until the context is ready */
-    pa_threaded_mainloop_wait(mainloop);
-
-    if (pa_context_get_state(context) != PA_CONTEXT_READY) {
-        ERROR ("Failed to connect to server: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    if (!(stream = pa_stream_new(context, "Audacious", &ss, NULL))) {
-        ERROR ("Failed to create stream: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    pa_stream_set_state_callback(stream, stream_state_cb, NULL);
-    pa_stream_set_write_callback(stream, stream_request_cb, NULL);
-    pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL);
-
-    /* Connect stream with sink and default volume */
-    /* Buffer struct */
-
-    int aud_buffer = aud_get_int(NULL, "output_buffer_size");
-    size_t buffer_size = pa_usec_to_bytes(aud_buffer, &ss) * 1000;
-    pa_buffer_attr buffer = {(uint32_t) -1, buffer_size, (uint32_t) -1, (uint32_t) -1, buffer_size};
-
-    if (pa_stream_connect_playback(stream, NULL, &buffer, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) {
-        ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-
-    /* Wait until the stream is ready */
-    pa_threaded_mainloop_wait(mainloop);
-
-    if (pa_stream_get_state(stream) != PA_STREAM_READY) {
-        ERROR ("Failed to connect stream: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    /* Now subscribe to events */
-    if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) {
-        ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    success = 0;
-    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-        CHECK_DEAD_GOTO(fail, 1);
-        pa_threaded_mainloop_wait(mainloop);
-    }
-
-    if (!success) {
-        ERROR ("pa_context_subscribe() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    pa_operation_unref(o);
-
-    /* Now request the initial stream info */
-    if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, NULL))) {
-        ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-
-    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
-        CHECK_DEAD_GOTO(fail, 1);
-        pa_threaded_mainloop_wait(mainloop);
-    }
-
-    if (!volume_valid) {
-        ERROR ("pa_context_get_sink_input_info() failed: %s", pa_strerror(pa_context_errno(context)));
-        goto unlock_and_fail;
-    }
-    pa_operation_unref(o);
-
-    do_trigger = 0;
-    written = 0;
-    flush_time = 0;
-    bytes_per_second = FMT_SIZEOF (fmt) * nch * rate;
-    connected = 1;
-    volume_time_event = NULL;
-
-    pa_threaded_mainloop_unlock(mainloop);
-
-    return TRUE;
-
-unlock_and_fail:
-
-    if (o)
-        pa_operation_unref(o);
-
-    pa_threaded_mainloop_unlock(mainloop);
-
-fail:
-
-    pulse_close();
-
-    return FALSE;
-}
-
-static bool_t pulse_init (void)
-{
-    if (! pulse_open (FMT_S16_NE, 44100, 2))
-        return FALSE;
-
-    pulse_close ();
-    return TRUE;
-}
-
-static const char pulse_about[] =
- N_("Audacious PulseAudio Output Plugin\n\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.");
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("PulseAudio Output"),
-    .domain = PACKAGE,
-    .about_text = pulse_about,
-    .probe_priority = 8,
-    .init = pulse_init,
-    .get_volume = pulse_get_volume,
-    .set_volume = pulse_set_volume,
-    .open_audio = pulse_open,
-    .write_audio = pulse_write,
-    .close_audio = pulse_close,
-    .flush = pulse_flush,
-    .pause = pulse_pause,
-    .buffer_free = pulse_free,
-    .drain = pulse_drain,
-    .output_time = pulse_get_output_time
-)
diff --git a/src/pulse_audio/pulse_audio.cc b/src/pulse_audio/pulse_audio.cc
new file mode 100644
index 000000000000..4e828e8fb51a
--- /dev/null
+++ b/src/pulse_audio/pulse_audio.cc
@@ -0,0 +1,625 @@
+/***
+  This file is part of xmms-pulse.
+
+  xmms-pulse 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.
+
+  xmms-pulse is distributed in the hope that 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 xmms-pulse; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+  USA.
+***/
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <pulse/pulseaudio.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/i18n.h>
+
+class PulseOutput : public OutputPlugin
+{
+public:
+    static const char about[];
+
+    static constexpr PluginInfo info = {
+        N_("PulseAudio Output"),
+        PACKAGE,
+        about
+    };
+
+    constexpr PulseOutput () : OutputPlugin (info, 8) {}
+
+    bool init ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int fmt, int rate, int nch);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * ptr, int length);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+};
+
+EXPORT PulseOutput aud_plugin_instance;
+
+static pa_context *context = nullptr;
+static pa_stream *stream = nullptr;
+static pa_threaded_mainloop *mainloop = nullptr;
+
+static pa_cvolume volume;
+static bool volume_valid = false;
+
+static bool connected = false;
+
+#define CHECK_DEAD_GOTO(label, warn) do { \
+if (!mainloop || \
+    !context || pa_context_get_state(context) != PA_CONTEXT_READY || \
+    !stream || pa_stream_get_state(stream) != PA_STREAM_READY) { \
+        if (warn) \
+            AUDDBG("Connection died: %s\n", context ? pa_strerror(pa_context_errno(context)) : "nullptr"); \
+        goto label; \
+    }  \
+} while(0);
+
+#define CHECK_CONNECTED(retval) \
+do { \
+    if (!connected) return retval; \
+} while (0);
+
+static void info_cb(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) {
+    assert(c);
+
+    if (!i)
+        return;
+
+    volume = i->volume;
+    volume_valid = true;
+}
+
+static void subscribe_cb(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata) {
+    pa_operation *o;
+
+    assert(c);
+
+    if (!stream ||
+        index != pa_stream_get_index(stream) ||
+        (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE) &&
+         t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW)))
+        return;
+
+    if (!(o = pa_context_get_sink_input_info(c, index, info_cb, nullptr))) {
+        AUDDBG("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(c)));
+        return;
+    }
+
+    pa_operation_unref(o);
+}
+
+static void context_state_cb(pa_context *c, void *userdata) {
+    assert(c);
+
+    switch (pa_context_get_state(c)) {
+        case PA_CONTEXT_READY:
+        case PA_CONTEXT_TERMINATED:
+        case PA_CONTEXT_FAILED:
+            pa_threaded_mainloop_signal(mainloop, 0);
+            break;
+
+        case PA_CONTEXT_UNCONNECTED:
+        case PA_CONTEXT_CONNECTING:
+        case PA_CONTEXT_AUTHORIZING:
+        case PA_CONTEXT_SETTING_NAME:
+            break;
+    }
+}
+
+static void stream_state_cb(pa_stream *s, void * userdata) {
+    assert(s);
+
+    switch (pa_stream_get_state(s)) {
+
+        case PA_STREAM_READY:
+        case PA_STREAM_FAILED:
+        case PA_STREAM_TERMINATED:
+            pa_threaded_mainloop_signal(mainloop, 0);
+            break;
+
+        case PA_STREAM_UNCONNECTED:
+        case PA_STREAM_CREATING:
+            break;
+    }
+}
+
+static void stream_success_cb(pa_stream *s, int success, void *userdata) {
+    assert(s);
+
+    if (userdata)
+        *(int*) userdata = success;
+
+    pa_threaded_mainloop_signal(mainloop, 0);
+}
+
+static void context_success_cb(pa_context *c, int success, void *userdata) {
+    assert(c);
+
+    if (userdata)
+        *(int*) userdata = success;
+
+    pa_threaded_mainloop_signal(mainloop, 0);
+}
+
+static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
+    assert(s);
+
+    pa_threaded_mainloop_signal(mainloop, 0);
+}
+
+static void stream_latency_update_cb(pa_stream *s, void *userdata) {
+    assert(s);
+
+    pa_threaded_mainloop_signal(mainloop, 0);
+}
+
+StereoVolume PulseOutput::get_volume ()
+{
+    StereoVolume v = {0, 0};
+
+    if (! connected || ! volume_valid)
+        return v;
+
+    pa_threaded_mainloop_lock (mainloop);
+    CHECK_DEAD_GOTO (fail, 1);
+
+    if (volume.channels == 2)
+    {
+        v.left = aud::rescale<int> (volume.values[0], PA_VOLUME_NORM, 100);
+        v.right = aud::rescale<int> (volume.values[1], PA_VOLUME_NORM, 100);
+    }
+    else
+        v.left = v.right = aud::rescale<int> (pa_cvolume_avg (& volume), PA_VOLUME_NORM, 100);
+
+fail:
+    pa_threaded_mainloop_unlock (mainloop);
+    return v;
+}
+
+void PulseOutput::set_volume (StereoVolume v)
+{
+    pa_operation * o;
+
+    if (! connected)
+        return;
+
+    pa_threaded_mainloop_lock (mainloop);
+    CHECK_DEAD_GOTO (fail, 1);
+
+    if (! volume_valid || volume.channels != 1)
+    {
+        volume.values[0] = aud::rescale<int> (v.left, 100, PA_VOLUME_NORM);
+        volume.values[1] = aud::rescale<int> (v.right, 100, PA_VOLUME_NORM);
+        volume.channels = 2;
+    }
+    else
+    {
+        volume.values[0] = aud::rescale<int> (aud::max (v.left, v.right), 100, PA_VOLUME_NORM);
+        volume.channels = 1;
+    }
+
+    volume_valid = true;
+
+    if (! (o = pa_context_set_sink_input_volume (context, pa_stream_get_index
+     (stream), & volume, nullptr, nullptr)))
+        AUDDBG ("pa_context_set_sink_input_volume() failed: %s\n", pa_strerror
+         (pa_context_errno (context)));
+    else
+        pa_operation_unref(o);
+
+fail:
+    pa_threaded_mainloop_unlock (mainloop);
+}
+
+void PulseOutput::pause (bool pause)
+{
+    pa_operation *o = nullptr;
+    int success = 0;
+
+    CHECK_CONNECTED();
+
+    pa_threaded_mainloop_lock(mainloop);
+    CHECK_DEAD_GOTO(fail, 1);
+
+    if (!(o = pa_stream_cork(stream, pause, stream_success_cb, &success))) {
+        AUDDBG("pa_stream_cork() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto fail;
+    }
+
+    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
+        CHECK_DEAD_GOTO(fail, 1);
+        pa_threaded_mainloop_wait(mainloop);
+    }
+
+    if (!success)
+        AUDDBG("pa_stream_cork() failed: %s\n", pa_strerror(pa_context_errno(context)));
+
+fail:
+
+    if (o)
+        pa_operation_unref(o);
+
+    pa_threaded_mainloop_unlock(mainloop);
+}
+
+int PulseOutput::get_delay ()
+{
+    int delay = 0;
+
+    CHECK_CONNECTED(0);
+
+    pa_threaded_mainloop_lock(mainloop);
+
+    pa_usec_t usec;
+    int neg;
+    if (pa_stream_get_latency (stream, & usec, & neg) == PA_OK)
+        delay = usec / 1000;
+
+    pa_threaded_mainloop_unlock(mainloop);
+
+    return delay;
+}
+
+void PulseOutput::drain ()
+{
+    pa_operation *o = nullptr;
+    int success = 0;
+
+    CHECK_CONNECTED();
+
+    pa_threaded_mainloop_lock(mainloop);
+    CHECK_DEAD_GOTO(fail, 0);
+
+    if (!(o = pa_stream_drain(stream, stream_success_cb, &success))) {
+        AUDDBG("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto fail;
+    }
+
+    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
+        CHECK_DEAD_GOTO(fail, 1);
+        pa_threaded_mainloop_wait(mainloop);
+    }
+
+    if (!success)
+        AUDDBG("pa_stream_drain() failed: %s\n", pa_strerror(pa_context_errno(context)));
+
+fail:
+    if (o)
+        pa_operation_unref(o);
+
+    pa_threaded_mainloop_unlock(mainloop);
+}
+
+void PulseOutput::flush ()
+{
+    pa_operation *o = nullptr;
+    int success = 0;
+
+    CHECK_CONNECTED();
+
+    pa_threaded_mainloop_lock(mainloop);
+    CHECK_DEAD_GOTO(fail, 1);
+
+    if (!(o = pa_stream_flush(stream, stream_success_cb, &success))) {
+        AUDDBG("pa_stream_flush() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto fail;
+    }
+
+    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
+        CHECK_DEAD_GOTO(fail, 1);
+        pa_threaded_mainloop_wait(mainloop);
+    }
+
+    if (!success)
+        AUDDBG("pa_stream_flush() failed: %s\n", pa_strerror(pa_context_errno(context)));
+
+fail:
+    if (o)
+        pa_operation_unref(o);
+
+    pa_threaded_mainloop_unlock(mainloop);
+}
+
+void PulseOutput::period_wait ()
+{
+    pa_operation * o = nullptr;
+    int success = 0;
+
+    CHECK_CONNECTED ();
+
+    pa_threaded_mainloop_lock (mainloop);
+    CHECK_DEAD_GOTO (fail, 1);
+
+    if (! (o = pa_stream_trigger (stream, stream_success_cb, & success)))
+    {
+        AUDDBG ("pa_stream_trigger() failed: %s\n", pa_strerror (pa_context_errno (context)));
+        goto fail;
+    }
+
+    while (pa_operation_get_state (o) != PA_OPERATION_DONE)
+    {
+        CHECK_DEAD_GOTO (fail, 1);
+        pa_threaded_mainloop_wait (mainloop);
+    }
+
+    if (! success)
+        AUDDBG ("pa_stream_trigger() failed: %s\n", pa_strerror (pa_context_errno (context)));
+
+    while (! pa_stream_writable_size (stream))
+    {
+        CHECK_DEAD_GOTO (fail, 1);
+        pa_threaded_mainloop_wait (mainloop);
+    }
+
+fail:
+    if (o)
+        pa_operation_unref(o);
+
+    pa_threaded_mainloop_unlock (mainloop);
+}
+
+int PulseOutput::write_audio (const void * ptr, int length)
+{
+    CHECK_CONNECTED(0);
+
+    int ret = 0;
+    pa_threaded_mainloop_lock(mainloop);
+    CHECK_DEAD_GOTO(fail, 1);
+
+    length = aud::min ((size_t) length, pa_stream_writable_size (stream));
+
+    if (pa_stream_write (stream, ptr, length, nullptr, 0, PA_SEEK_RELATIVE) < 0)
+    {
+        AUDDBG ("pa_stream_write() failed: %s\n", pa_strerror (pa_context_errno (context)));
+        goto fail;
+    }
+
+    ret = length;
+
+fail:
+    pa_threaded_mainloop_unlock(mainloop);
+    return ret;
+}
+
+void PulseOutput::close_audio ()
+{
+    connected = false;
+
+    if (mainloop)
+        pa_threaded_mainloop_stop(mainloop);
+
+    if (stream) {
+        pa_stream_disconnect(stream);
+        pa_stream_unref(stream);
+        stream = nullptr;
+    }
+
+    if (context) {
+        pa_context_disconnect(context);
+        pa_context_unref(context);
+        context = nullptr;
+    }
+
+    if (mainloop) {
+        pa_threaded_mainloop_free(mainloop);
+        mainloop = nullptr;
+    }
+
+    volume_valid = false;
+}
+
+static pa_sample_format_t to_pulse_format (int aformat)
+{
+    switch (aformat)
+    {
+    case FMT_U8:      return PA_SAMPLE_U8;
+    case FMT_S16_LE:  return PA_SAMPLE_S16LE;
+    case FMT_S16_BE:  return PA_SAMPLE_S16BE;
+#ifdef PA_SAMPLE_S24_32LE
+    case FMT_S24_LE:  return PA_SAMPLE_S24_32LE;
+    case FMT_S24_BE:  return PA_SAMPLE_S24_32BE;
+#endif
+#ifdef PA_SAMPLE_S32LE
+    case FMT_S32_LE:  return PA_SAMPLE_S32LE;
+    case FMT_S32_BE:  return PA_SAMPLE_S32BE;
+#endif
+	case FMT_FLOAT:   return PA_SAMPLE_FLOAT32NE;
+    default:          return PA_SAMPLE_INVALID;
+    }
+}
+
+bool PulseOutput::open_audio (int fmt, int rate, int nch)
+{
+    pa_sample_spec ss;
+
+    assert(!mainloop);
+    assert(!context);
+    assert(!stream);
+    assert(!connected);
+
+    ss.format = to_pulse_format (fmt);
+    if (ss.format == PA_SAMPLE_INVALID)
+        return false;
+
+    ss.rate = rate;
+    ss.channels = nch;
+
+    if (!pa_sample_spec_valid(&ss))
+        return false;
+
+    if (!(mainloop = pa_threaded_mainloop_new())) {
+        AUDERR ("Failed to allocate main loop\n");
+        return false;
+    }
+
+    pa_threaded_mainloop_lock(mainloop);
+
+    if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Audacious"))) {
+        AUDERR ("Failed to allocate context\n");
+        goto FAIL1;
+    }
+
+    pa_context_set_state_callback(context, context_state_cb, nullptr);
+    pa_context_set_subscribe_callback(context, subscribe_cb, nullptr);
+
+    if (pa_context_connect(context, nullptr, (pa_context_flags_t) 0, nullptr) < 0) {
+        AUDERR ("Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL1;
+    }
+
+    if (pa_threaded_mainloop_start(mainloop) < 0) {
+        AUDERR ("Failed to start main loop\n");
+        goto FAIL1;
+    }
+
+    /* Wait until the context is ready */
+    pa_threaded_mainloop_wait(mainloop);
+
+    if (pa_context_get_state(context) != PA_CONTEXT_READY) {
+        AUDERR ("Failed to connect to server: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL1;
+    }
+
+    if (!(stream = pa_stream_new(context, "Audacious", &ss, nullptr))) {
+        AUDERR ("Failed to create stream: %s\n", pa_strerror(pa_context_errno(context)));
+
+FAIL1:
+        pa_threaded_mainloop_unlock (mainloop);
+        close_audio ();
+        return false;
+    }
+
+    pa_stream_set_state_callback(stream, stream_state_cb, nullptr);
+    pa_stream_set_write_callback(stream, stream_request_cb, nullptr);
+    pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, nullptr);
+
+    /* Connect stream with sink and default volume */
+    /* Buffer struct */
+
+    int aud_buffer = aud_get_int(nullptr, "output_buffer_size");
+    size_t buffer_size = pa_usec_to_bytes(aud_buffer, &ss) * 1000;
+    pa_buffer_attr buffer = {(uint32_t) -1, (uint32_t) buffer_size,
+     (uint32_t) -1, (uint32_t) -1, (uint32_t) buffer_size};
+
+    pa_operation *o = nullptr;
+    int success;
+
+    if (pa_stream_connect_playback (stream, nullptr, & buffer, (pa_stream_flags_t)
+     (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
+    {
+        AUDERR ("Failed to connect stream: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+
+
+    /* Wait until the stream is ready */
+    pa_threaded_mainloop_wait(mainloop);
+
+    if (pa_stream_get_state(stream) != PA_STREAM_READY) {
+        AUDERR ("Failed to connect stream: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+
+    /* Now subscribe to events */
+    if (!(o = pa_context_subscribe(context, PA_SUBSCRIPTION_MASK_SINK_INPUT, context_success_cb, &success))) {
+        AUDERR ("pa_context_subscribe() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+
+    success = 0;
+    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
+        CHECK_DEAD_GOTO(FAIL2, 1);
+        pa_threaded_mainloop_wait(mainloop);
+    }
+
+    if (!success) {
+        AUDERR ("pa_context_subscribe() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+
+    pa_operation_unref(o);
+
+    /* Now request the initial stream info */
+    if (!(o = pa_context_get_sink_input_info(context, pa_stream_get_index(stream), info_cb, nullptr))) {
+        AUDERR ("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+
+    while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
+        CHECK_DEAD_GOTO(FAIL2, 1);
+        pa_threaded_mainloop_wait(mainloop);
+    }
+
+    if (!volume_valid) {
+        AUDERR ("pa_context_get_sink_input_info() failed: %s\n", pa_strerror(pa_context_errno(context)));
+        goto FAIL2;
+    }
+    pa_operation_unref(o);
+
+    connected = true;
+
+    pa_threaded_mainloop_unlock(mainloop);
+
+    return true;
+
+FAIL2:
+    if (o)
+        pa_operation_unref(o);
+
+    pa_threaded_mainloop_unlock(mainloop);
+    close_audio ();
+    return false;
+}
+
+bool PulseOutput::init ()
+{
+    if (! open_audio (FMT_S16_NE, 44100, 2))
+        return false;
+
+    close_audio ();
+    return true;
+}
+
+const char PulseOutput::about[] =
+ N_("Audacious PulseAudio Output Plugin\n\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.");
diff --git a/src/qtaudio/Makefile b/src/qtaudio/Makefile
new file mode 100644
index 000000000000..1020965fd528
--- /dev/null
+++ b/src/qtaudio/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = qtaudio${PLUGIN_SUFFIX}
+
+SRCS = qtaudio.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
+
+LD = ${CXX}
+CPPFLAGS += -I../.. ${QTMULTIMEDIA_CFLAGS}
+CXXFLAGS += ${GLIB_CFLAGS} ${PLUGIN_CFLAGS}
+LIBS += -lm ${GLIB_LIBS} ${QTMULTIMEDIA_LIBS}
diff --git a/src/qtaudio/qtaudio.cc b/src/qtaudio/qtaudio.cc
new file mode 100644
index 000000000000..40df5583debf
--- /dev/null
+++ b/src/qtaudio/qtaudio.cc
@@ -0,0 +1,302 @@
+/*
+ * QtMultimedia Audio Output Plugin for Audacious
+ * Copyright 2014 William Pitcock
+ *
+ * Based on:
+ * SDL Output Plugin for Audacious
+ * Copyright 2010 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 <math.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include <QAudioOutput>
+
+#define VOLUME_RANGE 40 /* decibels */
+
+#define error(...) do { \
+    aud_ui_show_error (str_printf ("QtAudio error: " __VA_ARGS__)); \
+} while (0)
+
+class QtAudio : public OutputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+
+    static constexpr PluginInfo info = {
+        N_("QtMultimedia Output"),
+        PACKAGE,
+        about
+    };
+
+    constexpr QtAudio () : OutputPlugin (info, 1) {}
+
+    bool init ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int aud_format, int rate, int chan);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+};
+
+EXPORT QtAudio aud_plugin_instance;
+
+const char QtAudio::about[] =
+ N_("QtMultimedia Audio Output Plugin for Audacious\n"
+    "Copyright 2014 William Pitcock\n\n"
+    "Based on SDL Output Plugin for Audacious\n"
+    "Copyright 2010 John Lindgren");
+
+const char * const QtAudio::defaults[] = {
+ "vol_left", "100",
+ "vol_right", "100",
+ nullptr};
+
+static const timespec fifty_ms = {0, 50000000};
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static int bytes_per_sec;
+static bool paused;
+static int last_buffered, delay_estimate;
+static timeval last_system_time;
+
+static QAudioOutput * output_instance = nullptr;
+static QIODevice * buffer_instance = nullptr;
+
+struct FormatDescriptionMap {
+    int aud_format;
+
+    unsigned int sample_size;
+    enum QAudioFormat::SampleType sample_type;
+    enum QAudioFormat::Endian endian;    
+};
+static struct FormatDescriptionMap FormatMap[] = {
+    {FMT_S16_LE, 16, QAudioFormat::SignedInt, QAudioFormat::LittleEndian},
+    {FMT_S16_BE, 16, QAudioFormat::SignedInt, QAudioFormat::BigEndian},
+    {FMT_U16_LE, 16, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian},
+    {FMT_U16_BE, 16, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian},
+    {FMT_S32_LE, 32, QAudioFormat::SignedInt, QAudioFormat::LittleEndian},
+    {FMT_S32_BE, 32, QAudioFormat::SignedInt, QAudioFormat::BigEndian},
+    {FMT_U32_LE, 32, QAudioFormat::UnSignedInt, QAudioFormat::LittleEndian},
+    {FMT_U32_BE, 32, QAudioFormat::UnSignedInt, QAudioFormat::BigEndian},
+    {FMT_FLOAT, 32, QAudioFormat::Float, QAudioFormat::LittleEndian},
+};
+
+bool QtAudio::init ()
+{
+    aud_config_set_defaults ("qtaudio", defaults);
+    return true;
+}
+
+StereoVolume QtAudio::get_volume ()
+{
+    return {aud_get_int ("qtaudio", "vol_left"), aud_get_int ("qtaudio", "vol_right")};
+}
+
+void QtAudio::set_volume (StereoVolume v)
+{
+    int vol_max = aud::max (v.left, v.right);
+
+    aud_set_int ("qtaudio", "vol_left", v.left);
+    aud_set_int ("qtaudio", "vol_right", v.right);
+
+    if (output_instance)
+    {
+        float factor = (vol_max == 0) ? 0.0 : powf (10, (float) VOLUME_RANGE * (vol_max - 100) / 100 / 20);
+
+        output_instance->setVolume (factor);
+    }
+}
+
+bool QtAudio::open_audio (int format, int rate, int chan)
+{
+    struct FormatDescriptionMap * m = nullptr;
+
+    for (struct FormatDescriptionMap it : FormatMap)
+    {
+        if (it.aud_format == format)
+        {
+            m = & it;
+            break;
+        }
+    }
+
+    if (! m)
+    {
+        error ("The requested audio format %d is unsupported.\n", format);
+        return false;
+    }
+
+    AUDDBG ("Opening audio for %d channels, %d Hz.\n", chan, rate);
+
+    bytes_per_sec = FMT_SIZEOF (format) * chan * rate;
+
+    int buffer_ms = aud_get_int (nullptr, "output_buffer_size");
+    int buffer_size = FMT_SIZEOF (format) * chan * aud::rescale (buffer_ms, 1000, rate);
+
+    paused = false;
+    last_buffered = 0;
+    delay_estimate = 0;
+
+    gettimeofday (& last_system_time, nullptr);
+
+    QAudioFormat fmt;
+    fmt.setSampleRate (rate);
+    fmt.setChannelCount (chan);
+    fmt.setSampleSize (m->sample_size);
+    fmt.setCodec ("audio/pcm");
+    fmt.setByteOrder (m->endian);
+    fmt.setSampleType (m->sample_type);
+
+    QAudioDeviceInfo info (QAudioDeviceInfo::defaultOutputDevice ());
+    if (! info.isFormatSupported (fmt))
+    {
+        error ("Format not supported by backend.\n");
+        return false;
+    }
+
+    output_instance = new QAudioOutput (fmt, nullptr);
+    output_instance->setBufferSize (buffer_size);
+    buffer_instance = output_instance->start ();
+
+    set_volume (get_volume ());
+
+    return true;
+}
+
+void QtAudio::close_audio ()
+{
+    AUDDBG ("Closing audio.\n");
+
+    output_instance->stop ();
+
+    delete output_instance;
+    output_instance = nullptr;
+}
+
+void QtAudio::period_wait ()
+{
+    pthread_mutex_lock (& mutex);
+
+    while (output_instance->bytesFree () < output_instance->periodSize ())
+        pthread_cond_timedwait (& cond, & mutex, & fifty_ms);
+
+    pthread_mutex_unlock (& mutex);
+}
+
+int QtAudio::write_audio (const void * data, int len)
+{
+    pthread_mutex_lock (& mutex);
+
+    len = aud::min (len, output_instance->bytesFree ());
+    buffer_instance->write ((const char *) data, len);
+    last_buffered += len;
+
+    pthread_mutex_unlock (& mutex);
+    return len;
+}
+
+void QtAudio::drain ()
+{
+    AUDDBG ("Draining.\n");
+    pthread_mutex_lock (& mutex);
+
+    while (output_instance->bytesFree () < output_instance->bufferSize ())
+        pthread_cond_timedwait (& cond, & mutex, & fifty_ms);
+
+    pthread_mutex_unlock (& mutex);
+}
+
+int QtAudio::get_delay ()
+{
+    auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
+        { return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
+
+    pthread_mutex_lock (& mutex);
+
+    int buffered = output_instance->bufferSize () - output_instance->bytesFree ();
+    int delay = aud::rescale (buffered, bytes_per_sec, 1000);
+
+    timeval now;
+    gettimeofday (& now, nullptr);
+
+    if (buffered == last_buffered && ! paused)
+        delay += aud::max (delay_estimate - timediff (last_system_time, now), (int64_t) 0);
+    else
+    {
+        delay_estimate = aud::rescale (last_buffered - buffered, bytes_per_sec, 1000);
+        delay += delay_estimate;
+        last_buffered = buffered;
+        last_system_time = now;
+    }
+
+    pthread_mutex_unlock (& mutex);
+    return delay;
+}
+
+void QtAudio::pause (bool pause)
+{
+    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
+    pthread_mutex_lock (& mutex);
+
+    if (pause)
+        output_instance->suspend ();
+    else
+        output_instance->resume ();
+
+    paused = pause;
+
+    pthread_cond_broadcast (& cond); /* wake up period wait */
+    pthread_mutex_unlock (& mutex);
+}
+
+void QtAudio::flush ()
+{
+    AUDDBG ("Seek requested; discarding buffer.\n");
+    pthread_mutex_lock (& mutex);
+
+    last_buffered = 0;
+    delay_estimate = 0;
+
+    gettimeofday (& last_system_time, nullptr);
+
+    output_instance->reset ();
+    buffer_instance = output_instance->start ();
+
+    pthread_cond_broadcast (& cond); /* wake up period wait */
+    pthread_mutex_unlock (& mutex);
+}
diff --git a/src/qtui/Makefile b/src/qtui/Makefile
new file mode 100644
index 000000000000..058123190307
--- /dev/null
+++ b/src/qtui/Makefile
@@ -0,0 +1,107 @@
+PLUGIN = qtui${PLUGIN_SUFFIX}
+
+SRCS = qtui.cc \
+       dialog_windows.cc \
+       main_window.cc \
+       main_window_actions.cc \
+       playlist.cc \
+       playlist_model.cc \
+       playlist_tabs.cc \
+       filter_input.cc \
+       info_bar.cc \
+       status_bar.cc \
+       tool_bar.cc \
+       time_slider.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+# These overrides variables in buildsys.mk and so must come after it.
+PACKAGE_NAME = audacious
+
+CUSTOM_ICONS=no
+ifeq ($(HAVE_MSWINDOWS),yes)
+CUSTOM_ICONS=yes
+endif
+ifeq ($(HAVE_DARWIN),yes)
+CUSTOM_ICONS=yes
+endif
+
+ifeq ($(CUSTOM_ICONS),yes)
+DATA = QtUi/16/audio-volume-high.png \
+       QtUi/16/audio-volume-low.png \
+       QtUi/16/audio-volume-medium.png \
+       QtUi/16/audio-volume-muted.png \
+       QtUi/16/audio-volume-off.png \
+       QtUi/16/document-open.png \
+       QtUi/16/edit-find.png \
+       QtUi/16/list-add.png \
+       QtUi/16/media-playback-pause.png \
+       QtUi/16/media-playback-start.png \
+       QtUi/16/media-playback-stop.png \
+       QtUi/16/media-playlist-repeat.png \
+       QtUi/16/media-playlist-shuffle.png \
+       QtUi/16/media-skip-backward.png \
+       QtUi/16/media-skip-forward.png \
+       QtUi/22/audio-volume-high.png \
+       QtUi/22/audio-volume-low.png \
+       QtUi/22/audio-volume-medium.png \
+       QtUi/22/audio-volume-muted.png \
+       QtUi/22/audio-volume-off.png \
+       QtUi/22/document-open.png \
+       QtUi/22/edit-find.png \
+       QtUi/22/list-add.png \
+       QtUi/22/media-playback-pause.png \
+       QtUi/22/media-playback-start.png \
+       QtUi/22/media-playback-stop.png \
+       QtUi/22/media-playlist-repeat.png \
+       QtUi/22/media-playlist-shuffle.png \
+       QtUi/22/media-skip-backward.png \
+       QtUi/22/media-skip-forward.png \
+       QtUi/32/audio-volume-high.png \
+       QtUi/32/audio-volume-low.png \
+       QtUi/32/audio-volume-medium.png \
+       QtUi/32/audio-volume-muted.png \
+       QtUi/32/audio-volume-off.png \
+       QtUi/32/document-open.png \
+       QtUi/32/edit-find.png \
+       QtUi/32/list-add.png \
+       QtUi/32/media-playback-pause.png \
+       QtUi/32/media-playback-start.png \
+       QtUi/32/media-playback-stop.png \
+       QtUi/32/media-playlist-repeat.png \
+       QtUi/32/media-playlist-shuffle.png \
+       QtUi/32/media-skip-backward.png \
+       QtUi/32/media-skip-forward.png \
+       QtUi/44/audio-volume-high.png \
+       QtUi/44/audio-volume-low.png \
+       QtUi/44/audio-volume-medium.png \
+       QtUi/44/audio-volume-muted.png \
+       QtUi/44/audio-volume-off.png \
+       QtUi/44/document-open.png \
+       QtUi/44/edit-find.png \
+       QtUi/44/list-add.png \
+       QtUi/44/media-playback-pause.png \
+       QtUi/44/media-playback-start.png \
+       QtUi/44/media-playback-stop.png \
+       QtUi/44/media-playlist-repeat.png \
+       QtUi/44/media-playlist-shuffle.png \
+       QtUi/44/media-skip-backward.png \
+       QtUi/44/media-skip-forward.png \
+       QtUi/AUTHORS \
+       QtUi/index.theme
+endif
+
+plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
+
+LD = ${CXX}
+
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${QT_CFLAGS}
+LIBS += ${QT_LIBS} -laudqt
+
+%.moc: %.h
+	moc $< -o $@
+
+rc_%.cc: %.qrc
+	rcc $< -o $@
diff --git a/src/qtui/QtUi/16/audio-volume-high.png b/src/qtui/QtUi/16/audio-volume-high.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b0a4de4b81c7d100cce57d2cffe0e75b296d539
GIT binary patch
literal 709
zcmV;$0y_PPP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10zyedK~y-6rBgv`6HyTU=DlQ>5VxsF*T#ktNzjlIFab#;;-!b8
zLJx%y^im1l1P?{9#FJw17nn=0g&xF1NGTK#;<3H7Cb|$vY0(NzYnF6r5^Kqh2eYLu
z9x8n>@R%9C`QH1!A!f#Tj`)vWT3K1STCdkHpU5)vS%R4PilQhbUDw|*v)8Hpi-8M(
z=lEp9Fowh7 at WWUv_I+n(=YA%WxeY*`W<bpBNvG3y{eJ&TX4aUQ8jVIE6bj`4RI}Oa
zGfmSL-EQ}LW*%VXzW}Cb4#(s1$H8FmIT3x9QWlwcz%UHIqA10QiHR4wuD_E~E>2EP
zP6PN<EEcahPw+&e(MPMRt4}sJH`B~)5|If2nx+Y#&!;RbEZi9z8~fPpc0FFNcN;*v
zP$)zk6 at --XCxCANegLqDXdeIqfq*$WI{Lx3?XIe-y8!l@&88%x_QuA>007km04|s7
z0DyJ$YeX&QUaeMJ0Cqc_&H;dZRaN(h=%BB!@0Y{Cjzl6>55Vd%XahjGT)wovz8)VO
z9NenaY8QnNEh(kfw(ZXN`1m$}-vU6VR4Ub$mX^wMb8}yOK3_u!u at 3-32udcCwOlUu
zwNk0v2nK^&Yiny4q?Da(HoFbrgjpmr_Zx<hE))uxo>}Pd at GzB1rJf2QUeC_XK9Ewr
zO(YUC%&Z^Dcq-hE#*RNs)4Vx9KR-1zG?Z6W_0{t7^1a@`Gh10$mUVq(WMn3v&rdOP
rzf(Ia0GL at co6TFy96p|>^RDwBx-66N2i7`600000NkvXXu0mjfo`^D@

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/audio-volume-low.png b/src/qtui/QtUi/16/audio-volume-low.png
new file mode 100644
index 0000000000000000000000000000000000000000..629da844f8e8d2c6ac8c61ed86accf7ff762c5dc
GIT binary patch
literal 577
zcmV-H0>1r;P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10lrB@K~y-6rISI6Qc)Dgf9Jl(kUh$3pk7Z}xHG|EpwL-ct!5>R
zNegN3%2jK>gkQvEf%FMn2!@)VF)@<qV{|Oio~K3ckxfPnbKt<`aL(`i at 1J``Rk=!-
z%QTC~U;UQ?00$zH{2#yuu3y+JBH{u8 at K8jYT>t at M#bWW9=XtMzn}AHGQ?FDiWq`-P
zDX<0}ZEq9b_aEf*`RBgx?~g{Km&TYOaIM$t-N<Az^<*;n)^*+9csx!410XFTmZ}B@
zh^5o%SFKj7G8_(%RdpsJGe8{2G4XhOuix(<6$*t}sA?IijYn57mSuebJ_4VBxrm$t
zBoc{fE|+_=*=&L!2qIq$pb@|Zux<N0FyAt58J)Y`?h=@|uKOb_{qb-Nut}v-^AIo(
z6?_F~x7+)J!QjAk-IK*)u?-O5EK=~T(P#{s&E}oSWMV3n%Kg=9bq=UyStgs!ekhmA
zC$(BF9xiY~$k{KPYLvFB-tKfd$Mt&sg{nHLYS!!ZlWMh^1&)Bbz*FEbnv)%WVGp<k
zeBScJ0QbW5fOo38j6Ap)tL@=X<pvl7G2neP4D3|!&kzw4!hYAT`kj9QTCux+y503g
P00000NkvXXu0mjfU_Abd

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/audio-volume-medium.png b/src/qtui/QtUi/16/audio-volume-medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..eb1bc0d071fde6cfb53d253c7499324a29864ed0
GIT binary patch
literal 632
zcmV-;0*C#HP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10rg2lK~y-6rISBvQ(+Xwf9HLZ8#JvK?-0^b$}MzA7BMcliQp0k
z36e!xoph+;AUG<-)z8pRP$<-?5QO01M<^y5Xh at _;ooW+OlKwFy$LWUn2etITGo1H%
z&X4mBM^u%IlsQjWM1ITvFTen^kx1l*h%EgJ5C!7XnP#);FE1}Y&FAxRAT1&je;Qzb
z`0DEF?fLon7r+(3bi3V!VzKz3-EKcQJw5e3&jYwNnNn5hcDsHilX>j>{!0=0V6EL&
z)nv2TTyPv`yHqN at N+c3*thH~~*46^xE?`v^16)q0(+_uccAo9+?X9S4M?^XRGcz;B
zbzP at YsoW|Q3hzgw(Iv-mVt at c{xVEv at egnP$Ux6bL=>yEo%^e0o at NPUFk7BXd0nlqS
z8i{B$$~1sTByt8Eg%XiL_{H7b-2rfLa&mG8^cNQwCte5`r&6h-UjWAd^?KcFx7(Ry
zGP&PswXPat20;)EhQlF1F9aM{DwWUGYPGhpvGLJ$-9uwcAHZ5`ve|5_TrPjA*X!4P
z-`}s*YTp430jO%IsH%F6Mq_1tef_?w&Z?>z4u>~$x!iMO%<HYKt$VKP-T`vq+%zDR
zqpFFi-gG*h?B?d?qf)6<0E$5TZ-76^^m;uH$N@{!o}A|zMZ~D;_@}pvp7RgD=?&!o
S-m|3u0000<MNUMnLSTYlr5QT_

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/audio-volume-muted.png b/src/qtui/QtUi/16/audio-volume-muted.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3e3c647d2090bc75f8cf58a365fd89984914e07
GIT binary patch
literal 527
zcmV+q0`UEbP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10gOpRK~y-6rINpk6Hyd}zk9>N7Be<m*ozBxyNH#RB7&@T(Za?~
zK}5n#>SXM6#zNLY()a at w#1Skk{TBqcvsgtY0XwmnV54u2MV62aBSby$ig(|8-#z!f
zYm)dM`QKa~jYeyL{WGAh>%F2V?kvV^l at iLb>{L~C#mp|7*|iYDcE8_0Xmyb1`DRfR
zR~M61RdvJ6UIQ;BeRuaKM;v5X=5ZWflC%Ll1jb2{oG#0<GairkfLFjh;Fp=bkn~_W
zogNzu20t7iilV!c-U82njU{L2fcs{)3v4w_^AYI8alAb*!OV`g)!yxPgPDzhlOcr9
z0Pem9G)>c-Y3;$XB-zsbNY|Yi?rYoQ!+*aCd~x>^03n2*Gb8?f4oK5<SJDMZ*MV<9
zv%vWPq`+-p-`!6Ep|0zFXqkgN&o|xuY?36;VKxJk$>f%#N0Kg@*;C*kNs{xefHq}W
zwjM>%4zOcpT{GM2^?ILH1{^{>ilTRt-lS>zczz&h<ux1**Cp9vY-I<3(r?5S)ttN7
R08an_002ovPDHLkV1l9H<iY>|

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/audio-volume-off.png b/src/qtui/QtUi/16/audio-volume-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..a5378493529e54a7671c8289f81e5623a34c2b5b
GIT binary patch
literal 495
zcmV<L0TBL)P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10c=S`K~y-6rIWo%13?spzcagn8b!2F5sX?0(ITL+u~!HvR*OD>
zbqZf2uagG|zCs#75Y%YQHi2F8gApBz%;FkXBzWOAGjqRt?wJ``Yxz%@Ne)Z;aeg8I
zuqSEjFMtQkj&+u#Rp1 at ik(A2<2$&9n;5eVpUyVW5fdk+Lcms;bh7Ztcwesb1`6P;>
z#b&d4VT`#4W+e at PeV_$&fdX&`>`L;iweLPKQ!14%+wJz5lh~2eNp)WW7F=Nw=sC3u
zK*s>a^Slsv1fGFdQWwCE?)U-70fW at o)&WK%_`d%N#3|Ey8RjPO?co^UqfjWs4iGy9
zeFrkY2G9p)QUC!_qF_*~)o$zc`cfE%rc$Y_4Tr;Ss!0Sq0o$%Y&OsvFoavlzG#Wv*
zT0OVc&benUU=uh6mVqPSFsV_-UzlR#e3<gY04pxnfNN`QFY#bJ-qOWR<p<DqKHMb5
lK&FCULy~c at ueJYv=T8-Ij+dLsYa##u002ovPDHLkV1g)+$hQCh

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/document-open.png b/src/qtui/QtUi/16/document-open.png
new file mode 100644
index 0000000000000000000000000000000000000000..2139547d213398c690ce174c863453e82021279e
GIT binary patch
literal 585
zcmV-P0=E5$P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10mey0K~y-6l~X;7+dvR~yI#p~!p6zPAGiu>R5+wpYcQlq;UWQd
zZVj&U8}bKC3X{TW-K0q&+{Y<`1FD>uBUKQG4hIa5&L^!Wg-42_<nr-gSZQ|V&70j>
zK}29E0A>Cr01>Z$1`&aX&U(GxQ_HeumSxQ<mCCE>boz*h>bIE1c at V6iUaeMVTI&Y$
z3LykZDG$Yh$K&zFah#Wn#o`Tsy#fH=_sfI9-~)g=|Dc#Qo6Upea#?d6XD^7zY`5Fb
zgCKYY;P}^`PmrxvYaRr_3kARc at D0FaK0+xKH=E5c at 7r#-wJ3_txW_#JQ}NF=lVs?2
zyYD>DdkY{*tB%Lxhm*<VaV`fct%lRJWmvD*R{-7v*t5%6tycHaIL<i{NGao at 0`{Tc
z(`j6~|6c^AX(qoVFbv}t0`~ocQmK?FNcSaxq|@nKb8ndmA(C4NA^;KRBnrU6b=}Xy
z;jq5j?IZw<Mx&b6S^&5Upqh3S$FT$uxvm at b`~3?52a$VBWt?W>ywPYp3B&Ndl(Jb6
z at l`4H#rOT!wrzjR&VX at XOXl<WrRRCE*7{Si4aaeAY}?L;F0UXD6F`g4sE80hW&_^=
XSC7)qWU`e500000NkvXXu0mjf5?ljK

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/edit-find.png b/src/qtui/QtUi/16/edit-find.png
new file mode 100644
index 0000000000000000000000000000000000000000..267657225804ae635996f799bf4f0e0d124ce7e2
GIT binary patch
literal 643
zcmV-}0(||6P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10su)wK~y-6osvz65^)&DpT9GXvxALao0*6-VnOK8r9~t!;YqN<
z%btQg1R;cnD59%3BQ_|MrGs4zL9mkt4|)iUE)pJ+p=6i6WkV8#u#8OG+o7GsHKmUS
z9{wM^{NR0`mk|+`hyx%1FadmDR$$4t at D|GDvZ^S`J-6HaBpePuC>D#C0f;LJL}YnQ
zRn^;!u_1t6o6V*H*kz1;P!#1p5jp2-k8NF8KA*n=U=Rw0UX at Cvhm*<VMx|1 at 8;wR^
z0(hUvWUdhrw+bN1vb+u8O|@FxBqH(X-`?-{GaSdg7De$n5xG_Yys|9s1OkB<M094M
z$P<gjwmFV#5Yg#HfHlNJkH_;>*Y#7Hra2Z98I4A6K at h$G_$@LEU?dWWJtAV+Z1y?;
zF916LS2CGQo2KbiRdop9U=hF{owHi4_I5ZNUeq)#BM3q&7!1DCbv<qvh9AHr5{Z1m
zul+b7Hn&JNUDvM`3WbeUt98yWjCGFVzNORYea6_2PN#E8lBCb=cKc~6mD;!3nFm-p
zKby at ijK^cA-|s(=Bx%nyO{dT2+ni3PE{DTG-EOyZ3|Y1uOT1RE*KhJX{|LY{Q51K2
zy<TKK#=o(z(P(V(JYNLxI3ADRA|m_006;|R&1Q2em&@H53<euSv~&i4k_W(903QJy
d{tw`UegbQ#eeY_WZX^Hz002ovPDHLkV1l5)2q^#n

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/list-add.png b/src/qtui/QtUi/16/list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ae4c7d6dab49048d6e654b75043559f97763ff3
GIT binary patch
literal 463
zcmV;=0WkiFP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10Zd6mK~y-6rISHQ!%z^0zqDy%Q>d7geNZS05qHIIgq|R0=mlK$
zAl-H6(#v!i?6wO<Xvr(hLM&Q|QN~T8FWR8cfq at z3pa0Fzys<=teXO!qH(-|$Yppx;
z`Md$(`~HhkY6<)vS44Js)APJB5CM_rd1DcAcVSB<xURbZG@!HiPYD*#$YRH~?RQ`c
zkj0LHea+=q`4*xm>hyZOs~oY}Y>tv7IR$VW=dRUiJ?6F9Y<8`bS`;Q&uh$209A6r*
zB>4nMl62!ZJ~Oa4N~xlRdc7{dszmD6Ofqbdpxti2jYgx}JfBXdhhZ2V1N8g-)nG7q
zGO=H5#!9Lp(#_ltf?x<tfJqPpLlN<fdNuDex9|ZxWN}k#eV&i5wSEScKcy5T{3_UX
z%J&-6GMrU%OqDcEFGS=7z_P6STCEnc<13dD{M+`v#!sWowyTVD1m^$%002ovPDHLk
FV1mF1#F792

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-playback-pause.png b/src/qtui/QtUi/16/media-playback-pause.png
new file mode 100644
index 0000000000000000000000000000000000000000..993d3fad541ec8474384a57fec1393f870cd32e2
GIT binary patch
literal 380
zcmeAS at N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf<Z~8yL>4nJ
za0!Ai<Bf}ULO?;u64!{5;QX|b^2DN4hVt at qz0ADq;^f4FRK5J7^x5xhq=1Tkdb&7<
zSoCh4ywR`4L7;7atE%)9Q4OB=2^mwv5B!MR(;i~iu+1byWLmg at 7FXA9)%L0zI%zxa
ztTjB6nP&X|jQMYI<!6;?-W9W#F;*^I#*lb#etNBXLJ{L46JPn;+xD`a`22@=fzIjb
z28+J(&`?|E_H2f$CTHhf`^C6m-Rts(b+6|!v?W%s#>Fr!nPPi^*(Gp`$+v0S-r4K_
z*k`XRJtZi9S<MC$a|aGX##=l(47r*6nfk6BoBWq~@!!p?=Reo!usCkmlmJxVRe81P
z;+%%$K#|{tGSLkxo at xy`r=uDSc)lOtQqq&T%quYCdqz>lr{hV-S$_oQ>^qh(5EQdU
T*2-QE7zhlWu6{1-oD!M<u_=$V

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-playback-start.png b/src/qtui/QtUi/16/media-playback-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..687781f2528eca784d8c21036e4dd3bb975e2407
GIT binary patch
literal 437
zcmV;m0ZRUfP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10WwKMK~y-6&67b(0#Ou&zc)_JVi-f5c7jCfK%_uuA-L-&)GD{S
z at dpI%TG%>fl|RQ;Nf06k1%b at cAX03CP8*BKu~OW0;H=)cANSpNpOM5mvev3z0N9vL
zr+L6znjk6eE!TCgeBW<{VVIY+Id`6L0^oVxIdEr;xh at uqr;@fMSw8_1Gcd+Pz(~?t
zx7%$vjuX^swL>7i%nV4SQV}o)UVt!)qI3`h7ujs~tkdc20?x01SqGDtpMl|MG}<ed
z%a`qT`v5SXd3yoib=JW*6$*tx5Cnr#sq_eZEl&avy8-~d?~hxp)<d;gy#;Q7D4tIM
zEX#_3iEZ2O^?H5SY&P#RnM?<Gn$H5sXUyetCzVR2(eL+<CGD)b2X3#|JCd|7$^NTY
f66W81rj_*pj=A;oOL!k`00000NkvXXu0mjf4_vc-

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-playback-stop.png b/src/qtui/QtUi/16/media-playback-stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec322be27fb045f2a42021c745104cb1065e10c3
GIT binary patch
literal 327
zcmeAS at N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf<Z~8yL>4nJ
za0!Ai<Bf}ULO?;u64!{5;QX|b^2DN4hVt at qz0ADq;^f4FRK5J7^x5xhq=1T!c)B=-
zSoAKv?9bKYAaeZU`p at kLnJXIe1od`1 at AxPrciNhz@j{f1Gl%191;<l47e!PrN1VCM
z`{!P}`G+`@K4nGKrd^Dtm8az|Fz(pNFfsM!s#U9&uDABR92+ at pw)!W&6T8-l=iXjd
z>u}kGJ>fM|$KxL?GPMn7_q<}h5Eb9JnSX<%xk8IX!#VaFJ<=0`&iN%6=N*tR<_7XO
z{xt<<l`+jOWO5D^iJkYnT7H6x=ka7|#tyaPOBf$BH^}X%Vg9%7LG~VIJ~i9AgQp~I
Qfc|0dboFyt=akR{0C{P4#sB~S

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-playlist-repeat.png b/src/qtui/QtUi/16/media-playlist-repeat.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a5e6d6130dab997d49af977079b25367e457284
GIT binary patch
literal 555
zcmV+`0 at VG9P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10jNntK~y-6rIRse6LA#Ae}By#O%F at 89wgy}4B^0<4xx(>*CS*I
z?zf0*K=*8&DuR<^Aa%RlY=Ml;W`|;i3fW4MgP0RMn%11 at bGg<wrnQg<Z}@+F-^a)M
zzo$fmW$NBiY9KN9RtvEC`VCyhzDj;rDwSSzyWQ>E)cJh=pw(*a13v&%JOe$QPS<?j
ze+ at +cNuZ@tsZYb<@EtI{NU#<J!KPstN1o?>&gF99B4w}Fd*Hh6%OD6gfi>VeB7%sR
znx^g9w!JGN>oK;d*KOP0)iiBSL`)I6_6w(@(dZ{|eoOrGm~(moTs1gTN=<JN8ufa8
z3)qM`Xa5)|r6yq*TE6c;0!-jOpbZ9tCzfTstyZf$<MDVU3`0vPHJLY<IF551MbT;|
zllf>E#tvYW%jI%5oBh!5_n*yXGv74L_fZtBI*xM;OyKVxoHQDZL(lUPolfUlGMNm4
zX{}aE=(_%;*=#=6b$wQ;RC>i?@t5nmhrkKI{FFCD<f(|{L`22C)o!<66$*tnBJw=u
tTx!%Ek0}WhfUm%{9l5K)jkWYO{sAJ*+2eg$!SMh9002ovPDHLkV1gwt_7MO8

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-playlist-shuffle.png b/src/qtui/QtUi/16/media-playlist-shuffle.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7a88a0acc72d48a37215dd4b9879ed6e4e386ba
GIT binary patch
literal 652
zcmV;70(1R|P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10trb(K~y-6y^}#`QUM&szqhBpJ=8trrS7Rnhm{w>65gSU!*&=3
zkwjf2 at G^#%h#1sO4?-OjLhu-PTv)5=#gpt%bns>&1QkZ3De5riA)Cvu%ZeQuYz+Fr
z|Mc;F at c-ZwNa8HaoXLHffYE5A0&oHlPa7Zsn9F9f3r3^yMJyIu2B7>^NeUz#BsG%r
zBvq0olEzZ0<aan6k7ZeYZZerR0lWwB(QGz9EtN`sl7az%>~uQU`u+YgfM2pKH<y-{
zUh2BuNvG3KNY1LN`b`wYNw?eG1F+}ydgX4n8wBtPB&BFH8g;wfcU>;meNhzGL!r<e
zgTe4hmgUV#rLsyg+-NkeD~ht7&*$%v)JcjY0g at m&OVUDeZaf|@*zNX50Lr;sZk41$
z61`sUV!z*yk+dCpKoT<m42eYIimvN7gTdf!o6YucFc|pb@%ZbFjSZz%tGNJJip8SE
z=ks05WHJ{3SpRe=kTkp9?v-}C9R at J<csyT|$>f*C#l`JNBywvyom#9`>t{g_eh!C2
zRS*Q1$K!chuh*Yxnzn5KFs at ds?+y+QzDtrc4Fm!^06qZtv9+~jNu^Tr&1O^G-`_U^
z*d at 6uNz%D;xvVFX$sHX1=N~7LyhQS9tJS)pD9VFEp|CQUOu~m6gp+Qe)9IWid0Er6
mHvoD^J2+9mas0nA9mj7(JQ8SpT_6+y0000<MNUMnLSTZhk{q7^

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-skip-backward.png b/src/qtui/QtUi/16/media-skip-backward.png
new file mode 100644
index 0000000000000000000000000000000000000000..25023bcdd38e2d86ffd3ce50f62a940843dfea0d
GIT binary patch
literal 545
zcmV++0^a?JP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10iH=jK~y-6&67W9T2UCq&%IyXQ=z{6X$^wG!RTNX!A<Dm>X1Q)
zA|xSnFiWN)6arm4M9A(M$1H(BX@*KcM};6Q*2Sd-sZm-<viPT`%exXnrX)ko_~SbV
z?m1jV5|5F7l=~?IGyn&{i+gT-0Ms4kHC_|2>^RO*Fc^G)E5ui+RN}E%Y!ASq%RJR;
zbv+u5?gLl>0FVU9fQX#<{r*FeuZF|nS|}9ypp?3>ZTpzyD#>6Z5_zYTYKX`g$pA?#
z%-^E*NJOrZ$>e6M)!LrTW<CG|5xGpK)9HG>{&qT at E&=$fwf=2<%AGM_+xEd^GFf-K
z7y>Z+3V at dY1_1s6fMr=f$K&xw0GIO>lu|dTRH{)Z6h4W_0Kf>qC?1c0D;A5VUaz-r
zm{RKI?g|i*>u$IEt6VOBZnxWCGnvc}0Ha>7*DsYy=bcXHOFp0fuC at LnBG>ahOo`!e
zcrTGiydmk36q1Qrt+tcP<?<v~NGg&W&1Q2eo6YW;5>3DY$=4*4?xEoxk{cwgTg-Bq
jhvdA(2kZI#g$L_D!DG<srKPYb00000NkvXXu0mjfm$vMu

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/16/media-skip-forward.png b/src/qtui/QtUi/16/media-skip-forward.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb517e7410d630c173da31244f68032d6e69b836
GIT binary patch
literal 543
zcmV+)0^t3LP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000UR000UR0oc(#5&!@I8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10h~!hK~y-6%~LT*TTv7}?_K|IEGCc|<V$FVkU+8|I0iGh2ysgW
z35C)rIygxd5l0uZxMq={ql-|?)Zma+h=T?*_@{<YlTy;!<%e)w{tqfn>fo8)JNMqh
zyXWu}NxTO7Rnu=NpaA%u)Slx2;3I&UrvkxPEVj{TG@<}ZmkY$>@%37*mH_a<8 at 4QK
zD-a0m1Na00APJHo5&5o^I*&%9n<VE*&YGrqsFb=0hr>Jlet({1(C_!}iO4a at 5J^l;
zo}%@y at pwFK+xDtq7|Ypg_CQ4Xj^hlv-R_EISxc!@>PSTXX|0EoJ>3{XrfF`EMx)OU
zRto|64PgAhlUV?N4a2x`9A_86V3LAT>OX)XfT7RlyDgW?C&^^;(&I#AP%4$`nM~%~
z?R{h-MC49u{ij$gUUfR1AC*d_-s|;l0St4w+;zL%KC4!%r?zeX6p_10CZ37;eEwUj
z)%rp*K~j+n77B%8v)TMgGDT98^rzG5)kq|==9%aTm?V=Vr`$W-bHc58oFchEa?$Jc
hOnfok&tG^k?g2Sa(1fQ!_s9SM002ovPDHLkV1ka7 at bUlv

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/audio-volume-high.png b/src/qtui/QtUi/22/audio-volume-high.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1c00fa5c97f7af376d34ff2c8f5f2f1784ecac7
GIT binary patch
literal 976
zcmV;>126oEP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H115HUpK~y-6wUkXvV^tW2pZ4C~QsieK4ArV|DL4ov!G(rECIn=x
zKqhH|Ng<iAn3bIbHzcekY}AE2LtLnl2nmY{6E`L<YD|PMnrawu!T^oc^4BnPjbfdt
zQ0|m|E~ZSHio}8VChu9C^PT6MyywRvBK#k+o^iekoI8$l7O)Cbb#`|40M37mipXiK
zh)8u&QPDWC<@ft9i%4;9&1s;ji0DH at L$5V8HGKfwv0AP3 at p$|~cEJ<Ds)#%<B5o0R
zDyQEnB6 at Lg@y8a6B^nBau2fc5ehJ(zD=T|nL|n&#Eh3_cNTG<hOG`^XR21b~5vk7I
z>D1KJ%jM<eUjVlY3kyG=n3#AIxCtzcj*ec;G9H7AmzS4c3<Ls~0)fD#f`Wn at z)!%k
zh+H_ at X-P@RM~b4{oSU1wYO~p9fgk(&`mQxJG<*Wgx?Ha7B2u0UuCZFJ-vhs7y#&ky
z^I5PO3Wb_AP5Ta5YHVzL*XQ%S1AJ3aQSo+1N5^&GE4$r3B_hv>2v)!X*fN>S9`JM4
zzXE$%0~~t2-rbRrk<WnLSS;q$bv**?CzHu at Znt{_I7p|{1%NI89w%~OdwF1h-+Vq_
z6nJ2oW=T&^&o+=UP4j$rclS16W-=Kyd%qtwS>-~GRX7~p1Cpw$Cgbt=0g!Sy9LcS%
ztu$cTY_^9-wNC;r8yg#I1|HPa)oqQBkLy6Hrlw{)7z|berpx8}6G$ILA;3dj*NqdR
zP-kXlo?c&He+fu-b#-lSY-~IO?AO-T?(FRBIDrFQ*Auy5fZtbFS63pD$Vwy<S at HY*
zu{`jh-|xRaI5>E#rKKg_-rjy-7)CRY>h0~lmq;Wk0kgHWH4glh8^wKx!*Qd&zP=Pt
zrl+T0 at pwE33kwS>kODHm=H%pL)G&<ls;a8jMdV(8fB)TRG+MI1zh9{+N at 8GOU>!&T
zCqC(mBI3(?(u#<@;Prana=Bb1Yinz7sH*xY at ZRw7@HG*sIjXgs;-lAqS7Wi*`L?#U
z2E#CH9*@UZTwGkzG;J0*%+2^oWCCBi-R at gXr*qeCxBn3g2IHEh{cr?5DT at DMEuBtZ
y4u`{6MWi-={4`PI$MP(&$)f{)th0juReu8njd&mQ=-5&K0000<MNUMnLSTYj0=aeo

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/audio-volume-low.png b/src/qtui/QtUi/22/audio-volume-low.png
new file mode 100644
index 0000000000000000000000000000000000000000..9f3d0f19097c014678e3d0787eaffe508017ea68
GIT binary patch
literal 741
zcmV<B0vi2^P)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10%A!-K~y-6)s;a at 8&MR6zdIeH5izk?Dk^D|Xc`oBQ(8=SLKaiR
zzu>OWy_9b3Z*bwd0T-!pFDTvF76XEXO0lh0O*d^rLqroZVspEgXBnbmE4t`~3y*oj
z$2n)XcSKdWj<T+WdKF+1312x_MD7A3BGPhYU=axdH%t$Ui2M!M1|mQ&;8$Y-jUo~U
z9s*lH8E6Ay=YcJt5oiV?;c)nwZQHXzySZ-w?qo8V!M?t}2+#y1fOmib{UXxjR|e3!
zzP{cyGc(f#kWQx`SF6<_zy$)vZg(gYdRi`*2bY$Xo;Z#Zab33?$OAu(fDT{>098d*
zdo9b#8Ead>8n6s3t7^Zh1{N0=hXR4XTVSoTv-7#*I3vIq5I4%lfcu7rWg at U^wOR$(
zH2njpm<BjbrBbEI$;p>Mu~;m2CzHvlxeEb%=G=T%#w8!j-zQZVA0Ph=>>nK+wK|UD
z`oJY~K9w<bkh4lwR#qy&fo<Cd7rgsV;PCYH^boKgi^cK_3k!|rdC8~-IEe=fr~${(
zX!JYhN6|1pKYx3BdwUo-7#$tm&E;|@w)cGCKjOq}x6t9?;iG&$-vTf-H5JTevmF4c
z`U3a@^h``lq&7A->`W%}A(2P~T-UXLH$Xpd3wW=pJN_v4g27-m9*>6sYi at 4t-oU_s
zySln+8+*sVZaSUbEEEcD$z&1({c0Sy;|<BTdd2nC06YM00<ZAK7Q8_Tibxc17?yz%
zys`hNs-G?bUsxj2jJHdA at IK&c^}#N^-Bh)L=inExrgaK0tr)<p$~ILkp1S+*{&~Lv
X0qE-cHwY<f00000NkvXXu0mjfJk~T5

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/audio-volume-medium.png b/src/qtui/QtUi/22/audio-volume-medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..c4d0b3bbc613b9f0e4667051c78b331ccccc410e
GIT binary patch
literal 877
zcmV-z1CsoSP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10_sUbK~y-6)s at dn+h-idU(YxBev=eUY_J`AaM8GG&A~7t!LrG~
zs>D(P0reDUZ at GB%A82<LJZ%LJqL)c}>dix4on5h#(G9J{X7NXrEg4&BG1w&4e0uPk
zk!EqFr9Jcm at 5|@;JTKnQhv)e`N<{b=p?wtUhX5<38a^c03OEhJxCmTQO4Yq9Sk=fG
zK+E{}crX+SodYa at Un%uwt%%f;E+U_ch*w0M6?v<OwAI(w-%?7YCMPF*o12?Mz*XRj
zN=7A26A`<J)QO1K<#K&zu~>c<kydlv5RtaIxw(Mb?Y;y2X0zFD&(6+%sq6Yx;0j=`
z2D{eQ)-J|kvCFYo?6Tc%j{{GDH4(XBo}kU?bbfEKSne+^EnU}j{T}dZPfyP^pU*d7
zy7p9pm56vXO?wEWO+5mZfn^iySXfx-HVoqd at TjY+>)UWRd=vPwv9a++Bog_`1P9At
z&1}A<R4N?;znl6CI5Y+DYH)Dy#l*zK55Tjnt*y^I9#0Z at nakxG{C<DItUFWdRy?nO
z9aez>{tk!3Dd3=3EILD>&>oO47K`Tw1_lb6rYXQ)F1A)|tc28zm6er4AZN8&bNl=I
z1t9NmIC8aW-v!(-H8s@@9JIH$Kb at YQ_5k_T*4Dkn#YLl3DhZG;7i+*VaP0ATvYg%u
zJsyvr-`?K#1G)bG{@tCOohIO=*X#Wwkx1C8&1rxD|7>h*Y$TJ($H`>!@#yI2Ru%Yo
zWMm{4jYfY727~*3eSL*&Hroy4hlhtVo12^E-e#*?@!a8X#5+1V&H~!}{CvRY^A!?_
zgcT^7+MSu1NoTX!hL)C=ArZ-pjg9@;+1YuJN~K(;!Au#fPMOC#&<nVMyTCz3zHMk|
zXmEXf-M+fInhFF0`AjCG1Dhi9<X^%mv*Q0`6Om9losLE#k#9J87+;r7mUWurw}lS4
zbzN^dIy!0weiD&4uHE~BPd1;7%CjQ!>_2Ot+ at JRv6DqEwcVOeD00000NkvXXu0mjf
D)H$8;

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/audio-volume-muted.png b/src/qtui/QtUi/22/audio-volume-muted.png
new file mode 100644
index 0000000000000000000000000000000000000000..d6b909f3567842276b272647c2c6b565299b138f
GIT binary patch
literal 663
zcmV;I0%-k-P)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10u)I^K~y-6wUxh%6G0S!zqhjlJ(DZ!yh1!I&N_E+c51Yg!#_ZT
zLri5PCK3yUH6lXJEC~r>rD7$R<{AqtqlJP7MG!>r7b*M$OweTA%-BpICQ<KV@?hbc
znYZ6Q9=mVF7{e^WnTd58;!>%!GIepWSiGjSe!8)-u{1Stp-|ZCIL<C$r&8)(tyWY2
zEiM*|S6tV9-syC103U$WX0v&5OJd*mFZ;g#V0gb$smwc$lK>VXkw^hp2Q=W7%jG@&
zJhu<|e11nX8r^4?IeWuMr6O`D5{aw_LGVUIP8wrwi%1<vXsu5Gw|=WQ8jZdN-q~wJ
zn$PFwMC1%`xZCX}fSdLx0W<)#*2l-S;=rHU0^oVxci;kmh^!f7o>`8INW=2}apHf5
zQmSroS!?~$a$IZOu)HvlI0ynYW_#>R*lxu~ExvMHxBta8L}c0W*Ky*vf0I_L)p?)*
zAR-TegO(d25(hBGd>j$SVzIbVYEdb*2;3PKr&6hJB61(7i^wBm%vmdYY>ZhMcpxzF
z9w(E at pTHNpJnj4bXW+=7Jd??sFO^EWjWL@*47lq!PN20;0Aa7!+wAAcB=gw!{R*(=
zy6$QihEIScz{_T{S4Ud0oycah=af>3FbpqQ>5F!|eSI)z;^~%7r$33v9Pp#p>z(pE
xFPw at Ppw((6MdVm6mwP{aHc^ka5;Obf{Q`fwwwCUvV>SQ)002ovPDHLkV1o9%BkBME

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/audio-volume-off.png b/src/qtui/QtUi/22/audio-volume-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5a7bf1c380d2c8bbdf11d37f8cf827c9b33ab0b
GIT binary patch
literal 604
zcmV-i0;BzjP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10oh4JK~y-6)s;bO6HySyf8!==TT)C+L=jC`5lum;6a-m3_%(9&
zbNDfG@#HCod;-bUUUF&=ZHR@^r7G0Y+Ei?5#O`?5+2ye{G?w(>z~jBg&ilRp%+Ah=
zs&XB6<65Y*0E<X@=3o(N0-=bMW(F3KdBC&rTts9Vum{`+9svt~fj$LZ0o%X{PyrrK
z0t?^+^FX~^F25}ni|>HjIcNc>0dv3-uns8jL`3FNzk<z+{eJ&pyWOq>bi3U*<MDVI
z7`uv1X%$!lUIPz+UEt6zy9Y!rxEhAx`#6rPw*LWq%PIAMx+$#zI~INo7}<O`5BB3Y
zJ^_xHV5)j9A_HK>l<nH1Tfi4vXVDd$v!h8+#||CX$XRdL`a+HYPNx7*ZT||sWAibP
zesLob)c|LyV_I&%f*{y4czys`nJw9N-vJ*x;LJY-9}I`XK@>%UD2g^)t=3K+tg63(
zuOxZi2ZHphb4gZ7X)1pDzTa&$8YRH%bUH7a&E{FJ*SqP4r>dJG;sY=2>}Mb*DK!Q5
zvIr;iV-E;Pa{7T>{zc>&Ny&XQzY_3CRktn!Uuq(<K+;PBk{7tD4(!U^O;t}xB0C4x
qG^g;&iUF)uR#f%-g=hcWKkpAiG?H|_X+xd>0000<MNUMnLSTX>b^PoA

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/document-open.png b/src/qtui/QtUi/22/document-open.png
new file mode 100644
index 0000000000000000000000000000000000000000..eba48d7d34ce753430c8065ac71d55552b63bb86
GIT binary patch
literal 604
zcmV-i0;BzjP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10oh4JK~y-6?UgZa(?Ar*f9E;{`67ZuEU^QFBUqSWVPxvS#E$q7
zR$?V#V&Y4{#Lx+`w<|~$C|SBNv>+vwqBJ&1?D#R%uAHmWSg`V!PIqVh-%n4^@9va{
zU`QGJD~2kv3u^~(fg6S=27UsIEv&T!ieR@^tG!Q>q_t+S?V~u3Usr%ez%O70pt4dZ
z;DJ)=Gq5y*c7a=4z{^IXu|Jti-T<e?j1?dv@^%YglUBeF;3i-JX%4>Yy6&s-c>IE^
zHLj{fv)TMO8jaoor%FT=aNn}54<fPz(!T^-N~zs6O<w}Xm!%Mq^M8N>AR-I0b}e?r
z?@a-N!QhkUc`Nh#a5&s)wOY^1Vv6ATCa~vu2f%mMdsTU!_Yiot4Sd}Jm}gM)6wWur
zRRv$C|KMt1aU3U%qR1{YRRuealaT#jD_cx`-#^h>N14$aaMAeY$iWM(b>#d032+Wb
ze!JPgW8e``%QH|)-3Dm4+XuZ~Z)B$0>2%zFzyB0KM8?1o at C8Vf@q(zre6L=w?}cHw
z13cm4<}x)04z<>+*=)8C9OtDlYbu3#8U(>vx7)oFhT&le6acODDhPrzU|NXB%($r1
q@{}kBz5!o>qzd at bv&}%sgZl>>VYj3Gy>NU00000<MNUMnLSTZ_P6~Pe

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/edit-find.png b/src/qtui/QtUi/22/edit-find.png
new file mode 100644
index 0000000000000000000000000000000000000000..f9bc25ee02b2b3dae825bf486e0061d6cab3bc1b
GIT binary patch
literal 887
zcmV--1Bm>IP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10`y5lK~y-6wUkdtTUiu`zc+cjMoC^`BV*$$!GfEC7H1O?x~SLz
zg|U?pvu_8wQkgFLHl=PvH`SqwL>F$RSj3GB!_0sinbI!mAdEV;*bdtC|3eJ6ubHBK
z$;;`&Oi3j%ZJGYyEbif)@1A?lJy#JCzJ$~=eg&ujs(?cU-&<e at cnMUjrWCjes0)X~
z=hNwQtLwTE0FTG>q_(#9re#^b0GowP%1cCwt;#gbQ>v=o1|9<sfO`dd06bPz^|oo6
zr$nTBU+xE{6y341ySv-q_xmSuxm-992s|Gc82F>Bt1AOAJ3Ffn4Gp#0wrzMko~`Ze
z?F+iDrvSH7#WjXuTn3hOUH{#(taBoALPP>0qKinAWm)G#q0q0ul3^HEM5Lx%#l?$y
zP1CLew+06XFNw&}5(&oW=;%+tEltyIl!-w^_^PP*L-~CEFyOSbwEP34OB`^kt*vbt
zaI)EK2++#)t{AKYgTWoZSy))G*?V&PrL3&1yagOpRbO+!vnvMg>bm|Aa3&`wj|0IH
z at xhUiktV=tY-~&e*^dG5ba!_ at 1e}eHjqitthmQeapc?Q3N5;p;BWr7GX91_Dr{^w^
zDF^=GxdGAU=H~9j#l;3iQI13+k>5HyJC`&~%O#V^Z&Rt%4<fP&WasAQuD7?h-vQoK
z0t0y0*VoU)VzH*><>d%a5BLh3{tLYL at A!Vd|5Y>^y)!>Q|7XFUI|vLAbY1uK#Kc7X
z^z?Lab#?WyrfIHW7;pOf`?oqeI&!9I>QhrwQJ~i6^ZlL4WUc|vis7Zeuy^<001ZH>
zkdR?-tT$(7W?Eyh*ms54I$hVF+P0klp1y}4H17x4@!sCvi@?tXn+gO1S4HHQh^YGq
z<WqD%kx1O_>+5?2IKUIzw(CNn(2qbJl>d(_DF at t)$K!}der#;)Yv55npZBr%?S3}+
zJv@;}C|<AEO(v7o at pwE1yn^!0`xL3bN#H2(7jPet{{vi7pWD2OdIyU_zNp~1f;9jD
N002ovPDHLkV1gD5qkRAX

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/list-add.png b/src/qtui/QtUi/22/list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..637da1ecaef206064242193c1cf0d2aa4b47cc56
GIT binary patch
literal 462
zcmV;<0WtoGP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10ZU0lK~y-6wUxn2#4r$s|FmwU3nho1Ttshz2f=soF~ytD;Hiig
z!GkyTT56%$maZKS+m+dAn#4l~LYZmi>)&K1QAC6#ELwyL;3ROK62A90L%?SMG7&QX
zKAl-a<Ql7 at C~g3J at j*maL=?Mny^7N`9RPe=UdiP-GA}qu5(3cp=7oS`rY0Vr?aaJ`
z5r7{T_#D960_iNVOW_}FC<iM5>nMsIi0D+PdFKSB)T8jbVHoa42H6xtDfLQ3QuR*w
zZz9J?j%|$_0D~p&vTX>s!~a`-vIiVY0NS!FpLyIEgUx1h%af|AdJ&u*_LcM3>QeEC
z*7}}*xM`XT0M~qy*7^zi3g9JH&nZ5r=3Tbx`@Y4rj at uC=H+2>~v9a at Pb?medFtRM0
zloLEhrw`ocdA_adx)N~%(ZbSH;MKIqK_3K?w%DEb3%gyDyR-<wcK`qY07*qoM6N<$
Eg2-~h4gdfE

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-playback-pause.png b/src/qtui/QtUi/22/media-playback-pause.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b061de23dd1d432529281a744a0c426982f158a
GIT binary patch
literal 279
zcmeAS at N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fEX7WqAsj$Z!;#Vf<Z~8yL>2?p
zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4<ivthz5Jr|+3#$mfQqJgx;Tbd
z^uC?y$aTnp$2ES*<?0GS{`=h?-{lr;V=lbh_jX2yv#iUD`z&z}&Q5SuTIJO{XH`UY
zmvlR~fRWkRtB>?QZ#lv=r}v)4b+gBUJDwGJ%QU#T>@p3x%H44I at T<h|JxlbT%-$o+
z-}>kKqiV(f5j8zZPbFMWU9Y!c3=GYelxO6TtIXRcQmA+0-PV_#<<I~7U1r`aW~b at A
SweB|1eGHzielF{r5}E)Lf at g~W

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-playback-start.png b/src/qtui/QtUi/22/media-playback-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..a292db2389fa885728ce92acd74d9073738581d8
GIT binary patch
literal 555
zcmV+`0 at VG9P)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10jNntK~y-6&6T}tQ&AYkf9HBbs=0wk1Aag#L2;1~%+N`PLT0B7
z8A1keZKe(m4%vhtWXhs&{{ab--Mt at 6QAz_DZX^}@m4XPRDKvc?q#&1jZ*N*EzVIwB
z=lz|R!}D;AByOUt8=*#k&2_<cNdEya2aJJVR{;lYYynOpk#Otv`g0%$Bxfc|^2?I+
z1n2|b9mo0D>-C;Vx+m#Y!1+K$f!BczVA~k8mCxr_Bt4Rpi35&u#RND34ki5 at 4u`L7
z+x}3gR9*lJ!0lPz_;2uqj)9%&beiaPyYEt|)LYkep91#@F at OmOhy^@0#=MWX^sX^x
zE|<%F8Vm-XlgZ>hKKI1k*sonlJEPI)WuZ`b1I!0)cNOr&ah$_etJUrI`(J<~|8Q79
z08WFNmSvq+t5vVl=^SJ-nQy>X;A|G~#NQ~DN at Le`_lm`$#~(X}rZN^do6VlI+wI+2
ztu_W$fgcfbmx51i+dgkJ8vD&=^EjPOZvtDu^fD+Ap1g9oyzF`2Ye`Fz?!=Aqg at Swx
t at DNx8)_}cO8~Q2?eC_(@Kgj<J{tX};CnN1hVy6HA002ovPDHLkV1iA2?tuUR

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-playback-stop.png b/src/qtui/QtUi/22/media-playback-stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..2684c825338ee2f6cfb04455061cb81c1db57638
GIT binary patch
literal 252
zcmeAS at N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fEX7WqAsj$Z!;#Vf<Z~8yL>2?p
zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4<ivthz5Jr|+3#$mfQl+TT^vI!
zdf#5%$kkxL!*ap8 at ZFp1KR*8JeDETs#7g|-f?fdw=Y{6ez6IuaXmAQjI$iOoFgf?K
zB(C<_15SscLy`x+u?jmV?W_p#{QP&@pF69Pz8=^b@!_IOjoZP!U6bNmPrkPoYtYFo
px03AVbWd(>={ft#HUCz$uQ&sX(yoP4jUbmYc)I$ztaD0e0svP6TV4PF

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-playlist-repeat.png b/src/qtui/QtUi/22/media-playlist-repeat.png
new file mode 100644
index 0000000000000000000000000000000000000000..89ac023d3f85a3766a514aed27033bbc86392b2b
GIT binary patch
literal 676
zcmV;V0$crwP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10wGC6K~y-6)s??%6JZ#~Ki68`+(`^ER>Ua&7%DmyC8!_ at C1W8Z
zE)sAEt_HFPr(|jVfeszAOHIgd*&7jpgBe_{M!aHBX$B>CfyBq5S9`rAZ7O8&fro?V
zecsRezTfA0I88*Dh0V=`I!o}W332U&oDn_!;2>}oP$vZUfnDI|!BHan9?a!(D at v(N
zU<ddyrSB-EHgmb$iiiaFd77syt{8?<ux<MuV2^v=1k(Ur*Y#$v*Lwkch65=yK-so^
z6X+%qiAK3x{umC2kA!!-T`iNzT(8w?58b`WW&M>w6OkpL0c=^8wJIWp8$Zeo%d%F1
zEubMHOKyCmcs4*Z8r_~!4%^Lj{0n|?-~A4c0eWrd**6h9a`FT_4V?2_U}T?v@*Kda
z*Xstb!04bX02i~_>|LeQ8eq7&&IsIFyg(qZ4s3)%p*7Pqm)&Aqa at QlxX7g4g5-9+$
zftRLfE{8&)HDDtU2&{XHcc_n3snp|YwR#P>07QX#5qS#qW3kwyR;%@7I2<~_SKv2r
zhrMCyB$LTcl}hCmzCH%nEf$L(bX}Kfwff7p?Y8%2>2&(4Wm)e#osL(&H at dD5lF8(^
zd_KR;-dF=1x-q~aa2vSnIn)F!;D+Nku|lD6rc^4O9}EWbB4Pmp;0y2$`0m%(@7^Ks
z#+8UXXt&$X;_>)%SJSz14F8R%wMF1Q at D}KdOZZptvG)J{n*IPY*j%L_dER;e0000<
KMNUMnLSTa6yDA|7

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-playlist-shuffle.png b/src/qtui/QtUi/22/media-playlist-shuffle.png
new file mode 100644
index 0000000000000000000000000000000000000000..d52fb65e32d6849dc913af1b9b2b4f7e194aec8f
GIT binary patch
literal 793
zcmV+!1LpjRP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10+vZcK~y-6)s;_3RACgwf8V@${+VV{m_c(A46H#S9L7ZpE!rf4
z4WXDY3k`-gO=T;Iaak)DIXi{IO{;>OO%N4W>MC=hKa3lb!i5o5O3`Q=>9lBGyv(8!
z7acg8_wK##-gD3UJ|l_kfM;8(Zf9Zd7ILeBa^M}Xy7A?|cI*KvY}>w;OePNlVZi<&
zLXtz{BAYNEsa8_Gq==*l at CsNA1OitkCMFI@3Oe~tQmqqQWPR~jpcq)w-Q9iM>-F9>
z#>@k6ihK$@1Lln}vkeUm=OpcxgcmS?&lofAOks at qWZU-3csxFu&1PpC8yk=2^Z9<D
z04xJ<H%PNuSy}lZkx10Kr7*>@#$B8Oa(=&mIFU#kGsZjy?zgnGWF{vk&r3Qj=`=8I
zS=OCoGI_C3D4dkk at LMTTsnn6`>gv9+v9XwCS@(e3&CSi1CB-F$BzYu7nwpw2`FuVl
z>5!yS_fFi)@wgb26!H80!@#X at I6ShnwA5A9+=<^O>4c=Z&6e%htrpnpu)V$gaCv$8
zg+igQ$F}Xa*=+VvM at L5m5aOG6J%A}KE$!;->#P5j-5iY{yEp~hv at C06baeDgTU*;X
zVBF{PUG41bjJxc19heG*LYJner}w+<W+WM4pD`xod at L9YevU??A2XTEhiEkVJe^L*
zhK7druCK3G0X4vmV(4_S`><tMzE~`FBbUoP0A70m0c(=xT!X9u?|~=4(%|6WT5oUf
zdVhca;>^s<&Xtvwk_~oyQB_r?o}Qk%@0N8Po5rmWKcfa{a_NjQCR9>V at +F;4FAoe1
ztd*6O<$yV0(_i;b=#dm at ZEZcfu&{7yGrPGv{#)z<4gwGPcEbIDtrY$({=XY!+X{aL
X%R$j%*P>b>00000NkvXXu0mjfwQy>&

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-skip-backward.png b/src/qtui/QtUi/22/media-skip-backward.png
new file mode 100644
index 0000000000000000000000000000000000000000..443d538f5329fbe163c51de3e63314d0079ebf7a
GIT binary patch
literal 537
zcmV+!0_OdRP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10hUQbK~y-6-IT#<T0s<szmZtHk=jKNDwOPUUm=BTghC}HF5Cto
zo7;8wTC&oOui&a#l(y@>f)de?wiH|_h$c|7vQP{Of&SgxX-0D!1siB{VBpMrXMTn=
z=Nu!6yRg`usNM@<6RxFg#ql2lsn9<MPG at 2t0&Bn}@NFKmFE&8R7}GGuG=Np-<sPtJ
zC={N><MB74NEADmVv>+#B>6xaXiM at XJ&=^C)oNRw=e-36z?TJ>ku;SGfQfaQ&8DBv
z=l90r at e4^8z|gWzr{m{xxkwh3<KM!*?{D|}{oSy6M!-)Sa2s>YgaHQFFve8E^C!R=
za20Xqk4(~Qpa*ES+$O-JUa!APr_(2P at 2=aJD-<al1i|rOFgPleN}oK>`|e&2g5Y>G
z8g<I$^5<DLR~R@;CX?^0)oOb<9DXepi at jJZ_QSG7BJrV8sk9>4R9 at V2+XwdDvXS&i
z((`V&`!bu&zFL&o&$FMh6Z#*y*?AdY6KHX>^D at 9w;LtKx7_K{N=^;H^$A4|=|Nry&
b-xvM`?VJJQf+Zss00000NkvXXu0mjf^bziC

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/22/media-skip-forward.png b/src/qtui/QtUi/22/media-skip-forward.png
new file mode 100644
index 0000000000000000000000000000000000000000..58736abe1d2c6c3825c51b5e1f9f071c5ecff29d
GIT binary patch
literal 469
zcmV;`0V at 89P)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW
zd<bNS00009a7bBm000fw000fw0YWI7cmMzZ8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10a8gsK~y-6?UX%B!(bFf&y9@|C at 6t66c>k93jP6c>eNx_+POc#
zJ+n}-gIkBLe$D;@ry?yaC^~frh^UByL+$8wFqOAyHCej#feRPTo0Gg>5mjXou at +)o
zip^w<-UA%q4H(D9<$yKdeGbb5*{B}@&oKSP8 at 6qqRIAkrunDXhY~8l)(?3{NL^>kU
zF<t<wI;kRX3xtm2oHZJaJyp%A>PiaM1A3}jocQA6tEl=Sa__qCQMcROQPu4<%oK}p
zL5d=BY)sJtToKVip>RGN4l7AaRS$q6Fe5%>Ha6e`k4a2bgNZnP+&<&wdEP_2-M&c4
zrlvGk>^ROx5Ck`2820P+`XD9yO(rh3EbFUQtGzUv&5`f>cfbJHN at DRfni7}G<)>Dw
zH7=D(A#lylflp-f#OCJZfZgb!*VwrKSRUAq`b(mlC(HlwQaqDy-2~c0z04P^00000
LNkvXXu0mjfzFEe^

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/audio-volume-high.png b/src/qtui/QtUi/32/audio-volume-high.png
new file mode 100644
index 0000000000000000000000000000000000000000..477a168bcb143c27f489ed0a7f2e84d15f49549c
GIT binary patch
literal 1687
zcmV;I259+-P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11{6s|K~z|U#g}VLROuPVf9K4NGwT53!iXp=9Twt+LeZtOio{D|
zB<iYcs<Cv_q#rjl{a|`YL+l5Qmt@<7C`QHThbDe%^h4Ebl~%W2p)&PS<J5}nj>|=s
z%M2Li%wcBE(+`}XQwnys#rRL2<RtIq`9J^XIq&nniiq$gp}tY?fc-V@?F4+l1TX}c
zGfjG33OIqq&CSjJ&d$ySz`|K)ipX4>T}1r*_wQe$D9T@*PUi&?DHoBvndZ;6bDM}1
z4Gj$~RaNyK at EqvN&CNYxk(f7q&0MCy4iud^b7rB_>6Dt9nv1|FFcOVMKU}+ZZ4HnQ
zDE~_eydttlMCOZ#GE3woM~@y2sH*zV=kxtiL_S)!Y*`C%4|r&^*=|@Wc)v~x6cH&D
zk at B58cYa`P at b(PO7hkz@<y#rDhxhK?`<)jrUVL9w)!zeu0z&2G<v$XUQV~&KML at C4
zE+WN4Lqkj5ZuePWu%x8qXChKEt>8*JIy$~7BIS8`dFQQ&AK7fSo3U7IOJif>&w<;(
z9h=Q|%?iRZ69Fw9ZQ5?!xKZhFI6eiw079Ck{n{F{Pm}$Ab#?U*pFDZ;v8HLCr6czF
ze4mVsjWuRvWqk@<2majL+*~Ij3#SuMMdaNrTef_dlaq7I<MFh4Jf1dHRc`~&tPMLo
z9?vHh0f&g>pFVy1+p4MtfzK6130=Q_ee=G3`+f at C1a2yd(iMxvY65}4uYf-QpA{4o
z{6a+DP1jQTB+L$lLas}fF6{@jj2hK}K0p8zMTupMnN?L)y36H?=(?T|5v{(yzHxkf
z{5LHvEyE)tBOVcP?AWoRxTdD&FP)v86+ki)iTIg309`;l{TsT at pFckz7_%ZyTOSYy
z48TxTHJL#mvU26h#Knsje+$Hbk$5~_2s|q*D|^o55j++Q2H&fztLp}mKr)$3I;`~$
z$T*4%3k!8%IPGi}%Oqd|eH%7x2o)C>_X2U#G}YGD*0+j^io!qwh$j*W*T#(-qZXlr
zX_{_pz5U+^cs!oee{pUoijqknouZ!7($eSFcjWBZvt at q2Kdr!oX__go*K4|5t}!4f
zBDQPSu4!ok)4SmWufVhvq>&1T!!Mak6+WMDxUa8IP4DG$xuTYGX-g at JGIbhG5wP3s
zVnsSDW>CNl5Dtg^mI89{;KAsoO`B at c1S%>j^iU||Fbv}@AgO7Zv2NYE35(4CMZgBU
z-O$ibo=T<Mz-U21!PxTU%k at YkvY5#lV9Amt#;H at M7Fc_m`T6;y8EQ<`fKgjpo6644
z9_1A^Ff9f1gTbKt!i5VzVDiGDuV25u&oB%<9*_Hg37gH9*tTuk;MJ>F-?0=)=H%pz
zSnCs+3XFNZ-qhvGm!Gw at wP}W7C;)fw-ktaK>C@~C1rnJGbai!UPNy at h>-xCY>x~^d
zcC4?uy1LFZO#vqSe*eVg&71po at 811EI^s2J*7P#@2N?j0{OeNc237;5SS?f6b=kgs
z`@Ht{b}v9_Y3bwc?(Qz&@0NO{0|NuAYinzBPM$nD8i_=DcJ12LBqC1$Iehr=KkDo2
zZ&z1W|3pMa0D17>L3?FoWf16}P9P13ML-3Xo2I#<sj10+;>3x(*4EaCO-)UYfv477
zC-A<m>q|9F>&eQ>YA_5V2 at D4UfstFcZhc-<RJ5eOzrPq5ud1qw-oJnUcR&bunVEu2
zWXgO`Rn_t1$B(Z*a^%RD4u>NKL^H-GfIFI|8SU-uiBu|O0{w2cJ9+NhxkyV(%lN>+
zKqU|c*t2I(FAxF7r_wru0yAL&P-aE`C01|9fD<U`?d^Sk)v8r_2M!!~xpnK-XNwjs
z`mV0)QD9=liWSjdF!-3s)*Sh|1ilJfz^Z68TArJmJ6upuP%$ttPz3Y>($UfJJP-)n
zw1Sv&I+yPP1Gtl$o11*}=uvENaIgXR8z6 at c9U2G(0$-5PS*I|^w_-%ZDI(>eQ0OC{
z&-dfT#>S6D<a;8rV5a$VnSxAY0d+k+J>T&8d<m!1`9~&y-T%PrB9JEW9+O4e%`8u|
h*Gb?j;f=qJ{|OQ5Y^*b5<%$3R002ovPDHLkV1jB6Cn5j<

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/audio-volume-low.png b/src/qtui/QtUi/32/audio-volume-low.png
new file mode 100644
index 0000000000000000000000000000000000000000..bef96654b9d9a7f7f1d46e6471e75f2569042866
GIT binary patch
literal 1279
zcmV<b1OWSqP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11bj(EK~z|U-Iq;FR96&$zcb8?%rHEeL4HIr#aF2_V20GD%`mk_
z+jM1O*tqZ7RAS<eMUyUEwi|5F1u<#Z)PzN$iH1efhSpeNK~N?Jv7KtsX+an(^9F{Q
z+r at j2T!){k at h9;lZ*lKC_nhyZbKg1liBgK!DW2Er{f!3 at k!>QfrH_{eAR^m<P9Xlu
z0YpTA4}cJ`TSVS|WdI`LQ}(BIPn+H^BH`x+5FiXR13R4Yrp|$ch_ooB?f`c+8?omB
z at Bq7jx)Uc(bN~^cwoJzdG^A3gS|9;z2cjZU1>68u9KDE$G(HVL1>gnzK=b_ke05b-
z)fbm8UFvUXY3TwCP1g at JU%Pg#J{pbI#^Z6nW}^cr0 at IrQy0f4I1cBXv3G4;l8XX<o
zzH{f!uX4HEN5EVrlWEi7{J`$s-rl;-&dzV!+uJ|6c=6)>P$=Y<)(Fr7`~ei4xv+>-
zZUj&P>^gSr*!wj#HQk0`oG}dJ%;Cd_`wE3ZD{vop<n?+pj=lhq{{H?Q-QC^aluD(V
zsi~>YCnhF>r%s*vTeEK}rAmN4_e2`R=>_3bD%BK=#l8aq+ItIl2q*x<Fn-KtvjadH
zFviEn8xI{i^tEMKAs`S81}B%6mcEQcBKsB=7TnGK>_qoHXPi+={Z<}<ZG(e at 5#SLp
zqdl`g9#{sJJs!`h2DfnV;K9}5;o<Lr9Pluo&o==yH#b|FULCNgje~jw*3LjvQ<DYE
zyUsRwbbwXh!O^2fQ+xL8`3uOGN+nNkZ*MpnjpjAIN at uM;UJp=RU0wVi=gT6Z1K{lZ
zo at ttYVyA0iU|?WhB9V9kz&Qu*=jaoW3iqYA%-{-JNLdP8DW=ouf3Z_VeSQ7>RyNkz
zTqE&%70(`l06;pO-isZ9+}X2d7q4Eus)sr6bVRpC6qHiMHNP7GY${~{UZA$CtE;tG
zECzvWV`Jl^wzf7al}bf)0L{5OUKfFtWHMPa3?sW$1j<rSJ3c-h7#bS-444C~BS((R
z0=e1QS^cE{gWXG9$>{)Y1hV09xZ%o`D>D}^TnH>LFAKo+>(@im)6;9ES40Zh+KREU
zv4G$2Pg|C?6b^@T=gys*?dj>MnVXw)8<wS%%8H1ot<#IrS|I|viF}A%js?K7EOq?&
z at zBV~NEpC0&8geBZ;xRYA^<a!$t04=<o5ID&u2~3ymjEffttsUAG-iI9NkZ`n-;)`
zQfe&?`d5$ze!$L`0G>b~5W9T&^1CNbp3L?2_3b!)`t*{cyMkREXBrwB>Lw>A_Xh%j
z2l05kQgc41l=|J-z3Y5YcU~TWjl=`I10)KCg3ssk-2o=b!srKLH*em2(B9r21FEo_
z&rjIJ>SGOHOeuB$SpaaNQ4h3Yx7Lia`}K-;r%M92lv4LZqyzgR1MpBO^~<_7FZ#zs
zMEpvr6({uWEl2^QN~y(i{TF^GbevaU-zi*4ZRGr=05}ju;8*OTb5|)fvzhJ-Pr(z$
pMS?)yX-2Oe;A!N|{x^IY`47WCzTnR2N|gWr002ovPDHLkV1m5CRh$3-

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/audio-volume-medium.png b/src/qtui/QtUi/32/audio-volume-medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..943ae7d91b931f09a56c7bd324725635ad29c2b9
GIT binary patch
literal 1475
zcmV;!1w8tRP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11wcteK~z|U-B({sQ)d+aeYbxux20VxEkkA*X;Z}14T&=tJHsds
zC at 92Ceb~dyViXJ{B%8_N!=9EIUG`uiE=m?2NO)Sp!_-aXg-jpJgh&=6L1C;8i=9BB
zq}<!y_MScTUb%MV&oYdOCpk&e?>p!GzTY|Dcg|%*gx4wDYmNTK17M8tjImW?yfOfc
zF&@Ak09C8)Gj4EP9)LTMNTdZps1!x95I`YgY>|k@^BHU;13Z8&Jv}|8ilR7<A3rX0
z9LLnPO2(KouN4ukrHqJNMD#8Zy-h at 1o;^Gf`7U0(Si^DL?=F|?J0hxRXlSSha8T7?
zKL2Y4HxQABh$@a8IdYJQDpU};!OL&my0wGjxcdN}00<vDc5Htn64~Z<yASF>l&lAU
zk%&y1<C&S6Z5E5A55V*C^71c<$d`NayLa!tM?@7am#ZJZeE<&(2E(11nVD at J9UVa(
zfDcy#P^g_&)7!Uizi%>`egW_ofKfpZdet>PhxU=`>gtZMv9VKvAPfTd4ZvtoQPH>Y
zc)Zf>b~o!l6zBnHMQ8-D`M`k#yBrQjr`>KpZMWM`*VfivmSwpDz%+ok(P)gS`xyXN
zPft%#XJ_a4ilR71Mn>AB(P;S0nKM5FNCB9go0|&(Kp+rE=*q4{UxV5;bc~LUny+8K
z{xtwWw=M#R03ZNhj4kQbGF4SoBG2<NQ50n&687!e_emm=`0>Jp3$t@`b2cI}9X@<G
z(A3m4H8?nEQSFKW{HZz77%=zu_iq9a2QZ=22mlE{5<rsUxU>$y?9QD#GuN(N`w74j
zfH_H$N&!sx{r)E^3-RIM;SWNgkjV4A7R#dZvHT8{mX?YDX0>1|s2+d};8`dX8Z9d;
zdkR2O6ou>R>auz~p0K(u$+FD*{r;5MY}R5G<ON`}*)nScPcp{z0Dx?YrhGo%6ZLnj
zudmPV^?Ef1Qi`HvY&M%>wOTW(jfpX4&>ZAG#VM>JIVsR26Ap(Lkxdnfi;HI?kqD>x
z;(304HJ>j47>!0!Pr9PyVL$+Ya5(HmmH|3 at _UwE^L&Gi&!1nFi#l^)%E|EwWkWHaX
zL>e3a3xE;8rbCAgRb(<53xI`^l9G5J5D;Ur*cN1K0F{-M$;rt{lO#!6P)YAotASK7
z7|hu1_64j`134)u8Xg`lxO(;KX8>jZh;?;!kz_I{N|ICzAZ0KZ<mTq)=QnQL5M)`_
zW<UK^e!;+k)9Ea}dGqE(cXzjtOePrs+`D(L at bTlvb{zw<&ek+EG$feK=CCM=38&M!
zbm`KiNOg7fUPVy|K+5a&rWzX?r_Y~1U#PSD`z2O&L#Y$l0b&cXFC9ctq?VSJ!hwMS
zCjj_-zK7%E<3q?c91egt8jaQjgTc41T)DCki^Zmn9zEJlL}LKx+_`g;?d|QqmX(!x
zW3iYPXMl*7(~zh23aVO(XjdkaInmbEb_&2(U0q!*YA-OT`>jOu(bCdVD-kvEJpTiL
z%K*Nqsj2xQolbvz^5n at qSndORbDNQ#fqY^Buob{=S(Z&Elj#ot50LE*ng{@P3=9k;
z8yg$j(&_Y5i^Y<D^ytwv$8jTpK;RwS>4%7D`lSf#97sxtXfF|MUSS|9Afl~PQ&XRM
zJf6>cdwWk1QEh#FeI3>qNY-NDzlZ=}_x$|4-{Ek~wzjrTcXxLeY3BrRhlu|5C~YJF
z4MbHm8hz&Rcq(LB=GFfn6469HgN+8T?3ghtvbX9v5sj?4?^OX%L0AAtM5MeH0PB%A
d``d6m@()L~deYJD*L(l~002ovPDHLkV1g8MnezYu

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/audio-volume-muted.png b/src/qtui/QtUi/32/audio-volume-muted.png
new file mode 100644
index 0000000000000000000000000000000000000000..279df120f5a3c631f288a04dfdc673df1aba4caa
GIT binary patch
literal 1093
zcmV-L1iJf)P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11Hwr}K~z|U-B(>`990zl&dgm~<KTvbYN$o<hvI`jRHIS!P4Nd5
zs^U{s6lD7#+a@!+2|ma$2nn0LGZR at Uk}8VYr+`=l^AKxZilC{!_#kSDkXncZ<8Cqu
z$u2v`mpj|bcDvn3exTpW%suCP_xt9|+&eSG%-BsByQ+TO8z>fweWg-q&#oAdQr==1
z#_Yz%#^jD0 at I22j3}YI=Jw)`nlyYRp3=|55wClPI;8YSLqERX3z_uF*!>~sPF)O9a
z+O{14_%zWWBH4;Vo$dpLLLogeGO`SyCBgH&F3Ymc0ysoOYee*b5aLp`TAc^b3joY~
zIG4+v)_K?Lz|_=~DW&{S2vH7#;DuH-rBZ2+>$+>q{I?S7isSf`rKP2ah(;S%OY}}N
zx2*vw<xL9<3#W<bs0uybToZ<2Ppww_-uL}yOw)V|Kv|`puq^BN%F4<K0RO7kBje-a
z`*pr(5*#3+Bg}k*a{L&8`;&YUPcSht(H+O}w*U?S_^4W~-kVCLvdsLsD#^L7JK_8O
zHvo<RAk#Dt12}O-2PP*cQvkjOkR_s{>Z%*!tx%~{)&V3N%>g0AsBPO{09aJ9{l4!%
z2;eJ?_N+cf!$74{=_R6l?F5_Qy6$=$$FJe?gZZ2~o=a+&`6(j$L8IN-(!l>kKA-;?
zz;9}J$Jp3dFMzp*fMFc4ENf9SdE1s6P-qAWAs!+ky#sxjOr{24Nrk#S&+FQ11C4nM
z!`RdZ##R}4R2|tg%{gZ7PZC75s2=bh6)L-~yS8Np!Z7RyaF-gM9~>Mk19&*eGxNoA
zxqK at CQlX1FzhNMqPX7bo(k8`kjN>?2^B|&Wb=t3$%?Kg%7tx<B4P-Kz8WBCs%<mCV
zfrttKer#tz2w`c%3#nA<-5>~F1<<DqEjW(z6EnZ4)lKVjw0#+Qp10SstWyA9QWKuE
zZ9Aja6pO_^BKnSqj at Rq;Urp2e1wgk-AB&>sq*{h)09>!vZyz2W{_Bbkw1Vrp>roWF
z0^ofWI at 4T}&*v9cS6BNT$C(jAe5{F|aUACZ%d*~9;s9_?7r$l)bcA7e_t4PL`K#qi
zrP9sSYIP34K>!sZy02ENEej#$ad`#2>^RPsI<MnZ&`ulxvf1o%y<UG3z&sHhvu*o=
z5F*sX&o+y1%0MSj?H#af`!nD79RP2tR1Cmw#p(DKYzAt1{sFb`GxKmRmn-g=0RRYs
z;2<;40+?|e=Z&k?ZQFl=ZQH+_ruldjMVWSW+tz_jaee<Ac7p!^0Oe*k%1PfJ00000
LNkvXXu0mjfw<q-w

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/audio-volume-off.png b/src/qtui/QtUi/32/audio-volume-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..25a9b3a59aed1e4a38567e91c0ee0b4ec5248450
GIT binary patch
literal 1036
zcmV+n1oQieP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11BppQK~z|U-Iq&GTSpYfe}6wPHMOvVNFtL8QWA+qNWtAyl&G5u
zb<+hOfe*k3VA(}CEW4}PHCwVmVqxe*ZBV61Rn-XkP^i^}xJ}Z?QA5qOW1lYWTr++^
zXi9>VBVFA)=bk&~H)qbAnJY8nG$nSb-d}kDNhwK3`gmagl2X9Cz}1%yAW6VG!0W&T
zNta$4fTW~_OY5$uo{*ILKL7*3IUw^a=fJe2i)OY1+=*TRSDptz&hg0N;^O5X2=c(t
zA<pB#G%yIfC20V-1=O6$8A<1l10Z+Bfqc1K9!jUvA1^H}U7wts{1E60rKFgdHGsgW
z;=mNp0DkpMyK=z?cn!z{m)$j9EEb1HM at K)YR;$y%!`<E8tL~e)=R65qlQazc0Mw%q
z0~djkr^`v|_W=^#s7GdJXW!o3-29-~Y$gGMAed-2n?pbuutXy9r)S at qbHcDs0bde^
zz2NM|&1^@~ePG1t&O4|!fXw#xcB)t`egyc0Rp1_A&fz~D5o~x-><1>y>_<sgfE3U#
zY0wQI0yx_Xpl at Ym<qYr`*yRw3#bQtWwwX00eGk0nbq-J=OkRNDjy}_V9}xige7*|&
zb(nJ}PdgQ6_E^#r!lILw)Yk#f&p~oV?QVcfCe!FJ>=H>`08T0n0K$Bz_zqp9YCs>5
zloWTX<^aG+jU%LU3VgPszB@`<0EtAxc>V}vz2^$y@{45O?TCG at U5`e8A^?)Igryo_
z&&=vh*8=dIN9~qGOQ<$8Gt<asvlR!?^Xi-eSAGkg>b|@C01s%do^4AxiooBwT&}*c
zv9Ytfyqv1lY64haU(al9Z4G)3>$FSUd#(aMNxDE-0|2USm5ld*Yy&W$R45dFDHIBq
zqK<<g*q at u5+gn>(8v;nD({;}tGpk9uL3r at E<@%fS`oHbw|E#C`!w2y9f&lme_#F5Y
z_$-x5eYd*0`eb2Y;T{mo&(H5UyH*mJSpa-(W)BF<anikdXlB0=CS;_mm|0s6=o!ay
z5pGP^N~Kb4Y;5dz;3n{>%TP)XR>T3q&F3q^!u7rfaMR4n{{<kDbA+MYBCPAZX~Ugv
z2Kd>`?n;^h-f*uUnc25p-<<T1iKIT48{-_Df(-b^%qpGsCw?Y$&f~zFo_f2N^A`f(
zAR538!lHA>%x)iMd*V~j*141h_RXw$DgeikSNq at aIPx!bVLy-9XCBA^0000<MNUMn
GLSTZ;mf<=8

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/document-open.png b/src/qtui/QtUi/32/document-open.png
new file mode 100644
index 0000000000000000000000000000000000000000..55eb33862a1445d4bce0fe53b99752648c373223
GIT binary patch
literal 1053
zcmV+&1mgRNP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11DZ)hK~z|U#g|P;D_0c9fAf)Od=GhODCneMeYMa?Do at ZZx{%av
zy3>sd#jURF&RutJBZ!;s#AS5hLfp%fQi>Hzq?>4<EvfxLYZJ|rm at j8Cw~LviV>*cw
zF}yz<n3;R;Isf^eb7#(#gb=(-s4mYGpd0YJj0qrbTU!V`1Nx7Tk2`mEc6#b34-5>H
z78Vw=Ko)r0LL3vQxD7~kDR_T;eEf at eJpNh;(d9B<1OkEmLZR?=3&E=>0XMd}5>SD`
zKp^nCR4RRDvvz~e at At=BiL59}VQ_HpyF?=K2KWmoID_6pC=~iNm&-kG<V*;m8iw&f
zD+F|17pJGEA5BkBpYQJO-T`OTF{c7D at Dd0EeXRuWh#c?}Rw{nOD(IR5641Z8y87P6
z#>SVru7`yX(o;s4BuP{%mBiB0($@0wvW}GsQB~j>p!s~hZw$lu7`S`N;12jzRZZ%;
z{uOWz+*TFnip65xhGA&HpV;!W0g_=DS}Ydpo}Zu3Itj>ES64pZng;vz32|-5lEJYH
z`uh6HSOxMRdV6~_BO at c{&E{NQUUr?FoP6jqq}#E$N1!_Bg}~n4-VdXrqfM1EO_QOa
zAtjYcg__N)5l~fCcqJf&_yzbG$TXPJA<OcBq9`xjeA=-9I}Z-%UhM4bEDaQa+Xj{g
zau*jD`364zBU8Ol6veXw_FONhxcPLhe^d>4g(OMFLq6L|fCdV<5@@9eokjE*0?zgI
z3K$+8dx9iMm4|$`RRKj&Tx+120`IH_gr;dimgPIsG at tA@?6wPJSr(e63G9xm`XMSu
zA`uadMl*Q$5Iv#@YZi at 0Gm%I{U^OT;1#&=fdwcus`ucile}DgfE&0*WQCB{nR~(O2
zpi%4Qw-u<RU~FtGKQ%Q~T3lQ#+3`wnza{enuYh4(&II9bxFeZN1^{MfXX9I2TYofr
z^~1x%j>*Z%&x^%k03eY_Tn!Ho>%fmd61(T9Z_BGhUO4UpKyOb^&v-VQePO at Zr?M;;
z>K8g;nr5dEA_ZIlY;JCTKQ}k`J60=JL;cSPtaj`lhy4xQPE1VHPD4V7RHafeo0$;e
z8mqw}7!2w&GcyICTp!HsXy!&pUs+ixrqk)$gM)+TK-#tkp=nxqZEY>*^Z5*{Kjl5R
zrN9lHz$oy^&CQKjE|)!T)nG6v$+DaQzQs<*V+eqCXzd3=_O(}BW1RzvZiB55Xbb)Y
XjAF5IM?1)o00000NkvXXu0mjf19Q|&

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/edit-find.png b/src/qtui/QtUi/32/edit-find.png
new file mode 100644
index 0000000000000000000000000000000000000000..0d2f4bbe81a562da20b0b1663e15797492bfcb14
GIT binary patch
literal 1469
zcmV;u1w#6XP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11v*JYK~z|U#g|)56lWC2f5Yqzmng98A|O;2Db`R0Ni9LeHZ>&n
zqEV|nXoyK4v|8UxX|RS%@kP_5O*FhUO%oFh2 at j?w)P%+ui?R=Ginf>{ur62GWdpLx
zF1yR=!_2lD%FPS*pG-0{XU_NizyCSkIo~KE!v6`wGkmK6X27D~hkzh3v)lw$0Cs(H
z#>U1}x7%$fDJco*_AuZFCSEpy1byOF#l^+tU0q$f!r`!UW at aV>P!&aaWHcJx85tS3
z-EMa?kOVveBG1G?MCQ6oB9eRg^5xBDv$+`<1xA1Yzzy^P{lG9VYA_gXoH}*t9T8b4
zA}i(@bIxl%L-wIVhjuB7avvB3x`0lg(_*o-CnY8Q9D4 at -(8;)qi;F)IkvtJGya<7m
zU@%yqs_HGE8~9CC)sCvFs<WM)ou7%wF%dcD at pwLMXlSTOOia81{0iJx6s4=FscDOd
ztXV1nW!5${0&5)(N0ry>{TP_ETCL;PuV4SMtgLK8m*1zy*#@i~8X8L8x^?R|x7)oA
zu$WAy-cTs?IWPnSo;3$ju3fuUq|4e4v|qSzp;|=VpC`6P5!rU{-o4{yv$;+8xxat^
z{*Oc?{dq#Ly1cx+61WZAEGQ`WPDDNwk)#C%F^R~#M~)n60B!=e91cgFo(qc-NSGyv
z#qD-y08>CDKR^GWo(Bs_ISq6d6&3aCp_!hTn8*ZFJ){dFz78mW$zrjrL at O@XY&H*C
z#aj%a!otG-m|sFdLd<8;Iv=lq0FezFHu%w25@~B|v$C{mX}oyxqB-VgHk<v=LjWMS
ze*OC4*g#`rV{ho+SQi*W1rqPvxl<VP%gV}nqEEhPpO{S`bl|{&QB_sLKxAraDu4Ix
z-LC@<eWKY=fb{0(=H!u)k+K+pqeqWEK+BuOTkWi at OcasLm6etCz!jiHQIxhzmoAm)
zS-ncndV{_*UJC|;1s03t2cQ+Wl9QA3jfm_J5$p5pf+=9Asi~<uEiKItOo>SN at ZrPX
zZrr%>Js=%e3pjzyg9i^5TCLWvgTbH^7y}{|6%`|BP3h^PtB3zoLeRqU=GCiL%l7Ww
z`_|0NjEWY5)rz7_84QL2RaJwbP$)-4l7VrwCKUy++wFs+qod#J@=pTZm~E*9KufxE
zm&^6qzJ2 at F4Gs>bpdCa~bz6eI!pFdbs;V>5XjDPViDZ+>6iH1@{j;W~=BJY<Pd?HK
zhUc0{t*fh>>wOp)&dSQNoj7qK90&x)eLi2r at Arq$dVv=hPfbnr9Y22jK}$=^!|Lkl
zArbMnx3{N6qtVPjAW+!a+PXau2>f1AQ6az+=GYbUDG);fPzaO&=HcOC?%utt*zI;n
zOG_g=J6q5SRS#h7>+4(NbUNRT^IfedinXSurm?ZHv41Wl79;SFQa~n<4a6$tw5~)q
zT8vi#`I|Ov`k=G3Gd0dPLsiw4wY9ZhojG%6Xf}zZ5?BfpAh)--cSmVysnhHAu86Z`
zs;auOzP|qK>C>l&<4MfkhA#pE2Aodk1DDG+;BYu5(F+sciAJO2wY9ZhoI7_e9ZgM*
z^-EMB1`|-$)6-K>T3YJx`Fxf*TaK!#=13&+CE9s%@?|Oz!!*#ImzVdK%jFue+wD*I
zSBYM;+5C8VdfI at l{&EnAk at zJyH@Bywqr+>n*`CHoG&D50OePa(Rd-oJ5Dz1;-Q)4(
zoj-qG-MMpTWY3;G6F?i<&&;wD0PQ at n1+AWp12@qAGk8 at 5Vo;f*C%j4mb7HxYaLM=^
XM}uER0?C>t00000NkvXXu0mjfn|H1Q

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/list-add.png b/src/qtui/QtUi/32/list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..4661fd21bf9e08e01c79f0a1e7b1e6b390660671
GIT binary patch
literal 581
zcmV-L0=oT)P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10m4Z{K~z|U?Uyl2!$1_re;2J<DN<{3u(MESS8?=nluq>n6}QrF
z;?mv4!9~!a4uUp9vBsS59FjtMUecy&ir^mt$-BFEKVI_gy(nW0tCY9W-TwiA^_=q+
zum^0UjK2c at ZvyN9wQje&JDE&oqF1R at K02L_4`^V#s6&-A3+g~kDRl{K&NxzPEFx#X
zQ+zF?yb+kn2evKS%QB9Z1$YMD9k#*%!uU!`7YU#p0QU2 at 04i7?S*&tmv$P1<-^Nq{
zj_hy&RDt~zCsVlqrqAUBsI5n=bHbH|2mOA((Qdad(snn-JUYytQmUS|rq}D8w_2?s
z at Q}1SUxA32Ip>20><M1h8WC|0Isux^<{NOAMUbM at HL=gd0AekbR(X{LuvA+8IRIA{
z>;etoByCZtR65dHZzXNjYIQOijczjb8URCJlr*{`;1kvTYsc6oupuIcSP=@tFa++2
z4jj8qK$L!8dIcANAu22b$5<VxiO4BdHx&dy0NhegISzp}%T`=5@;pzA$gdWoc?$X3
z&=y*bT>yndAOP at v|JepG#=IxzEULUssUj-Z$MJnq8n_~7Tb>u-$F=f5qkn);3e257
TI1kcK00000NkvXXu0mjfoFMM@

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-playback-pause.png b/src/qtui/QtUi/32/media-playback-pause.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e427fd9477d9c3d8612080a8aab3b58ae3b9df7
GIT binary patch
literal 527
zcmeAS at N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8wRq
zM3g|7v7gud1W-`2#5JNMI6tkVJh3R1p}f3YFEcN at I61K(RWH9NefB#WDFz0{9#0p?
zkcif|)BU{;JBYOJU!u5n%PXY--B^vhuGJNdPG@!ZG_il;y0=Jgmw3!hVV2z+78och
zUHMb^Fye5^tSK!Mlxk=HIq`e%8S~1S2FWU(PLmVOtbXw&NHeVAwfX(RF<D{4uI<N!
zndCzm`Wl<({0WMCE7Q*qcbe&o&H3Fk&Zb?@T6F*Y{j<+MM>jkysMs2zqZfL<!e-x0
zzvbUU8F&<3%y|w6n+mctPQGT<FR+MPqLNvpj=Asgo`o|VmtU^*%)bBKST1t5bSpz!
z;*mdJt3;P&x^<naNXboYVEJ+BPQS?7&m#YxuVy&XwT}J3w%lCq29Jx9{cF~;ZP==t
zu{CPrqSuTkDk~mJdpJ*Ho3QzUuA!*I^PlXi7u?O8p4SLcwvKgLs%zJ}<*dsxr$Iz?
zS1;JuZ%`O({>kQjtZ$Fo;?VQzlTQ{INTk at Td+p|+*AiG at V99ijA$)Q*o7_ at 6c0ZGO
z><>EU$OZ~B98mmK`%wME?uP{pw!O!nr~B_PGh<v~DrGPJhCzz`2b=EI<!)*ZpK|~s
OkHOQ`&t;ucLK6UC4cB)7

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-playback-start.png b/src/qtui/QtUi/32/media-playback-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..8bd1ea84ede04f9a0e7dfff156996b4b2d19593c
GIT binary patch
literal 805
zcmV+=1KRwFP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10-{MoK~z|U?U%btTVWW+f62+koTQkvm^PP^PDKJzXa_4wMd;F^
zf?aBc;NXy<qfR17Hy1NmBzVCw|A4z4+Y%@(lv1clYz*FNXpD)Gldr=`AXuAo%%yhl
zg?BsWdw%D6-t)p|5JGU3WxP`LYXBVp7QhGG((!Cd06G$h#LY6mJ>bT_1~83{jXg1&
z&C8>sqd~v}+y$&nBM?H=>OfCVPYBos(ssLjH6D*Y6hhn=Lb!zxlE(X*t(mLcZa)F`
zfume5_cRm=#RGxB3&4pQOM4>*XaX1v1_7J_Szt#9p(K;ZS0<Bbd2n#>0dN}#0Jc^E
zlz?KnPk{sAhoUGQYiny!S(c|47Z=^AvvCJ7H5;JfKy~MV9Uz_0=O0HRkyXFn|1z7+
zR$_4hhE at Vp`WLVzgg8#6Qel_N6&n~Bcm#By#v(TiV6j-LBe<wffj!{6qA2qE`ub~|
z%{Cp4M!kR^@B-$#0W=&qAImndStt~`CMPG~cs!m^I-PDu-5)InsE*~E5aJ+{$vmH#
znR$k~xGvPvoLEVcO67xfm(gex!^6XGW3kwQ+wI;34uMi#0A&Y?dc}jm;O@%G%64~m
zcM<psBv9kIu=E0GI^c9VPiALlHzJWp5l8{=QHQf;X#!ZS)|wGWk|f5*$G7I@=8hc>
zM;7=1YygVZ*}4E~MbO*ZyT7!w^s}?G^9=X`d;|)5gmnWLjmAGB at Or(u`T6<1k&zJr
zBvI`?yo|7Jfa<@Xt*uR&n3&j|nwl!fvV4SU_ZEMd at TLG%hHz+T=xAYKq2TlR&VbLr
zCob`K)C(Z``udb`IK0!}-){gmQNKFVsBonW8W$4>(1p6w-=VJBrru<<005-2Xx%wC
j3eeK}?=L3T04=ZIN1jl7h at u%#00000NkvXXu0mjfdBk9y

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-playback-stop.png b/src/qtui/QtUi/32/media-playback-stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7a7911da8fcf72574e2a5b2f4c60350b750771a
GIT binary patch
literal 388
zcmeAS at N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8wRq
zM3g|7v7gud1W-`2#5JNMI6tkVJh3R1p}f3YFEcN at I61K(RWH9NefB#WDFy~cMo$;V
zkcif|*A4p)83?pKtWOfiyd;pjF;=Q?gZhb?7Od`%IZQh2Ocr+Z1a3Q^YH>)|M8qdM
z^V#J4BHMZ%cch9gyS%@_pFu|`ooP+lEaN>~0t*<Y88g}x)Ua+~nid+G+n#tMLv4C$
z<%{2S>{D!ZbcV20ysvlW=w*AbcmI-elNp}h;rwxtA*tVnL14%8<trDk#^^F`mt-*K
zJz&Q4e2!Jq4Q2iV?Jf!1Ta*^vYXou{N?8KeGp)#5puttjve8}6!R3nJ5xJWTw>dV%
z9om+wAA5bS>E+kE{PwY{d^F5#uwQVEp at Hwl=O>=im>AZ~?8{um^x=!xa)x~U&-Dkz
c6Zn3xhg3xtRUJs(0Sqw)Pgg&ebxsLQ06aO5lK=n!

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-playlist-repeat.png b/src/qtui/QtUi/32/media-playlist-repeat.png
new file mode 100644
index 0000000000000000000000000000000000000000..45ee8e33ed24694590b112851c29c59a519b7097
GIT binary patch
literal 1109
zcmV-b1giUqP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11JX%EK~z|U?U&C>9A_BEKQrUZZrrR(YS&`dtg%RJu+vLY+8B^Z
zx)+y1J at i%(FOtiid-Gr~n}0z)3GTTps0S%6EFqy3OSLL-8&)<Nv9elCVrGBLygkf2
zVf~$r7JJAS26pCs-|zF8=Y4qISw#rJMM}NU=<fjj4*+#<Fn-#c(^QdHO#tr!R{-sd
z!9Cf)Hn8<304+d$TU*;V>+9=xY};-;OJq&c3eC;U4|2KOk3c=JT0O2D=mS at Pu;1^$
zUn~~yNOI>a0JwFg`Fy?ymSuepY~p4EIGllyX_|M7#o|q1Ljs(Kv|_P%(=^Sy^Yio5
z#{sB-k<aHpk(7?6Y2{cf_GoZ$aJ8YKp(dE!-Cb>DWTa(gX66gqwsoK+y?>IioPz)w
zfNk3rPz31e>iTVZdU^?1_ny at tUteF}^X~5Mx=bc>tIFGpbqK&6(X<yp2_PPiKL&mV
z{;Dy!r}lU}Ze%i<PpiE5=@5XbsuiFNu(-JR%!7GLm83_x%KKyhMNw>T!S?pHb#S~^
zNsn at s_sIabmG3P$^I0uD%2nPc11O48L8e_*)mnRig4;!dxJ9c-k5ZNQJ{@%!c^N3z
zn1KLr4QTA?>G at nj_^L8c=7<a&0;sBi^3u}MhkyZG0(6evG98Ejk^cVvk9A$YpUGqf
zyg}*Vz0ipO0zlVwZwpG<Y&Mokr9!|}pbhv4X!clvM&MdHoo)(+LifhU$A>GGN~o@`
zZVn)oN(HmoY|QhM-mhc9;j^GU9*^Iinwq*T?;C-ue!qW7Rn<~cQ`6&IE;j`{1Hypb
z(b4f$Hk<uc2%!Uc;2%|09m6m#S(bGJcnTB%dV6~xPEJlfq^hqR+=5rhWU>$l1YXLt
zZ2)=8vZ8x?dmV*Bp+(MX9vT{o8iw)1^78U`LWlzJJ8lavJC37UmKBvi8$dY_2)s-t
zlLg?_aa#beX`1F%I-PzJ4u^MT>Q;e2fZ0GGupsA^hKGmsL?V$527`})72K-#itV{v
zvkH{L;qY!coql4P=9Ywft%F+ta2fd0ah%A)!h%>^TT{FNP1F94#bSQ~IUovj?d<H-
zClU$&#Kgo0j^ii*kw|23Y;0^({uZ5`or<ceYrrqSzIJ>R0JznD9k;sctDYC+n?0BJ
zKHwH`V|I2{9T*sBn46mmwzjtJuB@!&aX-ag0BgW9M}3+JA<pA^UkLHFZQJ)oM at I*v
z(deKM;<^yx@@Z?2%fQ=61=@knN~IEpVf>0)8|9N0ohN`NA8to{3hbRW`M&_DNf-Xd
b<Q>4jAQjda4<CX-00000NkvXXu0mjftj7R;

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-playlist-shuffle.png b/src/qtui/QtUi/32/media-playlist-shuffle.png
new file mode 100644
index 0000000000000000000000000000000000000000..401f6f9a3b12a7d56f56667b5074fc4abfe2f147
GIT binary patch
literal 1464
zcmV;p1xNacP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11vN=TK~z|U?U!9lQ)d{*f8{_ArC(4ORSJlFnP5i3HZhAcQ=A#N
z8FYY2hfB8I7!!<m<1UOhOuSi^EO@~U8R`YoCB2z^#NbGJv9RDw##fiotgV7D#ab&L
zZK3Vi#W`hX6*o6^-uO at 6q)DIiKL6+cJn#QKM<YoRFA^y)H2X^e&xwElyaHqanioO9
zGB!45jYJ~3z-GYkx6zU$J?oWMTU*<dl9F<xuCA_8lB9A;l5CPBY1fN?S_L#f24Def
zKp~(ro6U>yc-%HHFwmKik at 5NY^XKz`O+XGwZPBQFAPo?c62yTB5L+jC24Dr!TrOAI
z@#Dw0&dtr`00aU7)9mc*M}QVEXf&Eoetv$p+wJ~V6vb8GF0iO3pjRq*9HPJia9<&l
z16U3oJXq1&+uItAMoWNHRs1S&Po<I`FbIO+tE;Q~;>wjPlYkFcNj#)KckZ0!#EBCf
zNr^+EDEh2c>%{fz*L$<GvrWJfV9L$S{d9hQ-mWBj2&^cI0Z0nz1R_9Ck|fL0(o)mP
z%8Fa7)rx8Ynn)y~iN#|2Bm&0e<>frD*Za2BYHes}XlTED`SP#D#l`jW^YcxLl%e$W
z^rf=0vYT01Ss{R6Fql3%I=WT8(UvV+rY>H*I9gp at y`&IcKrLHAK|utVT~B{Nh{xmc
z#>U3k-Me>JdA;6GfLlOx$BrH2eSLjXX0v%M*y(g?ckS9$3Sc&y182^h8EI*0SpaSV
zKLQUDu?Yg<0|yQ)UAlDXGj&#v$CK9I-=8-;Jp6t`L&G<sD8`*mXDcuVgv-mzeNLxy
zQV;|eFr`SHJ2W)3Nf3m0>~{N&&d$!e27 at 7>B)+M%XAOxV)Bq+RJ*o0kK)<lCkYY3%
z<2s%0R5%<i1Ri8&W(FrFCWdV`+Yi8`YU7PVLqi2QIXQ1sR#t|Aao}g<S$PBr1tcJd
z+#5C00Lf at H8cIq^>cZi0889sfLfqkS{A9D)T)<3HRk50ynkX<0{DR!7b(6!NR;&ez
zfU=}j1Q<$7OW*Z)JRbsHAae5L$s08_HJ)R~j-?^{eulcJ=H})NMx(K|r>DovV+<%+
z0rS<XSIu_2y;=R|>guX46bco`VzFGn4TQFD-+ue-*|WEci;F9KKHmq6i;HdD-Q5}>
zgnSf5olX~7TwJU=eE9HJr%#`DxLmFQQ4~$63 at DjE%GA`9E)WR3l|(QGECXXeq`JEL
z&fwtSOiN44ve)Z<516 at d;linF*RFlHckkY at s;a6WKrk2-fKf at 3Hh4T9yI!x~SzllO
zwZq{^Rrb59kX;)>Yj1DwhW-2Zf4rVdSy@@(_V)IfqeqXf0;3LxBmc;eBRl<mzof{!
z8TlGcAVC^rd*1|PnM|hPuCA`0rlzKc$nA_K2xQO9%;XIW4D3`Vwpc9jZQHg<g at uJ0
zWaAh{_KMf$=H_0t+wCT&)0v|vX+$1ckX`V8QXQE<aYaSNt;xyBFOi4$VS<1F<O6Re
zJ+uP&fjfXFAsh10Rs$9N{r#H3!NJs#k&$%2-=7K)i9}L-KA(Cpv0AO+j*brhp+kox
z;CtXVKvLg^{{;oW>&Pcztp(%b<MGPMN-Ka?tBtp|w))%J+9XjFA0VqZjdFBTAKmj`
zVOm*<*DxKB>2|v_0n45}dltI7x>k#dilV@%vecK<Qxixa2K=u4-l)}THGO at 3_xA1E
zCm`GJFpruX at YffTX9W?c0Ln>{`~M;UvctyzF^cE+UGPN7pC^GQ#!CV(oWLJB3Qz8m
So>W2r0000<MNUMnLSTYu6tGPI

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-skip-backward.png b/src/qtui/QtUi/32/media-skip-backward.png
new file mode 100644
index 0000000000000000000000000000000000000000..95e8ec7e7ecd8bc198a3d86926015506fd724d76
GIT binary patch
literal 1099
zcmV-R1ho5!P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11IS54K~z|U?UqkWV^tK!fA7)q3W%1%)EN^Q2P-sfCXvLbA+o65
zNlA!dLvTS at AR1!Wv0_8ggcTdZf(7Z0#Y8iTnz-Ok0!A`eqmmGDnt?JyH3Cv*D9{3z
z>*C#)lt&A*5*M80=H=b at -S2$&oO928nv{~OH2q4wUkkVv at P82Cu)V*ehGoaVwt5ya
z4R9--XF%=(UoQd%un!zqllc+Q0dFJ{c`FbIv<3o!){&8sJ3vhl!b;#Z;Ku0aXdQ5~
z2(ApM1#T+btuub5l-6)cDeDcx_!`&(wt~Unr&7w=JPcAwmzt|@X=(Y;;c)!mcDp~9
zQodosIi-}ZNGa?4`}^N7EiL`lFpT?B%6jz;Ddo8o;B-3Ia=F~=03MHLGyju{MrAY_
z^+u!7&khd{-vf>f!}!h?$!fqoIXU at 4XJ=<`CX at L9puD{N8 at s=A0(4!^0DAysWo0?c
zJl6nK3kwUbNF>soPN!R?lqJC5K-T4QJypxyK=t0<o--H>wr^}~bV at 19fHbi0a5#1@
z6 at XcASpZGbPB9C|sH>}MO(v5cNhvFVT_6KUg%e7sx2dV=-NnVlkA)DofTv2N%;UaT
zKuJl-396cPT|W(lLXGqD^F2a{TIF~ZIL%+9X`1Nm?Y$j~#XdPYI=ZXGtpX<nxX+lD
zcN;o^J06dxEuBs`sRdF9;m1tLR-qjzTviBiR|(&=B51d&s;VD%c6Po3)-0}b5zsX4
z#3B$vc!30Y=eCduA*z6N%wAB`6!#fB*9kREJ61c%_4W0A-_X#oV!am|ZEbDy&CSg}
zU4~QK7Yk5%$^zNO#>UN+m6b>1<KuC!*Sl at a+lR;F*`Ax5OHEBpJ at EN_sbaW7HBcx5
zRuSfAXJ?Z at yt})5>+$2q4+jSamn$kN_Ut>0$KzYTgK#+fXCjeU9~&E6s;;h17l^=f
zr@&HtidlSL8iuhrG&J-qnM@|Sy1G_%T|cyNx~>b%I++A!dwP1(sZ?rhU|=BOa=G>`
z+;gSC;c(amfLXD>0QYKYYJQK!VwvUT<wv1V=r1L}+Sw`a5ct9{jQH^IaAtjdeXXOT
z<B6{8hl;zX00|Hb2D5&@f7kE#@A`Z`VZ$E)bHIJS- at h?4GjlLKJ^dsc4j<WYN5Id(
zJ+IfBn3$NzE-fu>w70kK=lg=QeE{G#@FwPs1 at Ig22XL;1Vs^e)fwwU`-mjSHDr7f+
zcYqQg4y1|+(14dQuTX%0xa4eOMzNG4&Bw;=Qn;cK_|NUif61-|Tno4s at GqW*zSg91
RTWkOT002ovPDHLkV1lr3{I382

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/32/media-skip-forward.png b/src/qtui/QtUi/32/media-skip-forward.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e73ff24755dcf3fe5050c42321decded15e0261
GIT binary patch
literal 1108
zcmV-a1grarP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW
zd<bNS00009a7bBm000ys000ys0gnww$N&HU8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11JOxDK~z|U?UqkSV^<W1zxOA;L`Q29C*uqq9c|Q*ECx#pt&)Yh
zC{zoXB1kuaMWhUZBHf7#p}Gl3ppAus(00*nTdB~6AlTB(Ft%Mx3!$ZCrjCk^lQ_ni
z#F#g?i at XOhd1_a+3lH4IyZLg?@1A?ky;l-KaGoZgYxD~N7Xtnd0 at RZ4D&P{Z4`fdH
zpAD!6a=^hUoC3Iu;t1d=@Z1DSGf*FmMsEPufonz}EAvF7(H4Vg0PH7l?zy=+uix*#
z<@ft<_4W0=30yr!2qDZN2_afFP5Zi{qT;*p@$qgUM2isOvJgTk;t)bK)z;R2tg7md
zy}iBf3L#pB5Lbl|wi51IAP~3>JO&<Xn)a>1N+wfQ1B#+-<#M^3kx1l=>gwtb7Z(>_
z25taOKr%T^(>C+@{Pm@!rB5m=D?gf<nR&(FE*EFk<#O!++rYNXW=oXDD-)oqY7%$^
zqz(=a-U@|6Uo|u|yq8X=uNVO?0od*Kr@$t#oylZgpPHKb-0gPXj>Tg2Kod|4NDhbN
z5J&@QS(eM{#i|RAfGqF?cp!wxuCK4Z?{qpBIyyRn7_}iul5TK&z(XO#UNV_{r?a#3
z%jV|h5a0o-BuRQ<a9P9m at dcMoD2kE?4vVI;z!P29-LY6~O4GFaLqkKK8UjkWq!7ZH
zNF+W`RrT#)F!-6n;n+7h!}l?hif%&*XmPn*p;Ri>VUZaqRJ#Yz6h*nO>-tI6Z=+BP
z)rz9TbzPSLoKELY$z<{y;7<xIS)Kt&lJdrCtjtV#jjroXAax3t1}b%3e+k$r at _o$8
zYCw{tBMK=yaRh_Gd!bP1hqJi0wzl}_=;-(6x8eJA0meRMt%ld at -B?~;zPq}*y5VxU
zc2D9w9?$N=!opfS9{;Poy?w`=x2l1YwxGDUaJ${lXJ=>EM at B~Sz!s2LTU%=_<*KTx
zauX91e@{+M9%`DF0{&Q8S*ZnHE%JS)0J9CT+wJ<;*x2Uu^mI<sw0+<XkN}!wSvK1c
zS(e4%;NVs`9M06$)n$QSfZu_7MNw)@&T0$F1gNTdB+GJUU|?W35{VpoJf0lzEAShj
zo184mc_7=>)s>o`pMU1_`Cb at 7f2MFr0iY;~c at Che>e&MN`}>~_4-Y>I1OfnY;2suT
z(bLnD3x~t&-QC?X at Bp|=;ifxgUawd8`Fwi-jg5_Eex#CD at fF|=V+An^EoWs;;57=z
z@*N6wVP!Qy0Jv#<Zvkt-#z_L8aEO$p%EJCFS4rVb0EIWkZt;&+0{&Aw_b1tffC~W^
a0{#JdQI`->UloD?0000<MNUMnLSTX%z5FWx

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/audio-volume-high.png b/src/qtui/QtUi/44/audio-volume-high.png
new file mode 100644
index 0000000000000000000000000000000000000000..78775077a23e727f98f9510e159183583c0c2adc
GIT binary patch
literal 2413
zcmV-z36l1SP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H12<k~hK~z|U)tOsN9Oo6se=`d#w`IL}HVd{xz)8RcyTOhGGO<Y-
zXhVXarUKP!A5c=oSasqD*GZb^2q&`oP~{;~Ejf1j(8R4(9LEodDvK7U!L+f1Lwrfh
z-R8Ci_A=mQ*`59RFf(RYgJY;->LVR#F5h?NKj-|<ne%-k2_blpL|$nCOO*!>aKZ{d
zKND~PVPFCXecuFW1v#vs12!cF3<9%vo3v7t$TXCcl$3)71qCk{Sk?lzyUr9s+;7bg
zLgWh}@>5e&|BOzB;p*z at I^+7oLI`QG`S%-anh at eqAw<5z;rJtP6X*kmBuV=2;K762
z4bbkzY}`){I{}Y*lAD`bH#j)BTL=*XB*0~}*#>+*--`~1Ljwj_fY1L6ho$9!RTO3S
z+i$=9P=9}aXG257DL at 0Fz@(;Wj}#RZ)fu*x1uZQjtf at kXM~u)tVw~R-XB`g5VPL{$
zvvrJ&jQltfiR>vTC^!aOF!UQqlCGRPcW$#WCnetAQa!v1SO?gRb31xw+ZP$13_Jwj
zbUOE|s#*t3YnqmumzTFUAt9mv<jIp?CM6}!7 at iIZA(Ebd{`r at T`R;gwO9AXQAD)$!
z^`az6pXTT1SF?EdoInmB4-O6{OifK~0fK-Zn4FoJ*}iq_*0mcpY#6Jnt7|s^Yk<$^
z^VPin{`;$p7oP8o1wtqZA(Dj<=@wlhgvbvDgB#M)(vAXNz-zPF+KtdX7H7k0(xAM&
z{Fg$A{I<5Xx|EcZPl5A>UXf+_-_z66#lyqHdy<lp{to=h&~I{ba(-vnSbaB2IDqwr
zXVzFWy`!VUt|-dyr>Cc at 02LV3G|kL<*%GY`j0DTb$T-l}*7k?0s;VtJcI-%d_uY3-
zq9<4s2*zSDWz(ijmD$<Z13P!_{L*sIH#$06YS>G+0<@O3G;}`F+}!Lrb?Ve(<_%5L
z=<MwLwWeu#Mp&neTS-EQ2IIIJogV7}$?0_N4+evEKtz(H@$T;KJ?q!6-<+G9TRbo@
zP;Ab(*=$qMX!JLqeDcXpYHMqE-UcQ~tJ>S!8%s+|!|1g-0`r?61;FF+G<v<>UvcLr
zQlJ<5Tb65)xG{D>s;{rl4+euZ=zLX$5K3`z at r%J=@UKUX9I;haR&FxJM>S1T-h1yo
zM^jT%ufyR8sH&O{AcP3N{PN3XUw{2|tKnrI%!N?`k^pYryjg=z{^>X!1_B01t6C)l
zXeUmb_^z<9um%0II}3PKRsCsmb91<&qQaM*oqe6T at T-Ro9V)lkY~Iq+(r=kdK6P+#
zu+WTz`2Z_m$#^pj=m&1Z>C^&X;{glwgiQPV^Utq1oz4*h at GW5SqmMo+0(#2I$}U>~
zPkFuGLLl(O6Hkm=07s(HsQGca&4h)@+D-KSboL%KUR1#Aa=H2&8XCT}jGG)98hR8^
zpL_1P5z7nDYMKTh5)%`>7Qk9G8cn_zz at bGvxtJ~_D$w)flTUh$mk$Fow{G3a1Vm0w
zPJlTNM>S2e17u}o1>yjw#sgkx#jzNOrN|5rD=jUZ*T6&~5f?yFQIXF83qULuO9m(`
zEHnX|*G<4Sbjpf_07n<Nwk+}ad}h)CAW2dPAQTEsS)U`zas*&{dU_`A`5JNZLwPtE
z;Egxl$gu)mvt~^Xz&r1}<FW#CyWM_(<HwIXtspZqGbfG1D0)KwV1UyBdV6~d(fJEN
zSy`D6;Nr!L4_g6yJRTL`+O=zLD`1buV}77+k6j4xT^E7(AQ?dV*|TTufk5DKV9dNx
zT3YG at 7#J8>hs7~2mn#6^^Z6WBz!@1C!NmXzL#5TLR|h60CQPy~Rb-5guDZJVB~8<0
z3<o46B#5f2s^G-Lgw5~w=b|Sj0OjT7BLI_=lUY{4Znt|n9<W)~glYKIS6>~HWqFq6
zm9=z0uC1-zpsMOt=9W3Ljg5`hHg4SL+p}lS<3 at dr0?~wogh*3UQ&3e^IS>eJ#8TF_
zZQEu>XD)Fq%}+XdXZBQIUtiMs^XKO+fts6}U7ekstKwZMgg9axcB7Y{JXKZYl9H00
zSFc`80m#Y8QM<dl144+7jEsx};cz&F(UWZ7zJ2oS*|YzA_St7Wt*x!~=$~`!c6(%O
zZ0u8~)7b;`nqIbYcnY0wgL!#*kLBg%%>!0bQ!`m#Uq5sD^y%Bpx-84FIQ$V{!r^e_
zUb=M2*Vxz?{P4pMU8hf<_9Z4J4i^^}mxaS&1-N8R*t>V{O<?@Og$q9eCJpcM%rno7
zIi1b`I(6=#ged`_75E!)#-iu!c6;FCk3SCW+qZAX02X=r>8B@*c`-vVJTxH7^5_R2
zd=P7GZ5`XZd2{&9H{YD?>gxKr5s4 at e-LhrN_^w^Md`FKSO$i2r`4(`|UAuPqjTbO0
z1+cWOsw`j|;5mHwaO|zO-pV+3?3llzqM{8wyf@;;E5K8Lr?<EFVnIQ{Z==zu23#`-
zbaZqKmz0!rxm>PVzu&(W7zId6OPlTQ at Bd0sl#A$%*li9kWlc8<`~w)=y?eKO{rdH(
zii(N=bA58WjH5^EqTB5bBqt{iVDauNue>r^Qc~hSaNt0q-|ycFj9?_&Yp=a_Ls67b
z^uA_ZnO)9CN(!(E*a&<D^f14vj~4|{VzJnd>g($>TUuH&D=RC5pMCaOBpeQZ<#M^2
z!r^cNFa(gDogM1y>l?P)?O&j;G-j;Ema~x(0{#R13F!JBu%LU|C(H8ei4!Np>#x5)
z-qO+%k!AVDx^?Sb2#3RK(dncC+Mz>-#_e|dAo^-$Cf?Zn+^V{r1HeR4QBmgQ%a?zF
z9wil^q at +Y`Z*QNJW%&#AQg%n1aKHD5Gl3FdAT>30Unmr^0oMVtva)8ny1D|2qFe>8
zuy9`7_x<5X;7dU3>FN1PMMXsyprxj!&Yn4Q#;+(!5Z$xmiy2s{9r!HZsc<-~)YR12
z_V3>xsj8}q0PX0N<c>brl$HEtum;$UPLn9Q=P&a;-Qr3D27SM72l~h13jgOnWtJrm
f+<&?U4)A{g0ry!NS73kt00000NkvXXu0mjf*?)`6

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/audio-volume-low.png b/src/qtui/QtUi/44/audio-volume-low.png
new file mode 100644
index 0000000000000000000000000000000000000000..032e10a07f7e4f65e7c0048bcd9906f52b64b188
GIT binary patch
literal 1729
zcmV;y20r<TP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H120lqdK~z|U?U`R_ROuDKf9IMwCdQ1(q)z_mbkpocO&aNL%nZ1S
zs1QV1aUu4lh1l-150--TO_1 at ah2o=75PVQXD2SA;6a|fKjhl6Lp(NG(vFj$;{4rx@
zOyXp`bNX=a#Os%dnIwd;;DL`j_xrwc at 9&=PeCM8XM^u#`lUQpFuvB>uyxQ^}c&Q>H
zyF?_I at BB3d7Li8ar@$v7Qksv>ngNT*cHn33X#vn8BI_5^TT2U18Rx}7%VJ6^0baKp
zB at w9=k at c$jJ<w+imy5{Ocj+$&cq8xuPzTfkCHX44Zt!zpw}@CkH!x~U+u at Gol%)cf
z12sU_*9w7ZplE^l#Xtb?xv=$ae*kDwColLG$ar*$c;nkE0uBNd0F{-MzY&oy>+9=}
zx??}dF+Tuo1p=v5>Vw9{##&=MBq9~6Is*(CV;_k~VZOi?&a#(!S`FY&CX-f4Ny#5Z
zMn=8>O8Wczf9dLM0K|X|0PNqtf49%)(`(nRJ*%p!@>&vLr+a(?q&@uwI0jl2*pK6z
zH9)1OZG7<Hfv=*X;*V2PQ-^^h at PlpJ-iu~8;T&vfY3c9p-o5+h*4EZvG&D4%&!0a(
zY+07~!8VIXwW_9p?+lj8T)^T<FE;^I0MTePc;m*653>WdZ4-;dzOZe(7Dxau-J$iW
zdcyskUDjFvzu*76L?ZDykQR~gSS<GIUAuP8hQr~|!-o&OKL1=*|0yEnz^9&m8~9RH
z-&&Od&+iI=U at +J|Iy(9*=7%i>#(-&0U)q>c1kl#jR-Z^DJ_B9=NmZ at byLa!YL?ZF0
zvuDqaA3uIPluoC!mMVAsH4dZzpWD9<XK##nZ(w-_3jxN)#y)eOZpvswz@!W5ZC-f^
z==JN at A2&2K{1tc(%mSmyWU at 6HjRub#IWoO%+cvMB06{lmj2PD|H_qpP=X_aJZQv>J
zz0qFgfHi?Lz&Nn6qobqS at AnV8z|+9Q)vH$<0a{vG5{6!ddz>`-H!K9~l`)*9na#7A
z5(mc1%F3ReIC0{?o_Q04gM)Pdt*xyyhECR}Uo8iChTN81sO6HEKwoon^C-^4r+`<}
z)6?Yu_4W0y7XVunxWMdq2gFk36_ANUBLBm)3h8vZ44|&AF75OAtW+wMjQ}eGHlKdk
z5|78Tn+^aGF<oKFvRW420C48anGhb}>gwt~fWE%ILXUOfjb%-XnigL*;1YoT{{99W
z{{>*ro;`7Z$B!SI_gxWiuARRWDFce`-Mi<ToSgg!Pi&1uB5{B_ckY<kUDj1h;FNJb
z7bWJFClCnadO749CD!4_)T2j_{?@i_3pcD46cnTmA3mG_=;-L!Way2%NB;s3G7s3!
z-u%?5Q-hXe%`Ovo6ClTq9ovyiCO-kPQDU~ez5U6~ojc>VZrv&x931r4ZVHTuh%i4x
zn=paB$xkUxhV<#cz`**ht}bs at MKl^Mi^XD_%?qgNU)-MqI2H~ilSwNa4j=F7=_vvT
zg+j^R-rmW=!oq(?B9Sefot?#=ON^`Pzj7o$uYtdt$&VNx1IvMrfe(2*za^DQX<J)c
z at y(kzv#(Js%gWfcec3(jcW)8|wq`P!-R<q|>#kh6QugT4qaT`@nuac4zC3dB<jJj>
zOvZcDuT*u|E&08b#*nIZnFca}!P$uAIGZOc#lZGVCbRkU>C at JQ3m3Kk95`^`#qHa-
z|Aw=yz3vg5G&P*bWUB7pzyEsQzJ0HHdV0P&c<^9oczD?RcAZew`)+xE5H|sH<!e<P
z%m+A^hzk(`f)_7d%$z%SuJqESOD_%`I&>Fjb38M2s(>&MoSB*Vy1BVI(B0i_es}0l
z)p!o;rh$K`>b#d&zQ9=txX>Z@{5cTAsTSsiAe?wyGc+{xtfr=BJ5G(4m3~$IkBAfl
z2Y5TL=~mU=TmVZ21}C#>0(Jo3;M8N&@6-U?DDW{(`85i3x<g at Li)ZQ#aNFE$D*>L<
z<&Dqgr{F;E0G_DoYY}O{sUf}c$o<HYQ*yoO@|7h&sasWa1Bl2r=EF|B3l`S)+nQMw
z&j4R7rnHv8T{zVZIPtqvRda3Jw`3(gykc>`p|t={Rn;s&bL+hS+iR8OJ at 9JFj}G|%
X;^%Y6HZiuY00000NkvXXu0mjfidsvF

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/audio-volume-medium.png b/src/qtui/QtUi/44/audio-volume-medium.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9b18455ec8c1b420859e8895aab4227d7904fdb
GIT binary patch
literal 2072
zcmV+z2<P{SP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H12bD=gK~z|U?U`LnRNEDRzcVvBaFxMPxC30A3RYCS7Q_e%RZIj6
z3B_D{(U6)*?lmbU{w1x6p~m=N2*&iGYT|>5sXmF(*lKvNNmCWPsq{t*A^x=TBV6!j
zfEnh at 48t&UX7}No!Q*jMpjC1cSF(~}pSAb?&f06Qy*5V at Lhxe}(`*AwS3UuMX!!&@
zU6CZ|XObj2rfNT{z>*}b0)7G%NRnimN}rDnYzLMA4yV)kC6KMPTYz<vB+Y%_03Q=L
z4M+v%0?BoCbvCQjs-OQeVBPx$nJKUY%$bIL8ejuRNlE!lV`JmzhYuefuBoZ<n at lE2
zXSYz2q|A3tJcE<YhUzIZpa8>w_Z{}10}B9bHrqj;&-b<2Z0_pp?EE%6J3CTdUY>pX
z_HB#KJ_!6>2oe2%0H>nHp;4Xz{y6Q)fCC^oIr+D;EPt&5SrZZxT7$vh at 9*EgpRjrJ
z=A~}8JEH6NNC?pt4`8YxApsdN*tE2?ZzM^&k&}~CsXb4L(<dzk+uz at B@%#O202vqs
z+~ecp>kA4BHWU;Tj8|4x8dqqUBuVi at P6%OCix4772w~T$QwWhG%kqkO^XB~tZ~-o}
z+58V7M2 at Cr-56=H_L7p4Ukf2}T3TARCMG7{0Pbn}$Ye78Q<miweSLko>FMcT0aZH9
zjKlVZhZmuynsn6Vk7+_%Tbnf{CFKu+K%fHf0WTCq(I@;^96Hc8n9XK8*wWJS$BK%I
zH5)c;n0M;bslNabP334bnv$27_e-bK8QHXHlhMm*@f at s=;RUE0gocI&$Mx&ie;RwB
zC<^WE?Yk63$wFP$SiH^^LTuB1_o0T46DDJJD-f0>X}GJaYj<{b_Ua`|mgM*K_2tL<
zo6Tl_Boe7>YHG6W+_^I&91h2T6ySz&^XYfzA^?ZOQR{NKcA#bfy$E0k7}K?d4K|4Y
z)z#HGvMg7j#;Z>Vk&>UE|BWomm(QI$XD%x%`%<%yD2kGD=FFJ|yLRpJrl+S%{r&wh
zU^D9KzSK_;3yC=~z at ed`D(&q827QK_zQP98iyz?1l`H?r&CUHYFak^fE}zf$i-v}V
zP-$tYCp|s=2VRAS at 5G4{C046d<mKfVGtEN7-;=<Tu`Gm8fTzHKLH%)Hjlf~R1I)W~
z=gy<#<mBfX at EG83YHC^qbQc#FKhy#HT`pHHKyGes$S_{Q+ko{l1cbDSrlLj}20V7V
z{pq%C+y1Sya}N#<E(Lt$<>k+HFFc_r3ILgznaWIngT(jb+termHH&nwUAxw$y?h85
z9~&E62neUs>E)G&BZ{I}0TwS_95x))Zvb124R3*%u8afGqN1WcbgK{!hwT8XR;}`A
zumD7((FB03tgKLCVxlP!2*f-+CE!S$wi$`X<B4rL03=BY0tACWzkVK*$uwmreJBqn
z0314W$cYX(BO{|5;P~<5c67k0si~s?y}iBGU@)l9yW<}NSOVq)^z`)PqQ)-(#l^)Q
zfR2ui#d=_e!{Gzy>+7>bqfvb|HYMPAJAXQ|5U{qkwpzVj?=p0Wzo at 9lqk(0jbBx_?
z_W}$I3>Xh9W15=;o?M1SixzoDMn*oHA*@9Mrn0i~TSZY!Xb!MgETW>KLLM0zF^`Up
zE<xwLl9H0=01qENG;Xq>ae`P{3!|QH?Ay0*&}1 at AFtfB~1Eeimwyf~^d<CfW#RM=>
zTU+~N<;s<w-Me=$i$o#`XerHNv4rdD>f}%;Bz1Ij%r}hZHUjI5A3N&V{qx at 5-nsYg
z-P7ko8X6kx?d|Ogi~|TE&S^jUP(A#G&*w8078ZW>`0?XJ0H at RG>+0(A3L)BTHrv5a
zC=^7iN!G7l?`~~vz1`H*G`3^MjtpH4M}WV+tN8Jt))YTvWo0eR%F22Ttg5QYU0q#0
z-rU?gS*)8(CgU|G00feflF}YLc;Kn6t(7lcyl8K3ZuZQXGv`@;etvN%6iNXe#5(NR
zvu6kxzIyel!?598 at vce6lg<US0 at r}sI{n^iwR*2zyB6HPfBzs_IBeXwaYWZQ79P)l
zmnM_x#f1wOqBn2ee7Sn{>QH at s{X}PH=dXY+&3lnGYt{_c)YN#oySt at Zw{9gFSY8-m
zVd{4}3HSo_8tyoI_H6Xnv17LL=g*IpmX@|?u)T5Y*8+~7o}P~7%a{Ky5{W3llbBIk
zTidh3!otq&+qciXeEG6Ie#5}ugb;5WVl%mfu0t!*QOm~;)M{?bU at M{C^|F0FpEn~T
zW0&9WAJ<^myLa#K>C>m(ckkYPSXNe+6$k|M%l|)LLSr%nv;gg>Dd!3BJPs_pD){@8
zl9KRxz29%$x^)nUl$DjaPo6xfgu~(P0|ySI8DN7z&)WcI at _&iRz8ch2>@t9L(P-3B
zUtced962J*pFe+~rluxv>Cz=*?EXs#G4LUPrz5ZJ0bu0l(W3*6jg6_gI~;&p2=U!J
z2l|NLI3(12V?OXGIXQW;EX%37=Ru%V2=T^o{MsP1^-)HWBok1Gx{)KmcR~pHz5QnM
zE0PAi4tOerc=<kim}TIZ$gF=dn67*R{?PKH1O6{ru7ozcj!z>10000<MNUMnLSTZK
CPw6TE

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/audio-volume-muted.png b/src/qtui/QtUi/44/audio-volume-muted.png
new file mode 100644
index 0000000000000000000000000000000000000000..636583f0cb37225375b145f8dd0db5b6a733eb93
GIT binary patch
literal 1412
zcmV-~1$+95P)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11p!G!K~z|U?O9!n)KnDyPG^|iY`dDMNPvvU3lGL<6xIlcJfI00
ze*y+25jXx2d@(T7b{7%}m&Sx2x$Uw}SP~53LE{?`2}p>BD7Xm{_d)c*7haagst<@x
zn{0NbJ-!Tj_tKr&L1!l<e95Hkch5QfdUAVu?j2%g+)gmsEudN45!`Cr5!@_%-#;j&
zd~v$=)Xpjq1i=6^7XXwE!&qJ{7JqEy)3yvtDR<Vy0zh|?BqvIx((FclZ4*pHmo at 6a
zN~LlX0M+xGalul`&81Rlw&OUT0NAIFG4qNb2wtz}KcjP4O1YDW1b}nh-QCZOjg7^Y
zWt{}@oMLt*48ui2i1D--GnQdREC4(mhT#DrL_$RG0#L=}Ez2sTgaB}h8J1EOh^U{4
zHrlrRMI(F9^Rkv at od@uw$}{sS*LBbOzAphd%Fth#OlCo$P`IwgYAVB?=NUl|l!#~m
zz+7hD+{nlG{T?AiHA#{+0Iq1mdjXJP7`p)csqlBjahzJ4r!Cm?ye`YKjx+On3jJ(7
zA1UQd0K-8LJl5CO_bY%6>NpWC34-9&VzGFQnLk#?nEB<jn5k1D2!cgPl02>jw*mC%
zwvOYZmLYA<UJApoM+h<D`~C?4YWB`Kj<Yfdf at RD+tng77hWF_&UpD1NeMGdEi0anE
zdXQ2+tcV4GM at -Y)0bn~bZzm#E at bZCyfqTm3@&(JXeg|-WjW<oxTm|5i8vCXxK}1C~
zDBg|Wy6#UzbXbeKb#QQSj_bOY0H~kf3^PA3gh&9KoFvXLR_L+Q=J4GABK8KV)oPK5
zMinX>$8iq;F!M3hmYG-8PDfNeNs{?`+?Lhh{{H?lGk>Phi)+WPHU5Fx at v2G^(L6nF
zOFtaUd{Mhz0sw|#T-8kH*W*>RRB$Gfxu{W#0id(9Qx`T504kMADzBoYf-9BE|K6yy
zI>S$B)Cd4XQKY}vR{>zwtXX<S^^CVxFcD1>%*-PIkj-XOg~f54`XDM=CU|IQ$YSR8
z8a)C4Ns_G8_)!2b45RrBYqj&1F+M)NAHYI|inH15_qFr2+C9Gl0A`-l4gmN?kDHd^
zJ(%2|HVrA|Qf7WfqxTgGg)!gv9|G{G!dE9ICQf;tX8?FfbztUi8w$2<`=DVM^NDEb
zjUO{F18{b_f}<$<4!{wGx)g??001J|rI~-TZQHg#y1KfS;@>_30KzDWzSLvi)cgQI
zu~@tY;DX8>I&^4txm-RB;0=Y2)BJ at HiRXD6Ez1Ic4Mfyi>(rhCptp at fwFg<N at u$<4
zNz;DmHf`EeaU7?YnLkkI^HbRiA(Ai*H!|~T+qQog92}ej;8WFxh=v`<IktQE?t6(y
zpF+pe;x=6+T-V*f%x?p at Oho(Y*$N>N*LBa9N~Ml!wfZ at L1$sCD=;-L!4&ZKuzn;tG
zP9X&|vTF7`&oE8%2od%Eb7P|Ywrv-slnaUIX8<|HWvk;jAEw2ckyW!0B8j5tEh4(n
zy`9eI^RDN41`!>AB9 at 3o!!Z14s#r6&%ojo=`Fy??z at A(#w|?Eab+Kuhdog)W0s!8h
zYEJ at a<7QwG1aC64TKYgl!?ta&05GMfw(YGk^BVP<h(<G+%qyrP7HFg3FbrP<aHe)y
zCZZR%Y}xW#Bfqxp4||^1X`1Fy!!Qoowtcd(N1FxT3flgcL9 at 6cxYfAr1pf{7MCJ6)
S!Y(iX0000<MNUMnLSTY^wvIOd

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/audio-volume-off.png b/src/qtui/QtUi/44/audio-volume-off.png
new file mode 100644
index 0000000000000000000000000000000000000000..bfc2f8069cc755a67c0881977a85f81859bf1973
GIT binary patch
literal 1318
zcmV+>1=;$EP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11fxkrK~z|U?U}nzTt^g#zq4j}7~8yGc1)gr1jmVmOodV;UD8HK
zNtMD%L5D;|6^WW6{{U5rv>>IiB0(Y-Q4)ilNH&%Uj_nWvhQ)ww9^Pe7ikZvK&b{md
z0xL`Wq|x0wcV_N)&pmVI%w17cUM0m!4N$C(fDc+nz{N^L-WQRULfe-VSVS%XuLGST
za;lI%B?A_b3&30Uv<&DHk at 9@~N@?L2-uZE$D_^HW2NsbxMWkF+XMq{-a=nPWmaG3>
zfXjhq%<F6gDhlmr-QYdos))pZDd36M?4rFEsbYaoU?xc|#_vu6XYKDoV9(pr2H>)q
zyx<QY?KG_-<J<cJt^-a3(%jtqm55yL=;-*wj?t6{RwCN8i%6rYZUBFI*UpJZyii~P
zDlyg!N(<1GNF<I`S66?%xVZQwP(3|8{h94knFF at gTJkqw!@K;hJx&8jr at qYIGcWK-
z;BBBCW6hw{jE|33wY9Z<v%bFmG4KqSPo+}91c|hUb%SmZsZrG};Fi~<Rzyy#Y7%(t
zU2BaR)AhY7pben6x3_(4Y^=j=I5RWz#rF1gJFo&gx7EAmrk>AU5s at 3Jnh=o%vaR<9
zFbB+Ij1{O^L}IGy`gay^13*(#)3v3grOydlUx7tn-Kk3wArU$0z=D~a=Ye~+xWM(+
zU!MY7WTMV7jNdP~W4ln50EtB6Qy_&2>~5I at RxPAkLQ>UdgkSMHB2uBMYrvZOd_ar!
z^98R at y+5{V;h4Qy3V2A4*Il6QU at TPSfYn;4d5qNqH3G93gSZM!=BOyKh<P<H3oMbc
z5B`r=U1N_+UVZRToB4pF0=^%5_M at lXd96L}2DT^QNWa{pR=o4T!dqVbzJOE3a~+-z
z+QPNoc`&K`gekDBZ&BakB?I0KY)`<u&irB|B4xlCuR8GQ2CqJt=svLT>setf4bafg
zutIoo$W?aJCCn}&kdm=*o7Xl7b2VOlC}O$5n*aj?1CQhJ_~w3qMWhasK)ISx)lIu>
zyNiYb3pNGyGqmN<*v_}LN_&&;<>lr0)YR0 at g>*WteSLj(larH;{s5{vY=7Q&fCcyf
zliY(@if^cDT12|Y&cv2f^=A>O2fCg56mZ>7e#HA2SPfhSF5s<#$z)P{dU`5GM at M(8
z5R1jq+uPgU`oJFa84J4>0R?bVRsXeHes`xar>YZP+tAYd0{98|4*1?FKgQ$n)sc~r
zm;L?ykFf60+1VMqvQX@{$;|J-FBY}}==7Q`Ti9|kZzIsWKV}qgpl6t5Bq;ZQAAp6S
zp`qCD at bGMFYwPOZ;9!t-MK0%Rv}8AxU1V~GKzHr&9NC+IB;m{r2)jf+od7<>Y(&9?
zsR`f_Il`fJk1K$?g at 2%`cSPhk at DbU@n^M(3qsA(B*Zdq918!ridLQ^Z7cA_!$89p%
z+Y{ifeUQr@#|H3Vx3P+~@V;aLF9Or5ni7!?vbRM5x9mrjNag*W at PEo$dI~^9&Ju=Q
z&IJpl{kG=siZ_6p`8t&ncmlJ#0TUK~wVwiV>QH?+bn{HOd#I|BVJy_==x?tB))DYQ
c>y-ok4>Sg>YArqq6951J07*qoM6N<$f|tm7c>n+a

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/document-open.png b/src/qtui/QtUi/44/document-open.png
new file mode 100644
index 0000000000000000000000000000000000000000..dd3928c058260058227a1a2b657d7d735e4bacea
GIT binary patch
literal 1038
zcmV+p1o8WcP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11B*#SK~z|U?U~JM6iFC|pH2;C6T^;}9U{Svta_1z-a{Y<VJ^YN
zgPs&*=?p=^gEtTMzo8eeg3yq_UOWUm?Lt6rLe}-Lc$p{?6F<jECSyLF>1hwutu>vR
z>5oY^#?1o-(=}CZ{pzi^s;RdP&-2(zWMZ`Giuk{=9YW&LO7H<72lNmvxCT^#_rQ)X
zm!S!X1HduBNNB4HyrDDEk*lTia1JoW#>P(1&COkJG#ba+84yCu=kxiSv$L~*1AQrl
z2Go%guL5hj209O)1iFL}e?*B5$Ye54Yqi>yPLygW1Mk9>VZmKU!5D_|06EKggy9Tu
zka!!oErwyd%4V~(<#PG9U$qE)3=3>U1=v6eZdW#dRb>2iR6NfcSYBTKJ(tT}^)(y{
ziwb+C0l0whJnvSU$?O!t#(kmaX(BARo8+g%cGBk;7kCNu0zV*E5onI#Zs2IKSnM7j
zAHTS?v~=Ee-Jkzs!2k#$UJeWl+ at G15xi>mGx{egT5f*#|_;F}x=+eT%!nNHH8fI{C
z at Xq4m;xw>=43#FqCjgPjWbV4Idl(r{pLRv5e0lW=A<Ff7{W3B{=HY7$cL4&xb=@rR
zb{9md)PXhEb^HBifz;U0ot-Pl8GQ>Zhbwe~KWgfBi!CoLo#3c9o0h4msXr~tT2Inv
zdV0ENVq)UABz=NSr at oSJCNU7;dEWgr{S3o67h(5?|FcMo7*6G3;0aIyo)f(X1n>*c
z51dUhh)!_Y4Ode7$GwG=l8(2X9!^W5 at wU^$Y5D(oc+Uym4~Yo&J-pNGdw8e$zC9e|
zC4$@lBO at baqH__tl9rY>eJxG;)I`cAfNk5AZ$+ at L1(a*PD)<9Hp-@<L9Ot!Znib at 7
z#VrBB{i|IOO8YIgOw+75j`O-uD6INz-Up4txwW5wVc=AhTMWZ!N+WrmcQ2|>3p*D=
zcGP>^KYr1A801XmfXB$oXl(NN{I7|Ww(nB`9s-Y0#DYHEsuG at 1a8uag8Q@H8rOo`M
zJ}4_yL~{{{^Zi0CwZMpJn&E_ViR3i(QEYxW6~d&+>23l&wr#IZPEPhJ^^a57YQnbd
z;MTp_s!f!Kb$kG at EUW4`PD$hG#F(bJ<~UBtvaG5)hK{HhZbj_VBq2|Me^HLHFlhyY
z%;OFN$AN5GBR(s at Go;vRyM~<zR!I|DDzQIKcKjhF>42T`88S(UPN?p;EdT%j07*qo
IM6N<$f~g(dPXGV_

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/edit-find.png b/src/qtui/QtUi/44/edit-find.png
new file mode 100644
index 0000000000000000000000000000000000000000..4bb3155406b0e89202323165080180278686363a
GIT binary patch
literal 2105
zcmV-92*&q`P)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H12ewH>K~z|U?U`*%RM{EFe|KhpnSo(=XRL_qvf>saXj`j9jG9tS
z#Ku64QGzR^YGbmPZemE<#1BoHG-{jJM2$&(!$q?(t{?0NV))Q%>#pwB?kXD)M8*K(
z;N at j;aF_vRPCuM8?&!_{S6$gAeUh6@&dYQD_kW+a^Nc2h;D1R>vkkzgSYC2p0+0mQ
zl at 7BS4+4{b4;TdkuL|%*(F~eIB9MUuJQE231He;*xMIpo0b2kUl2PjG>*rj$bZME#
z<N0AA5Lgfl26F+-W^;E!Lc%?l%hgs{S^4?Fg9jg}{XW2hWdAz{Yz2M*Sh~BrEk#8|
z?~ja({E~0XAeIE3PUpvW?%X+&o0~hS!1e+DS3)d=nCh_#Ar=TB3d+mND>Y5~0(gvM
zs|Roc_kcF_+*4ycYRzL!)4nJ#FRv6r6ewK@)0{cwGZn)YAQ!M?Wo6asy1oM$ReVUB
zobJ<TNSn6<q0G$8vyUG?K83XF?iuWl2`ZMj0L!XXt5)c`{vI*{3;`1W85tRmHf-2%
zd*#ZN!)w;8c^VfNr!_Y>+pk~0p4QaVv`E+W9AHGfpi|fN?JHKSXuome#&sYQ`K1g?
zEQS+-x#!QHPpPi1{;Lqe4m<&brfH#yii&Fu4Gs5`l9Hls4g><!*4Dm#;lhR0!C=sg
zWII{YwDF at ykN#@Uo;^drLtY|!!~#4YNJvgj-skmt%K#lf(=>7J+_{gpZQJHmhjjq`
z$j}u8vVd&hUBG_v;>Dz`Tens!&;XfMtM${dv9aGHneR0UIGSN62q6mg?c28o=mI_i
zJ^?=2xN+m3g%G=i5I<868Ou5BLWs3Oh+Q=`HGd56SGwGX4jn2{4rqEEPL~E`<mcyC
zc6D`aQB0DWnmXWiyRSH%&i?>+m_9ru081t&CYI*s=dbSR>B&*!j=a3QkKAteCEyX@
zH9~N-TEY&X>v}%YZi7H@?b@|%PN(xe at L&dDK}LhlxVX5kii(Q%upZ#+{{H^OYE7aM
zu(1GJ00MzPO2i?-qN1WcWH|B}(Ek*8ux#0~{zzSZzki;Zk2eZ9T39m!Xqx6w2LMn~
zQt|*9JB<`H0f4fyvTjY&CWR218V?x-8kSgb*laeNM~V1kZnyi1`e~#j)c|x|A40yo
z24FIo2GqP^;L#4B1VSk(DfgAa5D+?i`0zqCKhsJLWF5lp-Mimb&K&|miHV6{t9irO
zE*4-hfByVFBJ8fOudh(eI}GSg0_f=IC{}udK+xrKg%ieWVb}*yTwMH|qj<gEMU9P(
zNk}u931}OTa_iQugyG at gqDWn3Wo7r&no*;Gqs8HPAg`sRC4cGCrSAoU!8kRZYPDJ)
zj*X4|0m)21v16zmRf{+rj^B)qjxJW~iI0!>4h#%jayT5V$i!sGETS<y4)_- at UOc*M
z*RD^Ah at XDHzj)rfc@=8k9AGYxjI`@`B=asH2e1?t7XEy6bhH#04C|??s%m#Q9K-5m
zUyBWctPO^b962(QnVETC9Tot3dwYAUZ8qEQjvqgsf;0~ovi8VRFOl5T)RgFOI6i1=
zYx^~_F7|~1*VWYxA!`#u87?eS)x&dv;+B?{>?KQ<l!ii~_=xdzP1AgdiHSF}v$MNO
zN=iCxHrwRYt5*v=9#6j4>s=;<a4JylNTsJvow`_CTid2y!Ve4+5$|6Guo-v<Sb6N&
zG5g-Vdy6CNIR*9EW9$tfuR{YbPGn?cbm_YOQN&OX$@r5O*BS*3(l(2LAGNl&vT4(%
zw>mpJGu500NJToB9hnq->KP$+MtoP(v~i2YqNk^)x8A&Y^Mbnb=}5Mxl<Bfo0QeI4
zvaql))ZX6iuB)qSwb^WbHRnNk`d2^;a35KL`LeRIhWGE^-!e2b^jUXz_vZ%=9Jp;Z
zo5z76Aw=@T#6-Tw<N3wHg$sY%+1Y79-a=BR18k%(kqeXp$rBS3T)TG7bougS>y;~4
z(gJ~i#o=%SQc_YTv$C=#wrttr-Mo2o&}4d^j|B at B%<JszOhZN#E8qmOtyXJmdwctV
znJ{g%kzxaW3=}YZrR4?MfxAfd-deYA-A|gEn{!`Smj>ipt=6x4dwc(so}M1I>8PNM
z_SVLLe*tHJzah<~Umehgtd;KqO~85J-^gq>0`#t5zy7)G$u|yn&+qpy%E`(3U~q8I
z%oOHfl;M{ZGcryW?cBLD at 8rpo^P;TD0N%0N?YBK1&tDu4M~Em)zp3tJ5P7X1IC0{{
zSWQh$H{WKuAL#J;d_^vo>wT}+Ya$BMZ?fI$McxH_PM<#Quc at hd7zMNkX!rSi#dGG&
z*%JZU7FP16Od?X8z$zeT$BrEdXV0F^in1mfC`e07`^VtmU?UMNf!Szij{yG!dK(%V
z{M)y0kLHMdz+F|A0)#W{taaeSp!?38IWt~WRTXZ;L_QBoOH1z{9rjt9b~gVq7y+)C
zOs0n)e)!>db#?W#5)=s9Y&L&mV`C4pE_qhj&GvsBVbFaI4Goj^_4Na3X=(oD%a;$e
zwYBNFxw+x)efSPID^3?pl7ZF8(lsnW;P1#}^voo_FMvUYuAd?kj2GF5`&P5?`viDK
jGTSz6SpE<AyO#d~ug=8CPTfJX00000NkvXXu0mjf-#qZr

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/list-add.png b/src/qtui/QtUi/44/list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b2ee79ee8881a605c88551aac59dffaeee017f8
GIT binary patch
literal 696
zcmV;p0!RIcP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H10yRlQK~z|U?U})fQ!x~Vzr=f6u%a-GL*10pr8}W(- at s=mKADT+
z6S(&gTq~u at z`)GN9j+C%T6+^0Hv_Y1axy0ESm_6s7Vhc!|DL2LNw2cjvQOx{HgH=G
zhPTb$87?yAQSJ(1atP%x{0MlAJX$ND0=}h)rA`SAoJ8j7xL9c<f}~cs3#jRI`fxIt
zybc8#V_rDD4)E)51yc<xfaP*|&suwwm at A4bKe~RuzXIwUxg at d}?smHd_>m)*M6R|5
zu+EsvOHRX0##~<hy9z7XHsqrOD2l=oU*S+bXcrjoo;PIp0d1p?9fjBmKZ(fm8PAFs
zGIK24-z1cS!fD^iu*MCY*7}vT_E->UfYVTbQtFM61Eo}DjCtv_H5)ceF%^v2Cn)k%
zSkw{?YpvfmP16^`EVAK`5n2~gOiYEpyDOEL9Ab=USSi)8qaN$Dg2Ys~VMnW2j83fK
zom7}ihS%)Qu&CoRY}|*7*=+W~7!&NVbzQ6Rc>F9BGoR1jNoKUxKi%6ko<nP>!dJk_
za5$87SS%J|TN{l=VjhQe+8YTOUeGR&OZ*MJ0~}RVRRT{1Bi9wa0)Bg93~)|hE=zN`
z0nP&V?*qE7>rP0- at x{HKafgRc0LrqAS?RKHIB{&7Lxs0Zs$mPz>-FqlF!-9mkBCZq
z#-V``Z9jf4#J;5+g--+ynK6PX7~m5BLU5B6?cp-1La7zLiS*_FnLo6z$zn)i at 1AiS
e3~!sgGyDhfO_n!%eYH>k0000<MNUMnLSTXv!7+CL

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-playback-pause.png b/src/qtui/QtUi/44/media-playback-pause.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b2cc00f7a736b9de2b7f3e1282af22466b52b10
GIT binary patch
literal 402
zcmeAS at N?(olHy`uVBq!ia0vp^Iv~u!1|;QLq8Nb`OR<w at 2nP_<aHMnq`J4qFk;M!Q
z((6H(F-~ft3{X(A#5JNMI6tkVJh3R1p}f3YFEcN at I61K(RWH9NefB#WDFy~ceoq(2
zkcif|GY$O?I|wj5pTKM);&Q6EqIRE?wD~fFLmM<}6c;AsU*8p+Qt96HCh3WEY>xPA
z6{R(u?bYlRoe!?L6l8~q-?99A{LkedOm?4t3UAQ<p==PzY;%zP!POUhKYt_ at u)b)V
z{PfVZ=tYO+xQkb)iYYKw_smYe`|$bw)yqq+xCmDM4o?0Y9QSy!$fLdOjCE4KwY;0|
zOM}R>{$HHpRhzVbXwByMm-l9MPExz_4QH0{520p)GV4wG1!E3|cRt|S=e0*w>xUMI
zw~?*?jPNWKrM>Bli}fpem9CvUf5gUbQ(e5oj=t4iF>ayD>Xj__7na=dY5ceFrNIU1
in({Dn`97#WYS at BT#^-)}DCrLjKL$@%KbLh*2~7a=(w+DK

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-playback-start.png b/src/qtui/QtUi/44/media-playback-start.png
new file mode 100644
index 0000000000000000000000000000000000000000..790ea71f2e51260b063f694cce19445d8c8f23b5
GIT binary patch
literal 1091
zcmV-J1ibr+P)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11Hef{K~z|U?U`RlTUQ*%KPP|ZO>K%ZX0=4KZWQN(I1uqUAo!{v
zz6n0;B~R`xAk4vV$Uq<F#w0AnK_3QVI2r6wANpcOmyIz7WwQxwMN5rVi=9 at lXAi$*
z>sq(m+}xP1_=N-Eo_o&y+~4_~-|u%%l-8R6lU(%%s8r{`wbn}y?6EP%QF$u3_Yx2)
z{@w$&0Ml`zGEx at 9ngXr@?x(Ju00rP7aAvX5>hgLh!g{^l<ml+=o5isqpbao;gLjIw
z)>fKVYkf^?eGPa3Yy<*<)Y8(@+okJT>&seekHz_HH>)n;1zrbGN_`7l06a>m-S+nO
z&vUulH>LMS++>Fuxrv<}{}{3Ip4R$8KA(Tr<ME`1hKAlke7zZn0s-eR|CSx#W8etc
zY at 5KoX_{9T7Z*PX1OgMORO%A4B3Fvd>liK8qr}rL at x>|qekAO9l~Vhyt*zJB*4DoA
z`~4bmjU8Yci7Zvgu7#g%`@lL-&|3S~*Vo?(1Olm8EY^*<NfY8GjV}stsqFxFfj!eS
zudJ-BOdE#r{_N~*GZGpv0}*6JY{`yGd}?uSKe7S+N~wczIQ(@cllii(t?jtj{}9QR
z6}gEW;EyYL0B{j_6>z)V?)yDGJ)f<vu6|$aGZE-rtCKnH5~sCoU=1jkrrDgyWZr9N
zX!szJNW6w*&oGiLU$OFVI~M-P@~b^BKLThdrJgi3HGQ|dynMZ at tLsUze-kOJ90mTc
z3gD71BH&)7RH3`Odm)?6-az7e?!N|BQeKvHT>h4_+D0~AC>RX7hlhuwzzr({>jjL@
z=R1nW<2R?KruGcuuVSxIZd_e}W3gC%VPRo25{ZD+Ccgl8fP->l?Eu^U%7{cF+sR}y
zH!v`8Qk>^DkVO)XC7p?d4Z}E0BoenLCMN!Hxm*gk5Bvb!qr${dYhXP%ICyt{etx&5
zr3Iws_!+nb9NKtx?SMNvI(E|O^k!dQA4s_R9r%$lakiWs2X1U^Je;1Mz88<jOTNAV
z+(eQ>)#asQz%G|dkByCO%*@Oj1cN~ZJOX|KenTwmh#ZL$y}i9V>2!Lxv$NBMz}-S%
z_p9W4PE}br6bc>A&CP9%jEtz_r8~&-KcGe*p|*g1KHtgs`1sc3<fJwXLm_cAi_`&*
zWWs+_#lZdj{e@&Qc@&LCT}Wv970FbOorXJ2l^j*Qfz;12WVh!Ls}?xJqbjQw)<{?i
zBmS91{Pl%B4E)C!&d{RI%FZWJUH`>-=}+M6u5;j8>m0b&`V)Puv}jM$6chje002ov
JPDHLkV1m2h1hN1C

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-playback-stop.png b/src/qtui/QtUi/44/media-playback-stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..d16291b851be1af4b20cf28083d011a45b134cb4
GIT binary patch
literal 350
zcmeAS at N?(olHy`uVBq!ia0vp^Iv~u!1|;QLq8Nb`OR<w at 2nP_<aHMnq`J4qFk;M!Q
z((6H(F-~ft3{X(A#5JNMI6tkVJh3R1p}f3YFEcN at I61K(RWH9NefB#WDWIa;o-U3d
z5v^};?&WJT5NUh3eTC1uS63^(-s_s&yqGz#kJ;ju{FB2|=9njD&r<ij{7~Rb&#bI}
zyc%Z at zLHt9&gz3%ajb-WYVEm2G9TnD7-!G7cxm;3%_gb4Xx$M;Td at VKeJfp83g<P*
zI&eHRVt$pKR+i>q?y}DPovhlnlar=4tT%FXRDH1ACvZaZ)wNQ8CTVg-edV;S at Zt;G
zp0&X~JGf|r75nPX;ZAd#uP!}cd)Q@}>E_=|^ZJfhD5ifZmNpOiE*a{|&HCTs%H(r5
q+ZtV^SFO&ody`Pg7Zxu2gSWobgeiKz&v&3V89ZJ6T-G at yGywo>E`+xL

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-playlist-repeat.png b/src/qtui/QtUi/44/media-playlist-repeat.png
new file mode 100644
index 0000000000000000000000000000000000000000..558e68d15bf5c8b6a11c226a5d1b28053e3c6e22
GIT binary patch
literal 1339
zcmV-B1;qM^P)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H11h`2=K~z|U?U`RlTUQ*%KljEo&C-amcD8k6YgblVd=Q;l8fYIj
z0--(@K`3lKmf=btH89e>6b4e*`aTAG7=0CyO&B&bWtJ=v2J0BMbx!B(GLq_ct;xMP
zdpI}l=6VwoYa9i?a3MMOch2u~e&=`oC5jM&mr3gX4N$B0f$Ob(;Ckz&18%6%zFr+H
zRBN~$unPzPUcf_rfj5A4AOjfX43!EShYx6__EC6I>A(u`kJHO?z&@Z2ps%m*Tr!z_
z-!P1mLWstC5GsnY>T<arcXf4rIWsf!y;;2E1nmUu0^R@`0)fDAHk%z_?<QxVsj2Bs
zCX at Lb8R=iKrH9jS2Y`lPFxZ>TW-kLdKm+pBFga?J3b=t+vf1qAU@$lnkH;UFENQEu
zQ-og!yl%JqGhNqD0c&-FEGK_ML&ID?pZ^Fs34gP`bc(PCz%Yzf<ctNt<#Org&!10>
zjEp=Ahr`czgKTng^5D&zH{ZH{|Nc9MVH8<1rteJ_tLzb0fl~mAqTE6D5P%C8E<Ct<
z_wK{p0JZDl#fxWRu~@IA$SZ^xFh9>>NySP_mWCzaBaz4)unhbF{Ju-9Z9rEf5^=|3
zu`Zi$M^yseuzm at JLJPn{B<yZYz9qmL3WY$f3PtJ8=9Pi%l@@o-wXGH%{5h%;uzh>1
z=W4O$;LlODM7Z91;Rx>o0}68YI%Ix-TC2ak1oi>1BDdh8+G_Pz=}@EFo}J1K97n>r
zhlht>^LRX;nD1P*`l}lF(xpph%yOSuulSUc0yG0}0*4Zb#DSKUmJe><zWr$~mut5g
znr&AFT=lXxJv|*pZXCyKb~$7&T6d?C;qUJ54yID6D?*5XX+Q7Kc2&!oJwgTZp}Dzv
z6-$pbO*`%L`L6f(_qW^X95CU)HvHGFU2F4rJRc{M$q&uL{}S*c at E1UTe}B8r=ew?H
z+G(pV({~9^QBD!w0K6R?9qCvscHC0_RMWKXiHV7BMNu{jg%DRvXg_ciP!fs6fp9oH
zkWQ!HGks)`hw;trUQv{<ENwr*k_H_e9mO+n$?>2Z at H*g)L?X-g?%g|5C=`lxE68DM
zMGm=LM**d$r{`QMl^Qe*BVan5!*WcusDQiztsoES0zg$&5s5^WEi5H+nlu?e4~0U{
zMn^{<sj8Ys_CAk1t<3^)%TuDk!NC)ajg10W0FuC;Y at JZLS$EcKGY{yhs^&*WM<0bk
zp=YMemX21sgq{Vu;_*1qXw*MDJL^xU(+BN_tE;PD`2GF@@CP#b?`oPxG#Yi^x^?TA
zuIny)9lKguTAp`ycCJOE(Y0VOh}qGfsPYnOh3*C3MlMn1^c^xnPmq)DEYJyf=jZ3e
z(9qDK>FMdi_DVvC1&6i- at C)$333fYRkPG_>pdC1j{6WR8Z;-?Ox24RF?CeRvH9kHr
zu3o*`ytK5mSzicYy#%ZySB{^N9pBLpDNb_A`ErMO1-ZQS0Y^4AHpGn^H`KAQvBSAs
zP8C9YZQ4CSj!;#q6?i8qNt4CJMPq1a$TKxH^{x57<j%I8_5!%5k~Bf)z79ODrIEb^
xhX2x}2S~AXOW(eM{eO|_tbO2mYah7Y`WI4t&Qp4(1E2r^002ovPDHLkV1n<WZr}g_

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-playlist-shuffle.png b/src/qtui/QtUi/44/media-playlist-shuffle.png
new file mode 100644
index 0000000000000000000000000000000000000000..39e8c02914241e9038b5d7e51a9d3db7bb303243
GIT binary patch
literal 1806
zcmV+p2l4ocP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H128&5VK~z|U?U-*&RM{EEe`hW;1LMrF%%CiYs4TJ at jZBPaXju})
zV%9cIwAS#2WCLlsZMUR~iI}*?#MSfz at q_7Nm$o4^X~afj+-M^1mbEeIC at vC6kYHNb
zZNOy(2b4cD16)o&oIC9>-WkVkfNa8(oMh(SIq!My`|o+ at 3MnPuC0Lf4z^h`J at Iqsm
z at IoVL3C?r^s{jc+14fO{2|+ADTU!rUBfif7L%?Jrn- at DJEEr_1R_h-tD=Tx2 at 2i0<
z=0Auzq?C)bEK*9VlrmpRnGcKrk6kX;A8y^cRbX7-Af at z3DMc(h3zZTY-~f`1WhW|{
zLWoa|-)KUJKz at GyN4>qhEynGbX=0WVmKZBhxPWy)CXfcC#MnOxJORd~l&KFMJovzB
zwSHVxRTa*0(=>_nume at Swira_fN3CPtZ_h(xUT^js4l?HojbR5c6Po!F){I$uIuZi
zl+Gx7kE8awP?4B*yWLl>UAy-Cl9G}js)KxOJm5US>*A0#gAN3Mr^bP60Ndrumz@<A
z6^Ey$rgi`#&i=1Wt|bF*AV~-j*tl`y$KBoCpP?M}75uLcTf$_85TBb_7eb6_nl_M<
zlJe!YZQK6V+S=NMibyKT3%2s|@;5JDy!cxw<!h)Y1dYR{Q4x9>CQzPqIh{_qfB*iq
zFYqutYyt8NVxJ{oSf-?;_)ncW^-)bt%@csSy1JFMwYBvI*{7(Kd1YvtHd9ei;Xilo
z+<?R30BFS|B_ato#Il8oh!rE>JRZ;GKp at a?`}S>nNlD4?bY0Iv<>o9vUS3|`i4!O8
zmzI_Wv$C at 0c~}Th9(_PTK|#;?^XGduZQ7&*Q$Q!sgX$W9xirt1T#LRwYPDL2ySuyp
z1W;O9dek605GK2C- at Y#{UAok7vBYdJ|F!4wcmj2Gb?sGERg<XN=mYLz5~VQVa0jqS
zDSvHd{lbL{E1H{|Gj80t at q<t(ly~IFk^0QcOnt+K4L=M9gM~mpDrecedGkYq>{FDN
z{*B6M4JFM0Kh`vDwz9Ia{p{JZ!$$arfi~a~vF3{i6>&%@*M*fR)(QrLZyr8;_-!d=
z{=tI>cL*W6fWHHu0H1ih-aiix4*pU~`6DUiN)xrqmr~|$-MaNmcX#*uQp#UQDc_Y+
z`V1wEtC(g=7b}KIsFvda2m}IJMn=XNUDwkLk6^W0XKvoS`H$k_;vwL+;q_>|VR*U}
z75<077bIAu|Mz&Ao16QduIsNG2kHPPPo8WqE-oGi?xRv59-aXI1jb0L<pJ}(=|G7`
zUW~O4 at PtAkv1-+-cgM!YcA}bj5SZD$dw1{AqesV{KY!jcI5;>5yoQqI=<_rHyWRfN
z>gsAQuQ;tGtaPVOpH9DW<;okKot^t;XJ^-=dgBnl>eZ{C_V)JnI-Sl39*^gpP$-l(
zIXQX8*cw0$>T^UCoe<)$z^vEn{j{Z}rMa-Ma2i!;0pbkxW_`H%B at ZcqZw$gX9FCCR
z at 4xT!`MxPCDsr~9wfzPVsi~=-_xJZVx?C>Pa0?+mM9H~b2r;^4%a*^~yLZoT+<v8L
zO^>mHs2R2g)uv|LZufXgOG}T>=bNmns|(z{d-rFkLVNh^*|QxUkLSaZl9Iyu`ugb9
z0F}dCK);mI)zQ)ME4$tP!J$Kk!l at B=T8s4X`(_ at Af;@2Gz at vtShOxA?v{|5|si|pg
zb#-;c#KgoS<2RW=P8=I;5ucNRwWz$GO;1m6y?*`r#fUVCE6qPQv+nhJrwR%R#*2!I
zf_wMwo!-8EJ1DUUD^gxpS65zHSy}e*@NkN;%?)G&D|oS>{JaPcs+N*9O&cvNEWB{%
z&Yd<)rnN|=`&S&VgdtHfd<Rt|Nx%x9&zIBJ*EdjIU7g(2)bu(kg+>yv7se1ORkGb~
zx4XQ&d_D6cVLHIS6T{e)LGB4EL<7w4pBhROz7HgKbac#Jy?Qmt at Auo=+uNNZBO?jT
z+BTa_uc at gSI)424T)b&560wvn(dM28d=J$DVh->^h>YlKyLRmwZES1|=H%p9h%v1#
z<e$(?RHd&3(ouyKN!Szqyk^asP(wq**q%LmG+r{TE#`}qu*!vn<0m$oZSL5yW23dT
zwHCYGE=XWnTg+Eg^HQp;tZclov2i*(J6j`0_|32suc~rUj#}Jl?OR|F^*Z1&ifHU%
w-2_YF;ctcS-235W!V8UM!V8UM!V8W60Ge1syrm5y!vFvP07*qoM6N<$g3Xz4{Qv*}

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-skip-backward.png b/src/qtui/QtUi/44/media-skip-backward.png
new file mode 100644
index 0000000000000000000000000000000000000000..f79995027abb9d989cea544324a57762a3da2e27
GIT binary patch
literal 996
zcmV<A0~`E_P)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H117S%-K~z|U?U>6;R8btqKXXSLof5HV0vpq2(ZXfc$`&GuJ4vEd
zf=s%p1lMkSfcQTMlL)R#2!bBs!i_@&VGl?&l^MZi(w;VvHRFt@#l0ir^*+wr97>ok
z{1)>&_jAwpckb^#&bWjS93?6L+CaW48ZNYoh6}Bt;X>=k87?u&yR^vFZh^f>$;j{t
z;0)l_<x{{%U|Zt63UCsrL at jjlusD~&tNA=oYI4F9ux2r#OPlNz`wLD3k;CBhJ*;HS
zx?HYjxuK08Ghnhh4%7lZz}?Z&QD0hGdRH4OIW$fPksFE-;(`$30_x at 8i)>yyCYSLD
zA^h3#k&%%r<>lq~fDH%SeLK$VrUQ6yF_x|V6zZj9Zf>ruy}doSwY7B>C_`<ZA9mdQ
z{Jf{7rRAmsw+EYP$0V-+Raz(jfk2>rZEdYf2vLQ4vwQ)59ug;QIAxNrMY}PYnwlEI
z;qa|YCQ}Ot;2V&@_z~!olQwL&!tUPQ-kMM-bUT?$Uet04ZPK*G`P_YdeP_qU#_lAO
z$%Z^QX~PFrcxq~@qNk at Pm`EgAH1;R(8Tf5AiBm3L!~0g)@AqGi$K%(85XZH#4J>XB
z6D}>wIWfF%g=4YU4b&d{0DML5JzF{D%#=?{d_sLDOZVGfa)z?{THDEu(b3U|6%`d<
z^m)5*$~iHd%8ma1{_XYk_1E3q-EZA)_b>gpSvcjK7}i((uClT+6$*tCtE;OoTU%Qr
zHY;?1TV7s%)z;P~%jIoYUvUh04n*qe>cq^<%-3)@{HDIXe#2yi4sd}$V0U_YT9(V(
zuu;WnU>0}+Y&14DvaqnQIXOAGR9#*D-GDLTKIFmWW!S9ZUDOYwN1BQ6ot>RxWo0Ek
zG&B_PdcE5=+~Zs>5{blyhlisUoU~!PiqpU{@Bnz>^?H8|4i4@{qtRF}7>p~5l9b^*
z9?$QAfq_gk8jW>zb;T?=Tf<U41tfua&A^h+=gW+bkEa(G7vs&%&7UQ?MW4@?nV6W!
z*l|W%q&n1{MYAqHi`*9JG;j&1(SFY&w?#S)Tn7ABoY9-^BkFcVuk0q&N<uqk8aM|u
zpkCfhN$#l~XSBju>D%SM-R5WYUl`Qu$o=zEG+byE4HsHP!-ZDSaG`bN4F3UHd|X=~
S7^GML0000<MNUMnLSTXqLDS9v

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/44/media-skip-forward.png b/src/qtui/QtUi/44/media-skip-forward.png
new file mode 100644
index 0000000000000000000000000000000000000000..76c7a2339800ddc4163273448e33eadaa340eec2
GIT binary patch
literal 940
zcmV;d15^BoP)<h;3K|Lk000e1NJLTq001li001lq1^@s69)wx}00004b3#c}2nYxW
zd<bNS00009a7bBm000}W000}W0bUxB8~^|S8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ at H111U*FK~z|U?U=n!Q&AX)pVNX+qydeTqy{AwJCGO#Lt=shkg#eP
z+#oP9p^HPqPN0w&Clb==s!`(LKVZUQ{2<0baWNLDSP&~n<fDAO4(AqYxovMtZ<OTz
zk~dAy?Q_oWyyxqlDiPs0$@Q-d6e`EC-Es`uEyu9katzz8GLy1OpdJul6<D)a*9pLf
zPC}tv9pK3*-vpL{?es!rax^z&z)9enQ9&-9LwB}N?ksRJ%d>T0A-%wCN>l)pmzUq~
z?(S|jzBd4VbT+c-M3I~aKq>V+J<^~3B at xMtCJ_muv$N>&cpeQ84__6Lpom-)kvb7^
zTi_lS!5xIbHD&%jm*MxoJP-$>wY9Z(XJ%$D85La+ky9d~O31xQk8Fl>?GnF?MiYR0
zb#?VdYisL+Kp=1paHAK>d7#<?_b?C$T+hSpWQ3`58QwNx1&9GFBI1okqc_XS%I>wd
zw_irjO+R|BsvKN(G#VYW$fcrS!|A<EqPLiNU~O-2uVH$6dZe<la&&NTFtw|w5^_h%
zaC&T at x0%ntdNP at 8nV6WEsHv&BH8nNmEiq>*vwgS;a4Dtk<mgOFUf>K+u9RB$`~6QA
z78b6Qf)kP3z&`NNs^L)!4TB!i(}n>T at Szl(hzyw-HanVA$~r72ilgVM&u-4 at qRSgz
zuQxF=GV-*9T)~FT7SEw at yWN`u0|W13vDn+8p`ncua;C~PC9?K1rLL~7SR at ijG&VLW
zqmd}kQUv$O3YX7t)?PL at H~)x4B1>&;ZSZGdECPFWa8?Z;%CO(>-xwPki}&>Oq_&nX
zz)SSPX+lr2LtK4*{bo2Ej`#QX?-#-qYWSeXRaI5Hp-^Zk6bkKDR8%PRvHJ>`L%-;k
zlq=Toj?3lR at 9XPJgu~$-pU<a&E%e*eEP5ETa=pF1-^a(tcMIW;WVoZFBQZHSxfu)w
z-9{s`Mx$G~DlC at 6VusC5y3|#t6FqEmzzg7Kp1O+VQdgwTjPhrgT#?K&yof$|;=pU*
zYn}#=$}Jn8`x)iyY0nO1mf`<e$L at a#$FSXU4BIWou-$SD+bzei-TDoZ&uVJav4JrF
O0000<MNUMnLSTZ2mafbI

literal 0
HcmV?d00001

diff --git a/src/qtui/QtUi/AUTHORS b/src/qtui/QtUi/AUTHORS
new file mode 100644
index 000000000000..39aba5554ac5
--- /dev/null
+++ b/src/qtui/QtUi/AUTHORS
@@ -0,0 +1,3 @@
+Faience is designed and developed by Matthieu James <matthieu.james at gmail.com>.
+
+Faience icons are all licensed under the GPL.
diff --git a/src/qtui/QtUi/index.theme b/src/qtui/QtUi/index.theme
new file mode 100644
index 000000000000..01f09ef0a91e
--- /dev/null
+++ b/src/qtui/QtUi/index.theme
@@ -0,0 +1,17 @@
+[Icon Theme]
+Name=QtUi
+Comment=Theme for Audacious Qt Interface plugin, includes icons from Faience theme by Matthieu James
+Inherits=default
+Directories=16,22
+
+[16]
+Size=16
+
+[22]
+Size=22
+
+[32]
+Size=32
+
+[44]
+Size=44
diff --git a/src/qtui/dialog_windows.cc b/src/qtui/dialog_windows.cc
new file mode 100644
index 000000000000..b5575e57e34f
--- /dev/null
+++ b/src/qtui/dialog_windows.cc
@@ -0,0 +1,68 @@
+/*
+ * dialog_windows.cc
+ * Copyright 2014 John Lindgren and Michał Lipski
+ *
+ * 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 "dialog_windows.h"
+
+#include <QMessageBox>
+#include <libaudcore/i18n.h>
+
+void DialogWindows::create_progress ()
+{
+    if (! m_progress)
+    {
+        m_progress = new QMessageBox (m_parent);
+        m_progress->setIcon (QMessageBox::Information);
+        m_progress->setText (_("Working ..."));
+        m_progress->setStandardButtons (QMessageBox::NoButton);
+        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 ();
+}
+
+void DialogWindows::show_progress (const char * message)
+{
+    create_progress ();
+    m_progress->setInformativeText (message);
+    m_progress->show ();
+}
+
+void DialogWindows::show_progress_2 (const char * message)
+{
+    create_progress ();
+    m_progress->setText (message);
+    m_progress->show ();
+}
+
+void DialogWindows::hide_progress ()
+{
+    if (m_progress)
+        m_progress->hide ();
+}
diff --git a/src/qtui/dialog_windows.h b/src/qtui/dialog_windows.h
new file mode 100644
index 000000000000..d226bc833b50
--- /dev/null
+++ b/src/qtui/dialog_windows.h
@@ -0,0 +1,53 @@
+/*
+ * dialog_windows.h
+ * Copyright 2014 John Lindgren and Michał Lipski
+ *
+ * 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 DIALOG_WINDOWS_H
+#define DIALOG_WINDOWS_H
+
+#include <libaudcore/hook.h>
+
+class QMessageBox;
+class QWidget;
+
+class DialogWindows
+{
+public:
+    DialogWindows (QWidget * parent) :
+        m_parent (parent) {}
+
+private:
+    QWidget * m_parent;
+    QMessageBox * m_progress = nullptr;
+    QMessageBox * m_error = nullptr;
+
+    void create_progress ();
+    void show_error (const char * message);
+    void show_progress (const char * message);
+    void show_progress_2 (const char * message);
+    void hide_progress ();
+
+    const HookReceiver<DialogWindows, const char *>
+     show_hook1 {"ui show progress", this, & DialogWindows::show_progress},
+     show_hook2 {"ui show progress 2", this, & DialogWindows::show_progress_2},
+     show_hook3 {"ui show error", this, & DialogWindows::show_error};
+    const HookReceiver<DialogWindows>
+     hide_hook {"ui hide progress", this, & DialogWindows::hide_progress};
+};
+
+#endif // DIALOG_WINDOWS_H
diff --git a/src/qtui/filter_input.cc b/src/qtui/filter_input.cc
new file mode 100644
index 000000000000..e1977b554280
--- /dev/null
+++ b/src/qtui/filter_input.cc
@@ -0,0 +1,56 @@
+/*
+ * filter_input.cc
+ * Copyright 2014 Daniel (dmilith) Dettlaff
+ *
+ * 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 <libaudcore/i18n.h>
+
+#include "filter_input.h"
+
+#include <QKeyEvent>
+
+FilterInput::FilterInput (QWidget * parent) : QLineEdit (parent)
+{
+#ifdef Q_OS_MAC
+    setStyleSheet (
+        "QLineEdit {"
+        "   padding: 2px 4px;"
+        "   border: 1px solid silver;"
+        "   border-radius: 10px;"
+        "   margin-right: 5px;"
+        "}"
+        "QLineEdit:focus {"
+        "   border: 1px solid gray;"
+        "}"
+    );
+#endif
+
+    setAttribute (Qt::WA_MacShowFocusRect, false);
+    setClearButtonEnabled (true);
+    setPlaceholderText (_("Search"));
+}
+
+void FilterInput::keyPressEvent (QKeyEvent * e)
+{
+    if (e->key () == Qt::Key_Enter or e->key () == Qt::Key_Return)
+    {
+        e->ignore ();
+        focusNextChild ();
+    }
+    else
+        QLineEdit::keyPressEvent (e);
+}
diff --git a/src/qtui/filter_input.h b/src/qtui/filter_input.h
new file mode 100644
index 000000000000..41559a200407
--- /dev/null
+++ b/src/qtui/filter_input.h
@@ -0,0 +1,34 @@
+/*
+ * filter_input.h
+ * Copyright 2014 Daniel (dmilith) Dettlaff
+ *
+ * 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 FILTER_INPUT_WIDGET_H
+#define FILTER_INPUT_WIDGET_H
+
+#include <QLineEdit>
+
+class FilterInput : public QLineEdit
+{
+public:
+    FilterInput (QWidget * parent = nullptr);
+
+protected:
+    virtual void keyPressEvent (QKeyEvent * e); /* override default handler */
+};
+
+#endif
diff --git a/src/qtui/info_bar.cc b/src/qtui/info_bar.cc
new file mode 100644
index 000000000000..b62517fad7ca
--- /dev/null
+++ b/src/qtui/info_bar.cc
@@ -0,0 +1,211 @@
+/*
+ * info_bar.cc
+ * Copyright 2014 William Pitcock
+ *
+ * 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 <cmath>
+
+#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 <libaudqt/libaudqt.h>
+
+#include <QGraphicsItem>
+#include <QGraphicsPixmapItem>
+#include <QFont>
+
+VisItem::VisItem (QGraphicsItem * parent) :
+    QGraphicsItem (parent),
+    Visualizer (Freq)
+{
+    aud_visualizer_add (this);
+}
+
+VisItem::~VisItem ()
+{
+    aud_visualizer_remove (this);
+}
+
+QRectF VisItem::boundingRect () const
+{
+    return QRectF (0.0, 0.0, InfoBar::VisWidth, InfoBar::Height);
+}
+
+void VisItem::paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
+{
+    QColor c = Qt::blue;
+
+    painter->fillRect (boundingRect (), QColor (0, 0, 0, 0));
+    painter->setPen (QPen (c, 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin));
+
+    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);
+
+        painter->fillRect (x, InfoBar::IconSize, 6, t, c);
+    }
+}
+
+void VisItem::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,
+     15.5, 24.9, 39.82, 63.5, 101.09, 160.77, 255.5};
+
+    for (int i = 0; i < InfoBar::VisBands; i ++)
+    {
+        int a = ceilf (xscale[i]);
+        int b = floorf (xscale[i + 1]);
+        float n = 0;
+
+        if (b < a)
+            n += freq[b] * (xscale[i + 1] - xscale[i]);
+        else
+        {
+            if (a > 0)
+                n += freq[a - 1] * (a - xscale[i]);
+            for (; a < b; a ++)
+                n += freq[a];
+            if (b < 256)
+                n += freq[b] * (xscale[i + 1] - b);
+        }
+
+        /* 40 dB range */
+        int x = 40 + 20 * log10f (n);
+        x = aud::clamp (x, 0, 40);
+
+        m_bars[i] -= aud::max (0, InfoBar::VisFalloff - m_delay[i]);
+
+        if (m_delay[i])
+            m_delay[i] --;
+
+        if (x > m_bars[i])
+        {
+            m_bars[i] = x;
+            m_delay[i] = InfoBar::VisDelay;
+        }
+    }
+
+    update ();
+}
+
+void VisItem::clear ()
+{
+    memset (m_bars, 0, sizeof m_bars);
+    memset (m_delay, 0, sizeof m_delay);
+
+    update ();
+}
+
+void AlbumArtItem::update_cb ()
+{
+    setPixmap (audqt::art_request_current (InfoBar::IconSize, InfoBar::IconSize));
+}
+
+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
+{
+    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);
+}
+
+QSize InfoBar::minimumSizeHint () const
+{
+    return QSize (InfoBar::IconSize + (2 * InfoBar::Spacing), InfoBar::Height);
+}
+
+void InfoBar::resizeEvent (QResizeEvent * event)
+{
+    QGraphicsView::resizeEvent (event);
+
+    QRect rect = contentsRect ();
+    setSceneRect (rect);
+
+    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);
+
+    m_art->setPos (InfoBar::Spacing, InfoBar::Spacing);
+
+    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));
+
+#ifdef XXX_NOTYET
+    m_vis->setPos ((rect.width () - InfoBar::VisWidth) - (InfoBar::Spacing * 2), 0);
+#endif
+}
+
+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));
+}
diff --git a/src/qtui/info_bar.h b/src/qtui/info_bar.h
new file mode 100644
index 000000000000..f8cabbc23951
--- /dev/null
+++ b/src/qtui/info_bar.h
@@ -0,0 +1,96 @@
+/*
+ * info_bar.h
+ * Copyright 2014 William Pitcock
+ *
+ * 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 <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];
+};
+
+class AlbumArtItem : public QGraphicsPixmapItem {
+private:
+    void update_cb ();
+
+    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 InfoBar : public QGraphicsView {
+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 *);
+
+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 ();
+
+    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};
+};
+
+#endif
diff --git a/src/qtui/main_window.cc b/src/qtui/main_window.cc
new file mode 100644
index 000000000000..f0ccfc7612d1
--- /dev/null
+++ b/src/qtui/main_window.cc
@@ -0,0 +1,317 @@
+/*
+ * main_window.cc
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 "main_window.h"
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+
+#include <libaudqt/libaudqt.h>
+#include <libaudqt/volumebutton.h>
+
+#include "filter_input.h"
+#include "playlist.h"
+#include "time_slider.h"
+#include "status_bar.h"
+#include "playlist_tabs.h"
+#include "tool_bar.h"
+
+#include <QApplication>
+#include <QDockWidget>
+#include <QAction>
+#include <QSettings>
+
+MainWindow::MainWindow () :
+    m_dialogs (this),
+    filterInput (new FilterInput (this)),
+    playlistTabs (new PlaylistTabs (this)),
+    infoBar (new InfoBar (this)),
+    centralWidget (new QWidget (this)),
+    centralLayout (new QVBoxLayout (centralWidget))
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_MAC)
+    QIcon::setThemeName ("QtUi");
+
+    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);
+
+    const ToolBarItem items[] = {
+        ToolBarAction ("document-open", N_("Open Files"), N_("Open Files"),
+            [] () { audqt::fileopener_show (audqt::FileMode::Open); }),
+        ToolBarAction ("list-add", N_("Add Files"), N_("Add Files"),
+            [] () { audqt::fileopener_show (audqt::FileMode::Add); }),
+        ToolBarSeparator (),
+        ToolBarAction ("media-playback-play", N_("Play"), N_("Play"), aud_drct_play_pause, & toolButtonPlayPause),
+        ToolBarAction ("media-playback-stop", N_("Stop"), N_("Stop"), aud_drct_stop),
+        ToolBarAction ("media-skip-backward", N_("Previous"), N_("Previous"), aud_drct_pl_prev),
+        ToolBarAction ("media-skip-forward", N_("Next"), N_("Next"), aud_drct_pl_next),
+        ToolBarSeparator (),
+        ToolBarCustom (slider),
+        ToolBarCustom (slider->label ()),
+        ToolBarSeparator (),
+        ToolBarAction ("media-playlist-repeat", N_("Repeat"), N_("Repeat"),
+            [] (bool on) { aud_set_bool (nullptr, "repeat", on); }, & toolButtonRepeat),
+        ToolBarAction ("media-playlist-shuffle", N_("Shuffle"), N_("Shuffle"),
+            [] (bool on) { aud_set_bool (nullptr, "shuffle", on); }, & toolButtonShuffle),
+        ToolBarCustom (new audqt::VolumeButton (this)),
+        ToolBarCustom (filterInput),
+    };
+
+    addToolBar (Qt::TopToolBarArea, new ToolBar (this, items));
+
+    setUnifiedTitleAndToolBarOnMac (true);
+
+    updateToggles ();
+
+    setStatusBar (new StatusBar (this));
+    setCentralWidget (centralWidget);
+
+    centralLayout->addWidget (playlistTabs);
+    centralLayout->addWidget (infoBar);
+
+    centralLayout->setContentsMargins (0, 0, 0, 0);
+    centralLayout->setSpacing (4);
+
+    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 ();
+    }
+    else
+        playback_stop_cb ();
+
+    title_change_cb ();
+
+    readSettings ();
+}
+
+MainWindow::~MainWindow ()
+{
+    remove_dock_plugins ();
+}
+
+void MainWindow::closeEvent (QCloseEvent * e)
+{
+    QSettings settings ("audacious", "QtUi");
+    settings.setValue ("geometry", saveGeometry());
+    settings.setValue ("windowState", saveState());
+
+    aud_quit ();
+    e->ignore ();
+}
+
+void MainWindow::readSettings ()
+{
+    QSettings settings ("audacious", "QtUi");
+    restoreGeometry (settings.value ("geometry").toByteArray());
+    restoreState (settings.value ("windowState").toByteArray());
+}
+
+void MainWindow::keyPressEvent (QKeyEvent * e)
+{
+    switch (e->modifiers ())
+    {
+    case Qt::ControlModifier:
+        switch (e->key ())
+        {
+        case Qt::Key_F:
+            filterInput->setFocus ();
+            break;
+        }
+        break;
+    }
+
+    QMainWindow::keyPressEvent (e);
+}
+
+void MainWindow::updateToggles ()
+{
+    toolButtonRepeat->setChecked (aud_get_bool (nullptr, "repeat"));
+    toolButtonShuffle->setChecked (aud_get_bool (nullptr, "shuffle"));
+}
+
+void MainWindow::update_play_pause ()
+{
+    if (! aud_drct_get_playing () || aud_drct_get_paused ())
+    {
+        toolButtonPlayPause->setIcon (QIcon::fromTheme ("media-playback-start"));
+        toolButtonPlayPause->setText (_("Play"));
+        toolButtonPlayPause->setToolTip (_("Play"));
+    }
+    else
+    {
+        toolButtonPlayPause->setIcon (QIcon::fromTheme ("media-playback-pause"));
+        toolButtonPlayPause->setText (_("Pause"));
+        toolButtonPlayPause->setToolTip (_("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"));
+}
+
+void MainWindow::playback_begin_cb ()
+{
+    update_play_pause ();
+
+    int last_list = aud_playlist_by_unique_id (playing_id);
+    auto last_widget = playlistTabs->playlistWidget (last_list);
+    if (last_widget)
+        last_widget->updatePlaybackIndicator ();
+
+    int list = aud_playlist_get_playing ();
+    auto widget = playlistTabs->playlistWidget (list);
+    if (widget)
+        widget->scrollToCurrent ();
+    if (widget && widget != last_widget)
+        widget->updatePlaybackIndicator ();
+
+    playing_id = aud_playlist_get_unique_id (list);
+
+    buffering_timer.start (250);
+}
+
+void MainWindow::playback_ready_cb ()
+{
+    title_change_cb ();
+}
+
+void MainWindow::pause_cb ()
+{
+    update_play_pause ();
+
+    int list = aud_playlist_by_unique_id (playing_id);
+    auto widget = playlistTabs->playlistWidget (list);
+    if (widget)
+        widget->updatePlaybackIndicator ();
+}
+
+void MainWindow::playback_stop_cb ()
+{
+    setWindowTitle ("Audacious");
+    update_play_pause ();
+
+    int last_list = aud_playlist_by_unique_id (playing_id);
+    auto last_widget = playlistTabs->playlistWidget (last_list);
+    if (last_widget)
+        last_widget->updatePlaybackIndicator ();
+
+    playing_id = -1;
+}
+
+void MainWindow::update_toggles_cb ()
+{
+    updateToggles ();
+}
+
+struct DockWidget {
+    QDockWidget * w;
+    PluginHandle * pl;
+};
+
+void MainWindow::add_dock_plugin_cb (PluginHandle * plugin)
+{
+    QWidget * widget = (QWidget *) aud_plugin_get_qt_widget (plugin);
+
+    if (widget)
+    {
+        widget->resize (320, 240);
+
+        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);
+
+        dock_widgets.append (w, plugin);
+    }
+}
+
+void MainWindow::remove_dock_plugin_cb (PluginHandle * plugin)
+{
+    auto remove_cb = [&] (DockWidget & dw)
+    {
+        if (dw.pl != plugin)
+            return false;
+
+        removeDockWidget (dw.w);
+
+        delete dw.w;
+        return true;
+    };
+
+    dock_widgets.remove_if (remove_cb);
+}
+
+void MainWindow::add_dock_plugins ()
+{
+    for (PluginHandle * plugin : aud_plugin_list (PluginType::General))
+    {
+        if (aud_plugin_get_enabled (plugin))
+            add_dock_plugin_cb (plugin);
+    }
+
+    for (PluginHandle * plugin : aud_plugin_list (PluginType::Vis))
+    {
+        if (aud_plugin_get_enabled (plugin))
+            add_dock_plugin_cb (plugin);
+    }
+}
+
+void MainWindow::remove_dock_plugins ()
+{
+    for (PluginHandle * plugin : aud_plugin_list (PluginType::General))
+    {
+        if (aud_plugin_get_enabled (plugin))
+            remove_dock_plugin_cb (plugin);
+    }
+
+    for (PluginHandle * plugin : aud_plugin_list (PluginType::Vis))
+    {
+        if (aud_plugin_get_enabled (plugin))
+            remove_dock_plugin_cb (plugin);
+    }
+}
diff --git a/src/qtui/main_window.h b/src/qtui/main_window.h
new file mode 100644
index 000000000000..0c486eb3b0bc
--- /dev/null
+++ b/src/qtui/main_window.h
@@ -0,0 +1,103 @@
+/*
+ * main_window.h
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 MAIN_WINDOW_H
+#define MAIN_WINDOW_H
+
+#include <libaudcore/hook.h>
+#include <libaudcore/index.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 MainWindow : public QMainWindow
+{
+public:
+    MainWindow ();
+    ~MainWindow ();
+
+private:
+    DialogWindows m_dialogs;
+    FilterInput * filterInput;
+    PlaylistTabs * playlistTabs;
+    InfoBar * infoBar;
+    QWidget * centralWidget;
+    QVBoxLayout * centralLayout;
+
+    QAction * toolButtonPlayPause;
+    QAction * toolButtonRepeat;
+    QAction * toolButtonShuffle;
+
+    QTimer buffering_timer;
+
+    void closeEvent (QCloseEvent * e);
+    void keyPressEvent (QKeyEvent * e);
+
+    void updateToggles ();
+    void setupActions ();
+    void readSettings ();
+
+    void update_play_pause ();
+    void show_buffering ();
+
+    void add_dock_plugins ();
+    void remove_dock_plugins ();
+
+    void title_change_cb ();
+    void playback_begin_cb ();
+    void playback_ready_cb ();
+    void pause_cb ();
+    void playback_stop_cb ();
+    void update_toggles_cb ();
+
+    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},
+     hook4 {"playback pause", this, & MainWindow::pause_cb},
+     hook5 {"playback unpause", this, & MainWindow::pause_cb},
+     hook6 {"playback stop", this, & MainWindow::playback_stop_cb},
+     hook7 {"set repeat", this, & MainWindow::update_toggles_cb},
+     hook8 {"set shuffle", this, & MainWindow::update_toggles_cb},
+     hook9 {"set no_playlist_advance", this, & MainWindow::update_toggles_cb},
+     hook10 {"set stop_after_current_song", this, & MainWindow::update_toggles_cb};
+
+    const HookReceiver<MainWindow, PluginHandle *>
+     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;
+    int playing_id = -1;
+};
+
+#endif
diff --git a/src/qtui/main_window_actions.cc b/src/qtui/main_window_actions.cc
new file mode 100644
index 000000000000..6e63257a03fb
--- /dev/null
+++ b/src/qtui/main_window_actions.cc
@@ -0,0 +1,197 @@
+/*
+ * main_window_actions.cc
+ * Copyright 2014 Michał Lipski and William Pitcock
+ *
+ * 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 "main_window.h"
+
+#include <QMenuBar>
+
+#include <libaudcore/drct.h>
+#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>
+#include <libaudcore/playlist.h>
+
+#include <libaudqt/libaudqt.h>
+#include <libaudqt/menu.h>
+
+static QMenu * services_menu () { return audqt::menu_get_by_id (AudMenuID::Main); }
+
+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 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); }
+static void rm_dupes_path () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+
+static void sort_track () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Track); }
+static void sort_title () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Title); }
+static void sort_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Artist); }
+static void sort_album () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Album); }
+static void sort_album_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::AlbumArtist); }
+static void sort_date () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Date); }
+static void sort_genre () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Genre); }
+static void sort_length () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Length); }
+static void sort_path () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+static void sort_custom_title () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::FormattedTitle); }
+static void sort_reverse () { aud_playlist_reverse (aud_playlist_get_active ()); }
+static void sort_random () { aud_playlist_randomize (aud_playlist_get_active ()); }
+
+static void sort_sel_track () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Track); }
+static void sort_sel_title () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Title); }
+static void sort_sel_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Artist); }
+static void sort_sel_album () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Album); }
+static void sort_sel_album_artist () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::AlbumArtist); }
+static void sort_sel_date () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Date); }
+static void sort_sel_genre () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Genre); }
+static void sort_sel_length () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Length); }
+static void sort_sel_path () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Path); }
+static void sort_sel_custom_title () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::FormattedTitle); }
+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_close () { audqt::playlist_confirm_delete (aud_playlist_get_active ()); }
+
+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 configure_effects () { audqt::prefswin_show_plugin_page (PluginType::Effect); }
+
+void MainWindow::setupActions ()
+{
+    static constexpr 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_("_Add Files ..."), "list-add", "Ctrl+Shift+O"}, add_files),
+        audqt::MenuCommand ({N_("_Add Folder ..."), "list-add"}, add_folder),
+        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),
+        audqt::MenuSep (),
+        audqt::MenuCommand ({N_("_Log Inspector ...")}, audqt::log_inspector_show),
+        audqt::MenuSep (),
+        audqt::MenuCommand ({N_("_Quit"), "application-exit", "Ctrl+Q"}, aud_quit)
+    };
+
+    static constexpr 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_("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[] = {
+        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[] = {
+        audqt::MenuCommand ({N_("By Track _Number")}, sort_track),
+        audqt::MenuCommand ({N_("By _Title")}, sort_title),
+        audqt::MenuCommand ({N_("By _Artist")}, sort_artist),
+        audqt::MenuCommand ({N_("By Al_bum")}, sort_album),
+        audqt::MenuCommand ({N_("By Albu_m Artist")}, sort_album_artist),
+        audqt::MenuCommand ({N_("By Release _Date")}, sort_date),
+        audqt::MenuCommand ({N_("By _Genre")}, sort_genre),
+        audqt::MenuCommand ({N_("By _Length")}, sort_length),
+        audqt::MenuCommand ({N_("By _File Path")}, sort_path),
+        audqt::MenuCommand ({N_("By _Custom Title")}, sort_custom_title),
+        audqt::MenuSep (),
+        audqt::MenuCommand ({N_("R_everse Order"), "view-sort-descending"}, sort_reverse),
+        audqt::MenuCommand ({N_("_Random Order")}, sort_random)
+    };
+
+    static constexpr 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),
+        audqt::MenuCommand ({N_("By Al_bum")}, sort_sel_album),
+        audqt::MenuCommand ({N_("By Albu_m Artist")}, sort_sel_album_artist),
+        audqt::MenuCommand ({N_("By Release _Date")}, sort_sel_date),
+        audqt::MenuCommand ({N_("By _Genre")}, sort_sel_genre),
+        audqt::MenuCommand ({N_("By _Length")}, sort_sel_length),
+        audqt::MenuCommand ({N_("By _File Path")}, sort_sel_path),
+        audqt::MenuCommand ({N_("By _Custom Title")}, sort_sel_custom_title),
+        audqt::MenuSep (),
+        audqt::MenuCommand ({N_("R_everse Order"), "view-sort-descending"}, sort_sel_reverse),
+        audqt::MenuCommand ({N_("_Random Order")}, sort_sel_random)
+    };
+
+    static constexpr 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 (),
+        audqt::MenuSub ({N_("_Sort"), "view-sort-ascending"}, sort_items),
+        audqt::MenuSub ({N_("Sort Se_lected"), "view-sort-ascending"}, sort_selected_items),
+        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_("Remo_ve"), "edit-delete", "Ctrl+W"}, pl_close),
+        audqt::MenuSep (),
+        //audqt::MenuCommand ({N_("_Import ..."), "document-open"}, TODO),
+        //audqt::MenuCommand ({N_("_Export ..."), "document-save"}, TODO),
+        audqt::MenuSep (),
+        //audqt::MenuCommand ({N_("Playlist _Manager ..."), "audio-x-generic", "Ctrl+P"}, TODO),
+        audqt::MenuCommand ({N_("_Queue Manager ..."), nullptr, "Ctrl+U"}, audqt::queue_manager_show)
+    };
+
+    static constexpr 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::MenuSep (),
+        audqt::MenuCommand ({N_("E_ffects ...")}, configure_effects)
+    };
+
+    static constexpr audqt::MenuItem main_items[] = {
+        audqt::MenuSub ({N_("_File")}, file_items),
+        audqt::MenuSub ({N_("_Playback")}, playback_items),
+        audqt::MenuSub ({N_("P_laylist")}, playlist_items),
+        audqt::MenuSub ({N_("_Services")}, services_menu),
+        audqt::MenuSub ({N_("_Output")}, output_items),
+    };
+
+    setMenuBar (audqt::menubar_build (main_items, this));
+}
diff --git a/src/qtui/playlist.cc b/src/qtui/playlist.cc
new file mode 100644
index 000000000000..232336e851f0
--- /dev/null
+++ b/src/qtui/playlist.cc
@@ -0,0 +1,287 @@
+/*
+ * playlist.cc
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 <QKeyEvent>
+#include <QSortFilterProxyModel>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/playlist.h>
+
+#include "playlist.h"
+#include "playlist_model.h"
+
+PlaylistWidget::PlaylistWidget (QTreeView * parent, int uniqueId) : QTreeView (parent)
+{
+    model = new PlaylistModel (nullptr, uniqueId);
+
+    /* setting up filtering model */
+    proxyModel = new QSortFilterProxyModel (this);
+    proxyModel->setSourceModel (model);
+    proxyModel->setFilterKeyColumn (-1); /* filter by all columns */
+
+    setModel (proxyModel);
+    setAlternatingRowColors (true);
+    setAttribute (Qt::WA_MacShowFocusRect, false);
+    setIndentation (0);
+    setUniformRowHeights (true);
+    setFrameShape (QFrame::NoFrame);
+    setSelectionMode (ExtendedSelection);
+    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 ();
+}
+
+void PlaylistWidget::setFilter (const QString & text)
+{
+    proxyModel->setFilterRegExp (QRegExp (text, Qt::CaseInsensitive, QRegExp::FixedString));
+}
+
+PlaylistWidget::~PlaylistWidget ()
+{
+    delete model;
+    delete proxyModel;
+}
+
+QModelIndex PlaylistWidget::rowToIndex (int row)
+{
+    if (row < 0)
+        return QModelIndex ();
+
+    return proxyModel->mapFromSource (model->index (row));
+}
+
+int PlaylistWidget::indexToRow (const QModelIndex & index)
+{
+    if (! index.isValid ())
+        return -1;
+
+    return proxyModel->mapToSource (index).row ();
+}
+
+void PlaylistWidget::keyPressEvent (QKeyEvent * e)
+{
+    switch (e->modifiers ())
+    {
+    case Qt::NoModifier:
+        switch (e->key ())
+        {
+        case Qt::Key_Escape:
+            scrollToCurrent ();
+            break;
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+            playCurrentIndex ();
+            break;
+        case Qt::Key_Right:
+            aud_drct_seek (aud_drct_get_time () + 5000);
+            break;
+        case Qt::Key_Left:
+            aud_drct_seek (aud_drct_get_time () - 5000);
+            break;
+        case Qt::Key_Space:
+            aud_drct_play_pause ();
+            break;
+        case Qt::Key_Delete:
+            deleteCurrentSelection ();
+            break;
+        case Qt::Key_Z:
+            aud_drct_pl_prev ();
+            return;
+        case Qt::Key_X:
+            aud_drct_play ();
+            return;
+        case Qt::Key_C:
+            aud_drct_pause ();
+            return;
+        case Qt::Key_V:
+            aud_drct_stop ();
+            return;
+        case Qt::Key_B:
+            aud_drct_pl_next ();
+            return;
+        case Qt::Key_Q:
+            toggleQueue ();
+            return;
+        }
+        break;
+    }
+
+     QTreeView::keyPressEvent (e);
+}
+
+void PlaylistWidget::mouseDoubleClickEvent (QMouseEvent * event)
+{
+    if (event->button () == Qt::LeftButton)
+        playCurrentIndex ();
+}
+
+void PlaylistWidget::currentChanged (const QModelIndex & current, const QModelIndex & previous)
+{
+    QTreeView::currentChanged (current, previous);
+
+    if (! inUpdate)
+        aud_playlist_set_focus (playlist (), indexToRow (current));
+}
+
+void PlaylistWidget::selectionChanged (const QItemSelection & selected,
+ const QItemSelection & deselected)
+{
+    QTreeView::selectionChanged (selected, deselected);
+
+    if (! inUpdate)
+    {
+        int list = playlist ();
+
+        for (const QModelIndex & idx : selected.indexes ())
+            aud_playlist_entry_set_selected (list, indexToRow (idx), true);
+        for (const QModelIndex & idx : deselected.indexes ())
+            aud_playlist_entry_set_selected (list, indexToRow (idx), false);
+    }
+}
+
+int PlaylistWidget::playlist () const
+{
+    return model->playlist ();
+}
+
+int PlaylistWidget::uniqueId () const
+{
+    return model->uniqueId ();
+}
+
+void PlaylistWidget::scrollToCurrent ()
+{
+    int list = playlist ();
+    int entry = aud_playlist_get_position (list);
+
+    aud_playlist_select_all (list, false);
+    aud_playlist_entry_set_selected (list, entry, true);
+    aud_playlist_set_focus (list, entry);
+
+    // a playlist update should have been queued, unless the playlist is empty
+    if (aud_playlist_update_pending (list))
+        scrollQueued = true;
+}
+
+void PlaylistWidget::updatePlaybackIndicator ()
+{
+    int list = playlist ();
+
+    if (aud_playlist_update_pending (list))
+        needIndicatorUpdate = true;
+    else if (currentPos >= 0)
+        model->updateRows (currentPos, 1);
+}
+
+void PlaylistWidget::update (const Playlist::Update & update)
+{
+    inUpdate = true;
+
+    int list = playlist ();
+    int entries = aud_playlist_entry_count (list);
+    int changed = entries - update.before - update.after;
+
+    if (update.level == Playlist::Structure)
+    {
+        int old_entries = model->rowCount ();
+        int removed = old_entries - update.before - update.after;
+
+        if (currentPos >= old_entries - update.after)
+            currentPos += entries - old_entries;
+        else if (currentPos >= update.before)
+            currentPos = -1;
+
+        model->removeRows (update.before, removed);
+        model->insertRows (update.before, changed);
+    }
+    else if (update.level == Playlist::Metadata || update.queue_changed)
+        model->updateRows (update.before, changed);
+
+    if (update.queue_changed)
+    {
+        for (int i = aud_playlist_queue_count (list); i --; )
+        {
+            int entry = aud_playlist_queue_get_entry (list, i);
+            if (entry < update.before || entry >= entries - update.after)
+                model->updateRows (entry, 1);
+        }
+    }
+
+    int pos = aud_playlist_get_position (list);
+
+    if (needIndicatorUpdate || pos != currentPos)
+    {
+        if (currentPos >= 0)
+            model->updateRows (currentPos, 1);
+        if (pos >= 0 && pos != currentPos)
+            model->updateRows (pos, 1);
+
+        currentPos = pos;
+        needIndicatorUpdate = false;
+    }
+
+    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);
+    }
+
+    auto current = rowToIndex (aud_playlist_get_focus (list));
+    sel->setCurrentIndex (current, sel->NoUpdate);
+
+    if (scrollQueued)
+    {
+        scrollTo (current);
+        scrollQueued = false;
+    }
+
+    inUpdate = false;
+}
+
+void PlaylistWidget::playCurrentIndex ()
+{
+    aud_playlist_set_position (playlist (), indexToRow (currentIndex ()));
+    aud_playlist_play (playlist ());
+}
+
+void PlaylistWidget::deleteCurrentSelection ()
+{
+    aud_playlist_delete_selected (playlist ());
+}
+
+void PlaylistWidget::toggleQueue ()
+{
+    int row = indexToRow (currentIndex ());
+    int at = aud_playlist_queue_find_entry (playlist (), row);
+
+    if (at < 0)
+        aud_playlist_queue_insert (playlist (), -1, row);
+    else
+        aud_playlist_queue_delete (playlist (), at, 1);
+}
diff --git a/src/qtui/playlist.h b/src/qtui/playlist.h
new file mode 100644
index 000000000000..a6bf16157257
--- /dev/null
+++ b/src/qtui/playlist.h
@@ -0,0 +1,63 @@
+/*
+ * playlist.h
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 PLAYLIST_H
+#define PLAYLIST_H
+
+#include <QTreeView>
+#include <libaudcore/playlist.h>
+
+#include "playlist_model.h"
+#include "filter_input.h"
+
+class QSortFilterProxyModel;
+
+class PlaylistWidget : public QTreeView
+{
+public:
+    PlaylistWidget (QTreeView * parent = nullptr, int uniqueId = -1);
+    ~PlaylistWidget ();
+    void scrollToCurrent ();
+    void updatePlaybackIndicator ();
+    void update (const Playlist::Update & update);
+    void playCurrentIndex ();
+    void deleteCurrentSelection ();
+    void setFilter (const QString &text);
+    void toggleQueue ();
+    int playlist () const;
+    int uniqueId () const;
+
+private:
+    PlaylistModel * model;
+    QSortFilterProxyModel * proxyModel;
+    int currentPos = -1;
+    bool inUpdate = false;
+    bool needIndicatorUpdate = false;
+    bool scrollQueued = false;
+
+    QModelIndex rowToIndex (int row);
+    int indexToRow (const QModelIndex & index);
+
+    void keyPressEvent (QKeyEvent * e); /* override default handler */
+    void mouseDoubleClickEvent (QMouseEvent * event);
+    void currentChanged (const QModelIndex & current, const QModelIndex & previous);
+    void selectionChanged (const QItemSelection & selected, const QItemSelection & deselected);
+};
+
+#endif
diff --git a/src/qtui/playlist_model.cc b/src/qtui/playlist_model.cc
new file mode 100644
index 000000000000..98613eabebb3
--- /dev/null
+++ b/src/qtui/playlist_model.cc
@@ -0,0 +1,181 @@
+/*
+ * playlist_model.cc
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 <QApplication>
+#include <QIcon>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/tuple.h>
+
+#include "playlist_model.h"
+
+static inline QPixmap get_icon (const char * name)
+{
+    qreal r = qApp->devicePixelRatio ();
+    QPixmap pm = QIcon::fromTheme (name).pixmap (16 * r);
+    pm.setDevicePixelRatio (r);
+    return pm;
+}
+
+PlaylistModel::PlaylistModel (QObject * parent, int id) : QAbstractListModel (parent),
+    m_uniqueId (id)
+{
+    m_rows = aud_playlist_entry_count (playlist ());
+}
+
+PlaylistModel::~PlaylistModel ()
+{
+
+}
+
+int PlaylistModel::rowCount (const QModelIndex & parent) const
+{
+    return m_rows;
+}
+
+int PlaylistModel::columnCount (const QModelIndex & parent) const
+{
+    return PL_COLS;
+}
+
+QVariant PlaylistModel::data (const QModelIndex &index, int role) const
+{
+    String title, artist, album;
+    Tuple tuple;
+
+    switch (role)
+    {
+    case Qt::DisplayRole:
+        switch (index.column ())
+        {
+        case PL_COL_TITLE:
+        case PL_COL_ARTIST:
+        case PL_COL_ALBUM:
+        case PL_COL_LENGTH:
+            tuple = aud_playlist_entry_get_tuple (playlist (), index.row (), Playlist::Guess);
+            break;
+        }
+
+        switch (index.column ())
+        {
+        case PL_COL_TITLE:
+            return QString (tuple.get_str (Tuple::Title));
+        case PL_COL_ARTIST:
+            return QString (tuple.get_str (Tuple::Artist));
+        case PL_COL_ALBUM:
+            return QString (tuple.get_str (Tuple::Album));
+        case PL_COL_QUEUED:
+            return getQueued (index.row ());
+        case PL_COL_LENGTH:
+            return QString (str_format_time (tuple.get_int (Tuple::Length)));
+        }
+
+    case Qt::TextAlignmentRole:
+        switch (index.column ())
+        {
+        case PL_COL_LENGTH:
+            return Qt::AlignRight;
+        }
+
+    case Qt::DecorationRole:
+        if (index.column () == 0 && index.row () == aud_playlist_get_position (playlist ()))
+        {
+            if (aud_playlist_get_playing () == playlist ())
+                if (aud_drct_get_paused ())
+                    return get_icon ("media-playback-pause");
+                else
+                    return get_icon ("media-playback-start");
+            else
+                return get_icon ("media-playback-stop");
+        }
+    }
+    return QVariant ();
+}
+
+QVariant PlaylistModel::headerData (int section, Qt::Orientation orientation, int role) const
+{
+    if (role == Qt::DisplayRole)
+    {
+        if (orientation == Qt::Horizontal)
+        {
+            switch (section)
+            {
+            case PL_COL_TITLE:
+                return QString (_("Title"));
+            case PL_COL_ARTIST:
+                return QString (_("Artist"));
+            case PL_COL_ALBUM:
+                return QString (_("Album"));
+            case PL_COL_QUEUED:
+                return QString ();
+            case PL_COL_LENGTH:
+                return QString ();
+            }
+        }
+    }
+    return QVariant ();
+}
+
+int PlaylistModel::playlist () const
+{
+    return aud_playlist_by_unique_id (m_uniqueId);
+}
+
+int PlaylistModel::uniqueId () const
+{
+    return m_uniqueId;
+}
+
+bool PlaylistModel::insertRows (int row, int count, const QModelIndex & parent)
+{
+    int last = row + count - 1;
+    beginInsertRows (parent, row, last);
+    m_rows = aud_playlist_entry_count (playlist ());
+    endInsertRows ();
+    return true;
+}
+
+bool PlaylistModel::removeRows (int row, int count, const QModelIndex & parent)
+{
+    int last = row + count - 1;
+    beginRemoveRows (parent, row, last);
+    m_rows = aud_playlist_entry_count (playlist ());
+    endRemoveRows ();
+    return true;
+}
+
+void PlaylistModel::updateRows (int row, int count)
+{
+    int bottom = row + count - 1;
+    auto topLeft = createIndex (row, 0);
+    auto bottomRight = createIndex (bottom, columnCount () - 1);
+    emit dataChanged (topLeft, bottomRight);
+}
+
+QString PlaylistModel::getQueued (int row) const
+{
+    int at = aud_playlist_queue_find_entry (playlist (), row);
+    if (at < 0)
+        return QString ("");
+    else
+        return QString ("#%1").arg (at + 1);
+}
diff --git a/src/qtui/playlist_model.h b/src/qtui/playlist_model.h
new file mode 100644
index 000000000000..6c31f4125e2a
--- /dev/null
+++ b/src/qtui/playlist_model.h
@@ -0,0 +1,54 @@
+/*
+ * playlist_model.h
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 PLAYLIST_MODEL_H
+#define PLAYLIST_MODEL_H
+
+#include <QAbstractListModel>
+
+enum {
+    PL_COL_NOW_PLAYING,
+    PL_COL_TITLE,
+    PL_COL_ARTIST,
+    PL_COL_ALBUM,
+    PL_COL_QUEUED,
+    PL_COL_LENGTH,
+    PL_COLS
+};
+
+class PlaylistModel : public QAbstractListModel
+{
+public:
+    PlaylistModel (QObject * parent = nullptr, int id = -1);
+    ~PlaylistModel ();
+    int rowCount (const QModelIndex & parent = QModelIndex ()) const;
+    int columnCount (const QModelIndex & parent = QModelIndex ()) const;
+    QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const;
+    QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+    bool insertRows (int row, int count, const QModelIndex & parent = QModelIndex ());
+    bool removeRows (int row, int count, const QModelIndex & parent = QModelIndex ());
+    void updateRows (int row, int count);
+    QString getQueued (int row) const;
+    int playlist () const;
+    int uniqueId () const;
+    int m_uniqueId;
+    int m_rows;
+};
+
+#endif
diff --git a/src/qtui/playlist_tabs.cc b/src/qtui/playlist_tabs.cc
new file mode 100644
index 000000000000..f82e76a2127d
--- /dev/null
+++ b/src/qtui/playlist_tabs.cc
@@ -0,0 +1,239 @@
+/*
+ * playlist_tabs.cc
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 "playlist.h"
+#include "playlist_tabs.h"
+
+#include <QKeyEvent>
+#include <QLineEdit>
+
+#include <libaudcore/playlist.h>
+#include <libaudcore/runtime.h>
+
+#include <libaudqt/libaudqt.h>
+
+PlaylistTabs::PlaylistTabs (QWidget * parent) :
+    QTabWidget (parent),
+    m_leftbtn (nullptr),
+    m_tabbar (new PlaylistTabBar (this))
+{
+    installEventFilter (this);
+
+    // set up tab bar
+    m_tabbar->setFocusPolicy (Qt::NoFocus);
+    setTabBar (m_tabbar);
+
+    populatePlaylists ();
+    setCurrentIndex (aud_playlist_get_active ());
+
+    connect (this, &QTabWidget::currentChanged, this, &PlaylistTabs::currentChangedTrigger);
+}
+
+PlaylistTabs::~PlaylistTabs ()
+{
+    // TODO: cleanup playlists
+}
+
+void PlaylistTabs::maybeCreateTab (int count_, int uniq_id)
+{
+    int tabs = count ();
+
+    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_)));
+}
+
+void PlaylistTabs::cullPlaylists ()
+{
+    int tabs = count ();
+
+    for (int i = 0; i < tabs; i++)
+    {
+         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())));
+    }
+}
+
+void PlaylistTabs::populatePlaylists ()
+{
+    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);
+}
+
+void PlaylistTabs::filterTrigger (const QString &text)
+{
+    ((PlaylistWidget *) currentWidget ())->setFilter (text);
+}
+
+void PlaylistTabs::currentChangedTrigger (int idx)
+{
+    cancelRename ();
+    aud_playlist_set_active (idx);
+}
+
+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)
+{
+    QWidget * old = m_tabbar->tabButton (idx, QTabBar::LeftSide);
+    m_tabbar->setTabButton (idx, QTabBar::LeftSide, button);
+    setTabText (idx, text);
+
+    if (oldp)
+        * oldp = old;
+    else
+    {
+        old->setParent (nullptr);
+        old->deleteLater ();
+    }
+}
+
+void PlaylistTabs::tabEditedTrigger ()
+{
+    int idx = currentIndex ();
+    if (idx < 0)
+        return;
+
+    QLineEdit * edit = getTabEdit (idx);
+    if (! edit)
+        return;
+
+    QString title = edit->text ();
+    aud_playlist_set_title (idx, title.toUtf8 ());
+
+    setupTab (idx, m_leftbtn, title, nullptr);
+    m_leftbtn = nullptr;
+}
+
+void PlaylistTabs::editTab (int idx)
+{
+    QLineEdit * edit = new QLineEdit (tabText (idx));
+
+    connect (edit, & QLineEdit::returnPressed, this, & PlaylistTabs::tabEditedTrigger);
+
+    setupTab (idx, edit, QString (), & m_leftbtn);
+
+    edit->selectAll ();
+    edit->setFocus ();
+}
+
+bool PlaylistTabs::eventFilter (QObject * obj, QEvent * e)
+{
+    if (e->type() == QEvent::KeyPress)
+    {
+        QKeyEvent *ke = (QKeyEvent *) e;
+
+        if (ke->key() == Qt::Key_Escape)
+        {
+            cancelRename ();
+            return true;
+        }
+    }
+
+    return QTabWidget::eventFilter(obj, e);
+}
+
+void PlaylistTabs::cancelRename ()
+{
+    for (int i = 0; i < count (); i ++)
+    {
+        QLineEdit * edit = getTabEdit (i);
+        if (! edit)
+            continue;
+
+        setupTab (i, m_leftbtn, (const char *) aud_playlist_get_title (i), nullptr);
+        m_leftbtn = nullptr;
+    }
+}
+
+void PlaylistTabs::playlist_update_cb (Playlist::UpdateLevel global_level)
+{
+    if (global_level == Playlist::Structure)
+        populatePlaylists ();
+
+    int lists = aud_playlist_count ();
+    for (int list = 0; list < lists; list ++)
+    {
+        auto update = aud_playlist_update_detail (list);
+        if (update.level)
+            playlistWidget (list)->update (update);
+    }
+}
+
+void PlaylistTabs::playlist_position_cb (int list)
+{
+    auto widget = playlistWidget (list);
+    if (widget)
+        widget->scrollToCurrent ();
+}
+
+PlaylistTabBar::PlaylistTabBar (QWidget * parent) : QTabBar (parent)
+{
+    setDocumentMode (true);
+    setTabsClosable (true);
+
+    connect (this, &QTabBar::tabCloseRequested, this, &PlaylistTabBar::handleCloseRequest);
+}
+
+void PlaylistTabBar::mouseDoubleClickEvent (QMouseEvent *e)
+{
+    PlaylistTabs *p = (PlaylistTabs *) parent();
+
+    int idx = tabAt (e->pos());
+    if (idx < 0)
+        return;
+
+    p->editTab (idx);
+}
+
+void PlaylistTabBar::handleCloseRequest (int idx)
+{
+    PlaylistTabs *p = (PlaylistTabs *) parent ();
+    PlaylistWidget *pl = (PlaylistWidget *) p->widget (idx);
+
+    if (! pl)
+        return;
+
+    audqt::playlist_confirm_delete (pl->playlist ());
+}
diff --git a/src/qtui/playlist_tabs.h b/src/qtui/playlist_tabs.h
new file mode 100644
index 000000000000..f9384a90ee56
--- /dev/null
+++ b/src/qtui/playlist_tabs.h
@@ -0,0 +1,82 @@
+/*
+ * playlist_tabs.h
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 PLAYLIST_TABS_H
+#define PLAYLIST_TABS_H
+
+#include <QTabWidget>
+
+#include <libaudcore/hook.h>
+#include <libaudcore/playlist.h>
+
+#include "playlist.h"
+#include "filter_input.h"
+
+class PlaylistTabBar;
+class PlaylistWidget;
+class QLineEdit;
+
+class PlaylistTabs : public QTabWidget
+{
+public:
+    PlaylistTabs (QWidget * parent = nullptr);
+    ~PlaylistTabs ();
+
+    PlaylistWidget * playlistWidget (int num);
+
+    void editTab (int idx);
+    void filterTrigger (const QString &text);
+    void currentChangedTrigger (int idx);
+    void tabEditedTrigger ();
+
+protected:
+    bool eventFilter (QObject * obj, QEvent *e);
+
+private:
+    QWidget *m_leftbtn;
+    PlaylistTabBar *m_tabbar;
+
+    QLineEdit * getTabEdit (int idx);
+    void setupTab (int idx, QWidget * button, const QString & text, QWidget * * oldp);
+
+    void populatePlaylists ();
+    void maybeCreateTab (int count_, int uniq_id);
+    void cullPlaylists ();
+    void cancelRename ();
+
+    void playlist_update_cb (Playlist::UpdateLevel global_level);
+    void playlist_position_cb (int list);
+
+    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};
+};
+
+class PlaylistTabBar : public QTabBar
+{
+public:
+    PlaylistTabBar (QWidget * parent = nullptr);
+    void handleCloseRequest (int idx);
+
+protected:
+    void mouseDoubleClickEvent (QMouseEvent *e);
+};
+
+#endif
diff --git a/src/qtui/qtui.cc b/src/qtui/qtui.cc
new file mode 100644
index 000000000000..24c86c11d81f
--- /dev/null
+++ b/src/qtui/qtui.cc
@@ -0,0 +1,83 @@
+/*
+ * qtui.cc
+ * Copyright 2014 Michał Lipski
+ *
+ * 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 <QApplication>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include <libaudqt/libaudqt.h>
+#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};
+
+class QtUI : public audqt::QtIfacePlugin
+{
+private:
+    QApplication * qapp = nullptr;
+    MainWindow * window = nullptr;
+
+public:
+    constexpr QtUI () : audqt::QtIfacePlugin ({N_("Qt Interface"), PACKAGE}) {}
+
+    bool init ()
+    {
+        if (aud_get_mainloop_type () != MainloopType::Qt)
+            return false;
+
+        qapp = new QApplication (dummy_argc, dummy_argv);
+        qapp->setAttribute(Qt::AA_UseHighDpiPixmaps);
+        window = new MainWindow;
+
+        return true;
+    }
+
+    void cleanup ()
+    {
+        delete window;
+        window = nullptr;
+
+        audqt::cleanup ();
+
+        delete qapp;
+        qapp = nullptr;
+    }
+
+    void run ()
+    {
+        qapp->exec ();
+    }
+
+    void show (bool show)
+    {
+        window->setVisible (show);
+    }
+
+    void quit ()
+    {
+        qapp->quit();
+    }
+};
+
+EXPORT QtUI aud_plugin_instance;
diff --git a/src/qtui/status_bar.cc b/src/qtui/status_bar.cc
new file mode 100644
index 000000000000..3856ffac2548
--- /dev/null
+++ b/src/qtui/status_bar.cc
@@ -0,0 +1,99 @@
+/*
+ * status_bar.cc
+ * Copyright 2014 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 "status_bar.h"
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
+
+StatusBar::StatusBar (QWidget * parent) :
+    QStatusBar (parent),
+    codec_label (new QLabel (this)),
+    length_label (new QLabel (this))
+{
+    setStyleSheet ("QStatusBar { background: transparent; } QStatusBar::item { border: none; }");
+
+    addWidget (codec_label);
+    addPermanentWidget (length_label);
+
+    update_codec ();
+    update_length ();
+}
+
+void StatusBar::update_codec ()
+{
+    if (! aud_drct_get_ready ())
+    {
+        codec_label->hide ();
+        return;
+    }
+
+    Tuple tuple = aud_drct_get_tuple ();
+    String codec = tuple.get_str (Tuple::Codec);
+
+    int bitrate, samplerate, channels;
+    aud_drct_get_info (bitrate, samplerate, channels);
+
+    StringBuf buf (0);
+
+    if (codec)
+    {
+        buf.insert (-1, codec);
+        if (channels > 0 || samplerate > 0 || bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (channels > 0)
+    {
+        if (channels == 1)
+            buf.insert (-1, _("mono"));
+        else if (channels == 2)
+            buf.insert (-1, _("stereo"));
+        else
+            buf.combine (str_printf (ngettext ("%d channel", "%d channels", channels), channels));
+
+        if (samplerate > 0 || bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (samplerate > 0)
+    {
+        buf.combine (str_printf ("%d kHz", samplerate / 1000));
+        if (bitrate > 0)
+            buf.insert (-1, ", ");
+    }
+
+    if (bitrate > 0)
+        buf.combine (str_printf (_("%d kbps"), bitrate / 1000));
+
+    codec_label->setText ((const char *) buf);
+    codec_label->show ();
+}
+
+void StatusBar::update_length ()
+{
+    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));
+
+    length_label->setText ((const char *) str_concat ({s1, " / ", s2}));
+}
diff --git a/src/qtui/status_bar.h b/src/qtui/status_bar.h
new file mode 100644
index 000000000000..1cdece5c7a9d
--- /dev/null
+++ b/src/qtui/status_bar.h
@@ -0,0 +1,49 @@
+/*
+ * status_bar.h
+ * Copyright 2014 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.
+ */
+
+#ifndef STATUS_BAR_H
+#define STATUS_BAR_H
+
+#include <QLabel>
+#include <QStatusBar>
+
+#include <libaudcore/hook.h>
+
+class StatusBar : public QStatusBar
+{
+public:
+    StatusBar (QWidget * parent);
+
+private:
+    QLabel * codec_label;
+    QLabel * length_label;
+
+    void update_codec ();
+    void update_length ();
+
+    const HookReceiver<StatusBar>
+     hook1 {"playlist activate", this, & StatusBar::update_length},
+     hook2 {"playlist update", this, & StatusBar::update_length},
+     hook3 {"playback ready", this, & StatusBar::update_codec},
+     hook4 {"playback stop", this, & StatusBar::update_codec},
+     hook5 {"info change", this, & StatusBar::update_codec},
+     hook6 {"tuple change", this, & StatusBar::update_codec};
+};
+
+#endif // STATUS_BAR_H
diff --git a/src/qtui/time_slider.cc b/src/qtui/time_slider.cc
new file mode 100644
index 000000000000..dee7d47380a3
--- /dev/null
+++ b/src/qtui/time_slider.cc
@@ -0,0 +1,121 @@
+/*
+ * time_slider.cc
+ * Copyright 2014 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 "time_slider.h"
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+
+TimeSlider::TimeSlider (QWidget * parent) :
+    QSlider (Qt::Horizontal, parent),
+    m_label (new QLabel (parent))
+{
+    setFocusPolicy (Qt::NoFocus);
+    setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+    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);
+
+    start_stop ();
+}
+
+TimeSlider::~TimeSlider () {}
+
+void TimeSlider::set_label (int time, int length)
+{
+    QString text;
+
+    if (length > 0)
+        text = str_concat ({str_format_time (time), " / ", str_format_time (length)});
+    else
+        text = str_format_time (time);
+
+    m_label->setText (text);
+}
+
+void TimeSlider::start_stop ()
+{
+    bool ready = aud_drct_get_ready ();
+    bool paused = aud_drct_get_paused ();
+
+    setEnabled (ready);
+    m_label->setEnabled (ready);
+
+    if (ready)
+    {
+        if (! isSliderDown ())
+            update ();
+    }
+    else
+    {
+        setRange (0, 0);
+        m_label->setText ("0:00 / 0:00");
+    }
+
+    if (ready && ! paused && ! isSliderDown ())
+        m_timer.start (250);
+    else
+        m_timer.stop ();
+}
+
+void TimeSlider::update ()
+{
+    int time = aud_drct_get_time ();
+    int length = aud_drct_get_length ();
+
+    setRange (0, length);
+    setValue (time);
+
+    set_label (time, length);
+}
+
+void TimeSlider::moved (int value)
+{
+    set_label (value, aud_drct_get_length ());
+}
+
+void TimeSlider::pressed ()
+{
+    m_timer.stop ();
+}
+
+void TimeSlider::released ()
+{
+    aud_drct_seek (value ());
+    set_label (value (), aud_drct_get_length ());
+
+    if (! aud_drct_get_paused ())
+        m_timer.start (250);
+}
+
+void TimeSlider::mousePressEvent (QMouseEvent * event)
+{
+    if (event->button () == Qt::LeftButton)
+    {
+        setValue (QStyle::sliderValueFromPosition (minimum (), maximum (), event->x (), width ()));
+        event->accept ();
+    }
+
+    QSlider::mousePressEvent (event);
+}
diff --git a/src/qtui/time_slider.h b/src/qtui/time_slider.h
new file mode 100644
index 000000000000..f0a82bfd6594
--- /dev/null
+++ b/src/qtui/time_slider.h
@@ -0,0 +1,61 @@
+/*
+ * time_slider.h
+ * Copyright 2014 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.
+ */
+
+#ifndef TIME_SLIDER_H
+#define TIME_SLIDER_H
+
+#include <QLabel>
+#include <QSlider>
+#include <QTimer>
+#include <QStyle>
+#include <QMouseEvent>
+
+#include <libaudcore/hook.h>
+
+class TimeSlider : public QSlider
+{
+public:
+    TimeSlider (QWidget * parent);
+    ~TimeSlider ();
+
+    QLabel * label ()
+        { return m_label; }
+
+private:
+    void set_label (int time, int length);
+
+    void start_stop ();
+    void update ();
+    void moved (int value);
+    void pressed ();
+    void released ();
+
+    void mousePressEvent (QMouseEvent * event);
+
+    QTimer m_timer;
+    QLabel * m_label;
+
+    const HookReceiver<TimeSlider>
+     hook1 {"playback ready", this, & TimeSlider::start_stop},
+     hook2 {"playback pause", this, & TimeSlider::start_stop},
+     hook3 {"playback unpause", this, & TimeSlider::start_stop},
+     hook4 {"playback stop", this, & TimeSlider::start_stop};
+};
+
+#endif // TIME_SLIDER_H
diff --git a/src/qtui/tool_bar.cc b/src/qtui/tool_bar.cc
new file mode 100644
index 000000000000..1d67ff00e816
--- /dev/null
+++ b/src/qtui/tool_bar.cc
@@ -0,0 +1,65 @@
+/*
+ * tool_bar.cc
+ * Copyright 2014 William Pitcock
+ *
+ * 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 "tool_bar.h"
+
+#include <QAction>
+#include <QIcon>
+
+#include <libaudcore/runtime.h>
+#include <libaudqt/libaudqt.h>
+
+ToolBar::ToolBar (QWidget * parent, ArrayRef<ToolBarItem> items)
+    : QToolBar (parent)
+{
+    setContextMenuPolicy (Qt::PreventContextMenu);
+    setMovable (false);
+    setIconSize (QSize (22, 22));
+    setObjectName ("MainToolBar");
+
+    for (const ToolBarItem & item : items)
+    {
+        if (item.widget)
+            addWidget (item.widget);
+        else if (item.sep)
+            addSeparator ();
+        else if (item.icon_name)
+        {
+            QAction * a = new QAction (QIcon::fromTheme (item.icon_name),
+             audqt::translate_str (item.name), this);
+
+            if (item.tooltip_text)
+                a->setToolTip (audqt::translate_str (item.tooltip_text));
+
+            if (item.callback)
+                connect (a, &QAction::triggered, item.callback);
+
+            if (item.toggled)
+            {
+                a->setCheckable (true);
+                connect (a, &QAction::toggled, item.toggled);
+            }
+
+            addAction (a);
+
+            if (item.action_ptr)
+                * item.action_ptr = a;
+        }
+    }
+}
diff --git a/src/qtui/tool_bar.h b/src/qtui/tool_bar.h
new file mode 100644
index 000000000000..31d31263dcac
--- /dev/null
+++ b/src/qtui/tool_bar.h
@@ -0,0 +1,63 @@
+/*
+ * tool_bar.h
+ * Copyright 2014 William Pitcock
+ *
+ * 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 TOOL_BAR_H
+#define TOOL_BAR_H
+
+#include <QToolBar>
+
+#include <libaudcore/objects.h>
+
+struct ToolBarItem
+{
+    const char * icon_name;
+    const char * name;
+    const char * tooltip_text;
+
+    void (* callback) ();
+    void (* toggled) (bool on);
+
+    QWidget * widget;
+
+    bool sep;
+
+    QAction * * action_ptr;
+};
+
+class ToolBar : public QToolBar
+{
+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)
+    { 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)
+    { return { icon_name, name, tooltip_text, nullptr, toggled, nullptr, false, action_ptr }; }
+
+constexpr ToolBarItem ToolBarCustom (QWidget * item)
+    { return { nullptr, nullptr, nullptr, nullptr, nullptr, item }; }
+
+constexpr ToolBarItem ToolBarSeparator ()
+    { return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, true }; }
+
+#endif
diff --git a/src/resample/Makefile b/src/resample/Makefile
index b0cde15079c8..1cba05df253b 100644
--- a/src/resample/Makefile
+++ b/src/resample/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = resample${PLUGIN_SUFFIX}
 
-SRCS = resample.c
+SRCS = resample.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} -lsamplerate
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -lsamplerate
diff --git a/src/resample/resample.c b/src/resample/resample.c
deleted file mode 100644
index 5830362c0787..000000000000
--- a/src/resample/resample.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Sample Rate Converter Plugin for Audacious
- * Copyright 2010-2012 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 <stdio.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <samplerate.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.h>
-
-#define MIN_RATE 8000
-#define MAX_RATE 192000
-#define RATE_STEP 50
-
-#define RESAMPLE_ERROR(e) fprintf (stderr, "resample: %s\n", src_strerror (e))
-
-static const char * const resample_defaults[] = {
- "method", "2", /* SRC_SINC_FASTEST */
- "default-rate", "44100",
- "use-mappings", "FALSE",
- "8000", "48000",
- "16000", "48000",
- "22050", "44100",
- "44100", "44100",
- "48000", "48000",
- "96000", "96000",
- "192000", "96000",
- NULL};
-
-static SRC_STATE * state;
-static int stored_channels;
-static double ratio;
-static float * buffer;
-static int buffer_samples;
-
-bool_t resample_init (void)
-{
-    aud_config_set_defaults ("resample", resample_defaults);
-    return TRUE;
-}
-
-void resample_cleanup (void)
-{
-    if (state)
-    {
-        src_delete (state);
-        state = NULL;
-    }
-
-    g_free (buffer);
-    buffer = NULL;
-    buffer_samples = 0;
-}
-
-void resample_start (int * channels, int * rate)
-{
-    if (state)
-    {
-        src_delete (state);
-        state = NULL;
-    }
-
-    int new_rate = 0;
-
-    if (aud_get_bool ("resample", "use-mappings"))
-    {
-        char rate_s[16];
-        str_itoa (* rate, rate_s, sizeof rate_s);
-        new_rate = aud_get_int ("resample", rate_s);
-    }
-
-    if (! new_rate)
-        new_rate = aud_get_int ("resample", "default-rate");
-
-    new_rate = CLAMP (new_rate, MIN_RATE, MAX_RATE);
-
-    if (new_rate == * rate)
-        return;
-
-    int method = aud_get_int ("resample", "method");
-    int error;
-
-    if ((state = src_new (method, * channels, & error)) == NULL)
-    {
-        RESAMPLE_ERROR (error);
-        return;
-    }
-
-    stored_channels = * channels;
-    ratio = (double) new_rate / * rate;
-    * rate = new_rate;
-}
-
-void do_resample (float * * data, int * samples, bool_t finish)
-{
-    if (! state || ! * samples)
-        return;
-
-    if (buffer_samples < (int) (* samples * ratio) + 256)
-    {
-        buffer_samples = (int) (* samples * ratio) + 256;
-        buffer = g_renew (float, buffer, buffer_samples);
-    }
-
-    SRC_DATA d = {
-     .data_in = * data,
-     .input_frames = * samples / stored_channels,
-     .data_out = buffer,
-     .output_frames = buffer_samples / stored_channels,
-     .src_ratio = ratio,
-     .end_of_input = finish};
-
-    int error;
-    if ((error = src_process (state, & d)))
-    {
-        RESAMPLE_ERROR (error);
-        return;
-    }
-
-    * data = buffer;
-    * samples = stored_channels * d.output_frames_gen;
-}
-
-void resample_process (float * * data, int * samples)
-{
-    do_resample (data, samples, FALSE);
-}
-
-void resample_flush (void)
-{
-    int error;
-    if (state && (error = src_reset (state)))
-        RESAMPLE_ERROR (error);
-}
-
-void resample_finish (float * * data, int * samples)
-{
-    do_resample (data, samples, TRUE);
-    resample_flush ();
-}
-
-static const char resample_about[] =
- N_("Sample Rate Converter Plugin for Audacious\n"
-    "Copyright 2010-2012 John Lindgren");
-
-static const ComboBoxElements method_list[] = {
- {"3", N_("Skip/repeat samples")}, /* SRC_ZERO_ORDER_HOLD */
- {"4", N_("Linear interpolation")}, /* SRC_LINEAR */
- {"2", N_("Fast sinc interpolation")}, /* SRC_SINC_FASTEST */
- {"1", N_("Medium sinc interpolation")}, /* SRC_SINC_MEDIUM_QUALITY */
- {"0", N_("Best sinc interpolation")}}; /* SRC_SINC_BEST_QUALITY */
-
-static const PreferencesWidget resample_widgets[] = {
- {WIDGET_LABEL, N_("<b>Conversion</b>")},
- {WIDGET_COMBO_BOX, N_("Method:"),
-  .cfg_type = VALUE_STRING, .csect = "resample", .cname = "method",
-  .data = {.combo = {method_list, ARRAY_LEN (method_list)}}},
- {WIDGET_SPIN_BTN, N_("Rate:"),
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "default-rate",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_LABEL, N_("<b>Rate Mappings</b>")},
- {WIDGET_CHK_BTN, N_("Use rate mappings"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "resample", .cname = "use-mappings"},
- {WIDGET_SPIN_BTN, N_("8 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "8000",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("16 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "16000",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("22.05 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "22050",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("44.1 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "44100",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("48 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "48000",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("96 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "96000",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}},
- {WIDGET_SPIN_BTN, N_("192 kHz:"), .child = TRUE,
-  .cfg_type = VALUE_INT, .csect = "resample", .cname = "192000",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}}};
-
-static const PluginPreferences resample_prefs = {
- .widgets = resample_widgets,
- .n_widgets = ARRAY_LEN (resample_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Sample Rate Converter"),
-    .domain = PACKAGE,
-    .about_text = resample_about,
-    .prefs = & resample_prefs,
-    .init = resample_init,
-    .cleanup = resample_cleanup,
-    .start = resample_start,
-    .process = resample_process,
-    .flush = resample_flush,
-    .finish = resample_finish,
-    .order = 2 /* must be before crossfade */
-)
diff --git a/src/resample/resample.cc b/src/resample/resample.cc
new file mode 100644
index 000000000000..ac08630de233
--- /dev/null
+++ b/src/resample/resample.cc
@@ -0,0 +1,247 @@
+/*
+ * Sample Rate Converter Plugin for Audacious
+ * Copyright 2010-2012 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 <samplerate.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/audstrings.h>
+
+#define MIN_RATE 8000
+#define MAX_RATE 192000
+#define RATE_STEP 50
+
+#define RESAMPLE_ERROR(e) AUDERR ("%s\n", src_strerror (e))
+
+class Resampler : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Sample Rate Converter"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    /* order #2: must be before crossfade */
+    constexpr Resampler () : EffectPlugin (info, 2, false) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    bool flush (bool force);
+
+    Index<float> & process (Index<float> & data)
+        { return resample (data, false); }
+    Index<float> & finish (Index<float> & data, bool end_of_playlist)
+        { return resample (data, true); }
+
+private:
+    Index<float> & resample (Index<float> & data, bool finish);
+};
+
+EXPORT Resampler aud_plugin_instance;
+
+const char * const Resampler::defaults[] = {
+ "method", aud::numeric_string<SRC_SINC_FASTEST>::str,
+ "default-rate", "44100",
+ "use-mappings", "FALSE",
+ "8000", "48000",
+ "16000", "48000",
+ "22050", "44100",
+ "32000", "48000",
+ "44100", "44100",
+ "48000", "48000",
+ "88200", "44100",
+ "96000", "48000",
+ "176400", "44100",
+ "192000", "48000",
+ nullptr};
+
+static SRC_STATE * state;
+static int stored_channels;
+static double ratio;
+static Index<float> buffer;
+
+bool Resampler::init ()
+{
+    aud_config_set_defaults ("resample", defaults);
+    return true;
+}
+
+void Resampler::cleanup ()
+{
+    if (state)
+    {
+        src_delete (state);
+        state = nullptr;
+    }
+
+    buffer.clear ();
+}
+
+void Resampler::start (int & channels, int & rate)
+{
+    if (state)
+    {
+        src_delete (state);
+        state = nullptr;
+    }
+
+    int new_rate = 0;
+
+    if (aud_get_bool ("resample", "use-mappings"))
+        new_rate = aud_get_int ("resample", int_to_str (rate));
+
+    if (! new_rate)
+        new_rate = aud_get_int ("resample", "default-rate");
+
+    new_rate = aud::clamp (new_rate, MIN_RATE, MAX_RATE);
+
+    if (new_rate == rate)
+        return;
+
+    int method = aud_get_int ("resample", "method");
+    int error;
+
+    if ((state = src_new (method, channels, & error)) == nullptr)
+    {
+        RESAMPLE_ERROR (error);
+        return;
+    }
+
+    stored_channels = channels;
+    ratio = (double) new_rate / rate;
+    rate = new_rate;
+}
+
+Index<float> & Resampler::resample (Index<float> & data, bool finish)
+{
+    if (! state || ! data.len ())
+        return data;
+
+    buffer.resize ((int) (data.len () * ratio) + 256);
+
+    SRC_DATA d = SRC_DATA ();
+
+    d.data_in = data.begin ();
+    d.input_frames = data.len () / stored_channels;
+    d.data_out = buffer.begin ();
+    d.output_frames = buffer.len () / stored_channels;
+    d.src_ratio = ratio;
+    d.end_of_input = finish;
+
+    int error;
+    if ((error = src_process (state, & d)))
+    {
+        RESAMPLE_ERROR (error);
+        return data;
+    }
+
+    buffer.resize (stored_channels * d.output_frames_gen);
+
+    if (finish)
+        flush (true);
+
+    return buffer;
+}
+
+bool Resampler::flush (bool force)
+{
+    int error;
+    if (state && (error = src_reset (state)))
+        RESAMPLE_ERROR (error);
+
+    return true;
+}
+
+const char Resampler::about[] =
+ N_("Sample Rate Converter Plugin for Audacious\n"
+    "Copyright 2010-2012 John Lindgren");
+
+static const ComboItem method_list[] = {
+    ComboItem(N_("Skip/repeat samples"), SRC_ZERO_ORDER_HOLD),
+    ComboItem(N_("Linear interpolation"), SRC_LINEAR),
+    ComboItem(N_("Fast sinc interpolation"), SRC_SINC_FASTEST),
+    ComboItem(N_("Medium sinc interpolation"), SRC_SINC_MEDIUM_QUALITY),
+    ComboItem(N_("Best sinc interpolation"), SRC_SINC_BEST_QUALITY)
+};
+
+const PreferencesWidget Resampler::widgets[] = {
+    WidgetLabel (N_("<b>Conversion</b>")),
+    WidgetCombo (N_("Method:"),
+        WidgetInt ("resample", "method"),
+        {{method_list}}),
+    WidgetSpin (N_("Rate:"),
+        WidgetInt ("resample", "default-rate"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}),
+    WidgetLabel (N_("<b>Rate Mappings</b>")),
+    WidgetCheck (N_("Use rate mappings"),
+        WidgetBool ("resample", "use-mappings")),
+    WidgetSpin (N_("8 kHz:"),
+        WidgetInt ("resample", "8000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("16 kHz:"),
+        WidgetInt ("resample", "16000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("22.05 kHz:"),
+        WidgetInt ("resample", "22050"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("32.0 kHz:"),
+        WidgetInt ("resample", "32000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("44.1 kHz:"),
+        WidgetInt ("resample", "44100"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("48 kHz:"),
+        WidgetInt ("resample", "48000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("88.2 kHz:"),
+        WidgetInt ("resample", "88200"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("96 kHz:"),
+        WidgetInt ("resample", "96000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("176.4 kHz:"),
+        WidgetInt ("resample", "176400"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD),
+    WidgetSpin (N_("192 kHz:"),
+        WidgetInt ("resample", "192000"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")},
+        WIDGET_CHILD)
+};
+
+const PluginPreferences Resampler::prefs = {{widgets}};
diff --git a/src/scrobbler2/Makefile b/src/scrobbler2/Makefile
index a2f8fd6ea719..3bede4e57a2f 100644
--- a/src/scrobbler2/Makefile
+++ b/src/scrobbler2/Makefile
@@ -1,9 +1,9 @@
 PLUGIN = scrobbler${PLUGIN_SUFFIX}
 
-SRCS = scrobbler.c \
-	   scrobbler_communication.c \
-	   scrobbler_xml_parsing.c \
-	   config_window.c
+SRCS = scrobbler.cc \
+	   scrobbler_communication.cc \
+	   scrobbler_xml_parsing.cc \
+	   config_window.cc
 
 
 include ../../buildsys.mk
@@ -13,6 +13,8 @@ PACKAGE_NAME = audacious
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS} -Wall
 CPPFLAGS += ${PLUGIN_CPPFLAGS}  ${GTK_CFLAGS} ${GLIB_CFLAGS} ${CURL_CFLAGS} ${XML_CFLAGS} -I../..
 LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${CURL_LIBS} ${XML_LIBS}
diff --git a/src/scrobbler2/config_window.c b/src/scrobbler2/config_window.c
deleted file mode 100644
index 075ca58f271c..000000000000
--- a/src/scrobbler2/config_window.c
+++ /dev/null
@@ -1,234 +0,0 @@
-
-//external includes
-#include <gdk/gdk.h>
-//plugin includes
-#include "scrobbler.h"
-
-
-//shared variables
-bool_t          permission_check_requested   = FALSE;
-bool_t          invalidate_session_requested = FALSE;
-enum permission perm_result                  = PERMISSION_UNKNOWN;
-gchar          *username                     = NULL; /* pooled */
-
-
-//static (private) variables
-static GtkWidget *button;
-static GtkWidget *revoke_button;
-static GtkWidget *permission_status_icon;
-static GtkWidget *permission_status_label;
-
-static GtkWidget *details_label_first;
-static GtkWidget *url_button;
-static GtkWidget *details_label_second;
-
-static GtkWidget *additional_details_icon;
-static GtkWidget *additional_details_label;
-
-
-static gboolean permission_checker_thread (gpointer data) {
-    if (permission_check_requested == TRUE) {
-        //the answer hasn't arrived yet
-        return TRUE;
-
-    } else {
-        //the answer has arrived
-        g_assert(perm_result != PERMISSION_UNKNOWN);
-
-        if (perm_result == PERMISSION_ALLOWED) {
-            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "face-smile", GTK_ICON_SIZE_SMALL_TOOLBAR);
-
-            gchar *markup = g_markup_printf_escaped(_("OK. Scrobbling for user: %s"), username);
-
-            gtk_label_set_markup(GTK_LABEL(permission_status_label), markup);
-            gtk_widget_set_sensitive(revoke_button, TRUE);
-            g_free(markup);
-
-        } else if (perm_result == PERMISSION_DENIED) {
-
-            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "dialog-error", GTK_ICON_SIZE_SMALL_TOOLBAR);
-            gtk_image_set_from_icon_name(GTK_IMAGE(additional_details_icon), "dialog-information", GTK_ICON_SIZE_SMALL_TOOLBAR);
-
-
-            gtk_label_set_label(GTK_LABEL(permission_status_label), _("Permission Denied"));
-
-            gtk_label_set_markup(GTK_LABEL(details_label_first), _("Access the following link to allow Audacious to scrobble your plays:"));
-
-            gchar *url = g_markup_printf_escaped("http://www.last.fm/api/auth/?api_key=%s&token=%s", SCROBBLER_API_KEY, request_token);
-
-            gtk_link_button_set_uri(GTK_LINK_BUTTON(url_button), url);
-            gtk_button_set_label(GTK_BUTTON(url_button), url);
-            gtk_widget_show(url_button);
-            g_free(url);
-
-            gtk_label_set_markup(GTK_LABEL(details_label_second), _("Keep this window open and click 'Check Permission' again.\n"));
-
-            gtk_label_set_label(GTK_LABEL(additional_details_label),
-                                _("Don't worry. Your scrobbles are saved on your computer.\n"
-                                  "They will be submitted as soon as Audacious is allowed to do so."));
-
-        } else if (perm_result == PERMISSION_NONET) {
-            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "dialog-warning", GTK_ICON_SIZE_SMALL_TOOLBAR);
-            gtk_image_set_from_icon_name(GTK_IMAGE(additional_details_icon), "dialog-information", GTK_ICON_SIZE_SMALL_TOOLBAR);
-
-
-            gtk_label_set_label(GTK_LABEL(permission_status_label), _("Network Problem."));
-            gtk_label_set_label(GTK_LABEL(details_label_first),     _("There was a problem contacting Last.fm. Please try again later."));
-            gtk_label_set_label(GTK_LABEL(additional_details_label),
-                    _("Don't worry. Your scrobbles are saved on your computer.\n"
-                      "They will be submitted as soon as Audacious is allowed to do so."));
-        }
-
-        perm_result = PERMISSION_UNKNOWN;
-        gtk_widget_set_sensitive(button, TRUE);
-
-        return FALSE;
-    }
-}
-
-
-static void cleanup_window() {
-    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));
-
-    gtk_label_set_label(GTK_LABEL(permission_status_label), (""));
-    gtk_label_set_label(GTK_LABEL(details_label_first), "");
-    gtk_widget_hide(url_button);
-    gtk_label_set_label(GTK_LABEL(details_label_second), "");
-    gtk_label_set_label(GTK_LABEL(additional_details_label), "");
-}
-
-static void permission_checker (GtkButton *button12, gpointer data) {
-    cleanup_window();
-
-    gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "system-run", GTK_ICON_SIZE_SMALL_TOOLBAR);
-    gtk_label_set_label(GTK_LABEL(permission_status_label), _("Checking..."));
-
-    //This will make the communication thread check the permission
-    //and set the current status on the perm_result enum
-    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;
-
-    //Wake up the communication thread in case it's waiting for track plays
-    pthread_mutex_lock(&communication_mutex);
-    pthread_cond_signal(&communication_signal);
-    pthread_mutex_unlock(&communication_mutex);
-
-    //The button is clicked. Wait for the permission check to be done.
-    gdk_threads_add_timeout_seconds(1, permission_checker_thread, data);
-}
-
-static void revoke_permissions (GtkButton *revoke_button2, gpointer data) {
-    cleanup_window();
-
-    pthread_mutex_lock(&communication_mutex);
-    invalidate_session_requested = TRUE;
-
-    scrobbling_enabled = FALSE;
-    pthread_cond_signal(&communication_signal);
-    pthread_mutex_unlock(&communication_mutex);
-
-    gtk_widget_set_sensitive(button, TRUE);
-}
-
-/*
-  ,---config_box---------------------.
-  |                                  |
-  |,-permission_box----------------. |
-  || ,-buttons_box--.              | |
-  || |button        | perm_status  | |
-  || |revoke_button |              | |
-  || `--------------'              | |
-  |`-------------------------------' |
-  |                                  |
-  |,-details_box------------------.  |
-  ||details_label_first           |  |
-  ||url_button                    |  |
-  ||details_label_second          |  |
-  |`------------------------------'  |
-  |                                  |
-  |,-additional_details_box--------. |
-  ||_______________________________| |
-  |__________________________________|
-
- */
-static void *config_status_checker () {
-    GtkWidget *config_box;
-    GtkWidget *permission_box;
-    GtkWidget *buttons_box;
-    GtkWidget *details_box;
-    GtkWidget *additional_details_box;
-
-    config_box              = gtk_box_new(GTK_ORIENTATION_VERTICAL,  15);
-    permission_box          = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-    buttons_box             = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
-    details_box             = gtk_box_new(GTK_ORIENTATION_VERTICAL,   0);
-    additional_details_box  = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
-
-    permission_status_icon  = gtk_image_new();
-    permission_status_label = gtk_label_new("");
-
-    details_label_first  = gtk_label_new ("");
-    url_button           = gtk_link_button_new("");
-    details_label_second = gtk_label_new("");
-    gtk_widget_set_halign(details_label_first,  GTK_ALIGN_CENTER);
-    gtk_widget_set_halign(url_button,           GTK_ALIGN_CENTER);
-    gtk_widget_set_halign(details_label_second, GTK_ALIGN_CENTER);
-
-//    gtk_label_set_use_markup(GTK_LABEL(details_label), TRUE);
-
-    additional_details_icon  = gtk_image_new();
-    additional_details_label = gtk_label_new("");
-
-
-    g_signal_connect (button,        "clicked", G_CALLBACK (permission_checker), NULL);
-    g_signal_connect (revoke_button, "clicked", G_CALLBACK (revoke_permissions), NULL);
-
-    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(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(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;
-}
-
-
-static const PreferencesWidget config_contents[] = {
-    {
-        .type  = WIDGET_LABEL,
-        .label = N_("You need to allow Audacious to scrobble tracks to your Last.fm account.\n"),
-        .data  = { .label = {.single_line = TRUE} }
-    },
-    {
-        .type = WIDGET_CUSTOM,
-        .data = { .populate = config_status_checker }
-    }
-};
-
-const PluginPreferences configuration = {
-    .widgets = config_contents,
-    .n_widgets = ARRAY_LEN(config_contents)
-};
diff --git a/src/scrobbler2/config_window.cc b/src/scrobbler2/config_window.cc
new file mode 100644
index 000000000000..c122f625ad1b
--- /dev/null
+++ b/src/scrobbler2/config_window.cc
@@ -0,0 +1,224 @@
+
+//external includes
+#include <gdk/gdk.h>
+//plugin includes
+#include "scrobbler.h"
+
+
+//shared variables
+gboolean          permission_check_requested   = FALSE;
+gboolean          invalidate_session_requested = FALSE;
+enum permission perm_result                  = PERMISSION_UNKNOWN;
+String          username;
+
+
+//static (private) variables
+static GtkWidget *button;
+static GtkWidget *revoke_button;
+static GtkWidget *permission_status_icon;
+static GtkWidget *permission_status_label;
+
+static GtkWidget *details_label_first;
+static GtkWidget *url_button;
+static GtkWidget *details_label_second;
+
+static GtkWidget *additional_details_icon;
+static GtkWidget *additional_details_label;
+
+
+static gboolean permission_checker_thread (void * data) {
+    if (permission_check_requested == TRUE) {
+        //the answer hasn't arrived yet
+        return TRUE;
+
+    } else {
+        //the answer has arrived
+        g_assert(perm_result != PERMISSION_UNKNOWN);
+
+        if (perm_result == PERMISSION_ALLOWED) {
+            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "face-smile", GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+            char *markup = g_markup_printf_escaped(_("OK. Scrobbling for user: %s"),
+             (const char *)username);
+
+            gtk_label_set_markup(GTK_LABEL(permission_status_label), markup);
+            gtk_widget_set_sensitive(revoke_button, TRUE);
+            g_free(markup);
+
+        } else if (perm_result == PERMISSION_DENIED) {
+
+            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "dialog-error", GTK_ICON_SIZE_SMALL_TOOLBAR);
+            gtk_image_set_from_icon_name(GTK_IMAGE(additional_details_icon), "dialog-information", GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+
+            gtk_label_set_label(GTK_LABEL(permission_status_label), _("Permission Denied"));
+
+            gtk_label_set_markup(GTK_LABEL(details_label_first), _("Access the following link to allow Audacious to scrobble your plays:"));
+
+            char *url = g_markup_printf_escaped("http://www.last.fm/api/auth/?api_key=%s&token=%s",
+             SCROBBLER_API_KEY, (const char *)request_token);
+
+            gtk_link_button_set_uri(GTK_LINK_BUTTON(url_button), url);
+            gtk_button_set_label(GTK_BUTTON(url_button), url);
+            gtk_widget_show(url_button);
+            g_free(url);
+
+            gtk_label_set_markup(GTK_LABEL(details_label_second), _("Keep this window open and click 'Check Permission' again.\n"));
+
+            gtk_label_set_label(GTK_LABEL(additional_details_label),
+                                _("Don't worry. Your scrobbles are saved on your computer.\n"
+                                  "They will be submitted as soon as Audacious is allowed to do so."));
+
+        } else if (perm_result == PERMISSION_NONET) {
+            gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "dialog-warning", GTK_ICON_SIZE_SMALL_TOOLBAR);
+            gtk_image_set_from_icon_name(GTK_IMAGE(additional_details_icon), "dialog-information", GTK_ICON_SIZE_SMALL_TOOLBAR);
+
+
+            gtk_label_set_label(GTK_LABEL(permission_status_label), _("Network Problem."));
+            gtk_label_set_label(GTK_LABEL(details_label_first),     _("There was a problem contacting Last.fm. Please try again later."));
+            gtk_label_set_label(GTK_LABEL(additional_details_label),
+                    _("Don't worry. Your scrobbles are saved on your computer.\n"
+                      "They will be submitted as soon as Audacious is allowed to do so."));
+        }
+
+        perm_result = PERMISSION_UNKNOWN;
+        gtk_widget_set_sensitive(button, TRUE);
+
+        return FALSE;
+    }
+}
+
+
+static void cleanup_window() {
+    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));
+
+    gtk_label_set_label(GTK_LABEL(permission_status_label), (""));
+    gtk_label_set_label(GTK_LABEL(details_label_first), "");
+    gtk_widget_hide(url_button);
+    gtk_label_set_label(GTK_LABEL(details_label_second), "");
+    gtk_label_set_label(GTK_LABEL(additional_details_label), "");
+}
+
+static void permission_checker (GtkButton *button12, void * data) {
+    cleanup_window();
+
+    gtk_image_set_from_icon_name(GTK_IMAGE(permission_status_icon), "system-run", GTK_ICON_SIZE_SMALL_TOOLBAR);
+    gtk_label_set_label(GTK_LABEL(permission_status_label), _("Checking..."));
+
+    //This will make the communication thread check the permission
+    //and set the current status on the perm_result enum
+    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;
+
+    //Wake up the communication thread in case it's waiting for track plays
+    pthread_mutex_lock(&communication_mutex);
+    pthread_cond_signal(&communication_signal);
+    pthread_mutex_unlock(&communication_mutex);
+
+    //The button is clicked. Wait for the permission check to be done.
+    gdk_threads_add_timeout_seconds(1, permission_checker_thread, data);
+}
+
+static void revoke_permissions (GtkButton *revoke_button2, void * data) {
+    cleanup_window();
+
+    pthread_mutex_lock(&communication_mutex);
+    invalidate_session_requested = TRUE;
+
+    scrobbling_enabled = FALSE;
+    pthread_cond_signal(&communication_signal);
+    pthread_mutex_unlock(&communication_mutex);
+
+    gtk_widget_set_sensitive(button, TRUE);
+}
+
+/*
+  ,---config_box---------------------.
+  |                                  |
+  |,-permission_box----------------. |
+  || ,-buttons_box--.              | |
+  || |button        | perm_status  | |
+  || |revoke_button |              | |
+  || `--------------'              | |
+  |`-------------------------------' |
+  |                                  |
+  |,-details_box------------------.  |
+  ||details_label_first           |  |
+  ||url_button                    |  |
+  ||details_label_second          |  |
+  |`------------------------------'  |
+  |                                  |
+  |,-additional_details_box--------. |
+  ||_______________________________| |
+  |__________________________________|
+
+ */
+static void *config_status_checker () {
+    GtkWidget *config_box;
+    GtkWidget *permission_box;
+    GtkWidget *buttons_box;
+    GtkWidget *details_box;
+    GtkWidget *additional_details_box;
+
+    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);
+
+    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);
+
+    permission_status_icon  = gtk_image_new();
+    permission_status_label = gtk_label_new("");
+
+    details_label_first  = gtk_label_new ("");
+    url_button           = gtk_link_button_new("");
+    details_label_second = gtk_label_new("");
+
+    gtk_widget_hide(url_button);
+    gtk_widget_set_no_show_all(url_button, TRUE);
+
+    additional_details_icon  = gtk_image_new();
+    additional_details_label = gtk_label_new("");
+
+
+    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(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(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);
+
+    return config_box;
+}
+
+
+static const PreferencesWidget config_contents[] = {
+    WidgetLabel (N_("You need to allow Audacious to scrobble tracks to your Last.fm account.\n")),
+    WidgetCustomGTK (config_status_checker)
+};
+
+const PluginPreferences configuration = {{config_contents}};
diff --git a/src/scrobbler2/scrobbler.c b/src/scrobbler2/scrobbler.c
deleted file mode 100644
index 527468897deb..000000000000
--- a/src/scrobbler2/scrobbler.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Scrobbler Plugin v2.0 for Audacious by Pitxyoki
- *
- * Copyright 2012-2013 Luís Picciochi Oliveira <Pitxyoki at Gmail.com>
- *
- * This plugin is part of the Audacious Media Player.
- * It is licensed under the GNU General Public License, version 3.
- */
-
-#include <glib/gstdio.h>
-
-//audacious includes
-#include <audacious/plugin.h>
-#include <audacious/drct.h>
-#include <audacious/playlist.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-
-
-//plugin includes
-#include "scrobbler.h"
-
-
-//shared variables
-bool_t scrobbler_running        = TRUE;
-bool_t migrate_config_requested = FALSE;
-bool_t now_playing_requested    = FALSE;
-Tuple *now_playing_track        = NULL;
-
-pthread_mutex_t communication_mutex = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t communication_signal = PTHREAD_COND_INITIALIZER;
-pthread_mutex_t log_access_mutex = PTHREAD_MUTEX_INITIALIZER;
-gchar *session_key = NULL; /* pooled */
-gchar *request_token = NULL; /* pooled */
-
-
-//static (private) variables
-static Tuple * playing_track       = NULL;
-//all times are in microseconds
-static  gint64 timestamp           = 0;
-static  gint64 play_started_at     = 0;
-static  gint64 pause_started_at    = 0;
-static  gint64 time_until_scrobble = 0;
-static   guint queue_function_ID   = 0;
-
-static pthread_t communicator;
-
-static void cleanup_current_track(void) {
-
-    timestamp = 0;
-    play_started_at = 0;
-    pause_started_at = 0;
-    time_until_scrobble = 0;
-    if (queue_function_ID != 0) {
-        gboolean success = g_source_remove(queue_function_ID);
-        queue_function_ID = 0;
-        if (!success) {
-            AUDDBG("BUG: No success on g_source_remove!\n");
-        }
-    }
-    if (playing_track != NULL) {
-        tuple_unref(playing_track);
-        playing_track = NULL;
-    }
-}
-
-char *clean_string(char *string) {
-    if (!string)
-        return str_get("");
-
-    SCOPY(temp, string);
-    str_replace_char(temp, '\t', ' ');
-    str_unref(string);
-    return str_get(temp);
-}
-
-static gboolean queue_track_to_scrobble (gpointer data) {
-    AUDDBG("The playing track is going to be ENQUEUED!\n.");
-
-    char *queuepath = g_strconcat(aud_get_path(AUD_PATH_USER_DIR),"/scrobbler.log", NULL);
-
-    char *artist = clean_string(tuple_get_str(playing_track, FIELD_ARTIST));
-    char *title  = clean_string(tuple_get_str(playing_track, FIELD_TITLE));
-    char *album  = clean_string(tuple_get_str(playing_track, FIELD_ALBUM));
-
-    int track  = tuple_get_int(playing_track, FIELD_TRACK_NUMBER);
-    int length = tuple_get_int(playing_track, FIELD_LENGTH);
-
-    //artist, title and length are required for a successful scrobble
-    if (artist[0] && title[0] && length > 0) {
-        char *track_str = (track > 0) ? int_to_str(track) : str_get("");
-
-        pthread_mutex_lock(&log_access_mutex);
-        FILE *f = g_fopen(queuepath, "a");
-
-        if (f == NULL) {
-            perror("fopen");
-        } else {
-            //This isn't exactly the scrobbler.log format because the header
-            //is missing, but we're sticking to it anyway...
-            //See http://www.audioscrobbler.net/wiki/Portable_Player_Logging
-            if (fprintf(f, "%s\t%s\t%s\t%s\t%i\tL\t%"G_GINT64_FORMAT"\n",
-             artist, album, title, track_str, length / 1000, timestamp) < 0) {
-                perror("fprintf");
-            } else {
-                pthread_mutex_lock(&communication_mutex);
-                pthread_cond_signal(&communication_signal);
-                pthread_mutex_unlock(&communication_mutex);
-            }
-            fclose(f);
-        }
-        pthread_mutex_unlock(&log_access_mutex);
-
-        str_unref(track_str);
-    }
-    g_free(queuepath);
-    str_unref(artist);
-    str_unref(title);
-    str_unref(album);
-
-    cleanup_current_track();
-    return FALSE;
-}
-
-
-static void stopped (void *hook_data, void *user_data) {
-    // Called when pressing STOP and when the playlist ends.
-    cleanup_current_track();
-}
-
-static void ended (void *hook_data, void *user_data) {
-    //Called when when a track finishes playing.
-
-    //TODO: hic sunt race conditions
-    if (playing_track != NULL && (g_get_monotonic_time() > (play_started_at + 30*G_USEC_PER_SEC)) ) {
-      //This is an odd situation when the track's real length doesn't correspond to the length reported by the player.
-      //If we are at the end of the track, it is longer than 30 seconds and it wasn't scrobbled, we scrobble it by then.
-
-      if (queue_function_ID != 0) {
-        gboolean success = g_source_remove(queue_function_ID);
-        queue_function_ID = 0;
-        if (!success) {
-          AUDDBG("BUG or race condition: Could not remove source.\n");
-        } else {
-          queue_track_to_scrobble(NULL);
-        }
-      }
-    }
-
-    cleanup_current_track();
-}
-
-static void ready (void *hook_data, void *user_data) {
-    cleanup_current_track();
-
-    Tuple *current_track = aud_playlist_entry_get_tuple(aud_playlist_get_playing(), aud_playlist_get_position(aud_playlist_get_playing()), FALSE);
-
-    int duration_seconds = tuple_get_int(current_track, FIELD_LENGTH) / 1000;
-    if (duration_seconds <= 30) {
-        tuple_unref(current_track);
-        return;
-    }
-
-    pthread_mutex_lock(&communication_mutex);
-    now_playing_track = tuple_ref(current_track);
-    now_playing_requested = TRUE;
-    pthread_cond_signal(&communication_signal);
-    pthread_mutex_unlock(&communication_mutex);
-
-    time_until_scrobble = (((gint64)duration_seconds)*G_USEC_PER_SEC) / 2;
-    if (time_until_scrobble > 4*60*G_USEC_PER_SEC) {
-        time_until_scrobble = 4*60*G_USEC_PER_SEC;
-    }
-    timestamp = g_get_real_time() / G_USEC_PER_SEC;
-    play_started_at = g_get_monotonic_time();
-    playing_track = current_track;
-
-    queue_function_ID = g_timeout_add_seconds(time_until_scrobble / G_USEC_PER_SEC, (GSourceFunc) queue_track_to_scrobble, NULL);
-
-}
-
-static void paused (void *hook_data, void *user_data) {
-    if (playing_track == NULL) {
-        //This happens when audacious is started in paused mode
-        return;
-    }
-
-    gboolean success = g_source_remove(queue_function_ID);
-    queue_function_ID = 0;
-    if (!success) {
-        AUDDBG("BUG: Could not remove source.\n");
-        return;
-    }
-
-    pause_started_at = g_get_monotonic_time();
-}
-
-static void unpaused (void *hook_data, void *user_data) {
-
-    if (playing_track == NULL
-        || pause_started_at == 0) { //TODO: audacious was started with a paused track.
-        return;
-    }
-    time_until_scrobble = time_until_scrobble - (pause_started_at - play_started_at);
-
-    queue_function_ID = g_timeout_add_seconds(time_until_scrobble / G_USEC_PER_SEC, (GSourceFunc) queue_track_to_scrobble, NULL);
-
-    pause_started_at = 0;
-    play_started_at = g_get_monotonic_time();
-}
-
-
-
-static bool_t scrobbler_init (void) {
-    // Initialize libXML and check potential ABI mismatches between
-    // the version it was compiled for and the actual libXML in use
-    LIBXML_TEST_VERSION
-
-    if (scrobbler_communication_init() == FALSE) {
-        aud_interface_show_error(_("The Scrobbler plugin could not be started.\n"
-                                   "There might be a problem with your installation."));
-        return FALSE;
-    }
-
-    session_key = aud_get_str("scrobbler", "session_key");
-    if (!session_key[0])
-        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
-    //Migration from the old scrobbler config
-    if (!session_key[0]) {
-      //We haven't been configured yet
-
-      char *migrated = aud_get_str("scrobbler", "migrated");
-      if (strcmp(migrated, "true") != 0) {
-        //We haven't been migrated yet
-
-        char *oldpass = aud_get_str("audioscrobbler","password");
-        if (oldpass[0]) {
-
-          char *olduser = aud_get_str("audioscrobbler","username");
-          if (olduser[0]) {
-            //And the old scrobbler was configured
-
-            scrobbling_enabled = FALSE;
-            migrate_config_requested = TRUE;
-          }
-          str_unref(olduser);
-        }
-        str_unref(oldpass);
-      }
-      str_unref(migrated);
-    }
-
-
-
-    pthread_create(&communicator, NULL, scrobbling_thread, NULL);
-
-    hook_associate("playback stop", (HookFunction) stopped, NULL);
-    hook_associate("playback end", (HookFunction) ended, NULL);
-    hook_associate("playback ready", (HookFunction) ready, NULL);
-    hook_associate("playback pause", (HookFunction) paused, NULL);
-    hook_associate("playback unpause", (HookFunction) unpaused, NULL);
-    return TRUE;
-}
-
-static void scrobbler_cleanup (void) {
-
-    hook_dissociate("playback stop", (HookFunction) stopped);
-    hook_dissociate("playback end", (HookFunction) ended);
-    hook_dissociate("playback ready", (HookFunction) ready);
-    hook_dissociate("playback pause", (HookFunction) paused);
-    hook_dissociate("playback unpause", (HookFunction) unpaused);
-
-    cleanup_current_track();
-
-    scrobbling_enabled = FALSE;
-    scrobbler_running  = FALSE;
-    pthread_mutex_lock(&communication_mutex);
-    pthread_cond_signal(&communication_signal);
-    pthread_mutex_unlock(&communication_mutex);
-
-    pthread_join(communicator, NULL);
-
-    str_unref(request_token);
-    str_unref(session_key);
-    str_unref(username);
-    request_token = NULL;
-    session_key   = NULL;
-    username      = NULL;
-    scrobbler_running = TRUE;
-}
-
-static const char scrobbler_about[] =
- N_("Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n\n"
-    "Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n\n"
-    "Thanks to John Lindgren for giving me a hand at the beginning of this project.\n\n");
-
-
-AUD_GENERAL_PLUGIN (
-    .name = N_("Scrobbler 2.0"),
-    .domain = PACKAGE,
-    .about_text = scrobbler_about,
-    .init = scrobbler_init,
-    .cleanup = scrobbler_cleanup,
-    .prefs = &configuration //see config_window.c
-)
diff --git a/src/scrobbler2/scrobbler.cc b/src/scrobbler2/scrobbler.cc
new file mode 100644
index 000000000000..f930b68cd15d
--- /dev/null
+++ b/src/scrobbler2/scrobbler.cc
@@ -0,0 +1,291 @@
+/*
+ * Scrobbler Plugin v2.0 for Audacious by Pitxyoki
+ *
+ * Copyright 2012-2013 Luís Picciochi Oliveira <Pitxyoki at Gmail.com>
+ *
+ * This plugin is part of the Audacious Media Player.
+ * It is licensed under the GNU General Public License, version 3.
+ */
+
+#include <glib/gstdio.h>
+
+//audacious includes
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+
+
+//plugin includes
+#include "scrobbler.h"
+
+class Scrobbler : public GeneralPlugin
+{
+public:
+    static const char about[];
+
+    static constexpr PluginInfo info = {
+        N_("Scrobbler 2.0"),
+        PACKAGE,
+        about,
+        & configuration
+    };
+
+    constexpr Scrobbler () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT Scrobbler aud_plugin_instance;
+
+//shared variables
+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;
+pthread_cond_t communication_signal = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t log_access_mutex = PTHREAD_MUTEX_INITIALIZER;
+String session_key;
+String request_token;
+
+
+//static (private) variables
+static Tuple playing_track;
+//all times are in microseconds
+static  int64_t timestamp           = 0;
+static  int64_t play_started_at     = 0;
+static  int64_t pause_started_at    = 0;
+static  int64_t time_until_scrobble = 0;
+static   unsigned queue_function_ID   = 0;
+
+static pthread_t communicator;
+
+static void cleanup_current_track(void) {
+
+    timestamp = 0;
+    play_started_at = 0;
+    pause_started_at = 0;
+    time_until_scrobble = 0;
+    if (queue_function_ID != 0) {
+        gboolean success = g_source_remove(queue_function_ID);
+        queue_function_ID = 0;
+        if (!success) {
+            AUDDBG("BUG: No success on g_source_remove!\n");
+        }
+    }
+    playing_track = Tuple ();
+}
+
+StringBuf clean_string (const char *string) {
+    StringBuf temp = str_copy (string ? string : "");
+    str_replace_char (temp, '\t', ' ');
+    return temp;
+}
+
+static gboolean queue_track_to_scrobble (void * data) {
+    AUDDBG("The playing track is going to be ENQUEUED!\n.");
+
+    char *queuepath = g_strconcat(aud_get_path(AudPath::UserDir),"/scrobbler.log", nullptr);
+
+    StringBuf artist = clean_string (playing_track.get_str (Tuple::Artist));
+    StringBuf title  = clean_string (playing_track.get_str (Tuple::Title));
+    StringBuf album  = clean_string (playing_track.get_str (Tuple::Album));
+
+    int track  = playing_track.get_int (Tuple::Track);
+    int length = playing_track.get_int (Tuple::Length);
+
+    //artist, title and length are required for a successful scrobble
+    if (artist[0] && title[0] && length > 0) {
+        StringBuf track_str = (track > 0) ? int_to_str (track) : StringBuf (0);
+
+        pthread_mutex_lock(&log_access_mutex);
+        FILE *f = g_fopen(queuepath, "a");
+
+        if (f == nullptr) {
+            perror("fopen");
+        } else {
+            //This isn't exactly the scrobbler.log format because the header
+            //is missing, but we're sticking to it anyway...
+            //See http://www.audioscrobbler.net/wiki/Portable_Player_Logging
+            if (fprintf(f, "%s\t%s\t%s\t%s\t%i\tL\t%" G_GINT64_FORMAT "\n",
+             (const char *)artist, (const char *)album, (const char *)title,
+             (const char *)track_str, length / 1000, timestamp) < 0) {
+                perror("fprintf");
+            } else {
+                pthread_mutex_lock(&communication_mutex);
+                pthread_cond_signal(&communication_signal);
+                pthread_mutex_unlock(&communication_mutex);
+            }
+            fclose(f);
+        }
+        pthread_mutex_unlock(&log_access_mutex);
+    }
+    g_free(queuepath);
+    cleanup_current_track();
+    return FALSE;
+}
+
+
+static void stopped (void *hook_data, void *user_data) {
+    // Called when pressing STOP and when the playlist ends.
+    cleanup_current_track();
+}
+
+static void ended (void *hook_data, void *user_data) {
+    //Called when when a track finishes playing.
+
+    //TODO: hic sunt race conditions
+    if (playing_track && (g_get_monotonic_time() > (play_started_at + 30*G_USEC_PER_SEC)) ) {
+      //This is an odd situation when the track's real length doesn't correspond to the length reported by the player.
+      //If we are at the end of the track, it is longer than 30 seconds and it wasn't scrobbled, we scrobble it by then.
+
+      if (queue_function_ID != 0) {
+        gboolean success = g_source_remove(queue_function_ID);
+        queue_function_ID = 0;
+        if (!success) {
+          AUDDBG("BUG or race condition: Could not remove source.\n");
+        } else {
+          queue_track_to_scrobble(nullptr);
+        }
+      }
+    }
+
+    cleanup_current_track();
+}
+
+static void ready (void *hook_data, void *user_data) {
+    cleanup_current_track();
+
+    Tuple current_track = aud_drct_get_tuple();
+
+    int duration_seconds = current_track.get_int (Tuple::Length) / 1000;
+    if (duration_seconds <= 30)
+        return;
+
+    pthread_mutex_lock(&communication_mutex);
+    now_playing_track = current_track.ref ();
+    now_playing_requested = TRUE;
+    pthread_cond_signal(&communication_signal);
+    pthread_mutex_unlock(&communication_mutex);
+
+    time_until_scrobble = (((int64_t)duration_seconds)*G_USEC_PER_SEC) / 2;
+    if (time_until_scrobble > 4*60*G_USEC_PER_SEC) {
+        time_until_scrobble = 4*60*G_USEC_PER_SEC;
+    }
+    timestamp = g_get_real_time() / G_USEC_PER_SEC;
+    play_started_at = g_get_monotonic_time();
+    playing_track = std::move (current_track);
+
+    queue_function_ID = g_timeout_add_seconds(time_until_scrobble / G_USEC_PER_SEC, (GSourceFunc) queue_track_to_scrobble, nullptr);
+
+}
+
+static void paused (void *hook_data, void *user_data) {
+    if (! playing_track) {
+        //This happens when audacious is started in paused mode
+        return;
+    }
+
+    gboolean success = g_source_remove(queue_function_ID);
+    queue_function_ID = 0;
+    if (!success) {
+        AUDDBG("BUG: Could not remove source.\n");
+        return;
+    }
+
+    pause_started_at = g_get_monotonic_time();
+}
+
+static void unpaused (void *hook_data, void *user_data) {
+
+    if (! playing_track
+        || pause_started_at == 0) { //TODO: audacious was started with a paused track.
+        return;
+    }
+    time_until_scrobble = time_until_scrobble - (pause_started_at - play_started_at);
+
+    queue_function_ID = g_timeout_add_seconds(time_until_scrobble / G_USEC_PER_SEC, (GSourceFunc) queue_track_to_scrobble, nullptr);
+
+    pause_started_at = 0;
+    play_started_at = g_get_monotonic_time();
+}
+
+bool Scrobbler::init ()
+{
+    // Initialize libXML and check potential ABI mismatches between
+    // the version it was compiled for and the actual libXML in use
+    LIBXML_TEST_VERSION
+
+    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;
+    }
+
+    session_key = aud_get_str("scrobbler", "session_key");
+    if (!session_key[0])
+        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
+    //Migration from the old scrobbler config
+    if (!session_key[0]) {
+      //We haven't been configured yet
+
+      String migrated = aud_get_str("scrobbler", "migrated");
+      if (strcmp(migrated, "true") != 0) {
+        //We haven't been migrated yet
+
+        String oldpass = aud_get_str("audioscrobbler","password");
+        String olduser = aud_get_str("audioscrobbler","username");
+        if (oldpass[0] && olduser[0]) {
+          //And the old scrobbler was configured
+
+          scrobbling_enabled = FALSE;
+          migrate_config_requested = TRUE;
+        }
+      }
+    }
+
+    pthread_create(&communicator, nullptr, scrobbling_thread, nullptr);
+
+    hook_associate("playback stop", (HookFunction) stopped, nullptr);
+    hook_associate("playback end", (HookFunction) ended, nullptr);
+    hook_associate("playback ready", (HookFunction) ready, nullptr);
+    hook_associate("playback pause", (HookFunction) paused, nullptr);
+    hook_associate("playback unpause", (HookFunction) unpaused, nullptr);
+    return TRUE;
+}
+
+void Scrobbler::cleanup ()
+{
+    hook_dissociate("playback stop", (HookFunction) stopped);
+    hook_dissociate("playback end", (HookFunction) ended);
+    hook_dissociate("playback ready", (HookFunction) ready);
+    hook_dissociate("playback pause", (HookFunction) paused);
+    hook_dissociate("playback unpause", (HookFunction) unpaused);
+
+    cleanup_current_track();
+
+    scrobbling_enabled = FALSE;
+    scrobbler_running  = FALSE;
+    pthread_mutex_lock(&communication_mutex);
+    pthread_cond_signal(&communication_signal);
+    pthread_mutex_unlock(&communication_mutex);
+
+    pthread_join(communicator, nullptr);
+
+    request_token = String();
+    session_key = String();
+    username = String();
+    scrobbler_running = TRUE;
+}
+
+const char Scrobbler::about[] =
+ N_("Audacious Scrobbler Plugin 2.0 by Pitxyoki,\n\n"
+    "Copyright © 2012-2013 Luís M. Picciochi Oliveira <Pitxyoki at Gmail.com>\n\n"
+    "Thanks to John Lindgren for giving me a hand at the beginning of this project.\n\n");
diff --git a/src/scrobbler2/scrobbler.h b/src/scrobbler2/scrobbler.h
index 9e162ec133d7..aa7db765cdc1 100644
--- a/src/scrobbler2/scrobbler.h
+++ b/src/scrobbler2/scrobbler.h
@@ -18,10 +18,10 @@
 #include <gtk/gtk.h>
 
 //audacious includes
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/debug.h>
-#include <audacious/preferences.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/tuple.h>
 
 #define SCROBBLER_API_KEY "4b4f73bda181868353f9b438604adf52"
 #define SCROBBLER_SHARED_SECRET "716cc0a784bb62835de5bd674e65eb57"
@@ -37,8 +37,8 @@ extern enum permission {
     PERMISSION_NONET
 } perm_result;
 
-extern bool_t scrobbler_running;
-extern bool_t scrobbling_enabled;
+extern gboolean scrobbler_running;
+extern gboolean scrobbling_enabled;
 
 
 //used to tell the scrobbling thread that there's something to do:
@@ -55,41 +55,41 @@ extern pthread_mutex_t log_access_mutex;
  */
 
 //TRUE when a permission check is being requested
-extern bool_t permission_check_requested;
-extern bool_t invalidate_session_requested;
+extern gboolean permission_check_requested;
+extern gboolean invalidate_session_requested;
 
 //Migrate the settings from the old scrobbler
-extern bool_t migrate_config_requested;
+extern gboolean migrate_config_requested;
 
 //Send "now playing"
-extern bool_t now_playing_requested;
-extern Tuple *now_playing_track;
+extern gboolean now_playing_requested;
+extern Tuple now_playing_track;
 
 
 
 
 //scrobbler_communication.c
-extern bool_t   scrobbler_communication_init();
-extern gpointer scrobbling_thread(gpointer data);
+extern gboolean   scrobbler_communication_init();
+extern void * scrobbling_thread(void * data);
 
 
 
 /* Internal stuff */
 //Data sent to the XML parser
-extern gchar *received_data;
+extern char *received_data;
 extern size_t received_data_size;
 
 //Data filled by the XML parser
-extern gchar *request_token; /* pooled */
-extern gchar *session_key; /* pooled */
-extern gchar *username; /* pooled */
+extern String request_token;
+extern String session_key;
+extern String username;
 
 //scrobbler_xml_parsing.c
-extern bool_t read_authentication_test_result(char **error_code, char **error_detail);
-extern bool_t read_token(char **error_code, char **error_detail);
-extern bool_t read_session_key(char **error_code, char **error_detail);
-extern bool_t read_scrobble_result(char **error_code, char **error_detail, bool_t *ignored, char **ignored_code);
+extern gboolean read_authentication_test_result(String &error_code, String &error_detail);
+extern gboolean read_token(String &error_code, String &error_detail);
+extern gboolean read_session_key(String &error_code, String &error_detail);
+extern gboolean read_scrobble_result(String &error_code, String &error_detail, gboolean *ignored, String &ignored_code);
 
 //scrobbler.c
-extern char *clean_string(char *string);
+extern StringBuf clean_string(const char *string);
 #endif /* SCROBBLER_H_ */
diff --git a/src/scrobbler2/scrobbler_communication.c b/src/scrobbler2/scrobbler_communication.c
deleted file mode 100644
index 381fefaa30fd..000000000000
--- a/src/scrobbler2/scrobbler_communication.c
+++ /dev/null
@@ -1,789 +0,0 @@
-
-//external includes
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <curl/curl.h>
-
-#include <libaudcore/audstrings.h>
-
-//plugin includes
-#include "scrobbler.h"
-
-typedef struct {
-    gchar *paramName;
-    gchar *argument;
-} API_Parameter;
-
-static CURL *curlHandle = NULL;     //global handle holding cURL options
-
-bool_t scrobbling_enabled = TRUE;
-
-//shared variables
-gchar *received_data = NULL;   //Holds the result of the last request made to last.fm
-size_t received_data_size = 0; //Holds the size of the received_data buffer
-
-
-
-// The cURL callback function to store the received data from the last.fm servers.
-static size_t result_callback (void *buffer, size_t size, size_t nmemb, void *userp) {
-
-    const size_t len = size*nmemb;
-
-    gchar *temp_data = realloc(received_data, received_data_size + len + 1);
-
-    if (temp_data == NULL) {
-      return 0;
-    } else {
-      received_data = temp_data;
-    }
-
-    memcpy(received_data + received_data_size, buffer, len);
-
-    received_data_size += len;
-
-    return len;
-}
-
-static int scrobbler_compare_API_Parameters(const void *a, const void *b) {
-    return g_strcmp0(((const API_Parameter *) a)->paramName, ((const API_Parameter *) b)->paramName);
-}
-
-static char *scrobbler_get_signature(int nparams, API_Parameter *parameters) {
-    qsort(parameters, nparams, sizeof(API_Parameter), scrobbler_compare_API_Parameters);
-
-    char *all_params = NULL;
-    gchar *result = NULL;
-    gchar *api_sig = NULL;
-    size_t api_sig_length = strlen(SCROBBLER_SHARED_SECRET);
-
-    for (gint i = 0; i < nparams; i++) {
-        api_sig_length += strlen(parameters[i].paramName) + strlen(parameters[i].argument);
-    }
-    all_params = g_new0(gchar, api_sig_length);
-
-    for (int i = 0; i < nparams; i++) {
-        strcat(all_params, parameters[i].paramName);
-        strcat(all_params, parameters[i].argument);
-    }
-
-    api_sig = g_strconcat(all_params, SCROBBLER_SHARED_SECRET, NULL);
-    g_free(all_params);
-
-
-    result = g_compute_checksum_for_string(G_CHECKSUM_MD5, api_sig, -1);
-    g_free(api_sig);
-    return result;
-}
-
-
-
-
-/*
- * n_args should count with the given authentication parameters
- * At most 2: api_key, session_key.
- * api_sig (checksum) is always included, be it necessary or not
- * Example usage:
- *   create_message_to_lastfm("track.scrobble", 5
- *        "artist", "Artist Name", "track", "Track Name", "timestamp", time(NULL),
- *        "api_key", SCROBBLER_API_KEY, "sk", session_key);
- *
- * Returns NULL if an error occurrs
- */
-static gchar *create_message_to_lastfm (char *method_name, int n_args, ...) {
-    //TODO: Improve this f-ugly mess.
-    gchar *result = NULL;
-
-    //parameters to be sent to the get_signature() function
-    API_Parameter signable_params[n_args+1];
-    signable_params[0].paramName = g_strdup("method");
-    signable_params[0].argument  = g_strdup(method_name);
-
-    size_t msg_size = 2; // First '=' and final '\0'
-    msg_size = msg_size + strlen("method") + strlen(method_name);
-
-    va_list vl;
-    va_start(vl, n_args);
-    for (int i = 0; i < n_args; i++) {
-
-        signable_params[i+1].paramName = g_strdup(va_arg(vl, gchar *));
-        signable_params[i+1].argument  = g_strdup(va_arg(vl, gchar *));
-
-        msg_size += strlen( signable_params[i+1].paramName );
-        msg_size += strlen( signable_params[i+1].argument );
-        msg_size += 2; //Counting '&' and '='
-    }
-    va_end(vl);
-
-    gchar *aux;
-    result = g_strconcat("method=", method_name, NULL);
-    char *escaped_argument;
-
-    for (int i = 0; i < n_args; i++) {
-        escaped_argument = curl_easy_escape(curlHandle, signable_params[i+1].argument, 0);
-
-        aux = g_strdup_printf("%s&%s=%s", result, signable_params[i+1].paramName, escaped_argument);
-        g_free(result);
-        curl_free(escaped_argument);
-        result = aux;
-    }
-
-    gchar *api_sig = scrobbler_get_signature(n_args+1, signable_params);
-
-    aux = g_strdup_printf("%s&api_sig=%s", result, api_sig);
-    result = aux;
-
-    AUDDBG("FINAL message: %s.\n", result);
-    g_free(api_sig);
-    for (int i = 0; i < n_args+1; i++) {
-        g_free(signable_params[i].paramName);
-        g_free(signable_params[i].argument);
-    }
-
-    return result;
-}
-
-
-static bool_t send_message_to_lastfm(gchar *data) {
-    AUDDBG("This message will be sent to last.fm:\n%s\n%%%%End of message%%%%\n", data);//Enter?\n", data);
-    curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS, data);
-    CURLcode curl_requests_result = curl_easy_perform(curlHandle);
-
-    if (curl_requests_result != CURLE_OK) {
-        AUDDBG("Could not communicate with last.fm: %s.\n", curl_easy_strerror(curl_requests_result));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-//returns:
-// FALSE if there was a network problem
-// TRUE otherwise (request_token must be checked)
-static bool_t scrobbler_request_token() {
-    gchar *tokenmsg = create_message_to_lastfm("auth.getToken",
-                                              1,
-                                              "api_key", SCROBBLER_API_KEY
-                                             );
-
-    if (send_message_to_lastfm(tokenmsg) == FALSE) {
-        AUDDBG("Could not send token request to last.fm.\n");
-        g_free(tokenmsg);
-        return FALSE;
-    }
-
-    bool_t success = TRUE;
-    gchar *error_code = NULL;
-    gchar *error_detail = NULL;
-
-    if (read_token(&error_code, &error_detail) == FALSE) {
-        success = FALSE;
-        if (error_code != NULL && g_strcmp0(error_code, "8")) {
-            //error code 8: There was an error granting the request token. Please try again later
-            str_unref(request_token);
-            request_token = NULL;
-        }
-    }
-
-    str_unref(error_code);
-    str_unref(error_detail);
-    return success;
-}
-
-
-static bool_t update_session_key() {
-    bool_t result = TRUE;
-    gchar *error_code = NULL;
-    gchar *error_detail = NULL;
-
-    if (read_session_key(&error_code, &error_detail) == FALSE) {
-        if (error_code != NULL && (
-                g_strcmp0(error_code,  "4") == 0 || //invalid token
-                g_strcmp0(error_code, "14") == 0 || //token not authorized
-                g_strcmp0(error_code, "15") == 0    //token expired
-            )) {
-            AUDDBG("error code CAUGHT: %s\n", error_code);
-            str_unref(session_key);
-            session_key = NULL;
-            result = TRUE;
-        } else {
-            result= FALSE;
-        }
-    }
-
-    aud_set_str("scrobbler", "session_key", session_key ? session_key : "");
-
-    str_unref(error_code);
-    str_unref(error_detail);
-    return result;
-}
-
-//returns:
-// FALSE if there was a network problem
-// TRUE otherwise (session_key must be checked)
-static bool_t scrobbler_request_session() {
-
-    gchar *sessionmsg = create_message_to_lastfm("auth.getSession",
-                                                 2,
-                                                 "token", request_token,
-                                                 "api_key", SCROBBLER_API_KEY);
-
-    if (send_message_to_lastfm(sessionmsg) == FALSE) {
-        g_free(sessionmsg);
-        return FALSE;
-    }
-
-    g_free(sessionmsg);
-    //the token can only be sent once
-    str_unref(request_token);
-    request_token = NULL;
-
-    return update_session_key();
-}
-
-
-
-//returns:
-// FALSE if there was a network problem.
-// TRUE otherwise (scrobbling_enabled must be checked)
-//sets scrobbling_enabled to TRUE if the session is OK
-//sets session_key to NULL if it is invalid
-static bool_t scrobbler_test_connection() {
-
-    if (!session_key || !session_key[0]) {
-        scrobbling_enabled = FALSE;
-        return TRUE;
-    }
-
-
-    gchar *testmsg = create_message_to_lastfm("user.getRecommendedArtists",
-                                              3,
-                                              "limit", "1",
-                                              "api_key", SCROBBLER_API_KEY,
-                                              "sk", session_key
-                                             );
-    bool_t success = send_message_to_lastfm(testmsg);
-    g_free(testmsg);
-    if (success == FALSE) {
-        AUDDBG("Network problems. Will not scrobble any tracks.\n");
-        scrobbling_enabled = FALSE;
-        if (permission_check_requested) {
-            perm_result = PERMISSION_NONET;
-        }
-        return FALSE;
-    }
-
-    gchar *error_code = NULL;
-    gchar *error_detail = NULL;
-
-    if (read_authentication_test_result(&error_code, &error_detail) == FALSE) {
-        AUDDBG("Error code: %s. Detail: %s.\n", error_code, error_detail);
-        if (error_code != NULL && (
-                g_strcmp0(error_code, "4") == 0 || //error code 4: Authentication Failed - You do not have permissions to access the service
-                g_strcmp0(error_code, "9") == 0    //error code 9: Invalid session key - Please re-authenticate
-            )) {
-            str_unref(session_key);
-            session_key = NULL;
-            aud_set_str("scrobbler", "session_key", "");
-            scrobbling_enabled = FALSE;
-        } else {
-            //network problem.
-            scrobbling_enabled = FALSE;
-            AUDDBG("Connection NOT OK. Scrobbling disabled\n");
-            success = FALSE;
-        }
-    } else {
-        //THIS IS THE ONLY PLACE WHERE SCROBBLING IS SET TO ENABLED IN RUN-TIME
-        scrobbling_enabled = TRUE;
-        AUDDBG("Connection OK. Scrobbling enabled.\n");
-    }
-
-    str_unref(error_code);
-    str_unref(error_detail);
-    return success;
-}
-
-//called from scrobbler_init() @ scrobbler.c
-bool_t 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;
-    }
-
-    curlHandle = curl_easy_init();
-    if (curlHandle == NULL) {
-        AUDDBG("Could not initialize libCURL.\n");
-        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;
-    }
-
-    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 TRUE;
-}
-
-static void set_timestamp_to_current(gchar **line) {
-    //line[0] line[1] line[2] line[3] line[4] line[5] line[6]   line[7]
-    //artist  album   title   number  length  "L"     timestamp NULL
-
-    gchar **splitted_line = g_strsplit(*line, "\t", 0);
-    g_free(splitted_line[6]);
-    splitted_line[6] = g_strdup_printf("%"G_GINT64_FORMAT"", g_get_real_time() / G_USEC_PER_SEC);
-    AUDDBG("splitted line's timestamp is now: %s.\n", splitted_line[6]);
-    g_free(*line);
-    (*line) = g_strjoinv("\t", splitted_line);
-}
-
-static void delete_lines_from_scrobble_log (GSList **lines_to_remove_ptr, GSList **lines_to_retry_ptr, gchar *queuepath) {
-    GSList *lines_to_remove = *lines_to_remove_ptr;
-    GSList *lines_to_retry = *lines_to_retry_ptr;
-    gchar *contents = NULL;
-    gchar **lines = NULL;
-    gchar **finallines = g_malloc_n(1, sizeof(gchar *));
-    int n_finallines;
-
-    if (lines_to_remove != NULL) {
-        lines_to_remove = g_slist_reverse(lines_to_remove);
-    }
-    if (lines_to_retry != NULL) {
-        lines_to_retry = g_slist_reverse(lines_to_retry);
-    }
-
-
-    pthread_mutex_lock(&log_access_mutex);
-
-    gboolean success = g_file_get_contents(queuepath, &contents, NULL, NULL);
-    if (!success) {
-        AUDDBG("Could not read scrobbler.log contents.\n");
-    } else {
-        lines = g_strsplit(contents, "\n", 0);
-
-        n_finallines = 0;
-        for (int i = 0 ; lines[i] != NULL && strlen(lines[i]) > 0; i++) {
-            if (lines_to_remove != NULL && *((int *) (lines_to_remove->data)) == i) {
-                //this line is to remove
-                lines_to_remove = g_slist_next(lines_to_remove);
-            } else {
-                //keep this line
-                AUDDBG("Going to keep line %i\n", i);
-                if (lines_to_retry != NULL && *((int *) (lines_to_retry->data)) == i) {
-                  lines_to_retry = g_slist_next(lines_to_retry);
-                  //this line will be retried with a zero timestamp
-                  AUDDBG("Going to zero this line.\n");
-                  AUDDBG("Line before: %s.\n", lines[i]);
-                  set_timestamp_to_current(&(lines[i]));
-                  AUDDBG("Line after: %s.\n", lines[i]);
-
-                } else {
-                  AUDDBG("not zeroing this line\n");
-                }
-                n_finallines++;
-                finallines = g_realloc_n(finallines, n_finallines, sizeof(gchar *));
-                finallines[n_finallines-1] = g_strdup(lines[i]);
-            }
-        }
-
-        finallines = g_realloc_n(finallines, n_finallines+2, sizeof(gchar *));
-        finallines[n_finallines] = g_strdup("");
-        finallines[n_finallines+1] = NULL;
-        g_free(contents);
-        contents = g_strjoinv("\n", finallines);
-        success = g_file_set_contents(queuepath, contents, -1, NULL);
-        if (!success) {
-            AUDDBG("Could not write to scrobbler.log!\n");
-        }
-
-    }
-
-    pthread_mutex_unlock(&log_access_mutex);
-
-
-    g_strfreev(finallines);
-    g_strfreev(lines);
-    g_free(contents);
-}
-
-static void save_line_to_remove(GSList **lines_to_remove, int linenumber) {
-    int *rem = g_malloc(sizeof(int));
-    *rem = linenumber;
-    (*lines_to_remove) = g_slist_prepend((*lines_to_remove), rem);
-}
-
-static void scrobble_cached_queue() {
-
-    gchar *queuepath = g_build_filename(aud_get_path(AUD_PATH_USER_DIR),"scrobbler.log", NULL);
-    gchar *contents = NULL;
-    gboolean success;
-    gchar **lines = NULL;
-    gchar **line;
-    gchar *scrobblemsg;
-    GSList *lines_to_remove = NULL; //lines to remove because they were scrobbled (or ignored, and will not be retried)
-    GSList *lines_to_retry = NULL; //lines to retry later because they were too old TODO: or "daily scrobble limit reached"
-
-    pthread_mutex_lock(&log_access_mutex);
-    success = g_file_get_contents(queuepath, &contents, NULL, NULL);
-    pthread_mutex_unlock(&log_access_mutex);
-    if (!success) {
-        AUDDBG("Couldn't access the queue file.\n");
-    } else {
-
-        lines = g_strsplit(contents, "\n", 0);
-
-        for (int i = 0; lines[i] != NULL && strlen(lines[i]) > 0 && scrobbling_enabled; i++) {
-            line = g_strsplit(lines[i], "\t", 0);
-
-            //line[0] line[1] line[2] line[3] line[4] line[5] line[6]   line[7]
-            //artist  album   title   number  length  "L"     timestamp NULL
-
-            if (line[0] && line[2] && (strcmp(line[5], "L") == 0) && line[6] && (line[7] == NULL)) {
-                scrobblemsg = create_message_to_lastfm("track.scrobble",
-                                                       8,
-                                                       "artist", line[0],
-                                                       "album", line[1],
-                                                       "track", line[2],
-                                                       "trackNumber", line[3],
-                                                       "duration", line[4],
-                                                       "timestamp", line[6],
-                                                       "api_key", SCROBBLER_API_KEY,
-                                                       "sk", session_key);
-                if (send_message_to_lastfm(scrobblemsg) == TRUE) {
-                    char *error_code = NULL;
-                    char *error_detail = NULL;
-                    bool_t ignored = FALSE;
-                    char *ignored_code = NULL;
-
-                    if (read_scrobble_result(&error_code, &error_detail, &ignored, &ignored_code) == TRUE) {
-                        AUDDBG("SCROBBLE OK. Error code: %s. Error detail: %s\n", error_code, error_detail);
-                        AUDDBG("SCROBBLE OK. ignored: %i.\n", ignored);
-                        AUDDBG("SCROBBLE OK. ignored code: %s.\n", ignored_code);
-                        if (ignored == TRUE && g_strcmp0(ignored_code, "3") == 0) { //3: Timestamp was too old
-                            AUDDBG("SCROBBLE IGNORED!!! %i, detail: %s\n", ignored, ignored_code);
-                            save_line_to_remove(&lines_to_retry, i);
-                        } 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.
-                           //TODO
-
-                        } else {
-                            AUDDBG("Not ignored. Carrying on...\n");
-                            save_line_to_remove(&lines_to_remove, i);
-                        }
-                    } else {
-                        AUDDBG("SCROBBLE NOT OK. Error code: %s. Error detail: %s.\n", error_code, error_detail);
-
-                        if (error_code == NULL) { //net error(?) or the answer from last.fm was not well read
-                            //scrobble to be retried
-                        }
-                        else if (g_strcmp0(error_code, "11") == 0 ||
-                                 g_strcmp0(error_code, "16") == 0){
-                            //error code 11: Service Offline - This service is temporarily offline. Try again later.
-                            //error code 16: The service is temporarily unavailable, please try again.
-                            //scrobble to be retried
-                        }
-                        else if (g_strcmp0(error_code,  "9") == 0) {
-                            //Bad Session. Reauth.
-                            scrobbling_enabled = FALSE;
-                            str_unref(session_key);
-                            session_key = NULL;
-                            aud_set_str("scrobbler", "session_key", "");
-                        }
-                        else {
-                            save_line_to_remove(&lines_to_remove, i);
-                        }
-                    }
-
-                    str_unref(error_code);
-                    str_unref(error_detail);
-                    str_unref(ignored_code);
-                } else {
-                    AUDDBG("Could not scrobble a track on the queue. Network problem?\n");
-                    //scrobble to be retried
-                    scrobbling_enabled = FALSE;
-                }
-
-                g_free(scrobblemsg);
-                //TODO: Avoid spamming last.fm --- It's not as simple as just adding a wait here:
-                //If audacious is closed while we're on this loop, tracks might be re-scrobbled.
-                //This shall be doable if we only pick one track at a time from the scrobbler.log
-            } else {
-                AUDDBG("Unscrobbable line.\n");
-                //leave entry on the cache file
-            }
-            g_strfreev(line);
-        }//for
-
-
-        delete_lines_from_scrobble_log(&lines_to_remove, &lines_to_retry, queuepath);
-
-        if (lines_to_remove != NULL) {
-            g_slist_free_full(lines_to_remove, g_free);
-        }
-        if (lines_to_retry != NULL) {
-            g_slist_free_full(lines_to_retry, g_free);
-        }
-
-        g_strfreev(lines);
-    }
-
-    g_free(contents);
-    g_free(queuepath);
-}
-
-
-static void send_now_playing() {
-
-  gchar  *error_code = NULL;
-  gchar  *error_detail = NULL;
-  bool_t ignored = FALSE;
-  gchar  *ignored_code = NULL;
-  /*
-   * now_playing_track can be set to something else while we this method is
-   * running. Creating a local variable avoids to get data for different tracks,
-   * while now_playing_track was updated concurrently.
-   */
-  Tuple *curr_track = now_playing_track;
-
-  char *artist = clean_string(tuple_get_str(curr_track, FIELD_ARTIST));
-  char *title  = clean_string(tuple_get_str(curr_track, FIELD_TITLE));
-  char *album  = clean_string(tuple_get_str(curr_track, FIELD_ALBUM));
-
-  int track  = tuple_get_int(curr_track, FIELD_TRACK_NUMBER);
-  int length = tuple_get_int(curr_track, FIELD_LENGTH);
-
-  tuple_unref(curr_track);
-
-  if (artist[0] && title[0] && length > 0) {
-    char *track_str = (track > 0) ? int_to_str(track) : str_get("");
-    char *length_str = int_to_str(length / 1000);
-
-    gchar *playingmsg = create_message_to_lastfm("track.updateNowPlaying",
-                                            7,
-                                           "artist", artist,
-                                           "album", album,
-                                           "track", title,
-                                           "trackNumber", track_str,
-                                           "duration", length_str,
-                                           "api_key", SCROBBLER_API_KEY,
-                                           "sk", session_key);
-
-    bool_t success = send_message_to_lastfm(playingmsg);
-    g_free(playingmsg);
-
-    str_unref(track_str);
-    str_unref(length_str);
-
-    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) {
-      //see scrobble_cached_queue()
-      AUDDBG("NOW PLAYING OK.\n");
-    } else {
-      AUDDBG("NOW PLAYING NOT OK. Error code: %s. Error detail: %s.\n", error_code, error_detail);
-      //From the API: Now Playing requests that fail should not be retried.
-
-      if (g_strcmp0(error_code, "9") == 0) {
-        //Bad Session. Reauth.
-        //We don't really care about any other errors.
-        scrobbling_enabled = FALSE;
-        str_unref(session_key);
-        session_key = NULL;
-        aud_set_str("scrobbler", "session_key", "");
-      }
-
-    }
-    //We don't care if the now playing was not accepted, no need to read the result from the server.
-
-  }
-
-  str_unref(artist);
-  str_unref(title);
-  str_unref(album);
-
-  str_unref(error_code);
-  str_unref(error_detail);
-  str_unref(ignored_code);
-}
-
-static void treat_permission_check_request() {
-    if (!session_key || !session_key[0]) {
-        perm_result = PERMISSION_DENIED;
-
-        if (!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) {
-            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]) {
-                perm_result = PERMISSION_NONET;
-            } //else PERMISSION_DENIED
-        }
-    }
-    if (session_key && session_key[0]) {
-        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]) {
-                    perm_result = PERMISSION_DENIED;
-                } //else PERMISSION_NONET
-            }
-
-        } else {
-            if (scrobbling_enabled) {
-                perm_result = PERMISSION_ALLOWED;
-            } else {
-             /* This means that we have a session key but couldn't make
-              * an authenticated call with it. This happens when:
-              * a) the user revoked the permission to Audacious on his
-              * last.fm account OR
-              * b) something might be wrong on last.fm's side (?) OR
-              * 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]) {
-                    perm_result = PERMISSION_DENIED;
-                } else {
-                    perm_result = PERMISSION_NONET;
-                }
-            }
-        }
-    } //session_key == NULL || strlen(session_key) == 0
-}
-
-// This is a sister function of scrobbler_request_session, using the getMobileSession
-//API call, for migrating from the old config
-//returns:
-// FALSE if there was a network problem OR a session_key was not obtained
-// TRUE if a new session_key was obtained
-static bool_t treat_migrate_config() {
-
-    char *password = aud_get_str("audioscrobbler","password");
-    if (!password[0]) {
-        str_unref(password);
-        return FALSE;
-    }
-
-    char *username = aud_get_str("audioscrobbler","username");
-    if (!username[0]) {
-        str_unref(password);
-        str_unref(username);
-        return FALSE;
-    }
-
-    gchar *checksumThis = g_strdup_printf("%s%s", username, password);
-    gchar *authToken = g_compute_checksum_for_string(G_CHECKSUM_MD5, checksumThis, -1);
-
-    gchar *sessionmsg = create_message_to_lastfm("auth.getMobileSession",
-                                                 3,
-                                                 "authToken", authToken,
-                                                 "username", username,
-                                                 "api_key", SCROBBLER_API_KEY);
-    str_unref(username);
-    str_unref(password);
-    g_free(checksumThis);
-    g_free(authToken);
-
-    if (send_message_to_lastfm(sessionmsg) == FALSE) {
-        g_free(sessionmsg);
-        return FALSE;
-    }
-
-    g_free(sessionmsg);
-
-    if (!update_session_key())
-        return FALSE;
-
-    return (session_key && session_key[0]);
-}
-
-
-//Scrobbling will only be enabled after the first connection test passed
-gpointer scrobbling_thread (gpointer input_data) {
-
-    while (scrobbler_running) {
-
-        if (migrate_config_requested) {
-          if (treat_migrate_config() == FALSE) {
-            aud_interface_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;
-
-        } else if (permission_check_requested) {
-            treat_permission_check_request();
-            permission_check_requested = FALSE;
-
-        } else if (invalidate_session_requested) {
-            str_unref(session_key);
-            session_key = NULL;
-            aud_set_str("scrobbler", "session_key", "");
-            invalidate_session_requested = FALSE;
-
-        } else if (now_playing_requested) {
-            if (scrobbling_enabled) {
-              send_now_playing();
-            }
-            now_playing_requested = FALSE;
-
-        } else {
-            if (scrobbling_enabled) {
-              scrobble_cached_queue();
-            }
-            //scrobbling may be disabled at this point if communication errors occur
-
-            pthread_mutex_lock(&communication_mutex);
-            if (scrobbling_enabled) {
-                pthread_cond_wait(&communication_signal, &communication_mutex);
-                pthread_mutex_unlock(&communication_mutex);
-            }
-            else {
-                //We don't want to wait until receiving a signal to retry
-                //if submitting the cache failed due to network problems
-                pthread_mutex_unlock(&communication_mutex);
-
-                if (scrobbler_test_connection() == FALSE || !scrobbling_enabled) {
-                    struct timeval curtime;
-                    struct timespec timeout;
-                    pthread_mutex_lock(&communication_mutex);
-                    gettimeofday(&curtime, NULL);
-                    timeout.tv_sec = curtime.tv_sec + 7;
-                    timeout.tv_nsec = curtime.tv_usec * 1000;
-                    pthread_cond_timedwait(&communication_signal, &communication_mutex, &timeout);
-                    pthread_mutex_unlock(&communication_mutex);
-                }
-            }
-        }
-    }//while(scrobbler_running)
-
-    //reset all vars to their initial values
-    g_free(received_data);
-    received_data = NULL;
-    received_data_size = 0;
-
-    curl_easy_cleanup(curlHandle);
-    curlHandle = NULL;
-
-    scrobbling_enabled = TRUE;
-    return NULL;
-}
-
diff --git a/src/scrobbler2/scrobbler_communication.cc b/src/scrobbler2/scrobbler_communication.cc
new file mode 100644
index 000000000000..4e4d54903db3
--- /dev/null
+++ b/src/scrobbler2/scrobbler_communication.cc
@@ -0,0 +1,703 @@
+
+//external includes
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <curl/curl.h>
+
+#include <glib.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/interface.h>
+
+//plugin includes
+#include "scrobbler.h"
+
+typedef struct {
+    String paramName;
+    String argument;
+} API_Parameter;
+
+static CURL *curlHandle = nullptr;     //global handle holding cURL options
+
+gboolean scrobbling_enabled = TRUE;
+
+//shared variables
+char *received_data = nullptr;   //Holds the result of the last request made to last.fm
+size_t received_data_size = 0; //Holds the size of the received_data buffer
+
+
+
+// The cURL callback function to store the received data from the last.fm servers.
+static size_t result_callback (void *buffer, size_t size, size_t nmemb, void *userp) {
+
+    const size_t len = size*nmemb;
+
+    char *temp_data = g_renew(char, received_data, received_data_size + len + 1);
+
+    if (temp_data == nullptr) {
+      return 0;
+    } else {
+      received_data = temp_data;
+    }
+
+    memcpy(received_data + received_data_size, buffer, len);
+
+    received_data_size += len;
+
+    return len;
+}
+
+static int param_compare (const API_Parameter & a, const API_Parameter & b, void *)
+{
+    return g_strcmp0 (a.paramName, b.paramName);
+}
+
+static char * scrobbler_get_signature (Index<API_Parameter> & params)
+{
+    params.sort (param_compare, nullptr);
+
+    StringBuf buf (0);
+
+    for (const API_Parameter & param : params)
+    {
+        buf.insert (-1, param.paramName);
+        buf.insert (-1, param.argument);
+    }
+
+    buf.insert (-1, SCROBBLER_SHARED_SECRET);
+
+    return g_compute_checksum_for_string (G_CHECKSUM_MD5, buf, -1);
+}
+
+/*
+ * n_args should count with the given authentication parameters
+ * At most 2: api_key, session_key.
+ * api_sig (checksum) is always included, be it necessary or not
+ * Example usage:
+ *   create_message_to_lastfm("track.scrobble", 5
+ *        "artist", "Artist Name", "track", "Track Name", "timestamp", time(nullptr),
+ *        "api_key", SCROBBLER_API_KEY, "sk", session_key);
+ *
+ * Returns nullptr if an error occurrs
+ */
+static String create_message_to_lastfm (const char * method_name, int n_args, ...)
+{
+    Index<API_Parameter> params;
+    params.append (String ("method"), String (method_name));
+
+    StringBuf buf = str_concat ({"method=", method_name});
+
+    va_list vl;
+    va_start (vl, n_args);
+
+    for (int i = 0; i < n_args; i ++)
+    {
+        const char * name = va_arg (vl, const char *);
+        const char * arg = va_arg (vl, const char *);
+
+        params.append (String (name), String (arg));
+
+        char * esc = curl_easy_escape (curlHandle, arg, 0);
+        buf.insert (-1, "&");
+        buf.insert (-1, name);
+        buf.insert (-1, "=");
+        buf.insert (-1, esc);
+        curl_free (esc);
+    }
+
+    va_end (vl);
+
+    char * api_sig = scrobbler_get_signature (params);
+    buf.insert (-1, "&api_sig=");
+    buf.insert (-1, api_sig);
+    g_free (api_sig);
+
+    AUDDBG ("FINAL message: %s.\n", (const char *) buf);
+
+    return String (buf);
+}
+
+static gboolean send_message_to_lastfm (const char * data)
+{
+    AUDDBG("This message will be sent to last.fm:\n%s\n%%%%End of message%%%%\n", data);//Enter?\n", data);
+    curl_easy_setopt(curlHandle, CURLOPT_POSTFIELDS, data);
+    CURLcode curl_requests_result = curl_easy_perform(curlHandle);
+
+    if (curl_requests_result != CURLE_OK) {
+        AUDDBG("Could not communicate with last.fm: %s.\n", curl_easy_strerror(curl_requests_result));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+//returns:
+// FALSE if there was a network problem
+// TRUE otherwise (request_token must be checked)
+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) {
+        AUDDBG("Could not send token request to last.fm.\n");
+        return FALSE;
+    }
+
+    gboolean success = TRUE;
+    String error_code;
+    String error_detail;
+
+    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();
+        }
+    }
+
+    return success;
+}
+
+
+static gboolean update_session_key() {
+    gboolean result = TRUE;
+    String error_code;
+    String error_detail;
+
+    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
+                g_strcmp0(error_code, "15") == 0    //token expired
+            )) {
+            AUDDBG("error code CAUGHT: %s\n", (const char *)error_code);
+            session_key = String();
+            result = TRUE;
+        } else {
+            result= FALSE;
+        }
+    }
+
+    aud_set_str("scrobbler", "session_key", session_key ? session_key : "");
+
+    return result;
+}
+
+//returns:
+// FALSE if there was a network problem
+// TRUE otherwise (session_key must be checked)
+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;
+
+    //the token can only be sent once
+    request_token = String();
+
+    return update_session_key();
+}
+
+//returns:
+// FALSE if there was a network problem.
+// TRUE otherwise (scrobbling_enabled must be checked)
+//sets scrobbling_enabled to TRUE if the session is OK
+//sets session_key to nullptr if it is invalid
+static gboolean scrobbler_test_connection() {
+
+    if (!session_key || !session_key[0]) {
+        scrobbling_enabled = FALSE;
+        return TRUE;
+    }
+
+    String testmsg = create_message_to_lastfm ("user.getRecommendedArtists", 3,
+     "limit", "1", "api_key", SCROBBLER_API_KEY,
+     "sk", (const char *) session_key);
+
+    gboolean success = send_message_to_lastfm(testmsg);
+
+    if (success == FALSE) {
+        AUDDBG("Network problems. Will not scrobble any tracks.\n");
+        scrobbling_enabled = FALSE;
+        if (permission_check_requested) {
+            perm_result = PERMISSION_NONET;
+        }
+        return FALSE;
+    }
+
+    String error_code;
+    String error_detail;
+
+    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 && (
+                g_strcmp0(error_code, "4") == 0 || //error code 4: Authentication Failed - You do not have permissions to access the service
+                g_strcmp0(error_code, "9") == 0    //error code 9: Invalid session key - Please re-authenticate
+            )) {
+            session_key = String();
+            aud_set_str("scrobbler", "session_key", "");
+            scrobbling_enabled = FALSE;
+        } else {
+            //network problem.
+            scrobbling_enabled = FALSE;
+            AUDDBG("Connection NOT OK. Scrobbling disabled\n");
+            success = FALSE;
+        }
+    } else {
+        //THIS IS THE ONLY PLACE WHERE SCROBBLING IS SET TO ENABLED IN RUN-TIME
+        scrobbling_enabled = TRUE;
+        AUDDBG("Connection OK. Scrobbling enabled.\n");
+    }
+
+    return success;
+}
+
+//called from scrobbler_init() @ scrobbler.c
+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;
+    }
+
+    curlHandle = curl_easy_init();
+    if (curlHandle == nullptr) {
+        AUDDBG("Could not initialize libCURL.\n");
+        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;
+    }
+
+    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 TRUE;
+}
+
+static void set_timestamp_to_current(char **line) {
+    //line[0] line[1] line[2] line[3] line[4] line[5] line[6]   line[7]
+    //artist  album   title   number  length  "L"     timestamp nullptr
+
+    char **splitted_line = g_strsplit(*line, "\t", 0);
+    g_free(splitted_line[6]);
+    splitted_line[6] = g_strdup_printf("%" G_GINT64_FORMAT, g_get_real_time() / G_USEC_PER_SEC);
+    AUDDBG("splitted line's timestamp is now: %s.\n", splitted_line[6]);
+    g_free(*line);
+    (*line) = g_strjoinv("\t", splitted_line);
+}
+
+static void delete_lines_from_scrobble_log (GSList **lines_to_remove_ptr, GSList **lines_to_retry_ptr, char *queuepath) {
+    GSList *lines_to_remove = *lines_to_remove_ptr;
+    GSList *lines_to_retry = *lines_to_retry_ptr;
+    char *contents = nullptr;
+    char **lines = nullptr;
+    char **finallines = g_new (char *, 1);
+    int n_finallines;
+
+    if (lines_to_remove != nullptr) {
+        lines_to_remove = g_slist_reverse(lines_to_remove);
+    }
+    if (lines_to_retry != nullptr) {
+        lines_to_retry = g_slist_reverse(lines_to_retry);
+    }
+
+
+    pthread_mutex_lock(&log_access_mutex);
+
+    gboolean success = g_file_get_contents(queuepath, &contents, nullptr, nullptr);
+    if (!success) {
+        AUDDBG("Could not read scrobbler.log contents.\n");
+    } else {
+        lines = g_strsplit(contents, "\n", 0);
+
+        n_finallines = 0;
+        for (int i = 0 ; lines[i] != nullptr && strlen(lines[i]) > 0; i++) {
+            if (lines_to_remove != nullptr && *((int *) (lines_to_remove->data)) == i) {
+                //this line is to remove
+                lines_to_remove = g_slist_next(lines_to_remove);
+            } else {
+                //keep this line
+                AUDDBG("Going to keep line %i\n", i);
+                if (lines_to_retry != nullptr && *((int *) (lines_to_retry->data)) == i) {
+                  lines_to_retry = g_slist_next(lines_to_retry);
+                  //this line will be retried with a zero timestamp
+                  AUDDBG("Going to zero this line.\n");
+                  AUDDBG("Line before: %s.\n", lines[i]);
+                  set_timestamp_to_current(&(lines[i]));
+                  AUDDBG("Line after: %s.\n", lines[i]);
+
+                } else {
+                  AUDDBG("not zeroing this line\n");
+                }
+                n_finallines++;
+                finallines = g_renew (char *, finallines, n_finallines);
+                finallines[n_finallines-1] = g_strdup(lines[i]);
+            }
+        }
+
+        finallines = g_renew (char *, finallines, n_finallines + 2);
+        finallines[n_finallines] = g_strdup("");
+        finallines[n_finallines+1] = nullptr;
+        g_free(contents);
+        contents = g_strjoinv("\n", finallines);
+        success = g_file_set_contents(queuepath, contents, -1, nullptr);
+        if (!success) {
+            AUDDBG("Could not write to scrobbler.log!\n");
+        }
+
+    }
+
+    pthread_mutex_unlock(&log_access_mutex);
+
+
+    g_strfreev(finallines);
+    g_strfreev(lines);
+    g_free(contents);
+}
+
+static void save_line_to_remove(GSList **lines_to_remove, int linenumber) {
+    int *rem = g_new (int, 1);
+    *rem = linenumber;
+    (*lines_to_remove) = g_slist_prepend((*lines_to_remove), rem);
+}
+
+static void scrobble_cached_queue() {
+
+    char *queuepath = g_build_filename(aud_get_path(AudPath::UserDir),"scrobbler.log", nullptr);
+    char *contents = nullptr;
+    gboolean success;
+    char **lines = nullptr;
+    char **line;
+    GSList *lines_to_remove = nullptr; //lines to remove because they were scrobbled (or ignored, and will not be retried)
+    GSList *lines_to_retry = nullptr; //lines to retry later because they were too old TODO: or "daily scrobble limit reached"
+
+    pthread_mutex_lock(&log_access_mutex);
+    success = g_file_get_contents(queuepath, &contents, nullptr, nullptr);
+    pthread_mutex_unlock(&log_access_mutex);
+    if (!success) {
+        AUDDBG("Couldn't access the queue file.\n");
+    } else {
+
+        lines = g_strsplit(contents, "\n", 0);
+
+        for (int i = 0; lines[i] != nullptr && strlen(lines[i]) > 0 && scrobbling_enabled; i++) {
+            line = g_strsplit(lines[i], "\t", 0);
+
+            //line[0] line[1] line[2] line[3] line[4] line[5] line[6]   line[7]
+            //artist  album   title   number  length  "L"     timestamp nullptr
+
+            if (line[0] && line[2] && (strcmp(line[5], "L") == 0) && line[6] && (line[7] == nullptr))
+            {
+                String scrobblemsg = create_message_to_lastfm ("track.scrobble",
+                 8, "artist", line[0], "album", line[1], "track", line[2],
+                 "trackNumber", line[3], "duration", line[4],
+                 "timestamp", line[6], "api_key", SCROBBLER_API_KEY,
+                 "sk", (const char *) session_key);
+
+                if (send_message_to_lastfm(scrobblemsg) == TRUE) {
+                    String error_code;
+                    String error_detail;
+                    gboolean ignored = FALSE;
+                    String ignored_code;
+
+                    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
+                            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
+                           //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.
+                           //TODO
+
+                        } else {
+                            AUDDBG("Not ignored. Carrying on...\n");
+                            save_line_to_remove(&lines_to_remove, i);
+                        }
+                    } else {
+                        AUDDBG("SCROBBLE NOT OK. Error code: %s. Error detail: %s.\n",
+                         (const char *)error_code, (const char *)error_detail);
+
+                        if (! error_code) { //net error(?) or the answer from last.fm was not well read
+                            //scrobble to be retried
+                        }
+                        else if (g_strcmp0(error_code, "11") == 0 ||
+                                 g_strcmp0(error_code, "16") == 0){
+                            //error code 11: Service Offline - This service is temporarily offline. Try again later.
+                            //error code 16: The service is temporarily unavailable, please try again.
+                            //scrobble to be retried
+                        }
+                        else if (g_strcmp0(error_code,  "9") == 0) {
+                            //Bad Session. Reauth.
+                            scrobbling_enabled = FALSE;
+                            session_key = String();
+                            aud_set_str("scrobbler", "session_key", "");
+                        }
+                        else {
+                            save_line_to_remove(&lines_to_remove, i);
+                        }
+                    }
+                } else {
+                    AUDDBG("Could not scrobble a track on the queue. Network problem?\n");
+                    //scrobble to be retried
+                    scrobbling_enabled = FALSE;
+                }
+
+                //TODO: Avoid spamming last.fm --- It's not as simple as just adding a wait here:
+                //If audacious is closed while we're on this loop, tracks might be re-scrobbled.
+                //This shall be doable if we only pick one track at a time from the scrobbler.log
+            } else {
+                AUDDBG("Unscrobbable line.\n");
+                //leave entry on the cache file
+            }
+            g_strfreev(line);
+        }//for
+
+
+        delete_lines_from_scrobble_log(&lines_to_remove, &lines_to_retry, queuepath);
+
+        if (lines_to_remove != nullptr) {
+            g_slist_free_full(lines_to_remove, g_free);
+        }
+        if (lines_to_retry != nullptr) {
+            g_slist_free_full(lines_to_retry, g_free);
+        }
+
+        g_strfreev(lines);
+    }
+
+    g_free(contents);
+    g_free(queuepath);
+}
+
+
+static void send_now_playing() {
+
+  String error_code;
+  String error_detail;
+  gboolean ignored = FALSE;
+  String ignored_code;
+  /*
+   * now_playing_track can be set to something else while we this method is
+   * running. Creating a local variable avoids to get data for different tracks,
+   * while now_playing_track was updated concurrently.
+   *
+   * FIXME: Make this actually thread-safe.
+   */
+  Tuple curr_track = now_playing_track.ref ();
+
+  StringBuf artist = clean_string (curr_track.get_str (Tuple::Artist));
+  StringBuf title = clean_string (curr_track.get_str (Tuple::Title));
+  StringBuf album = clean_string (curr_track.get_str (Tuple::Album));
+
+  int track  = curr_track.get_int (Tuple::Track);
+  int length = curr_track.get_int (Tuple::Length);
+
+  if (artist[0] && title[0] && length > 0) {
+    StringBuf track_str = (track > 0) ? int_to_str (track) : StringBuf (0);
+    StringBuf length_str = int_to_str (length / 1000);
+
+    String playingmsg = create_message_to_lastfm ("track.updateNowPlaying", 7,
+     "artist", (const char *) artist, "album", (const char *) album,
+     "track", (const char *) title, "trackNumber", (const char *) track_str,
+     "duration", (const char *) length_str, "api_key", SCROBBLER_API_KEY,
+     "sk", (const char *) session_key);
+
+    gboolean success = send_message_to_lastfm(playingmsg);
+
+    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) {
+      //see scrobble_cached_queue()
+      AUDDBG("NOW PLAYING OK.\n");
+    } else {
+      AUDDBG("NOW PLAYING NOT OK. Error code: %s. Error detail: %s.\n",
+       (const char *)error_code, (const char *)error_detail);
+      //From the API: Now Playing requests that fail should not be retried.
+
+      if (g_strcmp0(error_code, "9") == 0) {
+        //Bad Session. Reauth.
+        //We don't really care about any other errors.
+        scrobbling_enabled = FALSE;
+        session_key = String();
+        aud_set_str("scrobbler", "session_key", "");
+      }
+
+    }
+    //We don't care if the now playing was not accepted, no need to read the result from the server.
+
+  }
+}
+
+static void treat_permission_check_request() {
+    if (!session_key || !session_key[0]) {
+        perm_result = PERMISSION_DENIED;
+
+        if (!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) {
+            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]) {
+                perm_result = PERMISSION_NONET;
+            } //else PERMISSION_DENIED
+        }
+    }
+    if (session_key && session_key[0]) {
+        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]) {
+                    perm_result = PERMISSION_DENIED;
+                } //else PERMISSION_NONET
+            }
+
+        } else {
+            if (scrobbling_enabled) {
+                perm_result = PERMISSION_ALLOWED;
+            } else {
+             /* This means that we have a session key but couldn't make
+              * an authenticated call with it. This happens when:
+              * a) the user revoked the permission to Audacious on his
+              * last.fm account OR
+              * b) something might be wrong on last.fm's side (?) OR
+              * 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]) {
+                    perm_result = PERMISSION_DENIED;
+                } else {
+                    perm_result = PERMISSION_NONET;
+                }
+            }
+        }
+    } //session_key == nullptr || strlen(session_key) == 0
+}
+
+// This is a sister function of scrobbler_request_session, using the getMobileSession
+//API call, for migrating from the old config
+//returns:
+// FALSE if there was a network problem OR a session_key was not obtained
+// TRUE if a new session_key was obtained
+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;
+
+    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);
+
+    String sessionmsg = create_message_to_lastfm ("auth.getMobileSession", 3,
+     "authToken", authToken, "username", (const char *) username,
+     "api_key", SCROBBLER_API_KEY);
+
+    g_free(checksumThis);
+    g_free(authToken);
+
+    if (send_message_to_lastfm(sessionmsg) == FALSE)
+        return FALSE;
+
+    if (!update_session_key())
+        return FALSE;
+
+    return (session_key && session_key[0]);
+}
+
+
+//Scrobbling will only be enabled after the first connection test passed
+void * scrobbling_thread (void * input_data) {
+
+    while (scrobbler_running) {
+
+        if (migrate_config_requested) {
+          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;
+
+        } else if (permission_check_requested) {
+            treat_permission_check_request();
+            permission_check_requested = FALSE;
+
+        } else if (invalidate_session_requested) {
+            session_key = String();
+            aud_set_str("scrobbler", "session_key", "");
+            invalidate_session_requested = FALSE;
+
+        } else if (now_playing_requested) {
+            if (scrobbling_enabled) {
+              send_now_playing();
+            }
+            now_playing_requested = FALSE;
+
+        } else {
+            if (scrobbling_enabled) {
+              scrobble_cached_queue();
+            }
+            //scrobbling may be disabled at this point if communication errors occur
+
+            pthread_mutex_lock(&communication_mutex);
+            if (scrobbling_enabled) {
+                pthread_cond_wait(&communication_signal, &communication_mutex);
+                pthread_mutex_unlock(&communication_mutex);
+            }
+            else {
+                //We don't want to wait until receiving a signal to retry
+                //if submitting the cache failed due to network problems
+                pthread_mutex_unlock(&communication_mutex);
+
+                if (scrobbler_test_connection() == FALSE || !scrobbling_enabled) {
+                    struct timeval curtime;
+                    struct timespec timeout;
+                    pthread_mutex_lock(&communication_mutex);
+                    gettimeofday(&curtime, nullptr);
+                    timeout.tv_sec = curtime.tv_sec + 7;
+                    timeout.tv_nsec = curtime.tv_usec * 1000;
+                    pthread_cond_timedwait(&communication_signal, &communication_mutex, &timeout);
+                    pthread_mutex_unlock(&communication_mutex);
+                }
+            }
+        }
+    }//while(scrobbler_running)
+
+    //reset all vars to their initial values
+    g_free(received_data);
+    received_data = nullptr;
+    received_data_size = 0;
+
+    curl_easy_cleanup(curlHandle);
+    curlHandle = nullptr;
+
+    scrobbling_enabled = TRUE;
+    return nullptr;
+}
+
diff --git a/src/scrobbler2/scrobbler_xml_parsing.c b/src/scrobbler2/scrobbler_xml_parsing.c
deleted file mode 100644
index 750676dbf3e9..000000000000
--- a/src/scrobbler2/scrobbler_xml_parsing.c
+++ /dev/null
@@ -1,322 +0,0 @@
-
-//plugin includes
-#include "scrobbler.h"
-
-//static (private) variables
-static xmlDocPtr doc = NULL;
-static xmlXPathContextPtr context = NULL;
-
-static bool_t prepare_data () {
-    received_data[received_data_size] = '\0';
-    AUDDBG("Data received from last.fm:\n%s\n%%%%End of data%%%%\n", received_data);
-
-    doc = xmlParseMemory(received_data, received_data_size+1);
-    received_data_size = 0;
-    if (doc == NULL) {
-        AUDDBG("Document not parsed successfully.\n");
-        return FALSE;
-    }
-
-    context = xmlXPathNewContext(doc);
-    if (context == NULL) {
-        AUDDBG("Error in xmlXPathNewContext\n");
-        xmlFreeDoc(doc);
-        doc = NULL;
-        return FALSE;
-    }
-    return TRUE;
-}
-
-static void clean_data() {
-    xmlXPathFreeContext(context);
-    xmlFreeDoc(doc);
-    context = NULL;
-    doc = NULL;
-}
-
-
-//returns:
-// NULL if an error occurs or the attribute was not found
-// the attribute's value if it was found
-static char *get_attribute_value (const char *node_expression, const char *attribute) {
-    if (doc == NULL || context == NULL) {
-        AUDDBG("Response from last.fm not parsed successfully. Did you call prepare_data?\n");
-        return NULL;
-    }
-
-    xmlXPathObjectPtr statusObj = xmlXPathEvalExpression((xmlChar *) node_expression, context);
-    if (statusObj == NULL) {
-        AUDDBG ("Error in xmlXPathEvalExpression.\n");
-        return NULL;
-    }
-    if (xmlXPathNodeSetIsEmpty(statusObj->nodesetval)) {
-        AUDDBG("No result.\n");
-        xmlXPathFreeObject(statusObj);
-        return NULL;
-    }
-
-    xmlChar *prop = xmlGetProp(statusObj->nodesetval->nodeTab[0], (xmlChar *) attribute);
-
-    char *result = NULL;
-    if (prop && prop[0])
-        result = str_get((char *) prop);
-
-    xmlXPathFreeObject(statusObj);
-    xmlFree(prop);
-
-    AUDDBG("RESULT FOR THIS FUNCTION: %s.\n", result);
-    return result;
-}
-
-//returns:
-// NULL if an error occurs or the node was not found
-static char *get_node_string (const char *node_expression) {
-    if (doc == NULL || context == NULL) {
-        AUDDBG("Response from last.fm not parsed successfully. Did you call prepare_data?\n");
-        return NULL;
-    }
-
-    xmlXPathObjectPtr statusObj = xmlXPathEvalExpression((xmlChar *) node_expression, context);
-    if (statusObj == NULL) {
-        AUDDBG ("Error in xmlXPathEvalExpression.\n");
-        return NULL;
-    }
-    if (xmlXPathNodeSetIsEmpty(statusObj->nodesetval)) {
-        AUDDBG("No result.\n");
-        xmlXPathFreeObject(statusObj);
-        return NULL;
-    }
-
-    xmlChar *string = xmlNodeListGetString(doc, statusObj->nodesetval->nodeTab[0]->children, 1);
-
-    char *result = NULL;
-    if (string && string[0])
-        result = str_get((char *) string);
-
-    xmlXPathFreeObject(statusObj);
-    xmlFree(string);
-
-    AUDDBG("RESULT FOR THIS FUNCTION: %s.\n", result);
-    return result;
-}
-
-
-//returns:
-// NULL if an error occurs
-// "true" if the the command succeeded
-// "false" if an error occurred. error_code and error_detail should be checked in this case
-static char *check_status (char **error_code, char **error_detail) {
-    (*error_code) = NULL;
-    (*error_detail) = NULL;
-
-    char *status = get_attribute_value("/lfm[@status]", "status");
-    if (!status) {
-        AUDDBG("last.fm not answering according to the API.\n");
-        return NULL;
-    }
-
-    AUDDBG ("status is %s.\n", status);
-    if (strcmp(status, "ok")) {
-
-        (*error_code) = get_attribute_value("/lfm/error[@code]", "code");
-        if (!(*error_code)) {
-            AUDDBG("Weird API answer. Last.fm says status is %s but there is no error code?\n", status);
-            str_unref(status);
-            status = NULL;
-        } else {
-            (*error_detail) = get_node_string("/lfm/error");
-        }
-    }
-
-    AUDDBG("check_status results: return: %s. error_code: %s. error_detail: %s.\n", status, (*error_code), (*error_detail));
-    return status;
-}
-
-/*
- * Returns:
- *  * TRUE if the scrobble was successful
- *    * with ignored = TRUE if it was ignored
- *      * ignored_code_out must be checked
- *    * with ignored = FALSE if it was scrobbled OK
- *  * FALSE if the scrobble was unsuccessful
- *    * error_code_out and error_detail_out must be checked:
- *      * They are NULL if an API communication error occur
- */
-bool_t read_scrobble_result(char **error_code, char **error_detail, bool_t *ignored, char **ignored_code) {
-
-    *error_code = NULL;
-    *error_detail = NULL;
-    *ignored = FALSE;
-    *ignored_code = NULL;
-
-    bool_t result = TRUE;
-
-    if (!prepare_data()) {
-        AUDDBG("Could not read received data from last.fm. What's up?\n");
-        return FALSE;
-    }
-
-    char *status = check_status(error_code, error_detail);
-
-    if (!status) {
-        AUDDBG("Status was NULL. Invalid API answer.\n");
-        clean_data();
-        return FALSE;
-    }
-
-    if (!strcmp(status, "failed")) {
-        AUDDBG("Error code: %s. Detail: %s.\n", *error_code, *error_detail);
-        result = FALSE;
-
-    } else {
-        //TODO: We are assuming that only one track is scrobbled per request! This will have to be
-        //re-done to support multiple tracks being scrobbled in batch
-        char *ignored_scrobble = get_attribute_value("/lfm/scrobbles[@ignored]", "ignored");
-
-        if (ignored_scrobble && strcmp(ignored_scrobble, "0")) {
-          //The track was ignored
-          //TODO: this assumes ignored_scrobble == 1!!!
-          *ignored = TRUE;
-          *ignored_code = get_attribute_value("/lfm/scrobbles/scrobble/ignoredMessage[@code]", "code");
-        }
-
-        str_unref(ignored_scrobble);
-
-        AUDDBG("ignored? %i, ignored_code: %s\n", *ignored, *ignored_code);
-    }
-
-    str_unref(status);
-
-    clean_data();
-    return result;
-}
-
-//returns
-//FALSE if there was an error with the connection
-bool_t read_authentication_test_result (char **error_code, char **error_detail) {
-
-    *error_code = NULL;
-    *error_detail = NULL;
-
-    bool_t result = TRUE;
-
-    if (!prepare_data()) {
-        AUDDBG("Could not read received data from last.fm. What's up?\n");
-        return FALSE;
-    }
-
-    char *status = check_status(error_code, error_detail);
-
-    if (!status) {
-        AUDDBG("Status was NULL. Invalid API answer.\n");
-        clean_data();
-        return FALSE;
-    }
-
-    if (!strcmp(status, "failed")) {
-        result = FALSE;
-
-    } else {
-        str_unref(username);
-        username = get_attribute_value("/lfm/recommendations[@user]", "user");
-        if (!username) {
-          AUDDBG("last.fm not answering according to the API.\n");
-          result = FALSE;
-        }
-    }
-
-    str_unref(status);
-
-    clean_data();
-    return result;
-}
-
-
-
-bool_t read_token (char **error_code, char **error_detail) {
-
-    *error_code = NULL;
-    *error_detail = NULL;
-
-    bool_t result = TRUE;
-
-    if (!prepare_data()) {
-        AUDDBG("Could not read received data from last.fm. What's up?\n");
-        return FALSE;
-    }
-
-    char *status = check_status(error_code, error_detail);
-
-    if (!status) {
-        AUDDBG("Status was NULL. Invalid API answer.\n");
-        clean_data();
-        return FALSE;
-    }
-
-    if (!strcmp(status, "failed")) {
-        AUDDBG("Error code: %s. Detail: %s.\n", *error_code, *error_detail);
-        result = FALSE;
-    }
-    else {
-        str_unref(request_token);
-        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;
-        }
-        else {
-            AUDDBG("This is the token: %s.\nNice? Nice.\n", request_token);
-        }
-    }
-
-    str_unref(status);
-
-    clean_data();
-    return result;
-}
-
-
-
-bool_t read_session_key(char **error_code, char **error_detail) {
-
-    *error_code = NULL;
-    *error_detail = NULL;
-
-    bool_t result = TRUE;
-
-    if (!prepare_data()) {
-        AUDDBG("Could not read received data from last.fm. What's up?\n");
-        return FALSE;
-    }
-
-    char *status = check_status(error_code, error_detail);
-
-    if (!status) {
-        AUDDBG("Status was NULL or empty. Invalid API answer.\n");
-        clean_data();
-        return FALSE;
-    }
-
-    if (!strcmp(status, "failed")) {
-        AUDDBG("Error code: %s. Detail: %s.\n", *error_code, *error_detail);
-        result = FALSE;
-
-    } else {
-        str_unref(session_key);
-        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;
-        } else {
-            AUDDBG("This is the session key: %s.\n", session_key);
-        }
-    }
-
-    str_unref(status);
-
-    clean_data();
-    return result;
-}
-
diff --git a/src/scrobbler2/scrobbler_xml_parsing.cc b/src/scrobbler2/scrobbler_xml_parsing.cc
new file mode 100644
index 000000000000..b1ea05b2b9a2
--- /dev/null
+++ b/src/scrobbler2/scrobbler_xml_parsing.cc
@@ -0,0 +1,300 @@
+
+//plugin includes
+#include "scrobbler.h"
+
+//static (private) variables
+static xmlDocPtr doc = nullptr;
+static xmlXPathContextPtr context = nullptr;
+
+static gboolean prepare_data () {
+    received_data[received_data_size] = '\0';
+    AUDDBG("Data received from last.fm:\n%s\n%%%%End of data%%%%\n", received_data);
+
+    doc = xmlParseMemory(received_data, received_data_size+1);
+    received_data_size = 0;
+    if (doc == nullptr) {
+        AUDDBG("Document not parsed successfully.\n");
+        return FALSE;
+    }
+
+    context = xmlXPathNewContext(doc);
+    if (context == nullptr) {
+        AUDDBG("Error in xmlXPathNewContext\n");
+        xmlFreeDoc(doc);
+        doc = nullptr;
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static void clean_data() {
+    xmlXPathFreeContext(context);
+    xmlFreeDoc(doc);
+    context = nullptr;
+    doc = nullptr;
+}
+
+
+//returns:
+// nullptr if an error occurs or the attribute was not found
+// the attribute's value if it was found
+static String get_attribute_value (const char *node_expression, const char *attribute) {
+    if (doc == nullptr || context == nullptr) {
+        AUDDBG("Response from last.fm not parsed successfully. Did you call prepare_data?\n");
+        return String();
+    }
+
+    xmlXPathObjectPtr statusObj = xmlXPathEvalExpression((xmlChar *) node_expression, context);
+    if (statusObj == nullptr) {
+        AUDDBG ("Error in xmlXPathEvalExpression.\n");
+        return String();
+    }
+    if (xmlXPathNodeSetIsEmpty(statusObj->nodesetval)) {
+        AUDDBG("No result.\n");
+        xmlXPathFreeObject(statusObj);
+        return String();
+    }
+
+    xmlChar *prop = xmlGetProp(statusObj->nodesetval->nodeTab[0], (xmlChar *) attribute);
+
+    String result;
+    if (prop && prop[0])
+        result = String((const char *)prop);
+
+    xmlXPathFreeObject(statusObj);
+    xmlFree(prop);
+
+    AUDDBG("RESULT FOR THIS FUNCTION: %s.\n", (const char *)result);
+    return result;
+}
+
+//returns:
+// nullptr if an error occurs or the node was not found
+static String get_node_string (const char *node_expression) {
+    if (doc == nullptr || context == nullptr) {
+        AUDDBG("Response from last.fm not parsed successfully. Did you call prepare_data?\n");
+        return String();
+    }
+
+    xmlXPathObjectPtr statusObj = xmlXPathEvalExpression((xmlChar *) node_expression, context);
+    if (statusObj == nullptr) {
+        AUDDBG ("Error in xmlXPathEvalExpression.\n");
+        return String();
+    }
+    if (xmlXPathNodeSetIsEmpty(statusObj->nodesetval)) {
+        AUDDBG("No result.\n");
+        xmlXPathFreeObject(statusObj);
+        return String();
+    }
+
+    xmlChar *string = xmlNodeListGetString(doc, statusObj->nodesetval->nodeTab[0]->children, 1);
+
+    String result;
+    if (string && string[0])
+        result = String((const char *) string);
+
+    xmlXPathFreeObject(statusObj);
+    xmlFree(string);
+
+    AUDDBG("RESULT FOR THIS FUNCTION: %s.\n", (const char *)result);
+    return result;
+}
+
+
+//returns:
+// nullptr if an error occurs
+// "true" if the the command succeeded
+// "false" if an error occurred. error_code and error_detail should be checked in this case
+static String check_status (String &error_code, String &error_detail) {
+
+    String status = get_attribute_value("/lfm[@status]", "status");
+    if (!status) {
+        AUDDBG("last.fm not answering according to the API.\n");
+        return String();
+    }
+
+    AUDDBG ("status is %s.\n", (const char *)status);
+    if (strcmp(status, "ok")) {
+
+        error_code = get_attribute_value("/lfm/error[@code]", "code");
+        if (!(*error_code)) {
+            AUDDBG("Weird API answer. Last.fm says status is %s but there is no error code?\n",
+             (const char *)status);
+            status = String();
+        } else {
+            error_detail = get_node_string("/lfm/error");
+        }
+    }
+
+    AUDDBG("check_status results: return: %s. error_code: %s. error_detail: %s.\n",
+     (const char *)status, (const char *)error_code, (const char *)error_detail);
+    return status;
+}
+
+/*
+ * Returns:
+ *  * TRUE if the scrobble was successful
+ *    * with ignored = TRUE if it was ignored
+ *      * ignored_code_out must be checked
+ *    * with ignored = FALSE if it was scrobbled OK
+ *  * FALSE if the scrobble was unsuccessful
+ *    * error_code_out and error_detail_out must be checked:
+ *      * They are nullptr if an API communication error occur
+ */
+gboolean read_scrobble_result(String &error_code, String &error_detail,
+ gboolean *ignored, String &ignored_code) {
+
+    *ignored = FALSE;
+
+    gboolean result = TRUE;
+
+    if (!prepare_data()) {
+        AUDDBG("Could not read received data from last.fm. What's up?\n");
+        return FALSE;
+    }
+
+    String status = check_status(error_code, error_detail);
+
+    if (!status) {
+        AUDDBG("Status was nullptr. Invalid API answer.\n");
+        clean_data();
+        return FALSE;
+    }
+
+    if (!strcmp(status, "failed")) {
+        AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code,
+         (const char *)error_detail);
+        result = FALSE;
+
+    } else {
+        //TODO: We are assuming that only one track is scrobbled per request! This will have to be
+        //re-done to support multiple tracks being scrobbled in batch
+        String ignored_scrobble = get_attribute_value("/lfm/scrobbles[@ignored]", "ignored");
+
+        if (ignored_scrobble && strcmp(ignored_scrobble, "0")) {
+          //The track was ignored
+          //TODO: this assumes ignored_scrobble == 1!!!
+          *ignored = TRUE;
+          ignored_code = get_attribute_value("/lfm/scrobbles/scrobble/ignoredMessage[@code]", "code");
+        }
+
+        AUDDBG("ignored? %i, ignored_code: %s\n", *ignored, (const char *)ignored_code);
+    }
+
+    clean_data();
+    return result;
+}
+
+//returns
+//FALSE if there was an error with the connection
+gboolean read_authentication_test_result (String &error_code, String &error_detail) {
+
+    gboolean result = TRUE;
+
+    if (!prepare_data()) {
+        AUDDBG("Could not read received data from last.fm. What's up?\n");
+        return FALSE;
+    }
+
+    String status = check_status(error_code, error_detail);
+
+    if (!status) {
+        AUDDBG("Status was nullptr. Invalid API answer.\n");
+        clean_data();
+        return FALSE;
+    }
+
+    if (!strcmp(status, "failed")) {
+        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;
+        }
+    }
+
+    clean_data();
+    return result;
+}
+
+
+
+gboolean read_token (String &error_code, String &error_detail) {
+
+    gboolean result = TRUE;
+
+    if (!prepare_data()) {
+        AUDDBG("Could not read received data from last.fm. What's up?\n");
+        return FALSE;
+    }
+
+    String status = check_status(error_code, error_detail);
+
+    if (!status) {
+        AUDDBG("Status was nullptr. Invalid API answer.\n");
+        clean_data();
+        return FALSE;
+    }
+
+    if (!strcmp(status, "failed")) {
+        AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code,
+         (const char *)error_detail);
+        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;
+        }
+        else {
+            AUDDBG("This is the token: %s.\nNice? Nice.\n", (const char *)request_token);
+        }
+    }
+
+    clean_data();
+    return result;
+}
+
+
+
+gboolean read_session_key(String &error_code, String &error_detail) {
+
+    gboolean result = TRUE;
+
+    if (!prepare_data()) {
+        AUDDBG("Could not read received data from last.fm. What's up?\n");
+        return FALSE;
+    }
+
+    String status = check_status(error_code, error_detail);
+
+    if (!status) {
+        AUDDBG("Status was nullptr or empty. Invalid API answer.\n");
+        clean_data();
+        return FALSE;
+    }
+
+    if (!strcmp(status, "failed")) {
+        AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code,
+         (const char *)error_detail);
+        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;
+        } else {
+            AUDDBG("This is the session key: %s.\n", (const char *)session_key);
+        }
+    }
+
+    clean_data();
+    return result;
+}
+
diff --git a/src/sdlout/Makefile b/src/sdlout/Makefile
index 7243d2e51f03..c59c97c4fee2 100644
--- a/src/sdlout/Makefile
+++ b/src/sdlout/Makefile
@@ -1,13 +1,13 @@
 PLUGIN = sdlout${PLUGIN_SUFFIX}
 
-SRCS = sdlout.c \
-       plugin.c \
+SRCS = sdlout.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
 
+LD = ${CXX}
 CPPFLAGS += -I../.. ${SDL_CFLAGS}
-CFLAGS += ${GLIB_CFLAGS} ${PLUGIN_CFLAGS}
-LIBS += -lm ${GLIB_LIBS} ${SDL_LIBS}
+CXXFLAGS += ${PLUGIN_CFLAGS}
+LIBS += -lm ${SDL_LIBS}
diff --git a/src/sdlout/plugin.c b/src/sdlout/plugin.c
deleted file mode 100644
index 785d7490fda9..000000000000
--- a/src/sdlout/plugin.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SDL Output Plugin for Audacious
- * Copyright 2010 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 <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-#include "sdlout.h"
-
-static const char sdlout_about[] =
- N_("SDL Output Plugin for Audacious\n"
-    "Copyright 2010 John Lindgren");
-
-AUD_OUTPUT_PLUGIN
-(
-    .name = N_("SDL Output"),
-    .domain = PACKAGE,
-    .about_text = sdlout_about,
-    .init = sdlout_init,
-    .cleanup = sdlout_cleanup,
-    .probe_priority = 1,
-    .get_volume = sdlout_get_volume,
-    .set_volume = sdlout_set_volume,
-    .open_audio = sdlout_open_audio,
-    .close_audio = sdlout_close_audio,
-    .buffer_free = sdlout_buffer_free,
-    .period_wait = sdlout_period_wait,
-    .write_audio = sdlout_write_audio,
-    .drain = sdlout_drain,
-    .output_time = sdlout_output_time,
-    .pause = sdlout_pause,
-    .flush = sdlout_flush
-)
diff --git a/src/sdlout/sdlout.c b/src/sdlout/sdlout.c
deleted file mode 100644
index cfc4b519472f..000000000000
--- a/src/sdlout/sdlout.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * SDL Output Plugin for Audacious
- * Copyright 2010 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 <assert.h>
-#include <math.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include <glib.h>
-
-#include <SDL.h>
-#include <SDL_audio.h>
-
-#include <audacious/debug.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include "sdlout.h"
-
-#define VOLUME_RANGE 40 /* decibels */
-
-#define sdlout_error(...) do { \
-    SPRINTF (sdlout_error_buf, "SDL error: " __VA_ARGS__); \
-    aud_interface_show_error (sdlout_error_buf); \
-} while (0)
-
-static const char * const sdl_defaults[] = {
- "vol_left", "100",
- "vol_right", "100",
- NULL};
-
-static pthread_mutex_t sdlout_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t sdlout_cond = PTHREAD_COND_INITIALIZER;
-
-static volatile int vol_left, vol_right;
-
-static int sdlout_chan, sdlout_rate;
-
-static unsigned char * buffer;
-static int buffer_size, buffer_data_start, buffer_data_len;
-
-static int64_t frames_written;
-static char prebuffer_flag, paused_flag;
-
-static int block_delay;
-static struct timeval block_time;
-
-int sdlout_init (void)
-{
-    aud_config_set_defaults ("sdlout", sdl_defaults);
-
-    vol_left = aud_get_int ("sdlout", "vol_left");
-    vol_right = aud_get_int ("sdlout", "vol_right");
-
-    if (SDL_Init (SDL_INIT_AUDIO) < 0)
-    {
-        fprintf (stderr, "Failed to init SDL: %s.\n", SDL_GetError ());
-        return 0;
-    }
-
-    return 1;
-}
-
-void sdlout_cleanup (void)
-{
-    SDL_Quit ();
-}
-
-void sdlout_get_volume (int * left, int * right)
-{
-    * left = vol_left;
-    * right = vol_right;
-}
-
-void sdlout_set_volume (int left, int right)
-{
-    vol_left = left;
-    vol_right = right;
-
-    aud_set_int ("sdlout", "vol_left", left);
-    aud_set_int ("sdlout", "vol_right", right);
-}
-
-static void apply_mono_volume (unsigned char * data, int len)
-{
-    int vol = MAX (vol_left, vol_right);
-    int factor = (vol == 0) ? 0 : powf (10, (float) VOLUME_RANGE * (vol - 100)
-     / 100 / 20) * 65536;
-
-    int16_t * i = (int16_t *) data;
-    int16_t * end = (int16_t *) (data + len);
-
-    while (i < end)
-    {
-        * i = ((int) * i * factor) >> 16;
-        i ++;
-    }
-}
-
-static void apply_stereo_volume (unsigned char * data, int len)
-{
-    int factor_left = (vol_left == 0) ? 0 : powf (10, (float) VOLUME_RANGE *
-     (vol_left - 100) / 100 / 20) * 65536;
-    int factor_right = (vol_right == 0) ? 0 : powf (10, (float) VOLUME_RANGE *
-     (vol_right - 100) / 100 / 20) * 65536;
-
-    int16_t * i = (int16_t *) data;
-    int16_t * end = (int16_t *) (data + len);
-
-    while (i < end)
-    {
-        * i = ((int) * i * factor_left) >> 16;
-        i ++;
-        * i = ((int) * i * factor_right) >> 16;
-        i ++;
-    }
-}
-
-static void callback (void * user, unsigned char * buf, int len)
-{
-    pthread_mutex_lock (& sdlout_mutex);
-
-    int copy = MIN (len, buffer_data_len);
-    int part = buffer_size - buffer_data_start;
-
-    if (copy <= part)
-    {
-        memcpy (buf, buffer + buffer_data_start, copy);
-        buffer_data_start += copy;
-    }
-    else
-    {
-        memcpy (buf, buffer + buffer_data_start, part);
-        memcpy (buf + part, buffer, copy - part);
-        buffer_data_start = copy - part;
-    }
-
-    buffer_data_len -= copy;
-
-    if (sdlout_chan == 2)
-        apply_stereo_volume (buf, copy);
-    else
-        apply_mono_volume (buf, copy);
-
-    if (copy < len)
-        memset (buf + copy, 0, len - copy);
-
-    /* At this moment, we know that there is a delay of (at least) the block of
-     * data just written.  We save the block size and the current time for
-     * estimating the delay later on. */
-    block_delay = copy / (2 * sdlout_chan) * 1000 / sdlout_rate;
-    gettimeofday (& block_time, NULL);
-
-    pthread_cond_broadcast (& sdlout_cond);
-    pthread_mutex_unlock (& sdlout_mutex);
-}
-
-int sdlout_open_audio (int format, int rate, int chan)
-{
-    if (format != FMT_S16_NE)
-    {
-        sdlout_error ("Only signed 16-bit, native endian audio is supported.\n");
-        return 0;
-    }
-
-    AUDDBG ("Opening audio for %d channels, %d Hz.\n", chan, rate);
-
-    sdlout_chan = chan;
-    sdlout_rate = rate;
-
-    buffer_size = 2 * chan * (aud_get_int (NULL, "output_buffer_size") * rate / 1000);
-    buffer = g_malloc (buffer_size);
-    buffer_data_start = 0;
-    buffer_data_len = 0;
-
-    frames_written = 0;
-    prebuffer_flag = 1;
-    paused_flag = 0;
-
-    SDL_AudioSpec spec = {
-     .freq = rate,
-     .format = AUDIO_S16,
-     .channels = chan,
-     .samples = 4096,
-     .callback = callback,
-     .userdata = NULL};
-
-    if (SDL_OpenAudio (& spec, NULL) < 0)
-    {
-        sdlout_error ("Failed to open audio stream: %s.\n", SDL_GetError ());
-        g_free (buffer);
-        buffer = NULL;
-        return 0;
-    }
-
-    return 1;
-}
-
-void sdlout_close_audio (void)
-{
-    AUDDBG ("Closing audio.\n");
-    SDL_CloseAudio ();
-    g_free (buffer);
-    buffer = NULL;
-}
-
-int sdlout_buffer_free (void)
-{
-    pthread_mutex_lock (& sdlout_mutex);
-    int space = buffer_size - buffer_data_len;
-    pthread_mutex_unlock (& sdlout_mutex);
-    return space;
-}
-
-static void check_started (void)
-{
-    if (! prebuffer_flag)
-        return;
-
-    AUDDBG ("Starting playback.\n");
-    prebuffer_flag = 0;
-    block_delay = 0;
-    SDL_PauseAudio (0);
-}
-
-void sdlout_period_wait (void)
-{
-    pthread_mutex_lock (& sdlout_mutex);
-
-    while (buffer_data_len == buffer_size)
-    {
-        if (! paused_flag)
-            check_started ();
-
-        pthread_cond_wait (& sdlout_cond, & sdlout_mutex);
-    }
-
-    pthread_mutex_unlock (& sdlout_mutex);
-}
-
-void sdlout_write_audio (void * data, int len)
-{
-    pthread_mutex_lock (& sdlout_mutex);
-
-    assert (len <= buffer_size - buffer_data_len);
-
-    int start = (buffer_data_start + buffer_data_len) % buffer_size;
-
-    if (len <= buffer_size - start)
-        memcpy (buffer + start, data, len);
-    else
-    {
-        int part = buffer_size - start;
-        memcpy (buffer + start, data, part);
-        memcpy (buffer, (char *) data + part, len - part);
-    }
-
-    buffer_data_len += len;
-    frames_written += len / (2 * sdlout_chan);
-
-    pthread_mutex_unlock (& sdlout_mutex);
-}
-
-void sdlout_drain (void)
-{
-    AUDDBG ("Draining.\n");
-    pthread_mutex_lock (& sdlout_mutex);
-
-    check_started ();
-
-    while (buffer_data_len)
-        pthread_cond_wait (& sdlout_cond, & sdlout_mutex);
-
-    pthread_mutex_unlock (& sdlout_mutex);
-}
-
-int sdlout_output_time (void)
-{
-    pthread_mutex_lock (& sdlout_mutex);
-
-    int out = (int64_t) (frames_written - buffer_data_len / (2 * sdlout_chan))
-     * 1000 / sdlout_rate;
-
-    /* Estimate the additional delay of the last block written. */
-    if (! prebuffer_flag && ! paused_flag && block_delay)
-    {
-        struct timeval cur;
-        gettimeofday (& cur, NULL);
-
-        int elapsed = 1000 * (cur.tv_sec - block_time.tv_sec) + (cur.tv_usec -
-         block_time.tv_usec) / 1000;
-
-        if (elapsed < block_delay)
-            out -= block_delay - elapsed;
-    }
-
-    pthread_mutex_unlock (& sdlout_mutex);
-    return out;
-}
-
-void sdlout_pause (int pause)
-{
-    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
-    pthread_mutex_lock (& sdlout_mutex);
-
-    paused_flag = pause;
-
-    if (! prebuffer_flag)
-        SDL_PauseAudio (pause);
-
-    pthread_cond_broadcast (& sdlout_cond); /* wake up period wait */
-    pthread_mutex_unlock (& sdlout_mutex);
-}
-
-void sdlout_flush (int time)
-{
-    AUDDBG ("Seek requested; discarding buffer.\n");
-    pthread_mutex_lock (& sdlout_mutex);
-
-    buffer_data_start = 0;
-    buffer_data_len = 0;
-
-    frames_written = (int64_t) time * sdlout_rate / 1000;
-    prebuffer_flag = 1;
-
-    pthread_cond_broadcast (& sdlout_cond); /* wake up period wait */
-    pthread_mutex_unlock (& sdlout_mutex);
-}
diff --git a/src/sdlout/sdlout.cc b/src/sdlout/sdlout.cc
new file mode 100644
index 000000000000..cc3b379d864a
--- /dev/null
+++ b/src/sdlout/sdlout.cc
@@ -0,0 +1,335 @@
+/*
+ * SDL Output Plugin for Audacious
+ * Copyright 2010 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 <math.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <SDL.h>
+#include <SDL_audio.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+#define VOLUME_RANGE 40 /* decibels */
+
+#define sdlout_error(...) do { \
+    aud_ui_show_error (str_printf ("SDL error: " __VA_ARGS__)); \
+} while (0)
+
+class SDLOutput : public OutputPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+
+    static constexpr PluginInfo info = {
+        N_("SDL Output"),
+        PACKAGE,
+        about
+    };
+
+    constexpr SDLOutput () : OutputPlugin (info, 1) {}
+
+    bool init ();
+    void cleanup ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int aud_format, int rate, int chans);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+};
+
+EXPORT SDLOutput aud_plugin_instance;
+
+const char SDLOutput::about[] =
+ N_("SDL Output Plugin for Audacious\n"
+    "Copyright 2010 John Lindgren");
+
+const char * const SDLOutput::defaults[] = {
+ "vol_left", "100",
+ "vol_right", "100",
+ nullptr};
+
+static pthread_mutex_t sdlout_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t sdlout_cond = PTHREAD_COND_INITIALIZER;
+
+static volatile int vol_left, vol_right;
+
+static int sdlout_chan, sdlout_rate;
+
+static RingBuf<unsigned char> buffer;
+
+static bool prebuffer_flag, paused_flag;
+
+static int block_delay;
+static struct timeval block_time;
+
+bool SDLOutput::init ()
+{
+    aud_config_set_defaults ("sdlout", defaults);
+
+    vol_left = aud_get_int ("sdlout", "vol_left");
+    vol_right = aud_get_int ("sdlout", "vol_right");
+
+    if (SDL_Init (SDL_INIT_AUDIO) < 0)
+    {
+        AUDERR ("Failed to init SDL: %s.\n", SDL_GetError ());
+        return false;
+    }
+
+    return true;
+}
+
+void SDLOutput::cleanup ()
+{
+    SDL_Quit ();
+}
+
+StereoVolume SDLOutput::get_volume ()
+{
+    return {vol_left, vol_right};
+}
+
+void SDLOutput::set_volume (StereoVolume v)
+{
+    vol_left = v.left;
+    vol_right = v.right;
+
+    aud_set_int ("sdlout", "vol_left", v.left);
+    aud_set_int ("sdlout", "vol_right", v.right);
+}
+
+static void apply_mono_volume (unsigned char * data, int len)
+{
+    int vol = aud::max (vol_left, vol_right);
+    int factor = (vol == 0) ? 0 : powf (10, (float) VOLUME_RANGE * (vol - 100)
+     / 100 / 20) * 65536;
+
+    int16_t * i = (int16_t *) data;
+    int16_t * end = (int16_t *) (data + len);
+
+    while (i < end)
+    {
+        * i = ((int) * i * factor) >> 16;
+        i ++;
+    }
+}
+
+static void apply_stereo_volume (unsigned char * data, int len)
+{
+    int factor_left = (vol_left == 0) ? 0 : powf (10, (float) VOLUME_RANGE *
+     (vol_left - 100) / 100 / 20) * 65536;
+    int factor_right = (vol_right == 0) ? 0 : powf (10, (float) VOLUME_RANGE *
+     (vol_right - 100) / 100 / 20) * 65536;
+
+    int16_t * i = (int16_t *) data;
+    int16_t * end = (int16_t *) (data + len);
+
+    while (i < end)
+    {
+        * i = ((int) * i * factor_left) >> 16;
+        i ++;
+        * i = ((int) * i * factor_right) >> 16;
+        i ++;
+    }
+}
+
+static void callback (void * user, unsigned char * buf, int len)
+{
+    pthread_mutex_lock (& sdlout_mutex);
+
+    int copy = aud::min (len, buffer.len ());
+    buffer.move_out (buf, copy);
+
+    if (sdlout_chan == 2)
+        apply_stereo_volume (buf, copy);
+    else
+        apply_mono_volume (buf, copy);
+
+    if (copy < len)
+        memset (buf + copy, 0, len - copy);
+
+    /* At this moment, we know that there is a delay of (at least) the block of
+     * data just written.  We save the block size and the current time for
+     * estimating the delay later on. */
+    block_delay = aud::rescale (copy / (2 * sdlout_chan), sdlout_rate, 1000);
+    gettimeofday (& block_time, nullptr);
+
+    pthread_cond_broadcast (& sdlout_cond);
+    pthread_mutex_unlock (& sdlout_mutex);
+}
+
+bool SDLOutput::open_audio (int format, int rate, int chan)
+{
+    if (format != FMT_S16_NE)
+    {
+        sdlout_error ("Only signed 16-bit, native endian audio is supported.\n");
+        return false;
+    }
+
+    AUDDBG ("Opening audio for %d channels, %d Hz.\n", chan, rate);
+
+    sdlout_chan = chan;
+    sdlout_rate = rate;
+
+    int buffer_ms = aud_get_int (nullptr, "output_buffer_size");
+    buffer.alloc (2 * chan * aud::rescale (buffer_ms, 1000, rate));
+
+    prebuffer_flag = true;
+    paused_flag = false;
+
+    SDL_AudioSpec spec = {0};
+
+    spec.freq = rate;
+    spec.format = AUDIO_S16;
+    spec.channels = chan;
+    spec.samples = 4096;
+    spec.callback = callback;
+
+    if (SDL_OpenAudio (& spec, nullptr) < 0)
+    {
+        sdlout_error ("Failed to open audio stream: %s.\n", SDL_GetError ());
+        buffer.destroy ();
+        return false;
+    }
+
+    return true;
+}
+
+void SDLOutput::close_audio ()
+{
+    AUDDBG ("Closing audio.\n");
+    SDL_CloseAudio ();
+    buffer.destroy ();
+}
+
+static void check_started ()
+{
+    if (! prebuffer_flag)
+        return;
+
+    AUDDBG ("Starting playback.\n");
+    prebuffer_flag = false;
+    block_delay = 0;
+    SDL_PauseAudio (0);
+}
+
+void SDLOutput::period_wait ()
+{
+    pthread_mutex_lock (& sdlout_mutex);
+
+    while (! buffer.space ())
+    {
+        if (! paused_flag)
+            check_started ();
+
+        pthread_cond_wait (& sdlout_cond, & sdlout_mutex);
+    }
+
+    pthread_mutex_unlock (& sdlout_mutex);
+}
+
+int SDLOutput::write_audio (const void * data, int len)
+{
+    pthread_mutex_lock (& sdlout_mutex);
+
+    len = aud::min (len, buffer.space ());
+    buffer.copy_in ((const unsigned char *) data, len);
+
+    pthread_mutex_unlock (& sdlout_mutex);
+    return len;
+}
+
+void SDLOutput::drain ()
+{
+    AUDDBG ("Draining.\n");
+    pthread_mutex_lock (& sdlout_mutex);
+
+    check_started ();
+
+    while (buffer.len ())
+        pthread_cond_wait (& sdlout_cond, & sdlout_mutex);
+
+    pthread_mutex_unlock (& sdlout_mutex);
+}
+
+int SDLOutput::get_delay ()
+{
+    auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
+        { return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
+
+    pthread_mutex_lock (& sdlout_mutex);
+
+    int delay = aud::rescale (buffer.len (), 2 * sdlout_chan * sdlout_rate, 1000);
+
+    /* Estimate the additional delay of the last block written. */
+    if (! prebuffer_flag && ! paused_flag && block_delay)
+    {
+        struct timeval cur;
+        gettimeofday (& cur, nullptr);
+
+        delay += aud::max (block_delay - timediff (block_time, cur), (int64_t) 0);
+    }
+
+    pthread_mutex_unlock (& sdlout_mutex);
+    return delay;
+}
+
+void SDLOutput::pause (bool pause)
+{
+    AUDDBG ("%sause.\n", pause ? "P" : "Unp");
+    pthread_mutex_lock (& sdlout_mutex);
+
+    paused_flag = pause;
+
+    if (! prebuffer_flag)
+        SDL_PauseAudio (pause);
+
+    pthread_cond_broadcast (& sdlout_cond); /* wake up period wait */
+    pthread_mutex_unlock (& sdlout_mutex);
+}
+
+void SDLOutput::flush ()
+{
+    AUDDBG ("Seek requested; discarding buffer.\n");
+    pthread_mutex_lock (& sdlout_mutex);
+
+    buffer.discard ();
+
+    prebuffer_flag = true;
+
+    pthread_cond_broadcast (& sdlout_cond); /* wake up period wait */
+    pthread_mutex_unlock (& sdlout_mutex);
+}
diff --git a/src/sdlout/sdlout.h b/src/sdlout/sdlout.h
deleted file mode 100644
index f33b2ffcb38c..000000000000
--- a/src/sdlout/sdlout.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SDL Output Plugin for Audacious
- * Copyright 2010 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.
- */
-
-#ifndef AUDACIOUS_SDLOUT_H
-#define AUDACIOUS_SDLOUT_H
-
-/* sdlout.c */
-int sdlout_init (void);
-void sdlout_cleanup (void);
-void sdlout_get_volume (int * left, int * right);
-void sdlout_set_volume (int left, int right);
-int sdlout_open_audio (int format, int rate, int chan);
-void sdlout_close_audio (void);
-int sdlout_buffer_free (void);
-void sdlout_period_wait (void);
-void sdlout_write_audio (void * data, int len);
-void sdlout_drain (void);
-int sdlout_output_time (void);
-void sdlout_pause (int pause);
-void sdlout_flush (int time);
-
-#endif
diff --git a/src/search-tool/Makefile b/src/search-tool/Makefile
index 66cc384d9b83..976158e72d4d 100644
--- a/src/search-tool/Makefile
+++ b/src/search-tool/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = search-tool${PLUGIN_SUFFIX}
 
-SRCS = search-tool.c
+SRCS = search-tool.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += -I../.. ${GTK_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += ${GTK_LIBS}
+LIBS += ${GTK_LIBS} -laudgui
diff --git a/src/search-tool/search-tool.c b/src/search-tool/search-tool.c
deleted file mode 100644
index 494453ebab92..000000000000
--- a/src/search-tool/search-tool.c
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * search-tool.c
- * Copyright 2011-2012 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 <errno.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/list.h>
-#include <libaudgui/menu.h>
-
-#define MAX_RESULTS 100
-#define SEARCH_DELAY 300
-
-enum {ARTIST, ALBUM, TITLE, FIELDS};
-
-typedef struct item {
-    int field;
-    char * name, * folded;
-    struct item * parent;
-    GHashTable * children;
-    GArray * matches;
-} Item;
-
-typedef struct {
-    Index * items[FIELDS];
-    int mask;
-} SearchState;
-
-static int playlist_id;
-static Index * search_terms;
-
-static GHashTable * added_table;
-static GHashTable * database;
-static Index * items;
-static GArray * selection;
-
-static bool_t adding;
-static int search_source;
-
-static GtkWidget * entry, * help_label, * wait_label, * scrolled, * results_list;
-
-static void item_free (Item * item);
-
-static Item * item_new (int field, char * name, Item * parent)
-{
-    Item * item = g_slice_new (Item);
-    item->field = field;
-    item->name = name;
-    item->folded = str_tolower_utf8 (name);
-    item->parent = parent;
-    item->matches = g_array_new (FALSE, FALSE, sizeof (int));
-
-    if (field == TITLE)
-        item->children = NULL;
-    else
-        item->children = g_hash_table_new_full ((GHashFunc) str_hash,
-         (GEqualFunc) str_equal, NULL, (GDestroyNotify) item_free);
-
-    return item;
-}
-
-static void item_free (Item * item)
-{
-    if (item->children)
-        g_hash_table_destroy (item->children);
-
-    str_unref (item->name);
-    str_unref (item->folded);
-    g_array_free (item->matches, TRUE);
-    g_slice_free (Item, item);
-}
-
-static void find_playlist (void)
-{
-    playlist_id = -1;
-
-    for (int p = 0; playlist_id < 0 && p < aud_playlist_count (); p ++)
-    {
-        char * title = aud_playlist_get_title (p);
-
-        if (! strcmp (title, _("Library")))
-            playlist_id = aud_playlist_get_unique_id (p);
-
-        str_unref (title);
-    }
-}
-
-static int create_playlist (void)
-{
-    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_t require_added, bool_t 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 void set_search_phrase (const char * phrase)
-{
-    char * folded = str_tolower_utf8 (phrase);
-    index_free_full (search_terms, (IndexFreeFunc) str_unref);
-    search_terms = str_list_to_index (folded, " ");
-    str_unref (folded);
-}
-
-static char * get_path (void)
-{
-    char * path = aud_get_str ("search-tool", "path");
-    if (g_file_test (path, G_FILE_TEST_EXISTS))
-        return path;
-
-    str_unref (path);
-
-    path = filename_build (g_get_home_dir (), "Music");
-    if (g_file_test (path, G_FILE_TEST_EXISTS))
-        return path;
-
-    str_unref (path);
-
-    return str_get (g_get_home_dir ());
-}
-
-static void destroy_added_table (void)
-{
-    if (added_table)
-    {
-        g_hash_table_destroy (added_table);
-        added_table = NULL;
-    }
-}
-
-static void destroy_database (void)
-{
-    if (items)
-        index_delete (items, 0, index_count (items));
-
-    if (database)
-    {
-        g_hash_table_destroy (database);
-        database = NULL;
-    }
-}
-
-static void create_database (int list)
-{
-    destroy_database ();
-
-    database = g_hash_table_new_full ((GHashFunc) str_hash, (GEqualFunc)
-     str_equal, NULL, (GDestroyNotify) item_free);
-
-    int entries = aud_playlist_entry_count (list);
-
-    for (int e = 0; e < entries; e ++)
-    {
-        char * title, * artist, * album;
-        Item * artist_item, * album_item, * title_item;
-
-        aud_playlist_entry_describe (list, e, & title, & artist, & album, TRUE);
-
-        if (! title)
-        {
-            str_unref (artist);
-            str_unref (album);
-            continue;
-        }
-
-        if (! artist)
-            artist = str_get (_("Unknown Artist"));
-        if (! album)
-            album = str_get (_("Unknown Album"));
-
-        artist_item = g_hash_table_lookup (database, artist);
-
-        if (! artist_item)
-        {
-            /* item_new() takes ownership of reference to artist */
-            artist_item = item_new (ARTIST, artist, NULL);
-            g_hash_table_insert (database, artist, artist_item);
-        }
-        else
-            str_unref (artist);
-
-        g_array_append_val (artist_item->matches, e);
-
-        album_item = g_hash_table_lookup (artist_item->children, album);
-
-        if (! album_item)
-        {
-            /* item_new() takes ownership of reference to album */
-            album_item = item_new (ALBUM, album, artist_item);
-            g_hash_table_insert (artist_item->children, album, album_item);
-        }
-        else
-            str_unref (album);
-
-        g_array_append_val (album_item->matches, e);
-
-        title_item = g_hash_table_lookup (album_item->children, title);
-
-        if (! title_item)
-        {
-            /* item_new() takes ownership of reference to title */
-            title_item = item_new (TITLE, title, album_item);
-            g_hash_table_insert (album_item->children, title, title_item);
-        }
-        else
-            str_unref (title);
-
-        g_array_append_val (title_item->matches, e);
-    }
-}
-
-static void search_cb (void * key, void * _item, void * _state)
-{
-    Item * item = _item;
-    SearchState * state = _state;
-
-    if (index_count (state->items[item->field]) > MAX_RESULTS)
-        return;
-
-    int oldmask = state->mask;
-    int count = index_count (search_terms);
-
-    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, index_get (search_terms, t)))
-            state->mask &= ~bit; /* we found it */
-        else if (! item->children)
-            break; /* quit early if there are no children to search */
-    }
-
-    if (! state->mask)
-        index_insert (state->items[item->field], -1, item);
-
-    if (item->children)
-        g_hash_table_foreach (item->children, search_cb, state);
-
-    state->mask = oldmask;
-}
-
-static int item_compare (const void * _a, const void * _b)
-{
-    const Item * a = _a, * b = _b;
-    return str_compare (a->name, b->name);
-}
-
-static void do_search (void)
-{
-    index_delete (items, 0, index_count (items));
-
-    if (! database)
-        return;
-
-    SearchState state;
-
-    for (int f = 0; f < FIELDS; f ++)
-        state.items[f] = index_new ();
-
-    /* effectively limits number of search terms to 32 */
-    state.mask = (1 << index_count (search_terms)) - 1;
-
-    g_hash_table_foreach (database, search_cb, & state);
-
-    int total = 0;
-
-    for (int f = 0; f < FIELDS; f ++)
-    {
-        int count = index_count (state.items[f]);
-        if (count > MAX_RESULTS - total)
-            count = MAX_RESULTS - total;
-
-        if (count)
-        {
-            index_sort (state.items[f], item_compare);
-            index_copy_insert (state.items[f], 0, items, -1, count);
-            total += count;
-        }
-
-        index_free (state.items[f]);
-    }
-
-    g_array_set_size (selection, total);
-    memset (selection->data, 0, selection->len);
-    if (selection->len > 0)
-        selection->data[0] = 1;
-}
-
-static bool_t filter_cb (const char * filename, void * unused)
-{
-    return added_table && ! g_hash_table_contains (added_table, filename);
-}
-
-static void begin_add (const char * path)
-{
-    int list = get_playlist (FALSE, FALSE);
-
-    if (list < 0)
-        list = create_playlist ();
-
-    aud_set_str ("search-tool", "path", path);
-
-    char * uri = filename_to_uri (path);
-    g_return_if_fail (uri);
-
-    if (! g_str_has_suffix (uri, "/"))
-    {
-        SCONCAT2 (temp, uri, "/");
-        str_unref (uri);
-        uri = str_get (temp);
-    }
-
-    destroy_added_table ();
-
-    added_table = g_hash_table_new_full ((GHashFunc) str_hash, (GEqualFunc)
-     str_equal, (GDestroyNotify) str_unref, NULL);
-
-    int entries = aud_playlist_entry_count (list);
-
-    for (int entry = 0; entry < entries; entry ++)
-    {
-        char * filename = aud_playlist_entry_get_filename (list, entry);
-
-        if (g_str_has_prefix (filename, uri) && ! g_hash_table_contains (added_table, filename))
-        {
-            aud_playlist_entry_set_selected (list, entry, FALSE);
-            g_hash_table_insert (added_table, filename, NULL);
-        }
-        else
-        {
-            aud_playlist_entry_set_selected (list, entry, TRUE);
-            str_unref (filename);
-        }
-    }
-
-    aud_playlist_delete_selected (list);
-    aud_playlist_remove_failed (list);
-
-    Index * add = index_new ();
-    index_insert (add, -1, uri);
-    aud_playlist_entry_insert_filtered (list, -1, add, NULL, filter_cb, NULL, FALSE);
-
-    adding = TRUE;
-}
-
-static void show_hide_widgets (void)
-{
-    if (! help_label || ! wait_label || ! scrolled)
-        return;
-
-    if (playlist_id < 0)
-    {
-        gtk_widget_hide (wait_label);
-        gtk_widget_hide (scrolled);
-        gtk_widget_show (help_label);
-    }
-    else
-    {
-        gtk_widget_hide (help_label);
-
-        if (database)
-        {
-            gtk_widget_hide (wait_label);
-            gtk_widget_show (scrolled);
-        }
-        else
-        {
-            gtk_widget_hide (scrolled);
-            gtk_widget_show (wait_label);
-        }
-    }
-}
-
-static int search_timeout (void * unused)
-{
-    do_search ();
-
-    if (results_list)
-    {
-        audgui_list_delete_rows (results_list, 0, audgui_list_row_count (results_list));
-        audgui_list_insert_rows (results_list, 0, index_count (items));
-    }
-
-    if (search_source)
-    {
-        g_source_remove (search_source);
-        search_source = 0;
-    }
-
-    return FALSE;
-}
-
-static void schedule_search (void)
-{
-    if (search_source)
-        g_source_remove (search_source);
-
-    search_source = g_timeout_add (SEARCH_DELAY, search_timeout, NULL);
-}
-
-static void update_database (void)
-{
-    int list = get_playlist (TRUE, TRUE);
-
-    if (list >= 0)
-    {
-        create_database (list);
-        schedule_search ();
-    }
-    else
-        destroy_database ();
-
-    if (results_list)
-        audgui_list_delete_rows (results_list, 0, audgui_list_row_count (results_list));
-
-    show_hide_widgets ();
-}
-
-static void add_complete_cb (void * unused, void * unused2)
-{
-    if (adding)
-    {
-        int list = get_playlist (TRUE, FALSE);
-
-        if (list >= 0 && ! aud_playlist_add_in_progress (list))
-        {
-            adding = FALSE;
-            destroy_added_table ();
-            aud_playlist_sort_by_scheme (list, PLAYLIST_SORT_PATH);
-        }
-    }
-
-    if (! database && ! aud_playlist_update_pending ())
-        update_database ();
-}
-
-static void scan_complete_cb (void * unused, void * unused2)
-{
-    if (! database && ! aud_playlist_update_pending ())
-        update_database ();
-}
-
-static void playlist_update_cb (void * data, void * unused)
-{
-    if (! database)
-        update_database ();
-    else
-    {
-        int list = get_playlist (TRUE, TRUE);
-        int at, count;
-
-        if (list < 0 || aud_playlist_updated_range (list, & at, & count) >=
-         PLAYLIST_UPDATE_METADATA)
-            update_database ();
-    }
-}
-
-static bool_t search_init (void)
-{
-    find_playlist ();
-
-    search_terms = index_new ();
-    items = index_new ();
-    selection = g_array_new (FALSE, FALSE, 1);
-
-    update_database ();
-
-    hook_associate ("playlist add complete", add_complete_cb, NULL);
-    hook_associate ("playlist scan complete", scan_complete_cb, NULL);
-    hook_associate ("playlist update", playlist_update_cb, NULL);
-
-    return TRUE;
-}
-
-static void search_cleanup (void)
-{
-    hook_dissociate ("playlist add complete", add_complete_cb);
-    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;
-    }
-
-    index_free_full (search_terms, (IndexFreeFunc) str_unref);
-    search_terms = NULL;
-
-    index_free (items);
-    items = NULL;
-    g_array_free (selection, TRUE);
-    selection = NULL;
-
-    destroy_added_table ();
-    destroy_database ();
-}
-
-static void do_add (bool_t play, char * * title)
-{
-    int list = aud_playlist_by_unique_id (playlist_id);
-    int n_items = index_count (items);
-    int n_selected = 0;
-
-    Index * filenames = index_new ();
-    Index * tuples = index_new ();
-
-    for (int i = 0; i < n_items; i ++)
-    {
-        if (! selection->data[i])
-            continue;
-
-        Item * item = index_get (items, i);
-
-        for (int m = 0; m < item->matches->len; m ++)
-        {
-            int entry = g_array_index (item->matches, int, m);
-            index_insert (filenames, -1, aud_playlist_entry_get_filename (list, entry));
-            index_insert (tuples, -1, aud_playlist_entry_get_tuple (list, entry, TRUE));
-        }
-
-        n_selected ++;
-        if (title && n_selected == 1)
-            * title = item->name;
-    }
-
-    if (title && n_selected != 1)
-        * title = NULL;
-
-    aud_playlist_entry_insert_batch (aud_playlist_get_active (), -1, filenames,
-     tuples, play);
-}
-
-static void action_play (void)
-{
-    int list = aud_playlist_get_temporary ();
-    aud_playlist_set_active (list);
-
-    if (aud_get_bool (NULL, "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, NULL);
-}
-
-static void action_create_playlist (void)
-{
-    char * title;
-
-    aud_playlist_insert (-1);
-    aud_playlist_set_active (aud_playlist_count () - 1);
-    do_add (FALSE, & title);
-
-    if (title)
-        aud_playlist_set_title (aud_playlist_count () - 1, title);
-}
-
-static void action_add_to_playlist (void)
-{
-    if (aud_playlist_by_unique_id (playlist_id) == aud_playlist_get_active ())
-        return;
-
-    do_add (FALSE, NULL);
-}
-
-static void list_get_value (void * user, int row, int column, GValue * value)
-{
-    g_return_if_fail (items && row >= 0 && row < index_count (items));
-
-    Item * item = index_get (items, row);
-    char * string = NULL;
-
-    switch (item->field)
-    {
-        int albums;
-        char scratch[128];
-
-    case TITLE:
-        string = g_strdup_printf (_("%s\n on %s by %s"), item->name,
-         item->parent->name, item->parent->parent->name);
-        break;
-
-    case ARTIST:
-        albums = g_hash_table_size (item->children);
-        snprintf (scratch, sizeof scratch, dngettext (PACKAGE, "%d album",
-         "%d albums", albums), albums);
-        string = g_strdup_printf (dngettext (PACKAGE, "%s\n %s, %d song",
-         "%s\n %s, %d songs", item->matches->len), item->name, scratch,
-         item->matches->len);
-        break;
-
-    case ALBUM:
-        string = g_strdup_printf (dngettext (PACKAGE, "%s\n %d song by %s",
-         "%s\n %d songs by %s", item->matches->len), item->name,
-         item->matches->len, item->parent->name);
-        break;
-    }
-
-    g_value_take_string (value, string);
-}
-
-static bool_t list_get_selected (void * user, int row)
-{
-    g_return_val_if_fail (selection && row >= 0 && row < selection->len, FALSE);
-    return selection->data[row];
-}
-
-static void list_set_selected (void * user, int row, bool_t selected)
-{
-    g_return_if_fail (selection && row >= 0 && row < selection->len);
-    selection->data[row] = selected;
-}
-
-static void list_select_all (void * user, bool_t selected)
-{
-    g_return_if_fail (selection);
-    memset (selection->data, selected, selection->len);
-}
-
-static void list_activate_row (void * user, int row)
-{
-    action_play ();
-}
-
-static void list_right_click (void * user, GdkEventButton * event)
-{
-    static const AudguiMenuItem items[] = {
-        {N_("_Play"), "media-playback-start", .func = action_play},
-        {N_("_Create Playlist"), "document-new", .func = action_create_playlist},
-        {N_("_Add to Playlist"), "list-add", .func = action_add_to_playlist}
-    };
-
-    GtkWidget * menu = gtk_menu_new ();
-    audgui_menu_init (menu, items, ARRAY_LEN (items), NULL);
-    gtk_menu_popup ((GtkMenu *) menu, NULL, NULL, NULL, NULL, event->button, event->time);
-}
-
-static const AudguiListCallbacks list_callbacks = {
- .get_value = list_get_value,
- .get_selected = list_get_selected,
- .set_selected = list_set_selected,
- .select_all = list_select_all,
- .activate_row = list_activate_row,
- .right_click = list_right_click};
-
-static void entry_cb (GtkEntry * entry, void * unused)
-{
-    set_search_phrase (gtk_entry_get_text ((GtkEntry *) entry));
-    schedule_search ();
-}
-
-static void refresh_cb (GtkButton * button, GtkWidget * chooser)
-{
-    char * path = gtk_file_chooser_get_filename ((GtkFileChooser *) chooser);
-    begin_add (path);
-    g_free (path);
-
-    update_database ();
-}
-
-static void * search_get_widget (void)
-{
-    GtkWidget * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-
-    entry = gtk_entry_new ();
-    gtk_entry_set_icon_from_icon_name ((GtkEntry *) entry, GTK_ENTRY_ICON_PRIMARY, "edit-find");
-    gtk_entry_set_placeholder_text ((GtkEntry *) entry, _("Search library"));
-    g_signal_connect (entry, "destroy", (GCallback) gtk_widget_destroyed, & entry);
-    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);
-    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);
-
-    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);
-
-    scrolled = gtk_scrolled_window_new (NULL, NULL);
-    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);
-
-    results_list = audgui_list_new (& list_callbacks, NULL, items ? index_count (items) : 0);
-    g_signal_connect (results_list, "destroy", (GCallback) gtk_widget_destroyed, & results_list);
-    gtk_tree_view_set_headers_visible ((GtkTreeView *) results_list, FALSE);
-    audgui_list_add_column (results_list, NULL, 0, G_TYPE_STRING, -1);
-    gtk_container_add ((GtkContainer *) scrolled, results_list);
-
-    GtkWidget * hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 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);
-
-    char * path = get_path ();
-    gtk_file_chooser_set_filename ((GtkFileChooser *) chooser, path);
-    str_unref (path);
-
-    GtkWidget * button = gtk_button_new ();
-    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);
-
-    g_signal_connect (entry, "changed", (GCallback) entry_cb, NULL);
-    g_signal_connect (entry, "activate", (GCallback) action_play, NULL);
-    g_signal_connect (button, "clicked", (GCallback) refresh_cb, chooser);
-
-    gtk_widget_show_all (vbox);
-    gtk_widget_show (results_list);
-    show_hide_widgets ();
-
-    return vbox;
-}
-
-int search_take_message (const char * code, const void * data, int size)
-{
-    if (! strcmp (code, "grab focus"))
-    {
-        if (entry)
-            gtk_widget_grab_focus (entry);
-        return 0;
-    }
-
-    return EINVAL;
-}
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Search Tool"),
-    .domain = PACKAGE,
-    .init = search_init,
-    .cleanup = search_cleanup,
-    .get_widget = search_get_widget,
-    .take_message = search_take_message
-)
diff --git a/src/search-tool/search-tool.cc b/src/search-tool/search-tool.cc
new file mode 100644
index 000000000000..f04ed2024c7a
--- /dev/null
+++ b/src/search-tool/search-tool.cc
@@ -0,0 +1,759 @@
+/*
+ * search-tool.c
+ * Copyright 2011-2012 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 <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/multihash.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/list.h>
+#include <libaudgui/menu.h>
+
+#define MAX_RESULTS 20
+#define SEARCH_DELAY 300
+
+class SearchTool : public GeneralPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Search Tool"),
+        PACKAGE
+    };
+
+    constexpr SearchTool () : GeneralPlugin (info, false) {}
+
+    void * get_gtk_widget ();
+    int take_message (const char * code, const void * data, int size);
+};
+
+EXPORT SearchTool 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;
+};
+
+static int playlist_id;
+static Index<String> search_terms;
+
+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 GtkWidget * entry, * help_label, * wait_label, * scrolled, * results_list, * stats_label;
+
+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 (gboolean require_added, gboolean 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 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");
+    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::Guess);
+
+        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);
+
+    selection.remove (0, -1);
+    selection.insert (0, items.len ());
+    if (items.len ())
+        selection[0] = true;
+}
+
+static bool filter_cb (const char * filename, void * unused)
+{
+    return ! added_table.lookup (String (filename));
+}
+
+static void begin_add (const char * path)
+{
+    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);
+
+    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 ()
+{
+    if (playlist_id < 0)
+    {
+        gtk_widget_hide (wait_label);
+        gtk_widget_hide (scrolled);
+        gtk_widget_hide (stats_label);
+        gtk_widget_show (help_label);
+    }
+    else
+    {
+        gtk_widget_hide (help_label);
+
+        if (database_valid)
+        {
+            gtk_widget_hide (wait_label);
+            gtk_widget_show (scrolled);
+            gtk_widget_show (stats_label);
+        }
+        else
+        {
+            gtk_widget_hide (scrolled);
+            gtk_widget_hide (stats_label);
+            gtk_widget_show (wait_label);
+        }
+    }
+}
+
+static int search_timeout (void * unused = nullptr)
+{
+    do_search ();
+
+    audgui_list_delete_rows (results_list, 0, audgui_list_row_count (results_list));
+    audgui_list_insert_rows (results_list, 0, items.len ());
+
+    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));
+    }
+
+    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);
+}
+
+static void update_database ()
+{
+    int list = get_playlist (true, true);
+
+    if (list >= 0)
+    {
+        create_database (list);
+        search_timeout ();
+    }
+    else
+    {
+        destroy_database ();
+        audgui_list_delete_rows (results_list, 0, audgui_list_row_count (results_list));
+        gtk_label_set_text ((GtkLabel *) stats_label, "");
+    }
+
+    show_hide_widgets ();
+}
+
+static void add_complete_cb (void * unused, void * unused2)
+{
+    int list = get_playlist (true, false);
+    if (list < 0)
+        return;
+
+    if (adding)
+    {
+        adding = false;
+        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);
+
+    if (search_source)
+    {
+        g_source_remove (search_source);
+        search_source = 0;
+    }
+
+    search_terms.clear ();
+    items.clear ();
+    selection.clear ();
+
+    added_table.clear ();
+    destroy_database ();
+}
+
+static void do_add (gboolean play, String & title)
+{
+    if (search_source)
+        search_timeout ();
+
+    int list = aud_playlist_by_unique_id (playlist_id);
+    int n_items = items.len ();
+    int n_selected = 0;
+
+    Index<PlaylistAddItem> add;
+
+    for (int i = 0; i < n_items; i ++)
+    {
+        if (! selection[i])
+            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::Guess)
+            );
+        }
+
+        n_selected ++;
+        if (n_selected == 1)
+            title = item->name;
+    }
+
+    if (n_selected != 1)
+        title = String ();
+
+    aud_playlist_entry_insert_batch (aud_playlist_get_active (), -1, std::move (add), play);
+}
+
+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));
+
+    String title;
+    do_add (true, title);
+}
+
+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);
+}
+
+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);
+}
+
+static void list_get_value (void * user, int row, int column, GValue * value)
+{
+    g_return_if_fail (row >= 0 && row < items.len ());
+
+    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);
+    }
+
+    g_value_set_string (value, string);
+}
+
+static bool list_get_selected (void * user, int row)
+{
+    g_return_val_if_fail (row >= 0 && row < selection.len (), false);
+    return selection[row];
+}
+
+static void list_set_selected (void * user, int row, bool selected)
+{
+    g_return_if_fail (row >= 0 && row < selection.len ());
+    selection[row] = selected;
+}
+
+static void list_select_all (void * user, bool selected)
+{
+    for (bool & s : selection)
+        s = selected;
+}
+
+static void list_activate_row (void * user, int row)
+{
+    action_play ();
+}
+
+static void list_right_click (void * user, GdkEventButton * event)
+{
+    static const AudguiMenuItem items[] = {
+        MenuCommand (N_("_Play"), "media-playback-start",
+         0, (GdkModifierType) 0, action_play),
+        MenuCommand (N_("_Create Playlist"), "document-new",
+         0, (GdkModifierType) 0, action_create_playlist),
+        MenuCommand (N_("_Add to Playlist"), "list-add",
+         0, (GdkModifierType) 0, action_add_to_playlist)
+    };
+
+    GtkWidget * menu = gtk_menu_new ();
+    audgui_menu_init (menu, {items}, nullptr);
+    gtk_menu_popup ((GtkMenu *) menu, nullptr, nullptr, nullptr, nullptr, event->button, event->time);
+}
+
+static const AudguiListCallbacks list_callbacks = {
+    list_get_value,
+    list_get_selected,
+    list_set_selected,
+    list_select_all,
+    list_activate_row,
+    list_right_click
+};
+
+static void entry_cb (GtkEntry * entry, void * unused)
+{
+    set_search_phrase (gtk_entry_get_text ((GtkEntry *) entry));
+    schedule_search ();
+}
+
+static void refresh_cb (GtkButton * button, GtkWidget * chooser)
+{
+    char * path = gtk_file_chooser_get_filename ((GtkFileChooser *) chooser);
+    begin_add (path);
+    g_free (path);
+
+    update_database ();
+}
+
+void * SearchTool::get_gtk_widget ()
+{
+    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);
+
+    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);
+    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);
+
+    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);
+
+    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);
+
+    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);
+    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);
+
+    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_file_chooser_set_filename ((GtkFileChooser *) chooser, get_path ());
+
+    GtkWidget * button = gtk_button_new ();
+    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);
+
+    search_init ();
+
+    g_signal_connect (vbox, "destroy", (GCallback) search_cleanup, nullptr);
+    g_signal_connect (entry, "changed", (GCallback) entry_cb, nullptr);
+    g_signal_connect (entry, "activate", (GCallback) action_play, nullptr);
+    g_signal_connect (button, "clicked", (GCallback) refresh_cb, chooser);
+
+    gtk_widget_show_all (vbox);
+    gtk_widget_show (results_list);
+    show_hide_widgets ();
+
+    return vbox;
+}
+
+int SearchTool::take_message (const char * code, const void * data, int size)
+{
+    if (! strcmp (code, "grab focus"))
+    {
+        if (entry)
+            gtk_widget_grab_focus (entry);
+        return 0;
+    }
+
+    return -1;
+}
diff --git a/src/sid/Makefile b/src/sid/Makefile
index e72b545ba571..d3f8e9ecef19 100644
--- a/src/sid/Makefile
+++ b/src/sid/Makefile
@@ -1,13 +1,8 @@
 PLUGIN = sid${PLUGIN_SUFFIX}
 
-SRCS = xs_support.c	\
-       xs_config.c	\
-       xs_length.c	\
-       xs_md5.c \
-       xs_stil.c	\
+SRCS = xs_config.cc	\
        xs_sidplay2.cc	\
-       xs_slsup.c	\
-       xmms-sid.c
+       xmms-sid.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -17,5 +12,5 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CXXFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} -DSIDDATADIR="\"$(datadir)/\"" -I../.. ${SIDPLAYFP_CFLAGS} ${GLIB_CFLAGS}
-LIBS += -lm ${SIDPLAYFP_LIBS} ${GLIB_LIBS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -DSIDDATADIR="\"$(datadir)/\"" -I../.. ${SIDPLAYFP_CFLAGS}
+LIBS += -lm ${SIDPLAYFP_LIBS}
diff --git a/src/sid/xmms-sid.c b/src/sid/xmms-sid.c
deleted file mode 100644
index 50ce3d16d815..000000000000
--- a/src/sid/xmms-sid.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   Main source file
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
-
-   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 along
-   with this program; if not, write to the Free Software Foundation, Inc.,
-   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libaudcore/audstrings.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-
-#include "xs_sidplay2.h"
-
-
-/*
- * Global variables
- */
-xs_status_t xs_status;
-pthread_mutex_t xs_status_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void xs_get_song_tuple_info(Tuple *pResult, xs_tuneinfo_t *pInfo, int subTune);
-
-/*
- * Initialization functions
- */
-bool_t xs_init(void)
-{
-    bool_t success;
-
-    /* Initialize and get configuration */
-    xs_init_configuration();
-
-    pthread_mutex_lock(&xs_status_mutex);
-    pthread_mutex_lock(&xs_cfg_mutex);
-
-    /* Initialize status and sanitize configuration */
-    memset(&xs_status, 0, sizeof(xs_status));
-
-    if (xs_cfg.audioFrequency < 8000)
-        xs_cfg.audioFrequency = 8000;
-
-    xs_status.audioFrequency = xs_cfg.audioFrequency;
-    xs_status.audioChannels = xs_cfg.audioChannels;
-
-    /* Try to initialize emulator engine */
-    success = xs_sidplayfp_init(&xs_status);
-
-    /* Get settings back, in case the chosen emulator backend changed them */
-    xs_cfg.audioFrequency = xs_status.audioFrequency;
-    xs_cfg.audioChannels = xs_status.audioChannels;
-
-    pthread_mutex_unlock(&xs_status_mutex);
-    pthread_mutex_unlock(&xs_cfg_mutex);
-
-    if (! success)
-        return FALSE;
-
-    /* Initialize song-length database */
-    xs_songlen_close();
-    if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0)) {
-        xs_error("Error initializing song-length database!\n");
-    }
-
-    /* Initialize STIL database */
-    xs_stil_close();
-    if (xs_cfg.stilDBEnable && (xs_stil_init() != 0)) {
-        xs_error("Error initializing STIL database!\n");
-    }
-
-    return TRUE;
-}
-
-
-/*
- * Shut down XMMS-SID
- */
-void xs_close(void)
-{
-    xs_tuneinfo_free(xs_status.tuneInfo);
-    xs_status.tuneInfo = NULL;
-
-    xs_sidplayfp_delete (& xs_status);
-    xs_sidplayfp_close (& xs_status);
-
-    xs_songlen_close();
-    xs_stil_close();
-}
-
-
-/*
- * Start playing the given file
- */
-bool_t xs_play_file(const char *filename, VFSFile *file)
-{
-    xs_tuneinfo_t *tmpTune;
-    int audioBufSize, bufRemaining, tmpLength, subTune = -1;
-    char *audioBuffer = NULL, *oversampleBuffer = NULL;
-    Tuple *tmpTuple;
-
-    uri_parse (filename, NULL, NULL, NULL, & subTune);
-
-    /* Get tune information */
-    pthread_mutex_lock(&xs_status_mutex);
-
-    if (! (xs_status.tuneInfo = xs_sidplayfp_getinfo (filename)))
-    {
-        pthread_mutex_unlock(&xs_status_mutex);
-        return FALSE;
-    }
-
-    /* Initialize the tune */
-    if (! xs_sidplayfp_load (& xs_status, filename))
-    {
-        pthread_mutex_unlock(&xs_status_mutex);
-        xs_tuneinfo_free(xs_status.tuneInfo);
-        xs_status.tuneInfo = NULL;
-        return FALSE;
-    }
-
-    bool_t error = FALSE;
-
-    /* Set general status information */
-    tmpTune = xs_status.tuneInfo;
-
-    if (subTune < 1 || subTune > xs_status.tuneInfo->nsubTunes)
-        xs_status.currSong = xs_status.tuneInfo->startTune;
-    else
-        xs_status.currSong = subTune;
-
-    int channels = xs_status.audioChannels;
-
-    /* Allocate audio buffer */
-    audioBufSize = xs_status.audioFrequency * channels * FMT_SIZEOF (FMT_S16_NE);
-    if (audioBufSize < 512) audioBufSize = 512;
-
-    audioBuffer = (char *) malloc(audioBufSize);
-    if (audioBuffer == NULL) {
-        xs_error("Couldn't allocate memory for audio data buffer!\n");
-        pthread_mutex_unlock(&xs_status_mutex);
-        goto xs_err_exit;
-    }
-
-    /* Check minimum playtime */
-    tmpLength = tmpTune->subTunes[xs_status.currSong - 1].tuneLength;
-    if (xs_cfg.playMinTimeEnable && (tmpLength >= 0)) {
-        if (tmpLength < xs_cfg.playMinTime)
-            tmpLength = xs_cfg.playMinTime;
-    }
-
-    /* Initialize song */
-    if (!xs_sidplayfp_initsong(&xs_status)) {
-        xs_error("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
-            tmpTune->sidFilename, xs_status.currSong);
-        pthread_mutex_unlock(&xs_status_mutex);
-        goto xs_err_exit;
-    }
-
-    /* Open the audio output */
-    if (!aud_input_open_audio(FMT_S16_NE, xs_status.audioFrequency, channels))
-    {
-        xs_error("Couldn't open audio output (fmt=%x, freq=%i, nchan=%i)!\n",
-            FMT_S16_NE,
-            xs_status.audioFrequency,
-            channels);
-
-        pthread_mutex_unlock(&xs_status_mutex);
-        goto xs_err_exit;
-    }
-
-    /* Set song information for current subtune */
-    xs_sidplayfp_updateinfo(&xs_status);
-    tmpTuple = tuple_new_from_filename(tmpTune->sidFilename);
-    xs_get_song_tuple_info(tmpTuple, tmpTune, xs_status.currSong);
-
-    pthread_mutex_unlock(&xs_status_mutex);
-
-    aud_input_set_tuple(tmpTuple);
-
-    while (! aud_input_check_stop ())
-    {
-        bufRemaining = xs_sidplayfp_fillbuffer(&xs_status, audioBuffer, audioBufSize);
-
-        aud_input_write_audio (audioBuffer, bufRemaining);
-
-        /* Check if we have played enough */
-        if (xs_cfg.playMaxTimeEnable) {
-            if (xs_cfg.playMaxTimeUnknown) {
-                if (tmpLength < 0 &&
-                    aud_input_written_time() >= xs_cfg.playMaxTime * 1000)
-                    break;
-            } else {
-                if (aud_input_written_time() >= xs_cfg.playMaxTime * 1000)
-                    break;
-            }
-        }
-
-        if (tmpLength >= 0) {
-            if (aud_input_written_time() >= tmpLength * 1000)
-                break;
-        }
-    }
-
-DONE:
-    free(audioBuffer);
-    free(oversampleBuffer);
-
-    /* Set playing status to false (stopped), thus when
-     * XMMS next calls xs_get_time(), it can return appropriate
-     * value "not playing" status and XMMS knows to move to
-     * next entry in the playlist .. or whatever it wishes.
-     */
-    pthread_mutex_lock(&xs_status_mutex);
-
-    /* Free tune information */
-    xs_sidplayfp_delete(&xs_status);
-    xs_tuneinfo_free(xs_status.tuneInfo);
-    xs_status.tuneInfo = NULL;
-    pthread_mutex_unlock(&xs_status_mutex);
-
-    /* Exit the playing thread */
-    return ! error;
-
-xs_err_exit:
-    error = TRUE;
-    goto DONE;
-}
-
-
-/*
- * Return song information Tuple
- */
-static void xs_get_song_tuple_info(Tuple *tuple, xs_tuneinfo_t *info, int subTune)
-{
-    tuple_set_str(tuple, FIELD_TITLE, info->sidName);
-    tuple_set_str(tuple, FIELD_ARTIST, info->sidComposer);
-    tuple_set_str(tuple, FIELD_COPYRIGHT, info->sidCopyright);
-    tuple_set_str(tuple, FIELD_CODEC, info->sidFormat);
-
-#if 0
-    switch (info->sidModel) {
-        case XS_SIDMODEL_6581: tmpStr = "6581"; break;
-        case XS_SIDMODEL_8580: tmpStr = "8580"; break;
-        case XS_SIDMODEL_ANY: tmpStr = "ANY"; break;
-        default: tmpStr = "?"; break;
-    }
-    tuple_set_str(tuple, -1, "sid-model", tmpStr);
-#endif
-
-    /* Get sub-tune information, if available */
-    if (subTune < 0 || info->startTune > info->nsubTunes)
-        subTune = info->startTune;
-
-    if (subTune > 0 && subTune <= info->nsubTunes) {
-        int tmpInt = info->subTunes[subTune - 1].tuneLength;
-        tuple_set_int(tuple, FIELD_LENGTH, (tmpInt < 0) ? -1 : tmpInt * 1000);
-
-#if 0
-        tmpInt = info->subTunes[subTune - 1].tuneSpeed;
-        if (tmpInt > 0) {
-            switch (tmpInt) {
-            case XS_CLOCK_PAL: tmpStr = "PAL"; break;
-            case XS_CLOCK_NTSC: tmpStr = "NTSC"; break;
-            case XS_CLOCK_ANY: tmpStr = "ANY"; break;
-            case XS_CLOCK_VBI: tmpStr = "VBI"; break;
-            case XS_CLOCK_CIA: tmpStr = "CIA"; break;
-            default:
-                snprintf(tmpStr2, sizeof(tmpStr2), "%dHz", tmpInt);
-                tmpStr = tmpStr2;
-                break;
-            }
-        } else
-            tmpStr = "?";
-
-        tuple_set_str(tuple, -1, "sid-speed", tmpStr);
-#endif
-    } else
-        subTune = 1;
-
-    tuple_set_int(tuple, FIELD_SUBSONG_NUM, info->nsubTunes);
-    tuple_set_int(tuple, FIELD_SUBSONG_ID, subTune);
-    tuple_set_int(tuple, FIELD_TRACK_NUMBER, subTune);
-}
-
-
-static void xs_fill_subtunes(Tuple *tuple, xs_tuneinfo_t *info)
-{
-    int count, found;
-    int subtunes[info->nsubTunes];
-
-    for (found = count = 0; count < info->nsubTunes; count++) {
-        if (count + 1 == info->startTune || !xs_cfg.subAutoMinOnly ||
-            info->subTunes[count].tuneLength < 0 ||
-            info->subTunes[count].tuneLength >= xs_cfg.subAutoMinTime)
-            subtunes[found ++] = count + 1;
-    }
-
-    tuple_set_subtunes (tuple, found, subtunes);
-}
-
-Tuple * xs_probe_for_tuple(const char *filename, VFSFile *fd)
-{
-    Tuple *tuple;
-    xs_tuneinfo_t *info;
-    int tune = -1;
-
-    pthread_mutex_lock(&xs_status_mutex);
-    if (!xs_sidplayfp_probe(fd)) {
-        pthread_mutex_unlock(&xs_status_mutex);
-        return NULL;
-    }
-    pthread_mutex_unlock(&xs_status_mutex);
-
-    /* Get information from URL */
-    tuple = tuple_new_from_filename (filename);
-    tune = tuple_get_int (tuple, FIELD_SUBSONG_NUM);
-
-    /* Get tune information from emulation engine */
-    pthread_mutex_lock(&xs_status_mutex);
-    info = xs_sidplayfp_getinfo (filename);
-    pthread_mutex_unlock(&xs_status_mutex);
-
-    if (info == NULL)
-        return tuple;
-
-    xs_get_song_tuple_info(tuple, info, tune);
-
-    if (xs_cfg.subAutoEnable && info->nsubTunes > 1 && ! tune)
-        xs_fill_subtunes(tuple, info);
-
-    xs_tuneinfo_free(info);
-
-    return tuple;
-}
-
-/*
- * Plugin header
- */
-static const char *xs_sid_fmts[] = { "sid", "psid", NULL };
-
-AUD_INPUT_PLUGIN
-(
-    .name = "SID Player",               /* Plugin description */
-    .domain = PACKAGE,
-    .init = xs_init,                    /* Initialization */
-    .cleanup = xs_close,                /* Cleanup */
-    .play = xs_play_file,               /* Play given file */
-    .probe_for_tuple = xs_probe_for_tuple,
-
-    .extensions = xs_sid_fmts,          /* File ext assist */
-    .have_subtune = TRUE,
-
-    /* medium priority (slow to initialize) */
-    .priority = 5,
-)
diff --git a/src/sid/xmms-sid.cc b/src/sid/xmms-sid.cc
new file mode 100644
index 000000000000..f1f59e96f028
--- /dev/null
+++ b/src/sid/xmms-sid.cc
@@ -0,0 +1,326 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Main source file
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
+   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
+
+   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 along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include "xs_config.h"
+#include "xs_sidplay2.h"
+
+class SIDPlugin : public InputPlugin
+{
+public:
+    static const char *const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("SID Player"),
+        PACKAGE,
+        nullptr,
+        & sid_prefs
+    };
+
+    static constexpr auto iinfo = InputInfo(FlagSubtunes)
+        .with_priority(5) /* medium priority (slow to initialize) */
+        .with_exts(exts);
+
+    constexpr SIDPlugin() : InputPlugin(info, iinfo) {}
+
+    bool delayed_init();
+    void cleanup();
+
+    bool is_our_file(const char *filename, VFSFile &file);
+    Tuple read_tuple(const char *filename, VFSFile &file);
+    bool play(const char *filename, VFSFile &file);
+
+private:
+    pthread_mutex_t m_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+    bool m_initialized = false;
+    bool m_init_failed = false;
+};
+
+EXPORT SIDPlugin aud_plugin_instance;
+
+static void xs_get_song_tuple_info(Tuple &pResult, const xs_tuneinfo_t &info, int subTune);
+
+/*
+ * Initialization functions
+ */
+bool SIDPlugin::delayed_init()
+{
+    pthread_mutex_lock(&m_init_mutex);
+
+    if (!m_initialized && !m_init_failed)
+    {
+        /* Initialize and get configuration */
+        xs_init_configuration();
+
+        /* Try to initialize emulator engine */
+        m_initialized = xs_sidplayfp_init();
+        if (!m_initialized)
+            m_init_failed = true;
+    }
+
+    pthread_mutex_unlock(&m_init_mutex);
+    return m_initialized;
+}
+
+
+/*
+ * Shut down XMMS-SID
+ */
+void SIDPlugin::cleanup()
+{
+    if (m_initialized)
+    {
+        xs_sidplayfp_close();
+        m_initialized = false;
+    }
+
+    m_init_failed = false;
+}
+
+
+/*
+ * Check whether this is a SID file
+ */
+bool SIDPlugin::is_our_file(const char *filename, VFSFile &file)
+{
+    char buf[4];
+    if (file.fread (buf, 1, 4) != 4)
+        return false;
+
+    // does not require xs_sidplayfp_init()
+    return xs_sidplayfp_probe(buf, 4);
+}
+
+
+/*
+ * Start playing the given file
+ */
+bool SIDPlugin::play(const char *filename, VFSFile &file)
+{
+    if (!delayed_init())
+        return false;
+
+    /* Load file */
+    Index<char> buf = file.read_all ();
+    if (!xs_sidplayfp_probe(buf.begin(), buf.len()))
+        return false;
+
+    /* Get tune information */
+    xs_tuneinfo_t info;
+    if (!xs_sidplayfp_getinfo(info, filename, buf.begin(), buf.len()))
+        return false;
+
+    /* Initialize the tune */
+    if (!xs_sidplayfp_load(buf.begin(), buf.len()))
+        return false;
+
+    /* Set general status information */
+    int subTune = -1;
+    uri_parse(filename, nullptr, nullptr, nullptr, &subTune);
+
+    if (subTune < 1 || subTune > info.nsubTunes)
+        subTune = info.startTune;
+
+    /* Check minimum playtime */
+    int tmpLength = info.subTunes[subTune - 1].tuneLength;
+    if (xs_cfg.playMinTimeEnable && (tmpLength >= 0)) {
+        if (tmpLength < xs_cfg.playMinTime)
+            tmpLength = xs_cfg.playMinTime;
+    }
+
+    /* Initialize song */
+    if (!xs_sidplayfp_initsong(subTune)) {
+        AUDERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
+            (const char *) info.sidFilename, subTune);
+        return false;
+    }
+
+    /* Set song information for current subtune */
+    xs_sidplayfp_updateinfo(info, subTune);
+
+    Tuple tmpTuple;
+    tmpTuple.set_filename(info.sidFilename);
+    xs_get_song_tuple_info(tmpTuple, info, subTune);
+    set_playback_tuple(std::move(tmpTuple));
+
+    /* Open the audio output */
+    open_audio(FMT_S16_NE, xs_cfg.audioFrequency, xs_cfg.audioChannels);
+
+    /* Allocate audio buffer */
+    int audioBufSize = xs_cfg.audioFrequency * xs_cfg.audioChannels * 2;
+    if (audioBufSize < 512)
+        audioBufSize = 512;
+
+    char *audioBuffer = new char[audioBufSize];
+    int64_t bytes_played = 0;
+
+    while (! check_stop ())
+    {
+        if (check_seek () >= 0)
+            AUDWARN ("Seeking is not implemented, ignoring.\n");
+
+        int bufRemaining = xs_sidplayfp_fillbuffer(audioBuffer, audioBufSize);
+
+        write_audio (audioBuffer, bufRemaining);
+        bytes_played += bufRemaining;
+
+        /* Check if we have played enough */
+        int time_played = aud::rescale<int64_t> (bytes_played,
+         xs_cfg.audioFrequency * xs_cfg.audioChannels * 2, 1000);
+
+        if (xs_cfg.playMaxTimeEnable) {
+            if (xs_cfg.playMaxTimeUnknown) {
+                if (tmpLength < 0 &&
+                    time_played >= xs_cfg.playMaxTime * 1000)
+                    break;
+            } else {
+                if (time_played >= xs_cfg.playMaxTime * 1000)
+                    break;
+            }
+        }
+
+        if (tmpLength >= 0) {
+            if (time_played >= tmpLength * 1000)
+                break;
+        }
+    }
+
+    delete[] audioBuffer;
+
+    return true;
+}
+
+
+/*
+ * Return song information Tuple
+ */
+static void xs_get_song_tuple_info(Tuple &tuple, const xs_tuneinfo_t &info, int subTune)
+{
+    tuple.set_str (Tuple::Title, info.sidName);
+    tuple.set_str (Tuple::Artist, info.sidComposer);
+    tuple.set_str (Tuple::Copyright, info.sidCopyright);
+    tuple.set_str (Tuple::Codec, info.sidFormat);
+
+#if 0
+    switch (info.sidModel) {
+        case XS_SIDMODEL_6581: tmpStr = "6581"; break;
+        case XS_SIDMODEL_8580: tmpStr = "8580"; break;
+        case XS_SIDMODEL_ANY: tmpStr = "ANY"; break;
+        default: tmpStr = "?"; break;
+    }
+    tuple_set_str(tuple, -1, "sid-model", tmpStr);
+#endif
+
+    /* Get sub-tune information, if available */
+    if (subTune < 0 || info.startTune > info.nsubTunes)
+        subTune = info.startTune;
+
+    if (subTune > 0 && subTune <= info.nsubTunes) {
+        int tmpInt = info.subTunes[subTune - 1].tuneLength;
+        tuple.set_int (Tuple::Length, (tmpInt < 0) ? -1 : tmpInt * 1000);
+
+#if 0
+        tmpInt = info.subTunes[subTune - 1].tuneSpeed;
+        if (tmpInt > 0) {
+            switch (tmpInt) {
+            case XS_CLOCK_PAL: tmpStr = "PAL"; break;
+            case XS_CLOCK_NTSC: tmpStr = "NTSC"; break;
+            case XS_CLOCK_ANY: tmpStr = "ANY"; break;
+            case XS_CLOCK_VBI: tmpStr = "VBI"; break;
+            case XS_CLOCK_CIA: tmpStr = "CIA"; break;
+            default:
+                snprintf(tmpStr2, sizeof(tmpStr2), "%dHz", tmpInt);
+                tmpStr = tmpStr2;
+                break;
+            }
+        } else
+            tmpStr = "?";
+
+        tuple_set_str(tuple, -1, "sid-speed", tmpStr);
+#endif
+    } else
+        subTune = 1;
+
+    tuple.set_int (Tuple::NumSubtunes, info.nsubTunes);
+    tuple.set_int (Tuple::Subtune, subTune);
+    tuple.set_int (Tuple::Track, subTune);
+}
+
+
+static void xs_fill_subtunes(Tuple &tuple, const xs_tuneinfo_t &info)
+{
+    Index<int> subtunes;
+
+    for (int count = 0; count < info.nsubTunes; count++) {
+        if (count + 1 == info.startTune || !xs_cfg.subAutoMinOnly ||
+            info.subTunes[count].tuneLength < 0 ||
+            info.subTunes[count].tuneLength >= xs_cfg.subAutoMinTime)
+            subtunes.append (count + 1);
+    }
+
+    tuple.set_subtunes (subtunes.len (), subtunes.begin ());
+}
+
+Tuple SIDPlugin::read_tuple(const char *filename, VFSFile &file)
+{
+    Tuple tuple;
+
+    if (!delayed_init())
+        return tuple;
+
+    xs_tuneinfo_t info;
+    int tune = -1;
+
+    Index<char> buf = file.read_all ();
+    if (!xs_sidplayfp_probe(buf.begin(), buf.len()))
+        return tuple;
+
+    /* Get information from URL */
+    tuple.set_filename (filename);
+    tune = tuple.get_int (Tuple::Subtune);
+
+    /* Get tune information from emulation engine */
+    if (!xs_sidplayfp_getinfo(info, filename, buf.begin(), buf.len()))
+        return tuple;
+
+    xs_get_song_tuple_info(tuple, info, tune);
+
+    if (xs_cfg.subAutoEnable && info.nsubTunes > 1 && tune < 0)
+        xs_fill_subtunes(tuple, info);
+
+    return tuple;
+}
+
+/*
+ * Plugin header
+ */
+const char *const SIDPlugin::exts[] = { "sid", "psid", nullptr };
diff --git a/src/sid/xmms-sid.h b/src/sid/xmms-sid.h
index 0093055478c9..13553ee74db5 100644
--- a/src/sid/xmms-sid.h
+++ b/src/sid/xmms-sid.h
@@ -23,48 +23,29 @@
 #ifndef XMMS_SID_H
 #define XMMS_SID_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <libaudcore/core.h>
+#include <libaudcore/index.h>
+#include <libaudcore/objects.h>
 
 /*
  * Some constants and defines
  */
 
-/* Size for some small buffers (always static variables) */
-#define XS_BUF_SIZE             (2048)
-
 /* Default audio rendering frequency in Hz
  */
 #define XS_AUDIO_FREQ           (44100)
 
-/* Size of data buffer used for SID-tune MD5 hash calculation.
- * If this is too small, the computed hash will be incorrect.
- * Largest SID files I've seen are ~70kB. */
-#define XS_SIDBUF_SIZE          (128*1024)
-
 /* Plugin-wide typedefs
  */
 typedef struct {
-    int tuneSpeed, tuneLength;
-    bool_t tunePlayed;
+    int tuneSpeed = -1;
+    int tuneLength = -1;
 } xs_subtuneinfo_t;
 
 typedef struct {
-    char *sidFilename, *sidName, *sidComposer, *sidCopyright, *sidFormat;
+    String sidFilename, sidName, sidComposer, sidCopyright, sidFormat;
     int loadAddr, initAddr, playAddr, dataFileLen, sidModel;
     int nsubTunes, startTune;
-    xs_subtuneinfo_t *subTunes;
+    Index<xs_subtuneinfo_t> subTunes;
 } xs_tuneinfo_t;
 
-/* Plugin function prototypes
- */
-#define xs_verror(fmt, args) vfprintf(stderr, fmt, args)
-#define xs_error(...) fprintf(stderr, __VA_ARGS__)
-
-#ifdef __cplusplus
-}
-#endif
 #endif /* XMMS_SID_H */
diff --git a/src/sid/xs_config.c b/src/sid/xs_config.c
deleted file mode 100644
index 1e663b437938..000000000000
--- a/src/sid/xs_config.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   Configuration dialog
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
-
-   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.
-*/
-
-#include "xs_config.h"
-
-#include <string.h>
-
-#include "xmms-sid.h"
-#include "xs_support.h"
-
-/*
- * Configuration specific stuff
- */
-pthread_mutex_t xs_cfg_mutex = PTHREAD_MUTEX_INITIALIZER;
-struct xs_cfg_t xs_cfg;
-
-/* Reset/initialize the configuration
- */
-void xs_init_configuration(void)
-{
-    /* Lock configuration mutex */
-    pthread_mutex_lock(&xs_cfg_mutex);
-
-    memset(&xs_cfg, 0, sizeof(xs_cfg));
-
-    /* Initialize values with sensible defaults */
-    xs_cfg.audioChannels = XS_CHN_STEREO;
-    xs_cfg.audioFrequency = XS_AUDIO_FREQ;
-
-    xs_cfg.mos8580 = FALSE;
-    xs_cfg.forceModel = FALSE;
-
-    /* Filter values */
-    xs_cfg.emulateFilters = TRUE;
-
-    xs_cfg.clockSpeed = XS_CLOCK_PAL;
-    xs_cfg.forceSpeed = FALSE;
-
-    xs_cfg.playMaxTimeEnable = FALSE;
-    xs_cfg.playMaxTimeUnknown = FALSE;
-    xs_cfg.playMaxTime = 150;
-
-    xs_cfg.playMinTimeEnable = FALSE;
-    xs_cfg.playMinTime = 15;
-
-    xs_cfg.songlenDBEnable = FALSE;
-    xs_pstrcpy(&xs_cfg.songlenDBPath, "~/C64Music/DOCUMENTS/Songlengths.txt");
-
-    xs_cfg.stilDBEnable = FALSE;
-    xs_pstrcpy(&xs_cfg.stilDBPath, "~/C64Music/DOCUMENTS/STIL.txt");
-    xs_pstrcpy(&xs_cfg.hvscPath, "~/C64Music");
-
-    xs_cfg.subAutoEnable = TRUE;
-    xs_cfg.subAutoMinOnly = TRUE;
-    xs_cfg.subAutoMinTime = 15;
-
-    /* Unlock the configuration */
-    pthread_mutex_unlock(&xs_cfg_mutex);
-}
diff --git a/src/sid/xs_config.cc b/src/sid/xs_config.cc
new file mode 100644
index 000000000000..f91062210458
--- /dev/null
+++ b/src/sid/xs_config.cc
@@ -0,0 +1,140 @@
+/*
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Configuration dialog
+
+   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
+   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
+
+   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.
+*/
+
+#include "xmms-sid.h"
+#include "xs_config.h"
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+/*
+ * Configuration specific stuff
+ */
+struct xs_cfg_t xs_cfg;
+
+static constexpr const char * const defaults[] = {
+    "audioChannels", aud::numeric_string<XS_CHN_STEREO>::str,
+    "audioFrequency", aud::numeric_string<XS_AUDIO_FREQ>::str,
+    "mos8580", "FALSE",
+    "forceModel", "FALSE",
+    "emulateFilters", "TRUE",
+    "clockSpeed", aud::numeric_string<XS_CLOCK_PAL>::str,
+    "forceSpeed", "FALSE",
+    "playMaxTimeEnable", "FALSE",
+    "playMaxTimeUnknown", "FALSE",
+    "playMaxTime", "150",
+    "playMinTimeEnable", "FALSE",
+    "playMinTime", "15",
+    "subAutoEnable", "TRUE",
+    "subAutoMinOnly", "TRUE",
+    "subAutoMinTime", "15",
+    nullptr
+};
+
+static constexpr ComboItem clock_speeds[] = {
+    {"NTSC", XS_CLOCK_NTSC},
+    {"PAL", XS_CLOCK_PAL}
+};
+
+static constexpr PreferencesWidget widgets[] = {
+    WidgetLabel(N_("<b>Output</b>")),
+    WidgetSpin(N_("Channels:"),
+        WidgetInt("sid", "audioChannels"),
+        {1, 2, 1}),
+    WidgetSpin(N_("Sample rate:"),
+        WidgetInt("sid", "audioFrequency"),
+        {8000, 96000, 25, N_("Hz")}),
+    WidgetLabel(N_("<b>Emulation</b>")),
+    WidgetCheck(N_("Emulate MOS 8580 (default: MOS 6581)"),
+        WidgetBool("sid", "mos8580")),
+    WidgetCheck(N_("Do not automatically select chip model"),
+        WidgetBool("sid", "forceModel")),
+    WidgetCheck(N_("Emulate filter"),
+        WidgetBool("sid", "emulateFilters")),
+    WidgetCombo(N_("Clock speed:"),
+        WidgetInt("sid", "clockSpeed"),
+        {{clock_speeds}}),
+    WidgetCheck(N_("Do not automatically select clock speed"),
+        WidgetBool("sid", "forceSpeed")),
+    WidgetLabel(N_("<b>Playback time</b>")),
+    WidgetCheck(N_("Set maximum playback time:"),
+        WidgetBool("sid", "playMaxTimeEnable")),
+    WidgetSpin(nullptr,
+        WidgetInt("sid", "playMaxTime"),
+        {5, 3600, 5, N_("seconds")},
+        WIDGET_CHILD),
+    WidgetCheck(N_("Use only when song length is unknown"),
+        WidgetBool("sid", "playMaxTimeUnknown"),
+        WIDGET_CHILD),
+    WidgetCheck(N_("Set minimum playback time:"),
+        WidgetBool("sid", "playMinTimeEnable")),
+    WidgetSpin(nullptr,
+        WidgetInt("sid", "playMinTime"),
+        {5, 3600, 5, N_("seconds")},
+        WIDGET_CHILD),
+    WidgetLabel(N_("<b>Subtunes</b>")),
+    WidgetCheck(N_("Enable subtunes"),
+        WidgetBool("sid", "subAutoEnable")),
+    WidgetCheck(N_("Ignore subtunes shorter than:"),
+        WidgetBool("sid", "subAutoMinOnly")),
+    WidgetSpin(nullptr,
+        WidgetInt("sid", "subAutoMinTime"),
+        {5, 3600, 5, N_("seconds")},
+        WIDGET_CHILD),
+    WidgetLabel(N_("<b>Note</b>")),
+    WidgetLabel(N_("These settings will take effect when Audacious is restarted."))
+};
+
+const PluginPreferences sid_prefs = {{widgets}};
+
+/* Reset/initialize the configuration
+ */
+void xs_init_configuration(void)
+{
+    aud_config_set_defaults("sid", defaults);
+
+    /* Initialize values with sensible defaults */
+    xs_cfg.audioChannels = aud_get_int("sid", "audioChannels");
+    xs_cfg.audioFrequency = aud_get_int("sid", "audioFrequency");
+
+    xs_cfg.mos8580 = aud_get_bool("sid", "mos8580");
+    xs_cfg.forceModel = aud_get_bool("sid", "forceModel");
+
+    /* Filter values */
+    xs_cfg.emulateFilters = aud_get_bool("sid", "emulateFilters");
+
+    xs_cfg.clockSpeed = aud_get_int("sid", "clockSpeed");
+    xs_cfg.forceSpeed = aud_get_bool("sid", "forceSpeed");
+
+    xs_cfg.playMaxTimeEnable = aud_get_bool("sid", "playMaxTimeEnable");
+    xs_cfg.playMaxTimeUnknown = aud_get_bool("sid", "playMaxTimeUnknown");
+    xs_cfg.playMaxTime = aud_get_int("sid", "playMaxTime");
+
+    xs_cfg.playMinTimeEnable = aud_get_bool("sid", "playMinTimeEnable");
+    xs_cfg.playMinTime = aud_get_int("sid", "playMinTime");
+
+    xs_cfg.subAutoEnable = aud_get_bool("sid", "subAutoEnable");
+    xs_cfg.subAutoMinOnly = aud_get_bool("sid", "subAutoMinOnly");
+    xs_cfg.subAutoMinTime = aud_get_int("sid", "subAutoMinTime");
+}
diff --git a/src/sid/xs_config.h b/src/sid/xs_config.h
index d4b8a92f0c8f..6570b1ce4f28 100644
--- a/src/sid/xs_config.h
+++ b/src/sid/xs_config.h
@@ -1,14 +1,6 @@
 #ifndef XS_CONFIG_H
 #define XS_CONFIG_H
 
-#include <pthread.h>
-#include <libaudcore/core.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 /* Configuration structure
  */
 enum XS_CHANNELS {
@@ -40,42 +32,33 @@ extern struct xs_cfg_t {
     int     audioFrequency;
 
     /* Emulation settings */
-    bool_t  mos8580;            /* TRUE = 8580, FALSE = 6581 */
-    bool_t  forceModel;
+    bool    mos8580;            /* true = 8580, false = 6581 */
+    bool    forceModel;
     int     clockSpeed;         /* PAL (50Hz) or NTSC (60Hz) */
-    bool_t  forceSpeed;         /* TRUE = force to given clockspeed */
+    bool    forceSpeed;         /* true = force to given clockspeed */
 
-    bool_t  emulateFilters;
+    bool    emulateFilters;
 
     /* Playing settings */
-    bool_t  playMaxTimeEnable,
+    bool    playMaxTimeEnable,
             playMaxTimeUnknown; /* Use max-time only when song-length is unknown */
     int     playMaxTime;        /* MAX playtime in seconds */
 
-    bool_t  playMinTimeEnable;
+    bool    playMinTimeEnable;
     int     playMinTime;        /* MIN playtime in seconds */
 
-    bool_t  songlenDBEnable;
-    char    *songlenDBPath;     /* Path to Songlengths.txt */
-
     /* Miscellaneous settings */
-    bool_t  stilDBEnable;
-    char    *stilDBPath;        /* Path to STIL.txt */
-    char    *hvscPath;          /* Path-prefix for HVSC */
-
-    bool_t  subAutoEnable,
+    bool    subAutoEnable,
             subAutoMinOnly;
     int     subAutoMinTime;
 } xs_cfg;
 
-extern pthread_mutex_t xs_cfg_mutex;
-
 
 /* Functions
  */
 void xs_init_configuration(void);
 
-#ifdef __cplusplus
-}
-#endif
+struct PluginPreferences;
+extern const PluginPreferences sid_prefs;
+
 #endif    /* XS_CONFIG_H */
diff --git a/src/sid/xs_length.c b/src/sid/xs_length.c
deleted file mode 100644
index 327786d664da..000000000000
--- a/src/sid/xs_length.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   Get song length from SLDB for PSID/RSID files
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
-
-   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.
-*/
-#include "xs_length.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "xmms-sid.h"
-#include "xs_support.h"
-
-/* Free memory allocated for given SLDB node
- */
-static void xs_sldb_node_free(sldb_node_t *node)
-{
-    if (node) {
-        /* Nothing much to do here ... */
-        free(node->lengths);
-        free(node);
-    }
-}
-
-
-/* Insert given node to db linked list
- */
-static void xs_sldb_node_insert(xs_sldb_t *db, sldb_node_t *node)
-{
-    assert(db);
-
-    if (db->nodes) {
-        /* The first node's prev points to last node */
-        node->prev = db->nodes->prev;    /* New node's prev = Previous last node */
-        db->nodes->prev->next = node;    /* Previous last node's next = New node */
-        db->nodes->prev = node;    /* New last node = New node */
-        node->next = NULL;    /* But next is NULL! */
-    } else {
-        db->nodes = node;    /* First node ... */
-        node->prev = node;    /* ... it's also last */
-        node->next = NULL;    /* But next is NULL! */
-    }
-}
-
-
-/* Parse a time-entry in SLDB format
- */
-static int xs_sldb_gettime(char *str, size_t *pos)
-{
-    int result, tmp;
-
-    /* Check if it starts with a digit */
-    if (g_ascii_isdigit(str[*pos])) {
-        /* Get minutes-field */
-        result = 0;
-        while (g_ascii_isdigit(str[*pos]))
-            result = (result * 10) + (str[(*pos)++] - '0');
-
-        result *= 60;
-
-        /* Check the field separator char */
-        if (str[*pos] == ':') {
-            /* Get seconds-field */
-            (*pos)++;
-            tmp = 0;
-            while (g_ascii_isdigit(str[*pos])) {
-                tmp = (tmp * 10) + (str[(*pos)++] - '0');
-            }
-
-            result += tmp;
-        } else
-            result = -2;
-    } else
-        result = -1;
-
-    /* Ignore and skip the possible attributes */
-    while (str[*pos] && !g_ascii_isspace(str[*pos]))
-        (*pos)++;
-
-    return result;
-}
-
-
-/* Parse one SLDB definition line, return SLDB node
- */
-sldb_node_t * xs_sldb_read_entry(char *inLine)
-{
-    size_t linePos;
-    int i;
-    bool_t isOK;
-    sldb_node_t *tmnode;
-
-    /* Allocate new node */
-    tmnode = (sldb_node_t *) malloc(sizeof(sldb_node_t));
-    if (!tmnode) {
-        xs_error("Error allocating new node. Fatal error.\n");
-        return NULL;
-    }
-    memset(tmnode, 0, sizeof(sldb_node_t));
-
-    /* Get hash value */
-    linePos = 0;
-    for (i = 0; i < XS_MD5HASH_LENGTH; i++, linePos += 2) {
-        unsigned tmpu;
-        sscanf(&inLine[linePos], "%2x", &tmpu);
-        tmnode->md5Hash[i] = tmpu;
-    }
-
-    /* Get playtimes */
-    if (inLine[linePos] != 0) {
-        if (inLine[linePos] != '=') {
-            xs_error("'=' expected on column #%d.\n", (int)linePos);
-            xs_sldb_node_free(tmnode);
-            return NULL;
-        } else {
-            size_t tmpLen, savePos;
-
-            /* First playtime is after '=' */
-            savePos = ++linePos;
-            tmpLen = strlen(inLine);
-
-            /* Get number of sub-tune lengths */
-            isOK = TRUE;
-            while ((linePos < tmpLen) && isOK) {
-                xs_findnext(inLine, &linePos);
-
-                if (xs_sldb_gettime(inLine, &linePos) >= 0)
-                    tmnode->nlengths++;
-                else
-                    isOK = FALSE;
-            }
-
-            /* Allocate memory for lengths */
-            if (tmnode->nlengths > 0) {
-                tmnode->lengths = (int *) malloc(tmnode->nlengths * sizeof(int));
-                if (!tmnode->lengths) {
-                    xs_error("Could not allocate memory for node.\n");
-                    xs_sldb_node_free(tmnode);
-                    return NULL;
-                }
-                memset(tmnode->lengths, 0, tmnode->nlengths * sizeof(int));
-            } else {
-                xs_sldb_node_free(tmnode);
-                return NULL;
-            }
-
-            /* Read lengths in */
-            i = 0;
-            linePos = savePos;
-            isOK = TRUE;
-            while ((linePos < tmpLen) && (i < tmnode->nlengths) && isOK) {
-                int l;
-
-                xs_findnext(inLine, &linePos);
-
-                l = xs_sldb_gettime(inLine, &linePos);
-                if (l >= 0)
-                    tmnode->lengths[i] = l;
-                else
-                    isOK = FALSE;
-
-                i++;
-            }
-
-            if (!isOK) {
-                xs_sldb_node_free(tmnode);
-                return NULL;
-            } else
-                return tmnode;
-        }
-    }
-
-    xs_sldb_node_free(tmnode);
-    return NULL;
-}
-
-
-/* Read database to memory
- */
-int xs_sldb_read(xs_sldb_t *db, const char *dbFilename)
-{
-    FILE *inFile;
-    char inLine[XS_BUF_SIZE];
-    size_t lineNum;
-    sldb_node_t *tmnode;
-    assert(db);
-
-    /* Try to open the file */
-    if ((inFile = fopen(dbFilename, "r")) == NULL) {
-        xs_error("Could not open SongLengthDB '%s'\n", dbFilename);
-        return -1;
-    }
-
-    /* Read and parse the data */
-    lineNum = 0;
-
-    while (fgets(inLine, XS_BUF_SIZE, inFile) != NULL) {
-        size_t linePos = 0;
-        lineNum++;
-
-        xs_findnext(inLine, &linePos);
-
-        /* Check if it is datafield */
-        if (g_ascii_isxdigit(inLine[linePos])) {
-            /* Check the length of the hash */
-            int hashLen;
-            for (hashLen = 0; inLine[linePos] && g_ascii_isxdigit(inLine[linePos]); hashLen++, linePos++);
-
-            if (hashLen != XS_MD5HASH_LENGTH_CH) {
-                xs_error("Invalid MD5-hash in SongLengthDB file '%s' line #%d!\n",
-                    dbFilename, (int)lineNum);
-            } else {
-                /* Parse and add node to db */
-                if ((tmnode = xs_sldb_read_entry(inLine)) != NULL) {
-                    xs_sldb_node_insert(db, tmnode);
-                } else {
-                    xs_error("Invalid entry in SongLengthDB file '%s' line #%d!\n",
-                        dbFilename, (int)lineNum);
-                }
-            }
-        } else if ((inLine[linePos] != ';') && (inLine[linePos] != '[') && (inLine[linePos] != 0)) {
-            xs_error("Invalid line in SongLengthDB file '%s' line #%d\n",
-                dbFilename, (int)lineNum);
-        }
-
-    }
-
-    /* Close the file */
-    fclose(inFile);
-
-    return 0;
-}
-
-
-/* Compare two given MD5-hashes.
- * Return: 0 if equal
- *         negative if testHash1 < testHash2
- *         positive if testHash1 > testHash2
- */
-static int xs_sldb_cmphash(xs_md5hash_t testHash1, xs_md5hash_t testHash2)
-{
-    int i, d;
-
-    /* Compute difference of hashes */
-    for (i = 0, d = 0; (i < XS_MD5HASH_LENGTH) && !d; i++)
-        d = (testHash1[i] - testHash2[i]);
-
-    return d;
-}
-
-
-/* Compare two nodes
- */
-static int xs_sldb_cmp(const void *node1, const void *node2)
-{
-    /* We assume here that we never ever get NULL-pointers or similar */
-    return xs_sldb_cmphash(
-        (*(sldb_node_t **) node1)->md5Hash,
-        (*(sldb_node_t **) node2)->md5Hash);
-}
-
-
-/* (Re)create index
- */
-int xs_sldb_index(xs_sldb_t * db)
-{
-    sldb_node_t *pCurr;
-    size_t i;
-    assert(db);
-
-    /* Free old index */
-    if (db->pindex) {
-        free(db->pindex);
-        db->pindex = NULL;
-    }
-
-    /* Get size of db */
-    pCurr = db->nodes;
-    db->n = 0;
-    while (pCurr) {
-        db->n++;
-        pCurr = pCurr->next;
-    }
-
-    /* Check number of nodes */
-    if (db->n > 0) {
-        /* Allocate memory for index-table */
-        db->pindex = (sldb_node_t **) malloc(sizeof(sldb_node_t *) * db->n);
-        if (!db->pindex)
-            return -1;
-
-        /* Get node-pointers to table */
-        i = 0;
-        pCurr = db->nodes;
-        while (pCurr && (i < db->n)) {
-            db->pindex[i++] = pCurr;
-            pCurr = pCurr->next;
-        }
-
-        /* Sort the indexes */
-        qsort(db->pindex, db->n, sizeof(sldb_node_t *), xs_sldb_cmp);
-    }
-
-    return 0;
-}
-
-
-/* Free a given song-length database
- */
-void xs_sldb_free(xs_sldb_t * db)
-{
-    sldb_node_t *pCurr, *next;
-
-    if (!db)
-        return;
-
-    /* Free the memory allocated for nodes */
-    pCurr = db->nodes;
-    while (pCurr) {
-        next = pCurr->next;
-        xs_sldb_node_free(pCurr);
-        pCurr = next;
-    }
-
-    db->nodes = NULL;
-
-    /* Free memory allocated for index */
-    if (db->pindex) {
-        free(db->pindex);
-        db->pindex = NULL;
-    }
-
-    /* Free structure */
-    db->n = 0;
-    free(db);
-}
-
-
-/* Compute md5hash of given SID-file
- */
-typedef struct {
-    char magicID[4];    /* "PSID" / "RSID" magic identifier */
-    uint16_t version,    /* Version number */
-        dataOffset,    /* Start of actual c64 data in file */
-        loadAddress,    /* Loading address */
-        initAddress,    /* Initialization address */
-        playAddress,    /* Play one frame */
-        nSongs,        /* Number of subsongs */
-        startSong;    /* Default starting song */
-    uint32_t speed;        /* Speed */
-    char sidName[32];    /* Descriptive text-fields, ASCIIZ */
-    char sidAuthor[32];
-    char sidCopyright[32];
-} psidv1_header_t;
-
-
-typedef struct {
-    uint16_t flags;        /* Flags */
-    uint8_t startPage, pageLength;
-    uint16_t reserved;
-} psidv2_header_t;
-
-
-static int xs_get_sid_hash(const char *filename, xs_md5hash_t hash)
-{
-    VFSFile *inFile;
-    xs_md5state_t inState;
-    psidv1_header_t psidH;
-    psidv2_header_t psidH2;
-    uint8_t *songData;
-    uint8_t ib8[2], i8;
-    int index, result;
-
-    /* Try to open the file */
-    if ((inFile = vfs_fopen(filename, "rb")) == NULL)
-        return -1;
-
-    /* Read PSID header in */
-    if (vfs_fread(psidH.magicID, 1, sizeof psidH.magicID, inFile) < sizeof psidH.magicID) {
-        vfs_fclose(inFile);
-        return -1;
-    }
-
-    if (strncmp(psidH.magicID, "PSID", 4) && strncmp(psidH.magicID, "RSID", 4)) {
-        vfs_fclose(inFile);
-        xs_error("Not a PSID or RSID file '%s'\n", filename);
-        return -2;
-    }
-
-    psidH.version = xs_fread_be16(inFile);
-    psidH.dataOffset = xs_fread_be16(inFile);
-    psidH.loadAddress = xs_fread_be16(inFile);
-    psidH.initAddress = xs_fread_be16(inFile);
-    psidH.playAddress = xs_fread_be16(inFile);
-    psidH.nSongs = xs_fread_be16(inFile);
-    psidH.startSong = xs_fread_be16(inFile);
-    psidH.speed = xs_fread_be32(inFile);
-
-    if (vfs_fread(psidH.sidName, 1, sizeof psidH.sidName, inFile) < sizeof psidH.sidName
-     || vfs_fread(psidH.sidAuthor, 1, sizeof psidH.sidAuthor, inFile) < sizeof psidH.sidAuthor
-     || vfs_fread(psidH.sidCopyright, 1, sizeof psidH.sidCopyright, inFile) < sizeof psidH.sidCopyright) {
-        vfs_fclose(inFile);
-        xs_error("Error reading SID file header from '%s'\n", filename);
-        return -4;
-    }
-
-    /* Check if we need to load PSIDv2NG header ... */
-    psidH2.flags = 0;    /* Just silence a stupid gcc warning */
-
-    if (psidH.version == 2) {
-        /* Yes, we need to */
-        psidH2.flags = xs_fread_be16(inFile);
-        psidH2.startPage = vfs_getc(inFile);
-        psidH2.pageLength = vfs_getc(inFile);
-        psidH2.reserved = xs_fread_be16(inFile);
-    }
-
-    /* Allocate buffer */
-    songData = (uint8_t *) malloc(XS_SIDBUF_SIZE * sizeof(uint8_t));
-    if (!songData) {
-        vfs_fclose(inFile);
-        xs_error("Error allocating temp data buffer for file '%s'\n", filename);
-        return -3;
-    }
-
-    /* Read data to buffer */
-    result = vfs_fread(songData, sizeof(uint8_t), XS_SIDBUF_SIZE, inFile);
-    vfs_fclose(inFile);
-
-    /* Initialize and start MD5-hash calculation */
-    xs_md5_init(&inState);
-
-    if (psidH.loadAddress == 0) {
-        /* Strip load address (2 first bytes) */
-        xs_md5_append(&inState, &songData[2], result - 2);
-    } else {
-        /* Append "as is" */
-        xs_md5_append(&inState, songData, result);
-    }
-
-    /* Free buffer */
-    free(songData);
-
-    /* Append header data to hash */
-#define XSADDHASH(QDATAB) do {                    \
-    ib8[0] = (QDATAB & 0xff);                \
-    ib8[1] = (QDATAB >> 8);                    \
-    xs_md5_append(&inState, (uint8_t *) &ib8, sizeof(ib8));    \
-    } while (0)
-
-    XSADDHASH(psidH.initAddress);
-    XSADDHASH(psidH.playAddress);
-    XSADDHASH(psidH.nSongs);
-#undef XSADDHASH
-
-    /* Append song speed data to hash */
-    i8 = 0;
-    for (index = 0; (index < psidH.nSongs) && (index < 32); index++) {
-        i8 = (psidH.speed & (1 << index)) ? 60 : 0;
-        xs_md5_append(&inState, &i8, sizeof(i8));
-    }
-
-    /* Rest of songs (more than 32) */
-    for (index = 32; index < psidH.nSongs; index++) {
-        xs_md5_append(&inState, &i8, sizeof(i8));
-    }
-
-    /* PSIDv2NG specific */
-    if (psidH.version == 2) {
-        /* SEE SIDPLAY HEADERS FOR INFO */
-        i8 = (psidH2.flags >> 2) & 3;
-        if (i8 == 2)
-            xs_md5_append(&inState, &i8, sizeof(i8));
-    }
-
-    /* Calculate the hash */
-    xs_md5_finish(&inState, hash);
-
-    return 0;
-}
-
-
-/* Get node from db index via binary search
- */
-sldb_node_t *xs_sldb_get(xs_sldb_t *db, const char *filename)
-{
-    sldb_node_t keyItem, *key, **item;
-
-    /* Check the database pointers */
-    if (!db || !db->nodes || !db->pindex)
-        return NULL;
-
-    /* Get the hash and then look up from db */
-    if (xs_get_sid_hash(filename, keyItem.md5Hash) == 0) {
-        key = &keyItem;
-        item = bsearch(&key, db->pindex, db->n,
-            sizeof(db->pindex[0]), xs_sldb_cmp);
-
-        if (item)
-            return *item;
-        else
-            return NULL;
-    } else
-        return NULL;
-}
-
-
diff --git a/src/sid/xs_length.h b/src/sid/xs_length.h
deleted file mode 100644
index a5798e3c09db..000000000000
--- a/src/sid/xs_length.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef XS_LENGTH_H
-#define XS_LENGTH_H
-
-#include <sys/types.h>
-
-#include "xs_md5.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Types
- */
-typedef struct _sldb_node_t {
-    xs_md5hash_t    md5Hash;    /* 128-bit MD5 hash-digest */
-    int            nlengths;   /* Number of lengths */
-    int            *lengths;   /* Lengths in seconds */
-    struct _sldb_node_t *prev, *next;
-} sldb_node_t;
-
-
-typedef struct {
-    sldb_node_t     *nodes,
-                    **pindex;
-    size_t          n;
-} xs_sldb_t;
-
-
-/* Functions
- */
-int            xs_sldb_read(xs_sldb_t *, const char *);
-int            xs_sldb_index(xs_sldb_t *);
-void            xs_sldb_free(xs_sldb_t *);
-sldb_node_t *   xs_sldb_get(xs_sldb_t *, const char *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* XS_LENGTH_H */
diff --git a/src/sid/xs_md5.c b/src/sid/xs_md5.c
deleted file mode 100644
index 26beec231eda..000000000000
--- a/src/sid/xs_md5.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Wrapper for GLib MD5 implementation */
-/* John Lindgren, March 31, 2012 */
-/* Public domain */
-
-#include <glib.h>
-
-#include "xs_md5.h"
-
-void xs_md5_init (xs_md5state_t * state)
-{
-    state->priv = g_checksum_new (G_CHECKSUM_MD5);
-}
-
-void xs_md5_append (xs_md5state_t * state, const void * data, int length)
-{
-    g_checksum_update (state->priv, data, length);
-}
-
-void xs_md5_finish (xs_md5state_t * state, xs_md5hash_t hash)
-{
-    size_t length = XS_MD5HASH_LENGTH;
-    g_checksum_get_digest (state->priv, hash, & length);
-    g_checksum_free (state->priv);
-    state->priv = NULL;
-}
diff --git a/src/sid/xs_md5.h b/src/sid/xs_md5.h
deleted file mode 100644
index d480e68d3e85..000000000000
--- a/src/sid/xs_md5.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Wrapper for GLib MD5 implementation */
-/* John Lindgren, March 31, 2012 */
-/* Public domain */
-
-#ifndef XS_MD5_H
-#define XS_MD5_H
-
-#define XS_MD5HASH_LENGTH 16
-#define XS_MD5HASH_LENGTH_CH 32
-
-typedef struct {
-    void * priv;
-} xs_md5state_t;
-
-typedef unsigned char xs_md5hash_t[XS_MD5HASH_LENGTH];
-
-void xs_md5_init (xs_md5state_t * state);
-void xs_md5_append (xs_md5state_t * state, const void * data, int length);
-void xs_md5_finish (xs_md5state_t * state, xs_md5hash_t hash);
-
-#endif
diff --git a/src/sid/xs_player.h b/src/sid/xs_player.h
deleted file mode 100644
index 9b3a2adc7bf8..000000000000
--- a/src/sid/xs_player.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef XS_PLAYER_H
-#define XS_PLAYER_H
-
-#include "xmms-sid.h"
-#include "xs_config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct xs_status_t {
-    int        audioFrequency,     /* Audio settings */
-                audioChannels;
-    void        *sidEngine;         /* SID-emulation internal engine data */
-    int        currSong;           /* Current sub-tune */
-
-    xs_tuneinfo_t *tuneInfo;
-} xs_status_t;
-
-
-/* Global variables
- */
-extern xs_status_t    xs_status;
-extern pthread_mutex_t xs_status_mutex;
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* XS_PLAYER_H */
diff --git a/src/sid/xs_sidplay2.cc b/src/sid/xs_sidplay2.cc
index 647901d846ed..1564fe670542 100644
--- a/src/sid/xs_sidplay2.cc
+++ b/src/sid/xs_sidplay2.cc
@@ -24,10 +24,10 @@
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "xs_config.h"
 #include "xs_sidplay2.h"
 
-#include <assert.h>
-#include <stdlib.h>
+#include <pthread.h>
 #include <string.h>
 
 #include <sidplayfp/sidplayfp.h>
@@ -37,373 +37,254 @@
 #include <sidplayfp/SidTuneInfo.h>
 #include <sidplayfp/builders/residfp.h>
 
-class xs_sidplayfp_t {
-public:
+#include <libaudcore/runtime.h>
+#include <libaudcore/vfs.h>
+
+struct SidState {
     sidplayfp *currEng;
     sidbuilder *currBuilder;
-    SidConfig currConfig;
     SidTune *currTune;
-    void *buf;
-    int64_t bufSize;
 
-    xs_sidplayfp_t(void);
-    virtual ~xs_sidplayfp_t(void) { ; }
+    SidDatabase database;
+    bool database_loaded = false;
+    pthread_mutex_t database_mutex = PTHREAD_MUTEX_INITIALIZER;
 };
 
+static SidState state;
 
-xs_sidplayfp_t::xs_sidplayfp_t(void)
-:currEng(NULL)
-{
-    buf = NULL;
-    bufSize = 0;
-    currTune = NULL;
-    currBuilder = NULL;
-}
-
-
-/* We need to 'export' all this pseudo-C++ crap */
-extern "C" {
 
 /* Check if we can play the given file
  */
-bool_t xs_sidplayfp_probe(VFSFile *f)
+bool xs_sidplayfp_probe(const void *buf, int64_t bufSize)
 {
-    char tmpBuf[5];
-
-    if (f == NULL) return FALSE;
+    if (bufSize < 4)
+        return false;
 
-    if (vfs_fread(tmpBuf, sizeof(char), 4, f) != 4)
-        return FALSE;
-
-    if (!strncmp(tmpBuf, "PSID", 4) || !strncmp(tmpBuf, "RSID", 4))
-        return TRUE;
-    else
-        return FALSE;
+    return !memcmp(buf, "PSID", 4) || !memcmp(buf, "RSID", 4);
 }
 
 
 /* Initialize SIDPlayFP
  */
-bool_t xs_sidplayfp_init(xs_status_t * status)
+bool xs_sidplayfp_init()
 {
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
-
-    /* Allocate internal structures */
-    engine = new xs_sidplayfp_t();
-    status->sidEngine = engine;
-    if (!engine) return FALSE;
-
     /* Initialize the engine */
-    engine->currEng = new sidplayfp;
-    if (!engine->currEng) {
-        xs_error("[SIDPlayFP] Could not initialize emulation engine.\n");
-        return FALSE;
-    }
+    state.currEng = new sidplayfp;
 
     /* Get current configuration */
-    engine->currConfig = engine->currEng->config();
+    SidConfig config = state.currEng->config();
 
     /* Configure channels and stuff */
-    switch (status->audioChannels)
+    switch (xs_cfg.audioChannels)
     {
     case XS_CHN_STEREO:
-        engine->currConfig.playback = SidConfig::STEREO;
+        config.playback = SidConfig::STEREO;
         break;
 
     case XS_CHN_MONO:
-        engine->currConfig.playback = SidConfig::MONO;
+        config.playback = SidConfig::MONO;
         break;
     }
 
     /* Audio parameters sanity checking and setup */
-    engine->currConfig.frequency = status->audioFrequency;
+    config.frequency = xs_cfg.audioFrequency;
 
     /* Initialize builder object */
-    ReSIDfpBuilder *rs = new ReSIDfpBuilder("ReSIDfp builder");
-    engine->currBuilder = (sidbuilder *) rs;
+    state.currBuilder = new ReSIDfpBuilder("ReSIDfp builder");
 
     /* Builder object created, initialize it */
-    engine->currBuilder->create(engine->currEng->info().maxsids());
-    if (!engine->currBuilder->getStatus()) {
-        xs_error("reSID->create() failed.\n");
-        return FALSE;
+    state.currBuilder->create(state.currEng->info().maxsids());
+    if (!state.currBuilder->getStatus()) {
+        AUDERR("reSID->create() failed.\n");
+        return false;
     }
 
-    engine->currBuilder->filter(xs_cfg.emulateFilters);
-    if (!engine->currBuilder->getStatus()) {
-        xs_error("reSID->filter(%d) failed.\n", xs_cfg.emulateFilters);
-        return FALSE;
+    state.currBuilder->filter(xs_cfg.emulateFilters);
+    if (!state.currBuilder->getStatus()) {
+        AUDERR("reSID->filter(%d) failed.\n", xs_cfg.emulateFilters);
+        return false;
     }
 
-    engine->currConfig.sidEmulation = engine->currBuilder;
+    config.sidEmulation = state.currBuilder;
 
     /* Clockspeed settings */
     switch (xs_cfg.clockSpeed) {
     case XS_CLOCK_NTSC:
-        engine->currConfig.defaultC64Model = SidConfig::NTSC;
+        config.defaultC64Model = SidConfig::NTSC;
         break;
 
     default:
-        xs_error("[SIDPlayFP] Invalid clockSpeed=%d, falling back to PAL.\n",
+        AUDERR("[SIDPlayFP] Invalid clockSpeed=%d, falling back to PAL.\n",
             xs_cfg.clockSpeed);
 
     case XS_CLOCK_PAL:
-        engine->currConfig.defaultC64Model = SidConfig::PAL;
+        config.defaultC64Model = SidConfig::PAL;
         xs_cfg.clockSpeed = XS_CLOCK_PAL;
         break;
     }
 
+    config.forceC64Model = xs_cfg.forceSpeed;
+
     /* Configure rest of the emulation */
     if (xs_cfg.mos8580)
-        engine->currConfig.defaultSidModel = SidConfig::MOS8580;
+        config.defaultSidModel = SidConfig::MOS8580;
     else
-        engine->currConfig.defaultSidModel = SidConfig::MOS6581;
+        config.defaultSidModel = SidConfig::MOS6581;
 
-    engine->currConfig.forceSidModel = xs_cfg.forceModel;
+    config.forceSidModel = xs_cfg.forceModel;
 
     /* Now set the emulator configuration */
-    if (!engine->currEng->config(engine->currConfig)) {
-        xs_error("[SIDPlayFP] Emulator engine configuration failed!\n");
-        return FALSE;
+    if (!state.currEng->config(config)) {
+        AUDERR("[SIDPlayFP] Emulator engine configuration failed!\n");
+        return false;
     }
 
-    /* Create the sidtune */
-    engine->currTune = new SidTune(0);
-    if (!engine->currTune) {
-        xs_error("[SIDPlayFP] Could not initialize SIDTune object.\n");
-        return FALSE;
+    /* Load ROMs */
+    VFSFile kernal_file("file://" SIDDATADIR "sidplayfp/kernal", "r");
+    VFSFile basic_file("file://" SIDDATADIR "sidplayfp/basic", "r");
+    VFSFile chargen_file("file://" SIDDATADIR "sidplayfp/chargen", "r");
+
+    if (kernal_file && basic_file && chargen_file)
+    {
+        Index<char> kernal = kernal_file.read_all();
+        Index<char> basic = basic_file.read_all();
+        Index<char> chargen = chargen_file.read_all();
+
+        if (kernal.len() == 8192 && basic.len() == 8192 && chargen.len() == 4096)
+            state.currEng->setRoms((uint8_t*)kernal.begin(), (uint8_t*)basic.begin(), (uint8_t*)chargen.begin());
     }
 
-    return TRUE;
+    /* Load song length database */
+    state.database_loaded = state.database.open(SIDDATADIR "sidplayfp/Songlengths.txt");
+
+    /* Create the sidtune */
+    state.currTune = new SidTune(0);
+
+    return true;
 }
 
 
 /* Close SIDPlayFP engine
  */
-void xs_sidplayfp_close(xs_status_t * status)
+void xs_sidplayfp_close()
 {
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
-
-    engine = (xs_sidplayfp_t *) status->sidEngine;
-
     /* Free internals */
-    if (engine->currBuilder) {
-        delete engine->currBuilder;
-        engine->currBuilder = NULL;
+    if (state.currBuilder) {
+        delete state.currBuilder;
+        state.currBuilder = nullptr;
     }
 
-    if (engine->currEng) {
-        delete engine->currEng;
-        engine->currEng = NULL;
+    if (state.currEng) {
+        delete state.currEng;
+        state.currEng = nullptr;
     }
 
-    if (engine->currTune) {
-        delete engine->currTune;
-        engine->currTune = NULL;
+    if (state.currTune) {
+        delete state.currTune;
+        state.currTune = nullptr;
     }
 
-    xs_sidplayfp_delete(status);
-
-    delete engine;
-    status->sidEngine = NULL;
+    if (state.database_loaded)
+        state.database.close();
 }
 
 
 /* Initialize current song and sub-tune
  */
-bool_t xs_sidplayfp_initsong(xs_status_t * status)
+bool xs_sidplayfp_initsong(int subtune)
 {
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
-
-    engine = (xs_sidplayfp_t *) status->sidEngine;
-    if (engine == NULL) return FALSE;
-
-    if (!engine->currTune->selectSong(status->currSong)) {
-        xs_error("[SIDPlayFP] currTune->selectSong() failed\n");
-        return FALSE;
+    if (!state.currTune->selectSong(subtune)) {
+        AUDERR("[SIDPlayFP] currTune->selectSong() failed\n");
+        return false;
     }
 
-    if (!engine->currEng->load(engine->currTune)) {
-        xs_error("[SIDPlayFP] currEng->load() failed\n");
-        return FALSE;
+    if (!state.currEng->load(state.currTune)) {
+        AUDERR("[SIDPlayFP] currEng->load() failed\n");
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 
 /* Emulate and render audio data to given buffer
  */
-unsigned xs_sidplayfp_fillbuffer(xs_status_t * status, char * audioBuffer, unsigned audioBufSize)
+unsigned xs_sidplayfp_fillbuffer(char * audioBuffer, unsigned audioBufSize)
 {
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
-
-    engine = (xs_sidplayfp_t *) status->sidEngine;
-    if (!engine) return 0;
-
-    return engine->currEng->play((short *)audioBuffer, audioBufSize / 2) * 2;
+    return state.currEng->play((short *)audioBuffer, audioBufSize / 2) * 2;
 }
 
 
 /* Load a given SID-tune file
  */
-bool_t xs_sidplayfp_load(xs_status_t * status, const char * pcFilename)
+bool xs_sidplayfp_load(const void *buf, int64_t bufSize)
 {
-    /* This is safe, since xmms-sid.c always calls us with xs_status locked */
-    static int loaded_roms = 0;
-
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
-
-    engine = (xs_sidplayfp_t *) status->sidEngine;
-    if (!engine) return FALSE;
-
-    /* In xs_sidplayfp_init aud-vfs is not initialized yet, so try to load
-       the optional rom files on the first xs_sidplayfp_load call. */
-    if (!loaded_roms) {
-        int64_t size = 0;
-        void *kernal = NULL, *basic = NULL, *chargen = NULL;
-
-        vfs_file_get_contents("file://" SIDDATADIR "sidplayfp/kernal", &kernal, &size);
-        if (size != 8192) {
-            free(kernal);
-            kernal = NULL;
-        }
-
-        vfs_file_get_contents("file://" SIDDATADIR "sidplayfp/basic", &basic, &size);
-        if(size != 8192) {
-            free(basic);
-            basic = NULL;
-        }
-
-        vfs_file_get_contents("file://" SIDDATADIR "sidplayfp/chargen", &chargen, &size);
-        if(size != 4096) {
-            free(chargen);
-            chargen = NULL;
-        }
-
-        engine->currEng->setRoms((uint8_t*)kernal, (uint8_t*)basic, (uint8_t*)chargen);
-        free(kernal);
-        free(basic);
-        free(chargen);
-        loaded_roms = 1;
-    }
-
     /* Try to get the tune */
-    vfs_file_get_contents(pcFilename, &engine->buf, &engine->bufSize);
-    if(!engine->bufSize) {
-        free(engine->buf);
-        engine->buf = NULL;
-        return FALSE;
-    }
-
-    engine->currTune->read((uint8_t*)engine->buf, engine->bufSize);
+    state.currTune->read((const uint8_t*)buf, bufSize);
 
-    return engine->currTune->getStatus();
+    return state.currTune->getStatus();
 }
 
 
-/* Delete INTERNAL information
- */
-void xs_sidplayfp_delete(xs_status_t * status)
+bool xs_sidplayfp_getinfo(xs_tuneinfo_t &ti, const char *filename, const void *buf, int64_t bufSize)
 {
-    xs_sidplayfp_t *engine;
-    assert(status != NULL);
+    /* Check if the tune exists and is readable */
+    SidTune myTune((const uint8_t*)buf, bufSize);
 
-    engine = (xs_sidplayfp_t *) status->sidEngine;
-    if (engine == NULL) return;
+    if (!myTune.getStatus())
+        return false;
 
-    free(engine->buf);
-    engine->buf = NULL;
-    engine->bufSize = 0;
-}
+    /* Get general tune information */
+    const SidTuneInfo *myInfo = myTune.getInfo();
 
+    /* Allocate tuneinfo structure and set information */
+    ti.sidFilename = String (filename);
 
-xs_tuneinfo_t* xs_sidplayfp_getinfo(const char *sidFilename)
-{
-    /* This is safe, since xmms-sid.c always calls us with xs_status locked */
-    static int got_db = -1;
-    static SidDatabase database;
+    ti.sidName = String (myInfo->infoString(0));
+    ti.sidComposer = String (myInfo->infoString(1));
+    ti.sidCopyright = String (myInfo->infoString(2));
 
-    xs_tuneinfo_t *result;
-    const SidTuneInfo *myInfo;
-    SidTune *myTune;
-    void *buf = NULL;
-    int64_t bufSize = 0;
+    ti.nsubTunes = myInfo->songs();
+    ti.startTune = myInfo->startSong();
 
-    /* Load file */
-    vfs_file_get_contents(sidFilename, &buf, &bufSize);
+    ti.loadAddr = myInfo->loadAddr();
+    ti.initAddr = myInfo->initAddr();
+    ti.playAddr = myInfo->playAddr();
+    ti.dataFileLen = myInfo->dataFileLen();
+    ti.sidFormat = String (myInfo->formatString());
 
-    /* Check if the tune exists and is readable */
-    if (!bufSize || !(myTune = new SidTune((uint8_t*)buf, bufSize))) {
-        free(buf);
-        return NULL;
-    }
-    free(buf);
+    ti.sidModel = myInfo->sidModel1();
 
-    if (!myTune->getStatus()) {
-        delete myTune;
-        return NULL;
-    }
+    /* Fill in subtune information */
+    ti.subTunes.insert(0, ti.nsubTunes);
 
-    /* Get general tune information */
-    myInfo = myTune->getInfo();
+    if (state.database_loaded)
+    {
+        pthread_mutex_lock(&state.database_mutex);
 
-    /* Allocate tuneinfo structure and set information */
-    result = xs_tuneinfo_new(sidFilename,
-        myInfo->songs(), myInfo->startSong(),
-        myInfo->infoString(0), myInfo->infoString(1), myInfo->infoString(2),
-        myInfo->loadAddr(), myInfo->initAddr(), myInfo->playAddr(),
-        myInfo->dataFileLen(), myInfo->formatString(), myInfo->sidModel1());
-
-    for (int i = 0; i < result->nsubTunes; i++) {
-        if (result->subTunes[i].tuneLength >= 0)
-            continue;
-
-        if (got_db == -1)
-            got_db = database.open(SIDDATADIR "sidplayfp/Songlengths.txt");
-
-        if (got_db) {
-            myTune->selectSong(i + 1);
-            result->subTunes[i].tuneLength = database.length(*myTune);
+        for (int i = 0; i < ti.nsubTunes; i++)
+        {
+            myTune.selectSong(i + 1);
+            ti.subTunes[i].tuneLength = state.database.length(myTune);
         }
-    }
 
-    delete myTune;
+        pthread_mutex_unlock(&state.database_mutex);
+    }
 
-    return result;
+    return true;
 }
 
-bool_t xs_sidplayfp_updateinfo(xs_status_t *myStatus)
+bool xs_sidplayfp_updateinfo(xs_tuneinfo_t &ti, int subtune)
 {
-    const SidTuneInfo *myInfo;
-    SidTune *myTune;
-    xs_sidplayfp_t *myEngine;
-    xs_tuneinfo_t *i;
-
-    /* Check if we have required structures initialized */
-    if (!myStatus || !myStatus->tuneInfo || !myStatus->sidEngine)
-        return FALSE;
-
-    myEngine = (xs_sidplayfp_t *) myStatus->sidEngine;
-    myTune = myEngine->currTune;
-    if (!myTune)
-        return FALSE;
-
     /* Get currently playing tune information */
-    myInfo = myTune->getInfo();
+    const SidTuneInfo *myInfo = state.currTune->getInfo();
 
     /* NOTICE! Here we assume that libSIDPlay[12] headers define
      * SIDTUNE_SIDMODEL_* similarly to our enums in xs_config.h ...
      */
-    i = myStatus->tuneInfo;
-    i->sidModel = myInfo->sidModel1();
+    ti.sidModel = myInfo->sidModel1();
 
-    if ((myStatus->currSong > 0) && (myStatus->currSong <= i->nsubTunes)) {
+    if ((subtune > 0) && (subtune <= ti.nsubTunes)) {
         int tmpSpeed = -1;
 
         switch (myInfo->clockSpeed()) {
@@ -428,15 +309,14 @@ bool_t xs_sidplayfp_updateinfo(xs_status_t *myStatus)
                 tmpSpeed = myInfo->songSpeed();
                 break;
             }
+            break;
         default:
             tmpSpeed = myInfo->clockSpeed();
             break;
         }
 
-        i->subTunes[myStatus->currSong - 1].tuneSpeed = tmpSpeed;
+        ti.subTunes[subtune - 1].tuneSpeed = tmpSpeed;
     }
 
-    return TRUE;
+    return true;
 }
-
-}    /* extern "C" */
diff --git a/src/sid/xs_sidplay2.h b/src/sid/xs_sidplay2.h
index bff3904479b1..9e0dac8957b5 100644
--- a/src/sid/xs_sidplay2.h
+++ b/src/sid/xs_sidplay2.h
@@ -1,25 +1,17 @@
 #ifndef XS_SIDPLAYFP_H
 #define XS_SIDPLAYFP_H
 
-#include "xs_player.h"
-#include "xs_support.h"
-#include "xs_slsup.h"
+#include "xmms-sid.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <stdint.h>
 
-bool_t    xs_sidplayfp_probe(VFSFile *);
-void        xs_sidplayfp_close(xs_status_t *);
-bool_t    xs_sidplayfp_init(xs_status_t *);
-bool_t    xs_sidplayfp_initsong(xs_status_t *);
-unsigned        xs_sidplayfp_fillbuffer(xs_status_t *, char *, unsigned);
-bool_t    xs_sidplayfp_load(xs_status_t *, const char *);
-void        xs_sidplayfp_delete(xs_status_t *);
-xs_tuneinfo_t*    xs_sidplayfp_getinfo(const char *);
-bool_t    xs_sidplayfp_updateinfo(xs_status_t *);
+bool xs_sidplayfp_probe(const void *buf, int64_t bufSize);
+void xs_sidplayfp_close();
+bool xs_sidplayfp_init();
+bool xs_sidplayfp_initsong(int subtune);
+unsigned xs_sidplayfp_fillbuffer(char *, unsigned);
+bool xs_sidplayfp_load(const void *buf, int64_t bufSize);
+bool xs_sidplayfp_getinfo(xs_tuneinfo_t &ti, const char *filename, const void *buf, int64_t bufSize);
+bool xs_sidplayfp_updateinfo(xs_tuneinfo_t &ti, int subtune);
 
-#ifdef __cplusplus
-}
-#endif
 #endif /* XS_SIDPLAYFP_H */
diff --git a/src/sid/xs_slsup.c b/src/sid/xs_slsup.c
deleted file mode 100644
index 595715483250..000000000000
--- a/src/sid/xs_slsup.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   File information window
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2007 Tecnic Software productions (TNSP)
-
-   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.
-*/
-
-#include "xs_slsup.h"
-
-#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "xs_config.h"
-
-
-static xs_sldb_t *xs_sldb_db = NULL;
-pthread_mutex_t xs_sldb_db_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static xs_stildb_t *xs_stildb_db = NULL;
-pthread_mutex_t xs_stildb_db_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-/* STIL-database handling
- */
-int xs_stil_init(void)
-{
-    pthread_mutex_lock(&xs_cfg_mutex);
-
-    if (!xs_cfg.stilDBPath) {
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        return -1;
-    }
-
-    pthread_mutex_lock(&xs_stildb_db_mutex);
-
-    /* Check if already initialized */
-    if (xs_stildb_db)
-        xs_stildb_free(xs_stildb_db);
-
-    /* Allocate database */
-    xs_stildb_db = (xs_stildb_t *) g_malloc0(sizeof(xs_stildb_t));
-    if (!xs_stildb_db) {
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_stildb_db_mutex);
-        return -2;
-    }
-
-    /* Read the database */
-    if (xs_stildb_read(xs_stildb_db, xs_cfg.stilDBPath) != 0) {
-        xs_stildb_free(xs_stildb_db);
-        xs_stildb_db = NULL;
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_stildb_db_mutex);
-        return -3;
-    }
-
-    /* Create index */
-    if (xs_stildb_index(xs_stildb_db) != 0) {
-        xs_stildb_free(xs_stildb_db);
-        xs_stildb_db = NULL;
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_stildb_db_mutex);
-        return -4;
-    }
-
-    pthread_mutex_unlock(&xs_cfg_mutex);
-    pthread_mutex_unlock(&xs_stildb_db_mutex);
-    return 0;
-}
-
-
-void xs_stil_close(void)
-{
-    pthread_mutex_lock(&xs_stildb_db_mutex);
-    xs_stildb_free(xs_stildb_db);
-    xs_stildb_db = NULL;
-    pthread_mutex_unlock(&xs_stildb_db_mutex);
-}
-
-
-stil_node_t *xs_stil_get(char *filename)
-{
-    stil_node_t *result;
-    char *tmpFilename;
-
-    pthread_mutex_lock(&xs_stildb_db_mutex);
-    pthread_mutex_lock(&xs_cfg_mutex);
-
-    if (xs_cfg.stilDBEnable && xs_stildb_db) {
-        if (xs_cfg.hvscPath) {
-            /* Remove postfixed directory separator from HVSC-path */
-            tmpFilename = strrchr(xs_cfg.hvscPath, '/');
-            if (tmpFilename && (tmpFilename[1] == 0))
-                tmpFilename[0] = 0;
-
-            /* Remove HVSC location-prefix from filename */
-            tmpFilename = strstr(filename, xs_cfg.hvscPath);
-            if (tmpFilename)
-                tmpFilename += strlen(xs_cfg.hvscPath);
-            else
-                tmpFilename = filename;
-        } else
-            tmpFilename = filename;
-
-        result = xs_stildb_get_node(xs_stildb_db, tmpFilename);
-    } else
-        result = NULL;
-
-    pthread_mutex_unlock(&xs_stildb_db_mutex);
-    pthread_mutex_unlock(&xs_cfg_mutex);
-
-    return result;
-}
-
-
-/* Song length database handling glue
- */
-int xs_songlen_init(void)
-{
-    pthread_mutex_lock(&xs_cfg_mutex);
-
-    if (!xs_cfg.songlenDBPath) {
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        return -1;
-    }
-
-    pthread_mutex_lock(&xs_sldb_db_mutex);
-
-    /* Check if already initialized */
-    if (xs_sldb_db)
-        xs_sldb_free(xs_sldb_db);
-
-    /* Allocate database */
-    xs_sldb_db = (xs_sldb_t *) g_malloc0(sizeof(xs_sldb_t));
-    if (!xs_sldb_db) {
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_sldb_db_mutex);
-        return -2;
-    }
-
-    /* Read the database */
-    if (xs_sldb_read(xs_sldb_db, xs_cfg.songlenDBPath) != 0) {
-        xs_sldb_free(xs_sldb_db);
-        xs_sldb_db = NULL;
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_sldb_db_mutex);
-        return -3;
-    }
-
-    /* Create index */
-    if (xs_sldb_index(xs_sldb_db) != 0) {
-        xs_sldb_free(xs_sldb_db);
-        xs_sldb_db = NULL;
-        pthread_mutex_unlock(&xs_cfg_mutex);
-        pthread_mutex_unlock(&xs_sldb_db_mutex);
-        return -4;
-    }
-
-    pthread_mutex_unlock(&xs_cfg_mutex);
-    pthread_mutex_unlock(&xs_sldb_db_mutex);
-    return 0;
-}
-
-
-void xs_songlen_close(void)
-{
-    pthread_mutex_lock(&xs_sldb_db_mutex);
-    xs_sldb_free(xs_sldb_db);
-    xs_sldb_db = NULL;
-    pthread_mutex_unlock(&xs_sldb_db_mutex);
-}
-
-
-sldb_node_t *xs_songlen_get(const char * filename)
-{
-    sldb_node_t *result;
-
-    pthread_mutex_lock(&xs_sldb_db_mutex);
-
-    if (xs_cfg.songlenDBEnable && xs_sldb_db)
-        result = xs_sldb_get(xs_sldb_db, filename);
-    else
-        result = NULL;
-
-    pthread_mutex_unlock(&xs_sldb_db_mutex);
-
-    return result;
-}
-
-
-/* Allocate a new tune information structure
- */
-xs_tuneinfo_t *xs_tuneinfo_new(const char * filename,
-        int nsubTunes, int startTune, const char * sidName,
-        const char * sidComposer, const char * sidCopyright,
-        int loadAddr, int initAddr, int playAddr,
-        int dataFileLen, const char *sidFormat, int sidModel)
-{
-    xs_tuneinfo_t *result;
-    sldb_node_t *tmpLength;
-    int i;
-
-    /* Allocate structure */
-    result = (xs_tuneinfo_t *) g_malloc0(sizeof(xs_tuneinfo_t));
-
-    result->sidFilename = str_get (filename);
-
-    /* Allocate space for subtune information */
-    result->subTunes = g_malloc0(sizeof(xs_subtuneinfo_t) * (nsubTunes + 1));
-
-    result->sidName = str_get (sidName);
-    result->sidComposer = str_get (sidComposer);
-    result->sidCopyright = str_get (sidCopyright);
-
-    result->nsubTunes = nsubTunes;
-    result->startTune = startTune;
-
-    result->loadAddr = loadAddr;
-    result->initAddr = initAddr;
-    result->playAddr = playAddr;
-    result->dataFileLen = dataFileLen;
-    result->sidFormat = str_get (sidFormat);
-
-    result->sidModel = sidModel;
-
-    /* Get length information (NOTE: Do not free this!) */
-    tmpLength = xs_songlen_get(filename);
-
-    /* Fill in sub-tune information */
-    for (i = 0; i < result->nsubTunes; i++) {
-        if (tmpLength && (i < tmpLength->nlengths))
-            result->subTunes[i].tuneLength = tmpLength->lengths[i];
-        else
-            result->subTunes[i].tuneLength = -1;
-
-        result->subTunes[i].tuneSpeed = -1;
-    }
-
-    return result;
-}
-
-
-/* Free given tune information structure
- */
-void xs_tuneinfo_free(xs_tuneinfo_t * tune)
-{
-    if (!tune) return;
-
-    g_free(tune->subTunes);
-    str_unref (tune->sidFilename);
-    str_unref (tune->sidName);
-    str_unref (tune->sidComposer);
-    str_unref (tune->sidCopyright);
-    str_unref (tune->sidFormat);
-    g_free(tune);
-}
diff --git a/src/sid/xs_slsup.h b/src/sid/xs_slsup.h
deleted file mode 100644
index 01e0a0eed9e1..000000000000
--- a/src/sid/xs_slsup.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef XS_SLSUP_H
-#define XS_SLSUP_H
-
-#include "xmms-sid.h"
-#include "xs_stil.h"
-#include "xs_length.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int xs_stil_init(void);
-void xs_stil_close(void);
-stil_node_t *xs_stil_get(char *filename);
-
-int xs_songlen_init(void);
-void xs_songlen_close(void);
-sldb_node_t *xs_songlen_get(const char *filename);
-
-xs_tuneinfo_t *xs_tuneinfo_new(const char *pcFilename, int nsubTunes,
- int startTune, const char *sidName, const char *sidComposer,
- const char *sidCopyright, int loadAddr, int initAddr, int playAddr,
- int dataFileLen, const char *sidFormat, int sidModel);
-void xs_tuneinfo_free(xs_tuneinfo_t *tune);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* XS_SLSUP_H */
diff --git a/src/sid/xs_stil.c b/src/sid/xs_stil.c
deleted file mode 100644
index 3938473409ef..000000000000
--- a/src/sid/xs_stil.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   STIL-database handling functions
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)
-
-   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.
-*/
-#include "xs_stil.h"
-
-#include <assert.h>
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "xmms-sid.h"
-#include "xs_support.h"
-
-/* Database handling functions
- */
-static bool_t xs_stildb_node_realloc(stil_node_t *node, int nsubTunes)
-{
-    if (node == NULL) return FALSE;
-
-    /* Re-allocate subTune structure if needed */
-    if (nsubTunes > node->nsubTunes) {
-        int clearIndex, clearLength;
-
-        node->subTunes =
-            (stil_subnode_t **) realloc(node->subTunes,
-            (nsubTunes + 1) * sizeof(stil_subnode_t **));
-
-        if (!node->subTunes) {
-            xs_error("SubTune pointer structure realloc failed.\n");
-            return FALSE;
-        }
-
-        /* Clear the newly allocated memory */
-        if (node->nsubTunes == 0) {
-            clearIndex = 0;
-            clearLength = nsubTunes + 1;
-        } else {
-            clearIndex = node->nsubTunes + 1;
-            clearLength = (nsubTunes - clearIndex + 1);
-        }
-        memset(&(node->subTunes[clearIndex]), 0, clearLength * sizeof(stil_subnode_t **));
-
-        node->nsubTunes = nsubTunes;
-    }
-
-    /* Allocate memory for subTune */
-    if (!node->subTunes[nsubTunes]) {
-        node->subTunes[nsubTunes] = malloc(sizeof(stil_subnode_t));
-
-        if (node->subTunes[nsubTunes] == NULL) {
-            xs_error("SubTune structure malloc failed!\n");
-            return FALSE;
-        }
-        memset(node->subTunes[nsubTunes], 0, sizeof(stil_subnode_t));
-    }
-
-    return TRUE;
-}
-
-
-static void xs_stildb_node_free(stil_node_t *node)
-{
-    int i;
-    stil_subnode_t *subnode;
-
-    if (node == NULL) return;
-
-    /* Free subtune information */
-    for (i = 0; i <= node->nsubTunes; i++) {
-        subnode = node->subTunes[i];
-        if (subnode) {
-            free(subnode->name);
-            free(subnode->author);
-            free(subnode->info);
-            free(subnode->title);
-            free(subnode);
-        }
-    }
-    free(node->subTunes);
-    free(node->filename);
-    free(node);
-}
-
-
-static stil_node_t *xs_stildb_node_new(char *filename)
-{
-    stil_node_t *result;
-
-//fprintf(stderr, "LL: %s\n", filename);
-
-    /* Allocate memory for new node */
-    if ((result = malloc(sizeof(stil_node_t))) == NULL)
-        return NULL;
-    memset(result, 0, sizeof(stil_node_t));
-
-    /* Allocate filename and initial space for one subtune */
-    result->filename = g_strdup(filename);
-    if (result->filename == NULL || !xs_stildb_node_realloc(result, 1)) {
-        xs_stildb_node_free(result);
-        return NULL;
-    }
-
-    return result;
-}
-
-
-/* Insert given node to db linked list
- */
-static void xs_stildb_node_insert(xs_stildb_t *db, stil_node_t *node)
-{
-    assert(db != NULL);
-
-    if (db->nodes != NULL) {
-        /* The first node's pPrev points to last node */
-        node->prev = db->nodes->prev;    /* New node's prev = Previous last node */
-        db->nodes->prev->next = node;    /* Previous last node's next = New node */
-        db->nodes->prev = node;    /* New last node = New node */
-        node->next = NULL;    /* But next is NULL! */
-    } else {
-        db->nodes = node;    /* First node ... */
-        node->prev = node;    /* ... it's also last */
-        node->next = NULL;    /* But next is NULL! */
-    }
-}
-
-
-/* Read database (additively) to given db-structure
- */
-#define XS_STILDB_MULTI                                         \
-    if (multi) {                                                \
-        multi = FALSE;                                          \
-        xs_pstrcat(&(node->subTunes[subEntry]->info), "\n");    \
-    }
-
-static void XS_STILDB_ERR(int linenum, char *line, const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start(ap, fmt);
-    xs_verror(fmt, ap);
-    va_end(ap);
-
-    xs_error("#%d: '%s'\n", linenum, line);
-}
-
-int xs_stildb_read(xs_stildb_t *db, char *filename)
-{
-    FILE *f;
-    char line[XS_BUF_SIZE + 16];    /* Since we add some chars here and there */
-    stil_node_t *node;
-    bool_t error, multi;
-    int lineNum, subEntry;
-    assert(db != NULL);
-
-    /* Try to open the file */
-    if ((f = fopen(filename, "r")) == NULL) {
-        xs_error("Could not open STILDB '%s'\n", filename);
-        return -1;
-    }
-
-    /* Read and parse the data */
-    lineNum = 0;
-    error = FALSE;
-    multi = FALSE;
-    node = NULL;
-    subEntry = 0;
-
-    while (!error && fgets(line, XS_BUF_SIZE, f) != NULL) {
-        size_t linePos = 0, eolPos = 0;
-        line[XS_BUF_SIZE] = 0;
-        xs_findeol(line, &eolPos);
-        line[eolPos] = 0;
-        lineNum++;
-
-        switch (line[0]) {
-        case '/':
-            /* Check if we are already parsing entry */
-            multi = FALSE;
-            if (node != NULL) {
-                XS_STILDB_ERR(lineNum, line,
-                    "New entry found before end of current ('%s')!\n",
-                    node->filename);
-                xs_stildb_node_free(node);
-                node = NULL;
-            }
-
-            /* A new node */
-            subEntry = 0;
-            if ((node = xs_stildb_node_new(line)) == NULL) {
-                XS_STILDB_ERR(lineNum, line,
-                    "Could not allocate new STILdb-node!\n");
-                error = TRUE;
-            }
-            break;
-
-        case '(':
-            /* A new sub-entry */
-            multi = FALSE;
-            linePos++;
-            if (line[linePos] == '#') {
-                linePos++;
-                if (g_ascii_isdigit(line[linePos])) {
-                    size_t savePos = linePos;
-                    xs_findnum(line, &linePos);
-                    line[linePos] = 0;
-                    subEntry = atol(&line[savePos]);
-
-                    /* Sanity check */
-                    if (subEntry < 1) {
-                        char *tmp = node != NULL ? node->filename : NULL;
-                        XS_STILDB_ERR(lineNum, line,
-                            "Number of subEntry (%d) for '%s' is invalid\n",
-                            subEntry, tmp);
-                        subEntry = 0;
-                    }
-                } else {
-                    XS_STILDB_ERR(lineNum, line,
-                        "Syntax error, expected subEntry number.\n");
-                    subEntry = 0;
-                }
-            } else {
-                XS_STILDB_ERR(lineNum, line,
-                    "Syntax error, expected '#' before subEntry number.\n");
-                subEntry = 0;
-            }
-
-            break;
-
-        case 0:
-        case '#':
-        case '\n':
-        case '\r':
-            /* End of entry/field */
-            multi = FALSE;
-            if (node != NULL) {
-                xs_stildb_node_insert(db, node);
-                node = NULL;
-            }
-            break;
-
-        default:
-            /* Check if we are parsing an entry */
-            xs_findnext(line, &linePos);
-
-            if (node == NULL) {
-                XS_STILDB_ERR(lineNum, line,
-                    "Entry data encountered outside of entry or syntax error!\n");
-                break;
-            }
-
-            if (!xs_stildb_node_realloc(node, subEntry)) {
-                XS_STILDB_ERR(lineNum, line,
-                    "Could not (re)allocate memory for subEntries!\n");
-                error = TRUE;
-                break;
-            }
-
-            /* Some other type */
-            if (strncmp(line, "   NAME:", 8) == 0) {
-                XS_STILDB_MULTI;
-                free(node->subTunes[subEntry]->name);
-                node->subTunes[subEntry]->name = g_strdup(&line[9]);
-            } else if (strncmp(line, "  TITLE:", 8) == 0) {
-                XS_STILDB_MULTI;
-                multi = TRUE;
-                if (!node->subTunes[subEntry]->title)
-                    node->subTunes[subEntry]->title = g_strdup(&line[9]);
-                xs_pstrcat(&(node->subTunes[subEntry]->info), &line[2]);
-            } else if (strncmp(line, " AUTHOR:", 8) == 0) {
-                XS_STILDB_MULTI;
-                free(node->subTunes[subEntry]->author);
-                node->subTunes[subEntry]->author = g_strdup(&line[9]);
-            } else if (strncmp(line, " ARTIST:", 8) == 0) {
-                XS_STILDB_MULTI;
-                multi = TRUE;
-                xs_pstrcat(&(node->subTunes[subEntry]->info), &line[1]);
-            } else if (strncmp(line, "COMMENT:", 8) == 0) {
-                XS_STILDB_MULTI;
-                multi = TRUE;
-                xs_pstrcat(&(node->subTunes[subEntry]->info), line);
-            } else {
-                if (multi) {
-                    xs_pstrcat(&(node->subTunes[subEntry]->info), " ");
-                    xs_pstrcat(&(node->subTunes[subEntry]->info), &line[linePos]);
-                } else {
-                    XS_STILDB_ERR(lineNum, line,
-                    "Entry continuation found when multi == FALSE.\n");
-                }
-            }
-            break;
-        }
-    } /* while */
-
-    /* Check if there is one remaining node */
-    if (node != NULL)
-        xs_stildb_node_insert(db, node);
-
-    /* Close the file */
-    fclose(f);
-
-    return 0;
-}
-
-
-/* Compare two nodes
- */
-static int xs_stildb_cmp(const void *node1, const void *node2)
-{
-    /* We assume here that we never ever get NULL-pointers or similar */
-    return strcmp(
-        (*(stil_node_t **) node1)->filename,
-        (*(stil_node_t **) node2)->filename);
-}
-
-
-/* (Re)create index
- */
-int xs_stildb_index(xs_stildb_t *db)
-{
-    stil_node_t *curr;
-    size_t i;
-
-    /* Free old index */
-    if (db->pindex) {
-        free(db->pindex);
-        db->pindex = NULL;
-    }
-
-    /* Get size of db */
-    curr = db->nodes;
-    db->n = 0;
-    while (curr) {
-        db->n++;
-        curr = curr->next;
-    }
-
-    /* Check number of nodes */
-    if (db->n > 0) {
-        /* Allocate memory for index-table */
-        db->pindex = (stil_node_t **) malloc(sizeof(stil_node_t *) * db->n);
-        if (!db->pindex)
-            return -1;
-
-        /* Get node-pointers to table */
-        i = 0;
-        curr = db->nodes;
-        while (curr && (i < db->n)) {
-            db->pindex[i++] = curr;
-            curr = curr->next;
-        }
-
-        /* Sort the indexes */
-        qsort(db->pindex, db->n, sizeof(stil_node_t *), xs_stildb_cmp);
-    }
-
-    return 0;
-}
-
-
-/* Free a given STIL database
- */
-void xs_stildb_free(xs_stildb_t *db)
-{
-    stil_node_t *curr, *next;
-
-    if (!db)
-        return;
-
-    /* Free the memory allocated for nodes */
-    curr = db->nodes;
-    while (curr) {
-        next = curr->next;
-        xs_stildb_node_free(curr);
-        curr = next;
-    }
-
-    db->nodes = NULL;
-
-    /* Free memory allocated for index */
-    if (db->pindex) {
-        free(db->pindex);
-        db->pindex = NULL;
-    }
-
-    /* Free structure */
-    db->n = 0;
-    free(db);
-}
-
-
-/* Get STIL information node from database
- */
-stil_node_t *xs_stildb_get_node(xs_stildb_t *db, char *filename)
-{
-    stil_node_t keyItem, *key, **item;
-
-    /* Check the database pointers */
-    if (!db || !db->nodes || !db->pindex)
-        return NULL;
-
-    /* Look-up index using binary search */
-    keyItem.filename = filename;
-    key = &keyItem;
-    item = bsearch(&key, db->pindex, db->n, sizeof(stil_node_t *), xs_stildb_cmp);
-    if (item)
-        return *item;
-    else
-        return NULL;
-}
diff --git a/src/sid/xs_stil.h b/src/sid/xs_stil.h
deleted file mode 100644
index 7ff61184bc23..000000000000
--- a/src/sid/xs_stil.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef XS_STIL_H
-#define XS_STIL_H
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Types
- */
-typedef struct {
-    char *name, *author, *title, *info;
-} stil_subnode_t;
-
-
-typedef struct _stil_node_t {
-    char *filename;
-    int nsubTunes;
-    stil_subnode_t **subTunes;
-    struct _stil_node_t *prev, *next;
-} stil_node_t;
-
-
-typedef struct {
-    stil_node_t *nodes, **pindex;
-    size_t n;
-} xs_stildb_t;
-
-
-/* Functions
- */
-int xs_stildb_read(xs_stildb_t *, char *);
-int xs_stildb_index(xs_stildb_t *);
-void xs_stildb_free(xs_stildb_t *);
-stil_node_t *xs_stildb_get_node(xs_stildb_t *, char *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* XS_STIL_H */
diff --git a/src/sid/xs_support.c b/src/sid/xs_support.c
deleted file mode 100644
index 82b56d5a9b7b..000000000000
--- a/src/sid/xs_support.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
-
-   Miscellaneous support functions
-
-   Programmed and designed by Matti 'ccr' Hamalainen <ccr at tnsp.org>
-   (C) Copyright 1999-2007 Tecnic Software productions (TNSP)
-
-   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.
-*/
-
-#include "xs_support.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-uint16_t xs_fread_be16(VFSFile *f)
-{
-    uint16_t val;
-    if (vfs_fread (& val, 1, sizeof val, f) != sizeof val)
-        return 0;
-
-    return GUINT16_FROM_BE (val);
-}
-
-
-uint32_t xs_fread_be32(VFSFile *f)
-{
-    uint32_t val;
-    if (vfs_fread (& val, 1, sizeof val, f) != sizeof val)
-        return 0;
-
-    return GUINT32_FROM_BE (val);
-}
-
-
-/* Copy a given string over in *result.
- */
-int xs_pstrcpy(char **result, const char *str)
-{
-    /* Check the string pointers */
-    if (!result || !str)
-        return -1;
-
-    /* Allocate memory for destination */
-    if (*result)
-        free(*result);
-    *result = (char *) malloc(strlen(str) + 1);
-    if (!*result)
-        return -2;
-
-    /* Copy to the destination */
-    strcpy(*result, str);
-
-    return 0;
-}
-
-
-/* Concatenates a given string into string pointed by *result.
- */
-int xs_pstrcat(char **result, const char *str)
-{
-    /* Check the string pointers */
-    if (!result || !str)
-        return -1;
-
-    if (*result != NULL) {
-        *result = (char *) realloc(*result, strlen(*result) + strlen(str) + 1);
-        if (*result == NULL)
-            return -1;
-        strcat(*result, str);
-    } else {
-        *result = (char *) malloc(strlen(str) + 1);
-        if (*result == NULL)
-            return -1;
-        strcpy(*result, str);
-    }
-
-    return 0;
-}
-
-
-void xs_findnext(const char *str, size_t *pos)
-{
-    while (str[*pos] && g_ascii_isspace(str[*pos]))
-        (*pos)++;
-}
-
-
-void xs_findeol(const char *str, size_t *pos)
-{
-    while (str[*pos] && (str[*pos] != '\n') && (str[*pos] != '\r'))
-        (*pos)++;
-}
-
-
-void xs_findnum(const char *str, size_t *pos)
-{
-    while (str[*pos] && g_ascii_isdigit(str[*pos]))
-        (*pos)++;
-}
-
diff --git a/src/sid/xs_support.h b/src/sid/xs_support.h
deleted file mode 100644
index 8af27a1beda9..000000000000
--- a/src/sid/xs_support.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef XS_SUPPORT_H
-#define XS_SUPPORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <libaudcore/vfs.h>
-
-/* VFS replacement functions
- */
-uint16_t xs_fread_be16(VFSFile *);
-uint32_t xs_fread_be32(VFSFile *);
-
-
-/* Misc functions
- */
-int xs_pstrcpy(char **, const char *);
-int xs_pstrcat(char **, const char *);
-void xs_findnext(const char *, size_t *);
-void xs_findeol(const char *, size_t *);
-void xs_findnum(const char *, size_t *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* XS_SUPPORT_H */
diff --git a/src/silence-removal/Makefile b/src/silence-removal/Makefile
new file mode 100644
index 000000000000..f11da3a331e0
--- /dev/null
+++ b/src/silence-removal/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = silence-removal${PLUGIN_SUFFIX}
+
+SRCS = silence-removal.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
+
+LD = ${CXX}
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -lm
diff --git a/src/silence-removal/silence-removal.cc b/src/silence-removal/silence-removal.cc
new file mode 100644
index 000000000000..4cc3a7523854
--- /dev/null
+++ b/src/silence-removal/silence-removal.cc
@@ -0,0 +1,192 @@
+/*
+ * Silence Removal Plugin for Audacious
+ * Copyright 2014 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 <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/ringbuf.h>
+#include <libaudcore/runtime.h>
+
+#include <math.h>
+
+#define MAX_BUFFER_SECS  10
+
+class SilenceRemoval : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Silence Removal"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr SilenceRemoval () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+};
+
+EXPORT SilenceRemoval aud_plugin_instance;
+
+const char SilenceRemoval::about[] =
+ N_("Silence Removal Plugin for Audacious\n"
+    "Copyright 2014 John Lindgren");
+
+const char * const SilenceRemoval::defaults[] = {
+    "threshold", "-40",
+    nullptr
+};
+
+const PreferencesWidget SilenceRemoval::widgets[] = {
+    WidgetLabel (N_("<b>Silence Removal</b>")),
+    WidgetSpin (N_("Threshold:"),
+        WidgetInt ("silence-removal", "threshold"),
+        {-60, -20, 1, N_("dB")})
+};
+
+const PluginPreferences SilenceRemoval::prefs = {{widgets}};
+
+static RingBuf<float> buffer;
+static Index<float> output;
+static int current_channels;
+static bool initial_silence;
+
+bool SilenceRemoval::init ()
+{
+    aud_config_set_defaults ("silence-removal", defaults);
+    return true;
+}
+
+void SilenceRemoval::cleanup ()
+{
+    buffer.destroy ();
+    output.clear ();
+}
+
+void SilenceRemoval::start (int & channels, int & rate)
+{
+    buffer.discard ();
+    buffer.alloc (channels * rate * MAX_BUFFER_SECS);
+    output.resize (0);
+
+    current_channels = channels;
+    initial_silence = true;
+}
+
+static float * align_to_frame (float * begin, float * sample, bool align_to_end)
+{
+    if (! sample)
+        return nullptr;
+
+    int offset = sample - begin;
+    if (align_to_end)
+        offset += current_channels;
+
+    return begin + (offset - offset % current_channels);
+}
+
+static void buffer_with_overflow (const float * data, int len)
+{
+    int max = buffer.size ();
+
+    if (len > max)
+    {
+        buffer.move_out (output, -1, -1);
+        output.insert (data, -1, len - max);
+        buffer.copy_in (data + len - max, max);
+    }
+    else
+    {
+        int cur = buffer.len ();
+        if (cur + len > max)
+            buffer.move_out (output, -1, cur + len - max);
+
+        buffer.copy_in (data, len);
+    }
+}
+
+Index<float> & SilenceRemoval::process (Index<float> & data)
+{
+    const int threshold_db = aud_get_int ("silence-removal", "threshold");
+    const float threshold = powf (10.0f, threshold_db / 20.0f);
+
+    float * first_sample = nullptr;
+    float * last_sample = nullptr;
+
+    for (float & sample : data)
+    {
+        if (sample > threshold || sample < -threshold)
+        {
+            if (! first_sample)
+                first_sample = & sample;
+
+            last_sample = & sample;
+        }
+    }
+
+    first_sample = align_to_frame (data.begin (), first_sample, false);
+    last_sample = align_to_frame (data.begin (), last_sample, true);
+
+    output.resize (0);
+
+    if (first_sample)
+    {
+        /* do not skip leading silence if non-silence has been seen */
+        if (! initial_silence)
+            first_sample = data.begin ();
+
+        initial_silence = false;
+
+        /* copy any saved silence from previous call */
+        buffer.move_out (output, -1, -1);
+
+        /* copy non-silent portion */
+        output.insert (first_sample, -1, last_sample - first_sample);
+
+        /* save trailing silence */
+        buffer_with_overflow (last_sample, data.end () - last_sample);
+    }
+    else
+    {
+        /* if non-silence has been seen, save entire silent chunk */
+        if (! initial_silence)
+            buffer_with_overflow (data.begin (), data.len ());
+    }
+
+    return output;
+}
+
+bool SilenceRemoval::flush (bool force)
+{
+    buffer.discard ();
+    output.resize (0);
+
+    initial_silence = true;
+    return true;
+}
diff --git a/src/skins/Makefile b/src/skins/Makefile
index 4496b9d89b4b..14710d5b3b68 100644
--- a/src/skins/Makefile
+++ b/src/skins/Makefile
@@ -1,36 +1,37 @@
 PLUGIN = skins${PLUGIN_SUFFIX}
 
-SRCS = drag-handle.c \
-       menus.c \
-       plugin.c \
-       preset-browser.c \
-       preset-list.c \
-       skins_cfg.c \
-       surface.c \
-       ui_skin.c \
-       ui_skin_load_ini.c \
-       ui_skinned_window.c \
-       ui_dock.c \
-       util.c \
-       ui_vis.c \
-       ui_svis.c \
-       ui_skinned_menurow.c \
-       ui_skinned_button.c \
-       ui_skinned_textbox.c \
-       ui_skinned_playstatus.c \
-       ui_skinned_monostereo.c \
-       ui_skinned_number.c \
-       ui_skinned_horizontal_slider.c \
-       ui_skinned_equalizer_graph.c \
-       ui_skinned_equalizer_slider.c \
-       ui_skinned_playlist.c \
-       ui_skinned_playlist_slider.c \
-       ui_main.c \
-       ui_equalizer.c \
-       ui_playlist.c \
-       ui_main_evlisteners.c \
-       ui_skinselector.c \
-       view.c
+SRCS = drag-handle.cc \
+       menus.cc \
+       plugin.cc \
+       plugin-window.cc \
+       preset-browser.cc \
+       preset-list.cc \
+       skins_cfg.cc \
+       surface.cc \
+       ui_skin.cc \
+       ui_skin_load_ini.cc \
+       ui_skinned_window.cc \
+       ui_dock.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
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -159,6 +160,8 @@ DATA = Skins/Classic/balance.png	\
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GTK_CFLAGS}
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += -lm ${GTK_LIBS}
+LIBS += -lm ${GTK_LIBS} -laudgui
diff --git a/src/skins/actions-mainwin.h b/src/skins/actions-mainwin.h
index 2566e2f1ad94..cad103bffaf0 100644
--- a/src/skins/actions-mainwin.h
+++ b/src/skins/actions-mainwin.h
@@ -24,5 +24,7 @@ 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);
 
 #endif /* SKINS_ACTIONS_MAINWIN_H */
diff --git a/src/skins/actions-playlist.h b/src/skins/actions-playlist.h
index 255513e22a10..2afd481ed047 100644
--- a/src/skins/actions-playlist.h
+++ b/src/skins/actions-playlist.h
@@ -56,18 +56,26 @@ void action_playlist_reverse_list(void);
 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_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_track_info(void);
 void action_queue_toggle(void);
diff --git a/src/skins/dnd.h b/src/skins/dnd.h
index e7618ce0e4c6..1d1a634c9ae7 100644
--- a/src/skins/dnd.h
+++ b/src/skins/dnd.h
@@ -39,17 +39,18 @@ enum {
 
 /* Drag data format listing for gtk_drag_dest_set() */
 static const GtkTargetEntry drop_types[] = {
-    {"text/plain", 0, DROP_PLAINTEXT},
-    {"text/uri-list", 0, DROP_URLENCODED},
-    {"STRING", 0, DROP_STRING},
-    {"interface/x-winamp-skin", 0, DROP_SKIN},
-    {"application/x-font-ttf", 0, DROP_FONT},
+    {(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, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
-     drop_types, ARRAY_LEN (drop_types), GDK_ACTION_COPY | GDK_ACTION_MOVE);
+    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 /* SKINS_DND_H */
diff --git a/src/skins/drag-handle.c b/src/skins/drag-handle.c
deleted file mode 100644
index 7dfb8776e592..000000000000
--- a/src/skins/drag-handle.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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"
-
-typedef struct {
-    gboolean held;
-    gint x_origin, y_origin;
-    void (* press) (void);
-    void (* drag) (gint x_offset, gint y_offset);
-} DHandleData;
-
-static gboolean handle_button_press (GtkWidget * handle, GdkEventButton * event)
-{
-    DHandleData * data = g_object_get_data ((GObject *) handle, "dhandledata");
-    g_return_val_if_fail (data, FALSE);
-
-    if (event->button != 1)
-        return FALSE;
-
-    data->held = TRUE;
-    data->x_origin = event->x_root;
-    data->y_origin = event->y_root;
-
-    if (data->press)
-        data->press ();
-
-    return TRUE;
-}
-
-static gboolean handle_button_release (GtkWidget * handle, GdkEventButton *
- event)
-{
-    DHandleData * data = g_object_get_data ((GObject *) handle, "dhandledata");
-    g_return_val_if_fail (data, FALSE);
-
-    if (event->button != 1)
-        return FALSE;
-
-    data->held = FALSE;
-    return TRUE;
-}
-
-static gboolean handle_motion (GtkWidget * handle, GdkEventMotion * event)
-{
-    DHandleData * data = 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, event->y_root -
-         data->y_origin);
-
-    return TRUE;
-}
-
-static void handle_destroy (GtkWidget * handle)
-{
-    g_free (g_object_get_data ((GObject *) handle, "dhandledata"));
-}
-
-GtkWidget * drag_handle_new (gint w, gint h, void (* press) (void), void
- (* drag) (gint x, gint y))
-{
-    GtkWidget * handle = gtk_event_box_new ();
-    gtk_event_box_set_visible_window ((GtkEventBox *) handle, FALSE);
-    gtk_widget_set_size_request (handle, w, h);
-    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, NULL);
-    g_signal_connect (handle, "button-release-event", (GCallback)
-     handle_button_release, NULL);
-    g_signal_connect (handle, "motion-notify-event", (GCallback) handle_motion,
-     NULL);
-    g_signal_connect (handle, "destroy", (GCallback) handle_destroy, NULL);
-
-    DHandleData * data = g_malloc0 (sizeof (DHandleData));
-    data->press = press;
-    data->drag = drag;
-    g_object_set_data ((GObject *) handle, "dhandledata", data);
-
-    return handle;
-}
diff --git a/src/skins/drag-handle.cc b/src/skins/drag-handle.cc
new file mode 100644
index 000000000000..9f08895c7ce6
--- /dev/null
+++ b/src/skins/drag-handle.cc
@@ -0,0 +1,106 @@
+/*
+ * 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"
+
+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)
+{
+    DHandleData * data = (DHandleData *) g_object_get_data ((GObject *) handle, "dhandledata");
+    g_return_val_if_fail (data, FALSE);
+
+    if (event->button != 1)
+        return FALSE;
+
+    data->held = TRUE;
+    data->x_origin = event->x_root;
+    data->y_origin = event->y_root;
+
+    if (data->press)
+        data->press ();
+
+    return TRUE;
+}
+
+static gboolean handle_button_release (GtkWidget * handle, 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;
+
+    data->held = FALSE;
+    return TRUE;
+}
+
+static gboolean handle_motion (GtkWidget * handle, 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);
+
+    return TRUE;
+}
+
+static void handle_destroy (GtkWidget * handle)
+{
+    g_free (g_object_get_data ((GObject *) handle, "dhandledata"));
+}
+
+GtkWidget * drag_handle_new (int w, int h, void (* press) (void), void
+ (* drag) (int x, int y))
+{
+    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;
+}
diff --git a/src/skins/drag-handle.h b/src/skins/drag-handle.h
index 0907b7896fe3..a8ba6df43b78 100644
--- a/src/skins/drag-handle.h
+++ b/src/skins/drag-handle.h
@@ -24,7 +24,7 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * drag_handle_new (gint w, gint h, void (* press) (void), void
- (* drag) (gint x, gint y));
+GtkWidget * drag_handle_new (int w, int h, void (* press) (void), void
+ (* drag) (int x, int y));
 
 #endif
diff --git a/src/skins/draw-compat.h b/src/skins/draw-compat.h
index 4c7a44cb860c..d17890b53bfc 100644
--- a/src/skins/draw-compat.h
+++ b/src/skins/draw-compat.h
@@ -27,17 +27,24 @@
 static void widget_realized (GtkWidget * w)
 {
     GdkWindow * window = gtk_widget_get_window (w);
-    gdk_window_set_background_pattern (window, NULL);
+    gdk_window_set_back_pixmap (window, nullptr, FALSE);
 }
 
-#define DRAW_SIGNAL "draw"
-#define DRAW_FUNC_BEGIN(n) static gboolean n (GtkWidget * wid, cairo_t * cr) { \
- g_return_val_if_fail (wid && cr, FALSE);
-#define DRAW_FUNC_END return 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 { \
-    g_signal_connect (w, "realize", (GCallback) widget_realized, NULL); \
-    g_signal_connect (w, DRAW_SIGNAL, (GCallback) f, NULL); \
+    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/menus.c b/src/skins/menus.c
deleted file mode 100644
index 0e83d45296ce..000000000000
--- a/src/skins/menus.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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 <gdk/gdkkeysyms.h>
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/menu.h>
-
-#include "actions-mainwin.h"
-#include "actions-playlist.h"
-#include "preset-browser.h"
-#include "preset-list.h"
-#include "view.h"
-
-#define SHIFT GDK_SHIFT_MASK
-#define CTRL GDK_CONTROL_MASK
-#define ALT GDK_MOD1_MASK
-
-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_plugin_menu_main (void) {return aud_get_plugin_menu (AUD_MENU_MAIN); }
-static GtkWidget * get_plugin_menu_playlist (void) {return aud_get_plugin_menu (AUD_MENU_PLAYLIST); }
-static GtkWidget * get_plugin_menu_playlist_add (void) {return aud_get_plugin_menu (AUD_MENU_PLAYLIST_ADD); }
-static GtkWidget * get_plugin_menu_playlist_remove (void) {return aud_get_plugin_menu (AUD_MENU_PLAYLIST_REMOVE); }
-
-static const AudguiMenuItem main_items[] = {
-    {N_("Open Files ..."), "document-open", 'l', .func = action_play_file},
-    {N_("Open URL ..."), "folder-remote", 'l', CTRL, .func = action_play_location},
-    {.sep = TRUE},
-    {N_("Playback"), .get_sub = get_menu_playback},
-    {N_("Playlist"), .get_sub = get_menu_playlist},
-    {N_("View"), .get_sub = get_menu_view},
-    {.sep = TRUE},
-    {N_("Services"), .get_sub = get_plugin_menu_main},
-    {.sep = TRUE},
-    {N_("About ..."), "help-about", .func = audgui_show_about_window},
-    {N_("Settings ..."), "preferences-system", 'p', CTRL, .func = aud_show_prefs_window},
-    {N_("Quit"), "application-exit", 'q', CTRL, .func = aud_drct_quit}
-};
-
-static const AudguiMenuItem playback_items[] = {
-    {N_("Song Info ..."), "dialog-information", 'i', .func = audgui_infowin_show_current},
-    {.sep = TRUE},
-    {N_("Repeat"), NULL, 'r', .cname = "repeat", .hook = "set repeat"},
-    {N_("Shuffle"), NULL, 's', .cname = "shuffle", .hook = "set shuffle"},
-    {N_("No Playlist Advance"), NULL, 'n', CTRL, .cname = "no_playlist_advance", .hook = "set no_playlist_advance"},
-    {N_("Stop After This Song"), NULL, 'm', CTRL, .cname = "stop_after_current_song", .hook = "set stop_after_current_song"},
-    {.sep = TRUE},
-    {N_("Play"), "media-playback-start", 'x', .func = aud_drct_play},
-    {N_("Pause"), "media-playback-pause", 'c', .func = aud_drct_pause},
-    {N_("Stop"), "media-playback-stop", 'v', .func = aud_drct_stop},
-    {N_("Previous"), "media-skip-backward", 'z', .func = aud_drct_pl_prev},
-    {N_("Next"), "media-skip-forward", 'b', .func = aud_drct_pl_next},
-    {.sep = TRUE},
-    {N_("Set A-B Repeat"), NULL, 'a', .func = action_ab_set},
-    {N_("Clear A-B Repeat"), NULL, 'a', SHIFT, .func = action_ab_clear},
-    {.sep = TRUE},
-    {N_("Jump to Song ..."), "go-jump", 'j',.func = audgui_jump_to_track},
-    {N_("Jump to Time ..."), "go-jump", 'j', CTRL, .func = audgui_jump_to_time}
-};
-
-static const AudguiMenuItem playlist_items[] = {
-    {N_("Play This Playlist"), "media-playback-start", GDK_KEY_Return, SHIFT, .func = action_playlist_play},
-    {.sep = TRUE},
-    {N_("New Playlist"), "document-new", 'n', SHIFT, .func = action_playlist_new},
-    {N_("Rename Playlist ..."), "insert-text", GDK_KEY_F2, .func = action_playlist_rename},
-    {N_("Remove Playlist"), "edit-delete", 'd', SHIFT, .func = action_playlist_delete},
-    {.sep = TRUE},
-    {N_("Previous Playlist"), "media-skip-backward", GDK_KEY_Tab, SHIFT, .func = action_playlist_prev},
-    {N_("Next Playlist"), "media-skip-forward", GDK_KEY_Tab, .func = action_playlist_next},
-    {.sep = TRUE},
-    {N_("Import Playlist ..."), "document-open", 'o', .func = audgui_import_playlist},
-    {N_("Export Playlist ..."), "document-save", 's', SHIFT, .func = audgui_export_playlist},
-    {.sep = TRUE},
-    {N_("Playlist Manager ..."), "audio-x-generic", 'p', .func = audgui_playlist_manager},
-    {N_("Queue Manager ..."), NULL, 'u', CTRL, .func = audgui_queue_manager_show},
-    {.sep = TRUE},
-    {N_("Refresh Playlist"), "view-refresh", GDK_KEY_F5, .func = action_playlist_refresh_list}
-};
-
-static const AudguiMenuItem view_items[] = {
-    {N_("Show Playlist Editor"), NULL, 'e', ALT, .csect = "skins", "playlist_visible",
-     .hook = "skins set playlist_visible", .func = view_apply_show_playlist},
-    {N_("Show Equalizer"), NULL, 'g', ALT, .csect = "skins", "equalizer_visible",
-     .hook = "skins set equalizer_visible", .func = view_apply_show_equalizer},
-    {.sep = TRUE},
-    {N_("Show Remaining Time"), NULL, 'r', CTRL, .csect = "skins", "show_remaining_time",
-     .hook = "skins set show_remaining_time", .func = view_apply_show_remaining},
-    {.sep = TRUE},
-    {N_("Always on Top"), NULL, 'o', CTRL, .csect = "skins", "always_on_top",
-     .hook = "skins set always_on_top", .func = view_apply_on_top},
-    {N_("On All Workspaces"), NULL, 's', CTRL, .csect = "skins", "sticky",
-     .hook = "skins set sticky", .func = view_apply_sticky},
-    {.sep = TRUE},
-    {N_("Roll Up Player"), NULL, 'w', CTRL, .csect = "skins", "player_shaded",
-     .hook = "skins set player_shaded", .func = view_apply_player_shaded},
-    {N_("Roll Up Playlist Editor"), NULL, 'w', SHIFT | CTRL, .csect = "skins", "playlist_shaded",
-     .hook = "skins set playlist_shaded", .func = view_apply_playlist_shaded},
-    {N_("Roll Up Equalizer"), NULL, 'w', CTRL | ALT, .csect = "skins", "equalizer_shaded",
-     .hook = "skins set equalizer_shaded", .func = view_apply_equalizer_shaded}
-};
-
-static const AudguiMenuItem playlist_add_items[] = {
-    {N_("Services"), .get_sub = get_plugin_menu_playlist_add},
-    {.sep = TRUE},
-    {N_("Add URL ..."), "folder-remote", 'h', CTRL, .func = action_playlist_add_url},
-    {N_("Add Files ..."), "list-add", 'f', .func = action_playlist_add_files}
-};
-
-static const AudguiMenuItem dupe_items[] = {
-    {N_("By Title"), .func = action_playlist_remove_dupes_by_title},
-    {N_("By Filename"), .func = action_playlist_remove_dupes_by_filename},
-    {N_("By File Path"), .func = action_playlist_remove_dupes_by_full_path}
-};
-
-static const AudguiMenuItem playlist_remove_items[] = {
-    {N_("Services"), .get_sub = get_plugin_menu_playlist_remove},
-    {.sep = TRUE},
-    {N_("Remove All"), "edit-delete", .func = action_playlist_remove_all},
-    {N_("Clear Queue"), "edit-clear", 'q', SHIFT, .func = action_playlist_clear_queue},
-    {.sep = TRUE},
-    {N_("Remove Unavailable Files"), "dialog-warning", .func = action_playlist_remove_unavailable},
-    {N_("Remove Duplicates"), "edit-copy", .items = dupe_items, ARRAY_LEN (dupe_items)},
-    {.sep = TRUE},
-    {N_("Remove Unselected"), "list-remove", .func = action_playlist_remove_unselected},
-    {N_("Remove Selected"), "list-remove", GDK_KEY_Delete, .func = action_playlist_remove_selected}
-};
-
-static const AudguiMenuItem playlist_select_items[] = {
-    {N_("Search and Select"), "edit-find", 'f', CTRL, .func = action_playlist_search_and_select},
-    {.sep = TRUE},
-    {N_("Invert Selection"), .func = action_playlist_invert_selection},
-    {N_("Select None"), NULL, 'a', SHIFT | CTRL, .func = action_playlist_select_none},
-    {N_("Select All"), "edit-select-all", 'a', CTRL, .func = action_playlist_select_all},
-};
-
-static const AudguiMenuItem sort_items[] = {
-    {N_("By Title"), .func = action_playlist_sort_by_title},
-    {N_("By Album"), .func = action_playlist_sort_by_album},
-    {N_("By Artist"), .func = action_playlist_sort_by_artist},
-    {N_("By Filename"), .func = action_playlist_sort_by_filename},
-    {N_("By File Path"), .func = action_playlist_sort_by_full_path},
-    {N_("By Release Date"), .func = action_playlist_sort_by_date},
-    {N_("By Track Number"), .func = action_playlist_sort_by_track_number}
-};
-
-static const AudguiMenuItem sort_selected_items[] = {
-    {N_("By Title"), .func = action_playlist_sort_selected_by_title},
-    {N_("By Album"), .func = action_playlist_sort_selected_by_album},
-    {N_("By Artist"), .func = action_playlist_sort_selected_by_artist},
-    {N_("By Filename"), .func = action_playlist_sort_selected_by_filename},
-    {N_("By File Path"), .func = action_playlist_sort_selected_by_full_path},
-    {N_("By Release Date"), .func = action_playlist_sort_selected_by_date},
-    {N_("By Track Number"), .func = action_playlist_sort_selected_by_track_number}
-};
-
-static const AudguiMenuItem playlist_sort_items[] = {
-    {N_("Randomize List"), NULL, 'r', SHIFT | CTRL, .func = action_playlist_randomize_list},
-    {N_("Reverse List"), "view-sort-descending", .func = action_playlist_reverse_list},
-    {.sep = TRUE},
-    {N_("Sort Selected"), "view-sort-ascending", .items = sort_selected_items, ARRAY_LEN (sort_selected_items)},
-    {N_("Sort List"), "view-sort-ascending", .items = sort_items, ARRAY_LEN (sort_items)}
-};
-
-static const AudguiMenuItem playlist_context_items[] = {
-    {N_("Song Info ..."), "dialog-information", 'i', ALT, .func = action_playlist_track_info},
-    {.sep = TRUE},
-    {N_("Cut"), "edit-cut", 'x', CTRL, .func = action_playlist_cut},
-    {N_("Copy"), "edit-copy", 'c', CTRL, .func = action_playlist_copy},
-    {N_("Paste"), "edit-paste", 'v', CTRL, .func = action_playlist_paste},
-    {.sep = TRUE},
-    {N_("Queue/Unqueue"), NULL, 'q', .func = action_queue_toggle},
-    {.sep = TRUE},
-    {N_("Services"), .get_sub = get_plugin_menu_playlist}
-};
-
-static const AudguiMenuItem eq_preset_items[] = {
-    {N_("Load Preset ..."), "document-open", .func = eq_preset_load},
-    {N_("Load Auto Preset ..."), .func = eq_preset_load_auto},
-    {N_("Load Default"), .func = eq_preset_load_default},
-    {N_("Load Preset File ..."), .func = eq_preset_load_file},
-    {N_("Load EQF File ..."), .func = eq_preset_load_eqf},
-    {.sep = TRUE},
-    {N_("Save Preset ..."), "document-save", .func = eq_preset_save},
-    {N_("Save Auto Preset ..."), .func = eq_preset_save_auto},
-    {N_("Save Default"), .func = eq_preset_save_default},
-    {N_("Save Preset File ..."), .func = eq_preset_save_file},
-    {N_("Save EQF File ..."), .func = eq_preset_save_eqf},
-    {.sep = TRUE},
-    {N_("Delete Preset ..."), "edit-delete", .func = eq_preset_delete},
-    {N_("Delete Auto Preset ..."), .func = eq_preset_delete_auto},
-    {.sep = TRUE},
-    {N_("Import Winamp Presets ..."), "document-open", .func = eq_preset_import_winamp},
-    {.sep = TRUE},
-    {N_("Reset to Zero"), "edit-clear", .func = eq_preset_set_zero}
-};
-
-void menu_init (void)
-{
-    static const struct {
-        const AudguiMenuItem * items;
-        int n_items;
-    } table[] = {
-        {main_items, ARRAY_LEN (main_items)},
-        {playback_items, ARRAY_LEN (playback_items)},
-        {playlist_items, ARRAY_LEN (playlist_items)},
-        {view_items, ARRAY_LEN (view_items)},
-        {playlist_add_items, ARRAY_LEN (playlist_add_items)},
-        {playlist_remove_items, ARRAY_LEN (playlist_remove_items)},
-        {playlist_select_items, ARRAY_LEN (playlist_select_items)},
-        {playlist_sort_items, ARRAY_LEN (playlist_sort_items)},
-        {playlist_context_items, ARRAY_LEN (playlist_context_items)},
-        {eq_preset_items, ARRAY_LEN (eq_preset_items)}
-    };
-
-    accel = gtk_accel_group_new ();
-
-    for (int i = UI_MENUS; i --; )
-    {
-        menus[i] = gtk_menu_new ();
-        audgui_menu_init (menus[i], table[i].items, table[i].n_items, accel);
-        g_signal_connect (menus[i], "destroy", (GCallback) gtk_widget_destroyed, & menus[i]);
-    }
-}
-
-void menu_cleanup (void)
-{
-    for (int i = 0; i < UI_MENUS; i ++)
-    {
-        if (menus[i])
-            gtk_widget_destroy (menus[i]);
-    }
-
-    g_object_unref (accel);
-    accel = NULL;
-}
-
-GtkAccelGroup * menu_get_accel_group (void)
-{
-    return accel;
-}
-
-static void get_monitor_geometry (GdkScreen * screen, gint x, gint y, GdkRectangle * geom)
-{
-    int monitors = gdk_screen_get_n_monitors (screen);
-
-    for (int i = 0; i < monitors; i ++)
-    {
-        gdk_screen_get_monitor_geometry (screen, i, geom);
-
-        if (x >= geom->x && x < geom->x + geom->width && y >= geom->y && y < geom->y + geom->height)
-            return;
-    }
-
-    /* fall back to entire screen */
-    geom->x = 0;
-    geom->y = 0;
-    geom->width = gdk_screen_get_width (screen);
-    geom->height = gdk_screen_get_height (screen);
-}
-
-typedef struct {
-    int x, y;
-    bool_t leftward, upward;
-} MenuPosition;
-
-static void position_menu (GtkMenu * menu, int * x, int * y, bool_t * push_in, void * data)
-{
-    const MenuPosition * pos = data;
-
-    GdkRectangle geom;
-    get_monitor_geometry (gtk_widget_get_screen ((GtkWidget *) menu), pos->x, pos->y, & geom);
-
-    GtkRequisition request;
-    gtk_widget_get_preferred_size ((GtkWidget *) menu, NULL, & request);
-
-    if (pos->leftward)
-        * x = MAX (pos->x - request.width, geom.x);
-    else
-        * x = MIN (pos->x, geom.x + geom.width - request.width);
-
-    if (pos->upward)
-        * y = MAX (pos->y - request.height, geom.y);
-    else
-        * y = MIN (pos->y, geom.y + geom.height - request.height);
-}
-
-void menu_popup (int id, int x, int y, bool_t leftward, bool_t upward,
- int button, int time)
-{
-    const MenuPosition pos = {x, y, leftward, upward};
-    gtk_menu_popup ((GtkMenu *) menus[id], NULL, NULL, position_menu, (void *) & pos, button, time);
-}
diff --git a/src/skins/menus.cc b/src/skins/menus.cc
new file mode 100644
index 000000000000..66925e963ecd
--- /dev/null
+++ b/src/skins/menus.cc
@@ -0,0 +1,311 @@
+/*
+ * 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 <gdk/gdkkeysyms.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+#include <libaudgui/menu.h>
+
+#include "actions-mainwin.h"
+#include "actions-playlist.h"
+#include "preset-browser.h"
+#include "preset-list.h"
+#include "view.h"
+
+#define SHIFT GDK_SHIFT_MASK
+#define CTRL GDK_CONTROL_MASK
+#define ALT GDK_MOD1_MASK
+
+#define SHIFT_CTRL (GdkModifierType) (SHIFT | CTRL)
+#define CTRL_ALT   (GdkModifierType) (CTRL | ALT)
+#define NO_MOD     (GdkModifierType) 0
+
+#define NO_KEY     0, NO_MOD
+
+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_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 const AudguiMenuItem main_items[] = {
+    MenuCommand (N_("Open Files ..."), "document-open", 'l', NO_MOD, action_play_file),
+    MenuCommand (N_("Open URL ..."), "folder-remote", 'l', CTRL, action_play_location),
+    MenuCommand (N_("Search Library"), "edit-find", 'y', NO_MOD, action_search_tool),
+    MenuSep (),
+    MenuSub (N_("Playback"), nullptr, get_menu_playback),
+    MenuSub (N_("Playlist"), nullptr, get_menu_playlist),
+    MenuSub (N_("View"), nullptr, get_menu_view),
+    MenuSep (),
+    MenuSub (N_("Services"), nullptr, get_plugin_menu_main),
+    MenuSep (),
+    MenuCommand (N_("About ..."), "help-about", NO_KEY, audgui_show_about_window),
+    MenuCommand (N_("Settings ..."), "preferences-system", 'p', CTRL, audgui_show_prefs_window),
+    MenuCommand (N_("Quit"), "application-exit", 'q', CTRL, aud_quit)
+};
+
+static const AudguiMenuItem playback_items[] = {
+    MenuCommand (N_("Song Info ..."), "dialog-information", 'i', NO_MOD, audgui_infowin_show_current),
+    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_("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 (),
+    MenuCommand (N_("Play"), "media-playback-start", 'x', NO_MOD, aud_drct_play),
+    MenuCommand (N_("Pause"), "media-playback-pause", 'c', NO_MOD, aud_drct_pause),
+    MenuCommand (N_("Stop"), "media-playback-stop", 'v', NO_MOD, aud_drct_stop),
+    MenuCommand (N_("Previous"), "media-skip-backward", 'z', NO_MOD, aud_drct_pl_prev),
+    MenuCommand (N_("Next"), "media-skip-forward", 'b', NO_MOD, aud_drct_pl_next),
+    MenuSep (),
+    MenuCommand (N_("Set A-B Repeat"), nullptr, 'a', NO_MOD, action_ab_set),
+    MenuCommand (N_("Clear A-B Repeat"), nullptr, 'a', SHIFT, action_ab_clear),
+    MenuSep (),
+    MenuCommand (N_("Jump to Song ..."), "go-jump", 'j', NO_MOD, audgui_jump_to_track),
+    MenuCommand (N_("Jump to Time ..."), "go-jump", 'j', CTRL, audgui_jump_to_time)
+};
+
+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_("Rename Playlist ..."), "insert-text", GDK_KEY_F2, NO_MOD, action_playlist_rename),
+    MenuCommand (N_("Remove Playlist"), "edit-delete", 'd', SHIFT, action_playlist_delete),
+    MenuSep (),
+    MenuCommand (N_("Previous Playlist"), "media-skip-backward", GDK_KEY_Tab, SHIFT, action_playlist_prev),
+    MenuCommand (N_("Next Playlist"), "media-skip-forward", GDK_KEY_Tab, NO_MOD, action_playlist_next),
+    MenuSep (),
+    MenuCommand (N_("Import Playlist ..."), "document-open", 'o', NO_MOD, audgui_import_playlist),
+    MenuCommand (N_("Export Playlist ..."), "document-save", 's', SHIFT, audgui_export_playlist),
+    MenuSep (),
+    MenuCommand (N_("Playlist Manager ..."), "audio-x-generic", 'p', NO_MOD, action_playlist_manager),
+    MenuCommand (N_("Queue Manager ..."), nullptr, 'u', CTRL, audgui_queue_manager_show),
+    MenuSep (),
+    MenuCommand (N_("Refresh Playlist"), "view-refresh", GDK_KEY_F5, NO_MOD, action_playlist_refresh_list)
+};
+
+static const AudguiMenuItem view_items[] = {
+    MenuToggle (N_("Show Playlist Editor"), nullptr, 'e', ALT, "skins", "playlist_visible", view_apply_show_playlist, "skins set playlist_visible"),
+    MenuToggle (N_("Show Equalizer"), nullptr, 'g', ALT, "skins", "equalizer_visible", view_apply_show_equalizer, "skins set equalizer_visible"),
+    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_("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 (),
+    MenuToggle (N_("Roll Up Player"), nullptr, 'w', CTRL, "skins", "player_shaded", view_apply_player_shaded, "skins set player_shaded"),
+    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")
+};
+
+static const AudguiMenuItem playlist_add_items[] = {
+    MenuSub (N_("Services"), nullptr, get_plugin_menu_playlist_add),
+    MenuSep (),
+    MenuCommand (N_("Add URL ..."), "folder-remote", 'h', CTRL, action_playlist_add_url),
+    MenuCommand (N_("Add Files ..."), "list-add", 'f', NO_MOD, action_playlist_add_files)
+};
+
+static const AudguiMenuItem dupe_items[] = {
+    MenuCommand (N_("By Title"), nullptr, NO_KEY, action_playlist_remove_dupes_by_title),
+    MenuCommand (N_("By File Name"), nullptr, NO_KEY, action_playlist_remove_dupes_by_filename),
+    MenuCommand (N_("By File Path"), nullptr, NO_KEY, action_playlist_remove_dupes_by_full_path)
+};
+
+static const AudguiMenuItem playlist_remove_items[] = {
+    MenuSub (N_("Services"), nullptr, get_plugin_menu_playlist_remove),
+    MenuSep (),
+    MenuCommand (N_("Remove All"), "edit-delete", NO_KEY, action_playlist_remove_all),
+    MenuCommand (N_("Clear Queue"), "edit-clear", 'q', SHIFT, action_playlist_clear_queue),
+    MenuSep (),
+    MenuCommand (N_("Remove Unavailable Files"), "dialog-warning", NO_KEY, action_playlist_remove_unavailable),
+    MenuSub (N_("Remove Duplicates"), "edit-copy", {dupe_items}),
+    MenuSep (),
+    MenuCommand (N_("Remove Unselected"), "list-remove", NO_KEY, action_playlist_remove_unselected),
+    MenuCommand (N_("Remove Selected"), "list-remove", GDK_KEY_Delete, NO_MOD, action_playlist_remove_selected)
+};
+
+static const AudguiMenuItem playlist_select_items[] = {
+    MenuCommand (N_("Search and Select"), "edit-find", 'f', CTRL, action_playlist_search_and_select),
+    MenuSep (),
+    MenuCommand (N_("Invert Selection"), nullptr, NO_KEY, action_playlist_invert_selection),
+    MenuCommand (N_("Select None"), nullptr, 'a', SHIFT_CTRL, action_playlist_select_none),
+    MenuCommand (N_("Select All"), "edit-select-all", 'a', CTRL, action_playlist_select_all),
+};
+
+static const AudguiMenuItem sort_items[] = {
+    MenuCommand (N_("By Track Number"), nullptr, NO_KEY, action_playlist_sort_by_track_number),
+    MenuCommand (N_("By Title"), nullptr, NO_KEY, action_playlist_sort_by_title),
+    MenuCommand (N_("By Artist"), nullptr, NO_KEY, action_playlist_sort_by_artist),
+    MenuCommand (N_("By Album"), nullptr, NO_KEY, action_playlist_sort_by_album),
+    MenuCommand (N_("By Album Artist"), nullptr, NO_KEY, action_playlist_sort_by_album_artist),
+    MenuCommand (N_("By Release Date"), nullptr, NO_KEY, action_playlist_sort_by_date),
+    MenuCommand (N_("By Genre"), nullptr, NO_KEY, action_playlist_sort_by_genre),
+    MenuCommand (N_("By Length"), nullptr, NO_KEY, action_playlist_sort_by_length),
+    MenuCommand (N_("By File Name"), nullptr, NO_KEY, action_playlist_sort_by_filename),
+    MenuCommand (N_("By File Path"), nullptr, NO_KEY, action_playlist_sort_by_full_path),
+    MenuCommand (N_("By Custom Title"), nullptr, NO_KEY, action_playlist_sort_by_custom_title)
+};
+
+static const AudguiMenuItem sort_selected_items[] = {
+    MenuCommand (N_("By Track Number"), nullptr, NO_KEY, action_playlist_sort_selected_by_track_number),
+    MenuCommand (N_("By Title"), nullptr, NO_KEY, action_playlist_sort_selected_by_title),
+    MenuCommand (N_("By Artist"), nullptr, NO_KEY, action_playlist_sort_selected_by_artist),
+    MenuCommand (N_("By Album"), nullptr, NO_KEY, action_playlist_sort_selected_by_album),
+    MenuCommand (N_("By Album Artist"), nullptr, NO_KEY, action_playlist_sort_selected_by_album_artist),
+    MenuCommand (N_("By Genre"), nullptr, NO_KEY, action_playlist_sort_selected_by_genre),
+    MenuCommand (N_("By Release Date"), nullptr, NO_KEY, action_playlist_sort_selected_by_date),
+    MenuCommand (N_("By Length"), nullptr, NO_KEY, action_playlist_sort_selected_by_length),
+    MenuCommand (N_("By File Name"), nullptr, NO_KEY, action_playlist_sort_selected_by_filename),
+    MenuCommand (N_("By File Path"), nullptr, NO_KEY, action_playlist_sort_selected_by_full_path),
+    MenuCommand (N_("By Custom Title"), nullptr, NO_KEY, action_playlist_sort_selected_by_custom_title)
+};
+
+static const AudguiMenuItem playlist_sort_items[] = {
+    MenuCommand (N_("Randomize List"), nullptr, 'r', SHIFT_CTRL, action_playlist_randomize_list),
+    MenuCommand (N_("Reverse List"), "view-sort-descending", NO_KEY, action_playlist_reverse_list),
+    MenuSep (),
+    MenuSub (N_("Sort Selected"), "view-sort-ascending", {sort_selected_items}),
+    MenuSub (N_("Sort List"), "view-sort-ascending", {sort_items})
+};
+
+static const AudguiMenuItem playlist_context_items[] = {
+    MenuCommand (N_("Song Info ..."), "dialog-information", 'i', ALT, action_playlist_track_info),
+    MenuSep (),
+    MenuCommand (N_("Cut"), "edit-cut", 'x', CTRL, action_playlist_cut),
+    MenuCommand (N_("Copy"), "edit-copy", 'c', CTRL, action_playlist_copy),
+    MenuCommand (N_("Paste"), "edit-paste", 'v', CTRL, action_playlist_paste),
+    MenuSep (),
+    MenuCommand (N_("Queue/Unqueue"), nullptr, 'q', NO_MOD, action_queue_toggle),
+    MenuSep (),
+    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)
+{
+    static const ArrayRef<AudguiMenuItem> table[] = {
+        {main_items},
+        {playback_items},
+        {playlist_items},
+        {view_items},
+        {playlist_add_items},
+        {playlist_remove_items},
+        {playlist_select_items},
+        {playlist_sort_items},
+        {playlist_context_items},
+        {eq_preset_items}
+    };
+
+    accel = gtk_accel_group_new ();
+
+    for (int i = UI_MENUS; i --; )
+    {
+        menus[i] = gtk_menu_new ();
+        audgui_menu_init (menus[i], table[i], accel);
+        g_signal_connect (menus[i], "destroy", (GCallback) gtk_widget_destroyed, & menus[i]);
+    }
+}
+
+void menu_cleanup (void)
+{
+    for (int i = 0; i < UI_MENUS; i ++)
+    {
+        if (menus[i])
+            gtk_widget_destroy (menus[i]);
+    }
+
+    g_object_unref (accel);
+    accel = nullptr;
+}
+
+GtkAccelGroup * menu_get_accel_group (void)
+{
+    return accel;
+}
+
+typedef struct {
+    int x, y;
+    gboolean leftward, upward;
+} MenuPosition;
+
+static void position_menu (GtkMenu * menu, int * x, int * y, gboolean * push_in, void * data)
+{
+    const MenuPosition * pos = (MenuPosition *) data;
+
+    GdkRectangle geom;
+    audgui_get_monitor_geometry (gtk_widget_get_screen ((GtkWidget *) menu), pos->x, pos->y, & geom);
+
+    GtkRequisition request;
+    gtk_widget_size_request ((GtkWidget *) menu, & request);
+
+    if (pos->leftward)
+        * x = aud::max (pos->x - request.width, geom.x);
+    else
+        * x = aud::min (pos->x, geom.x + geom.width - request.width);
+
+    if (pos->upward)
+        * y = aud::max (pos->y - request.height, geom.y);
+    else
+        * y = aud::min (pos->y, geom.y + geom.height - request.height);
+}
+
+void menu_popup (int id, int x, int y, gboolean leftward, gboolean upward,
+ int button, int time)
+{
+    const MenuPosition pos = {x, y, leftward, upward};
+    gtk_menu_popup ((GtkMenu *) menus[id], nullptr, nullptr, position_menu, (void *) & pos, button, time);
+}
diff --git a/src/skins/menus.h b/src/skins/menus.h
index fea57657ea3f..bbd211a0c761 100644
--- a/src/skins/menus.h
+++ b/src/skins/menus.h
@@ -23,7 +23,6 @@
 #define SKINS_MENUS_H
 
 #include <gtk/gtk.h>
-#include <libaudcore/core.h>
 
 enum
 {
@@ -44,6 +43,6 @@ void menu_init ();
 void menu_cleanup ();
 
 GtkAccelGroup * menu_get_accel_group (void);
-void menu_popup (int id, int x, int y, bool_t leftward, bool_t upward, int button, int time);
+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/plugin-window.cc b/src/skins/plugin-window.cc
new file mode 100644
index 000000000000..afb4b0025513
--- /dev/null
+++ b/src/skins/plugin-window.cc
@@ -0,0 +1,175 @@
+/*
+ * 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 <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/runtime.h>
+
+static GList * windows;
+
+static gboolean delete_cb (GtkWidget * window, GdkEvent * event, PluginHandle * plugin)
+{
+    aud_plugin_enable (plugin, false);
+    return true;
+}
+
+static gboolean escape_cb (GtkWidget * widget, GdkEventKey * event, PluginHandle * plugin)
+{
+    if (event->keyval != GDK_KEY_Escape)
+        return false;
+
+    aud_plugin_enable (plugin, false);
+    return true;
+}
+
+static void add_dock_plugin (PluginHandle * plugin, void * unused)
+{
+    GtkWidget * widget = (GtkWidget *) aud_plugin_get_gtk_widget (plugin);
+
+    if (widget)
+    {
+        GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+        gtk_window_set_title ((GtkWindow *) window, aud_plugin_get_name (plugin));
+        gtk_container_add ((GtkContainer *) window, widget);
+
+        g_object_set_data ((GObject *) window, "skins-plugin-id", plugin);
+        g_signal_connect (window, "delete-event", (GCallback) delete_cb, plugin);
+        g_signal_connect (widget, "key-press-event", (GCallback) escape_cb, plugin);
+
+        windows = g_list_prepend (windows, window);
+
+        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, aud::n_elems (pos)))
+        {
+            gtk_window_set_default_size ((GtkWindow *) window, pos[2], pos[3]);
+            gtk_window_move ((GtkWindow *) window, pos[0], pos[1]);
+        }
+        else
+            gtk_window_set_default_size ((GtkWindow *) window, 300, 200);
+
+        if (aud_ui_is_shown ())
+            gtk_widget_show_all (window);
+    }
+}
+
+static void save_window_size (GtkWidget * window)
+{
+    auto plugin = (PluginHandle *) g_object_get_data ((GObject *) window, "skins-plugin-id");
+
+    if (! plugin || ! gtk_widget_get_visible (window))
+        return;
+
+    int pos[4];
+    gtk_window_get_position ((GtkWindow *) window, & pos[0], & pos[1]);
+    gtk_window_get_size ((GtkWindow *) window, & pos[2], & pos[3]);
+
+    const char * basename = aud_plugin_get_basename (plugin);
+    StringBuf pos_str = int_array_to_str (pos, aud::n_elems (pos));
+    aud_set_str ("skins-layout", basename, pos_str);
+}
+
+static int find_cb (GtkWidget * window, PluginHandle * plugin)
+{
+    return (g_object_get_data ((GObject *) window, "skins-plugin-id") != plugin);
+}
+
+static void remove_dock_plugin (PluginHandle * plugin, void * unused)
+{
+    GList * node = g_list_find_custom (windows, plugin, (GCompareFunc) find_cb);
+
+    if (node)
+    {
+        save_window_size ((GtkWidget *) node->data);
+        gtk_widget_destroy ((GtkWidget *) node->data);
+        windows = g_list_delete_link (windows, node);
+    }
+}
+
+void create_plugin_windows (void)
+{
+    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 (void)
+{
+    g_list_foreach (windows, (GFunc) gtk_widget_show_all, nullptr);
+}
+
+void focus_plugin_window (PluginHandle * plugin)
+{
+    GList * node = g_list_find_custom (windows, plugin, (GCompareFunc) find_cb);
+    if (node)
+        gtk_window_present ((GtkWindow *) node->data);
+
+    aud_plugin_send_message (plugin, "grab focus", nullptr, 0);
+}
+
+void hide_plugin_windows (void)
+{
+    g_list_foreach (windows, (GFunc) save_window_size, nullptr);
+    g_list_foreach (windows, (GFunc) gtk_widget_hide, nullptr);
+}
+
+void destroy_plugin_windows (void)
+{
+    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);
+
+    g_warn_if_fail (! windows);
+}
diff --git a/src/skins/plugin-window.h b/src/skins/plugin-window.h
new file mode 100644
index 000000000000..33598939ce94
--- /dev/null
+++ b/src/skins/plugin-window.h
@@ -0,0 +1,33 @@
+/*
+ * plugin-window.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_PLUGIN_WINDOW_H
+#define SKINS_PLUGIN_WINDOW_H
+
+class PluginHandle;
+
+void create_plugin_windows (void);
+void show_plugin_windows (void);
+void focus_plugin_window (PluginHandle * plugin);
+void hide_plugin_windows (void);
+void destroy_plugin_windows (void);
+
+#endif /* SKINS_PLUGIN_WINDOW_H */
diff --git a/src/skins/plugin.c b/src/skins/plugin.c
deleted file mode 100644
index d7701f4aa03d..000000000000
--- a/src/skins/plugin.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-
-#include "menus.h"
-#include "plugin.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 "view.h"
-
-gchar * skins_paths[SKINS_PATH_COUNT];
-
-static gboolean skins_init (void);
-static void skins_cleanup (void);
-
-AUD_IFACE_PLUGIN
-(
-    .name = N_("Winamp Classic Interface"),
-    .domain = PACKAGE,
-    .init = skins_init,
-    .cleanup = skins_cleanup,
-    .prefs = & skins_prefs,
-    .show = view_show_player
-)
-
-static gint update_source;
-
-static void skins_free_paths(void) {
-    int i;
-
-    for (i = 0; i < SKINS_PATH_COUNT; i++)  {
-        g_free(skins_paths[i]);
-        skins_paths[i] = NULL;
-    }
-}
-
-static void skins_init_paths() {
-    char *xdg_data_home;
-    char *xdg_cache_home;
-
-    xdg_data_home = (getenv("XDG_DATA_HOME") == NULL
-        ? g_build_filename(g_get_home_dir(), ".local", "share", NULL)
-        : g_strdup(getenv("XDG_DATA_HOME")));
-    xdg_cache_home = (getenv("XDG_CACHE_HOME") == NULL
-        ? g_build_filename(g_get_home_dir(), ".cache", NULL)
-        : g_strdup(getenv("XDG_CACHE_HOME")));
-
-    skins_paths[SKINS_PATH_USER_SKIN_DIR] =
-        g_build_filename(xdg_data_home, "audacious", "Skins", NULL);
-    skins_paths[SKINS_PATH_SKIN_THUMB_DIR] =
-        g_build_filename(xdg_cache_home, "audacious", "thumbs", NULL);
-
-    g_free(xdg_data_home);
-    g_free(xdg_cache_home);
-}
-
-static gboolean update_cb (void * unused)
-{
-    mainwin_update_song_info ();
-    return TRUE;
-}
-
-static gboolean skins_init (void)
-{
-    skins_init_paths();
-    skins_cfg_load();
-
-    menu_init ();
-
-    char * skin = aud_get_str ("skins", "skin");
-    init_skins (skin);
-    str_unref (skin);
-
-    view_apply_on_top ();
-    view_apply_sticky ();
-
-    if (aud_drct_get_playing ())
-    {
-        ui_main_evlistener_playback_begin (NULL, NULL);
-        if (aud_drct_get_paused ())
-            ui_main_evlistener_playback_pause (NULL, NULL);
-    }
-    else
-        mainwin_update_song_info ();
-
-    update_source = g_timeout_add (250, update_cb, NULL);
-
-    return TRUE;
-}
-
-static void skins_cleanup (void)
-{
-    mainwin_unhook ();
-    playlistwin_unhook ();
-    g_source_remove (update_source);
-
-    skins_cfg_save();
-
-    cleanup_skins();
-    skins_free_paths();
-
-    eq_preset_browser_cleanup ();
-    eq_preset_list_cleanup ();
-
-    menu_cleanup ();
-}
-
-bool_t handle_window_close (void)
-{
-    bool_t handled = FALSE;
-    hook_call ("window close", & handled);
-
-    if (! handled)
-        aud_drct_quit ();
-
-    return TRUE;
-}
diff --git a/src/skins/plugin.cc b/src/skins/plugin.cc
new file mode 100644
index 000000000000..fc7f60cff5cd
--- /dev/null
+++ b/src/skins/plugin.cc
@@ -0,0 +1,202 @@
+/*
+ * 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 <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/hook.h>
+#include <libaudgui/libaudgui.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 "view.h"
+
+class SkinnedUI : public IfacePlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Winamp Classic Interface"),
+        PACKAGE,
+        nullptr,
+        & skins_prefs
+    };
+
+    constexpr SkinnedUI () : IfacePlugin (info) {}
+
+    bool init ();
+    void cleanup ();
+
+    void run ()
+        { gtk_main (); }
+    void quit ()
+        { gtk_main_quit (); }
+
+    void show (bool show)
+        { view_show_player (show); }
+
+    void show_about_window ()
+        { audgui_show_about_window (); }
+    void hide_about_window ()
+        { audgui_hide_about_window (); }
+    void show_filebrowser (bool open)
+        { audgui_run_filebrowser (open); }
+    void hide_filebrowser ()
+        { audgui_hide_filebrowser (); }
+    void show_jump_to_song ()
+        { audgui_jump_to_track (); }
+    void hide_jump_to_song ()
+        { audgui_jump_to_track_hide (); }
+    void show_prefs_window ()
+        { audgui_show_prefs_window (); }
+    void hide_prefs_window ()
+        { audgui_hide_prefs_window (); }
+    void plugin_menu_add (AudMenuID id, void func (), const char * name, const char * icon)
+        { audgui_plugin_menu_add (id, func, name, icon); }
+    void plugin_menu_remove (AudMenuID id, void func ())
+        { audgui_plugin_menu_remove (id, func); }
+};
+
+EXPORT SkinnedUI aud_plugin_instance;
+
+char * skins_paths[SKINS_PATH_COUNT];
+
+static int update_source;
+
+static void skins_free_paths(void) {
+    int i;
+
+    for (i = 0; i < SKINS_PATH_COUNT; i++)  {
+        g_free(skins_paths[i]);
+        skins_paths[i] = nullptr;
+    }
+}
+
+static void skins_init_paths ()
+{
+    const char * xdg_data_home = g_get_user_data_dir ();
+    const char * xdg_cache_home = g_get_user_cache_dir ();
+
+    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);
+}
+
+static gboolean update_cb (void *)
+{
+    mainwin_update_song_info ();
+    return G_SOURCE_CONTINUE;
+}
+
+static void skins_init_main (void)
+{
+    init_skins (aud_get_str ("skins", "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);
+    }
+    else
+        mainwin_update_song_info ();
+
+    update_source = g_timeout_add (250, update_cb, nullptr);
+}
+
+bool SkinnedUI::init ()
+{
+    if (aud_get_mainloop_type () != MainloopType::GLib)
+        return false;
+
+    audgui_init ();
+
+    skins_cfg_load ();
+    skins_init_paths ();
+
+    menu_init ();
+    skins_init_main ();
+
+    create_plugin_windows ();
+
+    return true;
+}
+
+static void skins_cleanup_main (void)
+{
+    mainwin_unhook ();
+    playlistwin_unhook ();
+    g_source_remove (update_source);
+
+    cleanup_skins ();
+
+    eq_preset_browser_cleanup ();
+    eq_preset_list_cleanup ();
+}
+
+void SkinnedUI::cleanup ()
+{
+    skins_cfg_save ();
+
+    destroy_plugin_windows ();
+
+    skins_cleanup_main ();
+    menu_cleanup ();
+
+    skins_free_paths ();
+
+    audgui_cleanup ();
+}
+
+void skins_restart (void)
+{
+    skins_cleanup_main ();
+    skins_init_main ();
+
+    if (aud_ui_is_shown ())
+        view_show_player (true);
+}
+
+gboolean handle_window_close (void)
+{
+    gboolean 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 58c7cc06e0bb..9f94c83508fd 100644
--- a/src/skins/plugin.h
+++ b/src/skins/plugin.h
@@ -21,7 +21,7 @@
 #ifndef PLUGIN_SKINS_H
 #define PLUGIN_SKINS_H
 
-#include <libaudcore/core.h>
+#include <glib.h>
 
 enum {
     SKINS_PATH_USER_SKIN_DIR,
@@ -31,6 +31,8 @@ enum {
 
 extern char * skins_paths[];
 
-bool_t handle_window_close (void);
+void skins_restart (void);
+
+gboolean handle_window_close (void);
 
 #endif
diff --git a/src/skins/preset-browser.c b/src/skins/preset-browser.c
deleted file mode 100644
index 83c4cc802f56..000000000000
--- a/src/skins/preset-browser.c
+++ /dev/null
@@ -1,169 +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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.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, bool_t save,
- const char * default_filename, FilebrowserCallback callback)
-{
-    if (preset_browser)
-        gtk_widget_destroy (preset_browser);
-
-    preset_browser = gtk_file_chooser_dialog_new (title, NULL, save ?
-     GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, _("Cancel"),
-     GTK_RESPONSE_CANCEL, save ? _("Save") : _("Load"), GTK_RESPONSE_ACCEPT,
-     NULL);
-
-    if (default_filename)
-        gtk_file_chooser_set_current_name ((GtkFileChooser *) preset_browser, default_filename);
-
-    g_signal_connect (preset_browser, "response", (GCallback) browser_response, 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 = aud_load_preset_file (filename);
-    if (! preset)
-        return;
-
-    equalizerwin_apply_preset (preset);
-    aud_equalizer_preset_free (preset);
-}
-
-void eq_preset_load_file (void)
-{
-    show_preset_browser (_("Load Preset File"), FALSE, NULL, do_load_file);
-}
-
-static void do_load_eqf (const char * filename)
-{
-    VFSFile * file = vfs_fopen (filename, "r");
-    if (! file)
-        return;
-
-    Index * presets = aud_import_winamp_presets (file);
-
-    if (presets)
-    {
-        if (index_count (presets) >= 1)
-            equalizerwin_apply_preset (index_get (presets, 0));
-
-        index_free_full (presets, (IndexFreeFunc) aud_equalizer_preset_free);
-    }
-
-    vfs_fclose (file);
-}
-
-void eq_preset_load_eqf (void)
-{
-    show_preset_browser (_("Load EQF File"), FALSE, NULL, do_load_eqf);
-}
-
-static void do_save_file (const char * filename)
-{
-    EqualizerPreset * preset = aud_equalizer_preset_new ("");
-    equalizerwin_update_preset (preset);
-    aud_save_preset_file (preset, filename);
-    aud_equalizer_preset_free (preset);
-}
-
-void eq_preset_save_file (void)
-{
-    char * title = aud_drct_get_title ();
-    char * name = title ? str_printf ("%s.%s", title, EQUALIZER_DEFAULT_PRESET_EXT) : NULL;
-
-    show_preset_browser (_("Save Preset File"), TRUE, name, do_save_file);
-
-    str_unref (title);
-    str_unref (name);
-}
-
-static void do_save_eqf (const char * filename)
-{
-    VFSFile * file = vfs_fopen (filename, "w");
-    if (! file)
-        return;
-
-    EqualizerPreset * preset = aud_equalizer_preset_new ("Preset1");
-    equalizerwin_update_preset (preset);
-    aud_export_winamp_preset (preset, file);
-    aud_equalizer_preset_free (preset);
-
-    vfs_fclose (file);
-}
-
-void eq_preset_save_eqf (void)
-{
-    show_preset_browser (_("Save EQF File"), TRUE, NULL, do_save_eqf);
-}
-
-static void do_import_winamp (const char * filename)
-{
-    VFSFile * file = vfs_fopen (filename, "r");
-    if (! file)
-        return;
-
-    Index * list = aud_import_winamp_presets (file);
-    if (list)
-        equalizerwin_import_presets (list);
-
-    vfs_fclose (file);
-}
-
-void eq_preset_import_winamp (void)
-{
-    show_preset_browser (_("Import Winamp Presets"), FALSE, NULL, do_import_winamp);
-}
-
-void eq_preset_browser_cleanup (void)
-{
-    if (preset_browser)
-        gtk_widget_destroy (preset_browser);
-}
diff --git a/src/skins/preset-browser.cc b/src/skins/preset-browser.cc
new file mode 100644
index 000000000000..538b95ec1c1d
--- /dev/null
+++ b/src/skins/preset-browser.cc
@@ -0,0 +1,158 @@
+/*
+ * 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.c b/src/skins/preset-list.c
deleted file mode 100644
index 025761b4d7b7..000000000000
--- a/src/skins/preset-list.c
+++ /dev/null
@@ -1,468 +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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-#include "ui_equalizer.h"
-
-static GtkWidget *equalizerwin_load_window = NULL;
-static GtkWidget *equalizerwin_load_auto_window = NULL;
-static GtkWidget *equalizerwin_save_window = NULL;
-static GtkWidget *equalizerwin_save_entry = NULL;
-static GtkWidget *equalizerwin_save_auto_window = NULL;
-static GtkWidget *equalizerwin_save_auto_entry = NULL;
-static GtkWidget *equalizerwin_delete_window = NULL;
-static GtkWidget *equalizerwin_delete_auto_window = NULL;
-
-static void
-equalizerwin_delete_selected_presets(GtkTreeView *view, gchar *filename)
-{
-    gchar *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 = NULL;
-    GList *litr;
-
-    for (litr = list; litr; litr = litr->next)
-    {
-        GtkTreePath *path = litr->data;
-        rrefs = g_list_append(rrefs, gtk_tree_row_reference_new(model, path));
-    }
-
-    for (litr = rrefs; litr; litr = litr->next)
-    {
-        GtkTreeRowReference *ref = litr->data;
-        GtkTreePath *path = gtk_tree_row_reference_get_path(ref);
-        GtkTreeIter iter;
-        gtk_tree_model_get_iter(model, &iter, 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, gpointer data)
-{
-    const gchar *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, gpointer data)
-{
-    gchar *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(NULL, NULL);
-
-            g_free(text);
-        }
-    }
-}
-
-static void
-equalizerwin_load_ok(GtkWidget *widget, gpointer data)
-{
-    gchar *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, gpointer data)
-{
-    equalizerwin_load_ok(NULL, treeview);
-}
-
-static void
-equalizerwin_delete_delete(GtkWidget *widget, gpointer data)
-{
-    equalizerwin_delete_selected_presets(GTK_TREE_VIEW(data), "eq.preset");
-}
-
-static void
-equalizerwin_save_auto_ok(GtkWidget *widget, gpointer data)
-{
-    const gchar *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, gpointer data)
-{
-    gchar *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(NULL, NULL);
-
-            g_free(text);
-        }
-    }
-}
-
-static void
-equalizerwin_load_auto_ok(GtkWidget *widget, gpointer data)
-{
-    gchar *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, gpointer data)
-{
-    equalizerwin_load_auto_ok(NULL, treeview);
-}
-
-static void
-equalizerwin_delete_auto_delete(GtkWidget *widget, gpointer data)
-{
-    equalizerwin_delete_selected_presets(GTK_TREE_VIEW(data), "eq.auto_preset");
-}
-
-static GtkWidget * equalizerwin_create_list_window (Index * preset_list,
-                                const gchar *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_box_new(GTK_ORIENTATION_VERTICAL, 10);
-    gtk_container_add(GTK_CONTAINER(*window), vbox);
-
-    scrolled_window = gtk_scrolled_window_new(NULL, NULL);
-    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 (int p = 0; p < index_count (preset_list); p ++)
-    {
-        EqualizerPreset * preset = index_get (preset_list, p);
-        gtk_list_store_append(store, &iter);
-        gtk_list_store_set (store, & iter, 0, 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, NULL);
-    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, NULL);
-        gtk_box_pack_start(GTK_BOX(vbox), *entry, FALSE, FALSE, 0);
-    }
-
-    bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
-    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", NULL, NULL);
-    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), NULL);
-
-    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, NULL,
-                                    audgui_button_new (_("Load"), "document-open", NULL, NULL),
-                                    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, NULL,
-                                    audgui_button_new (_("Load"), "document-open", NULL, NULL),
-                                    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", NULL, NULL),
-                                    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", NULL, NULL),
-                                        G_CALLBACK(equalizerwin_save_auto_ok),
-                                        G_CALLBACK(equalizerwin_save_auto_select));
-
-    char * name = aud_drct_get_filename ();
-
-    if (name != NULL)
-    {
-        char * base = g_path_get_basename (name);
-        gtk_entry_set_text ((GtkEntry *) equalizerwin_save_auto_entry, base);
-        g_free (base);
-        str_unref (name);
-    }
-}
-
-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, NULL,
-                                    audgui_button_new (_("Delete"), "edit-delete", NULL, NULL),
-                                    G_CALLBACK(equalizerwin_delete_delete),
-                                    NULL);
-}
-
-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, NULL,
-                                    audgui_button_new (_("Delete"), "edit-delete", NULL, NULL),
-                                    G_CALLBACK(equalizerwin_delete_auto_delete),
-                                    NULL);
-}
-
-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)
-{
-    const EqualizerPreset zero = {0};
-    equalizerwin_apply_preset (& zero);
-}
-
-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/preset-list.cc b/src/skins/preset-list.cc
new file mode 100644
index 000000000000..1b602645e063
--- /dev/null
+++ b/src/skins/preset-list.cc
@@ -0,0 +1,462 @@
+/*  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/skins_cfg.c b/src/skins/skins_cfg.c
deleted file mode 100644
index 3dd2d8119f3e..000000000000
--- a/src/skins/skins_cfg.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * 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 <gtk/gtk.h>
-
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/preferences.h>
-#include <libaudcore/audstrings.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 "util.h"
-
-static const gchar * 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",
- "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",
- NULL};
-
-skins_cfg_t config;
-
-static GtkWidget * skin_view;
-
-typedef struct skins_cfg_boolent_t {
-    const gchar * name;
-    gboolean * ptr;
-} skins_cfg_boolent;
-
-static const skins_cfg_boolent 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}};
-
-typedef struct skins_cfg_nument_t {
-    const gchar * name;
-    gint * ptr;
-} skins_cfg_nument;
-
-static const skins_cfg_nument 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}};
-
-typedef struct skins_cfg_strent_t {
-    const gchar * name;
-    gchar * * ptr;
-} skins_cfg_strent;
-
-void skins_cfg_load (void)
-{
-    aud_config_set_defaults ("skins", skins_defaults);
-
-    for (gint i = 0; i < ARRAY_LEN (skins_boolents); i ++)
-        * skins_boolents[i].ptr = aud_get_bool ("skins", skins_boolents[i].name);
-
-    for (gint i = 0; i < ARRAY_LEN (skins_numents); i ++)
-        * skins_numents[i].ptr = aud_get_int ("skins", skins_numents[i].name);
-}
-
-void skins_cfg_save (void)
-{
-    for (gint i = 0; i < ARRAY_LEN (skins_boolents); i ++)
-        aud_set_bool ("skins", skins_boolents[i].name, * skins_boolents[i].ptr);
-
-    for (gint i = 0; i < ARRAY_LEN (skins_numents); i ++)
-        aud_set_int ("skins", skins_numents[i].name, * skins_numents[i].ptr);
-}
-
-static void
-mainwin_font_set_cb()
-{
-    char * font = aud_get_str ("skins", "mainwin_font");
-    textbox_set_font (mainwin_info, config.mainwin_use_bitmapfont ? NULL : font);
-    str_unref (font);
-}
-
-static void
-playlist_font_set_cb()
-{
-    char * font = aud_get_str ("skins", "playlist_font");
-    ui_skinned_playlist_set_font (playlistwin_list, font);
-    str_unref (font);
-}
-
-static void autoscroll_set_cb (void)
-{
-    textbox_set_scroll (mainwin_info, config.autoscroll);
-    textbox_set_scroll (playlistwin_sinfo, config.autoscroll);
-}
-
-static void vis_reset_cb (void)
-{
-    ui_vis_clear_data (mainwin_vis);
-    ui_svis_clear_data (mainwin_svis);
-    start_stop_visual (FALSE);
-}
-
-static PreferencesWidget font_table_elements[] = {
- {WIDGET_FONT_BTN, N_("_Player:"),
-  .cfg_type = VALUE_STRING, .csect = "skins", .cname = "mainwin_font",
-  .callback = mainwin_font_set_cb, .data = {.font_btn = {N_("Select main player window font:")}}},
- {WIDGET_FONT_BTN, N_("_Playlist:"),
-  .cfg_type = VALUE_STRING, .csect = "skins", .cname = "playlist_font",
-  .callback = playlist_font_set_cb, .data = {.font_btn = {N_("Select playlist font:")}}}};
-
-static void * create_skin_view (void);
-
-static const PreferencesWidget skins_widgets_general[] = {
-    {WIDGET_LABEL, N_("<b>Skin</b>")},
-    {WIDGET_CUSTOM, .data.populate = create_skin_view},
-    {WIDGET_LABEL, N_("<b>Fonts</b>")},
-    {WIDGET_TABLE, .child = TRUE,
-     .data.table = {font_table_elements, ARRAY_LEN (font_table_elements)}},
-    {WIDGET_CHK_BTN, N_("Use bitmap fonts (supports ASCII only)"),
-     .cfg_type = VALUE_BOOLEAN, .cfg = & config.mainwin_use_bitmapfont, .callback = mainwin_font_set_cb},
-    {WIDGET_CHK_BTN, N_("Scroll song title"),
-     .cfg_type = VALUE_BOOLEAN, .cfg = & config.autoscroll, .callback = autoscroll_set_cb},
-    {WIDGET_CHK_BTN, N_("Scroll song title in both directions"),
-     .cfg_type = VALUE_BOOLEAN, .cfg = & config.twoway_scroll, .callback = autoscroll_set_cb}
-};
-
-static ComboBoxElements vis_mode_elements[] = {
-    {GINT_TO_POINTER (VIS_ANALYZER), N_("Analyzer")},
-    {GINT_TO_POINTER (VIS_SCOPE), N_("Scope")},
-    {GINT_TO_POINTER (VIS_VOICEPRINT), N_("Voiceprint / VU meter")},
-    {GINT_TO_POINTER (VIS_OFF), N_("Off")}
-};
-
-static ComboBoxElements analyzer_mode_elements[] = {
-    {GINT_TO_POINTER (ANALYZER_NORMAL), N_("Normal")},
-    {GINT_TO_POINTER (ANALYZER_FIRE), N_("Fire")},
-    {GINT_TO_POINTER (ANALYZER_VLINES), N_("Vertical lines")}
-};
-
-static ComboBoxElements analyzer_type_elements[] = {
-    {GINT_TO_POINTER (ANALYZER_LINES), N_("Lines")},
-    {GINT_TO_POINTER (ANALYZER_BARS), N_("Bars")}
-};
-
-static ComboBoxElements falloff_elements[] = {
-    {GINT_TO_POINTER (FALLOFF_SLOWEST), N_("Slowest")},
-    {GINT_TO_POINTER (FALLOFF_SLOW), N_("Slow")},
-    {GINT_TO_POINTER (FALLOFF_MEDIUM), N_("Medium")},
-    {GINT_TO_POINTER (FALLOFF_FAST), N_("Fast")},
-    {GINT_TO_POINTER (FALLOFF_FASTEST), N_("Fastest")}
-};
-
-static ComboBoxElements scope_mode_elements[] = {
-    {GINT_TO_POINTER (SCOPE_DOT), N_("Dots")},
-    {GINT_TO_POINTER (SCOPE_LINE), N_("Line")},
-    {GINT_TO_POINTER (SCOPE_SOLID), N_("Solid")}
-};
-
-static ComboBoxElements voiceprint_mode_elements[] = {
-    {GINT_TO_POINTER (VOICEPRINT_NORMAL), N_("Normal")},
-    {GINT_TO_POINTER (VOICEPRINT_FIRE), N_("Fire")},
-    {GINT_TO_POINTER (VOICEPRINT_ICE), N_("Ice")}
-};
-
-static ComboBoxElements vu_mode_elements[] = {
-    {GINT_TO_POINTER (VU_NORMAL), N_("Normal")},
-    {GINT_TO_POINTER (VU_SMOOTH), N_("Smooth")}
-};
-
-static const PreferencesWidget skins_widgets_vis[] = {
-    {WIDGET_LABEL, N_("<b>Type</b>")},
-    {WIDGET_COMBO_BOX, N_("Visualization type:"),
-     .cfg_type = VALUE_INT, .cfg = & config.vis_type, .callback = vis_reset_cb,
-     .data.combo = {vis_mode_elements, ARRAY_LEN (vis_mode_elements)}},
-    {WIDGET_LABEL, N_("<b>Analyzer</b>")},
-    {WIDGET_CHK_BTN, N_("Show peaks"),
-     .cfg_type = VALUE_BOOLEAN, .cfg = & config.analyzer_peaks, .callback = vis_reset_cb},
-    {WIDGET_COMBO_BOX, N_("Coloring:"),
-     .cfg_type = VALUE_INT, .cfg = & config.analyzer_mode, .callback = vis_reset_cb,
-     .data.combo = {analyzer_mode_elements, ARRAY_LEN (analyzer_mode_elements)}},
-    {WIDGET_COMBO_BOX, N_("Style:"),
-     .cfg_type = VALUE_INT, .cfg = & config.analyzer_type, .callback = vis_reset_cb,
-     .data.combo = {analyzer_type_elements, ARRAY_LEN (analyzer_type_elements)}},
-    {WIDGET_COMBO_BOX, N_("Falloff:"),
-     .cfg_type = VALUE_INT, .cfg = & config.analyzer_falloff, .callback = vis_reset_cb,
-     .data.combo = {falloff_elements, ARRAY_LEN (falloff_elements)}},
-    {WIDGET_COMBO_BOX, N_("Peak falloff:"),
-     .cfg_type = VALUE_INT, .cfg = & config.peaks_falloff, .callback = vis_reset_cb,
-     .data.combo = {falloff_elements, ARRAY_LEN (falloff_elements)}},
-    {WIDGET_LABEL, N_("<b>Miscellaneous</b>")},
-    {WIDGET_COMBO_BOX, N_("Scope Style:"),
-     .cfg_type = VALUE_INT, .cfg = & config.scope_mode, .callback = vis_reset_cb,
-     .data.combo = {scope_mode_elements, ARRAY_LEN (scope_mode_elements)}},
-    {WIDGET_COMBO_BOX, N_("Voiceprint Coloring:"),
-     .cfg_type = VALUE_INT, .cfg = & config.voiceprint_mode, .callback = vis_reset_cb,
-     .data.combo = {voiceprint_mode_elements, ARRAY_LEN (voiceprint_mode_elements)}},
-    {WIDGET_COMBO_BOX, N_("VU Meter Style:"),
-     .cfg_type = VALUE_INT, .cfg = & config.vu_mode, .callback = vis_reset_cb,
-     .data.combo = {vu_mode_elements, ARRAY_LEN (vu_mode_elements)}}
-};
-
-static const NotebookTab skins_notebook_tabs[] = {
-    {N_("General"), skins_widgets_general, ARRAY_LEN (skins_widgets_general)},
-    {N_("Visualization"), skins_widgets_vis, ARRAY_LEN (skins_widgets_vis)}
-};
-
-static const PreferencesWidget skins_widgets[] = {
-    {WIDGET_NOTEBOOK, .data.notebook = {skins_notebook_tabs, ARRAY_LEN (skins_notebook_tabs)}}
-};
-
-const PluginPreferences skins_prefs = {
-    .widgets = skins_widgets,
-    .n_widgets = ARRAY_LEN (skins_widgets)
-};
-
-void
-on_skin_view_drag_data_received(GtkWidget * widget,
-                                GdkDragContext * context,
-                                gint x, gint y,
-                                GtkSelectionData * selection_data,
-                                guint info, guint time,
-                                gpointer user_data)
-{
-    const gchar * data = (const gchar *) gtk_selection_data_get_data (selection_data);
-    g_return_if_fail (data);
-
-    const gchar * end = strchr (data, '\r');
-    if (! end) end = strchr (data, '\n');
-    if (! end) end = data + strlen (data);
-
-    char * path = str_nget (data, end - data);
-
-    if (strstr (path, "://"))
-    {
-        char * path2 = uri_to_filename (path);
-        if (path2)
-        {
-            str_unref (path);
-            path = path2;
-        }
-    }
-
-    if (file_is_archive(path))
-    {
-        if (! active_skin_load (path))
-            goto DONE;
-
-        skin_install_skin(path);
-
-        if (skin_view)
-            skin_view_update ((GtkTreeView *) skin_view);
-    }
-
-DONE:
-    str_unref (path);
-}
-
-static void * create_skin_view (void)
-{
-    GtkWidget * scrolled = gtk_scrolled_window_new (NULL, NULL);
-    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);
-
-    skin_view = gtk_tree_view_new ();
-    skin_view_realize ((GtkTreeView *) skin_view);
-    skin_view_update ((GtkTreeView *) skin_view);
-    gtk_container_add ((GtkContainer *) scrolled, skin_view);
-
-    drag_dest_set (skin_view);
-
-    g_signal_connect (skin_view, "drag-data-received",
-     (GCallback) on_skin_view_drag_data_received, NULL);
-    g_signal_connect (skin_view, "destroy", (GCallback) gtk_widget_destroyed, & skin_view);
-
-    return scrolled;
-}
diff --git a/src/skins/skins_cfg.cc b/src/skins/skins_cfg.cc
new file mode 100644
index 000000000000..253800063ffd
--- /dev/null
+++ b/src/skins/skins_cfg.cc
@@ -0,0 +1,342 @@
+/*
+ * 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 <gtk/gtk.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 "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 "util.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};
+
+skins_cfg_t config;
+
+static GtkWidget * skin_view;
+
+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}
+};
+
+void skins_cfg_load (void)
+{
+    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);
+
+    config.scale = aud_get_bool ("skins", "double_size") ? 2 : 1;
+}
+
+void skins_cfg_save (void)
+{
+    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 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);
+}
+
+static void
+playlist_font_set_cb()
+{
+    String font = aud_get_str ("skins", "playlist_font");
+    ui_skinned_playlist_set_font (playlistwin_list, font);
+}
+
+static void autoscroll_set_cb (void)
+{
+    textbox_set_scroll (mainwin_info, config.autoscroll);
+    textbox_set_scroll (playlistwin_sinfo, config.autoscroll);
+}
+
+static void vis_reset_cb (void)
+{
+    ui_vis_clear_data (mainwin_vis);
+    ui_svis_clear_data (mainwin_svis);
+    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 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),
+    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 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)),
+    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}}),
+    WidgetLabel (N_("<b>Miscellaneous</b>")),
+    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 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}};
+
+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)
+{
+    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 (! active_skin_load (path))
+            return;
+
+        skin_install_skin(path);
+
+        if (skin_view)
+            skin_view_update ((GtkTreeView *) skin_view);
+    }
+}
+
+static void * create_skin_view (void)
+{
+    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);
+
+    skin_view = gtk_tree_view_new ();
+    skin_view_realize ((GtkTreeView *) skin_view);
+    skin_view_update ((GtkTreeView *) skin_view);
+    gtk_container_add ((GtkContainer *) scrolled, skin_view);
+
+    drag_dest_set (skin_view);
+
+    g_signal_connect (skin_view, "drag-data-received",
+     (GCallback) on_skin_view_drag_data_received, nullptr);
+    g_signal_connect (skin_view, "destroy", (GCallback) gtk_widget_destroyed, & skin_view);
+
+    return scrolled;
+}
diff --git a/src/skins/skins_cfg.h b/src/skins/skins_cfg.h
index 45be875d9d4a..efa8fa71004a 100644
--- a/src/skins/skins_cfg.h
+++ b/src/skins/skins_cfg.h
@@ -23,23 +23,24 @@
 
 #include <gtk/gtk.h>
 
-#include <audacious/types.h>
+struct PluginPreferences;
 
 typedef struct {
-    gint player_x, player_y;
-    gint equalizer_x, equalizer_y;
-    gint playlist_x, playlist_y;
-    gint playlist_width, playlist_height;
-    gboolean autoscroll;
-    gboolean analyzer_peaks;
-    gboolean twoway_scroll;
-    gint vis_type;
-    gint analyzer_mode, analyzer_type;
-    gint scope_mode;
-    gint voiceprint_mode;
-    gint vu_mode;
-    gint analyzer_falloff, peaks_falloff;
-    gboolean mainwin_use_bitmapfont;
+    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;
@@ -49,10 +50,10 @@ void skins_cfg_save();
 
 void on_skin_view_drag_data_received(GtkWidget * widget,
                                 GdkDragContext * context,
-                                gint x, gint y,
+                                int x, int y,
                                 GtkSelectionData * selection_data,
-                                guint info, guint time,
-                                gpointer user_data);
+                                unsigned info, unsigned time,
+                                void * user_data);
 
 extern const PluginPreferences skins_prefs;
 
diff --git a/src/skins/surface.c b/src/skins/surface.c
deleted file mode 100644
index f26544ce3100..000000000000
--- a/src/skins/surface.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * surface.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 <gdk/gdk.h>
-
-#include "surface.h"
-
-cairo_surface_t * surface_new (int w, int h)
-{
-    return cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
-}
-
-cairo_surface_t * surface_new_from_file (const gchar * name)
-{
-    GError * error = NULL;
-    GdkPixbuf * p = gdk_pixbuf_new_from_file (name, & error);
-    if (error) {
-        fprintf (stderr, "Error loading %s: %s.\n", name, error->message);
-        g_error_free (error);
-    }
-    if (! p)
-        return NULL;
-
-    cairo_surface_t * surface = surface_new (gdk_pixbuf_get_width (p),
-     gdk_pixbuf_get_height (p));
-    cairo_t * cr = cairo_create (surface);
-
-    gdk_cairo_set_source_pixbuf (cr, p, 0, 0);
-    cairo_paint (cr);
-
-    cairo_destroy (cr);
-    g_object_unref (p);
-    return surface;
-}
-
-guint32 surface_get_pixel (cairo_surface_t * s, gint x, gint y)
-{
-    if (x < 0 || x >= cairo_image_surface_get_width (s) ||
-     y < 0 || y >= cairo_image_surface_get_height (s))
-        return 0;
-
-    return * ((guint32 *) (cairo_image_surface_get_data (s) +
-     cairo_image_surface_get_stride (s) * y) + x) & 0xffffff;
-}
-
-void surface_copy_rect (cairo_surface_t * a, gint ax, gint ay, gint w, gint h,
- cairo_surface_t * b, gint bx, gint by)
-{
-    cairo_t * cr = cairo_create (b);
-    cairo_set_source_surface (cr, a, bx - ax, by - ay);
-    cairo_rectangle (cr, bx, by, w, h);
-    cairo_fill (cr);
-    cairo_destroy (cr);
-}
diff --git a/src/skins/surface.cc b/src/skins/surface.cc
new file mode 100644
index 000000000000..c71dd694b246
--- /dev/null
+++ b/src/skins/surface.cc
@@ -0,0 +1,74 @@
+/*
+ * surface.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 <gdk/gdk.h>
+
+#include "surface.h"
+
+#include <libaudcore/runtime.h>
+
+cairo_surface_t * surface_new (int w, int h)
+{
+    return cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
+}
+
+cairo_surface_t * surface_new_from_file (const char * name)
+{
+    GError * error = nullptr;
+    GdkPixbuf * p = gdk_pixbuf_new_from_file (name, & error);
+    if (error) {
+        AUDERR ("Error loading %s: %s.\n", name, error->message);
+        g_error_free (error);
+    }
+    if (! p)
+        return nullptr;
+
+    cairo_surface_t * surface = surface_new (gdk_pixbuf_get_width (p),
+     gdk_pixbuf_get_height (p));
+    cairo_t * cr = cairo_create (surface);
+
+    gdk_cairo_set_source_pixbuf (cr, p, 0, 0);
+    cairo_paint (cr);
+
+    cairo_destroy (cr);
+    g_object_unref (p);
+    return surface;
+}
+
+uint32_t surface_get_pixel (cairo_surface_t * s, int x, int y)
+{
+    if (x < 0 || x >= cairo_image_surface_get_width (s) ||
+     y < 0 || y >= cairo_image_surface_get_height (s))
+        return 0;
+
+    return * ((uint32_t *) (cairo_image_surface_get_data (s) +
+     cairo_image_surface_get_stride (s) * y) + x) & 0xffffff;
+}
+
+void surface_copy_rect (cairo_surface_t * a, int ax, int ay, int w, int h,
+ cairo_surface_t * b, int bx, int by)
+{
+    cairo_t * cr = cairo_create (b);
+    cairo_set_source_surface (cr, a, bx - ax, by - ay);
+    cairo_rectangle (cr, bx, by, w, h);
+    cairo_fill (cr);
+    cairo_destroy (cr);
+}
diff --git a/src/skins/surface.h b/src/skins/surface.h
index d725c8e89b0c..c0343398f249 100644
--- a/src/skins/surface.h
+++ b/src/skins/surface.h
@@ -22,13 +22,13 @@
 #ifndef SKINS_SURFACE_H
 #define SKINS_SURFACE_H
 
-#include <glib.h>
+#include <stdint.h>
 #include <cairo.h>
 
-cairo_surface_t * surface_new (gint w, gint h);
-cairo_surface_t * surface_new_from_file (const gchar * name);
-guint32 surface_get_pixel (cairo_surface_t * s, gint x, gint y);
-void surface_copy_rect (cairo_surface_t * a, gint ax, gint ay, gint w, gint h,
- cairo_surface_t * b, gint bx, gint by);
+cairo_surface_t * surface_new (int w, int h);
+cairo_surface_t * surface_new_from_file (const char * name);
+uint32_t surface_get_pixel (cairo_surface_t * s, int x, int y);
+void surface_copy_rect (cairo_surface_t * a, int ax, int ay, int w, int h,
+ cairo_surface_t * b, int bx, int by);
 
 #endif
diff --git a/src/skins/ui_dock.c b/src/skins/ui_dock.c
deleted file mode 100644
index c3eb0a337f87..000000000000
--- a/src/skins/ui_dock.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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 "ui_dock.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 {
-    GtkWidget * window;
-    gint * x, * y;
-    gint w, h;
-    gboolean main;
-    gboolean docked;
-} DockWindow;
-
-static GSList * windows;
-static gint last_x, last_y;
-
-static inline gint least_abs (gint a, gint b)
-{
-    return (abs (a) < abs (b)) ? a : b;
-}
-
-static DockWindow * find_window (GSList * list, GtkWidget * window)
-{
-    for (GSList * node = list; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        if (dw->window == window)
-            return dw;
-    }
-
-    return NULL;
-}
-
-void dock_add_window (GtkWidget * window, gint * x, gint * y, gint w, gint 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);
-}
-
-void dock_remove_window (GtkWidget * window)
-{
-    DockWindow * dw = find_window (windows, window);
-    g_return_if_fail (dw);
-
-    windows = g_slist_remove (windows, dw);
-    g_slice_free (DockWindow, dw);
-}
-
-static void dock_sync (void)
-{
-    for (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        gtk_window_get_position ((GtkWindow *) dw->window, dw->x, dw->y);
-    }
-}
-
-static void clear_docked (void)
-{
-    for (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        dw->docked = FALSE;
-    }
-}
-
-static gboolean is_docked (DockWindow * dw, DockWindow * base, gint 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;
-}
-
-static void find_docked (DockWindow * base, gint type)
-{
-    for (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        if (dw->docked || dw == base)
-            continue;
-
-        dw->docked = is_docked (dw, base, type);
-        if (dw->docked)
-            find_docked (dw, type);
-    }
-}
-
-static void invert_docked (void)
-{
-    for (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        dw->docked = ! dw->docked;
-    }
-}
-
-void dock_set_size (GtkWidget * window, gint w, gint h)
-{
-    DockWindow * base = find_window (windows, window);
-    g_return_if_fail (base);
-
-    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 (GSList * node = windows; node; node = node->next)
-            {
-                DockWindow * dw = node->data;
-                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 (GSList * node = windows; node; node = node->next)
-        {
-            DockWindow * dw = node->data;
-            if (! dw->docked)
-                continue;
-
-            * dw->y += h - base->h;
-            gtk_window_move ((GtkWindow *) dw->window, * 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 (GSList * node = windows; node; node = node->next)
-            {
-                DockWindow * dw = node->data;
-                if (! dw->docked || dw == base)
-                    continue;
-
-                find_docked (dw, DOCK_TYPE_RIGHT);
-            }
-
-            invert_docked ();
-        }
-
-        for (GSList * node = windows; node; node = node->next)
-        {
-            DockWindow * dw = node->data;
-            if (! dw->docked)
-                continue;
-
-            * dw->x += w - base->w;
-            gtk_window_move ((GtkWindow *) dw->window, * 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 (GtkWidget * window, gint x, gint y)
-{
-    DockWindow * dw = find_window (windows, window);
-    g_return_if_fail (dw);
-
-    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 (dw->main)
-        find_docked (dw, DOCK_TYPE_ANY);
-}
-
-void dock_move (gint x, gint y)
-{
-    gint 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 (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        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 ();
-    gint monitors = gdk_screen_get_n_monitors (screen);
-
-    for (gint m = 0; m < monitors; m ++)
-    {
-        GdkRectangle rect;
-        gdk_screen_get_monitor_geometry (screen, m, & rect);
-
-        for (GSList * node = windows; node; node = node->next)
-        {
-            DockWindow * dw = node->data;
-            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 (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        if (! dw->docked)
-            continue;
-
-        for (GSList * node2 = windows; node2; node2 = node2->next)
-        {
-            DockWindow * dw2 = node2->data;
-            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 (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        if (! dw->docked)
-            continue;
-
-        * dw->x += hori;
-        * dw->y += vert;
-    }
-
-    last_x += hori;
-    last_y += vert;
-
-    /* 5. Really move the windows. */
-
-    for (GSList * node = windows; node; node = node->next)
-    {
-        DockWindow * dw = node->data;
-        if (! dw->docked)
-            continue;
-
-        gtk_window_move ((GtkWindow *) dw->window, * dw->x, * dw->y);
-    }
-}
diff --git a/src/skins/ui_dock.cc b/src/skins/ui_dock.cc
new file mode 100644
index 000000000000..dfa302c05462
--- /dev/null
+++ b/src/skins/ui_dock.cc
@@ -0,0 +1,384 @@
+/*
+ * 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 "ui_dock.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 {
+    GtkWidget * window;
+    int * x, * y;
+    int w, h;
+    gboolean main;
+    gboolean docked;
+} DockWindow;
+
+static GSList * windows;
+static int last_x, last_y;
+
+static inline int least_abs (int a, int b)
+{
+    return (abs (a) < abs (b)) ? a : b;
+}
+
+static DockWindow * find_window (GSList * list, GtkWidget * window)
+{
+    for (GSList * node = list; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        if (dw->window == window)
+            return dw;
+    }
+
+    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);
+}
+
+void dock_remove_window (GtkWidget * window)
+{
+    DockWindow * dw = find_window (windows, window);
+    g_return_if_fail (dw);
+
+    windows = g_slist_remove (windows, dw);
+    g_slice_free (DockWindow, dw);
+}
+
+static void dock_sync (void)
+{
+    for (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        gtk_window_get_position ((GtkWindow *) dw->window, dw->x, dw->y);
+    }
+}
+
+static void clear_docked (void)
+{
+    for (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        dw->docked = FALSE;
+    }
+}
+
+static gboolean 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;
+}
+
+static void find_docked (DockWindow * base, int type)
+{
+    for (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        if (dw->docked || dw == base)
+            continue;
+
+        dw->docked = is_docked (dw, base, type);
+        if (dw->docked)
+            find_docked (dw, type);
+    }
+}
+
+static void invert_docked (void)
+{
+    for (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        dw->docked = ! dw->docked;
+    }
+}
+
+void dock_set_size (GtkWidget * window, int w, int h)
+{
+    DockWindow * base = find_window (windows, window);
+    g_return_if_fail (base);
+
+    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 (GSList * node = windows; node; node = node->next)
+            {
+                DockWindow * dw = (DockWindow *) node->data;
+                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 (GSList * node = windows; node; node = node->next)
+        {
+            DockWindow * dw = (DockWindow *) node->data;
+            if (! dw->docked)
+                continue;
+
+            * dw->y += h - base->h;
+            gtk_window_move ((GtkWindow *) dw->window, * 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 (GSList * node = windows; node; node = node->next)
+            {
+                DockWindow * dw = (DockWindow *) node->data;
+                if (! dw->docked || dw == base)
+                    continue;
+
+                find_docked (dw, DOCK_TYPE_RIGHT);
+            }
+
+            invert_docked ();
+        }
+
+        for (GSList * node = windows; node; node = node->next)
+        {
+            DockWindow * dw = (DockWindow *) node->data;
+            if (! dw->docked)
+                continue;
+
+            * dw->x += w - base->w;
+            gtk_window_move ((GtkWindow *) dw->window, * 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 (GtkWidget * window, int x, int y)
+{
+    DockWindow * dw = find_window (windows, window);
+    g_return_if_fail (dw);
+
+    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 (dw->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 (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        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 (GSList * node = windows; node; node = node->next)
+        {
+            DockWindow * dw = (DockWindow *) node->data;
+            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 (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        if (! dw->docked)
+            continue;
+
+        for (GSList * node2 = windows; node2; node2 = node2->next)
+        {
+            DockWindow * dw2 = (DockWindow *) node2->data;
+            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 (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        if (! dw->docked)
+            continue;
+
+        * dw->x += hori;
+        * dw->y += vert;
+    }
+
+    last_x += hori;
+    last_y += vert;
+
+    /* 5. Really move the windows. */
+
+    for (GSList * node = windows; node; node = node->next)
+    {
+        DockWindow * dw = (DockWindow *) node->data;
+        if (! dw->docked)
+            continue;
+
+        gtk_window_move ((GtkWindow *) dw->window, * dw->x, * dw->y);
+    }
+}
diff --git a/src/skins/ui_dock.h b/src/skins/ui_dock.h
index 2bccaf4f1c42..da9c7b631d32 100644
--- a/src/skins/ui_dock.h
+++ b/src/skins/ui_dock.h
@@ -24,13 +24,13 @@
 
 #include <gtk/gtk.h>
 
-void dock_add_window (GtkWidget * window, gint * x, gint * y, gint w, gint h,
+void dock_add_window (GtkWidget * window, int * x, int * y, int w, int h,
  gboolean main);
 void dock_remove_window (GtkWidget * window);
 
-void dock_set_size (GtkWidget * window, gint w, gint h);
+void dock_set_size (GtkWidget * window, int w, int h);
 
-void dock_move_start (GtkWidget * window, gint x, gint y);
-void dock_move (gint x, gint y);
+void dock_move_start (GtkWidget * window, int x, int y);
+void dock_move (int x, int y);
 
 #endif
diff --git a/src/skins/ui_equalizer.c b/src/skins/ui_equalizer.c
deleted file mode 100644
index 4f4757131e36..000000000000
--- a/src/skins/ui_equalizer.c
+++ /dev/null
@@ -1,526 +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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.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 gfloat equalizerwin_get_preamp (void);
-static gfloat equalizerwin_get_band (gint band);
-static void equalizerwin_set_preamp (gfloat preamp);
-static void equalizerwin_set_band (gint band, gfloat value);
-
-static void position_cb (void * data, void * user_data);
-
-GtkWidget *equalizerwin;
-static 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 * equalizer_presets, * equalizer_auto_presets;
-
-void equalizerwin_set_shape (void)
-{
-    int id = aud_get_bool ("skins", "equalizer_shaded") ? SKIN_MASK_EQ_SHADE : SKIN_MASK_EQ;
-    gtk_widget_shape_combine_region (equalizerwin, active_skin->masks[id]);
-}
-
-static void
-equalizerwin_shade_toggle(void)
-{
-    view_set_equalizer_shaded (! aud_get_bool ("skins", "equalizer_shaded"));
-}
-
-void
-equalizerwin_eq_changed(void)
-{
-    aud_set_double (NULL, "equalizer_preamp", equalizerwin_get_preamp ());
-
-    double bands[AUD_EQUALIZER_NBANDS];
-    for (gint i = 0; i < AUD_EQUALIZER_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_EQUALIZER_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_EQUALIZER_NBANDS; i ++)
-        preset->bands[i] = equalizerwin_get_band (i);
-}
-
-void equalizerwin_import_presets (Index * presets)
-{
-    index_copy_insert (presets, 0, equalizer_presets, -1, -1);
-    index_free (presets);
-
-    aud_equalizer_write_presets (equalizer_presets, "eq.preset");
-}
-
-static void eq_on_cb (GtkWidget * button, GdkEventButton * event)
- {aud_set_bool (NULL, "equalizer_active", button_get_active (button)); }
-static void eq_auto_cb (GtkWidget * button, GdkEventButton * event)
- {aud_set_bool (NULL, "equalizer_autoload", button_get_active (equalizerwin_auto)); }
-
-static void update_from_config (void * unused1, void * unused2)
-{
-    button_set_active (equalizerwin_on, aud_get_bool (NULL, "equalizer_active"));
-    eq_slider_set_val (equalizerwin_preamp, aud_get_double (NULL, "equalizer_preamp"));
-
-    gdouble bands[AUD_EQUALIZER_NBANDS];
-    aud_eq_get_bands (bands);
-
-    for (gint i = 0; i < AUD_EQUALIZER_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,
-                   gpointer callback_data)
-{
-    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
-     event->window == gtk_widget_get_window (widget) && event->y < 14)
-    {
-        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)
-{
-    gint pos = hslider_get_pos (equalizerwin_volume);
-
-    gint 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 (gint 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 ();
-    gint pos = hslider_get_pos (equalizerwin_volume);
-    gint 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)
-{
-    gint pos = hslider_get_pos (equalizerwin_balance);
-
-    gint 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 (gint 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 ();
-    gint pos = hslider_get_pos (equalizerwin_balance);
-    pos = MIN(pos, 38);         /* The skin uses a even number of pixels
-                                   for the balance-slider *sigh* */
-    gint 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 (NULL, "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 (NULL, "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 ();
-    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 (NULL, "equalizer_preamp"));
-
-    const gchar * const bandnames[AUD_EQUALIZER_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")};
-    gdouble bands[AUD_EQUALIZER_NBANDS];
-    aud_eq_get_bands (bands);
-
-    for (gint i = 0; i < AUD_EQUALIZER_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)
-{
-    bool_t 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)
-{
-    bool_t 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_taskbar_hint(GTK_WINDOW(equalizerwin), TRUE);
-
-    gtk_widget_set_app_paintable(equalizerwin, TRUE);
-
-    g_signal_connect (equalizerwin, "delete-event", (GCallback) handle_window_close, NULL);
-    g_signal_connect (equalizerwin, "button-press-event", (GCallback) equalizerwin_press, NULL);
-    g_signal_connect (equalizerwin, "key-press-event", (GCallback) mainwin_keypress, NULL);
-}
-
-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 ("playlist position", position_cb);
-
-    index_free_full (equalizer_presets, (IndexFreeFunc) aud_equalizer_preset_free);
-    index_free_full (equalizer_auto_presets, (IndexFreeFunc) aud_equalizer_preset_free);
-    equalizer_presets = NULL;
-    equalizer_auto_presets = NULL;
-}
-
-void
-equalizerwin_create(void)
-{
-    equalizer_presets = aud_equalizer_read_presets("eq.preset");
-    equalizer_auto_presets = aud_equalizer_read_presets("eq.auto_preset");
-
-    if (! equalizer_presets)
-        equalizer_presets = index_new ();
-    if (! equalizer_auto_presets)
-        equalizer_auto_presets = index_new ();
-
-    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, NULL);
-
-    hook_associate ("set equalizer_active", (HookFunction) update_from_config, NULL);
-    hook_associate ("set equalizer_bands", (HookFunction) update_from_config, NULL);
-    hook_associate ("set equalizer_preamp", (HookFunction) update_from_config, NULL);
-
-    int playlist = aud_playlist_get_playing ();
-
-    /* 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 (playlist != -1)
-        position_cb (GINT_TO_POINTER (playlist), NULL);
-
-    hook_associate ("playlist position", position_cb, NULL);
-}
-
-static int equalizerwin_find_preset (Index * list, const char * name)
-{
-    for (int p = 0; p < index_count (list); p ++)
-    {
-        EqualizerPreset * preset = index_get (list, p);
-        if (!g_ascii_strcasecmp(preset->name, name))
-            return p;
-    }
-
-    return -1;
-}
-
-bool_t equalizerwin_load_preset (Index * list, const char * name)
-{
-    int p = equalizerwin_find_preset (list, name);
-    if (p < 0)
-        return FALSE;
-
-    equalizerwin_apply_preset (index_get (list, p));
-    return TRUE;
-}
-
-void equalizerwin_save_preset (Index * list, const char * name, const char * filename)
-{
-    int p = equalizerwin_find_preset (list, name);
-    EqualizerPreset * preset = (p >= 0) ? index_get (list, p) : NULL;
-
-    if (! preset)
-    {
-        preset = aud_equalizer_preset_new (name);
-        index_insert (list, -1, preset);
-    }
-
-    equalizerwin_update_preset (preset);
-
-    aud_equalizer_write_presets (list, filename);
-}
-
-void equalizerwin_delete_preset (Index * list, const char * name, const char * filename)
-{
-    int p = equalizerwin_find_preset (list, name);
-    if (p < 0)
-        return;
-
-    index_delete_full (list, p, 1, (IndexFreeFunc) aud_equalizer_preset_free);
-
-    aud_equalizer_write_presets (list, filename);
-}
-
-static gboolean equalizerwin_read_aud_preset (const gchar * file)
-{
-    EqualizerPreset * preset = aud_load_preset_file (file);
-
-    if (preset == NULL)
-        return FALSE;
-
-    equalizerwin_apply_preset (preset);
-    aud_equalizer_preset_free (preset);
-    return TRUE;
-}
-
-static void equalizerwin_set_preamp (gfloat preamp)
-{
-    eq_slider_set_val (equalizerwin_preamp, preamp);
-    equalizerwin_eq_changed();
-}
-
-static void equalizerwin_set_band (gint band, gfloat value)
-{
-    g_return_if_fail(band >= 0 && band < AUD_EQUALIZER_NBANDS);
-    eq_slider_set_val (equalizerwin_bands[band], value);
-    equalizerwin_eq_changed();
-}
-
-static gfloat equalizerwin_get_preamp (void)
-{
-    return eq_slider_get_val (equalizerwin_preamp);
-}
-
-static gfloat equalizerwin_get_band (gint band)
-{
-    g_return_val_if_fail(band >= 0 && band < AUD_EQUALIZER_NBANDS, 0.0);
-    return eq_slider_get_val (equalizerwin_bands[band]);
-}
-
-static void load_auto_preset (const gchar * filename)
-{
-    gchar * ext = EQUALIZER_DEFAULT_PRESET_EXT;
-    gchar * eq_file = g_strconcat (filename, ".", ext, NULL);
-    gboolean success = equalizerwin_read_aud_preset (eq_file);
-    g_free (eq_file);
-
-    if (success)
-        return;
-
-    gchar * deffile = EQUALIZER_DEFAULT_DIR_PRESET;
-    gchar * folder = g_path_get_dirname (filename);
-    eq_file = g_build_filename (folder, deffile, NULL);
-    success = equalizerwin_read_aud_preset (eq_file);
-
-    g_free (folder);
-    g_free (eq_file);
-
-    if (success)
-        return;
-
-    gchar * base = g_path_get_basename (filename);
-
-    if (! equalizerwin_load_preset (equalizer_auto_presets, base))
-        eq_preset_load_default ();
-
-    g_free (base);
-}
-
-static void position_cb (void * data, void * user_data)
-{
-    gint playlist = GPOINTER_TO_INT (data);
-    gint position = aud_playlist_get_position (playlist);
-
-    if (! aud_get_bool (NULL, "equalizer_autoload") || playlist !=
-     aud_playlist_get_playing () || position == -1)
-        return;
-
-    gchar * filename = aud_playlist_entry_get_filename (playlist, position);
-    load_auto_preset (filename);
-    str_unref (filename);
-}
diff --git a/src/skins/ui_equalizer.cc b/src/skins/ui_equalizer.cc
new file mode 100644
index 000000000000..9cb2edfcdd0f
--- /dev/null
+++ b/src/skins/ui_equalizer.cc
@@ -0,0 +1,498 @@
+/*  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_equalizer.h b/src/skins/ui_equalizer.h
index 39e185625ebc..07b40e5252f6 100644
--- a/src/skins/ui_equalizer.h
+++ b/src/skins/ui_equalizer.h
@@ -28,28 +28,27 @@
 
 #include <gtk/gtk.h>
 
-#include <audacious/types.h>
-#include <libaudcore/index.h>
+#include <libaudcore/equalizer.h>
 
 #define EQUALIZER_DEFAULT_DIR_PRESET "dir_default.preset"
 #define EQUALIZER_DEFAULT_PRESET_EXT "preset"
 
-void equalizerwin_set_shape (void);
 void equalizerwin_create(void);
-void equalizerwin_set_volume_slider(gint percent);
-void equalizerwin_set_balance_slider(gint percent);
+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 * presets);
+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 * equalizer_presets, * equalizer_auto_presets;
+extern Index<EqualizerPreset> equalizer_presets, equalizer_auto_presets;
 
-bool_t equalizerwin_load_preset (Index * list, const char * name);
-void equalizerwin_save_preset (Index * list, const char * name, const char * filename);
-void equalizerwin_delete_preset (Index * list, const char * name, const char * filename);
+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);
 
 #endif /* SKINS_UI_EQUALIZER_H */
diff --git a/src/skins/ui_main.c b/src/skins/ui_main.c
deleted file mode 100644
index 8126eef36afe..000000000000
--- a/src/skins/ui_main.c
+++ /dev/null
@@ -1,1297 +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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <libaudcore/audstrings.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 "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 = NULL;
-
-static gint balance;
-static gint seek_source = 0, seek_start, seek_time;
-
-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 = NULL;
-
-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 gboolean mainwin_info_text_locked = FALSE;
-static guint mainwin_volume_release_timeout = 0;
-
-static void mainwin_position_motion_cb (void);
-static void mainwin_position_release_cb (void);
-static void mainwin_set_volume_diff (gint diff);
-
-static void format_time (gchar buf[7], gint time, gint length)
-{
-    bool_t zero = aud_get_bool (NULL, "leading_zero");
-    bool_t 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);
-    }
-}
-
-void mainwin_set_shape (void)
-{
-    int id = aud_get_bool ("skins", "player_shaded") ? SKIN_MASK_MAIN_SHADE : SKIN_MASK_MAIN;
-    gtk_widget_shape_combine_region (mainwin, active_skin->masks[id]);
-}
-
-static void
-mainwin_menubtn_cb(void)
-{
-    gint x, y;
-    gtk_window_get_position(GTK_WINDOW(mainwin), &x, &y);
-    menu_popup (UI_MENU_MAIN, x + 6, y + MAINWIN_SHADED_HEIGHT, 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 gchar *mainwin_tb_old_text = NULL;
-
-static void mainwin_lock_info_text (const gchar * text)
-{
-    if (mainwin_info_text_locked != TRUE)
-        mainwin_tb_old_text = g_strdup
-         (active_skin->properties.mainwin_othertext_is_status ?
-         textbox_get_text (mainwin_othertext) : textbox_get_text (mainwin_info));
-
-    mainwin_info_text_locked = TRUE;
-    if (active_skin->properties.mainwin_othertext_is_status)
-        textbox_set_text (mainwin_othertext, text);
-    else
-        textbox_set_text (mainwin_info, text);
-}
-
-static void mainwin_release_info_text (void)
-{
-    mainwin_info_text_locked = FALSE;
-
-    if (mainwin_tb_old_text != NULL)
-    {
-        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);
-        g_free(mainwin_tb_old_text);
-        mainwin_tb_old_text = NULL;
-    }
-}
-
-static void mainwin_set_info_text (const gchar * text)
-{
-    if (mainwin_info_text_locked)
-    {
-        g_free (mainwin_tb_old_text);
-        mainwin_tb_old_text = g_strdup (text);
-    }
-    else
-        textbox_set_text (mainwin_info, text);
-}
-
-static gint status_message_source = 0;
-
-static gboolean clear_status_message (void * unused)
-{
-    mainwin_release_info_text ();
-    status_message_source = 0;
-    return FALSE;
-}
-
-void mainwin_show_status_message (const gchar * 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, NULL);
-}
-
-static gchar *
-make_mainwin_title(const gchar * title)
-{
-    if (title != NULL)
-        return g_strdup_printf(_("%s - Audacious"), title);
-    else
-        return g_strdup(_("Audacious"));
-}
-
-void
-mainwin_set_song_title(const gchar * title)
-{
-    gchar *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, gint x, gint 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);
-
-        /* 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 (gint bitrate, gint samplerate, gint channels)
-{
-    gchar scratch[32];
-    gint 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");
-    }
-
-    textbox_set_text (mainwin_othertext, scratch);
-}
-
-void
-mainwin_clear_song_info(void)
-{
-    mainwin_set_song_title (NULL);
-
-    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);
-    textbox_set_text (mainwin_othertext, "");
-
-    if (mainwin_playstatus != NULL)
-        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,
-                           gpointer callback_data)
-{
-    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS &&
-     event->window == gtk_widget_get_window (widget) && event->y < 14)
-    {
-        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,
-                           gint x,
-                           gint y,
-                           GtkSelectionData * selection_data,
-                           guint info,
-                           guint time,
-                           gpointer user_data)
-{
-    g_return_if_fail(selection_data != NULL);
-
-    const gchar * data = (const gchar *) 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 gint time_now (void)
-{
-    struct timeval tv;
-    gettimeofday (& tv, NULL);
-    return (tv.tv_sec % (24 * 3600) * 1000 + tv.tv_usec / 1000);
-}
-
-static gint time_diff (gint a, gint 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 FALSE;
-    }
-
-    gint held = time_diff (seek_time, time_now ());
-    if (held < SEEK_THRESHOLD)
-        return TRUE;
-
-    gint position;
-    if (GPOINTER_TO_INT (rewind))
-        position = seek_start - held / SEEK_SPEED;
-    else
-        position = seek_start + held / SEEK_SPEED;
-
-    position = CLAMP (position, 0, 219);
-    hslider_set_pos (mainwin_position, position);
-    mainwin_position_motion_cb ();
-
-    return TRUE;
-}
-
-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 (NULL, "shuffle", button_get_active (button)); }
-static void mainwin_repeat_cb (GtkWidget * button, GdkEventButton * event)
- {aud_set_bool (NULL, "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)
-{
-    gint pos = hslider_get_pos (mainwin_sposition);
-
-    gint 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 ();
-
-    gint pos = hslider_get_pos (mainwin_sposition);
-    gint length = aud_drct_get_length ();
-    gint time = (pos - 1) * length / 12;
-
-    gchar 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 ();
-
-    gint pos = hslider_get_pos (mainwin_sposition);
-    aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12);
-}
-
-static void mainwin_position_motion_cb (void)
-{
-    gint length = aud_drct_get_length () / 1000;
-    gint pos = hslider_get_pos (mainwin_position);
-    gint time = pos * length / 219;
-
-    gchar * 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)
-{
-    gint length = aud_drct_get_length ();
-    gint pos = hslider_get_pos (mainwin_position);
-    gint time = (gint64) pos * length / 219;
-
-    aud_drct_seek(time);
-    mainwin_release_info_text();
-}
-
-void
-mainwin_adjust_volume_motion(gint v)
-{
-    gchar *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(gint b)
-{
-    gchar *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)
-{
-    gint pos = hslider_get_pos (mainwin_volume);
-    gint frame = (pos * 27 + 25) / 51;
-    hslider_set_frame (mainwin_volume, 0, 15 * frame);
-}
-
-void mainwin_set_volume_slider (gint 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 ();
-    gint pos = hslider_get_pos (mainwin_volume);
-    gint 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 void mainwin_balance_set_frame (void)
-{
-    gint pos = hslider_get_pos (mainwin_balance);
-    gint frame = (abs (pos - 12) * 27 + 6) / 12;
-    hslider_set_frame (mainwin_balance, 9, 15 * frame);
-}
-
-void mainwin_set_balance_slider (gint 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 ();
-    gint pos = hslider_get_pos (mainwin_balance);
-
-    gint 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 (gint diff)
-{
-    gint vol;
-
-    aud_drct_get_volume_main (& vol);
-    vol = 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, (GSourceFunc)(mainwin_volume_release_cb), NULL);
-}
-
-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;
-        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;
-        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 (NULL, "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 (NULL, "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);
-
-    char * font = aud_get_str ("skins", "mainwin_font");
-    mainwin_info = textbox_new (153, "", config.mainwin_use_bitmapfont ? NULL :
-     font, config.autoscroll);
-    str_unref (font);
-
-    window_put_widget (mainwin, FALSE, mainwin_info, 112, 27);
-    g_signal_connect (mainwin_info, "button-press-event", (GCallback)
-     mainwin_info_button_press, NULL);
-
-    mainwin_othertext = textbox_new (153, "", NULL, FALSE);
-    window_put_widget (mainwin, FALSE, mainwin_othertext, 112, 43);
-
-    mainwin_rate_text = textbox_new (15, "", NULL, FALSE);
-    window_put_widget (mainwin, FALSE, mainwin_rate_text, 111, 43);
-
-    mainwin_freq_text = textbox_new (10, "", NULL, 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), NULL);
-
-    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), NULL);
-
-    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), NULL);
-
-    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), NULL);
-
-    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), NULL);
-
-    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, "", NULL, FALSE);
-    window_put_widget (mainwin, TRUE, mainwin_stime_min, 130, 4);
-
-    mainwin_stime_sec = textbox_new (10, "", NULL, 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), NULL);
-    g_signal_connect(mainwin_stime_sec, "button-press-event", G_CALLBACK(change_timer_mode_cb), NULL);
-}
-
-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)
-{
-    bool_t 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)
-{
-    bool_t 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), NULL);
-    g_signal_connect(mainwin, "scroll_event",
-                     G_CALLBACK(mainwin_scrolled), NULL);
-
-    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), NULL);
-
-    ui_main_evlistener_init();
-
-    g_signal_connect ((GObject *) mainwin, "window-state-event", (GCallback) state_cb, NULL);
-    g_signal_connect ((GObject *) mainwin, "delete-event", (GCallback) handle_window_close, NULL);
-}
-
-void mainwin_unhook (void)
-{
-    if (seek_source != 0)
-    {
-        g_source_remove (seek_source);
-        seek_source = 0;
-    }
-
-    ui_main_evlistener_dissociate ();
-    start_stop_visual (TRUE);
-}
-
-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)
-{
-    gint volume, balance;
-
-    aud_drct_get_volume_main (& volume);
-    aud_drct_get_volume_balance (& 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 (gint time, gint length)
-{
-    gchar 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 (gint time, gint 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 * (gint64) 219 / length);
-            hslider_set_pos (mainwin_sposition, 1 + time * (gint64) 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;
-
-    gint 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_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_main.cc b/src/skins/ui_main.cc
new file mode 100644
index 000000000000..bd878038270f
--- /dev/null
+++ b/src/skins/ui_main.cc
@@ -0,0 +1,1352 @@
+/*  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_main.h b/src/skins/ui_main.h
index ab34404dd7dd..e194eeecc361 100644
--- a/src/skins/ui_main.h
+++ b/src/skins/ui_main.h
@@ -26,9 +26,9 @@
 #include <gtk/gtk.h>
 
 /* yes, main window size is fixed */
-#define MAINWIN_WIDTH            (gint)275
-#define MAINWIN_HEIGHT           (gint)116
-#define MAINWIN_TITLEBAR_HEIGHT  (gint)14
+#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
 
@@ -54,33 +54,31 @@ extern GtkWidget *mainwin_position, *mainwin_sposition;
 void mainwin_create(void);
 void mainwin_unhook (void);
 
-void mainwin_adjust_volume_motion(gint v);
+void mainwin_adjust_volume_motion(int v);
 void mainwin_adjust_volume_release(void);
-void mainwin_adjust_balance_motion(gint b);
+void mainwin_adjust_balance_motion(int b);
 void mainwin_adjust_balance_release(void);
-void mainwin_set_volume_slider(gint percent);
-void mainwin_set_balance_slider(gint percent);
+void mainwin_set_volume_slider(int percent);
+void mainwin_set_balance_slider(int percent);
 
 void mainwin_refresh_hints(void);
-void mainwin_set_song_title (const gchar * title);
-void mainwin_set_song_info(gint rate, gint freq, gint nch);
+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_set_shape (void);
-
 void mainwin_disable_seekbar(void);
 
 void mainwin_update_song_info (void);
-void mainwin_show_status_message (const gchar * message);
+void mainwin_show_status_message (const char * message);
 
 void mainwin_drag_data_received(GtkWidget * widget,
                                 GdkDragContext * context,
-                                gint x,
-                                gint y,
+                                int x,
+                                int y,
                                 GtkSelectionData * selection_data,
-                                guint info,
-                                guint time,
-                                gpointer user_data);
+                                unsigned info,
+                                unsigned time,
+                                void * user_data);
 
 gboolean change_timer_mode_cb(GtkWidget *widget, GdkEventButton *event);
 
diff --git a/src/skins/ui_main_evlisteners.c b/src/skins/ui_main_evlisteners.c
deleted file mode 100644
index c7d5b2e41b2d..000000000000
--- a/src/skins/ui_main_evlisteners.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * 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 <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <libaudcore/hook.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 "util.h"
-
-static void title_change (void)
-{
-    if (aud_drct_get_ready ())
-    {
-        gchar * title = aud_drct_get_title ();
-        mainwin_set_song_title (title);
-        str_unref (title);
-    }
-    else
-        mainwin_set_song_title ("Buffering ...");
-}
-
-static void info_change (void)
-{
-    gint bitrate = 0, samplerate = 0, channels = 0;
-
-    if (aud_drct_get_ready ())
-        aud_drct_get_info (& bitrate, & samplerate, & channels);
-
-    mainwin_set_song_info (bitrate, samplerate, channels);
-}
-
-static void
-ui_main_evlistener_hide_seekbar(gpointer hook_data, gpointer 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(gpointer hook_data, gpointer user_data)
-{
-    mainwin_clear_song_info ();
-}
-
-static void repeat_toggled (void * data, void * user)
-{
-    button_set_active (mainwin_repeat, aud_get_bool (NULL, "repeat"));
-}
-
-static void shuffle_toggled (void * data, void * user)
-{
-    button_set_active (mainwin_shuffle, aud_get_bool (NULL, "shuffle"));
-}
-
-static void no_advance_toggled (void * data, void * user)
-{
-    if (aud_get_bool (NULL, "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 (NULL, "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(gpointer hook_data, gpointer user_data)
-{
-    ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PLAY);
-}
-
-static void vis_clear_cb (void)
-{
-    ui_vis_clear_data (mainwin_vis);
-    ui_svis_clear_data (mainwin_svis);
-}
-
-static void render_mono_pcm (const gfloat * pcm)
-{
-    guchar data[512];
-
-    if (config.vis_type != VIS_SCOPE)
-        return;
-
-    for (gint i = 0; i < 75; i ++)
-    {
-        /* the signal is amplified by 2x */
-        /* output values are in the range 0 to 16 */
-        gint val = 8 + roundf (16 * pcm[i * 512 / 75]);
-        data[i] = CLAMP (val, 0, 16);
-    }
-
-    if (aud_get_bool ("skins", "player_shaded"))
-        ui_svis_timeout_func (mainwin_svis, data);
-    else
-        ui_vis_timeout_func (mainwin_vis, data);
-}
-
-/* calculate peak dB level, where 1 is 0 dB */
-static gfloat calc_peak_level (const gfloat * pcm, gint step)
-{
-    gfloat peak = 0.0001; /* must be > 0, or level = -inf */
-
-    for (gint i = 0; i < 512; i ++)
-    {
-        peak = MAX (peak, * pcm);
-        pcm += step;
-    }
-
-    return 20 * log10 (peak);
-}
-
-static void render_multi_pcm (const gfloat * pcm, gint channels)
-{
-    /* "VU meter" */
-    if (config.vis_type != VIS_VOICEPRINT || ! aud_get_bool ("skins", "player_shaded"))
-        return;
-
-    guchar data[512];
-
-    gint level = 38 + calc_peak_level (pcm, channels);
-    data[0] = CLAMP (level, 0, 38);
-
-    if (channels >= 2)
-    {
-        level = 38 + calc_peak_level (pcm + 1, channels);
-        data[1] = CLAMP (level, 0, 38);
-    }
-    else
-        data[1] = data[0];
-
-    ui_svis_timeout_func (mainwin_svis, data);
-}
-
-/* convert linear frequency graph to logarithmic one */
-static void make_log_graph (const gfloat * freq, gint bands, gint db_range, gint
- int_range, guchar * graph)
-{
-    static gint last_bands = 0;
-    static gfloat * xscale = NULL;
-
-    /* conversion table for the x-axis */
-    if (bands != last_bands)
-    {
-        xscale = g_realloc (xscale, sizeof (gfloat) * (bands + 1));
-        for (int i = 0; i <= bands; i ++)
-            xscale[i] = powf (256, (float) i / bands) - 0.5f;
-
-        last_bands = bands;
-    }
-
-    for (gint i = 0; i < bands; i ++)
-    {
-        /* sum up values in freq array between xscale[i] and xscale[i + 1],
-           including fractional parts */
-        gint a = ceilf (xscale[i]);
-        gint b = floorf (xscale[i + 1]);
-        gfloat 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 *= (gfloat) bands / 12;
-
-        /* convert to dB */
-        gfloat val = 20 * log10f (sum);
-
-        /* scale (-db_range, 0.0) to (0.0, int_range) */
-        val = (1 + val / db_range) * int_range;
-
-        graph[i] = CLAMP (val, 0, int_range);
-    }
-}
-
-static void render_freq (const gfloat * freq)
-{
-    bool_t shaded = aud_get_bool ("skins", "player_shaded");
-
-    guchar 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)
-        ui_svis_timeout_func (mainwin_svis, data);
-    else
-        ui_vis_timeout_func (mainwin_vis, data);
-}
-
-void
-ui_main_evlistener_init(void)
-{
-    hook_associate("hide seekbar", ui_main_evlistener_hide_seekbar, NULL);
-    hook_associate("playback begin", ui_main_evlistener_playback_begin, NULL);
-    hook_associate("playback ready", ui_main_evlistener_playback_begin, NULL);
-    hook_associate("playback stop", ui_main_evlistener_playback_stop, NULL);
-    hook_associate("playback pause", ui_main_evlistener_playback_pause, NULL);
-    hook_associate("playback unpause", ui_main_evlistener_playback_unpause, NULL);
-    hook_associate ("title change", (HookFunction) title_change, NULL);
-    hook_associate ("info change", (HookFunction) info_change, NULL);
-
-    hook_associate("playback seek", (HookFunction) mainwin_update_song_info, NULL);
-
-    hook_associate ("set repeat", repeat_toggled, NULL);
-    hook_associate ("set shuffle", shuffle_toggled, NULL);
-    hook_associate ("set no_playlist_advance", no_advance_toggled, NULL);
-    hook_associate ("set stop_after_current_song", stop_after_song_toggled, NULL);
-}
-
-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);
-}
-
-void start_stop_visual (gboolean exiting)
-{
-    static char started = 0;
-
-    if (config.vis_type != VIS_OFF && ! exiting && gtk_widget_get_visible (mainwin))
-    {
-        if (! started)
-        {
-            aud_vis_func_add (AUD_VIS_TYPE_CLEAR, (VisFunc) vis_clear_cb);
-            aud_vis_func_add (AUD_VIS_TYPE_MONO_PCM, (VisFunc) render_mono_pcm);
-            aud_vis_func_add (AUD_VIS_TYPE_MULTI_PCM, (VisFunc) render_multi_pcm);
-            aud_vis_func_add (AUD_VIS_TYPE_FREQ, (VisFunc) render_freq);
-            started = 1;
-        }
-    }
-    else
-    {
-        if (started)
-        {
-            aud_vis_func_remove ((VisFunc) vis_clear_cb);
-            aud_vis_func_remove ((VisFunc) render_mono_pcm);
-            aud_vis_func_remove ((VisFunc) render_multi_pcm);
-            aud_vis_func_remove ((VisFunc) render_freq);
-            started = 0;
-        }
-    }
-}
diff --git a/src/skins/ui_main_evlisteners.cc b/src/skins/ui_main_evlisteners.cc
new file mode 100644
index 000000000000..564400b1a0d2
--- /dev/null
+++ b/src/skins/ui_main_evlisteners.cc
@@ -0,0 +1,346 @@
+/*
+ * 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 "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 "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:
+    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 ()
+{
+    ui_vis_clear_data (mainwin_vis);
+    ui_svis_clear_data (mainwin_svis);
+}
+
+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"))
+        ui_svis_timeout_func (mainwin_svis, data);
+    else
+        ui_vis_timeout_func (mainwin_vis, 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];
+
+    ui_svis_timeout_func (mainwin_svis, 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 float * xscale = nullptr;
+
+    /* conversion table for the x-axis */
+    if (bands != last_bands)
+    {
+        xscale = g_renew (float, xscale, 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)
+        ui_svis_timeout_func (mainwin_svis, 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);
+}
+
+void start_stop_visual (gboolean exiting)
+{
+    static VisCallbacks callbacks;
+    static bool started = false;
+
+    if (config.vis_type != VIS_OFF && ! exiting && gtk_widget_get_visible (mainwin))
+    {
+        if (! started)
+        {
+            aud_visualizer_add (& callbacks);
+            started = true;
+        }
+    }
+    else
+    {
+        if (started)
+        {
+            aud_visualizer_remove (& callbacks);
+            started = false;
+        }
+    }
+}
diff --git a/src/skins/ui_playlist.c b/src/skins/ui_playlist.c
deleted file mode 100644
index 4bb64b4f6b4e..000000000000
--- a/src/skins/ui_playlist.c
+++ /dev/null
@@ -1,1124 +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 <audacious/debug.h>
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.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__)
-
-gint active_playlist = -1, active_length = 0;
-gchar * active_title = NULL;
-
-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,
-                                             gpointer other_cbt);
-static gboolean playlistwin_select_search_kp_cb(GtkWidget *entry,
-                                                GdkEventKey *event,
-                                                gpointer searchdlg_win);
-
-static gint resize_base_width, resize_base_height;
-static int drop_position;
-static gboolean song_changed;
-
-static void playlistwin_update_info (void)
-{
-    char s1[16], s2[16];
-    audgui_format_time (s1, sizeof s1, aud_playlist_get_selected_length (active_playlist));
-    audgui_format_time (s2, sizeof s2, aud_playlist_get_total_length (active_playlist));
-
-    SCONCAT3 (buf, s1, "/", s2);
-    textbox_set_text (playlistwin_info, buf);
-}
-
-static void update_rollup_text (void)
-{
-    gint playlist = aud_playlist_get_active ();
-    gint entry = aud_playlist_get_position (playlist);
-    gchar scratch[512];
-
-    scratch[0] = 0;
-
-    if (entry > -1)
-    {
-        gint length = aud_playlist_entry_get_length (playlist, entry, TRUE);
-
-        if (aud_get_bool (NULL, "show_numbers_in_pl"))
-            APPEND (scratch, "%d. ", 1 + entry);
-
-        gchar * title = aud_playlist_entry_get_title (playlist, entry, TRUE);
-        APPEND (scratch, "%s", title);
-        str_unref (title);
-
-        if (length > 0)
-        {
-            char buf[16];
-            audgui_format_time (buf, sizeof buf, length);
-            APPEND (scratch, " (%s)", 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)
-{
-    gint 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 (gint playlist)
-{
-    gint entries = aud_playlist_entry_count (playlist);
-    gint new = aud_playlist_count ();
-    Index * filenames = index_new ();
-    Index * tuples = index_new ();
-    gint entry;
-
-    aud_playlist_insert (new);
-
-    for (entry = 0; entry < entries; entry ++)
-    {
-        if (aud_playlist_entry_get_selected (playlist, entry))
-        {
-            index_insert (filenames, -1, aud_playlist_entry_get_filename (playlist, entry));
-            index_insert (tuples, -1, aud_playlist_entry_get_tuple (playlist, entry, TRUE));
-        }
-    }
-
-    aud_playlist_entry_insert_batch (new, 0, filenames, tuples, FALSE);
-    aud_playlist_set_active (new);
-}
-
-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;
-    gint result;
-
-    /* create dialog */
-    searchdlg_win = gtk_dialog_new_with_buttons(
-      _("Search entries in active playlist") , GTK_WINDOW(mainwin) ,
-      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT ,
-      _("Cancel") , GTK_RESPONSE_REJECT , _("Search") , GTK_RESPONSE_ACCEPT , NULL );
-
-    /* help text and logo */
-    searchdlg_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL , 4 );
-    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: ") );
-    searchdlg_entry_title = gtk_entry_new();
-    gtk_widget_set_hexpand( searchdlg_entry_title , TRUE );
-    gtk_widget_set_halign( searchdlg_label_title , GTK_ALIGN_START );
-    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: ") );
-    searchdlg_entry_album= gtk_entry_new();
-    gtk_widget_set_hexpand( searchdlg_entry_album , TRUE );
-    gtk_widget_set_halign( searchdlg_label_album , GTK_ALIGN_START );
-    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: ") );
-    searchdlg_entry_performer = gtk_entry_new();
-    gtk_widget_set_hexpand( searchdlg_entry_performer , TRUE );
-    gtk_widget_set_halign( searchdlg_label_performer , GTK_ALIGN_START );
-    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( _("Filename: ") );
-    searchdlg_entry_file_name = gtk_entry_new();
-    gtk_widget_set_hexpand( searchdlg_entry_file_name , TRUE );
-    gtk_widget_set_halign( searchdlg_label_file_name , GTK_ALIGN_START );
-    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_grid_new();
-    gtk_grid_set_row_spacing( GTK_GRID(searchdlg_grid) , 2 );
-    gtk_widget_set_margin_bottom( searchdlg_hbox , 8 );
-    gtk_widget_set_margin_top( searchdlg_checkbt_clearprevsel , 8 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_hbox , 0 , 0 , 2 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_label_title , 0 , 1 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_entry_title , 1 , 1 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_label_album , 0 , 2 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_entry_album , 1 , 2 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_label_performer , 0 , 3 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_entry_performer , 1 , 3 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_label_file_name , 0 , 4 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_entry_file_name , 1 , 4 , 1 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_checkbt_clearprevsel , 0 , 5 , 2 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_checkbt_autoenqueue , 0 , 6 , 2 , 1 );
-    gtk_grid_attach( GTK_GRID(searchdlg_grid) , searchdlg_checkbt_newplaylist , 0 , 7 , 2 , 1 );
-
-    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 = tuple_new();
-         gchar *searchdata = NULL;
-
-         searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_title) );
-         AUDDBG("title=\"%s\"\n", searchdata);
-         tuple_set_str(tuple, FIELD_TITLE, searchdata);
-
-         searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_album) );
-         AUDDBG("album=\"%s\"\n", searchdata);
-         tuple_set_str(tuple, FIELD_ALBUM, searchdata);
-
-         searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_performer) );
-         AUDDBG("performer=\"%s\"\n", searchdata);
-         tuple_set_str(tuple, FIELD_ARTIST, searchdata);
-
-         searchdata = (gchar*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_file_name) );
-         AUDDBG("filename=\"%s\"\n", searchdata);
-         tuple_set_str(tuple, FIELD_FILE_NAME, 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);
-         tuple_unref (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 */
-             gint entries = aud_playlist_entry_count (active_playlist);
-             gint 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)
-{
-    gint entries = aud_playlist_entry_count (active_playlist);
-    gint 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 (gint w, gint h)
-{
-    gint 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,
-                     gpointer 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,
-                  gpointer 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 gchar * minutes, const gchar * seconds)
-{
-    textbox_set_text (playlistwin_time_min, minutes);
-    textbox_set_text (playlistwin_time_sec, seconds);
-}
-
-static void drag_motion (GtkWidget * widget, GdkDragContext * context, gint x,
- gint y, guint 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, guint 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, gint x,
- gint y, guint 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,
- gint x, gint y, GtkSelectionData * data, guint info, guint time, void * unused)
-{
-    audgui_urilist_insert (active_playlist, drop_position, (const gchar *)
-     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 (gint x_offset, gint y_offset)
-{
-    bool_t 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)
-{
-    gint xpos, ypos;
-    gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos);
-    menu_popup (UI_MENU_PLAYLIST_ADD, xpos + 12, ypos + config.playlist_height -
-     8, FALSE, TRUE, event->button, event->time);
-}
-
-static void button_sub_cb (GtkWidget * button, GdkEventButton * event)
-{
-    gint xpos, ypos;
-    gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos);
-    menu_popup (UI_MENU_PLAYLIST_REMOVE, xpos + 40, ypos +
-     config.playlist_height - 8, FALSE, TRUE, event->button, event->time);
-}
-
-static void button_sel_cb (GtkWidget * button, GdkEventButton * event)
-{
-    gint xpos, ypos;
-    gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos);
-    menu_popup (UI_MENU_PLAYLIST_SELECT, xpos + 68, ypos +
-     config.playlist_height - 8, FALSE, TRUE, event->button, event->time);
-}
-
-static void button_misc_cb (GtkWidget * button, GdkEventButton * event)
-{
-    gint xpos, ypos;
-    gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos);
-    menu_popup (UI_MENU_PLAYLIST_SORT, xpos + 100, ypos + config.playlist_height
-     - 8, FALSE, TRUE, event->button, event->time);
-}
-
-static void button_list_cb (GtkWidget * button, GdkEventButton * event)
-{
-    gint xpos, ypos;
-    gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos);
-    menu_popup (UI_MENU_PLAYLIST, xpos + config.playlist_width - 12, ypos +
-     config.playlist_height - 8, TRUE, TRUE, event->button, event->time);
-}
-
-static void
-playlistwin_create_widgets(void)
-{
-    gint w = config.playlist_width, h = config.playlist_height;
-
-    playlistwin_sinfo = textbox_new (w - 35, "", NULL, 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);
-
-    char * 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);
-    str_unref (font);
-
-    /* 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, "", NULL, FALSE);
-    window_put_widget (playlistwin, FALSE, playlistwin_time_min, w - 82, h - 15);
-
-    playlistwin_time_sec = textbox_new (10, "", NULL, 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), NULL);
-    g_signal_connect(playlistwin_time_sec, "button-press-event", G_CALLBACK(change_timer_mode_cb), NULL);
-
-    playlistwin_info = textbox_new (90, "", NULL, 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)
-{
-    bool_t 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_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, NULL);
-    g_signal_connect (playlistwin, "button-press-event", (GCallback) playlistwin_press, NULL);
-    g_signal_connect (playlistwin, "scroll-event", (GCallback) playlistwin_scrolled, NULL);
-    g_signal_connect (playlistwin, "key-press-event", (GCallback) mainwin_keypress, NULL);
-
-    drag_dest_set (playlistwin);
-    drop_position = -1;
-
-    g_signal_connect (playlistwin, "drag-motion", (GCallback) drag_motion, NULL);
-    g_signal_connect (playlistwin, "drag-leave", (GCallback) drag_leave, NULL);
-    g_signal_connect (playlistwin, "drag-drop", (GCallback) drag_drop, NULL);
-    g_signal_connect (playlistwin, "drag-data-received", (GCallback) drag_data_received, NULL);
-}
-
-static void get_title (void)
-{
-    gint playlists = aud_playlist_count ();
-
-    g_free (active_title);
-
-    if (playlists > 1)
-    {
-        gchar * title = aud_playlist_get_title (active_playlist);
-        active_title = g_strdup_printf (_("%s (%d of %d)"), title, 1 +
-         active_playlist, playlists);
-        str_unref (title);
-    }
-    else
-        active_title = NULL;
-}
-
-static void update_cb (void * unused, void * another)
-{
-    gint 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)
-{
-    gint list = GPOINTER_TO_INT (data);
-    aud_playlist_select_all (list, FALSE);
-
-    gint 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 = NULL;
-    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);
-
-    gint 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, NULL);
-    hook_associate ("playlist activate", update_cb, NULL);
-    hook_associate ("playlist update", update_cb, NULL);
-}
-
-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 = NULL;
-}
-
-void action_playlist_track_info(void)
-{
-    playlistwin_fileinfo();
-}
-
-void action_queue_toggle (void)
-{
-    gint focus = aud_playlist_get_focus (active_playlist);
-    if (focus == -1)
-        return;
-
-    gint 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 (active_playlist, at, 1);
-}
-
-void action_playlist_sort_by_track_number (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_TRACK);
-}
-
-void action_playlist_sort_by_title (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_TITLE);
-}
-
-void action_playlist_sort_by_album (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_ALBUM);
-}
-
-void action_playlist_sort_by_artist (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_ARTIST);
-}
-
-void action_playlist_sort_by_full_path (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_PATH);
-}
-
-void action_playlist_sort_by_date (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_DATE);
-}
-
-void action_playlist_sort_by_filename (void)
-{
-    aud_playlist_sort_by_scheme (active_playlist, PLAYLIST_SORT_FILENAME);
-}
-
-void action_playlist_sort_selected_by_track_number (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_TRACK);
-}
-
-void action_playlist_sort_selected_by_title (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_TITLE);
-}
-
-void action_playlist_sort_selected_by_album (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_ALBUM);
-}
-
-void action_playlist_sort_selected_by_artist (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_ARTIST);
-}
-
-void action_playlist_sort_selected_by_full_path (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_PATH);
-}
-
-void action_playlist_sort_selected_by_date (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_DATE);
-}
-
-void action_playlist_sort_selected_by_filename (void)
-{
-    aud_playlist_sort_selected_by_scheme (active_playlist, PLAYLIST_SORT_FILENAME);
-}
-
-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_SORT_TITLE);
-}
-
-void action_playlist_remove_dupes_by_filename (void)
-{
-    aud_playlist_remove_duplicates_by_scheme (active_playlist,
-     PLAYLIST_SORT_FILENAME);
-}
-
-void action_playlist_remove_dupes_by_full_path (void)
-{
-    aud_playlist_remove_duplicates_by_scheme (active_playlist,
-     PLAYLIST_SORT_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);
-    gchar * list = audgui_urilist_create_from_selected (active_playlist);
-
-    if (list == NULL)
-        return;
-
-    gtk_clipboard_set_text (clip, list, -1);
-    g_free (list);
-}
-
-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);
-    gchar * list = gtk_clipboard_wait_for_text (clip);
-
-    if (list == NULL)
-        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_drct_play_playlist (aud_playlist_get_active ());
-}
-
-void action_playlist_new (void)
-{
-    gint 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
-    {
-        gint count = aud_playlist_count ();
-        if (count > 1)
-            aud_playlist_set_active (count - 1);
-    }
-}
-
-void action_playlist_next (void)
-{
-    gint 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, gpointer 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,
-                                gpointer 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_playlist.cc b/src/skins/ui_playlist.cc
new file mode 100644
index 000000000000..1eccd21d2da5
--- /dev/null
+++ b/src/skins/ui_playlist.cc
@@ -0,0 +1,1163 @@
+/*  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_playlist.h b/src/skins/ui_playlist.h
index 64e3a6af28cd..8d5754a3eea5 100644
--- a/src/skins/ui_playlist.h
+++ b/src/skins/ui_playlist.h
@@ -29,10 +29,10 @@ void playlistwin_update (void);
 void playlistwin_create(void);
 void playlistwin_unhook (void);
 void playlistwin_hide_timer(void);
-void playlistwin_set_time (const gchar * minutes, const gchar * seconds);
+void playlistwin_set_time (const char * minutes, const char * seconds);
 
-extern gint active_playlist, active_length;
-extern gchar * active_title;
+extern int active_playlist, active_length;
+extern char * active_title;
 extern GtkWidget * playlistwin, * playlistwin_list, * playlistwin_sinfo;
 
 #endif /* SKINS_UI_PLAYLIST_H */
diff --git a/src/skins/ui_skin.c b/src/skins/ui_skin.c
deleted file mode 100644
index ec2373c3b0b9..000000000000
--- a/src/skins/ui_skin.c
+++ /dev/null
@@ -1,821 +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 <audacious/debug.h>
-#include <audacious/misc.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 gchar *ext_targets[EXTENSION_TARGETS] =
-{ "bmp", "xpm", "png", "svg", "gif", "jpg", "jpeg" };
-
-struct _SkinPixmapIdMapping {
-    SkinPixmapId id;
-    const gchar *name;
-    const gchar *alt_name;
-    gint width, height;
-};
-
-typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
-
-static gboolean skin_load (Skin * skin, const gchar * path);
-
-Skin *active_skin = NULL;
-
-static SkinPixmapIdMapping skin_pixmap_id_map[] = {
-    {SKIN_MAIN, "main", NULL, 0, 0},
-    {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
-    {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
-    {SKIN_TEXT, "text", NULL, 0, 0},
-    {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
-    {SKIN_VOLUME, "volume", NULL, 0, 0},
-    {SKIN_BALANCE, "balance", "volume", 0, 0},
-    {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
-    {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
-    {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
-    {SKIN_POSBAR, "posbar", NULL, 0, 0},
-    {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
-    {SKIN_PLEDIT, "pledit", NULL, 0, 0},
-    {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
-};
-
-static guint skin_pixmap_id_map_size = ARRAY_LEN(skin_pixmap_id_map);
-
-static const guint32 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 gchar * path)
-{
-    AUDDBG("%s\n", path);
-    g_return_val_if_fail(active_skin != NULL, 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)
-{
-    gint i;
-
-    g_return_if_fail(skin != NULL);
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-    {
-        if (skin->pixmaps[i])
-        {
-            cairo_surface_destroy (skin->pixmaps[i]);
-            skin->pixmaps[i] = NULL;
-        }
-    }
-
-    for (i = 0; i < SKIN_MASK_COUNT; i++) {
-        if (skin->masks[i])
-            cairo_region_destroy (skin->masks[i]);
-        skin->masks[i] = NULL;
-    }
-
-    g_free(skin->path);
-    skin->path = NULL;
-}
-
-static void
-skin_destroy(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-    skin_free(skin);
-    g_free(skin);
-}
-
-static const SkinPixmapIdMapping *
-skin_pixmap_id_lookup(guint id)
-{
-    guint i;
-
-    for (i = 0; i < skin_pixmap_id_map_size; i++) {
-        if (id == skin_pixmap_id_map[i].id) {
-            return &skin_pixmap_id_map[i];
-        }
-    }
-
-    return NULL;
-}
-
-static gchar * skin_pixmap_locate (const gchar * dirname, gchar * * basenames)
-{
-    gchar * filename = NULL;
-    gint i;
-
-    for (i = 0; basenames[i] != NULL; i ++)
-    {
-        if ((filename = find_file_case_path (dirname, basenames[i])) != NULL)
-            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 gchar **
-skin_pixmap_create_basenames(const SkinPixmapIdMapping * pixmap_id_mapping)
-{
-    gchar **basenames = g_malloc0(sizeof(gchar*) * (EXTENSION_TARGETS * 2 + 1));
-    gint 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(gchar ** basenames)
-{
-    int i;
-    for (i = 0; basenames[i] != NULL; i++)
-    {
-        g_free(basenames[i]);
-        basenames[i] = NULL;
-    }
-    g_free(basenames);
-}
-
-/**
- * Locates a pixmap file for skin.
- */
-static gchar *
-skin_pixmap_locate_basenames(const Skin * skin,
-                             const SkinPixmapIdMapping * pixmap_id_mapping,
-                             const gchar * path_p)
-{
-    gchar *filename = NULL;
-    const gchar *path = path_p ? path_p : skin->path;
-    gchar **basenames = skin_pixmap_create_basenames(pixmap_id_mapping);
-
-    filename = skin_pixmap_locate(path, basenames);
-
-    skin_pixmap_free_basenames(basenames);
-
-    if (! filename)
-        fprintf (stderr, "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 gchar * path_p)
-{
-    const SkinPixmapIdMapping *pixmap_id_mapping;
-    gchar *filename;
-
-    g_return_val_if_fail(skin != NULL, 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 != NULL, FALSE);
-
-    filename = skin_pixmap_locate_basenames(skin, pixmap_id_mapping, path_p);
-
-    if (filename == NULL)
-        return FALSE;
-
-    skin->pixmaps[id] = surface_new_from_file (filename);
-
-    g_free (filename);
-    return skin->pixmaps[id] ? TRUE : FALSE;
-}
-
-static gint color_diff (guint32 a, guint32 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);
-
-    gint max_d = -1;
-    for (gint y = 0; y < 6; y ++)
-    {
-        for (gint x = 1; x < 150; x ++)
-        {
-            gint c = surface_get_pixel (s, x, y);
-            gint d = color_diff (skin->colors[SKIN_TEXTBG], c);
-            if (d > max_d)
-            {
-                skin->colors[SKIN_TEXTFG] = c;
-                max_d = d;
-            }
-        }
-    }
-}
-
-gboolean
-init_skins(const gchar * 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 == NULL)
-    {
-        mainwin_create();
-        equalizerwin_create();
-        playlistwin_create();
-    }
-
-    if (! path || ! active_skin_load (path))
-    {
-        if (path != NULL)
-            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 */
-        gchar * def = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "Skins"
-         G_DIR_SEPARATOR_S "Default", aud_get_path (AUD_PATH_DATA_DIR));
-
-        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 = NULL;
-
-    gtk_widget_destroy (mainwin);
-    mainwin = NULL;
-    gtk_widget_destroy (playlistwin);
-    playlistwin = NULL;
-    gtk_widget_destroy (equalizerwin);
-    equalizerwin = NULL;
-}
-
-static void skin_load_viscolor (Skin * skin, const gchar * path)
-{
-    memcpy (skin->vis_colors, default_vis_colors, sizeof skin->vis_colors);
-
-    VFSFile * file = open_local_file_nocase (path, "viscolor.txt");
-    if (! file)
-        return;
-
-    void * buffer = NULL;
-    vfs_file_read_all (file, & buffer, NULL);
-    vfs_fclose (file);
-
-    char * string = buffer;
-
-    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, gint, 0),
-             g_array_index (array, gint, 1), g_array_index (array, gint, 2));
-
-        g_array_free (array, TRUE);
-        string = next;
-    }
-
-    g_free (buffer);
-}
-
-static void
-skin_numbers_generate_dash(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-
-    cairo_surface_t * old = skin->pixmaps[SKIN_NUMBERS];
-    if (! old || cairo_image_surface_get_width (old) < 99)
-        return;
-
-    gint h = cairo_image_surface_get_height (old);
-    cairo_surface_t * new = surface_new (108, h);
-
-    surface_copy_rect (old, 0, 0, 99, h, new, 0, 0);
-    surface_copy_rect (old, 90, 0, 9, h, new, 99, 0);
-    surface_copy_rect (old, 20, 6, 5, 1, new, 101, 6);
-
-    cairo_surface_destroy (old);
-    skin->pixmaps[SKIN_NUMBERS] = new;
-}
-
-static gboolean
-skin_load_pixmaps(Skin * skin, const gchar * path)
-{
-    AUDDBG("Loading pixmaps in %s\n", path);
-
-    for (gint i = 0; i < SKIN_PIXMAP_COUNT; i++)
-        if (! skin_load_pixmap_id (skin, 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_masks (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 gchar * skin_path)
-{
-    guint i;
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-    {
-        gchar *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 gchar * path, gboolean force)
-{
-    gchar *newpath, *skin_path;
-    int archive = 0;
-
-    AUDDBG("Attempt to load skin \"%s\"\n", path);
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-    g_return_val_if_fail(path != NULL, 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;
-    }
-
-    if(archive) del_directory(skin_path);
-    g_free(skin_path);
-
-    mainwin_set_shape ();
-    equalizerwin_set_shape ();
-
-    return TRUE;
-}
-
-void skin_install_skin (const gchar * path)
-{
-#ifdef S_IRGRP
-    const mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-#else
-    const mode_t mode = S_IRWXU;
-#endif
-
-    if (g_mkdir_with_parents (skins_paths[SKINS_PATH_USER_SKIN_DIR], mode) < 0)
-    {
-        fprintf (stderr, "Failed to create %s: %s\n",
-         skins_paths[SKINS_PATH_USER_SKIN_DIR], strerror (errno));
-        return;
-    }
-
-    GError * err = 0;
-    gchar * data;
-    gsize len;
-
-    if (! g_file_get_contents (path, & data, & len, & err))
-    {
-        fprintf (stderr, "Failed to read %s: %s\n", path, err->message);
-        g_error_free (err);
-        return;
-    }
-
-    gchar * base = g_path_get_basename (path);
-    gchar * target = g_build_filename (skins_paths[SKINS_PATH_USER_SKIN_DIR], base, NULL);
-
-    if (! g_file_set_contents (target, data, len, & err))
-    {
-        fprintf (stderr, "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 gchar * path)
-{
-    gboolean ret;
-
-    g_return_val_if_fail(skin != NULL, 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])
-    {
-        gint 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]));
-
-    return TRUE;
-}
-
-void skin_draw_pixbuf (cairo_t * cr, SkinPixmapId id, gint xsrc, gint ysrc, gint
- xdest, gint ydest, gint width, gint height)
-{
-    if (! active_skin->pixmaps[id])
-        return;
-
-    cairo_set_source_surface (cr, active_skin->pixmaps[id], xdest - xsrc,
-     ydest - ysrc);
-    cairo_rectangle (cr, xdest, ydest, width, height);
-    cairo_fill (cr);
-}
-
-void skin_get_eq_spline_colors (Skin * skin, guint32 colors[19])
-{
-    if (! skin->pixmaps[SKIN_EQMAIN])
-    {
-        memset (colors, 0, sizeof (guint32) * 19);
-        return;
-    }
-
-    for (gint 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, gint width, gint
- 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
-     */
-
-    gint 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, gint width, gint
- 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
-     */
-
-    gint 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, gint width, gint
- 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)
-     */
-
-    gint 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, gint width, gint 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, gint 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)
-     */
-
-    gint 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)
-     */
-
-    gint 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.cc b/src/skins/ui_skin.cc
new file mode 100644
index 000000000000..d85811447022
--- /dev/null
+++ b/src/skins/ui_skin.cc
@@ -0,0 +1,809 @@
+/*  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.h b/src/skins/ui_skin.h
index 447709fa904b..acc64c874372 100644
--- a/src/skins/ui_skin.h
+++ b/src/skins/ui_skin.h
@@ -26,12 +26,13 @@
 #ifndef SKIN_H
 #define SKIN_H
 
+#include <stdint.h>
 #include <gtk/gtk.h>
 
-#define COLOR(r,g,b) (((guint32) (r) << 16) | ((guint32) (g) << 8) | (guint32) (b))
-#define COLOR_R(c) ((gint) (((c) & 0xff0000) >> 16))
-#define COLOR_G(c) ((gint) (((c) & 0xff00) >> 8))
-#define COLOR_B(c) ((gint) ((c) & 0xff))
+#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))
+#define COLOR_B(c) ((int) ((c) & 0xff))
 
 typedef enum {
     SKIN_MAIN = 0,
@@ -69,138 +70,137 @@ typedef enum {
     SKIN_COLOR_COUNT
 } SkinColorId;
 
-typedef struct {
+struct SkinProperties {
     /* Vis properties */
-    gint mainwin_vis_x;
-    gint mainwin_vis_y;
-    gboolean mainwin_vis_visible;
+    int mainwin_vis_x = 24;
+    int mainwin_vis_y = 43;
+    int mainwin_vis_visible = true;
 
     /* Text properties */
-    gint mainwin_text_x;
-    gint mainwin_text_y;
-    gint mainwin_text_width;
-    gboolean mainwin_text_visible;
+    int mainwin_text_x = 112;
+    int mainwin_text_y = 27;
+    int mainwin_text_width = 153;
+    int mainwin_text_visible = true;
 
     /* Infobar properties */
-    gint mainwin_infobar_x;
-    gint mainwin_infobar_y;
-    gboolean mainwin_othertext_visible;
+    int mainwin_infobar_x = 112;
+    int mainwin_infobar_y = 43;
+    int mainwin_othertext_visible = false;
 
-    gint mainwin_number_0_x;
-    gint mainwin_number_0_y;
+    int mainwin_number_0_x = 36;
+    int mainwin_number_0_y = 26;
 
-    gint mainwin_number_1_x;
-    gint mainwin_number_1_y;
+    int mainwin_number_1_x = 48;
+    int mainwin_number_1_y = 26;
 
-    gint mainwin_number_2_x;
-    gint mainwin_number_2_y;
+    int mainwin_number_2_x = 60;
+    int mainwin_number_2_y = 26;
 
-    gint mainwin_number_3_x;
-    gint mainwin_number_3_y;
+    int mainwin_number_3_x = 78;
+    int mainwin_number_3_y = 26;
 
-    gint mainwin_number_4_x;
-    gint mainwin_number_4_y;
+    int mainwin_number_4_x = 90;
+    int mainwin_number_4_y = 26;
 
-    gint mainwin_playstatus_x;
-    gint mainwin_playstatus_y;
+    int mainwin_playstatus_x = 24;
+    int mainwin_playstatus_y = 28;
 
-    gint mainwin_volume_x;
-    gint mainwin_volume_y;
+    int mainwin_volume_x = 107;
+    int mainwin_volume_y = 57;
 
-    gint mainwin_balance_x;
-    gint mainwin_balance_y;
+    int mainwin_balance_x = 177;
+    int mainwin_balance_y = 57;
 
-    gint mainwin_position_x;
-    gint mainwin_position_y;
+    int mainwin_position_x = 16;
+    int mainwin_position_y = 72;
 
-    gint mainwin_previous_x;
-    gint mainwin_previous_y;
+    int mainwin_previous_x = 16;
+    int mainwin_previous_y = 88;
 
-    gint mainwin_play_x;
-    gint mainwin_play_y;
+    int mainwin_play_x = 39;
+    int mainwin_play_y = 88;
 
-    gint mainwin_pause_x;
-    gint mainwin_pause_y;
+    int mainwin_pause_x = 62;
+    int mainwin_pause_y = 88;
 
-    gint mainwin_stop_x;
-    gint mainwin_stop_y;
+    int mainwin_stop_x = 85;
+    int mainwin_stop_y = 88;
 
-    gint mainwin_next_x;
-    gint mainwin_next_y;
+    int mainwin_next_x = 108;
+    int mainwin_next_y = 88;
 
-    gint mainwin_eject_x;
-    gint mainwin_eject_y;
+    int mainwin_eject_x = 136;
+    int mainwin_eject_y = 89;
 
-    gint mainwin_eqbutton_x;
-    gint mainwin_eqbutton_y;
+    int mainwin_eqbutton_x = 219;
+    int mainwin_eqbutton_y = 58;
 
-    gint mainwin_plbutton_x;
-    gint mainwin_plbutton_y;
+    int mainwin_plbutton_x = 242;
+    int mainwin_plbutton_y = 58;
 
-    gint mainwin_shuffle_x;
-    gint mainwin_shuffle_y;
+    int mainwin_shuffle_x = 164;
+    int mainwin_shuffle_y = 89;
 
-    gint mainwin_repeat_x;
-    gint mainwin_repeat_y;
+    int mainwin_repeat_x = 210;
+    int mainwin_repeat_y = 89;
 
-    gint mainwin_about_x;
-    gint mainwin_about_y;
+    int mainwin_about_x = 247;
+    int mainwin_about_y = 83;
 
-    gint mainwin_minimize_x;
-    gint mainwin_minimize_y;
+    int mainwin_minimize_x = 244;
+    int mainwin_minimize_y = 3;
 
-    gint mainwin_shade_x;
-    gint mainwin_shade_y;
+    int mainwin_shade_x = 254;
+    int mainwin_shade_y = 3;
 
-    gint mainwin_close_x;
-    gint mainwin_close_y;
+    int mainwin_close_x = 264;
+    int mainwin_close_y = 3;
 
-    gint mainwin_width;
-    gint mainwin_height;
+    int mainwin_width = 275;
+    int mainwin_height = 116;
 
-    gboolean mainwin_menurow_visible;
-    gboolean mainwin_streaminfo_visible;
-    gboolean mainwin_othertext_is_status;
+    int mainwin_menurow_visible = true;
+    int mainwin_streaminfo_visible = true;
+    int mainwin_othertext_is_status = false;
 
-    gint textbox_bitmap_font_width;
-    gint textbox_bitmap_font_height;
-} SkinProperties;
+    int textbox_bitmap_font_width = 5;
+    int textbox_bitmap_font_height = 6;
+};
 
 extern const SkinProperties skin_default_hints;
 
 typedef struct {
-    gchar *path;
+    char *path;
     cairo_surface_t * pixmaps[SKIN_PIXMAP_COUNT];
-    guint32 colors[SKIN_COLOR_COUNT];
-    guint32 vis_colors[24];
-    cairo_region_t * masks[SKIN_MASK_COUNT];
+    uint32_t colors[SKIN_COLOR_COUNT];
+    uint32_t vis_colors[24];
     SkinProperties properties;
 } Skin;
 
 extern Skin * active_skin;
 
-gboolean init_skins(const gchar * path);
+gboolean init_skins(const char * path);
 void cleanup_skins(void);
 
-gboolean active_skin_load(const gchar * path);
+gboolean active_skin_load(const char * path);
 
-void skin_draw_pixbuf (cairo_t * cr, SkinPixmapId id, gint xsrc, gint ysrc,
- gint xdest, gint ydest, gint width, gint height);
+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, guint32 colors[19]);
-void skin_install_skin(const gchar * path);
+void skin_get_eq_spline_colors(Skin * skin, uint32_t colors[19]);
+void skin_install_skin(const char * path);
 
-void skin_draw_playlistwin_shaded (cairo_t * cr, gint width, gboolean focus);
-void skin_draw_playlistwin_frame (cairo_t * cr, gint width, gint height,
+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);
 
 /* 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);
+void skin_load_masks (Skin * skin, const char * path, GdkRegion * masks[SKIN_MASK_COUNT]);
 
-static inline void set_cairo_color (cairo_t * cr, guint32 c)
+static inline void set_cairo_color (cairo_t * cr, uint32_t c)
 {
     cairo_set_source_rgb (cr, COLOR_R(c) / 255.0, COLOR_G(c) / 255.0, COLOR_B(c)
      / 255.0);
diff --git a/src/skins/ui_skin_load_ini.c b/src/skins/ui_skin_load_ini.c
deleted file mode 100644
index ed4f26d61e78..000000000000
--- a/src/skins/ui_skin_load_ini.c
+++ /dev/null
@@ -1,440 +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 "ui_skin.h"
-#include "util.h"
-
-/*
- * skin.hints parsing
- */
-
-typedef struct {
-    const char * name;
-    int * value_ptr;
-} HintPair;
-
-typedef struct {
-    bool_t valid_heading;
-} HintsLoadState;
-
-const SkinProperties skin_default_hints = {
-    .mainwin_vis_x = 24,
-    .mainwin_vis_y = 43,
-    .mainwin_vis_visible = TRUE,
-
-    .mainwin_text_x = 112,
-    .mainwin_text_y = 27,
-    .mainwin_text_width = 153,
-    .mainwin_text_visible = TRUE,
-
-    .mainwin_infobar_x = 112,
-    .mainwin_infobar_y = 43,
-    .mainwin_othertext_visible = FALSE,
-
-    .mainwin_number_0_x = 36,
-    .mainwin_number_0_y = 26,
-
-    .mainwin_number_1_x = 48,
-    .mainwin_number_1_y = 26,
-
-    .mainwin_number_2_x = 60,
-    .mainwin_number_2_y = 26,
-
-    .mainwin_number_3_x = 78,
-    .mainwin_number_3_y = 26,
-
-    .mainwin_number_4_x = 90,
-    .mainwin_number_4_y = 26,
-
-    .mainwin_playstatus_x = 24,
-    .mainwin_playstatus_y = 28,
-
-    .mainwin_volume_x = 107,
-    .mainwin_volume_y = 57,
-
-    .mainwin_balance_x = 177,
-    .mainwin_balance_y = 57,
-
-    .mainwin_position_x = 16,
-    .mainwin_position_y = 72,
-
-    .mainwin_previous_x = 16,
-    .mainwin_previous_y = 88,
-
-    .mainwin_play_x = 39,
-    .mainwin_play_y = 88,
-
-    .mainwin_pause_x = 62,
-    .mainwin_pause_y = 88,
-
-    .mainwin_stop_x = 85,
-    .mainwin_stop_y = 88,
-
-    .mainwin_next_x = 108,
-    .mainwin_next_y = 88,
-
-    .mainwin_eject_x = 136,
-    .mainwin_eject_y = 89,
-
-    .mainwin_eqbutton_x = 219,
-    .mainwin_eqbutton_y = 58,
-
-    .mainwin_plbutton_x = 242,
-    .mainwin_plbutton_y = 58,
-
-    .mainwin_shuffle_x = 164,
-    .mainwin_shuffle_y = 89,
-
-    .mainwin_repeat_x = 210,
-    .mainwin_repeat_y = 89,
-
-    .mainwin_about_x = 247,
-    .mainwin_about_y = 83,
-
-    .mainwin_minimize_x = 244,
-    .mainwin_minimize_y = 3,
-
-    .mainwin_shade_x = 254,
-    .mainwin_shade_y = 3,
-
-    .mainwin_close_x = 264,
-    .mainwin_close_y = 3,
-
-    .mainwin_width = 275,
-    .mainwin_height = 116,
-
-    .mainwin_menurow_visible = TRUE,
-    .mainwin_streaminfo_visible = TRUE,
-    .mainwin_othertext_is_status = FALSE,
-
-    .textbox_bitmap_font_width = 5,
-    .textbox_bitmap_font_height = 6
-};
-
-/* 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 * a, const void * b)
-{
-    return g_ascii_strcasecmp (((const HintPair *) a)->name, ((const HintPair *) b)->name);
-}
-
-static void hints_handle_heading (const char * heading, void * data)
-{
-    HintsLoadState * state = data;
-
-    state->valid_heading = ! g_ascii_strcasecmp (heading, "skin");
-}
-
-static void hints_handle_entry (const char * key, const char * value, void * data)
-{
-    HintsLoadState * state = data;
-
-    if (! state->valid_heading)
-        return;
-
-    HintPair key_pair = {.name = key};
-    HintPair * pair = bsearch (& key_pair, hint_pairs,
-     ARRAY_LEN (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;
-
-    HintsLoadState state = {.valid_heading = FALSE};
-
-    VFSFile * file = open_local_file_nocase (path, "skin.hints");
-
-    if (file)
-    {
-        inifile_parse (file, hints_handle_heading, hints_handle_entry, & state);
-        vfs_fclose (file);
-    }
-
-    skin->properties = static_hints;
-}
-
-/*
- * pledit.txt parsing
- */
-
-typedef struct {
-    bool_t valid_heading;
-    Skin * skin;
-} PLColorsLoadState;
-
-static void pl_colors_handle_heading (const char * heading, void * data)
-{
-    PLColorsLoadState * state = data;
-
-    state->valid_heading = ! g_ascii_strcasecmp (heading, "text");
-}
-
-static uint32_t convert_color_string (const char * str)
-{
-    if (* str == '#')
-        str ++;
-
-    return strtol (str, NULL, 16);
-}
-
-static void pl_colors_handle_entry (const char * key, const char * value, void * data)
-{
-    PLColorsLoadState * state = data;
-
-    if (! state->valid_heading)
-        return;
-
-    if (! g_ascii_strcasecmp (key, "normal"))
-        state->skin->colors[SKIN_PLEDIT_NORMAL] = convert_color_string (value);
-    else if (! g_ascii_strcasecmp (key, "current"))
-        state->skin->colors[SKIN_PLEDIT_CURRENT] = convert_color_string (value);
-    else if (! g_ascii_strcasecmp (key, "normalbg"))
-        state->skin->colors[SKIN_PLEDIT_NORMALBG] = convert_color_string (value);
-    else if (! g_ascii_strcasecmp (key, "selectedbg"))
-        state->skin->colors[SKIN_PLEDIT_SELECTEDBG] = convert_color_string (value);
-}
-
-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;
-
-    PLColorsLoadState state = {
-        .valid_heading = FALSE,
-        .skin = skin
-    };
-
-    VFSFile * file = open_local_file_nocase (path, "pledit.txt");
-
-    if (file)
-    {
-        inifile_parse (file, pl_colors_handle_heading, pl_colors_handle_entry, & state);
-        vfs_fclose (file);
-    }
-}
-
-/*
- * region.txt parsing
- */
-
-typedef struct {
-    SkinMaskId current_id;
-    GArray * numpoints[SKIN_MASK_COUNT];
-    GArray * pointlist[SKIN_MASK_COUNT];
-} MaskLoadState;
-
-static void mask_handle_heading (const char * heading, void * data)
-{
-    MaskLoadState * state = data;
-
-    if (! g_ascii_strcasecmp (heading, "normal"))
-        state->current_id = SKIN_MASK_MAIN;
-    else if (! g_ascii_strcasecmp (heading, "windowshade"))
-        state->current_id = SKIN_MASK_MAIN_SHADE;
-    else if (! g_ascii_strcasecmp (heading, "equalizer"))
-        state->current_id = SKIN_MASK_EQ;
-    else if (! g_ascii_strcasecmp (heading, "equalizerws"))
-        state->current_id = SKIN_MASK_EQ_SHADE;
-    else
-        state->current_id = -1;
-}
-
-static void mask_handle_entry (const char * key, const char * value, void * data)
-{
-    MaskLoadState * state = data;
-    SkinMaskId id = state->current_id;
-
-    if (id == -1)
-        return;
-
-    if (! g_ascii_strcasecmp (key, "numpoints"))
-    {
-        if (! state->numpoints[id])
-            state->numpoints[id] = string_to_garray (value);
-    }
-    else if (! g_ascii_strcasecmp (key, "pointlist"))
-    {
-        if (! state->pointlist[id])
-            state->pointlist[id] = string_to_garray (value);
-    }
-}
-
-static cairo_region_t * skin_create_mask (const GArray * num,
- const GArray * point, int width, int height)
-{
-    if (! num || ! point)
-    {
-        cairo_rectangle_int_t rect = {0, 0, width, height};
-        return cairo_region_create_rectangle (& rect);
-    }
-
-    cairo_region_t * mask = cairo_region_create ();
-    gboolean created_mask = FALSE;
-
-    int j = 0;
-    for (int 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;
-
-        GdkPoint gpoints[n_points];
-        for (int k = 0; k < n_points; k ++)
-        {
-            gpoints[k].x = g_array_index (point, int, j + k * 2);
-            gpoints[k].y = g_array_index (point, int, j + k * 2 + 1);
-        }
-
-        int xmin = width, ymin = height, xmax = 0, ymax = 0;
-        for (int k = 0; k < n_points; k ++)
-        {
-            xmin = MIN (xmin, gpoints[k].x);
-            ymin = MIN (ymin, gpoints[k].y);
-            xmax = MAX (xmax, gpoints[k].x);
-            ymax = MAX (ymax, gpoints[k].y);
-        }
-
-        if (xmax > xmin && ymax > ymin)
-        {
-            cairo_rectangle_int_t rect = {xmin, ymin, xmax - xmin, ymax - ymin};
-            cairo_region_union_rectangle (mask, & rect);
-        }
-
-        created_mask = TRUE;
-        j += n_points * 2;
-    }
-
-    if (! created_mask)
-    {
-        cairo_rectangle_int_t rect = {0, 0, width, height};
-        cairo_region_union_rectangle (mask, & rect);
-    }
-
-    return mask;
-}
-
-void skin_load_masks (Skin * skin, const char * path)
-{
-    int sizes[SKIN_MASK_COUNT][2] = {
-        {skin->properties.mainwin_width, skin->properties.mainwin_height},
-        {275, 16},
-        {275, 116},
-        {275, 16}
-    };
-
-    MaskLoadState state = {.current_id = -1};
-
-    VFSFile * file = open_local_file_nocase (path, "region.txt");
-
-    if (file)
-    {
-        inifile_parse (file, mask_handle_heading, mask_handle_entry, & state);
-        vfs_fclose (file);
-    }
-
-    for (SkinMaskId id = 0; id < SKIN_MASK_COUNT; id ++)
-    {
-        skin->masks[id] = skin_create_mask (state.numpoints[id],
-         state.pointlist[id], sizes[id][0], sizes[id][1]);
-
-        if (state.numpoints[id])
-            g_array_free (state.numpoints[id], TRUE);
-        if (state.pointlist[id])
-            g_array_free (state.pointlist[id], TRUE);
-    }
-}
diff --git a/src/skins/ui_skin_load_ini.cc b/src/skins/ui_skin_load_ini.cc
new file mode 100644
index 000000000000..ae49764b9316
--- /dev/null
+++ b/src/skins/ui_skin_load_ini.cc
@@ -0,0 +1,315 @@
+/*
+ * 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.c b/src/skins/ui_skinned_button.c
deleted file mode 100644
index cb423068deba..000000000000
--- a/src/skins/ui_skinned_button.c
+++ /dev/null
@@ -1,263 +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 "ui_skinned_button.h"
-
-enum {BUTTON_TYPE_NORMAL, BUTTON_TYPE_TOGGLE, BUTTON_TYPE_SMALL};
-
-typedef struct {
-    gint type;
-    gint w, h;
-    gint nx, ny, px, py;
-    gint 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 = 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 = 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 = 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 (gint type, gint w, gint 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, h);
-    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,
-     NULL);
-    g_signal_connect (button, "button-release-event", (GCallback)
-     button_release, NULL);
-    g_signal_connect (button, "destroy", (GCallback) button_destroy, NULL);
-
-    ButtonData * data = g_malloc0 (sizeof (ButtonData));
-    data->type = type;
-    data->w = w;
-    data->h = h;
-    g_object_set_data ((GObject *) button, "buttondata", data);
-
-    return button;
-}
-
-GtkWidget * button_new (gint w, gint h, gint nx, gint ny, gint px, gint py,
- SkinPixmapId si1, SkinPixmapId si2)
-{
-    GtkWidget * button = button_new_base (BUTTON_TYPE_NORMAL, w, h);
-    ButtonData * data = g_object_get_data ((GObject *) button, "buttondata");
-    g_return_val_if_fail (data, NULL);
-
-    data->nx = nx;
-    data->ny = ny;
-    data->px = px;
-    data->py = py;
-    data->si1 = si1;
-    data->si2 = si2;
-
-    return button;
-}
-
-GtkWidget * button_new_toggle (gint w, gint h, gint nx, gint ny, gint px, gint
- py, gint pnx, gint pny, gint ppx, gint ppy, SkinPixmapId si1, SkinPixmapId si2)
-{
-    GtkWidget * button = button_new_base (BUTTON_TYPE_TOGGLE, w, h);
-    ButtonData * data = g_object_get_data ((GObject *) button, "buttondata");
-    g_return_val_if_fail (data, NULL);
-
-    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 (gint w, gint h)
-{
-    return button_new_base (BUTTON_TYPE_SMALL, w, h);
-}
-
-void button_on_press (GtkWidget * button, ButtonCB callback)
-{
-    ButtonData * data = 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 = 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 = 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 = g_object_get_data ((GObject *) button, "buttondata");
-    g_return_if_fail (data);
-
-    data->on_rrelease = callback;
-}
-
-gboolean button_get_active (GtkWidget * button)
-{
-    ButtonData * data = 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 = 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.cc b/src/skins/ui_skinned_button.cc
new file mode 100644
index 000000000000..93f33cfdce62
--- /dev/null
+++ b/src/skins/ui_skinned_button.cc
@@ -0,0 +1,264 @@
+/*
+ * 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
index 8b992a5e68a1..47c0093e2449 100644
--- a/src/skins/ui_skinned_button.h
+++ b/src/skins/ui_skinned_button.h
@@ -28,12 +28,12 @@
 
 typedef void (* ButtonCB) (GtkWidget * button, GdkEventButton * event);
 
-GtkWidget * button_new (gint w, gint h, gint nx, gint ny, gint px,
- gint py, SkinPixmapId si1, SkinPixmapId si2);
-GtkWidget * button_new_toggle (gint w, gint h, gint nx, gint ny,
- gint px, gint py, gint pnx, gint pny, gint ppx, gint ppy, SkinPixmapId si1,
+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 (gint w, gint h);
+GtkWidget * button_new_small (int w, int h);
 
 void button_on_press (GtkWidget * button, ButtonCB callback);
 void button_on_release (GtkWidget * button, ButtonCB callback);
diff --git a/src/skins/ui_skinned_equalizer_graph.c b/src/skins/ui_skinned_equalizer_graph.c
deleted file mode 100644
index 3b338ad5608e..000000000000
--- a/src/skins/ui_skinned_equalizer_graph.c
+++ /dev/null
@@ -1,143 +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 <audacious/misc.h>
-
-#include "draw-compat.h"
-#include "ui_skin.h"
-#include "ui_skinned_equalizer_graph.h"
-
-static void init_spline (const gdouble * x, const gdouble * y, gint n, gdouble * y2)
-{
-    gint i, k;
-    gdouble p, qn, sig, un, *u;
-
-    u = (gdouble *) g_malloc(n * sizeof(gdouble));
-
-    y2[0] = u[0] = 0.0;
-
-    for (i = 1; i < n - 1; i++) {
-        sig = ((gdouble) x[i] - x[i - 1]) / ((gdouble) x[i + 1] - x[i - 1]);
-        p = sig * y2[i - 1] + 2.0;
-        y2[i] = (sig - 1.0) / p;
-        u[i] =
-            (((gdouble) y[i + 1] - y[i]) / (x[i + 1] - x[i])) -
-            (((gdouble) 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];
-    g_free(u);
-}
-
-gdouble eval_spline (const gdouble * xa, const gdouble * ya, const gdouble * y2a,
- gint n, gdouble x)
-{
-    gint klo, khi, k;
-    gdouble 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);
-}
-
-DRAW_FUNC_BEGIN (eq_graph_draw)
-    static const gdouble x[10] = {0, 11, 23, 35, 47, 59, 71, 83, 97, 109};
-
-    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 (NULL,
-     "equalizer_preamp") * 9 + EQUALIZER_MAX_GAIN / 2) / EQUALIZER_MAX_GAIN, 113, 1);
-
-    guint32 cols[19];
-    skin_get_eq_spline_colors(active_skin, cols);
-
-    gdouble bands[AUD_EQUALIZER_NBANDS];
-    aud_eq_get_bands (bands);
-
-    gdouble yf[10];
-    init_spline (x, bands, 10, yf);
-
-    /* now draw a pixelated line with vector graphics ... -- jlindgren */
-    gint py = 0;
-    for (gint i = 0; i < 109; i ++)
-    {
-        gint y = 9.5 - eval_spline (x, bands, yf, 10, i) * 9 / EQUALIZER_MAX_GAIN;
-        y = CLAMP (y, 0, 18);
-
-        if (!i)
-            py = y;
-
-        gint 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++)
-        {
-            cairo_rectangle (cr, i + 2, y, 1, 1);
-            set_cairo_color (cr, cols[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, 19);
-    DRAW_CONNECT (graph, eq_graph_draw);
-    return graph;
-}
-
-void eq_graph_update (GtkWidget * graph)
-{
-    gtk_widget_queue_draw (graph);
-}
diff --git a/src/skins/ui_skinned_equalizer_graph.cc b/src/skins/ui_skinned_equalizer_graph.cc
new file mode 100644
index 000000000000..42b22d2bf67b
--- /dev/null
+++ b/src/skins/ui_skinned_equalizer_graph.cc
@@ -0,0 +1,147 @@
+/*
+ * 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 "draw-compat.h"
+#include "skins_cfg.h"
+#include "ui_skin.h"
+#include "ui_skinned_equalizer_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;
+
+    u = (double *) g_malloc(n * sizeof(double));
+
+    y2[0] = u[0] = 0.0;
+
+    for (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];
+    g_free(u);
+}
+
+double eval_spline (const double * xa, const double * ya, const double * y2a,
+ int n, 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);
+}
+
+DRAW_FUNC_BEGIN (eq_graph_draw)
+    static const double x[10] = {0, 11, 23, 35, 47, 59, 71, 83, 97, 109};
+
+    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];
+    aud_eq_get_bands (bands);
+
+    double yf[10];
+    init_spline (x, bands, 10, 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;
+        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++)
+        {
+            cairo_rectangle (cr, i + 2, y, 1, 1);
+            set_cairo_color (cr, cols[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)
+{
+    gtk_widget_queue_draw (graph);
+}
diff --git a/src/skins/ui_skinned_equalizer_slider.c b/src/skins/ui_skinned_equalizer_slider.c
deleted file mode 100644
index 82ebcbd90c1b..000000000000
--- a/src/skins/ui_skinned_equalizer_slider.c
+++ /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 <audacious/i18n.h>
-#include <audacious/types.h>
-
-#include "draw-compat.h"
-#include "ui_equalizer.h"
-#include "ui_main.h"
-#include "ui_skin.h"
-#include "ui_skinned_equalizer_slider.h"
-
-typedef struct {
-    gchar * name;
-    gint pos;
-    gfloat val;
-    gboolean pressed;
-} EqSliderData;
-
-DRAW_FUNC_BEGIN (eq_slider_draw)
-    EqSliderData * data = g_object_get_data ((GObject *) wid, "eqsliderdata");
-    g_return_val_if_fail (data, FALSE);
-
-    gint 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, gint pos)
-{
-    data->pos = CLAMP (pos, 0, 50);
-    if (data->pos == 24 || data->pos == 26)
-        data->pos = 25;
-
-    data->val = (gfloat) (25 - data->pos) * EQUALIZER_MAX_GAIN / 25;
-
-    equalizerwin_eq_changed ();
-
-    gchar 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 = 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 - 5);
-    gtk_widget_queue_draw (slider);
-    return TRUE;
-}
-
-static gboolean eq_slider_button_release (GtkWidget * slider, GdkEventButton *
- event)
-{
-    EqSliderData * data = 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 - 5);
-    gtk_widget_queue_draw (slider);
-    return TRUE;
-}
-
-static gboolean eq_slider_motion (GtkWidget * slider, GdkEventMotion * event)
-{
-    EqSliderData * data = 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 - 5);
-    gtk_widget_queue_draw (slider);
-    return TRUE;
-}
-
-static gboolean eq_slider_scroll (GtkWidget * slider, GdkEventScroll * event)
-{
-    EqSliderData * data = 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, gfloat val)
-{
-    EqSliderData * data = g_object_get_data ((GObject *) slider, "eqsliderdata");
-    g_return_if_fail (data);
-
-    if (data->pressed)
-        return;
-
-    data->val = val;
-    data->pos = 25 - (gint) (val * 25 / EQUALIZER_MAX_GAIN);
-    data->pos = CLAMP (data->pos, 0, 50);
-
-    gtk_widget_queue_draw (slider);
-}
-
-gfloat eq_slider_get_val (GtkWidget * slider)
-{
-    EqSliderData * data = 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 = g_object_get_data ((GObject *) slider, "eqsliderdata");
-    g_return_if_fail (data);
-
-    g_free (data->name);
-    g_free (data);
-}
-
-GtkWidget * eq_slider_new (const gchar * name)
-{
-    GtkWidget * slider = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (slider, 14, 63);
-    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, NULL);
-    g_signal_connect (slider, "button-release-event", (GCallback)
-     eq_slider_button_release, NULL);
-    g_signal_connect (slider, "motion-notify-event", (GCallback)
-     eq_slider_motion, NULL);
-    g_signal_connect (slider, "scroll-event", (GCallback) eq_slider_scroll,
-     NULL);
-    g_signal_connect (slider, "destroy", (GCallback) eq_slider_destroy, NULL);
-
-    EqSliderData * data = g_malloc0 (sizeof (EqSliderData));
-    data->name = g_strdup (name);
-    g_object_set_data ((GObject *) slider, "eqsliderdata", data);
-
-    return slider;
-}
diff --git a/src/skins/ui_skinned_equalizer_slider.cc b/src/skins/ui_skinned_equalizer_slider.cc
new file mode 100644
index 000000000000..69fffab0b2d0
--- /dev/null
+++ b/src/skins/ui_skinned_equalizer_slider.cc
@@ -0,0 +1,191 @@
+/*
+ * 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_equalizer_slider.h b/src/skins/ui_skinned_equalizer_slider.h
index 0a1207186c29..bca392a50a44 100644
--- a/src/skins/ui_skinned_equalizer_slider.h
+++ b/src/skins/ui_skinned_equalizer_slider.h
@@ -27,8 +27,8 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * eq_slider_new (const gchar * name);
-void eq_slider_set_val (GtkWidget * widget, gfloat val);
-gfloat eq_slider_get_val (GtkWidget * widget);
+GtkWidget * eq_slider_new (const char * name);
+void eq_slider_set_val (GtkWidget * widget, float val);
+float eq_slider_get_val (GtkWidget * widget);
 
 #endif
diff --git a/src/skins/ui_skinned_horizontal_slider.c b/src/skins/ui_skinned_horizontal_slider.c
deleted file mode 100644
index d806f15cf6e1..000000000000
--- a/src/skins/ui_skinned_horizontal_slider.c
+++ /dev/null
@@ -1,238 +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 "ui_skin.h"
-#include "ui_skinned_horizontal_slider.h"
-
-typedef struct {
-    gint min, max, pos;
-    gboolean pressed;
-    SkinPixmapId si;
-    gint w, h;
-    gint fx, fy;
-    gint kw, kh;
-    gint knx, kny, kpx, kpy;
-    void (* on_motion) (void);
-    void (* on_release) (void);
-} HSliderData;
-
-DRAW_FUNC_BEGIN (hslider_draw)
-    HSliderData * data = 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 = 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 - data->kw / 2;
-    data->pos = 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 = 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 - data->kw / 2;
-    data->pos = 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 = 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 - data->kw / 2;
-    data->pos = 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 (gint min, gint max, SkinPixmapId si, gint w, gint h,
- gint fx, gint fy, gint kw, gint kh, gint knx, gint kny, gint kpx, gint kpy)
-{
-    GtkWidget * hslider = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (hslider, w, h);
-    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, NULL);
-    g_signal_connect (hslider, "button-release-event", (GCallback)
-     hslider_button_release, NULL);
-    g_signal_connect (hslider, "motion-notify-event", (GCallback)
-     hslider_motion_notify, NULL);
-    g_signal_connect (hslider, "destroy", (GCallback) hslider_destroy, NULL);
-
-    HSliderData * data = g_malloc0 (sizeof (HSliderData));
-    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, gint fx, gint fy)
-{
-    HSliderData * data = 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, gint knx, gint kny, gint kpx, gint
- kpy)
-{
-    HSliderData * data = 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);
-}
-
-gint hslider_get_pos (GtkWidget * hslider)
-{
-    HSliderData * data = g_object_get_data ((GObject *) hslider, "hsliderdata");
-    g_return_val_if_fail (data, 0);
-
-    return data->pos;
-}
-
-void hslider_set_pos (GtkWidget * hslider, gint pos)
-{
-    HSliderData * data = g_object_get_data ((GObject *) hslider, "hsliderdata");
-    g_return_if_fail (data);
-
-    if (data->pressed)
-        return;
-
-    data->pos = CLAMP (pos, data->min, data->max);
-    gtk_widget_queue_draw (hslider);
-}
-
-gboolean hslider_get_pressed (GtkWidget * hslider)
-{
-    HSliderData * data = 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 = 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 = 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 = g_object_get_data ((GObject *) hslider, "hsliderdata");
-    g_return_if_fail (data);
-
-    data->on_release = callback;
-}
diff --git a/src/skins/ui_skinned_horizontal_slider.cc b/src/skins/ui_skinned_horizontal_slider.cc
new file mode 100644
index 000000000000..8e523048dd8c
--- /dev/null
+++ b/src/skins/ui_skinned_horizontal_slider.cc
@@ -0,0 +1,241 @@
+/*
+ * 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_horizontal_slider.h b/src/skins/ui_skinned_horizontal_slider.h
index 9be02363b44f..866885610f75 100644
--- a/src/skins/ui_skinned_horizontal_slider.h
+++ b/src/skins/ui_skinned_horizontal_slider.h
@@ -30,13 +30,13 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * hslider_new (gint min, gint max, SkinPixmapId si, gint w, gint h,
- gint fx, gint fy, gint kw, gint kh, gint knx, gint kny, gint kpx, gint kpy);
-void hslider_set_frame (GtkWidget * hslider, gint fx, gint fy);
-void hslider_set_knob (GtkWidget * hslider, gint knx, gint kny, gint kpx, gint
+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);
-gint hslider_get_pos (GtkWidget * hslider);
-void hslider_set_pos (GtkWidget * hslider, gint pos);
+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));
diff --git a/src/skins/ui_skinned_menurow.c b/src/skins/ui_skinned_menurow.c
deleted file mode 100644
index a3e9f1504510..000000000000
--- a/src/skins/ui_skinned_menurow.c
+++ /dev/null
@@ -1,149 +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 <audacious/misc.h>
-
-#include "draw-compat.h"
-#include "skins_cfg.h"
-#include "ui_skin.h"
-#include "ui_skinned_menurow.h"
-
-static struct {
-    MenuRowItem selected;
-    gboolean pushed;
-} mr;
-
-DRAW_FUNC_BEGIN (menurow_draw)
-    if (mr.selected == MENUROW_NONE)
-    {
-        if (mr.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);
-
-    if (mr.pushed)
-    {
-        if (aud_get_bool ("skins", "always_on_top"))
-            skin_draw_pixbuf (cr, SKIN_TITLEBAR, 312, 54, 0, 10, 8, 8);
-#if 0
-        if (config.scaled)
-            skin_draw_pixbuf (cr, SKIN_TITLEBAR, 328, 70, 0, 26, 8, 8);
-#endif
-    }
-DRAW_FUNC_END
-
-static MenuRowItem menurow_find_selected (gint x, gint 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;
-}
-
-static gboolean menurow_button_press (GtkWidget * widget, GdkEventButton * event)
-{
-    if (event->button != 1)
-        return FALSE;
-
-    mr.pushed = TRUE;
-    mr.selected = menurow_find_selected (event->x, event->y);
-
-    mainwin_mr_change (mr.selected);
-
-    gtk_widget_queue_draw (widget);
-    return TRUE;
-}
-
-static gboolean menurow_button_release (GtkWidget * widget, GdkEventButton *
- event)
-{
-    if (event->button != 1)
-        return FALSE;
-
-    if (! mr.pushed)
-        return TRUE;
-
-    mainwin_mr_release (mr.selected, event);
-
-    mr.pushed = FALSE;
-    mr.selected = MENUROW_NONE;
-
-    gtk_widget_queue_draw (widget);
-    return TRUE;
-}
-
-static gboolean menurow_motion_notify (GtkWidget * widget, GdkEventMotion *
- event)
-{
-    if (! mr.pushed)
-        return TRUE;
-
-    mr.selected = menurow_find_selected (event->x, event->y);
-
-    mainwin_mr_change (mr.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, 43);
-    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, NULL);
-    g_signal_connect (wid, "button-release-event", (GCallback)
-     menurow_button_release, NULL);
-    g_signal_connect (wid, "motion-notify-event", (GCallback)
-     menurow_motion_notify, NULL);
-
-    return wid;
-}
-
-void ui_skinned_menurow_update (GtkWidget * menurow)
-{
-    gtk_widget_queue_draw (menurow);
-}
diff --git a/src/skins/ui_skinned_menurow.cc b/src/skins/ui_skinned_menurow.cc
new file mode 100644
index 000000000000..ebd722d08507
--- /dev/null
+++ b/src/skins/ui_skinned_menurow.cc
@@ -0,0 +1,147 @@
+/*
+ * 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 "draw-compat.h"
+#include "skins_cfg.h"
+#include "ui_skin.h"
+#include "ui_skinned_menurow.h"
+
+static struct {
+    MenuRowItem selected;
+    gboolean pushed;
+} mr;
+
+DRAW_FUNC_BEGIN (menurow_draw)
+    if (mr.selected == MENUROW_NONE)
+    {
+        if (mr.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);
+
+    if (mr.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)
+{
+    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;
+}
+
+static gboolean menurow_button_press (GtkWidget * widget, GdkEventButton * event)
+{
+    if (event->button != 1)
+        return FALSE;
+
+    mr.pushed = TRUE;
+    mr.selected = menurow_find_selected (event->x / config.scale, event->y / config.scale);
+
+    mainwin_mr_change (mr.selected);
+
+    gtk_widget_queue_draw (widget);
+    return TRUE;
+}
+
+static gboolean menurow_button_release (GtkWidget * widget, GdkEventButton *
+ event)
+{
+    if (event->button != 1)
+        return FALSE;
+
+    if (! mr.pushed)
+        return TRUE;
+
+    mainwin_mr_release (mr.selected, event);
+
+    mr.pushed = FALSE;
+    mr.selected = MENUROW_NONE;
+
+    gtk_widget_queue_draw (widget);
+    return TRUE;
+}
+
+static gboolean menurow_motion_notify (GtkWidget * widget, GdkEventMotion *
+ event)
+{
+    if (! mr.pushed)
+        return TRUE;
+
+    mr.selected = menurow_find_selected (event->x / config.scale, event->y / config.scale);
+
+    mainwin_mr_change (mr.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;
+}
+
+void ui_skinned_menurow_update (GtkWidget * menurow)
+{
+    gtk_widget_queue_draw (menurow);
+}
diff --git a/src/skins/ui_skinned_monostereo.c b/src/skins/ui_skinned_monostereo.c
deleted file mode 100644
index 9410358b2233..000000000000
--- a/src/skins/ui_skinned_monostereo.c
+++ /dev/null
@@ -1,65 +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 "ui_skin.h"
-#include "ui_skinned_monostereo.h"
-
-static gint monostereo_num_channels;
-
-DRAW_FUNC_BEGIN (monostereo_draw)
-    switch (monostereo_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);
-        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;
-    }
-DRAW_FUNC_END
-
-GtkWidget * ui_skinned_monostereo_new (void)
-{
-    GtkWidget * monostereo = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (monostereo, 56, 12);
-    DRAW_CONNECT (monostereo, monostereo_draw);
-    return monostereo;
-}
-
-void ui_skinned_monostereo_set_num_channels (GtkWidget * monostereo, gint nch)
-{
-    monostereo_num_channels = nch;
-    gtk_widget_queue_draw (monostereo);
-}
diff --git a/src/skins/ui_skinned_monostereo.cc b/src/skins/ui_skinned_monostereo.cc
new file mode 100644
index 000000000000..60d5397792ac
--- /dev/null
+++ b/src/skins/ui_skinned_monostereo.cc
@@ -0,0 +1,66 @@
+/*
+ * 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_monostereo.h"
+
+static int monostereo_num_channels;
+
+DRAW_FUNC_BEGIN (monostereo_draw)
+    switch (monostereo_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);
+        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;
+    }
+DRAW_FUNC_END
+
+GtkWidget * ui_skinned_monostereo_new (void)
+{
+    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;
+}
+
+void ui_skinned_monostereo_set_num_channels (GtkWidget * monostereo, int nch)
+{
+    monostereo_num_channels = nch;
+    gtk_widget_queue_draw (monostereo);
+}
diff --git a/src/skins/ui_skinned_monostereo.h b/src/skins/ui_skinned_monostereo.h
index 5867126426db..4cb41536fc69 100644
--- a/src/skins/ui_skinned_monostereo.h
+++ b/src/skins/ui_skinned_monostereo.h
@@ -31,6 +31,6 @@
 #include <gtk/gtk.h>
 
 GtkWidget * ui_skinned_monostereo_new (void);
-void ui_skinned_monostereo_set_num_channels(GtkWidget *widget, gint nch);
+void ui_skinned_monostereo_set_num_channels(GtkWidget *widget, int nch);
 
 #endif
diff --git a/src/skins/ui_skinned_number.c b/src/skins/ui_skinned_number.c
deleted file mode 100644
index 10157f2b4dc5..000000000000
--- a/src/skins/ui_skinned_number.c
+++ /dev/null
@@ -1,92 +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 "ui_skin.h"
-#include "ui_skinned_number.h"
-
-typedef struct {
-    gint w, h;
-    gint num;
-} NumberData;
-
-DRAW_FUNC_BEGIN (number_draw)
-    NumberData * data = 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, 13);
-
-    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, NULL);
-
-    NumberData * data = g_malloc0 (sizeof (NumberData));
-    data->w = 9;
-    data->h = 13;
-    g_object_set_data ((GObject *) number, "numberdata", data);
-
-    return number;
-}
-
-void ui_skinned_number_set (GtkWidget * number, gchar c)
-{
-    NumberData * data = g_object_get_data ((GObject *) number, "numberdata");
-    g_return_if_fail (data);
-
-    gint 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, gint width, gint height)
-{
-    NumberData * data = 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, height);
-    gtk_widget_queue_draw (number);
-}
diff --git a/src/skins/ui_skinned_number.cc b/src/skins/ui_skinned_number.cc
new file mode 100644
index 000000000000..53977ccdb399
--- /dev/null
+++ b/src/skins/ui_skinned_number.cc
@@ -0,0 +1,93 @@
+/*
+ * 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_number.h b/src/skins/ui_skinned_number.h
index 4c82630cb410..3ddde4a3e1cc 100644
--- a/src/skins/ui_skinned_number.h
+++ b/src/skins/ui_skinned_number.h
@@ -25,7 +25,7 @@
 #include <gtk/gtk.h>
 
 GtkWidget * ui_skinned_number_new ();
-void ui_skinned_number_set (GtkWidget * widget, gchar c);
-void ui_skinned_number_set_size(GtkWidget *widget, gint width, gint height);
+void ui_skinned_number_set (GtkWidget * widget, char c);
+void ui_skinned_number_set_size(GtkWidget *widget, int width, int height);
 
 #endif
diff --git a/src/skins/ui_skinned_playlist.c b/src/skins/ui_skinned_playlist.c
deleted file mode 100644
index 99fa24b65c3f..000000000000
--- a/src/skins/ui_skinned_playlist.c
+++ /dev/null
@@ -1,948 +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 <audacious/drct.h>
-#include <audacious/misc.h>
-#include <audacious/playlist.h>
-#include <libaudgui/libaudgui.h>
-
-enum {DRAG_SELECT = 1, DRAG_MOVE};
-
-typedef struct {
-    GtkWidget * slider;
-    PangoFontDescription * font;
-    gint width, height, row_height, offset, rows, first, scroll, scroll_source,
-     hover, drag;
-    gint 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, gint 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 gint calc_position (PlaylistData * data, gint y)
-{
-    if (y < data->offset)
-        return -1;
-
-    gint position = data->first + (y - data->offset) / data->row_height;
-
-    if (position >= data->first + data->rows || position >= active_length)
-        return active_length;
-
-    return position;
-}
-
-static gint adjust_position (PlaylistData * data, gboolean relative, gint
- position)
-{
-    if (active_length == 0)
-        return -1;
-
-    if (relative)
-    {
-        gint 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 = g_object_get_data ((GObject *) wid, "playlistdata");
-    g_return_val_if_fail (data, FALSE);
-
-    gint active_entry = aud_playlist_get_position (active_playlist);
-    gint left = 3, right = 3;
-    PangoLayout * layout;
-    gint 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 (gint 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 (NULL, "show_numbers_in_pl"))
-    {
-        width = 0;
-
-        for (gint i = data->first; i < data->first + data->rows && i <
-         active_length; i ++)
-        {
-            gchar 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, NULL, & rect);
-            width = 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 (gint i = data->first; i < data->first + data->rows && i <
-     active_length; i ++)
-    {
-        int len = aud_playlist_entry_get_length (active_playlist, i, TRUE);
-        if (len <= 0)
-            continue;
-
-        char buf[16];
-        audgui_format_time (buf, sizeof buf, len);
-
-        layout = gtk_widget_create_pango_layout (wid, buf);
-        pango_layout_set_font_description (layout, data->font);
-
-        PangoRectangle rect;
-        pango_layout_get_pixel_extents (layout, NULL, & rect);
-        width = 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 (gint i = data->first; i < data->first + data->rows && i <
-         active_length; i ++)
-        {
-            gint pos = aud_playlist_queue_find_entry (active_playlist, i);
-            if (pos < 0)
-                continue;
-
-            gchar 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, NULL, & rect);
-            width = 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 (gint i = data->first; i < data->first + data->rows && i <
-     active_length; i ++)
-    {
-        gchar * title = aud_playlist_entry_get_title (active_playlist, i, TRUE);
-
-        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);
-
-        str_unref (title);
-
-        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 */
-
-    gint 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 = 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 (gint width, gint height, const gchar * font)
-{
-    GtkWidget * list = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (list, width, height);
-    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, NULL);
-    g_signal_connect (list, "button-release-event", (GCallback)
-     playlist_button_release, NULL);
-    g_signal_connect (list, "leave-notify-event", (GCallback) playlist_leave,
-     NULL);
-    g_signal_connect (list, "motion-notify-event", (GCallback) playlist_motion,
-     NULL);
-    g_signal_connect (list, "destroy", (GCallback) playlist_destroy, NULL);
-
-    PlaylistData * data = g_malloc0 (sizeof (PlaylistData));
-    data->width = width;
-    data->height = height;
-    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 = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_if_fail (data);
-
-    data->slider = slider;
-}
-
-void ui_skinned_playlist_resize (GtkWidget * list, gint width, gint height)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_if_fail (data);
-
-    gtk_widget_set_size_request (list, width, height);
-
-    data->width = width;
-    data->height = height;
-
-    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 gchar * font)
-{
-    PlaylistData * data = 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, NULL, & rect);
-
-    /* make sure row_height is non-zero; we divide by it */
-    data->row_height = 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 = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_if_fail (data);
-
-    calc_layout (data);
-
-    gtk_widget_queue_draw (list);
-
-    if (data->slider != NULL)
-        ui_skinned_playlist_slider_update (data->slider);
-}
-
-static void scroll_to (PlaylistData * data, gint 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, gint 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, gint position)
-{
-    position = adjust_position (data, relative, position);
-
-    if (position == -1)
-        return;
-
-    gint count = adjust_position (data, TRUE, 0);
-    gint 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, gint 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, gint 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, gint position)
-{
-    gint 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);
-    gint 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 = 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_drct_play_playlist (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, gint * rows, gint * first)
-{
-    PlaylistData * data = 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, gint row)
-{
-    PlaylistData * data = 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, gint row)
-{
-    PlaylistData * data = 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, gint x, gint y)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_if_fail (data);
-
-    gint new;
-
-    if (y < data->offset)
-        new = data->first;
-    else if (y > data->offset + data->row_height * data->rows)
-        new = data->first + data->rows;
-    else
-        new = data->first + (y - data->offset + data->row_height / 2) /
-         data->row_height;
-
-    if (new > active_length)
-        new = active_length;
-
-    if (new != data->hover)
-    {
-        data->hover = new;
-        gtk_widget_queue_draw (list);
-    }
-}
-
-gint ui_skinned_playlist_hover_end (GtkWidget * list)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_val_if_fail (data, -1);
-
-    gint temp = data->hover;
-    data->hover = -1;
-
-    gtk_widget_queue_draw (list);
-    return temp;
-}
-
-static gboolean playlist_button_press (GtkWidget * list, GdkEventButton * event)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_val_if_fail (data, FALSE);
-
-    gint position = calc_position (data, event->y);
-    gint 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_drct_play_playlist (active_playlist);
-        break;
-      default:
-        return TRUE;
-    }
-
-    playlistwin_update ();
-    return TRUE;
-}
-
-static gboolean playlist_button_release (GtkWidget * list, GdkEventButton *
- event)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_val_if_fail (data, FALSE);
-
-    cancel_all (list, data);
-    return TRUE;
-}
-
-static gboolean scroll_cb (PlaylistData * data)
-{
-    gint position = adjust_position (data, TRUE, data->scroll);
-
-    if (position == -1)
-        return TRUE;
-
-    switch (data->drag)
-    {
-      case DRAG_SELECT:
-        select_extend (data, FALSE, position);
-        break;
-      case DRAG_MOVE:
-        select_move (data, FALSE, position);
-        break;
-    }
-
-    playlistwin_update ();
-    return TRUE;
-}
-
-static gboolean playlist_motion (GtkWidget * list, GdkEventMotion * event)
-{
-    PlaylistData * data = g_object_get_data ((GObject *) list, "playlistdata");
-    g_return_val_if_fail (data, FALSE);
-
-    gint position = calc_position (data, event->y);
-    gint 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, (GSourceFunc)
-                 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 (NULL, "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 = 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 (GtkWidget * list)
-{
-    PlaylistData * data = 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 FALSE;
-}
-
-static void popup_trigger (GtkWidget * list, PlaylistData * data, gint pos)
-{
-    popup_hide (list, data);
-
-    data->popup_pos = pos;
-    data->popup_source = g_timeout_add (aud_get_int (NULL, "filepopup_delay") *
-     100, (GSourceFunc) 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.cc b/src/skins/ui_skinned_playlist.cc
new file mode 100644
index 000000000000..3408356d3109
--- /dev/null
+++ b/src/skins/ui_skinned_playlist.cc
@@ -0,0 +1,945 @@
+/*
+ * 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
index bf1003669c74..ec919178e09e 100644
--- a/src/skins/ui_skinned_playlist.h
+++ b/src/skins/ui_skinned_playlist.h
@@ -30,16 +30,16 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * ui_skinned_playlist_new (gint width, gint height, const gchar * font);
+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, gint w, gint h);
-void ui_skinned_playlist_set_font (GtkWidget * list, const gchar * font);
+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, gint * rows, gint * first);
-void ui_skinned_playlist_scroll_to (GtkWidget * list, gint row);
-void ui_skinned_playlist_set_focused (GtkWidget * list, gint row);
-void ui_skinned_playlist_hover (GtkWidget * list, gint x, gint y);
-gint ui_skinned_playlist_hover_end (GtkWidget * list);
+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.c b/src/skins/ui_skinned_playlist_slider.c
deleted file mode 100644
index 0b4034c2ed5f..000000000000
--- a/src/skins/ui_skinned_playlist_slider.c
+++ /dev/null
@@ -1,141 +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 "ui_playlist.h"
-#include "ui_skin.h"
-#include "ui_skinned_playlist.h"
-#include "ui_skinned_playlist_slider.h"
-
-static GtkWidget * pl_slider_list;
-static gint pl_slider_height;
-static gboolean pl_slider_pressed;
-
-DRAW_FUNC_BEGIN (pl_slider_draw)
-    gint rows, first;
-    ui_skinned_playlist_row_info (pl_slider_list, & rows, & first);
-
-    gint range = active_length - rows;
-
-    gint y;
-    if (active_length > rows)
-        y = (first * (pl_slider_height - 19) + range / 2) / range;
-    else
-        y = 0;
-
-    for (gint 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 (gint y)
-{
-    y = CLAMP (y, 0, pl_slider_height - 19);
-
-    gint rows, first;
-    ui_skinned_playlist_row_info (pl_slider_list, & rows, & first);
-
-    gint 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 - 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 - 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 - 9);
-
-    gtk_widget_queue_draw (slider);
-    return TRUE;
-}
-
-GtkWidget * ui_skinned_playlist_slider_new (GtkWidget * list, gint height)
-{
-    GtkWidget * slider = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (slider, 8, height);
-    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, NULL);
-    g_signal_connect (slider, "button-release-event", (GCallback)
-     pl_slider_button_release, NULL);
-    g_signal_connect (slider, "motion-notify-event", (GCallback)
-     pl_slider_motion, NULL);
-
-    return slider;
-}
-
-void ui_skinned_playlist_slider_resize (GtkWidget * slider, gint height)
-{
-    pl_slider_height = height;
-    gtk_widget_set_size_request (slider, 8, height);
-    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_playlist_slider.cc b/src/skins/ui_skinned_playlist_slider.cc
new file mode 100644
index 000000000000..19a3cb879458
--- /dev/null
+++ b/src/skins/ui_skinned_playlist_slider.cc
@@ -0,0 +1,144 @@
+/*
+ * 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_playlist_slider.h b/src/skins/ui_skinned_playlist_slider.h
index 2bdb374f2511..8d28d3e7a5dc 100644
--- a/src/skins/ui_skinned_playlist_slider.h
+++ b/src/skins/ui_skinned_playlist_slider.h
@@ -30,8 +30,8 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * ui_skinned_playlist_slider_new (GtkWidget * list, gint height);
-void ui_skinned_playlist_slider_resize (GtkWidget * slider, gint height);
+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);
 
 #endif
diff --git a/src/skins/ui_skinned_playstatus.c b/src/skins/ui_skinned_playstatus.c
deleted file mode 100644
index 44d6f57e05c4..000000000000
--- a/src/skins/ui_skinned_playstatus.c
+++ /dev/null
@@ -1,81 +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 "ui_skin.h"
-#include "ui_skinned_playstatus.h"
-
-static gint 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, gint width, gint
- height)
-{
-    playstatus_width = width;
-    playstatus_height = height;
-
-    gtk_widget_set_size_request (playstatus, width, height);
-    gtk_widget_queue_draw (playstatus);
-}
diff --git a/src/skins/ui_skinned_playstatus.cc b/src/skins/ui_skinned_playstatus.cc
new file mode 100644
index 000000000000..f4f51e39beb5
--- /dev/null
+++ b/src/skins/ui_skinned_playstatus.cc
@@ -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.
+ */
+
+#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_playstatus.h b/src/skins/ui_skinned_playstatus.h
index efbddd6e566b..ffa8c4631887 100644
--- a/src/skins/ui_skinned_playstatus.h
+++ b/src/skins/ui_skinned_playstatus.h
@@ -36,6 +36,6 @@ typedef enum {
 
 GtkWidget * ui_skinned_playstatus_new (void);
 void ui_skinned_playstatus_set_status(GtkWidget *widget, PStatus status);
-void ui_skinned_playstatus_set_size(GtkWidget *widget, gint width, gint height);
+void ui_skinned_playstatus_set_size(GtkWidget *widget, int width, int height);
 
 #endif
diff --git a/src/skins/ui_skinned_textbox.c b/src/skins/ui_skinned_textbox.c
deleted file mode 100644
index 54e8d94804df..000000000000
--- a/src/skins/ui_skinned_textbox.c
+++ /dev/null
@@ -1,405 +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 "draw-compat.h"
-#include "skins_cfg.h"
-#include "ui_skin.h"
-#include "ui_skinned_textbox.h"
-
-#define TIMEOUT 30
-#define DELAY 50
-
-typedef struct {
-    gint width;
-    gchar * text;
-    PangoFontDescription * font;
-    cairo_surface_t * buf;
-    gint buf_width;
-    gboolean may_scroll, scrolling, backward;
-    gint scroll_source;
-    gint offset, delay;
-} TextboxData;
-
-static GList * textboxes;
-
-DRAW_FUNC_BEGIN (textbox_draw)
-    TextboxData * data = 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, 0);
-        cairo_paint (cr);
-
-        if (-data->offset + data->buf_width < data->width)
-        {
-            cairo_set_source_surface (cr, data->buf, -data->offset +
-             data->buf_width, 0);
-            cairo_paint (cr);
-        }
-    }
-    else
-    {
-        cairo_set_source_surface (cr, data->buf, 0, 0);
-        cairo_paint (cr);
-    }
-DRAW_FUNC_END
-
-static gboolean textbox_scroll (GtkWidget * textbox)
-{
-    TextboxData * data = g_object_get_data ((GObject *) textbox, "textboxdata");
-    g_return_val_if_fail (data, FALSE);
-
-    if (data->delay < DELAY)
-    {
-        data->delay ++;
-        return TRUE;
-    }
-
-    if (config.twoway_scroll && data->backward)
-        data->offset --;
-    else
-        data->offset ++;
-
-    if (config.twoway_scroll && (data->backward ? (data->offset <= 0) :
-     (data->offset + data->width >= data->buf_width)))
-    {
-        data->backward = ! data->backward;
-        data->delay = 0;
-    }
-
-    if (! config.twoway_scroll && data->offset >= data->buf_width)
-        data->offset = 0;
-
-    gtk_widget_queue_draw (textbox);
-    return TRUE;
-}
-
-static void textbox_render_vector (GtkWidget * textbox, TextboxData * data,
- const gchar * 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 rect;
-    pango_layout_get_pixel_extents (layout, & rect, NULL);
-
-    gtk_widget_set_size_request (textbox, data->width, rect.height);
-
-    data->buf_width = MAX (rect.width, data->width);
-    data->buf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-     data->buf_width, rect.height);
-
-    cairo_t * cr = cairo_create (data->buf);
-
-    set_cairo_color (cr, active_skin->colors[SKIN_TEXTBG]);
-    cairo_paint (cr);
-
-    cairo_move_to (cr, -rect.x, -rect.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 gchar c, gint * x, gint * y)
-{
-    gint 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 gchar * text)
-{
-    g_return_if_fail (! data->font && ! data->buf && text);
-
-    gint cw = active_skin->properties.textbox_bitmap_font_width;
-    gint ch = active_skin->properties.textbox_bitmap_font_height;
-
-    gtk_widget_set_size_request (textbox, data->width, ch);
-
-    glong len;
-    gunichar * utf32 = g_utf8_to_ucs4 (text, -1, NULL, & len, NULL);
-    g_return_if_fail (utf32);
-
-    data->buf_width = MAX (cw * len, data->width);
-    data->buf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-     data->buf_width, ch);
-
-    cairo_t * cr = cairo_create (data->buf);
-
-    gunichar * s = utf32;
-    for (gint x = 0; x < data->buf_width; x += cw)
-    {
-        gunichar c = * s ? * s ++ : ' ';
-        gint 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 = NULL;
-    }
-
-    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 (! config.twoway_scroll)
-        {
-            if (data->buf)
-            {
-                cairo_surface_destroy (data->buf);
-                data->buf = NULL;
-            }
-
-            gchar * 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, (GSourceFunc)
-             textbox_scroll, textbox);
-    }
-    else
-    {
-        if (data->scroll_source)
-        {
-            g_source_remove (data->scroll_source);
-            data->scroll_source = 0;
-        }
-    }
-}
-
-void textbox_set_width (GtkWidget * textbox, gint width)
-{
-    TextboxData * data = 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 gchar * textbox_get_text (GtkWidget * textbox)
-{
-    TextboxData * data = g_object_get_data ((GObject *) textbox, "textboxdata");
-    g_return_val_if_fail (data, NULL);
-
-    return data->text;
-}
-
-void textbox_set_text (GtkWidget * textbox, const gchar * text)
-{
-    TextboxData * data = 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 gchar * font)
-{
-    TextboxData * data = g_object_get_data ((GObject *) textbox, "textboxdata");
-    g_return_if_fail (data);
-
-    if (data->font)
-    {
-        pango_font_description_free (data->font);
-        data->font = NULL;
-    }
-
-    if (font)
-        data->font = pango_font_description_from_string (font);
-
-    textbox_render (textbox, data);
-}
-
-void textbox_set_scroll (GtkWidget * textbox, gboolean scroll)
-{
-    TextboxData * data = g_object_get_data ((GObject *) textbox, "textboxdata");
-    g_return_if_fail (data);
-
-    if (data->may_scroll == scroll)
-        return;
-
-    data->may_scroll = scroll;
-    textbox_render (textbox, data);
-}
-
-static void textbox_destroy (GtkWidget * textbox)
-{
-    TextboxData * data = 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 (gint width, const gchar * text, const gchar * 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, NULL);
-
-    TextboxData * data = g_malloc0 (sizeof (TextboxData));
-    data->width = width;
-    data->text = g_strdup (text);
-    data->may_scroll = 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 = node->data;
-        g_return_if_fail (textbox);
-        TextboxData * data = g_object_get_data ((GObject *) textbox,
-         "textboxdata");
-        g_return_if_fail (data);
-
-        textbox_render (textbox, data);
-    }
-}
diff --git a/src/skins/ui_skinned_textbox.cc b/src/skins/ui_skinned_textbox.cc
new file mode 100644
index 000000000000..574b00387a1a
--- /dev/null
+++ b/src/skins/ui_skinned_textbox.cc
@@ -0,0 +1,412 @@
+/*
+ * 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_textbox.h b/src/skins/ui_skinned_textbox.h
index 4dfb9a0c3edb..9cadea5ea4cb 100644
--- a/src/skins/ui_skinned_textbox.h
+++ b/src/skins/ui_skinned_textbox.h
@@ -30,12 +30,12 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * textbox_new (gint width, const gchar * text, const gchar * font,
+GtkWidget * textbox_new (int width, const char * text, const char * font,
  gboolean scroll);
-void textbox_set_width (GtkWidget * textbox, gint width);
-const gchar * textbox_get_text (GtkWidget * textbox);
-void textbox_set_text (GtkWidget * textbox, const gchar * text);
-void textbox_set_font (GtkWidget * textbox, const gchar * font);
+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);
 
 void textbox_update_all (void);
diff --git a/src/skins/ui_skinned_window.c b/src/skins/ui_skinned_window.c
deleted file mode 100644
index e791889e4507..000000000000
--- a/src/skins/ui_skinned_window.c
+++ /dev/null
@@ -1,196 +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 "ui_dock.h"
-#include "ui_skinned_window.h"
-
-typedef struct {
-    void (* draw) (GtkWidget * window, cairo_t * cr);
-    GtkWidget * normal, * shaded;
-    gboolean is_shaded, is_moving;
-} WindowData;
-
-DRAW_FUNC_BEGIN (window_draw)
-    WindowData * data = 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 gboolean window_button_press (GtkWidget * window, GdkEventButton * event)
-{
-    WindowData * data = 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 = 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 = 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 = 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);
-    g_free (data);
-}
-
-GtkWidget * window_new (gint * x, gint * y, gint w, gint h, gboolean main,
- gboolean shaded, void (* draw) (GtkWidget * window, cairo_t * cr))
-{
-    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, "button-press-event", (GCallback) window_button_press, NULL);
-    g_signal_connect (window, "button-release-event", (GCallback) window_button_release, NULL);
-    g_signal_connect (window, "motion-notify-event", (GCallback) window_motion, NULL);
-    g_signal_connect (window, "destroy", (GCallback) window_destroy, NULL);
-
-    WindowData * data = g_malloc0 (sizeof (WindowData));
-    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, gint w, gint h)
-{
-    gtk_widget_set_size_request (window, w, h);
-    gtk_window_resize ((GtkWindow *) window, w, h);
-    dock_set_size (window, w, h);
-}
-
-void window_set_shaded (GtkWidget * window, gboolean shaded)
-{
-    WindowData * data = 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;
-}
-
-void window_put_widget (GtkWidget * window, gboolean shaded, GtkWidget * widget,
- gint x, gint y)
-{
-    WindowData * data = 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, gint x, gint y)
-{
-    WindowData * data = 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 = 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_skinned_window.cc b/src/skins/ui_skinned_window.cc
new file mode 100644
index 000000000000..e2875ea8cbb3
--- /dev/null
+++ b/src/skins/ui_skinned_window.cc
@@ -0,0 +1,246 @@
+/*
+ * 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_skinned_window.h b/src/skins/ui_skinned_window.h
index a6abf9b3ec31..eb73db677d95 100644
--- a/src/skins/ui_skinned_window.h
+++ b/src/skins/ui_skinned_window.h
@@ -24,14 +24,15 @@
 
 #include <gtk/gtk.h>
 
-GtkWidget * window_new (gint * x, gint * y, gint w, gint h, gboolean main,
+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, gint w, gint h);
+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,
- gint x, gint y);
+ int x, int y);
 void window_move_widget (GtkWidget * window, gboolean shaded, GtkWidget *
- widget, gint x, gint y);
+ widget, int x, int y);
 void window_show_all (GtkWidget * window);
 
 #endif
diff --git a/src/skins/ui_skinselector.c b/src/skins/ui_skinselector.c
deleted file mode 100644
index 9898c9cf2484..000000000000
--- a/src/skins/ui_skinselector.c
+++ /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 <audacious/i18n.h>
-#include <audacious/misc.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 gchar *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 {
-    gchar *name;
-    gchar *desc;
-    gchar *path;
-    GTime *time;
-} SkinNode;
-
-static void skin_view_on_cursor_changed (GtkTreeView * treeview, void * data);
-
-static GList *skinlist = NULL;
-
-static gchar *
-get_thumbnail_filename(const gchar * path)
-{
-    gchar *basename, *pngname, *thumbname;
-
-    g_return_val_if_fail(path != NULL, NULL);
-
-    basename = g_path_get_basename(path);
-    pngname = g_strconcat(basename, ".png", NULL);
-
-    thumbname = g_build_filename(skins_paths[SKINS_PATH_SKIN_THUMB_DIR],
-                                 pngname, NULL);
-
-    g_free(basename);
-    g_free(pngname);
-
-    return thumbname;
-}
-
-
-static GdkPixbuf *
-skin_get_preview(const gchar * path)
-{
-    GdkPixbuf *preview = NULL;
-    gchar *dec_path, *preview_path;
-    gboolean is_archive = FALSE;
-    gint i = 0;
-    gchar buf[60];			/* gives us lots of room */
-
-    if (file_is_archive(path))
-    {
-        if (!(dec_path = archive_decompress(path)))
-            return NULL;
-
-        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)) != NULL)
-            break;
-    }
-
-    if (preview_path)
-    {
-        preview = gdk_pixbuf_new_from_file(preview_path, NULL);
-        g_free(preview_path);
-    }
-
-    if (is_archive)
-        del_directory(dec_path);
-
-    g_free(dec_path);
-
-    return preview;
-}
-
-static GdkPixbuf * skin_get_thumbnail (const gchar * path)
-{
-    gchar * thumbname = get_thumbnail_filename (path);
-    GdkPixbuf * thumb = NULL;
-
-    if (g_file_test (thumbname, G_FILE_TEST_EXISTS))
-    {
-        thumb = gdk_pixbuf_new_from_file (thumbname, NULL);
-        if (thumb)
-            goto DONE;
-    }
-
-    thumb = skin_get_preview (path);
-    if (! thumb)
-        goto DONE;
-
-    audgui_pixbuf_scale_within (& thumb, 128);
-
-    if (thumb)
-        gdk_pixbuf_save (thumb, thumbname, "png", NULL, NULL);
-
-DONE:
-    g_free (thumbname);
-    return thumb;
-}
-
-static void
-skinlist_add(const gchar * filename)
-{
-    SkinNode *node;
-    gchar *basename;
-
-    g_return_if_fail(filename != NULL);
-
-    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 gchar * path, const gchar * basename, gpointer 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 gchar * path)
-{
-    GError *error = NULL;
-
-    g_return_if_fail(path != NULL);
-
-    if (path[0] == '.')
-        return;
-
-    if (!dir_foreach(path, scan_skindir_func, NULL, &error)) {
-        g_warning("Failed to open directory (%s): %s", path, error->message);
-        g_error_free(error);
-        return;
-    }
-}
-
-static gint skinlist_compare_func (const void * _a, const void * _b)
-{
-    const SkinNode * a = _a, * b = _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 = _data;
-    g_return_if_fail(data != NULL);
-    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, NULL);
-    g_list_free(skinlist);
-    skinlist = NULL;
-}
-
-static void
-skinlist_update(void)
-{
-    gchar *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]);
-
-    gchar * path = g_strdup_printf ("%s/Skins", aud_get_path (AUD_PATH_DATA_DIR));
-    scan_skindir (path);
-    g_free (path);
-
-    skinsdir = getenv("SKINSDIR");
-    if (skinsdir) {
-        gchar **dir_list = g_strsplit(skinsdir, ":", 0);
-        gchar **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 != NULL);
-}
-
-void skin_view_update (GtkTreeView * treeview)
-{
-    GtkTreeSelection *selection = NULL;
-    GtkListStore *store;
-    GtkTreeIter iter, iter_current_skin;
-    gboolean have_current_skin = FALSE;
-    GtkTreePath *path;
-
-    GdkPixbuf *thumbnail;
-    gchar *formattedname;
-    gchar *name;
-    GList *entry;
-
-    g_signal_handlers_block_by_func (treeview, (GCallback) skin_view_on_cursor_changed, NULL);
-
-    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 = 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, NULL, TRUE, 0.5, 0.5);
-        gtk_tree_path_free(path);
-    }
-
-    g_signal_handlers_unblock_by_func (treeview, (GCallback) skin_view_on_cursor_changed, NULL);
-}
-
-
-static void
-skin_view_on_cursor_changed(GtkTreeView * treeview,
-                            gpointer data)
-{
-    GtkTreeModel *model;
-    GtkTreeSelection *selection;
-    GtkTreeIter iter;
-
-    GList *node;
-    gchar *name;
-    gchar *comp = NULL;
-
-    selection = gtk_tree_view_get_selection(treeview);
-
-    /* workaround for Gnome bug #679291 */
-    if (! selection)
-        return;
-
-    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, NULL);
-
-    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, NULL);
-
-    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), NULL);
-}
diff --git a/src/skins/ui_skinselector.cc b/src/skins/ui_skinselector.cc
new file mode 100644
index 000000000000..71b0ae9248ef
--- /dev/null
+++ b/src/skins/ui_skinselector.cc
@@ -0,0 +1,398 @@
+/*
+ * 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/ui_svis.c b/src/skins/ui_svis.c
deleted file mode 100644
index 02a80f41805f..000000000000
--- a/src/skins/ui_svis.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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 "draw-compat.h"
-#include "skins_cfg.h"
-#include "surface.h"
-#include "ui_skin.h"
-#include "ui_vis.h"
-
-static gint svis_analyzer_colors[] = {14, 11, 8, 5, 2};
-static gint svis_scope_colors[] = {20, 19, 18, 19, 20};
-static gint svis_vu_normal_colors[] = {16, 14, 12, 10, 8, 6, 4, 2};
-
-static struct {
-    gboolean active;
-    gint data[75];
-} svis;
-
-#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])
-
-DRAW_FUNC_BEGIN (ui_svis_draw)
-    guint32 rgb[38 * 5];
-    guint32 * set;
-
-    RGB_SEEK (0, 0);
-    for (gint x = 0; x < 38 * 5; x ++)
-        RGB_SET_INDEX (0);
-
-    switch (config.vis_type)
-    {
-    case VIS_ANALYZER:;
-        gboolean bars = (config.analyzer_type == ANALYZER_BARS);
-
-        for (gint x = 0; x < 38; x ++)
-        {
-            if (bars && (x % 3) == 2)
-                continue;
-
-            gint h = svis.data[bars ? (x / 3) : x];
-            h = CLAMP (h, 0, 5);
-            RGB_SEEK (x, 5 - h);
-
-            for (gint 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 (gint y = 0; y < 5; y ++)
-            {
-                if (y == 2)
-                    continue;
-
-                gint h = (svis.data[y / 3] * 8 + 19) / 38;
-                h = CLAMP (h, 0, 8);
-                RGB_SEEK (0, y);
-
-                for (gint 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 (gint y = 0; y < 5; y ++)
-            {
-                if (y == 2)
-                    continue;
-
-                gint h = svis.data[y / 3];
-                h = CLAMP (h, 0, 38);
-                RGB_SEEK (0, y);
-
-                for (gint x = 0; x < h; x ++)
-                    RGB_SET_INDEX (17 - (x * 16) / 38);
-            }
-            break;
-        }
-        break;
-    case VIS_SCOPE:;
-        static const gint scale[17] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
-         4, 4, 4, 4, 4};
-
-        if (! svis.active)
-            goto DRAW;
-
-        switch (config.scope_mode)
-        {
-        case SCOPE_DOT:
-            for (gint x = 0; x < 38; x ++)
-            {
-                gint h = scale[CLAMP (svis.data[2 * x], 0, 16)];
-                RGB_SEEK (x, h);
-                RGB_SET_INDEX (svis_scope_colors[h]);
-            }
-            break;
-        case SCOPE_LINE:
-            for (gint x = 0; x < 37; x++)
-            {
-                gint h = scale[CLAMP (svis.data[2 * x], 0, 16)];
-                gint h2 = scale[CLAMP (svis.data[2 * (x + 1)], 0, 16)];
-
-                if (h < h2) h2 --;
-                else if (h > h2) {gint temp = h; h = h2 + 1; h2 = temp;}
-
-                RGB_SEEK (x, h);
-                for (gint y = h; y <= h2; y ++)
-                    RGB_SET_INDEX_Y (svis_scope_colors[y]);
-            }
-
-            gint h = scale[CLAMP (svis.data[74], 0, 16)];
-            RGB_SEEK (37, h);
-            RGB_SET_INDEX (svis_scope_colors[h]);
-            break;
-        default: /* SCOPE_SOLID */
-            for (gint x = 0; x < 38; x++)
-            {
-                gint h = scale[CLAMP (svis.data[2 * x], 0, 16)];
-                gint h2;
-
-                if (h < 2) h2 = 2;
-                else {h2 = h; h = 2;}
-
-                RGB_SEEK (x, h);
-                for (gint y = h; y <= h2; y ++)
-                    RGB_SET_INDEX_Y (svis_scope_colors[y]);
-            }
-            break;
-        }
-        break;
-    }
-
-DRAW:;
-    cairo_surface_t * surf = cairo_image_surface_create_for_data ((void *) rgb,
-     CAIRO_FORMAT_RGB24, 38, 5, 4 * 38);
-    cairo_set_source_surface (cr, surf, 0, 0);
-    cairo_paint (cr);
-    cairo_surface_destroy (surf);
-DRAW_FUNC_END
-
-GtkWidget * ui_svis_new (void)
-{
-    GtkWidget * wid = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (wid, 38, 5);
-    gtk_widget_add_events (wid, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
-    DRAW_CONNECT (wid, ui_svis_draw);
-    return wid;
-}
-
-void ui_svis_clear_data (GtkWidget * widget)
-{
-    memset (& svis, 0, sizeof svis);
-    gtk_widget_queue_draw (widget);
-}
-
-void ui_svis_timeout_func (GtkWidget * widget, guchar * data)
-{
-    if (config.vis_type == VIS_VOICEPRINT)
-    {
-        for (gint i = 0; i < 2; i ++)
-            svis.data[i] = data[i];
-    }
-    else
-    {
-        for (gint i = 0; i < 75; i ++)
-            svis.data[i] = data[i];
-    }
-
-    svis.active = TRUE;
-    gtk_widget_queue_draw (widget);
-}
diff --git a/src/skins/ui_svis.cc b/src/skins/ui_svis.cc
new file mode 100644
index 000000000000..a5af1ca219c8
--- /dev/null
+++ b/src/skins/ui_svis.cc
@@ -0,0 +1,215 @@
+/*
+ * 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 "draw-compat.h"
+#include "skins_cfg.h"
+#include "surface.h"
+#include "ui_skin.h"
+#include "ui_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;
+
+#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])
+
+DRAW_FUNC_BEGIN (ui_svis_draw)
+    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:
+    {
+        gboolean 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];
+            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 = (svis.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 = svis.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 (! svis.active)
+            goto DRAW;
+
+        switch (config.scope_mode)
+        {
+        case SCOPE_DOT:
+            for (int x = 0; x < 38; x ++)
+            {
+                int h = scale[aud::clamp (svis.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 (svis.data[2 * x], 0, 16)];
+                int h2 = scale[aud::clamp (svis.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 (svis.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 (svis.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:;
+    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)
+{
+    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;
+}
+
+void ui_svis_clear_data (GtkWidget * widget)
+{
+    memset (& svis, 0, sizeof svis);
+    gtk_widget_queue_draw (widget);
+}
+
+void ui_svis_timeout_func (GtkWidget * widget, unsigned char * data)
+{
+    if (config.vis_type == VIS_VOICEPRINT)
+    {
+        for (int i = 0; i < 2; i ++)
+            svis.data[i] = data[i];
+    }
+    else
+    {
+        for (int i = 0; i < 75; i ++)
+            svis.data[i] = data[i];
+    }
+
+    svis.active = TRUE;
+    gtk_widget_queue_draw (widget);
+}
diff --git a/src/skins/ui_vis.c b/src/skins/ui_vis.c
deleted file mode 100644
index d2138ac789ec..000000000000
--- a/src/skins/ui_vis.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * 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 "draw-compat.h"
-#include "skins_cfg.h"
-#include "surface.h"
-#include "ui_skin.h"
-#include "ui_vis.h"
-
-static const gfloat vis_afalloff_speeds[] = {0.34, 0.5, 1.0, 1.3, 1.6};
-static const gfloat vis_pfalloff_speeds[] = {1.2, 1.3, 1.4, 1.5, 1.6};
-static const gint vis_scope_colors[16] = {22, 22, 21, 21, 20, 10, 19, 19, 18,
- 19, 19, 20, 20, 21, 21, 22};
-
-static guint32 vis_voice_color[256];
-static guint32 vis_voice_color_fire[256];
-static guint32 vis_voice_color_ice[256];
-static guint32 pattern_fill[76 * 2];
-
-static struct {
-    gboolean active;
-    gfloat data[75], peak[75], peak_speed[75];
-    guchar 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])
-
-void ui_vis_set_colors (void)
-{
-    g_return_if_fail (active_skin != NULL);
-
-    guint32 fgc = active_skin->colors[SKIN_TEXTFG];
-    guint32 bgc = active_skin->colors[SKIN_TEXTBG];
-    gint fg[3] = {COLOR_R (fgc), COLOR_G (fgc), COLOR_B (fgc)};
-    gint bg[3] = {COLOR_R (bgc), COLOR_G (bgc), COLOR_B (bgc)};
-
-    for (gint x = 0; x < 256; x ++)
-    {
-        guchar c[3];
-        for (gint 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]);
-    }
-
-    for (gint x = 0; x < 256; x ++)
-    {
-        guchar r = MIN (x, 127) * 2;
-        guchar g = CLAMP (x - 64, 0, 127) * 2;
-        guchar b = MAX (x - 128, 0) * 2;
-        vis_voice_color_fire[x] = COLOR (r, g, b);
-    }
-
-    for (gint x = 0; x < 256; x ++)
-        vis_voice_color_ice[x] = COLOR (x / 2, x, MIN (x * 2, 255));
-
-    guint32 * set = pattern_fill;
-    guint32 * end = set + 76;
-
-    while (set < end)
-        RGB_SET_INDEX (0);
-
-    end = set + 76;
-
-    while (set < end)
-    {
-        RGB_SET_INDEX (1);
-        RGB_SET_INDEX (0);
-    }
-}
-
-DRAW_FUNC_BEGIN (ui_vis_draw)
-    guint32 rgb[76 * 16];
-    guint32 * set;
-
-    if (config.vis_type != VIS_VOICEPRINT)
-    {
-        for (set = rgb; set < rgb + 76 * 16; set += 76 * 2)
-            memcpy (set, pattern_fill, sizeof pattern_fill);
-    }
-
-    switch (config.vis_type)
-    {
-    case VIS_ANALYZER:;
-        gboolean bars = (config.analyzer_type == ANALYZER_BARS);
-
-        for (gint x = 0; x < 75; x ++)
-        {
-            if (bars && (x & 3) == 3)
-                continue;
-
-            gint h = vis.data[bars ? (x >> 2) : x];
-            h = CLAMP (h, 0, 16);
-            RGB_SEEK (x, 16 - h);
-
-            switch (config.analyzer_mode)
-            {
-            case ANALYZER_NORMAL:
-                for (gint y = 0; y < h; y ++)
-                    RGB_SET_INDEX_Y (18 - h + y);
-                break;
-            case ANALYZER_FIRE:
-                for (gint y = 0; y < h; y ++)
-                    RGB_SET_INDEX_Y (2 + y);
-                break;
-            default: /* ANALYZER_VLINES */
-                for (gint y = 0; y < h; y ++)
-                    RGB_SET_INDEX_Y (18 - h);
-                break;
-            }
-
-            if (config.analyzer_peaks)
-            {
-                gint h = vis.peak[bars ? (x >> 2) : x];
-                h = CLAMP (h, 0, 16);
-
-                if (h)
-                {
-                    RGB_SEEK (x, 16 - h);
-                    RGB_SET_INDEX (23);
-                }
-            }
-        }
-
-        break;
-    case VIS_VOICEPRINT:
-        if (vis.voiceprint_advance)
-        {
-            vis.voiceprint_advance = FALSE;
-            memmove (vis.voiceprint_data, vis.voiceprint_data + 1, sizeof
-             vis.voiceprint_data - 1);
-
-            for (gint y = 0; y < 16; y ++)
-                vis.voiceprint_data[76 * y + 75] = vis.data[y];
-        }
-
-        guchar * get = vis.voiceprint_data;
-        guint32 * colors = (config.voiceprint_mode == VOICEPRINT_NORMAL) ?
-         vis_voice_color : (config.voiceprint_mode == VOICEPRINT_FIRE) ?
-         vis_voice_color_fire : /* VOICEPRINT_ICE */ vis_voice_color_ice;
-        set = rgb;
-
-        for (gint y = 0; y < 16; y ++)
-        for (gint x = 0; x < 76; x ++)
-            RGB_SET (colors[* get ++]);
-        break;
-    case VIS_SCOPE:
-        if (! vis.active)
-            goto DRAW;
-
-        switch (config.scope_mode)
-        {
-        case SCOPE_DOT:
-            for (gint x = 0; x < 75; x ++)
-            {
-                gint h = CLAMP (vis.data[x], 0, 15);
-                RGB_SEEK (x, h);
-                RGB_SET_INDEX (vis_scope_colors[h]);
-            }
-            break;
-        case SCOPE_LINE:
-            for (gint x = 0; x < 74; x++)
-            {
-                gint h = CLAMP (vis.data[x], 0, 15);
-                gint h2 = CLAMP (vis.data[x + 1], 0, 15);
-
-                if (h < h2) h2 --;
-                else if (h > h2) {gint temp = h; h = h2 + 1; h2 = temp;}
-
-                RGB_SEEK (x, h);
-
-                for (gint y = h; y <= h2; y ++)
-                    RGB_SET_INDEX_Y (vis_scope_colors[y]);
-            }
-
-            gint h = CLAMP (vis.data[74], 0, 15);
-            RGB_SEEK (74, h);
-            RGB_SET_INDEX (vis_scope_colors[h]);
-            break;
-        default: /* SCOPE_SOLID */
-            for (gint x = 0; x < 75; x++)
-            {
-                gint h = CLAMP (vis.data[x], 0, 15);
-                gint h2;
-
-                if (h < 8) h2 = 8;
-                else {h2 = h; h = 8;}
-
-                RGB_SEEK (x, h);
-
-                for (gint y = h; y <= h2; y ++)
-                    RGB_SET_INDEX_Y (vis_scope_colors[y]);
-            }
-            break;
-        }
-        break;
-    }
-
-DRAW:;
-    cairo_surface_t * surf = cairo_image_surface_create_for_data ((void *) rgb,
-     CAIRO_FORMAT_RGB24, 76, 16, 4 * 76);
-    cairo_set_source_surface (cr, surf, 0, 0);
-    cairo_paint (cr);
-    cairo_surface_destroy (surf);
-DRAW_FUNC_END
-
-GtkWidget * ui_vis_new (void)
-{
-    GtkWidget * wid = gtk_drawing_area_new ();
-    gtk_widget_set_size_request (wid, 76, 16);
-    gtk_widget_add_events (wid, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
-    DRAW_CONNECT (wid, ui_vis_draw);
-    return wid;
-}
-
-void ui_vis_clear_data (GtkWidget * wid)
-{
-    memset (& vis, 0, sizeof vis);
-    gtk_widget_queue_draw (wid);
-}
-
-void ui_vis_timeout_func (GtkWidget * widget, guchar * data)
-{
-    if (config.vis_type == VIS_ANALYZER)
-    {
-        const gint n = (config.analyzer_type == ANALYZER_BARS) ? 19 : 75;
-
-        for (gint i = 0; i < n; i++)
-        {
-            if (data[i] > vis.data[i])
-            {
-                vis.data[i] = data[i];
-                if (vis.data[i] > vis.peak[i])
-                {
-                    vis.peak[i] = vis.data[i];
-                    vis.peak_speed[i] = 0.01;
-
-                }
-                else if (vis.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;
-                }
-            }
-            else
-            {
-                if (vis.data[i] > 0.0)
-                {
-                    vis.data[i] -=
-                        vis_afalloff_speeds[config.analyzer_falloff];
-                    if (vis.data[i] < 0.0)
-                        vis.data[i] = 0.0;
-                }
-                if (vis.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;
-                }
-            }
-        }
-    }
-    else if (config.vis_type == VIS_VOICEPRINT)
-    {
-        for (gint i = 0; i < 16; i++)
-            vis.data[i] = data[15 - i];
-
-        vis.voiceprint_advance = TRUE;
-    }
-    else
-    {
-        for (gint i = 0; i < 75; i++)
-            vis.data[i] = data[i];
-    }
-
-    vis.active = TRUE;
-    gtk_widget_queue_draw (widget);
-}
diff --git a/src/skins/ui_vis.cc b/src/skins/ui_vis.cc
new file mode 100644
index 000000000000..c5c3ee3b5109
--- /dev/null
+++ b/src/skins/ui_vis.cc
@@ -0,0 +1,325 @@
+/*
+ * 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 "draw-compat.h"
+#include "skins_cfg.h"
+#include "surface.h"
+#include "ui_skin.h"
+#include "ui_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])
+
+void ui_vis_set_colors (void)
+{
+    g_return_if_fail (active_skin != nullptr);
+
+    uint32_t fgc = active_skin->colors[SKIN_TEXTFG];
+    uint32_t bgc = active_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)};
+
+    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;
+        vis_voice_color[x] = COLOR (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;
+        vis_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));
+
+    uint32_t * set = 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);
+    }
+}
+
+DRAW_FUNC_BEGIN (ui_vis_draw)
+    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);
+    }
+
+    switch (config.vis_type)
+    {
+    case VIS_ANALYZER:
+    {
+        gboolean 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];
+            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 = vis.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 (vis.voiceprint_advance)
+        {
+            vis.voiceprint_advance = FALSE;
+            memmove (vis.voiceprint_data, vis.voiceprint_data + 1, sizeof
+             vis.voiceprint_data - 1);
+
+            for (int y = 0; y < 16; y ++)
+                vis.voiceprint_data[76 * y + 75] = vis.data[y];
+        }
+
+        unsigned char * get = vis.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;
+        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 (! vis.active)
+            goto DRAW;
+
+        switch (config.scope_mode)
+        {
+        case SCOPE_DOT:
+            for (int x = 0; x < 75; x ++)
+            {
+                int h = aud::clamp ((int) vis.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) vis.data[x], 0, 15);
+                int h2 = aud::clamp ((int) vis.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) vis.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) vis.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:;
+    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)
+{
+    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;
+}
+
+void ui_vis_clear_data (GtkWidget * wid)
+{
+    memset (& vis, 0, sizeof vis);
+    gtk_widget_queue_draw (wid);
+}
+
+void ui_vis_timeout_func (GtkWidget * widget, 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] > vis.data[i])
+            {
+                vis.data[i] = data[i];
+                if (vis.data[i] > vis.peak[i])
+                {
+                    vis.peak[i] = vis.data[i];
+                    vis.peak_speed[i] = 0.01;
+
+                }
+                else if (vis.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;
+                }
+            }
+            else
+            {
+                if (vis.data[i] > 0.0)
+                {
+                    vis.data[i] -=
+                        vis_afalloff_speeds[config.analyzer_falloff];
+                    if (vis.data[i] < 0.0)
+                        vis.data[i] = 0.0;
+                }
+                if (vis.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;
+                }
+            }
+        }
+    }
+    else if (config.vis_type == VIS_VOICEPRINT)
+    {
+        for (int i = 0; i < 16; i++)
+            vis.data[i] = data[15 - i];
+
+        vis.voiceprint_advance = TRUE;
+    }
+    else
+    {
+        for (int i = 0; i < 75; i++)
+            vis.data[i] = data[i];
+    }
+
+    vis.active = TRUE;
+    gtk_widget_queue_draw (widget);
+}
diff --git a/src/skins/ui_vis.h b/src/skins/ui_vis.h
index 6850071d9c33..e3d753af96ad 100644
--- a/src/skins/ui_vis.h
+++ b/src/skins/ui_vis.h
@@ -54,10 +54,10 @@ typedef enum {
 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, guchar * data);
+void ui_vis_timeout_func (GtkWidget * widget, unsigned char * data);
 
 GtkWidget * ui_svis_new (void);
 void ui_svis_clear_data (GtkWidget * widget);
-void ui_svis_timeout_func (GtkWidget * widget, guchar * data);
+void ui_svis_timeout_func (GtkWidget * widget, unsigned char * data);
 
 #endif
diff --git a/src/skins/util.c b/src/skins/util.c
deleted file mode 100644
index 3295c0b33139..000000000000
--- a/src/skins/util.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*  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 <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/hook.h>
-#include <libaudcore/vfs.h>
-
-#include "util.h"
-
-typedef struct
-{
-    const gchar *to_match;
-    gchar *match;
-    gboolean found;
-} FindFileContext;
-
-#ifndef HAVE_MKDTEMP
-static void make_directory(const gchar *path, mode_t mode);
-#endif
-
-gchar * find_file_case (const gchar * folder, const gchar * basename)
-{
-    static GHashTable * cache = NULL;
-    GList * list = NULL;
-    void * vlist;
-
-    if (cache == NULL)
-        cache = g_hash_table_new (g_str_hash, g_str_equal);
-
-    if (g_hash_table_lookup_extended (cache, folder, NULL, & vlist))
-        list = vlist;
-    else
-    {
-        GDir * handle = g_dir_open (folder, 0, NULL);
-        if (! handle)
-            return NULL;
-
-        const char * name;
-        while ((name = g_dir_read_name (handle)))
-            list = g_list_prepend (list, g_strdup (name));
-
-        g_hash_table_insert (cache, g_strdup (folder), list);
-        g_dir_close (handle);
-    }
-
-    for (; list != NULL; list = list->next)
-    {
-        if (! g_ascii_strcasecmp (list->data, basename))
-            return g_strdup (list->data);
-    }
-
-    return NULL;
-}
-
-gchar * find_file_case_path (const gchar * folder, const gchar * basename)
-{
-    gchar * found, * path;
-
-    if ((found = find_file_case (folder, basename)) == NULL)
-        return NULL;
-
-    path = g_strdup_printf ("%s/%s", folder, found);
-    g_free (found);
-    return path;
-}
-
-VFSFile * open_local_file_nocase (const char * folder, const char * basename)
-{
-    char * path = find_file_case_path (folder, basename);
-    if (! path)
-        return NULL;
-
-    char * uri = filename_to_uri (path);
-    g_free (path);
-
-    if (! uri)
-        return NULL;
-
-    VFSFile * file = vfs_fopen (uri, "r");
-    str_unref (uri);
-    return file;
-}
-
-gchar * text_parse_line (gchar * text)
-{
-    gchar * newline = strchr (text, '\n');
-
-    if (newline == NULL)
-        return NULL;
-
-    * newline = 0;
-    return newline + 1;
-}
-
-typedef enum
-{
-    ARCHIVE_UNKNOWN = 0,
-    ARCHIVE_DIR,
-    ARCHIVE_TAR,
-    ARCHIVE_TGZ,
-    ARCHIVE_ZIP,
-    ARCHIVE_TBZ2
-} ArchiveType;
-
-typedef gchar *(*ArchiveExtractFunc) (const gchar *, const gchar *);
-
-typedef struct
-{
-    ArchiveType type;
-    const gchar *ext;
-} ArchiveExtensionType;
-
-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"},
-    {ARCHIVE_UNKNOWN, NULL}
-};
-
-static gchar *archive_extract_tar(const gchar *archive, const gchar *dest);
-static gchar *archive_extract_zip(const gchar *archive, const gchar *dest);
-static gchar *archive_extract_tgz(const gchar *archive, const gchar *dest);
-static gchar *archive_extract_tbz2(const gchar *archive, const gchar *dest);
-
-static ArchiveExtractFunc archive_extract_funcs[] = {
-    NULL,
-    NULL,
-    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 gchar *get_tar_command(void)
-{
-    static const gchar *command = NULL;
-
-    if (!command)
-    {
-        if (!(command = getenv("TARCMD")))
-            command = "tar";
-    }
-
-    return command;
-}
-
-static const gchar *get_unzip_command(void)
-{
-    static const gchar *command = NULL;
-
-    if (!command)
-    {
-        if (!(command = getenv("UNZIPCMD")))
-            command = "unzip";
-    }
-
-    return command;
-}
-
-
-static gchar *archive_extract_tar(const gchar *archive, const gchar *dest)
-{
-    return g_strdup_printf("%s >/dev/null xf \"%s\" -C %s", get_tar_command(),
-                           archive, dest);
-}
-
-static gchar *archive_extract_zip(const gchar *archive, const gchar *dest)
-{
-    return g_strdup_printf("%s >/dev/null -o -j \"%s\" -d %s",
-                           get_unzip_command(), archive, dest);
-}
-
-static gchar *archive_extract_tgz(const gchar *archive, const gchar *dest)
-{
-    return g_strdup_printf("%s >/dev/null xzf \"%s\" -C %s", get_tar_command(),
-                           archive, dest);
-}
-
-static gchar *archive_extract_tbz2(const gchar *archive, const gchar *dest)
-{
-    return g_strdup_printf("bzip2 -dc \"%s\" | %s >/dev/null xf - -C %s",
-                           archive, get_tar_command(), dest);
-}
-
-
-static ArchiveType archive_get_type(const gchar *filename)
-{
-    gint i = 0;
-
-    if (g_file_test(filename, G_FILE_TEST_IS_DIR))
-        return ARCHIVE_DIR;
-
-    while (archive_extensions[i].ext)
-    {
-        if (g_str_has_suffix(filename, archive_extensions[i].ext))
-        {
-            return archive_extensions[i].type;
-        }
-        i++;
-    }
-
-    return ARCHIVE_UNKNOWN;
-}
-
-gboolean file_is_archive(const gchar *filename)
-{
-    return (archive_get_type(filename) > ARCHIVE_DIR);
-}
-
-gchar *archive_basename(const gchar *str)
-{
-    gint i = 0;
-
-    while (archive_extensions[i].ext)
-    {
-        if (str_has_suffix_nocase(str, archive_extensions[i].ext))
-        {
-            const gchar *end = g_strrstr(str, archive_extensions[i].ext);
-            if (end)
-            {
-                return g_strndup(str, end - str);
-            }
-            break;
-        }
-        i++;
-    }
-
-    return NULL;
-}
-
-/**
- * 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().
- */
-static gchar *
-escape_shell_chars(const gchar * string)
-{
-    const gchar *special = "$`\"\\";    /* Characters to escape */
-    const gchar *in = string;
-    gchar *out, *escaped;
-    gint num = 0;
-
-    while (*in != '\0')
-        if (strchr(special, *in++))
-            num++;
-
-    escaped = g_malloc(strlen(string) + num + 1);
-
-    in = string;
-    out = escaped;
-
-    while (*in != '\0') {
-        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 NULL if failed,
-   watch out tho, doesn't actually check if the system command succeeds :-|
-*/
-
-gchar *archive_decompress(const gchar *filename)
-{
-    gchar *tmpdir, *cmd, *escaped_filename;
-    ArchiveType type;
-#ifndef HAVE_MKDTEMP
-#ifdef S_IRGRP
-    mode_t mode755 = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
-#else
-    mode_t mode755 = S_IRWXU;
-#endif
-#endif
-
-    if ((type = archive_get_type(filename)) <= ARCHIVE_DIR)
-        return NULL;
-
-#ifdef HAVE_MKDTEMP
-    tmpdir = g_build_filename(g_get_tmp_dir(), "audacious.XXXXXXXX", NULL);
-    if (!mkdtemp(tmpdir))
-    {
-        g_free(tmpdir);
-        AUDDBG("Unable to load skin: Failed to create temporary "
-               "directory: %s\n", g_strerror(errno));
-        return NULL;
-    }
-#else
-    tmpdir = g_strdup_printf("%s/audacious.%ld", g_get_tmp_dir(), (long)rand());
-    make_directory(tmpdir, mode755);
-#endif
-
-    escaped_filename = escape_shell_chars(filename);
-    cmd = archive_extract_funcs[type] (escaped_filename, tmpdir);
-    g_free(escaped_filename);
-
-    if (!cmd)
-    {
-        AUDDBG("extraction function is NULL!\n");
-        g_free(tmpdir);
-        return NULL;
-    }
-
-    AUDDBG("Attempt to execute \"%s\"\n", cmd);
-
-    if (system(cmd) != 0)
-    {
-        AUDDBG("could not execute cmd %s\n", cmd);
-        g_free(cmd);
-        return NULL;
-    }
-    g_free(cmd);
-
-    return tmpdir;
-}
-
-static gboolean del_directory_func(const gchar *path, const gchar *basename,
-                                   void *params)
-{
-    if (!strcmp(basename, ".") || !strcmp(path, ".."))
-        return FALSE;
-
-    if (g_file_test(path, G_FILE_TEST_IS_DIR))
-    {
-        dir_foreach(path, del_directory_func, NULL, NULL);
-        g_rmdir(path);
-        return FALSE;
-    }
-
-    g_unlink(path);
-
-    return FALSE;
-}
-
-void del_directory(const gchar *path)
-{
-    dir_foreach(path, del_directory_func, NULL, NULL);
-    g_rmdir(path);
-}
-
-GArray *string_to_garray(const gchar *str)
-{
-    GArray *array;
-    gint temp;
-    const gchar *ptr = str;
-    gchar *endptr;
-
-    array = g_array_new(FALSE, TRUE, sizeof(gint));
-    for (;;)
-    {
-        temp = strtol(ptr, &endptr, 10);
-        if (ptr == endptr)
-            break;
-        g_array_append_val(array, temp);
-        ptr = endptr;
-        while (!g_ascii_isdigit((int)*ptr) && (*ptr) != '\0')
-            ptr++;
-        if (*ptr == '\0')
-            break;
-    }
-    return (array);
-}
-
-gboolean dir_foreach(const gchar *path, DirForeachFunc function,
-                     gpointer user_data, GError **error)
-{
-    GError *error_out = NULL;
-    GDir *dir;
-    const gchar *entry;
-    gchar *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)))
-    {
-        entry_fullpath = g_build_filename(path, entry, NULL);
-
-        if ((*function) (entry_fullpath, entry, user_data))
-        {
-            g_free(entry_fullpath);
-            break;
-        }
-
-        g_free(entry_fullpath);
-    }
-
-    g_dir_close(dir);
-
-    return TRUE;
-}
-
-#ifndef HAVE_MKDTEMP
-static void make_directory(const gchar *path, mode_t mode)
-{
-    if (g_mkdir_with_parents(path, mode) == 0)
-        return;
-
-    g_printerr(_("Could not create directory (%s): %s\n"), path,
-               g_strerror(errno));
-}
-#endif
diff --git a/src/skins/util.cc b/src/skins/util.cc
new file mode 100644
index 000000000000..e93cdee5dd69
--- /dev/null
+++ b/src/skins/util.cc
@@ -0,0 +1,432 @@
+/*  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/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/hook.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
+
+char * find_file_case (const char * folder, const char * basename)
+{
+    static GHashTable * cache = nullptr;
+    GList * list = nullptr;
+    void * vlist;
+
+    if (cache == nullptr)
+        cache = g_hash_table_new ((GHashFunc) str_calc_hash, g_str_equal);
+
+    if (g_hash_table_lookup_extended (cache, folder, nullptr, & vlist))
+        list = (GList *) vlist;
+    else
+    {
+        GDir * handle = g_dir_open (folder, 0, nullptr);
+        if (! handle)
+            return nullptr;
+
+        const char * name;
+        while ((name = g_dir_read_name (handle)))
+            list = g_list_prepend (list, g_strdup (name));
+
+        g_hash_table_insert (cache, g_strdup (folder), list);
+        g_dir_close (handle);
+    }
+
+    for (; list != nullptr; list = list->next)
+    {
+        if (! g_ascii_strcasecmp ((char *) list->data, basename))
+            return g_strdup ((char *) list->data);
+    }
+
+    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;
+}
+
+VFSFile open_local_file_nocase (const char * folder, const char * basename)
+{
+    char * 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");
+}
+
+char * text_parse_line (char * text)
+{
+    char * newline = strchr (text, '\n');
+
+    if (newline == nullptr)
+        return nullptr;
+
+    * newline = 0;
+    return newline + 1;
+}
+
+typedef enum
+{
+    ARCHIVE_UNKNOWN = 0,
+    ARCHIVE_DIR,
+    ARCHIVE_TAR,
+    ARCHIVE_TGZ,
+    ARCHIVE_ZIP,
+    ARCHIVE_TBZ2
+} ArchiveType;
+
+typedef char *(*ArchiveExtractFunc) (const char *, const char *);
+
+typedef struct
+{
+    ArchiveType type;
+    const char *ext;
+} ArchiveExtensionType;
+
+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"},
+    {ARCHIVE_UNKNOWN, nullptr}
+};
+
+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 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 *command = nullptr;
+
+    if (!command)
+    {
+        if (!(command = getenv("TARCMD")))
+            command = "tar";
+    }
+
+    return command;
+}
+
+static const char *get_unzip_command(void)
+{
+    static const char *command = nullptr;
+
+    if (!command)
+    {
+        if (!(command = getenv("UNZIPCMD")))
+            command = "unzip";
+    }
+
+    return command;
+}
+
+
+static char *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);
+}
+
+static char *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);
+}
+
+static char *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);
+}
+
+static char *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);
+}
+
+
+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)
+    {
+        if (g_str_has_suffix(filename, archive_extensions[i].ext))
+        {
+            return archive_extensions[i].type;
+        }
+        i++;
+    }
+
+    return ARCHIVE_UNKNOWN;
+}
+
+gboolean file_is_archive(const char *filename)
+{
+    return (archive_get_type(filename) > ARCHIVE_DIR);
+}
+
+char *archive_basename(const char *str)
+{
+    int i = 0;
+
+    while (archive_extensions[i].ext)
+    {
+        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++;
+    }
+
+    return nullptr;
+}
+
+/**
+ * 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().
+ */
+static char *
+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);
+
+    in = string;
+    out = escaped;
+
+    while (*in != '\0') {
+        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)
+{
+    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);
+
+    if (!cmd)
+    {
+        AUDDBG("extraction function is nullptr!\n");
+        g_free(tmpdir);
+        return nullptr;
+    }
+
+    AUDDBG("Attempt to execute \"%s\"\n", cmd);
+
+    if (system(cmd) != 0)
+    {
+        AUDDBG("could not execute cmd %s\n", cmd);
+        g_free(cmd);
+        return nullptr;
+    }
+    g_free(cmd);
+
+    return tmpdir;
+}
+
+static gboolean del_directory_func(const char *path, const char *basename,
+                                   void *params)
+{
+    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;
+}
+
+void del_directory(const char *path)
+{
+    dir_foreach(path, del_directory_func, nullptr, nullptr);
+    g_rmdir(path);
+}
+
+GArray *string_to_garray(const char *str)
+{
+    GArray *array;
+    int temp;
+    const char *ptr = str;
+    char *endptr;
+
+    array = g_array_new(FALSE, TRUE, sizeof(int));
+    for (;;)
+    {
+        temp = strtol(ptr, &endptr, 10);
+        if (ptr == endptr)
+            break;
+        g_array_append_val(array, temp);
+        ptr = endptr;
+        while (!g_ascii_isdigit((int)*ptr) && (*ptr) != '\0')
+            ptr++;
+        if (*ptr == '\0')
+            break;
+    }
+    return (array);
+}
+
+gboolean dir_foreach(const char *path, DirForeachFunc function,
+                     void * user_data, GError **error)
+{
+    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)))
+    {
+        entry_fullpath = g_build_filename(path, entry, nullptr);
+
+        if ((*function) (entry_fullpath, entry, user_data))
+        {
+            g_free(entry_fullpath);
+            break;
+        }
+
+        g_free(entry_fullpath);
+    }
+
+    g_dir_close(dir);
+
+    return TRUE;
+}
+
+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));
+}
diff --git a/src/skins/util.h b/src/skins/util.h
index 87be2041f24c..6c041ae65e53 100644
--- a/src/skins/util.h
+++ b/src/skins/util.h
@@ -30,24 +30,26 @@
 
 #include <libaudcore/vfs.h>
 
-typedef gboolean(*DirForeachFunc) (const gchar *path, const gchar *basename,
-                                   gpointer user_data);
+typedef gboolean(*DirForeachFunc) (const char *path, const char *basename,
+                                   void * user_data);
 
-gchar * find_file_case (const gchar * folder, const gchar * basename);
-gchar * find_file_case_path (const gchar * folder, const gchar * basename);
+char * find_file_case (const char * folder, const char * basename);
+char * find_file_case_path (const char * folder, const char * basename);
 
-VFSFile * open_local_file_nocase (const char * folder, const char * basename);
+VFSFile open_local_file_nocase (const char * folder, const char * basename);
 
-gchar * text_parse_line (gchar * text);
+char * text_parse_line (char * text);
 
-void del_directory(const gchar *dirname);
-gboolean dir_foreach(const gchar *path, DirForeachFunc function,
-                     gpointer user_data, GError **error);
+void make_directory(const char *path);
+void del_directory(const char *path);
 
-GArray *string_to_garray(const gchar *str);
+gboolean dir_foreach(const char *path, DirForeachFunc function,
+                     void * user_data, GError **error);
 
-gboolean file_is_archive(const gchar *filename);
-gchar *archive_decompress(const gchar *path);
-gchar *archive_basename(const gchar *path);
+GArray *string_to_garray(const char *str);
+
+gboolean file_is_archive(const char *filename);
+char *archive_decompress(const char *path);
+char *archive_basename(const char *path);
 
 #endif
diff --git a/src/skins/view.c b/src/skins/view.c
deleted file mode 100644
index b1b69e750798..000000000000
--- a/src/skins/view.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * view.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 "view.h"
-
-#include <audacious/misc.h>
-#include <libaudcore/hook.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"
-
-void view_show_player (bool_t show)
-{
-    if (show)
-        gtk_window_present ((GtkWindow *) mainwin);
-    else
-        gtk_widget_hide (mainwin);
-
-    view_apply_show_playlist ();
-    view_apply_show_equalizer ();
-
-    start_stop_visual (FALSE);
-}
-
-void view_set_show_playlist (bool_t show)
-{
-    aud_set_bool ("skins", "playlist_visible", show);
-    hook_call ("skins set playlist_visible", NULL);
-
-    view_apply_show_playlist ();
-}
-
-void view_apply_show_playlist (void)
-{
-    bool_t show = aud_get_bool ("skins", "playlist_visible");
-
-    if (show && gtk_widget_get_visible (mainwin))
-        gtk_window_present ((GtkWindow *) playlistwin);
-    else
-        gtk_widget_hide (playlistwin);
-
-    button_set_active (mainwin_pl, show);
-}
-
-void view_set_show_equalizer (bool_t show)
-{
-    aud_set_bool ("skins", "equalizer_visible", show);
-    hook_call ("skins set equalizer_visible", NULL);
-
-    view_apply_show_equalizer ();
-}
-
-void view_apply_show_equalizer (void)
-{
-    bool_t show = aud_get_bool ("skins", "equalizer_visible");
-
-    if (show && gtk_widget_get_visible (mainwin))
-        gtk_window_present ((GtkWindow *) equalizerwin);
-    else
-        gtk_widget_hide (equalizerwin);
-
-    button_set_active (mainwin_eq, show);
-}
-
-void view_set_player_shaded (bool_t shaded)
-{
-    aud_set_bool ("skins", "player_shaded", shaded);
-    hook_call ("skins set player_shaded", NULL);
-
-    view_apply_player_shaded ();
-}
-
-void view_apply_player_shaded (void)
-{
-    bool_t shaded = aud_get_bool ("skins", "player_shaded");
-
-    window_set_shaded (mainwin, shaded);
-
-    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);
-
-    mainwin_set_shape ();
-}
-
-void view_set_playlist_shaded (bool_t shaded)
-{
-    aud_set_bool ("skins", "playlist_shaded", shaded);
-    hook_call ("skins set playlist_shaded", NULL);
-
-    view_apply_playlist_shaded ();
-}
-
-void view_apply_playlist_shaded (void)
-{
-    bool_t shaded = aud_get_bool ("skins", "playlist_shaded");
-
-    window_set_shaded (playlistwin, shaded);
-
-    int height = shaded ? MAINWIN_SHADED_HEIGHT : config.playlist_height;
-    window_set_size (playlistwin, config.playlist_width, height);
-
-    playlistwin_update ();
-}
-
-void view_set_equalizer_shaded (bool_t shaded)
-{
-    aud_set_bool ("skins", "equalizer_shaded", shaded);
-    hook_call ("skins set equalizer_shaded", NULL);
-
-    view_apply_equalizer_shaded ();
-}
-
-void view_apply_equalizer_shaded (void)
-{
-    bool_t shaded = aud_get_bool ("skins", "equalizer_shaded");
-
-    window_set_shaded (equalizerwin, shaded);
-    window_set_size (equalizerwin, 275, shaded ? 14 : 116);
-
-    equalizerwin_set_shape ();
-}
-
-void view_set_on_top (bool_t on_top)
-{
-    aud_set_bool ("skins", "always_on_top", on_top);
-    hook_call ("skins set always_on_top", NULL);
-
-    view_apply_on_top ();
-}
-
-void view_apply_on_top (void)
-{
-    bool_t 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);
-
-    ui_skinned_menurow_update (mainwin_menurow);
-}
-
-void view_set_sticky (bool_t sticky)
-{
-    aud_set_bool ("skins", "sticky", sticky);
-    hook_call ("skins set sticky", NULL);
-
-    view_apply_sticky ();
-}
-
-void view_apply_sticky (void)
-{
-    bool_t sticky = aud_get_bool ("skins", "sticky");
-
-    if (sticky)
-    {
-        gtk_window_stick ((GtkWindow *) mainwin);
-        gtk_window_stick ((GtkWindow *) equalizerwin);
-        gtk_window_stick ((GtkWindow *) playlistwin);
-    }
-    else
-    {
-        gtk_window_unstick ((GtkWindow *) mainwin);
-        gtk_window_unstick ((GtkWindow *) equalizerwin);
-        gtk_window_unstick ((GtkWindow *) playlistwin);
-    }
-}
-
-void view_set_show_remaining (bool_t remaining)
-{
-    aud_set_bool ("skins", "show_remaining_time", remaining);
-    hook_call ("skins set show_remaining_time", NULL);
-
-    view_apply_show_remaining ();
-}
-
-void view_apply_show_remaining (void)
-{
-    mainwin_update_song_info ();
-}
diff --git a/src/skins/view.cc b/src/skins/view.cc
new file mode 100644
index 000000000000..8baac93d9402
--- /dev/null
+++ b/src/skins/view.cc
@@ -0,0 +1,222 @@
+/*
+ * view.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 "view.h"
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/hook.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"
+
+void view_show_player (bool show)
+{
+    if (show)
+    {
+        gtk_window_present ((GtkWindow *) mainwin);
+        show_plugin_windows ();
+    }
+    else
+    {
+        gtk_widget_hide (mainwin);
+        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 (void)
+{
+    bool show = aud_get_bool ("skins", "playlist_visible");
+
+    if (show && gtk_widget_get_visible (mainwin))
+        gtk_window_present ((GtkWindow *) playlistwin);
+    else
+        gtk_widget_hide (playlistwin);
+
+    button_set_active (mainwin_pl, 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 (void)
+{
+    bool show = aud_get_bool ("skins", "equalizer_visible");
+
+    if (show && gtk_widget_get_visible (mainwin))
+        gtk_window_present ((GtkWindow *) equalizerwin);
+    else
+        gtk_widget_hide (equalizerwin);
+
+    button_set_active (mainwin_eq, 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 (void)
+{
+    bool shaded = aud_get_bool ("skins", "player_shaded");
+
+    window_set_shaded (mainwin, shaded);
+
+    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);
+}
+
+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 (void)
+{
+    bool shaded = aud_get_bool ("skins", "playlist_shaded");
+
+    window_set_shaded (playlistwin, shaded);
+
+    int height = shaded ? MAINWIN_SHADED_HEIGHT : config.playlist_height;
+    window_set_size (playlistwin, config.playlist_width, height);
+
+    playlistwin_update ();
+}
+
+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 (void)
+{
+    bool shaded = aud_get_bool ("skins", "equalizer_shaded");
+
+    window_set_shaded (equalizerwin, shaded);
+    window_set_size (equalizerwin, 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 (void)
+{
+    config.scale = aud_get_bool ("skins", "double_size") ? 2 : 1;
+    skins_restart ();
+}
+
+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 (void)
+{
+    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);
+
+    ui_skinned_menurow_update (mainwin_menurow);
+}
+
+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 (void)
+{
+    bool sticky = aud_get_bool ("skins", "sticky");
+
+    if (sticky)
+    {
+        gtk_window_stick ((GtkWindow *) mainwin);
+        gtk_window_stick ((GtkWindow *) equalizerwin);
+        gtk_window_stick ((GtkWindow *) playlistwin);
+    }
+    else
+    {
+        gtk_window_unstick ((GtkWindow *) mainwin);
+        gtk_window_unstick ((GtkWindow *) equalizerwin);
+        gtk_window_unstick ((GtkWindow *) playlistwin);
+    }
+}
+
+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 (void)
+{
+    mainwin_update_song_info ();
+}
diff --git a/src/skins/view.h b/src/skins/view.h
index 8497c37b7de3..18de79c30f2f 100644
--- a/src/skins/view.h
+++ b/src/skins/view.h
@@ -22,32 +22,33 @@
 #ifndef SKINS_VIEW_H
 #define SKINS_VIEW_H
 
-#include <libaudcore/core.h>
+void view_show_player (bool show);
 
-void view_show_player (bool_t show);
-
-void view_set_show_playlist (bool_t show);
+void view_set_show_playlist (bool show);
 void view_apply_show_playlist (void);
 
-void view_set_show_equalizer (bool_t show);
+void view_set_show_equalizer (bool show);
 void view_apply_show_equalizer (void);
 
-void view_set_player_shaded (bool_t shaded);
+void view_set_player_shaded (bool shaded);
 void view_apply_player_shaded (void);
 
-void view_set_playlist_shaded (bool_t shaded);
+void view_set_playlist_shaded (bool shaded);
 void view_apply_playlist_shaded (void);
 
-void view_set_equalizer_shaded (bool_t shaded);
+void view_set_equalizer_shaded (bool shaded);
 void view_apply_equalizer_shaded (void);
 
-void view_set_on_top (bool_t on_top);
+void view_set_double_size (bool double_size);
+void view_apply_double_size (void);
+
+void view_set_on_top (bool on_top);
 void view_apply_on_top (void);
 
-void view_set_sticky (bool_t sticky);
+void view_set_sticky (bool sticky);
 void view_apply_sticky (void);
 
-void view_set_show_remaining (bool_t remaining);
+void view_set_show_remaining (bool remaining);
 void view_apply_show_remaining (void);
 
 #endif /* SKINS_VIEW_H */
diff --git a/src/sndfile/Makefile b/src/sndfile/Makefile
index 6d0f4700f015..8f28aae08ae5 100644
--- a/src/sndfile/Makefile
+++ b/src/sndfile/Makefile
@@ -2,12 +2,14 @@ include ../../extra.mk
 
 PLUGIN = sndfile${PLUGIN_SUFFIX}
 
-SRCS = plugin.c
+SRCS = plugin.cc
 
 include ../../buildsys.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${SNDFILE_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${SNDFILE_LIBS} -lm
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${SNDFILE_CFLAGS} -I../..
+LIBS += ${SNDFILE_LIBS} -lm
diff --git a/src/sndfile/plugin.c b/src/sndfile/plugin.c
deleted file mode 100644
index 468a7135b316..000000000000
--- a/src/sndfile/plugin.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*  Audacious - Cross-platform multimedia player
- *  Copyright (C) 2005-2011 Audacious development team
- *
- *  Based on the xmms_sndfile input plugin:
- *  Copyright (C) 2000, 2002 Erik de Castro Lopo
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/*
- * Rewritten 17-Feb-2007 (nenolod):
- *   - now uses conditional variables to ensure that sndfile mutex is
- *     entirely protected.
- *   - pausing works now
- *   - fixed some potential race conditions when dealing with NFS.
- *   - TITLE_LEN removed
- *
- * Re-cleaned up 09-Aug-2009 (ccr):
- *   - removed threading madness.
- *   - improved locking.
- *   - misc. cleanups.
- *
- * Play loop rewritten 14-Nov-2009 (jlindgren):
- *   - decode in floating point
- *   - drain audio buffer before closing
- *   - handle seeking/stopping while paused
- */
-
-#include <math.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <sndfile.h>
-
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-#include <libaudcore/audstrings.h>
-
-/* Virtual file access wrappers for libsndfile
- */
-static sf_count_t
-sf_get_filelen (void *user_data)
-{
-    return vfs_fsize (user_data);
-}
-
-static sf_count_t
-sf_vseek (sf_count_t offset, int whence, void *user_data)
-{
-    return vfs_fseek(user_data, offset, whence);
-}
-
-static sf_count_t
-sf_vread (void *ptr, sf_count_t count, void *user_data)
-{
-    return vfs_fread(ptr, 1, count, user_data);
-}
-
-static sf_count_t
-sf_vwrite (const void *ptr, sf_count_t count, void *user_data)
-{
-    return vfs_fwrite(ptr, 1, count, user_data);
-}
-
-static sf_count_t
-sf_tell (void *user_data)
-{
-    return vfs_ftell(user_data);
-}
-
-static SF_VIRTUAL_IO sf_virtual_io =
-{
-    sf_get_filelen,
-    sf_vseek,
-    sf_vread,
-    sf_vwrite,
-    sf_tell
-};
-
-static void copy_string (SNDFILE * sf, int sf_id, Tuple * tup, int tup_id)
-{
-    const char * str = sf_get_string (sf, sf_id);
-    if (str)
-        tuple_set_str (tup, tup_id, str);
-}
-
-static void copy_int (SNDFILE * sf, int sf_id, Tuple * tup, int tup_id)
-{
-    const char * str = sf_get_string (sf, sf_id);
-    if (str && atoi (str))
-        tuple_set_int (tup, tup_id, atoi (str));
-}
-
-static Tuple * get_song_tuple (const char * filename, VFSFile * file)
-{
-    SNDFILE *sndfile;
-    SF_INFO sfinfo;
-    const char *format, *subformat;
-    Tuple * ti;
-
-    sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, file);
-
-    if (sndfile == NULL)
-        return NULL;
-
-    ti = tuple_new_from_filename (filename);
-
-    /* I have no idea version of sndfile ALBUM, GENRE, and TRACKNUMBER were
-     * added in. -jlindgren */
-    copy_string (sndfile, SF_STR_TITLE, ti, FIELD_TITLE);
-    copy_string (sndfile, SF_STR_ARTIST, ti, FIELD_ARTIST);
-/*    copy_string (sndfile, SF_STR_ALBUM, ti, FIELD_ALBUM); */
-    copy_string (sndfile, SF_STR_COMMENT, ti, FIELD_COMMENT);
-/*    copy_string (sndfile, SF_STR_GENRE, ti, FIELD_GENRE); */
-    copy_int (sndfile, SF_STR_DATE, ti, FIELD_YEAR);
-/*    copy_int (sndfile, SF_STR_TRACKNUMBER, ti, FIELD_TRACK_NUMBER); */
-
-    sf_close (sndfile);
-
-    if (sfinfo.samplerate > 0)
-    {
-        tuple_set_int(ti, FIELD_LENGTH,
-        (int) ceil (1000.0 * sfinfo.frames / sfinfo.samplerate));
-    }
-
-    switch (sfinfo.format & SF_FORMAT_TYPEMASK)
-    {
-        case SF_FORMAT_WAV:
-        case SF_FORMAT_WAVEX:
-            format = "Microsoft WAV";
-            break;
-        case SF_FORMAT_AIFF:
-            format = "Apple/SGI AIFF";
-            break;
-        case SF_FORMAT_AU:
-            format = "Sun/NeXT AU";
-            break;
-        case SF_FORMAT_RAW:
-            format = "Raw PCM data";
-            break;
-        case SF_FORMAT_PAF:
-            format = "Ensoniq PARIS";
-            break;
-        case SF_FORMAT_SVX:
-            format = "Amiga IFF / SVX8 / SV16";
-            break;
-        case SF_FORMAT_NIST:
-            format = "Sphere NIST";
-            break;
-        case SF_FORMAT_VOC:
-            format = "Creative VOC";
-            break;
-        case SF_FORMAT_IRCAM:
-            format = "Berkeley/IRCAM/CARL";
-            break;
-        case SF_FORMAT_W64:
-            format = "Sonic Foundry's 64 bit RIFF/WAV";
-            break;
-        case SF_FORMAT_MAT4:
-            format = "Matlab (tm) V4.2 / GNU Octave 2.0";
-            break;
-        case SF_FORMAT_MAT5:
-            format = "Matlab (tm) V5.0 / GNU Octave 2.1";
-            break;
-        case SF_FORMAT_PVF:
-            format = "Portable Voice Format";
-            break;
-        case SF_FORMAT_XI:
-            format = "Fasttracker 2 Extended Instrument";
-            break;
-        case SF_FORMAT_HTK:
-            format = "HMM Tool Kit";
-            break;
-        case SF_FORMAT_SDS:
-            format = "Midi Sample Dump Standard";
-            break;
-        case SF_FORMAT_AVR:
-            format = "Audio Visual Research";
-            break;
-        case SF_FORMAT_SD2:
-            format = "Sound Designer 2";
-            break;
-        case SF_FORMAT_FLAC:
-            format = "Free Lossless Audio Codec";
-            break;
-        case SF_FORMAT_CAF:
-            format = "Core Audio File";
-            break;
-        default:
-            format = "Unknown sndfile";
-    }
-
-    switch (sfinfo.format & SF_FORMAT_SUBMASK)
-    {
-        case SF_FORMAT_PCM_S8:
-            subformat = "signed 8 bit";
-            break;
-        case SF_FORMAT_PCM_16:
-            subformat = "signed 16 bit";
-            break;
-        case SF_FORMAT_PCM_24:
-            subformat = "signed 24 bit";
-            break;
-        case SF_FORMAT_PCM_32:
-            subformat = "signed 32 bit";
-            break;
-        case SF_FORMAT_PCM_U8:
-            subformat = "unsigned 8 bit";
-            break;
-        case SF_FORMAT_FLOAT:
-            subformat = "32 bit float";
-            break;
-        case SF_FORMAT_DOUBLE:
-            subformat = "64 bit float";
-            break;
-        case SF_FORMAT_ULAW:
-            subformat = "U-Law";
-            break;
-        case SF_FORMAT_ALAW:
-            subformat = "A-Law";
-            break;
-        case SF_FORMAT_IMA_ADPCM:
-            subformat = "IMA ADPCM";
-            break;
-        case SF_FORMAT_MS_ADPCM:
-            subformat = "MS ADPCM";
-            break;
-        case SF_FORMAT_GSM610:
-            subformat = "GSM 6.10";
-            break;
-        case SF_FORMAT_VOX_ADPCM:
-            subformat = "Oki Dialogic ADPCM";
-            break;
-        case SF_FORMAT_G721_32:
-            subformat = "32kbs G721 ADPCM";
-            break;
-        case SF_FORMAT_G723_24:
-            subformat = "24kbs G723 ADPCM";
-            break;
-        case SF_FORMAT_G723_40:
-            subformat = "40kbs G723 ADPCM";
-            break;
-        case SF_FORMAT_DWVW_12:
-            subformat = "12 bit Delta Width Variable Word";
-            break;
-        case SF_FORMAT_DWVW_16:
-            subformat = "16 bit Delta Width Variable Word";
-            break;
-        case SF_FORMAT_DWVW_24:
-            subformat = "24 bit Delta Width Variable Word";
-            break;
-        case SF_FORMAT_DWVW_N:
-            subformat = "N bit Delta Width Variable Word";
-            break;
-        case SF_FORMAT_DPCM_8:
-            subformat = "8 bit differential PCM";
-            break;
-        case SF_FORMAT_DPCM_16:
-            subformat = "16 bit differential PCM";
-            break;
-        default:
-            subformat = NULL;
-    }
-
-    if (subformat != NULL)
-    {
-        SPRINTF (codec, "%s (%s)", format, subformat);
-        tuple_set_format (ti, codec, sfinfo.channels, sfinfo.samplerate, 0);
-    }
-    else
-        tuple_set_format (ti, format, sfinfo.channels, sfinfo.samplerate, 0);
-
-    return ti;
-}
-
-static bool_t play_start (const char * filename, VFSFile * file)
-{
-    if (file == NULL)
-        return FALSE;
-
-    SF_INFO sfinfo;
-    SNDFILE * sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo,
-     file);
-    if (sndfile == NULL)
-        return FALSE;
-
-    if (! aud_input_open_audio (FMT_FLOAT, sfinfo.samplerate,
-     sfinfo.channels))
-    {
-        sf_close (sndfile);
-        return FALSE;
-    }
-
-    int size = sfinfo.channels * (sfinfo.samplerate / 50);
-    float * buffer = g_new (float, size);
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_value = aud_input_check_seek ();
-        if (seek_value != -1)
-            sf_seek (sndfile, (int64_t) seek_value * sfinfo.samplerate / 1000, SEEK_SET);
-
-        int samples = sf_read_float (sndfile, buffer, size);
-        if (! samples)
-            break;
-
-        aud_input_write_audio (buffer, sizeof (float) * samples);
-    }
-
-    sf_close (sndfile);
-    g_free (buffer);
-
-    return TRUE;
-}
-
-static int
-is_our_file_from_vfs(const char *filename, VFSFile *fin)
-{
-    SNDFILE *tmp_sndfile;
-    SF_INFO tmp_sfinfo;
-
-    /* Have to open the file to see if libsndfile can handle it. */
-    tmp_sndfile = sf_open_virtual (&sf_virtual_io, SFM_READ, &tmp_sfinfo, fin);
-
-    if (!tmp_sndfile)
-        return FALSE;
-
-    /* It can so close file and return TRUE. */
-    sf_close (tmp_sndfile);
-    tmp_sndfile = NULL;
-
-    return TRUE;
-}
-
-const char plugin_about[] =
- N_("Based on the xmms_sndfile plugin:\n"
-    "Copyright (C) 2000, 2002 Erik de Castro Lopo\n\n"
-    "Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\n\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.");
-
-static const char *sndfile_fmts[] = { "aiff", "au", "raw", "wav", NULL };
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Sndfile Plugin"),
-    .domain = PACKAGE,
-    .about_text = plugin_about,
-    .play = play_start,
-    .probe_for_tuple = get_song_tuple,
-    .is_our_file_from_vfs = is_our_file_from_vfs,
-    .extensions = sndfile_fmts,
-
-    /* low priority fallback (but before ffaudio) */
-    .priority = 9,
-)
diff --git a/src/sndfile/plugin.cc b/src/sndfile/plugin.cc
new file mode 100644
index 000000000000..b050aa7d5707
--- /dev/null
+++ b/src/sndfile/plugin.cc
@@ -0,0 +1,351 @@
+/*  Audacious - Cross-platform multimedia player
+ *  Copyright (C) 2005-2011 Audacious development team
+ *
+ *  Based on the xmms_sndfile input plugin:
+ *  Copyright (C) 2000, 2002 Erik de Castro Lopo
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <sndfile.h>
+
+#define WANT_VFS_STDIO_COMPAT
+#include <libaudcore/plugin.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/audstrings.h>
+
+class SndfilePlugin : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("Sndfile Plugin"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo ()
+        .with_priority (9)  /* low priority fallback (but before ffaudio) */
+        .with_exts (exts);
+
+    constexpr SndfilePlugin () : InputPlugin (info, iinfo) {}
+
+    bool is_our_file (const char * filename, VFSFile & file);
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT SndfilePlugin aud_plugin_instance;
+
+/* Virtual file access wrappers for libsndfile
+ */
+static sf_count_t
+sf_get_filelen (void *user_data)
+{
+    return ((VFSFile *) user_data)->fsize ();
+}
+
+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));
+}
+
+static sf_count_t
+sf_vread (void *ptr, sf_count_t count, void *user_data)
+{
+    return ((VFSFile *) user_data)->fread (ptr, 1, count);
+}
+
+static sf_count_t
+sf_vwrite (const void *ptr, sf_count_t count, void *user_data)
+{
+    return ((VFSFile *) user_data)->fwrite (ptr, 1, count);
+}
+
+static sf_count_t
+sf_tell (void *user_data)
+{
+    return ((VFSFile *) user_data)->ftell ();
+}
+
+static SF_VIRTUAL_IO sf_virtual_io =
+{
+    sf_get_filelen,
+    sf_vseek,
+    sf_vread,
+    sf_vwrite,
+    sf_tell
+};
+
+static void copy_string (SNDFILE * sf, int sf_id, Tuple & tup, Tuple::Field field)
+{
+    const char * str = sf_get_string (sf, sf_id);
+    if (str)
+        tup.set_str (field, str);
+}
+
+static void copy_int (SNDFILE * sf, int sf_id, Tuple & tup, Tuple::Field field)
+{
+    const char * str = sf_get_string (sf, sf_id);
+    if (str && atoi (str))
+        tup.set_int (field, atoi (str));
+}
+
+Tuple SndfilePlugin::read_tuple (const char * filename, VFSFile & file)
+{
+    SNDFILE *sndfile;
+    SF_INFO sfinfo;
+    const char *format, *subformat;
+    Tuple ti;
+
+    sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, & file);
+
+    if (sndfile == nullptr)
+        return ti;
+
+    ti.set_filename (filename);
+
+    copy_string (sndfile, SF_STR_TITLE, ti, Tuple::Title);
+    copy_string (sndfile, SF_STR_ARTIST, ti, Tuple::Artist);
+    copy_string (sndfile, SF_STR_ALBUM, ti, Tuple::Album);
+    copy_string (sndfile, SF_STR_COMMENT, ti, Tuple::Comment);
+    copy_string (sndfile, SF_STR_GENRE, ti, Tuple::Genre);
+    copy_int (sndfile, SF_STR_DATE, ti, Tuple::Year);
+    copy_int (sndfile, SF_STR_TRACKNUMBER, ti, Tuple::Track);
+
+    sf_close (sndfile);
+
+    if (sfinfo.samplerate > 0)
+        ti.set_int (Tuple::Length, ceil (1000.0 * sfinfo.frames / sfinfo.samplerate));
+
+    switch (sfinfo.format & SF_FORMAT_TYPEMASK)
+    {
+        case SF_FORMAT_WAV:
+        case SF_FORMAT_WAVEX:
+            format = "Microsoft WAV";
+            break;
+        case SF_FORMAT_AIFF:
+            format = "Apple/SGI AIFF";
+            break;
+        case SF_FORMAT_AU:
+            format = "Sun/NeXT AU";
+            break;
+        case SF_FORMAT_RAW:
+            format = "Raw PCM data";
+            break;
+        case SF_FORMAT_PAF:
+            format = "Ensoniq PARIS";
+            break;
+        case SF_FORMAT_SVX:
+            format = "Amiga IFF / SVX8 / SV16";
+            break;
+        case SF_FORMAT_NIST:
+            format = "Sphere NIST";
+            break;
+        case SF_FORMAT_VOC:
+            format = "Creative VOC";
+            break;
+        case SF_FORMAT_IRCAM:
+            format = "Berkeley/IRCAM/CARL";
+            break;
+        case SF_FORMAT_W64:
+            format = "Sonic Foundry's 64 bit RIFF/WAV";
+            break;
+        case SF_FORMAT_MAT4:
+            format = "Matlab (tm) V4.2 / GNU Octave 2.0";
+            break;
+        case SF_FORMAT_MAT5:
+            format = "Matlab (tm) V5.0 / GNU Octave 2.1";
+            break;
+        case SF_FORMAT_PVF:
+            format = "Portable Voice Format";
+            break;
+        case SF_FORMAT_XI:
+            format = "Fasttracker 2 Extended Instrument";
+            break;
+        case SF_FORMAT_HTK:
+            format = "HMM Tool Kit";
+            break;
+        case SF_FORMAT_SDS:
+            format = "Midi Sample Dump Standard";
+            break;
+        case SF_FORMAT_AVR:
+            format = "Audio Visual Research";
+            break;
+        case SF_FORMAT_SD2:
+            format = "Sound Designer 2";
+            break;
+        case SF_FORMAT_FLAC:
+            format = "Free Lossless Audio Codec";
+            break;
+        case SF_FORMAT_CAF:
+            format = "Core Audio File";
+            break;
+        default:
+            format = "Unknown sndfile";
+    }
+
+    switch (sfinfo.format & SF_FORMAT_SUBMASK)
+    {
+        case SF_FORMAT_PCM_S8:
+            subformat = "signed 8 bit";
+            break;
+        case SF_FORMAT_PCM_16:
+            subformat = "signed 16 bit";
+            break;
+        case SF_FORMAT_PCM_24:
+            subformat = "signed 24 bit";
+            break;
+        case SF_FORMAT_PCM_32:
+            subformat = "signed 32 bit";
+            break;
+        case SF_FORMAT_PCM_U8:
+            subformat = "unsigned 8 bit";
+            break;
+        case SF_FORMAT_FLOAT:
+            subformat = "32 bit float";
+            break;
+        case SF_FORMAT_DOUBLE:
+            subformat = "64 bit float";
+            break;
+        case SF_FORMAT_ULAW:
+            subformat = "U-Law";
+            break;
+        case SF_FORMAT_ALAW:
+            subformat = "A-Law";
+            break;
+        case SF_FORMAT_IMA_ADPCM:
+            subformat = "IMA ADPCM";
+            break;
+        case SF_FORMAT_MS_ADPCM:
+            subformat = "MS ADPCM";
+            break;
+        case SF_FORMAT_GSM610:
+            subformat = "GSM 6.10";
+            break;
+        case SF_FORMAT_VOX_ADPCM:
+            subformat = "Oki Dialogic ADPCM";
+            break;
+        case SF_FORMAT_G721_32:
+            subformat = "32kbs G721 ADPCM";
+            break;
+        case SF_FORMAT_G723_24:
+            subformat = "24kbs G723 ADPCM";
+            break;
+        case SF_FORMAT_G723_40:
+            subformat = "40kbs G723 ADPCM";
+            break;
+        case SF_FORMAT_DWVW_12:
+            subformat = "12 bit Delta Width Variable Word";
+            break;
+        case SF_FORMAT_DWVW_16:
+            subformat = "16 bit Delta Width Variable Word";
+            break;
+        case SF_FORMAT_DWVW_24:
+            subformat = "24 bit Delta Width Variable Word";
+            break;
+        case SF_FORMAT_DWVW_N:
+            subformat = "N bit Delta Width Variable Word";
+            break;
+        case SF_FORMAT_DPCM_8:
+            subformat = "8 bit differential PCM";
+            break;
+        case SF_FORMAT_DPCM_16:
+            subformat = "16 bit differential PCM";
+            break;
+        default:
+            subformat = nullptr;
+    }
+
+    if (subformat != nullptr)
+        ti.set_format (str_printf ("%s (%s)", format, subformat),
+         sfinfo.channels, sfinfo.samplerate, 0);
+    else
+        ti.set_format (format, sfinfo.channels, sfinfo.samplerate, 0);
+
+    return ti;
+}
+
+bool SndfilePlugin::play (const char * filename, VFSFile & file)
+{
+    SF_INFO sfinfo;
+    SNDFILE * sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, & file);
+    if (sndfile == nullptr)
+        return false;
+
+    open_audio (FMT_FLOAT, sfinfo.samplerate, sfinfo.channels);
+
+    Index<float> buffer;
+    buffer.resize (sfinfo.channels * (sfinfo.samplerate / 50));
+
+    while (! check_stop ())
+    {
+        int seek_value = check_seek ();
+        if (seek_value != -1)
+            sf_seek (sndfile, (int64_t) seek_value * sfinfo.samplerate / 1000, SEEK_SET);
+
+        int samples = sf_read_float (sndfile, buffer.begin (), buffer.len ());
+        if (! samples)
+            break;
+
+        write_audio (buffer.begin (), sizeof (float) * samples);
+    }
+
+    sf_close (sndfile);
+
+    return true;
+}
+
+bool SndfilePlugin::is_our_file (const char * filename, VFSFile & file)
+{
+    SNDFILE *tmp_sndfile;
+    SF_INFO tmp_sfinfo;
+
+    /* 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);
+
+    if (!tmp_sndfile)
+        return false;
+
+    /* It can so close file and return true. */
+    sf_close (tmp_sndfile);
+    tmp_sndfile = nullptr;
+
+    return true;
+}
+
+const char SndfilePlugin::about[] =
+ N_("Based on the xmms_sndfile plugin:\n"
+    "Copyright (C) 2000, 2002 Erik de Castro Lopo\n\n"
+    "Adapted for Audacious by Tony Vroon <chainsaw at gentoo.org>\n\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.");
+
+const char * const SndfilePlugin::exts[] = { "aiff", "au", "raw", "wav", nullptr };
diff --git a/src/sndio-ng/Makefile b/src/sndio-ng/Makefile
new file mode 100644
index 000000000000..bc7bcd8396b6
--- /dev/null
+++ b/src/sndio-ng/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = sndio-ng${PLUGIN_SUFFIX}
+
+SRCS = sndio.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
+
+LD = ${CXX}
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += ${SNDIO_LIBS}
diff --git a/src/sndio-ng/sndio.cc b/src/sndio-ng/sndio.cc
new file mode 100644
index 000000000000..9b1d841d817f
--- /dev/null
+++ b/src/sndio-ng/sndio.cc
@@ -0,0 +1,376 @@
+/*
+ * Sndio Output Plugin for Audacious
+ * Copyright 2014 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 <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/runtime.h>
+
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <sndio.h>
+
+class SndioPlugin : public OutputPlugin
+{
+public:
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Sndio Output"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr SndioPlugin () : OutputPlugin (info, 5) {}
+
+    bool init ();
+
+    StereoVolume get_volume ();
+    void set_volume (StereoVolume v);
+
+    bool open_audio (int format, int rate, int channels);
+    void close_audio ();
+
+    void period_wait ();
+    int write_audio (const void * data, int size);
+    void drain ();
+
+    int get_delay ();
+
+    void pause (bool pause);
+    void flush ();
+
+private:
+    bool poll_locked ();
+
+    static void volume_cb (void *, unsigned int vol);
+    static void move_cb (void * arg, int delta);
+
+    sio_hdl * m_handle = nullptr;
+
+    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;
+
+    pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
+    pthread_cond_t m_cond = PTHREAD_COND_INITIALIZER;
+};
+
+EXPORT SndioPlugin aud_plugin_instance;
+
+const char * const SndioPlugin::defaults[] = {
+    "save_volume", "FALSE",
+    "volume", "100",
+    nullptr
+};
+
+const PreferencesWidget SndioPlugin::widgets[] = {
+    WidgetEntry (N_("Device (blank for default):"),
+        WidgetString ("sndio", "device")),
+    WidgetCheck (N_("Save and restore volume:"),
+        WidgetBool ("sndio", "save_volume"))
+};
+
+const PluginPreferences SndioPlugin::prefs = {{widgets}};
+
+bool SndioPlugin::init ()
+{
+    aud_config_set_defaults ("sndio", defaults);
+    return true;
+}
+
+void SndioPlugin::volume_cb (void *, unsigned int vol)
+{
+    aud_set_int ("sndio", "volume", aud::rescale ((int) vol, SIO_MAXVOL, 100));
+}
+
+void SndioPlugin::set_volume (StereoVolume v)
+{
+    int vol = aud::max (v.left, v.right);
+    aud_set_int ("sndio", "volume", vol);
+
+    pthread_mutex_lock (& m_mutex);
+
+    if (m_handle)
+        sio_setvol (m_handle, aud::rescale (vol, 100, SIO_MAXVOL));
+
+    pthread_mutex_unlock (& m_mutex);
+}
+
+StereoVolume SndioPlugin::get_volume ()
+{
+    int vol = aud_get_int ("sndio", "volume");
+    return {vol, vol};
+}
+
+void SndioPlugin::move_cb (void * arg, int delta)
+{
+    auto me = (SndioPlugin *) arg;
+
+    me->m_frames_buffered -= delta;
+    gettimeofday (& me->m_last_write_time, nullptr);
+
+    pthread_cond_broadcast (& me->m_cond);
+}
+
+struct FormatData {
+    int format;
+    int bits, bytes;
+    bool sign, le;
+};
+
+static const FormatData format_table[] = {
+    {FMT_S8, 8, 1, true, false},
+    {FMT_U8, 8, 1, false, false},
+    {FMT_S16_LE, 16, 2, true, true},
+    {FMT_S16_BE, 16, 2, true, false},
+    {FMT_U16_LE, 16, 2, false, true},
+    {FMT_U16_BE, 16, 2, false, false},
+    {FMT_S24_LE, 24, 4, true, true},
+    {FMT_S24_BE, 24, 4, true, false},
+    {FMT_U24_LE, 24, 4, false, true},
+    {FMT_U24_BE, 24, 4, false, false},
+    {FMT_S32_LE, 32, 4, true, true},
+    {FMT_S32_BE, 32, 4, true, false},
+    {FMT_U32_LE, 32, 4, false, true},
+    {FMT_U32_BE, 32, 4, false, false},
+};
+
+bool SndioPlugin::open_audio (int format, int rate, int channels)
+{
+    const FormatData * fdata = nullptr;
+
+    for (const FormatData & f : format_table)
+    {
+        if (f.format == format)
+            fdata = & f;
+    }
+
+    if (! fdata)
+    {
+        aud_ui_show_error (str_printf (_("Sndio error: Unsupported audio format (%d)"), format));
+        return false;
+    }
+
+    String device = aud_get_str ("sndio", "device");
+    const char * device2 = device[0] ? (const char *) device : SIO_DEVANY;
+
+    m_handle = sio_open (device2, SIO_PLAY, true);
+
+    if (! m_handle)
+    {
+        aud_ui_show_error (_("Sndio error: sio_open() failed"));
+        return false;
+    }
+
+    m_rate = rate;
+    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;
+
+    int buffer_ms = aud_get_int (nullptr, "output_buffer_size");
+
+    sio_par par;
+    sio_initpar (& par);
+
+    par.bits = fdata->bits;
+    par.bps = fdata->bytes;
+    par.sig = fdata->sign;
+    par.le = fdata->le;
+    par.msb = false;
+    par.pchan = channels;
+    par.rate = rate;
+    par.bufsz = aud::rescale (buffer_ms, 1000, rate);
+    par.xrun = SIO_IGNORE;
+
+    if (! sio_setpar (m_handle, & par))
+    {
+        aud_ui_show_error (_("Sndio error: sio_setpar() failed"));
+        goto fail;
+    }
+
+    if (aud_get_bool ("sndio", "save_volume"))
+        set_volume (get_volume ());
+
+    sio_onvol (m_handle, volume_cb, nullptr);
+    sio_onmove (m_handle, move_cb, this);
+
+    if (! sio_start (m_handle))
+    {
+        aud_ui_show_error (_("Sndio error: sio_start() failed"));
+        goto fail;
+    }
+
+    return true;
+
+fail:
+    sio_close (m_handle);
+    m_handle = nullptr;
+    return false;
+}
+
+void SndioPlugin::close_audio ()
+{
+    sio_close (m_handle);
+    m_handle = nullptr;
+}
+
+bool SndioPlugin::poll_locked ()
+{
+    bool success = false;
+    pollfd * fds = nullptr;
+    int nfds, old_flush_count;
+
+    nfds = sio_nfds (m_handle);
+    if (nfds < 1)
+        goto fail;
+
+    fds = new pollfd[nfds];
+
+    nfds = sio_pollfd (m_handle, fds, POLLOUT);
+    if (nfds < 1)
+        goto fail;
+
+    old_flush_count = m_flush_count;
+
+    pthread_mutex_unlock (& m_mutex);
+
+    if (poll (fds, nfds, -1) < 0)
+        AUDERR ("poll() failed: %s\n", strerror (errno));
+    else
+        success = true;
+
+    pthread_mutex_lock (& m_mutex);
+
+    if (success && m_flush_count == old_flush_count)
+        sio_revents (m_handle, fds);
+
+fail:
+    delete[] fds;
+    return success;
+}
+
+void SndioPlugin::period_wait ()
+{
+    pthread_mutex_lock (& m_mutex);
+
+    if (m_paused || sio_eof (m_handle) || ! poll_locked ())
+        pthread_cond_wait (& m_cond, & m_mutex);
+
+    pthread_mutex_unlock (& m_mutex);
+}
+
+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;
+    }
+
+    pthread_mutex_unlock (& m_mutex);
+    return len;
+}
+
+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};
+
+        pthread_mutex_unlock (& m_mutex);
+        nanosleep (& delay, nullptr);
+        pthread_mutex_lock (& m_mutex);
+
+        poll_locked ();
+    }
+
+    pthread_mutex_unlock (& m_mutex);
+}
+
+int SndioPlugin::get_delay ()
+{
+    auto timediff = [] (const timeval & a, const timeval & b) -> int64_t
+        { return 1000 * (int64_t) (b.tv_sec - a.tv_sec) + (b.tv_usec - a.tv_usec) / 1000; };
+
+    pthread_mutex_lock (& m_mutex);
+
+    int delay = aud::rescale (m_frames_buffered, m_rate, 1000);
+
+    if (m_last_write_time.tv_sec)
+    {
+        timeval now;
+        gettimeofday (& now, nullptr);
+        delay = aud::max (delay - timediff (m_last_write_time, now), (int64_t) 0);
+    }
+
+    pthread_mutex_unlock (& m_mutex);
+    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);
+
+    sio_stop (m_handle);
+
+    m_frames_buffered = 0;
+    m_last_write_time = timeval ();
+    m_flush_count ++;
+
+    if (! sio_start (m_handle))
+        AUDERR ("sio_start() failed\n");
+
+    pthread_cond_broadcast (& m_cond);
+    pthread_mutex_unlock (& m_mutex);
+}
diff --git a/src/sndio/Makefile b/src/sndio/Makefile
deleted file mode 100644
index 0623484b01e8..000000000000
--- a/src/sndio/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-PLUGIN = sndio${PLUGIN_SUFFIX}
-
-SRCS =	sndio.c
-
-include ../../buildsys.mk
-include ../../extra.mk
-
-plugindir := ${plugindir}/${OUTPUT_PLUGIN_DIR}
-
-CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${GLIB_LIBS} ${SNDIO_LIBS}
diff --git a/src/sndio/sndio.c b/src/sndio/sndio.c
deleted file mode 100644
index 7246f26a1931..000000000000
--- a/src/sndio/sndio.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2008, 2009 Thomas Pfaff <tpfaff at tp76.info>
- * Copyright (c) 2012 Alexandre Ratchov <alex at caoua.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <errno.h>
-#include <poll.h>
-#include <pthread.h>
-#include <sndio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <audacious/plugin.h>
-#include <audacious/misc.h>
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-/*
- * minimum output buffer size in milliseconds
- */
-#define BUFFER_SIZE_MIN	250
-
-static int get_volume(void) { return aud_get_int("sndio", "volume"); }
-static void set_volume(int vol) { aud_set_int("sndio", "volume", vol); }
-
-bool_t	sndio_init(void);
-void	sndio_about(void);
-void	sndio_configure(void);
-void	sndio_get_volume(int *, int *);
-void	sndio_set_volume(int, int);
-bool_t	sndio_open(int, int, int);
-void	sndio_close(void);
-int	sndio_buffer_free(void);
-void    sndio_period_wait(void);
-void	sndio_write(void *, int);
-void	sndio_pause(bool_t);
-void	sndio_flush(int);
-int	sndio_output_time(void);
-
-void	onmove_cb(void *, int);
-void	onvol_cb(void *, unsigned);
-
-void	configure_win_ok_cb(GtkWidget *, gpointer);
-
-static struct sio_par par;
-static struct sio_hdl *hdl;
-static long long rdpos;
-static long long wrpos;
-static int paused, restarted;
-static int pause_pending, flush_pending, volume_pending;
-static int bytes_per_sec;
-static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
-
-static GtkWidget *configure_win;
-static GtkWidget *adevice_entry;
-
-AUD_OUTPUT_PLUGIN
-(
-	.name = "sndio",
-	.init = sndio_init,
-	.about = sndio_about,
-	.configure = sndio_configure,
-	.probe_priority = 2,
-	.get_volume = sndio_get_volume,
-	.set_volume = sndio_set_volume,
-	.open_audio = sndio_open,
-	.write_audio = sndio_write,
-	.close_audio = sndio_close,
-	.buffer_free = sndio_buffer_free,
-	.period_wait = sndio_period_wait,
-	.flush = sndio_flush,
-	.pause = sndio_pause,
-	.output_time = sndio_output_time
-)
-
-static struct fmt_to_par {
-	int fmt, bits, sig, le;
-} fmt_to_par[] = {
-	{FMT_S8,      8, 1, 0}, {FMT_U8,      8, 0, 0},
-	{FMT_S16_LE, 16, 1, 1}, {FMT_S16_BE, 16, 1, 0},
-	{FMT_U16_LE, 16, 0, 1},	{FMT_U16_BE, 16, 0, 0},
-	{FMT_S24_LE, 24, 1, 1},	{FMT_S24_BE, 24, 1, 0},
-	{FMT_U24_LE, 24, 0, 1},	{FMT_U24_BE, 24, 0, 0},
-	{FMT_S32_LE, 32, 1, 1},	{FMT_S32_BE, 32, 1, 0},
-	{FMT_U32_LE, 32, 0, 1},	{FMT_U32_BE, 32, 0, 0}
-};
-
-static const gchar * const sndio_defaults[] = {
-	"volume", "100",
-	NULL,
-};
-
-static void
-reset(void)
-{
-	if (!restarted) {
-		restarted = 1;
-		sio_stop(hdl);
-		sio_start(hdl);
-		rdpos = wrpos;
-	}
-}
-
-static void
-wait_ready(void)
-{
-	int n;
-	struct pollfd pfds[16];
-
-	if (volume_pending) {
-		sio_setvol(hdl, get_volume() * SIO_MAXVOL / 100);
-		volume_pending = 0;
-	}
-	if (flush_pending) {
-		reset();
-		flush_pending = 0;
-	}
-	if (pause_pending) {
-		if (paused)
-			reset();
-		pause_pending = 0;
-	}
-	if (paused) {
-		pthread_mutex_unlock(&mtx);
-		usleep(20000);
-		pthread_mutex_lock(&mtx);
-		return;
-	}
-	n = sio_pollfd(hdl, pfds, POLLOUT);
-	if (n != 0) {
-		pthread_mutex_unlock(&mtx);
-		while (poll(pfds, n, -1) < 0) {
-			if (errno != EINTR) {
-				perror("poll");
-				exit(1);
-			}
-		}
-		pthread_mutex_lock(&mtx);
-	}
-	(void)sio_revents(hdl, pfds);
-}
-
-bool_t
-sndio_init(void)
-{
-	aud_config_set_defaults("sndio", sndio_defaults);
-
-	return (1);
-}
-
-void
-sndio_about(void)
-{
-	static GtkWidget *about = NULL;
-
-	audgui_simple_message(&about, GTK_MESSAGE_INFO,
-	    _("About Sndio Output Plugin"),
-	    _("Sndio Output Plugin\n\n"
-	    "Written by Thomas Pfaff <tpfaff at tp76.info>\n"));
-}
-
-void
-sndio_get_volume(int *l, int *r)
-{
-	*l = *r = get_volume();
-}
-
-void
-sndio_set_volume(int l, int r)
-{
-	/* Ignore balance control, so use unattenuated channel. */
-	pthread_mutex_lock(&mtx);
-	set_volume(MAX(l, r));
-	volume_pending = 1;
-	pthread_mutex_unlock(&mtx);
-}
-
-bool_t
-sndio_open(int fmt, int rate, int nch)
-{
-	int i;
-	struct sio_par askpar;
-	GtkWidget *dialog = NULL;
-	unsigned buffer_size;
-
-	char *audiodev = aud_get_str("sndio", "audiodev");
-
-	hdl = sio_open(strlen(audiodev) > 0 ? audiodev : NULL, SIO_PLAY, 1);
-	if (!hdl) {
-		g_warning("failed to open audio device %s", audiodev);
-		free(audiodev);
-		return (0);
-	}
-
-	str_unref(audiodev);
-
-	sio_initpar(&askpar);
-	for (i = 0; ; i++) {
-		if (i == ARRAY_LEN(fmt_to_par)) {
-			g_warning("unknown format %d requested", fmt);
-			sndio_close();
-			return 0;
-		}
-		if (fmt_to_par[i].fmt == fmt)
-			break;
-	}
-	askpar.bits = fmt_to_par[i].bits;
-	askpar.bps = SIO_BPS(askpar.bits);
-	askpar.sig = fmt_to_par[i].sig;
-	if (askpar.bits > 8)
-		askpar.le = fmt_to_par[i].le;
-	if (askpar.bits < askpar.bps * 8)
-		askpar.msb = 0;
-	askpar.pchan = nch;
-	askpar.rate = rate;
-	buffer_size = aud_get_int(NULL, "output_buffer_size");
-	if (buffer_size < BUFFER_SIZE_MIN)
-		buffer_size = BUFFER_SIZE_MIN;
-	askpar.appbufsz = buffer_size * rate / 1000;
-	if (!sio_setpar(hdl, &askpar) || !sio_getpar(hdl, &par)) {
-		g_warning("failed to set parameters");
-		sndio_close();
-		return (0);
-	}
-	if ((par.bps > 1 && par.le != askpar.le) ||
-	    (par.bits < par.bps * 8 && par.msb) ||
-	    par.bps != askpar.bps ||
-	    par.sig != askpar.sig ||
-	    par.pchan != askpar.pchan ||
-            par.rate != askpar.rate) {
-		g_warning("parameters not supported by the audio device");
-		audgui_simple_message(&dialog, GTK_MESSAGE_INFO,
-		    _("Unsupported format"),
-		    _("A format not supported by the audio device "
-		    "was requested.\n\n"
-		    "Please try again with the sndiod(1) server running."));
-		sndio_close();
-		return (0);
-	}
-	rdpos = 0;
-	wrpos = 0;
-	sio_onmove(hdl, onmove_cb, NULL);
-	sio_onvol(hdl, onvol_cb, NULL);
-	sio_setvol(hdl, get_volume() * SIO_MAXVOL / 100);
-	if (!sio_start(hdl)) {
-		g_warning("failed to start audio device");
-		sndio_close();
-		return (0);
-	}
-	pause_pending = flush_pending = volume_pending = 0;
-	bytes_per_sec = par.bps * par.pchan * par.rate;
-	restarted = 1;
-	paused = 0;
-	return (1);
-}
-
-void
-sndio_write(void *ptr, int length)
-{
-	unsigned n;
-
-	pthread_mutex_lock(&mtx);
-	for (;;) {
-		if (paused)
-			break;
-		restarted = 0;
-		n = sio_write(hdl, ptr, length);
-		if (n == 0 && sio_eof(hdl))
-			return;
-		wrpos += n;
-		length -= n;
-		ptr = (char *)ptr + n;
-		if (length == 0)
-			break;
-		wait_ready();
-	}
-	pthread_mutex_unlock(&mtx);
-}
-
-void
-sndio_close(void)
-{
-	if (!hdl)
-		return;
-	sio_close(hdl);
-	hdl = NULL;
-}
-
-int
-sndio_buffer_free(void)
-{
-	return paused ? 0 : par.round * par.pchan * par.bps;
-}
-
-void
-sndio_period_wait(void)
-{
-	pthread_mutex_lock(&mtx);
-	wait_ready();
-	pthread_mutex_unlock(&mtx);
-}
-
-void
-sndio_flush(int time)
-{
-	pthread_mutex_lock(&mtx);
-	rdpos = wrpos = (long long)time * bytes_per_sec / 1000;
-	flush_pending = 1;
-	pthread_mutex_unlock(&mtx);
-}
-
-void
-sndio_pause(bool_t flag)
-{
-	pthread_mutex_lock(&mtx);
-	paused = flag;
-	pause_pending = 1;
-	pthread_mutex_unlock(&mtx);
-}
-
-int
-sndio_output_time(void)
-{
-	int time;
-
-	pthread_mutex_lock(&mtx);
-	time = rdpos * 1000 / bytes_per_sec;
-	pthread_mutex_unlock(&mtx);
-	return time;
-}
-
-void
-onmove_cb(void *addr, int delta)
-{
-	rdpos += delta * (int)(par.bps * par.pchan);
-}
-
-void
-onvol_cb(void *addr, unsigned ctl)
-{
-	/* Update volume only if it actually changed */
-	if (ctl != get_volume() * SIO_MAXVOL / 100)
-		set_volume(ctl * 100 / SIO_MAXVOL);
-}
-
-void
-configure_win_ok_cb(GtkWidget *w, gpointer data)
-{
-	aud_set_str("sndio", "audiodev", gtk_entry_get_text(GTK_ENTRY(adevice_entry)));
-	gtk_widget_destroy(configure_win);
-}
-
-void
-sndio_configure(void)
-{
-	GtkWidget *vbox;
-	GtkWidget *adevice_frame, *adevice_text, *adevice_vbox;
-	GtkWidget *bbox, *ok, *cancel;
-
-	if (configure_win) {
-		gtk_window_present(GTK_WINDOW(configure_win));
-		return;
-	}
-
-	configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-	g_signal_connect(configure_win, "destroy",
-	    G_CALLBACK(gtk_widget_destroyed), &configure_win);
-
-	gtk_window_set_title(GTK_WINDOW(configure_win), _("sndio device"));
-	gtk_window_set_resizable(GTK_WINDOW(configure_win), FALSE);
-	gtk_window_set_position(GTK_WINDOW(configure_win), GTK_WIN_POS_MOUSE);
-	gtk_container_set_border_width(GTK_CONTAINER(configure_win), 10);
-
-	vbox = gtk_vbox_new(FALSE, 5);
-	gtk_container_add(GTK_CONTAINER(configure_win), vbox);
-	gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
-
-	adevice_frame = gtk_frame_new(_("Audio device:"));
-	gtk_box_pack_start(GTK_BOX(vbox), adevice_frame, FALSE, FALSE, 0);
-
-	adevice_vbox = gtk_vbox_new(FALSE, 5);
-	gtk_container_set_border_width(GTK_CONTAINER(adevice_vbox), 5);
-	gtk_container_add(GTK_CONTAINER(adevice_frame), adevice_vbox);
-
-	adevice_text = gtk_label_new(_("(empty means default)"));
-	gtk_box_pack_start(GTK_BOX(adevice_vbox), adevice_text, TRUE, TRUE, 0);
-
-	char *audiodev = aud_get_str("sndio", "audiodev");
-
-	adevice_entry = gtk_entry_new();
-	gtk_entry_set_text(GTK_ENTRY(adevice_entry), audiodev);
-	gtk_box_pack_start(GTK_BOX(adevice_vbox), adevice_entry, TRUE, TRUE, 0);
-
-	str_unref(audiodev);
-
-	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);
-
-	ok = gtk_button_new_with_label(_("OK"));
-	g_signal_connect(ok, "clicked",
-	    G_CALLBACK(configure_win_ok_cb), NULL);
-
-	gtk_widget_set_can_default(ok, TRUE);
-	gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
-	gtk_widget_grab_default(ok);
-
-	cancel = gtk_button_new_with_label(_("Cancel"));
-	g_signal_connect(cancel, "clicked",
-	    G_CALLBACK(gtk_widget_destroy), &configure_win);
-
-	gtk_widget_set_can_default(cancel, TRUE);
-	gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
-
-	gtk_widget_show_all(configure_win);
-}
diff --git a/src/song-info-qt/Makefile b/src/song-info-qt/Makefile
new file mode 100644
index 000000000000..415e32201e28
--- /dev/null
+++ b/src/song-info-qt/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = song-info-qt${PLUGIN_SUFFIX}
+
+SRCS = song-info.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/song-info-qt/song-info.cc b/src/song-info-qt/song-info.cc
new file mode 100644
index 000000000000..8b2693374ba5
--- /dev/null
+++ b/src/song-info-qt/song-info.cc
@@ -0,0 +1,99 @@
+/*
+ * song-info.cc
+ * Copyright 2014 William Pitcock
+ *
+ * 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 <libaudcore/drct.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/playlist.h>
+#include <libaudcore/plugin.h>
+
+#include <libaudqt/libaudqt.h>
+#include <libaudqt/info-widget.h>
+
+class SongInfo : public GeneralPlugin {
+public:
+    static constexpr PluginInfo info = {
+        N_("Song Info (Qt)"),
+        PACKAGE
+    };
+
+    constexpr SongInfo () : GeneralPlugin (info, false) {}
+    void * get_qt_widget ();
+
+private:
+    static void update (void * unused, audqt::InfoWidget * widget);
+    static void clear (void * unused, audqt::InfoWidget * widget);
+    static void widget_cleanup (QObject * widget);
+};
+
+void SongInfo::update (void * unused, audqt::InfoWidget * widget)
+{
+    if (! aud_drct_get_playing ())
+        return;
+
+    if (! widget)
+        return;
+
+    int playlist = aud_playlist_get_playing ();
+
+    if (playlist == -1)
+        playlist = aud_playlist_get_active ();
+
+    int position = aud_playlist_get_position (playlist);
+    if (position == -1)
+        return;
+
+    String filename = aud_playlist_entry_get_filename (playlist, position);
+    if (! filename)
+        return;
+
+    PluginHandle * decoder = aud_playlist_entry_get_decoder (playlist, position);
+    if (! decoder)
+        return;
+
+    Tuple tuple = aud_playlist_entry_get_tuple (playlist, position);
+    if (tuple)
+        widget->fillInfo (playlist, position, filename, tuple, decoder, false);
+}
+
+void SongInfo::clear (void * unused, audqt::InfoWidget * widget)
+{
+    if (! widget)
+        return;
+}
+
+void SongInfo::widget_cleanup (QObject * widget)
+{
+    hook_dissociate ("playback begin", (HookFunction) update, widget);
+    hook_dissociate ("playback stop", (HookFunction) clear, widget);
+}
+
+void * SongInfo::get_qt_widget ()
+{
+    audqt::InfoWidget * widget = new audqt::InfoWidget;
+
+    QObject::connect (widget, &QObject::destroyed, widget_cleanup);
+
+    hook_associate ("playback begin", (HookFunction) update, widget);
+    hook_associate ("playback stop", (HookFunction) clear, widget);
+
+    return widget;
+}
+
+EXPORT SongInfo aud_plugin_instance;
diff --git a/src/song_change/Makefile b/src/song_change/Makefile
index b151bdf51713..c3b3b3a28825 100644
--- a/src/song_change/Makefile
+++ b/src/song_change/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = song_change${PLUGIN_SUFFIX}
 
-SRCS = formatter.c song_change.c
+SRCS = formatter.cc song_change.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS}  -I../..
 LIBS += ${GTK_LIBS} ${GLIB_LIBS}
diff --git a/src/song_change/formatter.c b/src/song_change/formatter.c
deleted file mode 100644
index c55d159954a8..000000000000
--- a/src/song_change/formatter.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*  Audacious
- *  Copyright (C) 2005-2007  Audacious team
- *
- *  XMMS - Cross-platform multimedia player
- *  Copyright (C) 1998-2003  Peter Alm, Mikael Alm, Olle Hallnas,
- *                           Thomas Nilsson and 4Front Technologies
- *  Copyright (C) 1999-2003  Haavard Kvaalen
- *
- *  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 <glib.h>
-#include <string.h>
-#include "formatter.h"
-
-Formatter *
-formatter_new(void)
-{
-    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 guchar id, const gchar *value)
-{
-    formatter_dissociate(formatter, id);
-    formatter->values[id] = g_strdup(value);
-}
-
-void
-formatter_dissociate(Formatter * formatter, const guchar id)
-{
-    if (formatter->values[id])
-        g_free(formatter->values[id]);
-    formatter->values[id] = 0;
-}
-
-gchar *
-formatter_format(Formatter * formatter, gchar *format)
-{
-    gchar *p, *q, *buffer;
-    gint len;
-
-    for (p = format, len = 0; *p; p++)
-        if (*p == '%') {
-            if (formatter->values[(int) *++p])
-                len += strlen(formatter->values[(int) *p]);
-            else if (!*p) {
-                len += 1;
-                p--;
-            }
-            else
-                len += 2;
-        }
-        else
-            len++;
-    buffer = g_malloc(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);
-            }
-            else {
-                *q++ = '%';
-                if (*p != '\0')
-                    *q++ = *p;
-                else
-                    p--;
-            }
-        }
-        else
-            *q++ = *p;
-    *q = 0;
-    return buffer;
-}
diff --git a/src/song_change/formatter.cc b/src/song_change/formatter.cc
new file mode 100644
index 000000000000..c46c075e81d6
--- /dev/null
+++ b/src/song_change/formatter.cc
@@ -0,0 +1,104 @@
+/*  Audacious
+ *  Copyright (C) 2005-2007  Audacious team
+ *
+ *  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2003  Peter Alm, Mikael Alm, Olle Hallnas,
+ *                           Thomas Nilsson and 4Front Technologies
+ *  Copyright (C) 1999-2003  Haavard Kvaalen
+ *
+ *  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 <glib.h>
+#include <string.h>
+#include "formatter.h"
+
+Formatter *
+formatter_new(void)
+{
+    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;
+    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) {
+                len += 1;
+                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);
+            }
+            else {
+                *q++ = '%';
+                if (*p != '\0')
+                    *q++ = *p;
+                else
+                    p--;
+            }
+        }
+        else
+            *q++ = *p;
+    *q = 0;
+    return buffer;
+}
diff --git a/src/song_change/formatter.h b/src/song_change/formatter.h
index b853bc5f790f..ec542e468f4c 100644
--- a/src/song_change/formatter.h
+++ b/src/song_change/formatter.h
@@ -4,13 +4,13 @@
 #include <glib.h>
 
 typedef struct {
-    gchar *values[256];
+    char *values[256];
 } Formatter;
 
 Formatter *formatter_new(void);
 void formatter_destroy(Formatter * formatter);
-void formatter_associate(Formatter * formatter, const guchar id, const gchar * value);
-void formatter_dissociate(Formatter * formatter, const guchar id);
-gchar *formatter_format(Formatter * formatter, gchar * format);
+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);
 
 #endif
diff --git a/src/song_change/song_change.c b/src/song_change/song_change.c
deleted file mode 100644
index bbda70756f41..000000000000
--- a/src/song_change/song_change.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * 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 <stdio.h>
-
-#include <string.h>
-
-#include <audacious/misc.h>
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-#include <audacious/playlist.h>
-#include <libaudcore/hook.h>
-#include <libaudcore/audstrings.h>
-#include <libaudcore/tuple.h>
-
-#include "formatter.h"
-
-static const PluginPreferences preferences;
-
-static gboolean init (void);
-static void cleanup(void);
-static void songchange_playback_begin(gpointer unused, gpointer unused2);
-static void songchange_playback_end(gpointer unused, gpointer unused2);
-static void songchange_playlist_eof(gpointer unused, gpointer unused2);
-//static void songchange_playback_ttc(gpointer, gpointer);
-
-typedef struct
-{
-    gchar *title;
-    gchar *filename;
-}
-songchange_playback_ttc_prevs_t;
-static songchange_playback_ttc_prevs_t *ttc_prevs = NULL;
-
-static char *cmd_line = NULL;
-static char *cmd_line_after = NULL;
-static char *cmd_line_end = NULL;
-static char *cmd_line_ttc = NULL;
-
-static GtkWidget *cmd_warn_label, *cmd_warn_img;
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Song Change"),
-    .domain = PACKAGE,
-    .prefs = & preferences,
-    .init = init,
-    .cleanup = cleanup
-)
-
-/**
- * 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().
- */
-static gchar *escape_shell_chars(const gchar * string)
-{
-    const gchar *special = "$`\"\\";    /* Characters to escape */
-    const gchar *in = string;
-    gchar *out, *escaped;
-    gint num = 0;
-
-    while (*in != '\0')
-        if (strchr(special, *in++))
-            num++;
-
-    escaped = g_malloc(strlen(string) + num + 1);
-
-    in = string;
-    out = escaped;
-
-    while (*in != '\0') {
-        if (strchr(special, *in))
-            *out++ = '\\';
-        *out++ = *in++;
-    }
-    *out = '\0';
-
-    return escaped;
-}
-
-static void bury_child(int signal)
-{
-    waitpid(-1, NULL, WNOHANG);
-}
-
-static void execute_command(char *cmd)
-{
-    char *argv[4] = {"/bin/sh", "-c", NULL, NULL};
-    int i;
-    argv[2] = cmd;
-    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", argv);
-    }
-}
-
-/* Format codes:
- *
- *   F - frequency (in hertz)
- *   c - number of channels
- *   f - filename (full path)
- *   l - length (in milliseconds)
- *   n - name
- *   r - rate (in bits per second)
- *   s - name (since everyone's used to it)
- *   t - playlist position (%02d)
- *   p - currently playing (1 or 0)
- *   a - artist
- *   b - album
- *   r - track title
- */
-/* do_command(): do @cmd after replacing the format codes
-   @cmd: command to run */
-static void do_command (char * cmd)
-{
-    int playlist = aud_playlist_get_playing ();
-    int pos = aud_playlist_get_position (playlist);
-
-    char *shstring = NULL, *temp, numbuf[32];
-    gboolean playing;
-    Formatter *formatter;
-
-    if (cmd && strlen(cmd) > 0)
-    {
-        formatter = formatter_new();
-
-        char * ctitle = aud_playlist_entry_get_title (playlist, pos, FALSE);
-        if (ctitle)
-        {
-            temp = escape_shell_chars (ctitle);
-            formatter_associate(formatter, 's', temp);
-            formatter_associate(formatter, 'n', temp);
-            g_free(temp);
-            str_unref (ctitle);
-        }
-        else
-        {
-            formatter_associate(formatter, 's', "");
-            formatter_associate(formatter, 'n', "");
-        }
-
-        char * filename = aud_playlist_entry_get_filename (playlist, pos);
-        if (filename)
-        {
-            temp = escape_shell_chars (filename);
-            formatter_associate(formatter, 'f', temp);
-            g_free(temp);
-            str_unref (filename);
-        }
-        else
-            formatter_associate(formatter, 'f', "");
-
-        g_snprintf(numbuf, sizeof(numbuf), "%02d", pos + 1);
-        formatter_associate(formatter, 't', numbuf);
-
-        int length = aud_playlist_entry_get_length (playlist, pos, FALSE);
-        if (length > 0)
-        {
-            str_itoa (length, numbuf, sizeof numbuf);
-            formatter_associate(formatter, 'l', numbuf);
-        }
-        else
-            formatter_associate(formatter, 'l', "0");
-
-        playing = aud_drct_get_playing();
-        str_itoa (playing, numbuf, sizeof numbuf);
-        formatter_associate(formatter, 'p', numbuf);
-
-        if (playing)
-        {
-            int brate, srate, chans;
-            aud_drct_get_info (& brate, & srate, & chans);
-            str_itoa (brate, numbuf, sizeof numbuf);
-            formatter_associate (formatter, 'r', numbuf);
-            str_itoa (srate, numbuf, sizeof numbuf);
-            formatter_associate (formatter, 'F', numbuf);
-            str_itoa (chans, numbuf, sizeof numbuf);
-            formatter_associate (formatter, 'c', numbuf);
-        }
-
-        Tuple * tuple = aud_playlist_entry_get_tuple
-            (aud_playlist_get_active (), pos, 0);
-
-        char * artist = tuple ? tuple_get_str (tuple, FIELD_ARTIST) : NULL;
-        if (artist)
-        {
-            formatter_associate(formatter, 'a', artist);
-            str_unref(artist);
-        }
-        else
-            formatter_associate(formatter, 'a', "");
-
-        char * album = tuple ? tuple_get_str (tuple, FIELD_ALBUM) : NULL;
-        if (album)
-        {
-            formatter_associate(formatter, 'b', album);
-            str_unref(album);
-        }
-        else
-            formatter_associate(formatter, 'b', "");
-
-        char * title = tuple ? tuple_get_str (tuple, FIELD_TITLE) : NULL;
-        if (title)
-        {
-            formatter_associate(formatter, 'T', title);
-            str_unref(title);
-        }
-        else
-            formatter_associate(formatter, 'T', "");
-
-        if (tuple)
-            tuple_unref (tuple);
-
-        shstring = formatter_format(formatter, cmd);
-        formatter_destroy(formatter);
-
-        if (shstring)
-        {
-            execute_command(shstring);
-            /* FIXME: This can possibly be freed too early */
-            g_free(shstring);
-        }
-    }
-}
-
-static void read_config(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");
-}
-
-static void cleanup(void)
-{
-    hook_dissociate("playback begin", songchange_playback_begin);
-    hook_dissociate("playback end", songchange_playback_end);
-    hook_dissociate("playlist end reached", songchange_playlist_eof);
-    // hook_dissociate( "playlist set info" , songchange_playback_ttc);
-
-    if ( ttc_prevs != NULL )
-    {
-        if ( ttc_prevs->title != NULL ) g_free( ttc_prevs->title );
-        if ( ttc_prevs->filename != NULL ) g_free( ttc_prevs->filename );
-        g_free( ttc_prevs );
-        ttc_prevs = NULL;
-    }
-
-    str_unref(cmd_line);
-    str_unref(cmd_line_after);
-    str_unref(cmd_line_end);
-    str_unref(cmd_line_ttc);
-
-    cmd_line = NULL;
-    cmd_line_after = NULL;
-    cmd_line_end = NULL;
-    cmd_line_ttc = NULL;
-
-    signal(SIGCHLD, SIG_DFL);
-}
-
-static void save_and_close(gchar * cmd, gchar * cmd_after, gchar * cmd_end, gchar * cmd_ttc)
-{
-    aud_set_str("song_change", "cmd_line", cmd);
-    aud_set_str("song_change", "cmd_line_after", cmd_after);
-    aud_set_str("song_change", "cmd_line_end", cmd_end);
-    aud_set_str("song_change", "cmd_line_ttc", cmd_ttc);
-
-    str_unref(cmd_line);
-    str_unref(cmd_line_after);
-    str_unref(cmd_line_end);
-    str_unref(cmd_line_ttc);
-
-    cmd_line = str_get(cmd);
-    cmd_line_after = str_get(cmd_after);
-    cmd_line_end = str_get(cmd_end);
-    cmd_line_ttc = str_get(cmd_ttc);
-}
-
-static int check_command(char *command)
-{
-    const char *dangerous = "fns";
-    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;
-}
-
-static gboolean init (void)
-{
-    read_config();
-
-    hook_associate("playback begin", songchange_playback_begin, NULL);
-    hook_associate("playback end", songchange_playback_end, NULL);
-    hook_associate("playlist end reached", songchange_playlist_eof, NULL);
-
-    ttc_prevs = g_malloc0(sizeof(songchange_playback_ttc_prevs_t));
-    ttc_prevs->title = NULL;
-    ttc_prevs->filename = NULL;
-    // hook_associate( "playlist set info" , songchange_playback_ttc , ttc_prevs );
-
-    return TRUE;
-}
-
-static void songchange_playback_begin(gpointer unused, gpointer unused2)
-{
-    do_command (cmd_line);
-}
-
-static void songchange_playback_end(gpointer unused, gpointer unused2)
-{
-    do_command (cmd_line_after);
-}
-
-#if 0
-    static void
-songchange_playback_ttc(gpointer plentry_gp, gpointer prevs_gp)
-{
-    if ( ( aud_ip_state->playing ) && ( strcmp(cmd_line_ttc,"") ) )
-    {
-        songchange_playback_ttc_prevs_t *prevs = prevs_gp;
-        PlaylistEntry *pl_entry = plentry_gp;
-
-        /* same filename but title changed, useful to detect http stream song changes */
-
-        if ( ( prevs->title != NULL ) && ( prevs->filename != NULL ) )
-        {
-            if ( ( pl_entry->filename != NULL ) && ( !strcmp(pl_entry->filename,prevs->filename) ) )
-            {
-                if ( ( pl_entry->title != NULL ) && ( strcmp(pl_entry->title,prevs->title) ) )
-                {
-                    int pos = aud_drct_pl_get_pos();
-                    char *current_file = aud_drct_pl_get_file(pos);
-                    do_command(cmd_line_ttc, current_file, pos);
-                    g_free(current_file);
-                    g_free(prevs->title);
-                    prevs->title = g_strdup(pl_entry->title);
-                }
-            }
-            else
-            {
-                g_free(prevs->filename);
-                prevs->filename = g_strdup(pl_entry->filename);
-                /* if filename changes, reset title as well */
-                if ( prevs->title != NULL )
-                    g_free(prevs->title);
-                prevs->title = g_strdup(pl_entry->title);
-            }
-        }
-        else
-        {
-            if ( prevs->title != NULL )
-                g_free(prevs->title);
-            prevs->title = g_strdup(pl_entry->title);
-            if ( prevs->filename != NULL )
-                g_free(prevs->filename);
-            prevs->filename = g_strdup(pl_entry->filename);
-        }
-    }
-}
-#endif
-
-static void songchange_playlist_eof(gpointer unused, gpointer unused2)
-{
-    do_command (cmd_line_end);
-}
-
-typedef struct {
-    gchar * cmd;
-    gchar * cmd_after;
-    gchar * cmd_end;
-    gchar * cmd_ttc;
-} SongChangeConfig;
-
-static SongChangeConfig config = {NULL};
-
-static void configure_ok_cb()
-{
-    char *cmd, *cmd_after, *cmd_end, *cmd_ttc;
-    cmd = g_strdup(config.cmd);
-    cmd_after = g_strdup(config.cmd_after);
-    cmd_end = g_strdup(config.cmd_end);
-    cmd_ttc = g_strdup(config.cmd_ttc);
-
-    if (check_command(cmd) < 0 || check_command(cmd_after) < 0 ||
-            check_command(cmd_end) < 0 || check_command(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);
-        save_and_close(cmd, cmd_after, cmd_end, cmd_ttc);
-    }
-
-    g_free(cmd);
-    g_free(cmd_after);
-    g_free(cmd_end);
-    g_free(cmd_ttc);
-}
-
-static const PreferencesWidget elements[] = {
-    {WIDGET_LABEL, N_("Command to run when Audacious starts a new song."),
-        .data = {.label = {.single_line = TRUE}}},
-    {WIDGET_ENTRY, N_("Command:"), .cfg_type = VALUE_STRING,
-        .cfg = & config.cmd, .callback = configure_ok_cb},
-    {WIDGET_SEPARATOR, .data = {.separator = {TRUE}}},
-
-    {WIDGET_LABEL, N_("Command to run toward the end of a song."),
-        .data = {.label = {.single_line = TRUE}}},
-    {WIDGET_ENTRY, N_("Command:"), .cfg_type = VALUE_STRING,
-        .cfg = & config.cmd_after, .callback = configure_ok_cb},
-    {WIDGET_SEPARATOR, .data = {.separator = {TRUE}}},
-
-    {WIDGET_LABEL, N_("Command to run when Audacious reaches the end of the "
-            "playlist."), .data = {.label = {.single_line = TRUE}}},
-    {WIDGET_ENTRY, N_("Command:"), .cfg_type = VALUE_STRING,
-        .cfg = & config.cmd_end, .callback = configure_ok_cb},
-    {WIDGET_SEPARATOR, .data = {.separator = {TRUE}}},
-
-    {WIDGET_LABEL, N_("Command to run when title changes for a song (i.e. "
-            "network streams titles)."), .data = {.label = {.single_line = TRUE}}},
-    {WIDGET_ENTRY, N_("Command:"), .cfg_type = VALUE_STRING,
-        .cfg = & config.cmd_ttc, .callback = configure_ok_cb},
-    {WIDGET_SEPARATOR, .data = {.separator = {TRUE}}},
-
-    {WIDGET_LABEL, N_("You can use the following format strings which\n"
-            "will be substituted before calling the command\n"
-            "(not all are useful for the end-of-playlist command):\n\n"
-            "%F: Frequency (in hertz)\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"
-            "%p: Currently playing (1 or 0)\n"
-            "%a: Artist\n"
-            "%b: Album\n"
-            "%T: Track title")},
-};
-
-/* static GtkWidget * custom_warning (void) */
-static void * custom_warning (void)
-{
-    GtkWidget *bbox_hbox;
-    gchar * temp;
-
-    bbox_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 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);
-
-    return bbox_hbox;
-}
-
-static const PreferencesWidget settings[] = {
-    {WIDGET_BOX, N_("Commands"), .data = {.box = {elements, ARRAY_LEN (elements), .frame = TRUE}}},
-    {WIDGET_CUSTOM, .data = {.populate = custom_warning}}};
-
-static void configure_init(void)
-{
-    read_config();
-
-    config.cmd = g_strdup(cmd_line);
-    config.cmd_after = g_strdup(cmd_line_after);
-    config.cmd_end = g_strdup(cmd_line_end);
-    config.cmd_ttc = g_strdup(cmd_line_ttc);
-}
-
-static void configure_cleanup(void)
-{
-    g_free(config.cmd);
-    config.cmd = NULL;
-
-    g_free(config.cmd_after);
-    config.cmd_after = NULL;
-
-    g_free(config.cmd_end);
-    config.cmd_end = NULL;
-
-    g_free(config.cmd_ttc);
-    config.cmd_ttc = NULL;
-}
-
-static const PluginPreferences preferences = {
-    .widgets = settings,
-    .n_widgets = ARRAY_LEN (settings),
-    .init = configure_init,
-    .cleanup = configure_cleanup,
-};
diff --git a/src/song_change/song_change.cc b/src/song_change/song_change.cc
new file mode 100644
index 000000000000..10a444bf0f16
--- /dev/null
+++ b/src/song_change/song_change.cc
@@ -0,0 +1,415 @@
+/*
+ * 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 <string.h>
+
+#include <libaudcore/runtime.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/tuple.h>
+
+#include "formatter.h"
+
+class SongChange : public GeneralPlugin
+{
+public:
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Song Change"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr SongChange () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+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().
+ */
+static char *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);
+
+    in = string;
+    out = escaped;
+
+    while (*in != '\0') {
+        if (strchr(special, *in))
+            *out++ = '\\';
+        *out++ = *in++;
+    }
+    *out = '\0';
+
+    return escaped;
+}
+
+static void bury_child(int signal)
+{
+    waitpid(-1, nullptr, WNOHANG);
+}
+
+static void execute_command(char *cmd)
+{
+    const char *argv[4] = {"/bin/sh", "-c", nullptr, nullptr};
+    int i;
+    argv[2] = cmd;
+    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);
+    }
+}
+
+/* Format codes:
+ *
+ *   F - frequency (in hertz)
+ *   c - number of channels
+ *   f - filename (full path)
+ *   l - length (in milliseconds)
+ *   n - name
+ *   r - rate (in bits per second)
+ *   s - name (since everyone's used to it)
+ *   t - playlist position (%02d)
+ *   p - currently playing (1 or 0)
+ *   a - artist
+ *   b - album
+ *   r - track title
+ */
+/* do_command(): do @cmd after replacing the format codes
+   @cmd: command to run */
+static void do_command (const char * cmd)
+{
+    char *shstring = nullptr, *temp;
+    gboolean playing;
+    Formatter *formatter;
+
+    if (cmd && strlen(cmd) > 0)
+    {
+        formatter = formatter_new();
+
+        playing = aud_drct_get_ready();
+
+        Tuple tuple;
+        if (playing)
+            tuple = aud_drct_get_tuple ();
+
+        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);
+        }
+        else
+        {
+            formatter_associate(formatter, 's', "");
+            formatter_associate(formatter, 'n', "");
+        }
+
+        String filename = aud_drct_get_filename ();
+        if (filename)
+        {
+            temp = escape_shell_chars (filename);
+            formatter_associate(formatter, 'f', temp);
+            g_free(temp);
+        }
+        else
+            formatter_associate(formatter, 'f', "");
+
+        if (playing)
+        {
+            int pos = aud_drct_get_position ();
+            formatter_associate (formatter, 't', str_printf ("%02d", pos + 1));
+        }
+        else
+            formatter_associate (formatter, 't', "");
+
+        int length = tuple.get_int (Tuple::Length);
+        if (length > 0)
+            formatter_associate(formatter, 'l', int_to_str (length));
+        else
+            formatter_associate(formatter, 'l', "0");
+
+        formatter_associate(formatter, '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));
+        }
+
+        String artist = tuple.get_str (Tuple::Artist);
+        if (artist)
+            formatter_associate(formatter, 'a', artist);
+        else
+            formatter_associate(formatter, 'a', "");
+
+        String album = tuple.get_str (Tuple::Album);
+        if (album)
+            formatter_associate(formatter, 'b', album);
+        else
+            formatter_associate(formatter, 'b', "");
+
+        String title = tuple.get_str (Tuple::Title);
+        if (title)
+            formatter_associate(formatter, 'T', title);
+        else
+            formatter_associate(formatter, 'T', "");
+
+        shstring = formatter_format(formatter, cmd);
+        formatter_destroy(formatter);
+
+        if (shstring)
+        {
+            execute_command(shstring);
+            /* FIXME: This can possibly be freed too early */
+            g_free(shstring);
+        }
+    }
+}
+
+static void read_config(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");
+}
+
+void SongChange::cleanup ()
+{
+    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);
+}
+
+static int check_command(const char *command)
+{
+    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;
+}
+
+bool SongChange::init ()
+{
+    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;
+}
+
+static void songchange_playback_begin(void *, void *)
+{
+    do_command (cmd_line);
+}
+
+static void songchange_playback_end(void *, void *)
+{
+    do_command (cmd_line_after);
+}
+
+static void songchange_playback_ttc(void *, void *)
+{
+    do_command (cmd_line_ttc);
+}
+
+static void songchange_playlist_eof(void *, void *)
+{
+    do_command (cmd_line_end);
+}
+
+typedef struct {
+    String cmd;
+    String cmd_after;
+    String cmd_end;
+    String cmd_ttc;
+} SongChangeConfig;
+
+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}),
+
+    WidgetLabel (N_("Command to run at the end of a song:")),
+    WidgetEntry (0, WidgetString (config.cmd_after, edit_cb)),
+    WidgetSeparator ({true}),
+
+    WidgetLabel (N_("Command to run at the end of the playlist:")),
+    WidgetEntry (0, WidgetString (config.cmd_end, edit_cb)),
+    WidgetSeparator ({true}),
+
+    WidgetLabel (N_("Command to run when song title changes (for network streams):")),
+    WidgetEntry (0, WidgetString (config.cmd_ttc, edit_cb)),
+    WidgetSeparator ({true}),
+
+    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"
+                    "%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"
+                    "%p: Currently playing (1 or 0)\n"
+                    "%a: Artist\n"
+                    "%b: Album\n"
+                    "%T: Track title")),
+
+    WidgetCustomGTK (custom_warning)
+};
+
+static void configure_init(void)
+{
+    config.cmd = cmd_line;
+    config.cmd_after = cmd_line_after;
+    config.cmd_end = cmd_line_end;
+    config.cmd_ttc = cmd_line_ttc;
+}
+
+static void configure_cleanup(void)
+{
+    config.cmd = String ();
+    config.cmd_after = String ();
+    config.cmd_end = String ();
+    config.cmd_ttc = String ();
+}
+
+const PluginPreferences SongChange::prefs = {
+    {widgets},
+    configure_init,
+    configure_ok_cb,
+    configure_cleanup,
+};
diff --git a/src/sox-resampler/Makefile b/src/sox-resampler/Makefile
index 57154da70ed8..bc3bcd9a8cc0 100644
--- a/src/sox-resampler/Makefile
+++ b/src/sox-resampler/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = sox-resampler${PLUGIN_SUFFIX}
 
-SRCS = sox-resampler.c
+SRCS = sox-resampler.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} -lsoxr
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -lsoxr
diff --git a/src/sox-resampler/sox-resampler.c b/src/sox-resampler/sox-resampler.c
deleted file mode 100644
index d9c86d562a5e..000000000000
--- a/src/sox-resampler/sox-resampler.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * SoX Resampler Plugin for Audacious
- * Copyright 2013 Michał Lipski
- *
- * Based on Sample Rate Converter Plugin:
- * Copyright 2010-2012 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 <stdio.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#include <soxr.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-#define MIN_RATE 8000
-#define MAX_RATE 192000
-#define RATE_STEP 50
-
-#define RESAMPLER_ERROR(e) fprintf (stderr, "sox-resampler: %s\n", e)
-
-static const char * const sox_resampler_defaults[] = {
- "quality", "4", /* SOXR_HQ */
- "rate", "44100",
- NULL};
-
-static soxr_t soxr;
-static soxr_error_t error;
-static int stored_channels;
-static double ratio;
-static float * buffer;
-static size_t buffer_samples;
-
-bool_t sox_resampler_init (void)
-{
-    aud_config_set_defaults ("soxr", sox_resampler_defaults);
-    return TRUE;
-}
-
-void sox_resampler_cleanup (void)
-{
-    soxr_delete (soxr);
-    soxr = 0;
-    g_free (buffer);
-    buffer = NULL;
-    buffer_samples = 0;
-}
-
-void sox_resampler_start (int * channels, int * rate)
-{
-    soxr_delete (soxr);
-    soxr = 0;
-
-    int new_rate = aud_get_int ("soxr", "rate");
-    new_rate = CLAMP (new_rate, MIN_RATE, MAX_RATE);
-
-    if (new_rate == * rate)
-        return;
-
-    soxr_quality_spec_t q = soxr_quality_spec(aud_get_int ("soxr", "quality"), 0);
-
-    soxr = soxr_create((double) * rate, (double) new_rate, * channels, & error, NULL, & q, NULL);
-
-    if (error)
-    {
-        RESAMPLER_ERROR (error);
-        return;
-    }
-
-    stored_channels = * channels;
-    ratio = (double) new_rate / * rate;
-    * rate = new_rate;
-}
-
-void do_resample (float * * data, int * samples)
-{
-    if (! soxr)
-         return;
-
-    if (buffer_samples < (int) (* samples * ratio) + 256)
-    {
-        buffer_samples = (int) (* samples * ratio) + 256;
-        buffer = g_renew (float, buffer, buffer_samples);
-    }
-
-    size_t samples_done;
-
-    error = soxr_process(soxr, * data, * samples / stored_channels, NULL,
-        buffer, buffer_samples / stored_channels, & samples_done);
-
-    if (error)
-    {
-        RESAMPLER_ERROR (error);
-        return;
-    }
-
-    * data = buffer;
-    * samples = samples_done * stored_channels;
-}
-
-void sox_resampler_process (float * * data, int * samples)
-{
-    do_resample (data, samples);
-}
-
-void sox_resampler_flush (void)
-{
-    if (soxr && (error = soxr_process(soxr, NULL, 0, NULL, NULL, 0, NULL)))
-        RESAMPLER_ERROR (error);
-}
-
-void sox_resampler_finish (float * * data, int * samples)
-{
-    do_resample (data, samples);
-}
-
-static const char sox_resampler_about[] =
- N_("SoX Resampler Plugin for Audacious\n"
-    "Copyright 2013 Michał Lipski\n\n"
-    "Based on Sample Rate Converter Plugin:\n"
-    "Copyright 2010-2012 John Lindgren");
-
-static const ComboBoxElements method_list[] = {
- {"0", N_("Quick")}, /* SOXR_QQ */
- {"1", N_("Low")}, /* SOXR_QL */
- {"2", N_("Medium")}, /* SOXR_QM */
- {"4", N_("High")}, /* SOXR_QH */
- {"6", N_("Very High")}}; /* SOXR_VHQ */
-
-static const PreferencesWidget sox_resampler_widgets[] = {
- {WIDGET_COMBO_BOX, N_("Quality:"),
-  .cfg_type = VALUE_STRING, .csect = "soxr", .cname = "quality",
-  .data = {.combo = {method_list, ARRAY_LEN (method_list)}}},
- {WIDGET_SPIN_BTN, N_("Rate:"),
-  .cfg_type = VALUE_INT, .csect = "soxr", .cname = "rate",
-  .data = {.spin_btn = {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")}}}
-};
-
-static const PluginPreferences sox_resampler_prefs = {
- .widgets = sox_resampler_widgets,
- .n_widgets = ARRAY_LEN (sox_resampler_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("SoX Resampler"),
-    .domain = PACKAGE,
-    .about_text = sox_resampler_about,
-    .prefs = & sox_resampler_prefs,
-    .init = sox_resampler_init,
-    .cleanup = sox_resampler_cleanup,
-    .start = sox_resampler_start,
-    .process = sox_resampler_process,
-    .flush = sox_resampler_flush,
-    .finish = sox_resampler_finish,
-    .order = 2 /* must be before crossfade */
-)
diff --git a/src/sox-resampler/sox-resampler.cc b/src/sox-resampler/sox-resampler.cc
new file mode 100644
index 000000000000..43cbe61a8924
--- /dev/null
+++ b/src/sox-resampler/sox-resampler.cc
@@ -0,0 +1,166 @@
+/*
+ * SoX Resampler Plugin for Audacious
+ * Copyright 2013 Michał Lipski
+ *
+ * Based on Sample Rate Converter Plugin:
+ * Copyright 2010-2012 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 <stdlib.h>
+#include <soxr.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+#define MIN_RATE 8000
+#define MAX_RATE 192000
+#define RATE_STEP 50
+
+class SoXResampler : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("SoX Resampler"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    /* order #2: must be before crossfade */
+    constexpr SoXResampler () : EffectPlugin (info, 2, false) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+    bool flush (bool force);
+};
+
+EXPORT SoXResampler aud_plugin_instance;
+
+const char * const SoXResampler::defaults[] = {
+ "quality", aud::numeric_string<SOXR_HQ>::str,
+ "rate", "44100",
+ nullptr};
+
+static soxr_t soxr;
+static soxr_error_t error;
+static int stored_channels;
+static double ratio;
+static Index<float> buffer;
+
+bool SoXResampler::init ()
+{
+    aud_config_set_defaults ("soxr", defaults);
+    return true;
+}
+
+void SoXResampler::cleanup ()
+{
+    soxr_delete (soxr);
+    soxr = 0;
+    buffer.clear ();
+}
+
+void SoXResampler::start (int & channels, int & rate)
+{
+    soxr_delete (soxr);
+    soxr = 0;
+
+    int new_rate = aud_get_int ("soxr", "rate");
+    new_rate = aud::clamp (new_rate, MIN_RATE, MAX_RATE);
+
+    if (new_rate == rate)
+        return;
+
+    soxr_quality_spec_t q = soxr_quality_spec(aud_get_int ("soxr", "quality"), 0);
+
+    soxr = soxr_create(rate, new_rate, channels, & error, nullptr, & q, nullptr);
+
+    if (error)
+    {
+        AUDERR (error);
+        return;
+    }
+
+    stored_channels = channels;
+    ratio = (double) new_rate / rate;
+    rate = new_rate;
+}
+
+Index<float> & SoXResampler::process (Index<float> & data)
+{
+    if (! soxr)
+         return data;
+
+    buffer.resize ((int) (data.len () * ratio) + 256);
+
+    size_t samples_done;
+    error = soxr_process (soxr, data.begin (), data.len () / stored_channels,
+     nullptr, buffer.begin (), buffer.len () / stored_channels, & samples_done);
+
+    if (error)
+    {
+        AUDERR (error);
+        return data;
+    }
+
+    buffer.resize (samples_done * stored_channels);
+
+    return buffer;
+}
+
+bool SoXResampler::flush (bool force)
+{
+    if (soxr && (error = soxr_process(soxr, nullptr, 0, nullptr, nullptr, 0, nullptr)))
+        AUDERR (error);
+
+    return true;
+}
+
+const char SoXResampler::about[] =
+ N_("SoX Resampler Plugin for Audacious\n"
+    "Copyright 2013 Michał Lipski\n\n"
+    "Based on Sample Rate Converter Plugin:\n"
+    "Copyright 2010-2012 John Lindgren");
+
+static const ComboItem method_list[] = {
+    ComboItem (N_("Quick"), SOXR_QQ),
+    ComboItem (N_("Low"), SOXR_LQ),
+    ComboItem (N_("Medium"), SOXR_MQ),
+    ComboItem (N_("High"), SOXR_HQ),
+    ComboItem (N_("Very High"), SOXR_VHQ)
+};
+
+const PreferencesWidget SoXResampler::widgets[] = {
+    WidgetCombo (N_("Quality:"),
+        WidgetInt ("soxr", "quality"),
+        {{method_list}}),
+    WidgetSpin (N_("Rate:"),
+        WidgetInt ("soxr", "rate"),
+        {MIN_RATE, MAX_RATE, RATE_STEP, N_("Hz")})
+};
+
+const PluginPreferences SoXResampler::prefs = {{widgets}};
diff --git a/src/speed-pitch/Makefile b/src/speed-pitch/Makefile
index 635e22bcb110..41a00d5add83 100644
--- a/src/speed-pitch/Makefile
+++ b/src/speed-pitch/Makefile
@@ -1,12 +1,13 @@
 PLUGIN = speed-pitch${PLUGIN_SUFFIX}
 
-SRCS = speed-pitch.c
+SRCS = speed-pitch.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../..
+LD = ${CXX}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
 CFLAGS += ${PLUGIN_CFLAGS}
-LIBS += -lm ${GLIB_LIBS} -lsamplerate
+LIBS += -lm -lsamplerate
diff --git a/src/speed-pitch/speed-pitch.c b/src/speed-pitch/speed-pitch.c
deleted file mode 100644
index 94a996a3ae90..000000000000
--- a/src/speed-pitch/speed-pitch.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Speed and Pitch effect plugin for Audacious
- * Copyright 2012 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 <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <samplerate.h>
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-/* The general idea of the speed change algorithm is to divide the input signal
- * into pieces, spaced at a time interval A, using a cosine-shaped window
- * function.  The pieces are then reassembled by adding them together again,
- * spaced at another time interval B.  By varying the ratio A:B, we change the
- * speed of the audio.  To get better results at the two ends of a song, we add
- * a short period of silence (half the width of the cosine window, to be exact)
- * to each end of the input signal beforehand and afterwards trim the same
- * amount from each end of the output signal. */
-
-#define FREQ    10
-#define OVERLAP  3
-
-#define CFGSECT "speed-pitch"
-#define MINSPEED 0.5
-#define MAXSPEED 2.0
-#define MINPITCH 0.5
-#define MAXPITCH 2.0
-
-#define BYTES(frames) ((frames) * curchans * sizeof (float))
-#define OFFSET(buf,frames) ((buf) + (frames) * curchans)
-
-typedef struct {
-    float * mem;
-    int size, len;
-} Buffer;
-
-static int curchans, currate;
-static SRC_STATE * srcstate;
-static int outstep, width;
-static double * cosine;
-static Buffer in, out;
-static int trim, written;
-static bool_t ending;
-
-static void bufgrow (Buffer * b, int len)
-{
-    if (len > b->size)
-    {
-        b->mem = g_realloc (b->mem, BYTES (len));
-        b->size = len;
-    }
-
-    if (len > b->len)
-    {
-        memset (OFFSET (b->mem, b->len), 0, BYTES (len - b->len));
-        b->len = len;
-    }
-}
-
-static void bufcut (Buffer * b, int len)
-{
-    memmove (b->mem, OFFSET (b->mem, len), BYTES (b->len - len));
-    b->len -= len;
-}
-
-static void bufadd (Buffer * b, float * data, int len, double ratio)
-{
-    int oldlen = b->len;
-    int max = len * ratio + 100;
-    bufgrow (b, oldlen + max);
-
-    SRC_DATA d = {
-     .data_in = data,
-     .input_frames = len,
-     .data_out = OFFSET (b->mem, oldlen),
-     .output_frames = max,
-     .src_ratio = ratio};
-
-    src_process (srcstate, & d);
-    b->len = oldlen + d.output_frames_gen;
-}
-
-static void speed_flush (void)
-{
-    src_reset (srcstate);
-
-    in.len = 0;
-    out.len = 0;
-
-    /* Add silence to the beginning of the input signal. */
-    bufgrow (& in, width / 2);
-
-    trim = width / 2;
-    written = 0;
-    ending = FALSE;
-}
-
-static void speed_start (int * chans, int * rate)
-{
-    curchans = * chans;
-    currate = * rate;
-
-    if (srcstate)
-        src_delete (srcstate);
-
-    srcstate = src_new (SRC_LINEAR, curchans, NULL);
-
-    /* Calculate the width of the cosine window and the spacing interval for
-     * output. */
-    outstep = currate / FREQ;
-    width = outstep * OVERLAP;
-
-    /* Generate the cosine window, scaled vertically to compensate for the
-     * overlap of the reassembled pieces of audio. */
-    cosine = g_realloc (cosine, width * sizeof (double));
-    for (int i = 0; i < width; i ++)
-        cosine[i] = (1.0 - cos (2.0 * M_PI * i / width)) / OVERLAP;
-
-    speed_flush ();
-}
-
-static void speed_process (float * * data, int * samples)
-{
-    double pitch = aud_get_double (CFGSECT, "pitch");
-    double speed = aud_get_double (CFGSECT, "speed");
-
-    /* Remove audio that has already been played from the output buffer. */
-    bufcut (& out, written);
-
-    /* Copy the passed audio to the input buffer, scaled to adjust pitch. */
-    bufadd (& in, * data, * samples / curchans, 1.0 / pitch);
-
-    /* If we are ending, add silence to the end of the input signal. */
-    if (ending)
-        bufgrow (& in, in.len + width / 2);
-
-    /* Calculate the spacing interval for input. */
-    int instep = round (outstep * speed / pitch);
-
-    /* Run the speed change algorithm. */
-    int src = 0;
-    int dst = 0;
-
-    while (src + MAX (width, instep) <= in.len)
-    {
-        bufgrow (& out, dst + width);
-        out.len = dst + width;
-
-        for (int i = 0; i < width; i ++)
-        for (int c = 0; c < curchans; c ++)
-            OFFSET (out.mem, dst + i)[c] += OFFSET (in.mem, src + i)[c] * cosine[i];
-
-        src += instep;
-        dst += outstep;
-    }
-
-    /* Remove processed audio from the input buffer. */
-    bufcut (& in, src);
-
-    /* Trim silence from the beginning of the output buffer. */
-    if (trim > 0)
-    {
-        int cut = MIN (trim, dst);
-        bufcut (& out, cut);
-        dst -= cut;
-        trim -= cut;
-    }
-
-    /* If we are ending, return all of the output buffer except the silence that
-     * we trim from the end of it. */
-    if (ending)
-        dst = out.len - width / 2;
-
-    /* Return processed audio in the output buffer and mark it to be removed on
-     * the next call. */
-    * data = out.mem;
-    * samples = dst * curchans;
-    written = dst;
-}
-
-static void speed_finish (float * * data, int * samples)
-{
-    /* Ignore the second "end of playlist" call since we are not in a state to
-     * handle it properly. */
-    if (! ending)
-    {
-        ending = TRUE;
-        speed_process (data, samples);
-    }
-}
-
-static int speed_adjust_delay (int delay)
-{
-    /* Not sample-accurate, but should be a decent estimate. */
-    double speed = aud_get_double (CFGSECT, "speed");
-    return delay * speed + width * 1000 / currate;
-}
-
-static const char * const speed_defaults[] = {
- "speed", "1",
- "pitch", "1",
- NULL};
-
-static const PreferencesWidget speed_widgets[] = {
- {WIDGET_LABEL, N_("<b>Speed and Pitch</b>")},
- {WIDGET_SPIN_BTN, N_("Speed:"),
-  .cfg_type = VALUE_FLOAT, .csect = CFGSECT, .cname = "speed",
-  .data = {.spin_btn = {MINSPEED, MAXSPEED, 0.05}}},
- {WIDGET_SPIN_BTN, N_("Pitch:"),
-  .cfg_type = VALUE_FLOAT, .csect = CFGSECT, .cname = "pitch",
-  .data = {.spin_btn = {MINPITCH, MAXPITCH, 0.05}}}};
-
-static const PluginPreferences speed_prefs = {
- .widgets = speed_widgets,
- .n_widgets = ARRAY_LEN (speed_widgets)};
-
-static bool_t speed_init (void)
-{
-    aud_config_set_defaults (CFGSECT, speed_defaults);
-    return TRUE;
-}
-
-static void speed_cleanup (void)
-{
-    if (srcstate)
-        src_delete (srcstate);
-
-    srcstate = NULL;
-
-    g_free (cosine);
-    cosine = NULL;
-
-    g_free (in.mem);
-    in.mem = NULL;
-    in.size = 0;
-
-    g_free (out.mem);
-    out.mem = NULL;
-    out.size = 0;
-}
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Speed and Pitch"),
-    .domain = PACKAGE,
-    .prefs = & speed_prefs,
-    .init = speed_init,
-    .cleanup = speed_cleanup,
-    .start = speed_start,
-    .process = speed_process,
-    .flush = speed_flush,
-    .finish = speed_finish,
-    .adjust_delay = speed_adjust_delay,
-    .preserves_format = TRUE
-)
diff --git a/src/speed-pitch/speed-pitch.cc b/src/speed-pitch/speed-pitch.cc
new file mode 100644
index 000000000000..17acca47fdf9
--- /dev/null
+++ b/src/speed-pitch/speed-pitch.cc
@@ -0,0 +1,237 @@
+/*
+ * Speed and Pitch effect plugin for Audacious
+ * Copyright 2012 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 <math.h>
+#include <samplerate.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+/* The general idea of the speed change algorithm is to divide the input signal
+ * into pieces, spaced at a time interval A, using a cosine-shaped window
+ * function.  The pieces are then reassembled by adding them together again,
+ * spaced at another time interval B.  By varying the ratio A:B, we change the
+ * speed of the audio. */
+
+#define FREQ    10
+#define OVERLAP  3
+
+#define CFGSECT "speed-pitch"
+#define MINSPEED 0.5
+#define MAXSPEED 2.0
+#define MINPITCH 0.5
+#define MAXPITCH 2.0
+
+class SpeedPitch : public EffectPlugin
+{
+public:
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Speed and Pitch"),
+        PACKAGE,
+        nullptr,
+        & prefs
+    };
+
+    constexpr SpeedPitch () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+    void cleanup ();
+
+    void start (int & channels, int & rate);
+    bool flush (bool force);
+    int adjust_delay (int delay);
+
+    Index<float> & process (Index<float> & samples)
+        { return process (samples, false); }
+    Index<float> & finish (Index<float> & samples, bool end_of_playlist)
+        { return process (samples, true); }
+
+private:
+    Index<float> & process (Index<float> & samples, bool ending);
+};
+
+EXPORT SpeedPitch aud_plugin_instance;
+
+static int curchans, currate;
+static SRC_STATE * srcstate;
+static int outstep, width;
+static Index<float> cosine;
+static Index<float> in, out;
+static int src, dst;
+
+static void add_data (Index<float> & b, Index<float> & data, float ratio)
+{
+    int oldlen = b.len ();
+    int inframes = data.len () / curchans;
+    int maxframes = (int) (inframes * ratio) + 256;
+    b.resize (oldlen + maxframes * curchans);
+
+    SRC_DATA d = SRC_DATA ();
+
+    d.data_in = data.begin ();
+    d.input_frames = inframes;
+    d.data_out = & b[oldlen];
+    d.output_frames = maxframes;
+    d.src_ratio = ratio;
+
+    src_process (srcstate, & d);
+    b.resize (oldlen + d.output_frames_gen * curchans);
+}
+
+bool SpeedPitch::flush (bool force)
+{
+    src_reset (srcstate);
+
+    in.resize (0);
+    out.resize (0);
+
+    /* The source and destination pointers give the center of the next cosine
+     * window to be copied, relative to the current input and output buffers. */
+    src = dst = 0;
+
+    /* The output buffer always extends right of the destination pointer by half
+     * the width of a cosine window. */
+    out.insert (0, width / 2);
+
+    return true;
+}
+
+void SpeedPitch::start (int & chans, int & rate)
+{
+    curchans = chans;
+    currate = rate;
+
+    if (srcstate)
+        src_delete (srcstate);
+
+    srcstate = src_new (SRC_LINEAR, curchans, nullptr);
+
+    /* Calculate the width of the cosine window and the spacing interval for
+     * output.  Make them both even numbers for convenience.  Note that the
+     * cosine window is applied without deinterleaving the audio samples. */
+    outstep = ((currate / FREQ) & ~1) * curchans;
+    width = outstep * OVERLAP;
+
+    /* Generate the cosine window, scaled vertically to compensate for the
+     * overlap of the reassembled pieces of audio. */
+    cosine.resize (width);
+    for (int i = 0; i < width; i ++)
+        cosine[i] = (1.0 - cos (2.0 * M_PI * i / width)) / OVERLAP;
+
+    flush (true);
+}
+
+Index<float> & SpeedPitch::process (Index<float> & data, bool ending)
+{
+    const float * cosine_center = & cosine[width / 2];
+    float pitch = aud_get_double (CFGSECT, "pitch");
+    float speed = aud_get_double (CFGSECT, "speed");
+
+    /* Copy the passed audio to the input buffer, scaled to adjust pitch. */
+    add_data (in, data, 1.0 / pitch);
+
+    /* Calculate the spacing interval for input. */
+    int instep = (int) round ((outstep / curchans) * speed / pitch) * curchans;
+
+    /* Stop copying half a window's width before the end of the input buffer (or
+     * right up to the end of the buffer if the song is ending). */
+    int stop = in.len () - (ending ? 0 : width / 2);
+
+    while (src <= stop)
+    {
+        /* Truncate the window to avoid overflows if necessary. */
+        int begin = aud::max (-(width / 2), aud::max (-src, -dst));
+        int end = aud::min (width / 2, aud::min (in.len () - src, out.len () - dst));
+
+        for (int i = begin; i < end; i ++)
+            out[dst + i] += in[src + i] * cosine_center[i];
+
+        src += instep;
+        dst += outstep;
+
+        out.insert (-1, outstep);
+    }
+
+    /* Discard input up to half a window's width before the source pointer (or
+     * right up to the previous source pointer if the song is ending. */
+    int seek = aud::clamp (0, src - (ending ? instep : width / 2), in.len ());
+    in.remove (0, seek);
+    src -= seek;
+
+    data.resize (0);
+
+    /* Return output up to half a window's width before the destination pointer
+     * (or right up to the previous destination pointer if the song is ending). */
+    int ret = aud::clamp (0, dst - (ending ? outstep : width / 2), out.len ());
+    data.move_from (out, 0, 0, ret, true, true);
+    dst -= ret;
+
+    return data;
+}
+
+int SpeedPitch::adjust_delay (int delay)
+{
+    float samples_to_ms = 1000.0 / (curchans * currate);
+    float speed = aud_get_double (CFGSECT, "speed");
+    int in_samples = in.len () - src;
+    int out_samples = dst;
+
+    return (delay + in_samples * samples_to_ms) * speed + out_samples * samples_to_ms;
+}
+
+const char * const SpeedPitch::defaults[] = {
+ "speed", "1",
+ "pitch", "1",
+ nullptr};
+
+const PreferencesWidget SpeedPitch::widgets[] = {
+    WidgetLabel (N_("<b>Speed and Pitch</b>")),
+    WidgetSpin (N_("Speed:"),
+        WidgetFloat (CFGSECT, "speed"),
+        {MINSPEED, MAXSPEED, 0.05}),
+    WidgetSpin (N_("Pitch:"),
+        WidgetFloat (CFGSECT, "pitch"),
+        {MINPITCH, MAXPITCH, 0.05})
+};
+
+const PluginPreferences SpeedPitch::prefs = {{widgets}};
+
+bool SpeedPitch::init ()
+{
+    aud_config_set_defaults (CFGSECT, defaults);
+    return true;
+}
+
+void SpeedPitch::cleanup ()
+{
+    if (srcstate)
+        src_delete (srcstate);
+
+    srcstate = nullptr;
+
+    cosine.clear ();
+    in.clear ();
+    out.clear ();
+}
diff --git a/src/statusicon/Makefile b/src/statusicon/Makefile
index 13d5f6dbde92..a48f29b45acd 100644
--- a/src/statusicon/Makefile
+++ b/src/statusicon/Makefile
@@ -1,13 +1,13 @@
 PLUGIN = statusicon${PLUGIN_SUFFIX}
 
-SRCS = statusicon.c \
-       util.c
+SRCS = statusicon.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS}  -I../..
-LIBS += ${GTK_LIBS} ${GLIB_LIBS} -laudgui
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} -I../..
+LIBS += ${GTK_LIBS} -laudgui
diff --git a/src/statusicon/statusicon.c b/src/statusicon/statusicon.c
deleted file mode 100644
index ffca3ac3ff16..000000000000
--- a/src/statusicon/statusicon.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-* Status Icon Plugin for Audacious
-*
-* Copyright 2005-2007 Giacomo Lozito <james at develia.org>
-* Copyright 2010 Michał Lipski <tallica at o2.pl>
-*
-* 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
-*
-*/
-
-#include "statusicon.h"
-
-#include <audacious/drct.h>
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/plugins.h>
-#include <audacious/preferences.h>
-#include <libaudcore/hook.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-#include <libaudgui/menu.h>
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#define POPUP_IS_ACTIVE GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon), "popup_active"))
-#define TIMER_IS_ACTIVE GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon), "timer_active"))
-
-static void si_popup_timer_start(GtkStatusIcon *);
-static void si_popup_timer_stop(GtkStatusIcon *);
-static void si_smallmenu_show(gint x, gint y, guint button, guint32 time, gpointer);
-static void si_smallmenu_recreate(GtkStatusIcon *);
-static void si_popup_hide(gpointer icon);
-
-static const char * const si_defaults[] = {
- "scroll_action", "0", /* SI_CFG_SCROLL_ACTION_VOLUME */
- "volume_delta", "5",
- "disable_popup", "FALSE",
- "close_to_tray", "FALSE",
- "reverse_scroll", "FALSE",
- NULL};
-
-static gboolean plugin_active = FALSE;
-static gboolean recreate_smallmenu = FALSE;
-
-static GtkStatusIcon *si_create(void)
-{
-    GtkStatusIcon *icon;
-    GtkIconTheme *theme;
-
-    theme = gtk_icon_theme_get_default();
-
-    if (gtk_icon_theme_has_icon(theme, "audacious-panel"))
-        icon = gtk_status_icon_new_from_icon_name("audacious-panel");
-    else if (gtk_icon_theme_has_icon(theme, "audacious"))
-        icon = gtk_status_icon_new_from_icon_name("audacious");
-    else
-    {
-        gchar * path = g_strdup_printf ("%s/images/audacious.png",
-         aud_get_path (AUD_PATH_DATA_DIR));
-        icon = gtk_status_icon_new_from_file (path);
-        g_free (path);
-    }
-
-    return icon;
-}
-
-static gboolean si_cb_btpress(GtkStatusIcon * icon, GdkEventButton * event, gpointer user_data)
-{
-    if (event->type != GDK_BUTTON_PRESS)
-        return FALSE;
-
-    si_popup_timer_stop(icon);
-    si_popup_hide(icon);
-
-    switch (event->button)
-    {
-      case 1:
-      {
-          if (event->state & GDK_SHIFT_MASK)
-              aud_drct_pl_next();
-          else if (! aud_headless_mode ())
-              aud_interface_show (! aud_interface_is_shown ());
-          break;
-      }
-
-      case 2:
-      {
-          aud_drct_pause();
-          break;
-      }
-
-      case 3:
-          if (event->state & GDK_SHIFT_MASK)
-              aud_drct_pl_prev();
-          else
-          {
-              if (recreate_smallmenu == TRUE)
-                  si_smallmenu_recreate(icon);
-              si_smallmenu_show(event->x_root, event->y_root, 3, event->time, icon);
-          }
-          break;
-    }
-
-    return TRUE;
-}
-
-static gboolean si_cb_btscroll(GtkStatusIcon * icon, GdkEventScroll * event, gpointer user_data)
-{
-    switch (event->direction)
-    {
-      case GDK_SCROLL_UP:
-      {
-          switch (aud_get_int ("statusicon", "scroll_action"))
-          {
-            case SI_CFG_SCROLL_ACTION_VOLUME:
-                si_volume_change (aud_get_int ("statusicon", "volume_delta"));
-                break;
-            case SI_CFG_SCROLL_ACTION_SKIP:
-                if (aud_get_bool ("statusicon", "reverse_scroll"))
-                    aud_drct_pl_next ();
-                else
-                    aud_drct_pl_prev ();
-                break;
-          }
-          break;
-      }
-
-      case GDK_SCROLL_DOWN:
-      {
-          switch (aud_get_int ("statusicon", "scroll_action"))
-          {
-            case SI_CFG_SCROLL_ACTION_VOLUME:
-                si_volume_change (-aud_get_int ("statusicon", "volume_delta"));
-                break;
-            case SI_CFG_SCROLL_ACTION_SKIP:
-                if (aud_get_bool ("statusicon", "reverse_scroll"))
-                    aud_drct_pl_prev ();
-                else
-                    aud_drct_pl_next ();
-                break;
-          }
-          break;
-      }
-
-      default:;
-    }
-
-    return FALSE;
-}
-
-static gboolean si_popup_show(gpointer icon)
-{
-    GdkRectangle area;
-    gint x, y;
-    static gint count = 0;
-
-    audgui_get_mouse_coords (NULL, & x, & y);
-    gtk_status_icon_get_geometry (icon, NULL, & area, NULL);
-
-    if (x < area.x || x > area.x + area.width || y < area.y || y > area.y + area.width)
-    {
-        si_popup_timer_stop(icon);
-        si_popup_hide(icon);
-        count = 0;
-
-        return TRUE;
-    }
-
-    if (!POPUP_IS_ACTIVE)
-    {
-        if (count < 10)
-        {
-            count++;
-            return TRUE;
-        }
-        else
-            count = 0;
-
-        audgui_infopopup_show_current();
-        g_object_set_data(G_OBJECT(icon), "popup_active", GINT_TO_POINTER(1));
-    }
-
-    return TRUE;
-}
-
-static void si_popup_hide(gpointer icon)
-{
-    if (POPUP_IS_ACTIVE)
-    {
-        g_object_set_data(G_OBJECT(icon), "popup_active", GINT_TO_POINTER(0));
-        audgui_infopopup_hide();
-    }
-}
-
-static void si_popup_reshow(gpointer data, gpointer icon)
-{
-    if (POPUP_IS_ACTIVE)
-    {
-        audgui_infopopup_hide();
-        audgui_infopopup_show_current();
-    }
-}
-
-static void si_popup_timer_start(GtkStatusIcon * icon)
-{
-    gint timer_id = g_timeout_add(100, si_popup_show, icon);
-    g_object_set_data(G_OBJECT(icon), "timer_id", GINT_TO_POINTER(timer_id));
-    g_object_set_data(G_OBJECT(icon), "timer_active", GINT_TO_POINTER(1));
-}
-
-static void si_popup_timer_stop(GtkStatusIcon * icon)
-{
-    if (TIMER_IS_ACTIVE)
-        g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon), "timer_id")));
-
-    g_object_set_data(G_OBJECT(icon), "timer_id", GINT_TO_POINTER(0));
-    g_object_set_data(G_OBJECT(icon), "timer_active", GINT_TO_POINTER(0));
-}
-
-static gboolean si_cb_tooltip(GtkStatusIcon * icon, gint x, gint y, gboolean keyboard_mode, GtkTooltip * tooltip, gpointer user_data)
-{
-    GtkWidget *menu = g_object_get_data(G_OBJECT(icon), "smenu");
-
-    if (aud_get_bool("statusicon", "disable_popup") || gtk_widget_get_visible(menu))
-        return FALSE;
-
-    if (!POPUP_IS_ACTIVE && !TIMER_IS_ACTIVE)
-        si_popup_timer_start(icon);
-
-    return FALSE;
-}
-
-static void si_smallmenu_show(gint x, gint y, guint button, guint32 time, gpointer evbox)
-{
-    GtkWidget *si_smenu = g_object_get_data(G_OBJECT(evbox), "smenu");
-    gtk_menu_popup(GTK_MENU(si_smenu), NULL, NULL, NULL, NULL, button, time);
-}
-
-static void open_files (void)
-{
-    audgui_run_filebrowser (TRUE);
-}
-
-static GtkWidget *si_smallmenu_create(void)
-{
-    static const AudguiMenuItem items[] = {
-        {N_("_Open Files ..."), "document-open", .func = open_files},
-        {N_("Pre_vious"), "media-skip-backward", .func = aud_drct_pl_prev},
-        {N_("_Play"), "media-playback-start", .func = aud_drct_play},
-        {N_("Paus_e"), "media-playback-pause", .func = aud_drct_pause},
-        {N_("_Stop"), "media-playback-stop", .func = aud_drct_stop},
-        {N_("_Next"), "media-skip-forward", .func = aud_drct_pl_next},
-        {.sep = TRUE},
-        {N_("Se_ttings ..."), "preferences-system", .func = aud_show_prefs_window},
-        {N_("_Quit"), "application-exit", .func = aud_drct_quit}
-    };
-
-    GtkWidget *si_smenu = gtk_menu_new();
-    audgui_menu_init (si_smenu, items, ARRAY_LEN (items), NULL);
-    return si_smenu;
-}
-
-static void si_smallmenu_recreate(GtkStatusIcon * icon)
-{
-    GtkWidget *smenu = g_object_get_data(G_OBJECT(icon), "smenu");
-    gtk_widget_destroy(GTK_WIDGET(smenu));
-    smenu = si_smallmenu_create();
-    g_object_set_data(G_OBJECT(icon), "smenu", smenu);
-    recreate_smallmenu = FALSE;
-}
-
-static void si_window_close(gpointer data, gpointer user_data)
-{
-    gboolean *handle = (gboolean*) data;
-
-    if (aud_get_bool ("statusicon", "close_to_tray"))
-    {
-        *handle = TRUE;
-        aud_interface_show (FALSE);
-    }
-}
-
-static void si_enable(gboolean enable)
-{
-    static GtkStatusIcon *si_applet = NULL;
-
-    if (enable && ! si_applet)
-    {
-        GtkWidget *si_smenu;
-
-        si_applet = si_create();
-
-        if (si_applet == NULL)
-        {
-            g_warning("StatusIcon plugin: unable to create a status icon.\n");
-            return;
-        }
-
-        g_object_set_data(G_OBJECT(si_applet), "timer_id", GINT_TO_POINTER(0));
-        g_object_set_data(G_OBJECT(si_applet), "timer_active", GINT_TO_POINTER(0));
-        g_object_set_data(G_OBJECT(si_applet), "popup_active", GINT_TO_POINTER(0));
-
-        g_signal_connect(G_OBJECT(si_applet), "button-press-event", G_CALLBACK(si_cb_btpress), NULL);
-        g_signal_connect(G_OBJECT(si_applet), "scroll-event", G_CALLBACK(si_cb_btscroll), NULL);
-        g_signal_connect(G_OBJECT(si_applet), "query-tooltip", G_CALLBACK(si_cb_tooltip), NULL);
-
-        gtk_status_icon_set_has_tooltip(si_applet, TRUE);
-        gtk_status_icon_set_visible(si_applet, TRUE);
-
-        /* small menu that can be used in place of the audacious standard one */
-        si_smenu = si_smallmenu_create();
-        g_object_set_data(G_OBJECT(si_applet), "smenu", si_smenu);
-
-        hook_associate("title change", si_popup_reshow, si_applet);
-        hook_associate("window close", si_window_close, NULL);
-    }
-
-    if (! enable && si_applet)
-    {
-        /* Prevent accidentally hiding of the interface
-         * by disabling the plugin while Audacious is closed to the tray. */
-        extern GeneralPlugin _aud_plugin_self;
-        PluginHandle *si = aud_plugin_by_header(&_aud_plugin_self);
-        if (! aud_plugin_get_enabled(si) && ! aud_headless_mode() && ! aud_interface_is_shown())
-            aud_interface_show(TRUE);
-
-        GtkWidget *si_smenu = g_object_get_data(G_OBJECT(si_applet), "smenu");
-        si_popup_timer_stop(si_applet);   /* just in case the timer is active */
-        gtk_widget_destroy(si_smenu);
-        g_object_unref(si_applet);
-        si_applet = NULL;
-
-        hook_dissociate("title change", si_popup_reshow);
-        hook_dissociate("window close", si_window_close);
-    }
-}
-
-static gboolean si_init (void)
-{
-    aud_config_set_defaults ("statusicon", si_defaults);
-    plugin_active = TRUE;
-    si_enable(TRUE);
-    return TRUE;
-}
-
-void si_cleanup(void)
-{
-    if (!plugin_active)
-        return;
-
-    plugin_active = FALSE;
-    si_enable(FALSE);
-}
-
-static const char si_about[] =
- N_("Status Icon Plugin\n\n"
-    "Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
-    "Copyright 2010 Michał Lipski <tallica at o2.pl>\n\n"
-    "This plugin provides a status icon, placed in\n"
-    "the system tray area of the window manager.");
-
-static const PreferencesWidget si_widgets[] = {
- {WIDGET_LABEL, N_("<b>Mouse Scroll Action</b>")},
- {WIDGET_RADIO_BTN, N_("Change volume"),
-  .cfg_type = VALUE_INT, .csect = "statusicon", .cname = "scroll_action",
-  .data = {.radio_btn = {SI_CFG_SCROLL_ACTION_VOLUME}}},
- {WIDGET_RADIO_BTN, N_("Change playing song"),
-  .cfg_type = VALUE_INT, .csect = "statusicon", .cname = "scroll_action",
-  .data = {.radio_btn = {SI_CFG_SCROLL_ACTION_SKIP}}},
- {WIDGET_LABEL, N_("<b>Other Settings</b>")},
- {WIDGET_CHK_BTN, N_("Disable the popup window"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "statusicon", .cname = "disable_popup"},
- {WIDGET_CHK_BTN, N_("Close to the system tray"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "statusicon", .cname = "close_to_tray"},
- {WIDGET_CHK_BTN, N_("Advance in playlist when scrolling upward"),
-  .cfg_type = VALUE_BOOLEAN, .csect = "statusicon", .cname = "reverse_scroll"}};
-
-static const PluginPreferences si_prefs = {
- .widgets = si_widgets,
- .n_widgets = ARRAY_LEN (si_widgets)};
-
-AUD_GENERAL_PLUGIN
-(
-    .name = N_("Status Icon"),
-    .domain = PACKAGE,
-    .about_text = si_about,
-    .prefs = & si_prefs,
-    .init = si_init,
-    .cleanup = si_cleanup,
-)
diff --git a/src/statusicon/statusicon.cc b/src/statusicon/statusicon.cc
new file mode 100644
index 000000000000..5c5f38743cb2
--- /dev/null
+++ b/src/statusicon/statusicon.cc
@@ -0,0 +1,395 @@
+/*
+ * Status Icon Plugin for Audacious
+ *
+ * Copyright 2005-2007 Giacomo Lozito <james at develia.org>
+ * Copyright 2010 Michał Lipski <tallica at o2.pl>
+ *
+ * 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
+ */
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/drct.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/interface.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/plugins.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/hook.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+#include <libaudgui/menu.h>
+
+class StatusIcon : public GeneralPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Status Icon"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr StatusIcon () : GeneralPlugin (info, false) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT StatusIcon aud_plugin_instance;
+
+#define POPUP_IS_ACTIVE GPOINTER_TO_INT (g_object_get_data ((GObject *) icon, "popup_active"))
+#define TIMER_IS_ACTIVE GPOINTER_TO_INT (g_object_get_data ((GObject *) icon, "timer_active"))
+
+enum {
+    SI_CFG_SCROLL_ACTION_VOLUME,
+    SI_CFG_SCROLL_ACTION_SKIP
+};
+
+static void si_popup_timer_start (GtkStatusIcon * icon);
+static void si_popup_timer_stop (GtkStatusIcon * icon);
+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 */
+    "volume_delta", "5",
+    "disable_popup", "FALSE",
+    "close_to_tray", "FALSE",
+    "reverse_scroll", "FALSE",
+    nullptr
+};
+
+static GtkStatusIcon * si_create ()
+{
+    GtkStatusIcon * icon;
+    GtkIconTheme * theme = gtk_icon_theme_get_default ();
+
+    if (gtk_icon_theme_has_icon (theme, "audacious-panel"))
+        icon = gtk_status_icon_new_from_icon_name ("audacious-panel");
+    else if (gtk_icon_theme_has_icon (theme, "audacious"))
+        icon = gtk_status_icon_new_from_icon_name ("audacious");
+    else
+        icon = gtk_status_icon_new_from_file (aud_get_path (AudPath::IconFile));
+
+    return icon;
+}
+
+static void si_volume_change (int value)
+{
+    aud_drct_set_volume_main (aud_drct_get_volume_main () + value);
+}
+
+static gboolean si_cb_btpress (GtkStatusIcon * icon, GdkEventButton * event)
+{
+    if (event->type != GDK_BUTTON_PRESS)
+        return false;
+
+    si_popup_timer_stop (icon);
+    si_popup_hide (icon);
+
+    switch (event->button)
+    {
+      case 1:
+          if (event->state & GDK_SHIFT_MASK)
+              aud_drct_pl_next ();
+          else if (! aud_get_headless_mode ())
+              aud_ui_show (! aud_ui_is_shown ());
+          break;
+
+      case 2:
+          aud_drct_pause ();
+          break;
+
+      case 3:
+          if (event->state & GDK_SHIFT_MASK)
+              aud_drct_pl_prev ();
+          else
+              si_menu_show (event->x_root, event->y_root, event->button, event->time, icon);
+          break;
+    }
+
+    return true;
+}
+
+static gboolean si_cb_btscroll (GtkStatusIcon * icon, GdkEventScroll * event)
+{
+    switch (event->direction)
+    {
+      case GDK_SCROLL_UP:
+      {
+          switch (aud_get_int ("statusicon", "scroll_action"))
+          {
+            case SI_CFG_SCROLL_ACTION_VOLUME:
+                si_volume_change (aud_get_int ("statusicon", "volume_delta"));
+                break;
+            case SI_CFG_SCROLL_ACTION_SKIP:
+                if (aud_get_bool ("statusicon", "reverse_scroll"))
+                    aud_drct_pl_next ();
+                else
+                    aud_drct_pl_prev ();
+                break;
+          }
+          break;
+      }
+
+      case GDK_SCROLL_DOWN:
+      {
+        switch (aud_get_int ("statusicon", "scroll_action"))
+        {
+          case SI_CFG_SCROLL_ACTION_VOLUME:
+              si_volume_change (-aud_get_int ("statusicon", "volume_delta"));
+              break;
+          case SI_CFG_SCROLL_ACTION_SKIP:
+              if (aud_get_bool ("statusicon", "reverse_scroll"))
+                  aud_drct_pl_prev ();
+              else
+                  aud_drct_pl_next ();
+              break;
+        }
+        break;
+      }
+
+      default:
+        break;
+    }
+
+    return false;
+}
+
+static gboolean si_popup_show (void * icon)
+{
+    int x, y;
+    GdkRectangle area;
+    static int count = 0;
+
+    audgui_get_mouse_coords (gtk_status_icon_get_screen ((GtkStatusIcon *) icon), & x, & y);
+    gtk_status_icon_get_geometry ((GtkStatusIcon *) icon, nullptr, & area, nullptr);
+
+    if (x < area.x || x > area.x + area.width || y < area.y || y > area.y + area.width)
+    {
+        si_popup_timer_stop ((GtkStatusIcon *) icon);
+        si_popup_hide ((GtkStatusIcon *) icon);
+        count = 0;
+
+        return true;
+    }
+
+    if (! POPUP_IS_ACTIVE)
+    {
+        if (count < 10)
+        {
+            count ++;
+            return true;
+        }
+        else
+            count = 0;
+
+        audgui_infopopup_show_current ();
+        g_object_set_data ((GObject *) icon, "popup_active", GINT_TO_POINTER (1));
+    }
+
+    return true;
+}
+
+static void si_popup_hide (void * icon)
+{
+    if (POPUP_IS_ACTIVE)
+    {
+        g_object_set_data ((GObject *) icon, "popup_active", GINT_TO_POINTER (0));
+        audgui_infopopup_hide ();
+    }
+}
+
+static void si_popup_reshow (void * data, void * icon)
+{
+    if (POPUP_IS_ACTIVE)
+    {
+        audgui_infopopup_hide ();
+        audgui_infopopup_show_current ();
+    }
+}
+
+static void si_popup_timer_start (GtkStatusIcon * icon)
+{
+    int timer_id = g_timeout_add (100, si_popup_show, icon);
+    g_object_set_data ((GObject *) icon, "timer_id", GINT_TO_POINTER (timer_id));
+    g_object_set_data ((GObject *) icon, "timer_active", GINT_TO_POINTER (1));
+}
+
+static void si_popup_timer_stop (GtkStatusIcon * icon)
+{
+    if (TIMER_IS_ACTIVE)
+        g_source_remove (GPOINTER_TO_INT (g_object_get_data ((GObject *) icon, "timer_id")));
+
+    g_object_set_data ((GObject *) icon, "timer_id", GINT_TO_POINTER (0));
+    g_object_set_data ((GObject *) icon, "timer_active", GINT_TO_POINTER (0));
+}
+
+static gboolean si_cb_tooltip (GtkStatusIcon * icon, int x, int y, gboolean keyboard_mode, GtkTooltip * tooltip)
+{
+    GtkWidget * menu = (GtkWidget *) g_object_get_data ((GObject *) icon, "menu");
+
+    if (aud_get_bool ("statusicon", "disable_popup") || gtk_widget_get_visible (menu))
+        return false;
+
+    if (! POPUP_IS_ACTIVE && ! TIMER_IS_ACTIVE)
+        si_popup_timer_start (icon);
+
+    return false;
+}
+
+static void si_menu_show (int x, int y, unsigned button, uint32_t time, void * evbox)
+{
+    GtkWidget * si_menu = (GtkWidget *) g_object_get_data ((GObject *) evbox, "menu");
+    gtk_menu_popup ((GtkMenu *) si_menu, nullptr, nullptr, nullptr, nullptr, button, time);
+}
+
+static void open_files ()
+{
+    audgui_run_filebrowser (true);
+}
+
+static GtkWidget * si_menu_create ()
+{
+    static const AudguiMenuItem items[] = {
+        MenuCommand (N_("_Open Files ..."), "document-open", 0, (GdkModifierType) 0, open_files),
+        MenuCommand (N_("Pre_vious"), "media-skip-backward", 0, (GdkModifierType) 0, aud_drct_pl_prev),
+        MenuCommand (N_("_Play"), "media-playback-start", 0, (GdkModifierType) 0, aud_drct_play),
+        MenuCommand (N_("Paus_e"), "media-playback-pause", 0, (GdkModifierType) 0, aud_drct_pause),
+        MenuCommand (N_("_Stop"), "media-playback-stop", 0, (GdkModifierType) 0, aud_drct_stop),
+        MenuCommand (N_("_Next"), "media-skip-forward", 0, (GdkModifierType) 0, aud_drct_pl_next),
+        MenuSep (),
+        MenuCommand (N_("Se_ttings ..."), "preferences-system", 0, (GdkModifierType) 0, audgui_show_prefs_window),
+        MenuCommand (N_("_Quit"), "application-exit", 0, (GdkModifierType) 0, aud_quit)
+    };
+
+    GtkWidget * si_menu = gtk_menu_new ();
+    audgui_menu_init (si_menu, {items}, nullptr);
+    return si_menu;
+}
+
+static void si_window_close (void * data, void * user_data)
+{
+    bool * handle = (bool *) data;
+
+    if (aud_get_bool ("statusicon", "close_to_tray"))
+    {
+        * handle = true;
+        aud_ui_show (false);
+    }
+}
+
+static void si_enable (bool enable)
+{
+    static GtkStatusIcon * si_applet = nullptr;
+
+    if (enable && ! si_applet)
+    {
+        si_applet = si_create ();
+
+        if (! si_applet)
+        {
+            AUDWARN ("StatusIcon plugin: unable to create a status icon.\n");
+            return;
+        }
+
+        g_object_set_data ((GObject *) si_applet, "timer_id", GINT_TO_POINTER (0));
+        g_object_set_data ((GObject *) si_applet, "timer_active", GINT_TO_POINTER (0));
+        g_object_set_data ((GObject *) si_applet, "popup_active", GINT_TO_POINTER (0));
+
+        g_signal_connect (si_applet, "button-press-event", (GCallback) si_cb_btpress, nullptr);
+        g_signal_connect (si_applet, "scroll-event", (GCallback) si_cb_btscroll, nullptr);
+        g_signal_connect (si_applet, "query-tooltip", (GCallback) si_cb_tooltip, nullptr);
+
+        gtk_status_icon_set_has_tooltip (si_applet, true);
+        gtk_status_icon_set_visible (si_applet, true);
+
+        GtkWidget * si_menu = si_menu_create ();
+        g_object_set_data ((GObject *) si_applet, "menu", si_menu);
+
+        hook_associate ("title change", si_popup_reshow, si_applet);
+        hook_associate ("window close", si_window_close, nullptr);
+    }
+
+    if (! enable && si_applet)
+    {
+        /* Prevent accidentally hiding of the interface
+         * by disabling the plugin while Audacious is closed to the tray. */
+        PluginHandle * si = aud_plugin_by_header (& aud_plugin_instance);
+        if (! aud_plugin_get_enabled (si) && ! aud_get_headless_mode () && ! aud_ui_is_shown ())
+            aud_ui_show (true);
+
+        GtkWidget * si_menu = (GtkWidget *) g_object_get_data ((GObject *) si_applet, "menu");
+        si_popup_timer_stop (si_applet);  /* just in case the timer is active */
+        gtk_widget_destroy (si_menu);
+        g_object_unref (si_applet);
+        si_applet = nullptr;
+
+        hook_dissociate ("title change", si_popup_reshow);
+        hook_dissociate ("window close", si_window_close);
+    }
+}
+
+bool StatusIcon::init ()
+{
+    if (aud_get_mainloop_type () != MainloopType::GLib)
+        return false;
+
+    aud_config_set_defaults ("statusicon", defaults);
+    audgui_init ();
+    si_enable (true);
+    return true;
+}
+
+void StatusIcon::cleanup ()
+{
+    si_enable (false);
+    audgui_cleanup ();
+}
+
+const char StatusIcon::about[] =
+ N_("Status Icon Plugin\n\n"
+    "Copyright 2005-2007 Giacomo Lozito <james at develia.org>\n"
+    "Copyright 2010 Michał Lipski <tallica at o2.pl>\n\n"
+    "This plugin provides a status icon, placed in\n"
+    "the system tray area of the window manager.");
+
+const PreferencesWidget StatusIcon::widgets[] = {
+    WidgetLabel (N_("<b>Mouse Scroll Action</b>")),
+    WidgetRadio (N_("Change volume"),
+        WidgetInt ("statusicon", "scroll_action"),
+        {SI_CFG_SCROLL_ACTION_VOLUME}),
+    WidgetRadio (N_("Change playing song"),
+        WidgetInt ("statusicon", "scroll_action"),
+        {SI_CFG_SCROLL_ACTION_SKIP}),
+    WidgetLabel (N_("<b>Other Settings</b>")),
+    WidgetCheck (N_("Disable the popup window"),
+        WidgetBool ("statusicon", "disable_popup")),
+    WidgetCheck (N_("Close to the system tray"),
+        WidgetBool ("statusicon", "close_to_tray")),
+    WidgetCheck (N_("Advance in playlist when scrolling upward"),
+        WidgetBool ("statusicon", "reverse_scroll"))
+};
+
+const PluginPreferences StatusIcon::prefs = {{widgets}};
diff --git a/src/statusicon/statusicon.h b/src/statusicon/statusicon.h
deleted file mode 100644
index b8c2a19a4790..000000000000
--- a/src/statusicon/statusicon.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* Status Icon Plugin for Audacious
-*
-* Copyright 2005-2007 Giacomo Lozito <james at develia.org>
-* Copyright 2010 Michał Lipski <tallica at o2.pl>
-*
-* 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 STATUS_ICON_H
-#define STATUS_ICON_H
-
-enum {
-    SI_CFG_SCROLL_ACTION_VOLUME,
-    SI_CFG_SCROLL_ACTION_SKIP
-};
-
-/* util.c */
-void si_volume_change (int value);
-
-#endif
diff --git a/src/statusicon/util.c b/src/statusicon/util.c
deleted file mode 100644
index 5d2ec5e0f874..000000000000
--- a/src/statusicon/util.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-* Status Icon Plugin for Audacious
-*
-* Copyright 2005-2007 Giacomo Lozito <james at develia.org>
-* Copyright 2010 Michał Lipski <tallica at o2.pl>
-*
-* 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
-*
-*/
-
-#include <glib.h>
-
-#include <audacious/drct.h>
-#include <libaudgui/libaudgui.h>
-
-#include "statusicon.h"
-
-void si_volume_change(gint value)
-{
-    gint vl, vr;
-    aud_drct_get_volume(&vl, &vr);
-    aud_drct_set_volume(CLAMP(vl + value, 0, 100), CLAMP(vr + value, 0, 100));
-}
diff --git a/src/stereo_plugin/Makefile b/src/stereo_plugin/Makefile
index dcadd2d3c40f..f9e9d0c0515b 100644
--- a/src/stereo_plugin/Makefile
+++ b/src/stereo_plugin/Makefile
@@ -1,11 +1,12 @@
 PLUGIN = stereo${PLUGIN_SUFFIX}
 
-SRCS = stereo.c
+SRCS = stereo.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/stereo_plugin/stereo.c b/src/stereo_plugin/stereo.c
deleted file mode 100644
index 3ec2cb8ba008..000000000000
--- a/src/stereo_plugin/stereo.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Extra Stereo Plugin for Audacious
- * Written by Johan Levin, 1999
- * Modified by John Lindgren, 2009-2012 */
-
-#include <audacious/i18n.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/preferences.h>
-
-static bool_t init (void);
-
-static void stereo_start (int * channels, int * rate);
-static void stereo_process (float * * data, int * samples);
-static void stereo_finish (float * * data, int * samples);
-
-static const char stereo_about[] =
- N_("Extra Stereo Plugin\n\n"
-    "By Johan Levin, 1999");
-
-static const char * const stereo_defaults[] = {
- "intensity", "2.5",
- NULL};
-
-static const PreferencesWidget stereo_widgets[] = {
- {WIDGET_LABEL, N_("<b>Extra Stereo</b>")},
- {WIDGET_SPIN_BTN, N_("Intensity:"),
-  .cfg_type = VALUE_FLOAT, .csect = "extra_stereo", .cname = "intensity",
-  .data = {.spin_btn = {0, 10, 0.1}}}};
-
-static const PluginPreferences stereo_prefs = {
- .widgets = stereo_widgets,
- .n_widgets = ARRAY_LEN (stereo_widgets)};
-
-AUD_EFFECT_PLUGIN
-(
-    .name = N_("Extra Stereo"),
-    .domain = PACKAGE,
-    .about_text = stereo_about,
-    .prefs = & stereo_prefs,
-    .init = init,
-    .start = stereo_start,
-    .process = stereo_process,
-    .finish = stereo_finish,
-    .preserves_format = TRUE
-)
-
-static bool_t init (void)
-{
-    aud_config_set_defaults ("extra_stereo", stereo_defaults);
-    return TRUE;
-}
-
-static int stereo_channels;
-
-static void stereo_start (int * channels, int * rate)
-{
-    stereo_channels = * channels;
-}
-
-static void stereo_process (float * * data, int * samples)
-{
-    float value = aud_get_double ("extra_stereo", "intensity");
-    float * f, * end;
-    float center;
-
-    if (stereo_channels != 2 || samples == 0)
-        return;
-
-    end = (* data) + (* samples);
-
-    for (f = * data; f < end; f += 2)
-    {
-        center = (f[0] + f[1]) / 2;
-        f[0] = center + (f[0] - center) * value;
-        f[1] = center + (f[1] - center) * value;
-    }
-}
-
-static void stereo_finish (float * * data, int * samples)
-{
-    stereo_process (data, samples);
-}
diff --git a/src/stereo_plugin/stereo.cc b/src/stereo_plugin/stereo.cc
new file mode 100644
index 000000000000..c6e875bfd39e
--- /dev/null
+++ b/src/stereo_plugin/stereo.cc
@@ -0,0 +1,84 @@
+/* Extra Stereo Plugin for Audacious
+ * Written by Johan Levin, 1999
+ * Modified by John Lindgren, 2009-2012 */
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+
+class ExtraStereo : public EffectPlugin
+{
+public:
+    static const char about[];
+    static const char * const defaults[];
+    static const PreferencesWidget widgets[];
+    static const PluginPreferences prefs;
+
+    static constexpr PluginInfo info = {
+        N_("Extra Stereo"),
+        PACKAGE,
+        about,
+        & prefs
+    };
+
+    constexpr ExtraStereo () : EffectPlugin (info, 0, true) {}
+
+    bool init ();
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+};
+
+EXPORT ExtraStereo aud_plugin_instance;
+
+const char ExtraStereo::about[] =
+ N_("Extra Stereo Plugin\n\n"
+    "By Johan Levin, 1999");
+
+const char * const ExtraStereo::defaults[] = {
+ "intensity", "2.5",
+ nullptr};
+
+const PreferencesWidget ExtraStereo::widgets[] = {
+    WidgetLabel (N_("<b>Extra Stereo</b>")),
+    WidgetSpin (N_("Intensity:"),
+        WidgetFloat ("extra_stereo", "intensity"),
+        {0, 10, 0.1})
+};
+
+const PluginPreferences ExtraStereo::prefs = {{widgets}};
+
+bool ExtraStereo::init ()
+{
+    aud_config_set_defaults ("extra_stereo", defaults);
+    return true;
+}
+
+static int stereo_channels;
+
+void ExtraStereo::start (int & channels, int & rate)
+{
+    stereo_channels = channels;
+}
+
+Index<float> & ExtraStereo::process(Index<float> & data)
+{
+    float value = aud_get_double ("extra_stereo", "intensity");
+    float * f, * end;
+    float center;
+
+    if (stereo_channels != 2)
+        return data;
+
+    end = data.end ();
+
+    for (f = data.begin (); f < end; f += 2)
+    {
+        center = (f[0] + f[1]) / 2;
+        f[0] = center + (f[0] - center) * value;
+        f[1] = center + (f[1] - center) * value;
+    }
+
+    return data;
+}
diff --git a/src/tonegen/Makefile b/src/tonegen/Makefile
index 4a0161f0e46d..ae998b0b6b59 100644
--- a/src/tonegen/Makefile
+++ b/src/tonegen/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = tonegen${PLUGIN_SUFFIX}
 
-SRCS = tonegen.c
+SRCS = tonegen.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS}  -I../..
-LIBS += ${GLIB_LIBS} -lm
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
+LIBS += -lm
diff --git a/src/tonegen/tonegen.c b/src/tonegen/tonegen.c
deleted file mode 100644
index 5143d6bc1ae6..000000000000
--- a/src/tonegen/tonegen.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *  Copyright 2000, 2001 Håvard Kvålen <havardk at sol.no>
- *
- *  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.
- */
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#define MIN_FREQ        10
-#define MAX_FREQ        20000
-#define OUTPUT_FREQ     44100
-#define BUF_SAMPLES     512
-#define BUF_BYTES       (BUF_SAMPLES * sizeof(float))
-
-#ifndef PI
-#define PI              3.14159265358979323846
-#endif
-
-static gboolean tone_is_our_fd(const gchar *filename, VFSFile *fd)
-{
-    if (!strncmp(filename, "tone://", 7))
-        return TRUE;
-    return FALSE;
-}
-
-static GArray *tone_filename_parse(const gchar * filename)
-{
-    GArray *frequencies = g_array_new(FALSE, FALSE, sizeof(double));
-    gchar **strings, **ptr;
-
-    if (strncmp(filename, "tone://", 7))
-        return NULL;
-
-    strings = g_strsplit(filename + 7, ";", 100);
-
-    for (ptr = strings; *ptr != NULL; ptr++)
-    {
-        gdouble freq = strtod(*ptr, NULL);
-        if (freq >= MIN_FREQ && freq <= MAX_FREQ)
-            g_array_append_val(frequencies, freq);
-    }
-    g_strfreev(strings);
-
-    if (frequencies->len == 0)
-    {
-        g_array_free(frequencies, TRUE);
-        frequencies = NULL;
-    }
-
-    return frequencies;
-}
-
-static gchar *tone_title(const gchar * filename)
-{
-    GArray *freqs;
-    gchar *title;
-    gsize i;
-
-    freqs = tone_filename_parse(filename);
-    if (freqs == NULL)
-        return NULL;
-
-    title = g_strdup_printf(_("%s %.1f Hz"), _("Tone Generator: "), g_array_index(freqs, double, 0));
-    for (i = 1; i < freqs->len; i++)
-    {
-        gchar *old_title = title;
-        title = g_strdup_printf("%s;%.1f Hz", old_title, g_array_index(freqs, double, i));
-        g_free(old_title);
-    }
-    g_array_free(freqs, TRUE);
-
-    return title;
-}
-
-static gboolean tone_play(const gchar *filename, VFSFile *file)
-{
-    GArray *frequencies;
-    gfloat data[BUF_SAMPLES];
-    gsize i;
-    gboolean error = FALSE;
-    struct
-    {
-        gdouble wd;
-        guint period, t;
-    } *tone = NULL;
-
-    frequencies = tone_filename_parse(filename);
-    if (frequencies == NULL)
-        return FALSE;
-
-    if (aud_input_open_audio(FMT_FLOAT, OUTPUT_FREQ, 1) == 0)
-    {
-        error = TRUE;
-        goto error_exit;
-    }
-
-    aud_input_set_bitrate(16 * OUTPUT_FREQ);
-
-    tone = g_malloc(frequencies->len * sizeof(*tone));
-    for (i = 0; i < frequencies->len; i++)
-    {
-        gdouble f = g_array_index(frequencies, gdouble, i);
-        tone[i].wd = 2 * PI * f / OUTPUT_FREQ;
-        tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * (OUTPUT_FREQ / f);
-        tone[i].t = 0;
-    }
-
-    while (!aud_input_check_stop())
-    {
-        for (i = 0; i < BUF_SAMPLES; i++)
-        {
-            gsize j;
-            double sum_sines;
-
-            for (sum_sines = 0, j = 0; j < frequencies->len; j++)
-            {
-                sum_sines += sin(tone[j].wd * tone[j].t);
-                if (tone[j].t > tone[j].period)
-                    tone[j].t -= tone[j].period;
-                tone[j].t++;
-            }
-            /* dithering can cause a little bit of clipping */
-            data[i] = (sum_sines * 0.999 / (gdouble) frequencies->len);
-        }
-
-        aud_input_write_audio(data, BUF_BYTES);
-    }
-
-error_exit:
-    g_array_free(frequencies, TRUE);
-    g_free(tone);
-
-    return !error;
-}
-
-static Tuple *tone_probe_for_tuple(const gchar *filename, VFSFile *fd)
-{
-    Tuple *tuple = tuple_new_from_filename(filename);
-    gchar *tmp;
-
-    if (tuple == NULL)
-        return NULL;
-
-    if ((tmp = tone_title(filename)) != NULL)
-    {
-        tuple_set_str(tuple, FIELD_TITLE, tmp);
-        g_free(tmp);
-    }
-
-    return tuple;
-}
-
-static const char tone_about[] =
- N_("Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
-    "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n\n"
-    "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
-    "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone");
-
-static const gchar * const schemes[] = {"tone", NULL};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Tone Generator"),
-    .domain = PACKAGE,
-    .about_text = tone_about,
-    .schemes = schemes,
-    .is_our_file_from_vfs = tone_is_our_fd,
-    .play = tone_play,
-    .probe_for_tuple = tone_probe_for_tuple
-)
diff --git a/src/tonegen/tonegen.cc b/src/tonegen/tonegen.cc
new file mode 100644
index 000000000000..9d9c9ef23e24
--- /dev/null
+++ b/src/tonegen/tonegen.cc
@@ -0,0 +1,165 @@
+/*
+ *  Copyright 2000, 2001 Håvard Kvålen <havardk at sol.no>
+ *
+ *  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.
+ */
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define MIN_FREQ        10
+#define MAX_FREQ        20000
+#define OUTPUT_FREQ     44100
+#define BUF_SAMPLES     512
+#define BUF_BYTES       (BUF_SAMPLES * sizeof(float))
+
+#ifndef PI
+#define PI              3.14159265358979323846
+#endif
+
+class ToneGen : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char *const schemes[];
+
+    static constexpr PluginInfo info = {
+        N_("Tone Generator"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo()
+        .with_schemes(schemes);
+
+    constexpr ToneGen() : InputPlugin(info, iinfo) {}
+
+    bool is_our_file(const char *filename, VFSFile &file);
+    Tuple read_tuple(const char *filename, VFSFile &file);
+    bool play(const char *filename, VFSFile &file);
+};
+
+EXPORT ToneGen aud_plugin_instance;
+
+bool ToneGen::is_our_file(const char *filename, VFSFile &file)
+{
+    if (!strncmp(filename, "tone://", 7))
+        return true;
+    return false;
+}
+
+static Index<double> tone_filename_parse(const char *filename)
+{
+    Index<double> frequencies;
+
+    if (strncmp(filename, "tone://", 7))
+        return frequencies;
+
+    auto strings = str_list_to_index(filename + 7, ";");
+
+    for (const char *str : strings)
+    {
+        double freq = strtod(str, nullptr);
+        if (freq >= MIN_FREQ && freq <= MAX_FREQ)
+            frequencies.append(freq);
+    }
+
+    return frequencies;
+}
+
+static StringBuf tone_title(const char *filename)
+{
+    auto freqs = tone_filename_parse(filename);
+    if (!freqs.len())
+        return StringBuf();
+
+    auto title = str_printf(_("%s %.1f Hz"), _("Tone Generator: "), freqs[0]);
+    for (int i = 1; i < freqs.len(); i++)
+        title.combine(str_printf(";%.1f Hz", freqs[i]));
+
+    return title;
+}
+
+struct tone_t
+{
+    double wd;
+    unsigned period, t;
+};
+
+bool ToneGen::play(const char *filename, VFSFile &file)
+{
+    float data[BUF_SAMPLES];
+
+    auto frequencies = tone_filename_parse(filename);
+    if (!frequencies.len())
+        return false;
+
+    set_stream_bitrate(16 * OUTPUT_FREQ);
+    open_audio(FMT_FLOAT, OUTPUT_FREQ, 1);
+
+    Index<tone_t> tone;
+    tone.resize(frequencies.len());
+    for (int i = 0; i < frequencies.len(); i++)
+    {
+        double f = frequencies[i];
+        tone[i].wd = 2 * PI * f / OUTPUT_FREQ;
+        tone[i].period = (INT_MAX * 2U / OUTPUT_FREQ) * (OUTPUT_FREQ / f);
+        tone[i].t = 0;
+    }
+
+    while (!check_stop())
+    {
+        for (int i = 0; i < BUF_SAMPLES; i++)
+        {
+            double sum_sines = 0;
+
+            for (int j = 0; j < frequencies.len(); j++)
+            {
+                sum_sines += sin(tone[j].wd * tone[j].t);
+                if (tone[j].t > tone[j].period)
+                    tone[j].t -= tone[j].period;
+                tone[j].t++;
+            }
+            /* dithering can cause a little bit of clipping */
+            data[i] = (sum_sines * 0.999 / (double)frequencies.len());
+        }
+
+        write_audio(data, BUF_BYTES);
+    }
+
+    return true;
+}
+
+Tuple ToneGen::read_tuple(const char *filename, VFSFile &file)
+{
+    Tuple tuple;
+    tuple.set_filename(filename);
+    tuple.set_str(Tuple::Title, tone_title(filename));
+    return tuple;
+}
+
+const char ToneGen::about[] =
+ N_("Sine tone generator by Håvard Kvålen <havardk at xmms.org>\n"
+    "Modified by Daniel J. Peng <danielpeng at bigfoot.com>\n\n"
+    "To use it, add a URL: tone://frequency1;frequency2;frequency3;...\n"
+    "e.g. tone://2000;2005 to play a 2000 Hz tone and a 2005 Hz tone");
+
+const char *const ToneGen::schemes[] = {"tone", nullptr};
diff --git a/src/voice_removal/Makefile b/src/voice_removal/Makefile
index 286924df390a..827b332329e9 100644
--- a/src/voice_removal/Makefile
+++ b/src/voice_removal/Makefile
@@ -1,11 +1,12 @@
 PLUGIN = voice_removal${PLUGIN_SUFFIX}
 
-SRCS = voice_removal.c
+SRCS = voice_removal.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${EFFECT_PLUGIN_DIR}
 
+LD = ${CXX}
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../..
diff --git a/src/voice_removal/voice_removal.c b/src/voice_removal/voice_removal.c
deleted file mode 100644
index 979a1b3c1966..000000000000
--- a/src/voice_removal/voice_removal.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-
-static int voice_channels;
-
-static void voice_start(int *channels, int *rate)
-{
-	voice_channels = *channels;
-}
-
-static void voice_process(float **d, int *samples)
-{
-	float *f = *d, *end;
-	end = *d + *samples;
-
-	if (voice_channels != 2)
-		return;
-
-	for (f = *d; f < end; f += 2)
-	{
-		f[0] -= f[1];
-		f[1] = f[0];
-	}
-}
-
-static void voice_finish(float **d, int *samples)
-{
-	voice_process(d, samples);
-}
-
-AUD_EFFECT_PLUGIN
-(
-	.name = N_("Voice Removal"),
-	.domain = PACKAGE,
-	.start = voice_start,
-	.process = voice_process,
-	.finish = voice_finish,
-	.preserves_format = TRUE
-)
diff --git a/src/voice_removal/voice_removal.cc b/src/voice_removal/voice_removal.cc
new file mode 100644
index 000000000000..c86804e9c852
--- /dev/null
+++ b/src/voice_removal/voice_removal.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 William Pitcock <nenolod at dereferenced.org>.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+
+class VoiceRemoval : public EffectPlugin
+{
+public:
+    static constexpr PluginInfo info = {
+        N_("Voice Removal"),
+        PACKAGE
+    };
+
+    constexpr VoiceRemoval () : EffectPlugin (info, 0, true) {}
+
+    void start (int & channels, int & rate);
+    Index<float> & process (Index<float> & data);
+};
+
+EXPORT VoiceRemoval aud_plugin_instance;
+
+static int voice_channels;
+
+void VoiceRemoval::start (int & channels, int & rate)
+{
+    voice_channels = channels;
+}
+
+Index<float> & VoiceRemoval::process (Index<float> & data)
+{
+    if (voice_channels != 2)
+        return data;
+
+    float * end = data.end ();
+
+    for (float * f = data.begin (); f < end; f += 2)
+    {
+        f[0] -= f[1];
+        f[1] = f[0];
+    }
+
+    return data;
+}
diff --git a/src/vorbis/Makefile b/src/vorbis/Makefile
index 739f6c93bbed..98d8059d660f 100644
--- a/src/vorbis/Makefile
+++ b/src/vorbis/Makefile
@@ -1,14 +1,16 @@
 PLUGIN = vorbis${PLUGIN_SUFFIX}
 
-SRCS = vcupdate.c \
-       vcedit.c		\
-       vorbis.c
+SRCS = vcupdate.cc \
+       vcedit.cc		\
+       vorbis.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${VORBIS_CFLAGS} ${GLIB_CFLAGS}  -I../..
 LIBS += ${VORBIS_LIBS} ${GLIB_LIBS}
diff --git a/src/vorbis/vcedit.c b/src/vorbis/vcedit.c
deleted file mode 100644
index dbc316c3ed1a..000000000000
--- a/src/vorbis/vcedit.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/* This program is licensed under the GNU Library General Public License, version 2,
- * a copy of which is included with this program (LICENCE.LGPL).
- *
- * (c) 2000-2001 Michael Smith <msmith at labyrinth.net.au>
- *
- *
- * Comment editing backend, suitable for use by nice frontend interfaces.
- *
- */
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-
-#include "vcedit.h"
-
-#define CHUNKSIZE 4096
-
-vcedit_state *
-vcedit_new_state(void)
-{
-    return g_new0(vcedit_state, 1);
-}
-
-char *
-vcedit_error(vcedit_state * state)
-{
-    return state->lasterror;
-}
-
-vorbis_comment *
-vcedit_comments(vcedit_state * state)
-{
-    return state->vc;
-}
-
-static void
-vcedit_clear_internals(vcedit_state * state)
-{
-    if (state->vc) {
-        vorbis_comment_clear(state->vc);
-        g_free(state->vc);
-        state->vc = NULL;
-    }
-    if (state->os) {
-        ogg_stream_clear(state->os);
-        g_free(state->os);
-        state->os = NULL;
-    }
-    if (state->oy) {
-        ogg_sync_clear(state->oy);
-        g_free(state->oy);
-        state->oy = NULL;
-    }
-    if (state->vendor) {
-        g_free(state->vendor);
-        state->vendor = NULL;
-    }
-}
-
-void
-vcedit_clear(vcedit_state * state)
-{
-    if (state) {
-        vcedit_clear_internals(state);
-        g_free(state);
-    }
-}
-
-/* Next two functions pulled straight from libvorbis, apart from one change
- * - we don't want to overwrite the vendor string.
- */
-static void
-_v_writestring(oggpack_buffer * o, char *s, int len)
-{
-    while (len--) {
-        oggpack_write(o, *s++, 8);
-    }
-}
-
-static int
-_commentheader_out(vorbis_comment * vc, char *vendor, ogg_packet * op)
-{
-    oggpack_buffer opb;
-
-    oggpack_writeinit(&opb);
-
-    /* preamble */
-    oggpack_write(&opb, 0x03, 8);
-    _v_writestring(&opb, "vorbis", 6);
-
-    /* vendor */
-    oggpack_write(&opb, strlen(vendor), 32);
-    _v_writestring(&opb, vendor, strlen(vendor));
-
-    /* comments */
-    oggpack_write(&opb, vc->comments, 32);
-    if (vc->comments) {
-        int i;
-        for (i = 0; i < vc->comments; i++) {
-            if (vc->user_comments[i]) {
-                oggpack_write(&opb, vc->comment_lengths[i], 32);
-                _v_writestring(&opb, vc->user_comments[i],
-                               vc->comment_lengths[i]);
-            }
-            else {
-                oggpack_write(&opb, 0, 32);
-            }
-        }
-    }
-    oggpack_write(&opb, 1, 1);
-
-    op->packet = _ogg_malloc(oggpack_bytes(&opb));
-    memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
-
-    op->bytes = oggpack_bytes(&opb);
-    op->b_o_s = 0;
-    op->e_o_s = 0;
-    op->granulepos = 0;
-
-    return 0;
-}
-
-static int
-_blocksize(vcedit_state * s, ogg_packet * p)
-{
-    int this = vorbis_packet_blocksize(&s->vi, p);
-    int ret = (this + s->prevW) / 4;
-
-    if (!s->prevW) {
-        s->prevW = this;
-        return 0;
-    }
-
-    s->prevW = this;
-    return ret;
-}
-
-static int
-_fetch_next_packet(vcedit_state * s, ogg_packet * p, ogg_page * page)
-{
-    int result;
-    char *buffer;
-    gint64 bytes;
-
-    result = ogg_stream_packetout(s->os, p);
-
-    if (result > 0)
-        return 1;
-    else {
-        if (s->eosin)
-            return 0;
-        while (ogg_sync_pageout(s->oy, page) <= 0) {
-            buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
-            bytes = s->read(buffer, 1, CHUNKSIZE, s->in);
-            ogg_sync_wrote(s->oy, bytes);
-            if (bytes == 0)
-                return 0;
-        }
-        if (ogg_page_eos(page))
-            s->eosin = 1;
-        else if (ogg_page_serialno(page) != s->serial) {
-            s->eosin = 1;
-            s->extrapage = 1;
-            return 0;
-        }
-
-        ogg_stream_pagein(s->os, page);
-        return _fetch_next_packet(s, p, page);
-    }
-}
-
-
-int
-vcedit_open(vcedit_state * state, VFSFile * in)
-{
-    return vcedit_open_callbacks(state, (void *) in,
-                                 (vcedit_read_func) vfs_fread,
-                                 (vcedit_write_func) vfs_fwrite);
-}
-
-int
-vcedit_open_callbacks(vcedit_state * state, void *in,
-                      vcedit_read_func read_func,
-                      vcedit_write_func write_func)
-{
-    char *buffer;
-    gint64 bytes, i;
-    ogg_packet *header;
-    ogg_packet header_main;
-    ogg_packet header_comments;
-    ogg_packet header_codebooks;
-    ogg_page og;
-
-    state->in = in;
-    state->read = read_func;
-    state->write = write_func;
-
-    state->oy = g_new(ogg_sync_state, 1);
-    ogg_sync_init(state->oy);
-
-    buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-
-    bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
-
-    ogg_sync_wrote(state->oy, bytes);
-
-    if (ogg_sync_pageout(state->oy, &og) != 1) {
-        if (bytes < CHUNKSIZE)
-            state->lasterror = "Input truncated or empty.";
-        else
-            state->lasterror = "Input is not an Ogg bitstream.";
-        goto err;
-    }
-
-    state->serial = ogg_page_serialno(&og);
-
-    state->os = g_new(ogg_stream_state, 1);
-    ogg_stream_init(state->os, state->serial);
-
-    vorbis_info_init(&state->vi);
-
-    state->vc = g_new(vorbis_comment, 1);
-    vorbis_comment_init(state->vc);
-
-    if (ogg_stream_pagein(state->os, &og) < 0) {
-        state->lasterror = "Error reading first page of Ogg bitstream.";
-        goto err;
-    }
-
-    if (ogg_stream_packetout(state->os, &header_main) != 1) {
-        state->lasterror = "Error reading initial header packet.";
-        goto err;
-    }
-
-    if (vorbis_synthesis_headerin(&state->vi, state->vc, &header_main) < 0) {
-        state->lasterror = "Ogg bitstream does not contain vorbis data.";
-        goto err;
-    }
-
-    state->mainlen = header_main.bytes;
-    state->mainbuf = g_malloc(state->mainlen);
-    memcpy(state->mainbuf, header_main.packet, header_main.bytes);
-
-    i = 0;
-    header = &header_comments;
-    while (i < 2) {
-        while (i < 2) {
-            int result = ogg_sync_pageout(state->oy, &og);
-            if (result == 0)
-                break;          /* Too little data so far */
-            else if (result == 1) {
-                ogg_stream_pagein(state->os, &og);
-                while (i < 2) {
-                    result = ogg_stream_packetout(state->os, header);
-                    if (result == 0)
-                        break;
-                    if (result == -1) {
-                        state->lasterror = "Corrupt secondary header.";
-                        goto err;
-                    }
-                    vorbis_synthesis_headerin(&state->vi, state->vc, header);
-                    if (i == 1) {
-                        state->booklen = header->bytes;
-                        state->bookbuf = g_malloc(state->booklen);
-                        memcpy(state->bookbuf, header->packet, header->bytes);
-                    }
-                    i++;
-                    header = &header_codebooks;
-                }
-            }
-        }
-
-        buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-        bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
-        if (bytes == 0 && i < 2) {
-            state->lasterror = "EOF before end of vorbis headers.";
-            goto err;
-        }
-        ogg_sync_wrote(state->oy, bytes);
-    }
-
-    /* Copy the vendor tag */
-    state->vendor = g_malloc(strlen(state->vc->vendor) + 1);
-    strcpy(state->vendor, state->vc->vendor);
-
-    /* Headers are done! */
-    return 0;
-
-  err:
-    vcedit_clear_internals(state);
-    return -1;
-}
-
-#if 0
-static void
-dump_state(vcedit_state * state)
-{
-}
-#endif
-
-int
-vcedit_write(vcedit_state * state, void *out)
-{
-
-    ogg_stream_state streamout;
-    ogg_packet header_main;
-    ogg_packet header_comments;
-    ogg_packet header_codebooks;
-
-    ogg_page ogout, ogin;
-    ogg_packet op;
-    ogg_int64_t granpos = 0;
-    int result;
-    char *buffer;
-    gint64 bytes;
-    int needflush = 0, needout = 0;
-
-    state->eosin = 0;
-    state->extrapage = 0;
-
-    header_main.bytes = state->mainlen;
-    header_main.packet = state->mainbuf;
-    header_main.b_o_s = 1;
-    header_main.e_o_s = 0;
-    header_main.granulepos = 0;
-
-    header_codebooks.bytes = state->booklen;
-    header_codebooks.packet = state->bookbuf;
-    header_codebooks.b_o_s = 0;
-    header_codebooks.e_o_s = 0;
-    header_codebooks.granulepos = 0;
-
-    ogg_stream_init(&streamout, state->serial);
-
-    _commentheader_out(state->vc, state->vendor, &header_comments);
-
-    ogg_stream_packetin(&streamout, &header_main);
-    ogg_stream_packetin(&streamout, &header_comments);
-    ogg_stream_packetin(&streamout, &header_codebooks);
-
-    while ((result = ogg_stream_flush(&streamout, &ogout))) {
-        if (state->write(ogout.header, 1, ogout.header_len, out) !=
-            (size_t) ogout.header_len)
-            goto cleanup;
-        if (state->write(ogout.body, 1, ogout.body_len, out) !=
-            (size_t) ogout.body_len)
-            goto cleanup;
-    }
-
-    while (_fetch_next_packet(state, &op, &ogin)) {
-        int size;
-        size = _blocksize(state, &op);
-        granpos += size;
-
-        if (needflush) {
-            if (ogg_stream_flush(&streamout, &ogout)) {
-                if (state->write(ogout.header, 1, ogout.header_len,
-                                 out) != (size_t) ogout.header_len)
-                    goto cleanup;
-                if (state->write(ogout.body, 1, ogout.body_len,
-                                 out) != (size_t) ogout.body_len)
-                    goto cleanup;
-            }
-        }
-        else if (needout) {
-            if (ogg_stream_pageout(&streamout, &ogout)) {
-                if (state->write(ogout.header, 1, ogout.header_len,
-                                 out) != (size_t) ogout.header_len)
-                    goto cleanup;
-                if (state->write(ogout.body, 1, ogout.body_len,
-                                 out) != (size_t) ogout.body_len)
-                    goto cleanup;
-            }
-        }
-
-        needflush = needout = 0;
-
-        if (op.granulepos == -1) {
-            op.granulepos = granpos;
-            ogg_stream_packetin(&streamout, &op);
-        }
-        else {                  /* granulepos is set, validly. Use it, and force a flush to
-                                   account for shortened blocks (vcut) when appropriate */
-            if (granpos > op.granulepos) {
-                granpos = op.granulepos;
-                ogg_stream_packetin(&streamout, &op);
-                needflush = 1;
-            }
-            else {
-                ogg_stream_packetin(&streamout, &op);
-                needout = 1;
-            }
-        }
-    }
-
-    streamout.e_o_s = 1;
-    while (ogg_stream_flush(&streamout, &ogout)) {
-        if (state->write(ogout.header, 1, ogout.header_len,
-                         out) != (size_t) ogout.header_len)
-            goto cleanup;
-        if (state->write(ogout.body, 1, ogout.body_len,
-                         out) != (size_t) ogout.body_len)
-            goto cleanup;
-    }
-
-    /* FIXME: freeing this here probably leaks memory */
-    /* Done with this, now */
-    vorbis_info_clear(&state->vi);
-
-    if (state->extrapage) {
-        if (state->write(ogin.header, 1, ogin.header_len,
-                         out) != (size_t) ogin.header_len)
-            goto cleanup;
-        if (state->write(ogin.body, 1, ogin.body_len, out) !=
-            (size_t) ogin.body_len)
-            goto cleanup;
-    }
-
-    state->eosin = 0;           /* clear it, because not all paths to here do */
-    while (!state->eosin) {     /* We reached eos, not eof */
-        /* We copy the rest of the stream (other logical streams)
-         * through, a page at a time. */
-        while (1) {
-            result = ogg_sync_pageout(state->oy, &ogout);
-            if (result == 0)
-                break;
-            if (result < 0)
-                state->lasterror = "Corrupt or missing data, continuing...";
-            else {
-                /* Don't bother going through the rest, we can just
-                 * write the page out now */
-                if (state->write(ogout.header, 1, ogout.header_len,
-                                 out) != (size_t) ogout.header_len)
-                    goto cleanup;
-                if (state->write(ogout.body, 1, ogout.body_len, out) !=
-                    (size_t) ogout.body_len)
-                    goto cleanup;
-            }
-        }
-        buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
-        bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
-        ogg_sync_wrote(state->oy, bytes);
-        if (bytes == 0) {
-            state->eosin = 1;
-            break;
-        }
-    }
-
-
-  cleanup:
-    ogg_stream_clear(&streamout);
-    ogg_packet_clear(&header_comments);
-
-    g_free(state->mainbuf);
-    g_free(state->bookbuf);
-
-    vcedit_clear_internals(state);
-    if (!state->eosin) {
-        state->lasterror =
-            "Error writing stream to output. "
-            "Output stream may be corrupted or truncated.";
-        return -1;
-    }
-
-    return 0;
-}
diff --git a/src/vorbis/vcedit.cc b/src/vorbis/vcedit.cc
new file mode 100644
index 000000000000..6b650ae2be5c
--- /dev/null
+++ b/src/vorbis/vcedit.cc
@@ -0,0 +1,443 @@
+/* This program is licensed under the GNU Library General Public License, version 2,
+ * a copy of which is included with this program (LICENCE.LGPL).
+ *
+ * (c) 2000-2001 Michael Smith <msmith at labyrinth.net.au>
+ *
+ *
+ * Comment editing backend, suitable for use by nice frontend interfaces.
+ *
+ */
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+
+#include "vcedit.h"
+
+#define CHUNKSIZE 4096
+
+vcedit_state *
+vcedit_new_state(void)
+{
+    return g_new0(vcedit_state, 1);
+}
+
+const char *
+vcedit_error(vcedit_state * state)
+{
+    return state->lasterror;
+}
+
+vorbis_comment *
+vcedit_comments(vcedit_state * state)
+{
+    return state->vc;
+}
+
+static void
+vcedit_clear_internals(vcedit_state * state)
+{
+    if (state->vc) {
+        vorbis_comment_clear(state->vc);
+        g_free(state->vc);
+        state->vc = nullptr;
+    }
+    if (state->os) {
+        ogg_stream_clear(state->os);
+        g_free(state->os);
+        state->os = nullptr;
+    }
+    if (state->oy) {
+        ogg_sync_clear(state->oy);
+        g_free(state->oy);
+        state->oy = nullptr;
+    }
+    if (state->vendor) {
+        g_free(state->vendor);
+        state->vendor = nullptr;
+    }
+}
+
+void
+vcedit_clear(vcedit_state * state)
+{
+    if (state) {
+        vcedit_clear_internals(state);
+        g_free(state);
+    }
+}
+
+/* Next two functions pulled straight from libvorbis, apart from one change
+ * - we don't want to overwrite the vendor string.
+ */
+static void
+_v_writestring(oggpack_buffer * o, const char *s, int len)
+{
+    while (len--) {
+        oggpack_write(o, *s++, 8);
+    }
+}
+
+static int
+_commentheader_out(vorbis_comment * vc, char *vendor, ogg_packet * op)
+{
+    oggpack_buffer opb;
+
+    oggpack_writeinit(&opb);
+
+    /* preamble */
+    oggpack_write(&opb, 0x03, 8);
+    _v_writestring(&opb, "vorbis", 6);
+
+    /* vendor */
+    oggpack_write(&opb, strlen(vendor), 32);
+    _v_writestring(&opb, vendor, strlen(vendor));
+
+    /* comments */
+    oggpack_write(&opb, vc->comments, 32);
+    if (vc->comments) {
+        int i;
+        for (i = 0; i < vc->comments; i++) {
+            if (vc->user_comments[i]) {
+                oggpack_write(&opb, vc->comment_lengths[i], 32);
+                _v_writestring(&opb, vc->user_comments[i],
+                               vc->comment_lengths[i]);
+            }
+            else {
+                oggpack_write(&opb, 0, 32);
+            }
+        }
+    }
+    oggpack_write(&opb, 1, 1);
+
+    op->packet = (unsigned char *) _ogg_malloc(oggpack_bytes(&opb));
+    memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
+
+    op->bytes = oggpack_bytes(&opb);
+    op->b_o_s = 0;
+    op->e_o_s = 0;
+    op->granulepos = 0;
+
+    return 0;
+}
+
+static int
+_blocksize(vcedit_state * s, ogg_packet * p)
+{
+    int size = vorbis_packet_blocksize(&s->vi, p);
+    int ret = (size + s->prevW) / 4;
+
+    if (!s->prevW) {
+        s->prevW = size;
+        return 0;
+    }
+
+    s->prevW = size;
+    return ret;
+}
+
+static int
+_fetch_next_packet(vcedit_state * s, ogg_packet * p, ogg_page * page)
+{
+    int result;
+    char *buffer;
+    int64_t bytes;
+
+    result = ogg_stream_packetout(s->os, p);
+
+    if (result > 0)
+        return 1;
+    else {
+        if (s->eosin)
+            return 0;
+        while (ogg_sync_pageout(s->oy, page) <= 0) {
+            buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
+            bytes = s->in->fread(buffer, 1, CHUNKSIZE);
+            ogg_sync_wrote(s->oy, bytes);
+            if (bytes == 0)
+                return 0;
+        }
+        if (ogg_page_eos(page))
+            s->eosin = 1;
+        else if (ogg_page_serialno(page) != s->serial) {
+            s->eosin = 1;
+            s->extrapage = 1;
+            return 0;
+        }
+
+        ogg_stream_pagein(s->os, page);
+        return _fetch_next_packet(s, p, page);
+    }
+}
+
+
+int
+vcedit_open(vcedit_state * state, VFSFile & in)
+{
+    char *buffer;
+    int64_t bytes, i;
+    ogg_packet *header;
+    ogg_packet header_main;
+    ogg_packet header_comments;
+    ogg_packet header_codebooks;
+    ogg_page og;
+
+    state->in = & in;
+
+    state->oy = g_new(ogg_sync_state, 1);
+    ogg_sync_init(state->oy);
+
+    buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
+
+    bytes = state->in->fread(buffer, 1, CHUNKSIZE);
+
+    ogg_sync_wrote(state->oy, bytes);
+
+    if (ogg_sync_pageout(state->oy, &og) != 1) {
+        if (bytes < CHUNKSIZE)
+            state->lasterror = "Input truncated or empty.";
+        else
+            state->lasterror = "Input is not an Ogg bitstream.";
+        goto err;
+    }
+
+    state->serial = ogg_page_serialno(&og);
+
+    state->os = g_new(ogg_stream_state, 1);
+    ogg_stream_init(state->os, state->serial);
+
+    vorbis_info_init(&state->vi);
+
+    state->vc = g_new(vorbis_comment, 1);
+    vorbis_comment_init(state->vc);
+
+    if (ogg_stream_pagein(state->os, &og) < 0) {
+        state->lasterror = "Error reading first page of Ogg bitstream.";
+        goto err;
+    }
+
+    if (ogg_stream_packetout(state->os, &header_main) != 1) {
+        state->lasterror = "Error reading initial header packet.";
+        goto err;
+    }
+
+    if (vorbis_synthesis_headerin(&state->vi, state->vc, &header_main) < 0) {
+        state->lasterror = "Ogg bitstream does not contain vorbis data.";
+        goto err;
+    }
+
+    state->mainlen = header_main.bytes;
+    state->mainbuf = g_new (unsigned char, state->mainlen);
+    memcpy(state->mainbuf, header_main.packet, header_main.bytes);
+
+    i = 0;
+    header = &header_comments;
+    while (i < 2) {
+        while (i < 2) {
+            int result = ogg_sync_pageout(state->oy, &og);
+            if (result == 0)
+                break;          /* Too little data so far */
+            else if (result == 1) {
+                ogg_stream_pagein(state->os, &og);
+                while (i < 2) {
+                    result = ogg_stream_packetout(state->os, header);
+                    if (result == 0)
+                        break;
+                    if (result == -1) {
+                        state->lasterror = "Corrupt secondary header.";
+                        goto err;
+                    }
+                    vorbis_synthesis_headerin(&state->vi, state->vc, header);
+                    if (i == 1) {
+                        state->booklen = header->bytes;
+                        state->bookbuf = g_new (unsigned char, state->booklen);
+                        memcpy(state->bookbuf, header->packet, header->bytes);
+                    }
+                    i++;
+                    header = &header_codebooks;
+                }
+            }
+        }
+
+        buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
+        bytes = state->in->fread(buffer, 1, CHUNKSIZE);
+        if (bytes == 0 && i < 2) {
+            state->lasterror = "EOF before end of vorbis headers.";
+            goto err;
+        }
+        ogg_sync_wrote(state->oy, bytes);
+    }
+
+    /* Copy the vendor tag */
+    state->vendor = g_strdup (state->vc->vendor);
+
+    /* Headers are done! */
+    return 0;
+
+  err:
+    vcedit_clear_internals(state);
+    return -1;
+}
+
+#if 0
+static void
+dump_state(vcedit_state * state)
+{
+}
+#endif
+
+int
+vcedit_write(vcedit_state * state, VFSFile & out)
+{
+
+    ogg_stream_state streamout;
+    ogg_packet header_main;
+    ogg_packet header_comments;
+    ogg_packet header_codebooks;
+
+    ogg_page ogout, ogin;
+    ogg_packet op;
+    ogg_int64_t granpos = 0;
+    int result;
+    char *buffer;
+    int64_t bytes;
+    int needflush = 0, needout = 0;
+
+    state->eosin = 0;
+    state->extrapage = 0;
+
+    header_main.bytes = state->mainlen;
+    header_main.packet = state->mainbuf;
+    header_main.b_o_s = 1;
+    header_main.e_o_s = 0;
+    header_main.granulepos = 0;
+
+    header_codebooks.bytes = state->booklen;
+    header_codebooks.packet = state->bookbuf;
+    header_codebooks.b_o_s = 0;
+    header_codebooks.e_o_s = 0;
+    header_codebooks.granulepos = 0;
+
+    ogg_stream_init(&streamout, state->serial);
+
+    _commentheader_out(state->vc, state->vendor, &header_comments);
+
+    ogg_stream_packetin(&streamout, &header_main);
+    ogg_stream_packetin(&streamout, &header_comments);
+    ogg_stream_packetin(&streamout, &header_codebooks);
+
+    while ((result = ogg_stream_flush(&streamout, &ogout))) {
+        if (out.fwrite(ogout.header, 1, ogout.header_len) != ogout.header_len)
+            goto cleanup;
+        if (out.fwrite(ogout.body, 1, ogout.body_len) != ogout.body_len)
+            goto cleanup;
+    }
+
+    while (_fetch_next_packet(state, &op, &ogin)) {
+        int size;
+        size = _blocksize(state, &op);
+        granpos += size;
+
+        if (needflush) {
+            if (ogg_stream_flush(&streamout, &ogout)) {
+                if (out.fwrite(ogout.header, 1, ogout.header_len) != ogout.header_len)
+                    goto cleanup;
+                if (out.fwrite(ogout.body, 1, ogout.body_len) != ogout.body_len)
+                    goto cleanup;
+            }
+        }
+        else if (needout) {
+            if (ogg_stream_pageout(&streamout, &ogout)) {
+                if (out.fwrite(ogout.header, 1, ogout.header_len) != ogout.header_len)
+                    goto cleanup;
+                if (out.fwrite(ogout.body, 1, ogout.body_len) != ogout.body_len)
+                    goto cleanup;
+            }
+        }
+
+        needflush = needout = 0;
+
+        if (op.granulepos == -1) {
+            op.granulepos = granpos;
+            ogg_stream_packetin(&streamout, &op);
+        }
+        else {                  /* granulepos is set, validly. Use it, and force a flush to
+                                   account for shortened blocks (vcut) when appropriate */
+            if (granpos > op.granulepos) {
+                granpos = op.granulepos;
+                ogg_stream_packetin(&streamout, &op);
+                needflush = 1;
+            }
+            else {
+                ogg_stream_packetin(&streamout, &op);
+                needout = 1;
+            }
+        }
+    }
+
+    streamout.e_o_s = 1;
+    while (ogg_stream_flush(&streamout, &ogout)) {
+        if (out.fwrite(ogout.header, 1, ogout.header_len) != ogout.header_len)
+            goto cleanup;
+        if (out.fwrite(ogout.body, 1, ogout.body_len) != ogout.body_len)
+            goto cleanup;
+    }
+
+    /* FIXME: freeing this here probably leaks memory */
+    /* Done with this, now */
+    vorbis_info_clear(&state->vi);
+
+    if (state->extrapage) {
+        if (out.fwrite(ogin.header, 1, ogin.header_len) != ogin.header_len)
+            goto cleanup;
+        if (out.fwrite(ogin.body, 1, ogin.body_len) != ogin.body_len)
+            goto cleanup;
+    }
+
+    state->eosin = 0;           /* clear it, because not all paths to here do */
+    while (!state->eosin) {     /* We reached eos, not eof */
+        /* We copy the rest of the stream (other logical streams)
+         * through, a page at a time. */
+        while (1) {
+            result = ogg_sync_pageout(state->oy, &ogout);
+            if (result == 0)
+                break;
+            if (result < 0)
+                state->lasterror = "Corrupt or missing data, continuing...";
+            else {
+                /* Don't bother going through the rest, we can just
+                 * write the page out now */
+                if (out.fwrite(ogout.header, 1, ogout.header_len) != ogout.header_len)
+                    goto cleanup;
+                if (out.fwrite(ogout.body, 1, ogout.body_len) != ogout.body_len)
+                    goto cleanup;
+            }
+        }
+        buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
+        bytes = state->in->fread(buffer, 1, CHUNKSIZE);
+        ogg_sync_wrote(state->oy, bytes);
+        if (bytes == 0) {
+            state->eosin = 1;
+            break;
+        }
+    }
+
+
+  cleanup:
+    ogg_stream_clear(&streamout);
+    ogg_packet_clear(&header_comments);
+
+    g_free(state->mainbuf);
+    g_free(state->bookbuf);
+
+    vcedit_clear_internals(state);
+    if (!state->eosin) {
+        state->lasterror =
+            "Error writing stream to output. "
+            "Output stream may be corrupted or truncated.";
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/src/vorbis/vcedit.h b/src/vorbis/vcedit.h
index ea4432f8f298..a26239555101 100644
--- a/src/vorbis/vcedit.h
+++ b/src/vorbis/vcedit.h
@@ -10,17 +10,9 @@
 #ifndef __VCEDIT_H
 #define __VCEDIT_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif 
-
-#include <stdio.h>
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
-#include <audacious/plugin.h>
-
-typedef gint64 (*vcedit_read_func)(void *, gint64, gint64, void *);
-typedef gint64 (*vcedit_write_func)(const void *, gint64, gint64, void *);
+#include <libaudcore/plugin.h>
 
 typedef struct {
 	ogg_sync_state	 *oy;
@@ -29,16 +21,13 @@ typedef struct {
 	vorbis_comment	 *vc;
 	vorbis_info       vi;
 
-	vcedit_read_func  read;
-	vcedit_write_func write;
-
-	void		 *in;
+	VFSFile		 *in;
 	long		  serial;
 	unsigned char	 *mainbuf;
 	unsigned char	 *bookbuf;
 	int		  mainlen;
 	int		  booklen;
-	char 	         *lasterror;
+	const char 	         *lasterror;
 	char             *vendor;
 	int               prevW;
 	int               extrapage;
@@ -48,16 +37,9 @@ typedef struct {
 extern vcedit_state *vcedit_new_state(void);
 extern void vcedit_clear(vcedit_state *state);
 extern vorbis_comment *vcedit_comments(vcedit_state *state);
-extern int vcedit_open(vcedit_state *state, VFSFile *in);
-extern int vcedit_open_callbacks(vcedit_state *state, void *in,
-                                 vcedit_read_func read_func,
-                                 vcedit_write_func write_func);
-extern int vcedit_write(vcedit_state *state, void *out);
-extern char *vcedit_error(vcedit_state *state);
-
-#ifdef __cplusplus
-}
-#endif 
+extern int vcedit_open(vcedit_state *state, VFSFile &in);
+extern int vcedit_write(vcedit_state *state, VFSFile &out);
+extern const char *vcedit_error(vcedit_state *state);
 
 #endif /* __VCEDIT_H */
 
diff --git a/src/vorbis/vcupdate.c b/src/vorbis/vcupdate.c
deleted file mode 100644
index 7a65bd5fec2e..000000000000
--- a/src/vorbis/vcupdate.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* 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; 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.
- *
- */
-
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <audacious/debug.h>
-#include <audacious/plugin.h>
-#include <audacious/i18n.h>
-#include <libaudcore/audstrings.h>
-
-#include "vorbis.h"
-#include "vcedit.h"
-
-static gboolean write_and_pivot_files(vcedit_state * state);
-
-static GHashTable * dictionary_from_vorbis_comment (vorbis_comment * vc)
-{
-    gint i;
-
-    GHashTable * dict = g_hash_table_new_full (g_str_hash, g_str_equal,
-     (GDestroyNotify) str_unref, (GDestroyNotify) str_unref);
-
-    for (i = 0; i < vc->comments; i++) {
-        gchar **frags;
-
-        AUDDBG("%s\n", vc->user_comments[i]);
-        frags = g_strsplit(vc->user_comments[i], "=", 2);
-
-        if (frags[0] && frags[1])
-        {
-            gchar * key = g_ascii_strdown (frags[0], -1);
-            g_hash_table_insert (dict, str_get (key), str_get (frags[1]));
-            g_free (key);
-        }
-
-        g_strfreev(frags); /* Don't use g_free() for string lists! --eugene */
-    }
-
-    return dict;
-}
-
-static void add_tag_cb (void * key, void * field, void * vc)
-{
-    vorbis_comment_add_tag (vc, key, field);
-}
-
-static void dictionary_to_vorbis_comment (vorbis_comment * vc, GHashTable * dict)
-{
-    vorbis_comment_clear(vc);
-    g_hash_table_foreach (dict, add_tag_cb, vc);
-}
-
-static void insert_str_tuple_field_to_dictionary (const Tuple * tuple, int
- fieldn, GHashTable * dict, const char * key)
-{
-    char * val = tuple_get_str (tuple, fieldn);
-
-    if (val && val[0])
-        g_hash_table_insert (dict, str_get (key), str_ref (val));
-    else
-        g_hash_table_remove (dict, key);
-
-    str_unref(val);
-}
-
-static void insert_int_tuple_field_to_dictionary (const Tuple * tuple, int
- fieldn, GHashTable * dict, const char * key)
-{
-    int val = tuple_get_int (tuple, fieldn);
-
-    if (val > 0)
-        g_hash_table_insert (dict, str_get (key), int_to_str (val));
-    else
-        g_hash_table_remove (dict, key);
-}
-
-gboolean vorbis_update_song_tuple (const char * filename, VFSFile * fd, const Tuple * tuple)
-{
-
-    vcedit_state *state;
-    vorbis_comment *comment;
-    gboolean ret;
-
-    if(!tuple || !fd) return FALSE;
-
-    state = vcedit_new_state();
-
-    if(vcedit_open(state, fd) < 0) {
-        vcedit_clear(state);
-        return FALSE;
-    }
-
-    comment = vcedit_comments(state);
-    GHashTable * dict = dictionary_from_vorbis_comment (comment);
-
-    insert_str_tuple_field_to_dictionary(tuple, FIELD_TITLE, dict, "title");
-    insert_str_tuple_field_to_dictionary(tuple, FIELD_ARTIST, dict, "artist");
-    insert_str_tuple_field_to_dictionary(tuple, FIELD_ALBUM, dict, "album");
-    insert_str_tuple_field_to_dictionary(tuple, FIELD_COMMENT, dict, "comment");
-    insert_str_tuple_field_to_dictionary(tuple, FIELD_GENRE, dict, "genre");
-
-    insert_int_tuple_field_to_dictionary(tuple, FIELD_YEAR, dict, "date");
-    insert_int_tuple_field_to_dictionary(tuple, FIELD_TRACK_NUMBER, dict, "tracknumber");
-
-    dictionary_to_vorbis_comment(comment, dict);
-    g_hash_table_destroy (dict);
-
-    ret = write_and_pivot_files(state);
-
-    vcedit_clear(state);
-
-    return ret;
-}
-
-#define COPY_BUF 65536
-
-gboolean copy_vfs (VFSFile * in, VFSFile * out)
-{
-    if (vfs_fseek (in, 0, SEEK_SET) < 0 || vfs_fseek (out, 0, SEEK_SET) < 0)
-        return FALSE;
-
-    gchar * buffer = g_malloc (COPY_BUF);
-    gint64 size = 0, readed;
-
-    while ((readed = vfs_fread (buffer, 1, COPY_BUF, in)) > 0)
-    {
-        if (vfs_fwrite (buffer, 1, readed, out) != readed)
-            goto FAILED;
-
-        size += readed;
-    }
-
-    if (vfs_ftruncate (out, size) < 0)
-        goto FAILED;
-
-    g_free (buffer);
-    return TRUE;
-
-FAILED:
-    g_free (buffer);
-    return FALSE;
-}
-
-#undef COPY_BUF
-
-gboolean write_and_pivot_files (vcedit_state * state)
-{
-    gchar * temp;
-    GError * error;
-    gint handle = g_file_open_tmp (NULL, & temp, & error);
-
-    if (handle < 0)
-    {
-        fprintf (stderr, "Failed to create temp file: %s.\n", error->message);
-        g_error_free (error);
-        return FALSE;
-    }
-
-    close (handle);
-
-    gchar * temp_uri = filename_to_uri (temp);
-    g_return_val_if_fail (temp_uri, FALSE);
-    VFSFile * temp_vfs = vfs_fopen (temp_uri, "r+");
-    g_return_val_if_fail (temp_vfs, FALSE);
-
-    str_unref (temp_uri);
-
-    if (vcedit_write (state, temp_vfs) < 0)
-    {
-        fprintf (stderr, "Tag update failed: %s.\n", state->lasterror);
-        vfs_fclose (temp_vfs);
-        g_free (temp);
-        return FALSE;
-    }
-
-    if (! copy_vfs (temp_vfs, state->in))
-    {
-        fprintf (stderr, "Failed to copy temp file.  The temp file has not "
-         "been deleted: %s.\n", temp);
-        vfs_fclose (temp_vfs);
-        g_free (temp);
-        return FALSE;
-    }
-
-    vfs_fclose (temp_vfs);
-
-    if (g_unlink (temp) < 0)
-        fprintf (stderr, "Failed to delete temp file: %s.\n", temp);
-
-    g_free (temp);
-    return TRUE;
-}
diff --git a/src/vorbis/vcupdate.cc b/src/vorbis/vcupdate.cc
new file mode 100644
index 000000000000..096ff10f43b0
--- /dev/null
+++ b/src/vorbis/vcupdate.cc
@@ -0,0 +1,210 @@
+/* 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; 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.
+ *
+ */
+
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/multihash.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include "vorbis.h"
+#include "vcedit.h"
+
+static bool write_and_pivot_files(vcedit_state * state);
+
+typedef SimpleHash<String, String> Dictionary;
+
+static Dictionary dictionary_from_vorbis_comment (vorbis_comment * vc)
+{
+    Dictionary dict;
+
+    for (int i = 0; i < vc->comments; i ++)
+    {
+        char **frags;
+
+        AUDDBG("%s\n", vc->user_comments[i]);
+        frags = g_strsplit(vc->user_comments[i], "=", 2);
+
+        if (frags[0] && frags[1])
+        {
+            char * key = g_ascii_strdown (frags[0], -1);
+            dict.add (String (key), String (frags[1]));
+            g_free (key);
+        }
+
+        g_strfreev(frags); /* Don't use g_free() for string lists! --eugene */
+    }
+
+    return dict;
+}
+
+static void add_tag_cb (const String & key, String & field, void * vc)
+{
+    vorbis_comment_add_tag ((vorbis_comment *) vc, key, field);
+}
+
+static void dictionary_to_vorbis_comment (vorbis_comment * vc, Dictionary & dict)
+{
+    vorbis_comment_clear(vc);
+    dict.iterate (add_tag_cb, vc);
+}
+
+static void insert_str_tuple_field_to_dictionary (const Tuple & tuple,
+ Tuple::Field field, Dictionary & dict, const char * key)
+{
+    String val = tuple.get_str (field);
+
+    if (val && val[0])
+        dict.add (String (key), std::move (val));
+    else
+        dict.remove (String (key));
+}
+
+static void insert_int_tuple_field_to_dictionary (const Tuple & tuple,
+ Tuple::Field field, Dictionary & dict, const char * key)
+{
+    int val = tuple.get_int (field);
+
+    if (val > 0)
+        dict.add (String (key), String (int_to_str (val)));
+    else
+        dict.remove (String (key));
+}
+
+bool VorbisPlugin::write_tuple (const char * filename, VFSFile & file, const Tuple & tuple)
+{
+    vcedit_state *state;
+    vorbis_comment *comment;
+    bool ret;
+
+    state = vcedit_new_state();
+
+    if(vcedit_open(state, file) < 0) {
+        vcedit_clear(state);
+        return false;
+    }
+
+    comment = vcedit_comments(state);
+    Dictionary dict = dictionary_from_vorbis_comment (comment);
+
+    insert_str_tuple_field_to_dictionary(tuple, Tuple::Title, dict, "title");
+    insert_str_tuple_field_to_dictionary(tuple, Tuple::Artist, dict, "artist");
+    insert_str_tuple_field_to_dictionary(tuple, Tuple::Album, dict, "album");
+    insert_str_tuple_field_to_dictionary(tuple, Tuple::Comment, dict, "comment");
+    insert_str_tuple_field_to_dictionary(tuple, Tuple::Genre, dict, "genre");
+
+    insert_int_tuple_field_to_dictionary(tuple, Tuple::Year, dict, "date");
+    insert_int_tuple_field_to_dictionary(tuple, Tuple::Track, dict, "tracknumber");
+
+    dictionary_to_vorbis_comment(comment, dict);
+
+    ret = write_and_pivot_files(state);
+
+    vcedit_clear(state);
+
+    return ret;
+}
+
+#define COPY_BUF 65536
+
+bool copy_vfs (VFSFile & in, VFSFile & out)
+{
+    if (in.fseek (0, VFS_SEEK_SET) < 0 || out.fseek (0, VFS_SEEK_SET) < 0)
+        return false;
+
+    char * buffer = g_new (char, COPY_BUF);
+    int64_t size = 0, readed;
+
+    while ((readed = in.fread (buffer, 1, COPY_BUF)) > 0)
+    {
+        if (out.fwrite (buffer, 1, readed) != readed)
+            goto FAILED;
+
+        size += readed;
+    }
+
+    if (out.ftruncate (size) < 0)
+        goto FAILED;
+
+    g_free (buffer);
+    return true;
+
+FAILED:
+    g_free (buffer);
+    return false;
+}
+
+#undef COPY_BUF
+
+bool write_and_pivot_files (vcedit_state * state)
+{
+    char * temp;
+    GError * error;
+    int handle = g_file_open_tmp (nullptr, & temp, & error);
+
+    if (handle < 0)
+    {
+        AUDERR ("Failed to create temp file: %s.\n", error->message);
+        g_error_free (error);
+        return false;
+    }
+
+    close (handle);
+
+    StringBuf temp_uri = filename_to_uri (temp);
+    g_return_val_if_fail (temp_uri, false);
+    VFSFile temp_vfs (temp_uri, "r+");
+    g_return_val_if_fail (temp_vfs, false);
+
+    if (vcedit_write (state, temp_vfs) < 0)
+    {
+        AUDERR ("Tag update failed: %s.\n", state->lasterror);
+        g_free (temp);
+        return false;
+    }
+
+    if (! copy_vfs (temp_vfs, * state->in))
+    {
+        AUDERR ("Failed to copy temp file.  The temp file has not "
+         "been deleted: %s.\n", temp);
+        g_free (temp);
+        return false;
+    }
+
+    temp_vfs = VFSFile ();
+
+    if (g_unlink (temp) < 0)
+        AUDERR ("Failed to delete temp file: %s.\n", temp);
+
+    g_free (temp);
+    return true;
+}
diff --git a/src/vorbis/vorbis.c b/src/vorbis/vorbis.c
deleted file mode 100644
index 868456e1a020..000000000000
--- a/src/vorbis/vorbis.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) Tony Arcieri <bascule at inferno.tusculum.edu>
- * Copyright (C) 2001-2002 Håvard Kvålen <havardk at xmms.org>
- * Copyright (C) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
- * Copyright (C) 2008 Cristi Măgherușan <majeru at gentoo.ro>
- * Copyright (C) 2008 Eugene Zagidullin <e.asphyx at gmail.com>
- * Copyright (C) 2009-2011 Audacious Developers
- *
- * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp at sjeng.org>
- *
- * 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.
- *
- */
-
-/*#define AUD_DEBUG
-#define DEBUG*/
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include "vorbis.h"
-
-static size_t ovcb_read (void * buffer, size_t size, size_t count, void * file)
-{
-    return vfs_fread (buffer, size, count, file);
-}
-
-static int ovcb_seek (void * file, ogg_int64_t offset, int whence)
-{
-    return vfs_fseek (file, offset, whence);
-}
-
-static int ovcb_close (void * file)
-{
-    return 0;
-}
-
-static long ovcb_tell (void * file)
-{
-    return vfs_ftell (file);
-}
-
-ov_callbacks vorbis_callbacks = {
-    ovcb_read,
-    ovcb_seek,
-    ovcb_close,
-    ovcb_tell
-};
-
-ov_callbacks vorbis_callbacks_stream = {
-    ovcb_read,
-    NULL,
-    ovcb_close,
-    NULL
-};
-
-static bool_t vorbis_check_fd (const char * filename, VFSFile * file)
-{
-    ogg_sync_state oy = {0};
-    ogg_stream_state os = {0};
-    ogg_page og = {0};
-    ogg_packet op = {0};
-
-    bool_t result = FALSE;
-
-    ogg_sync_init (& oy);
-
-    while (1)
-    {
-        int64_t bytes = ogg_sync_pageseek (& oy, & og);
-
-        if (bytes < 0) /* skipped some bytes */
-            continue;
-        if (bytes > 0) /* got a page */
-            break;
-
-        void * buffer = ogg_sync_buffer (& oy, 2048);
-        bytes = vfs_fread (buffer, 1, 2048, file);
-
-        if (bytes <= 0)
-            goto end;
-
-        ogg_sync_wrote (& oy, bytes);
-    }
-
-    if (! ogg_page_bos (& og))
-        goto end;
-
-    ogg_stream_init (& os, ogg_page_serialno (& og));
-    ogg_stream_pagein (& os, & og);
-
-    if (ogg_stream_packetout (& os, & op) > 0 && vorbis_synthesis_idheader (& op))
-        result = TRUE;
-
-end:
-    ogg_sync_clear (& oy);
-    ogg_stream_clear (& os);
-
-    return result;
-}
-
-static void
-set_tuple_str(Tuple *tuple, const gint nfield,
-    vorbis_comment *comment, gchar *key)
-{
-    tuple_set_str (tuple, nfield, vorbis_comment_query (comment, key, 0));
-}
-
-static Tuple *
-get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename)
-{
-    Tuple *tuple;
-    gint length;
-    vorbis_comment *comment = NULL;
-
-    tuple = tuple_new_from_filename(filename);
-
-    length = vfs_is_streaming (vorbisfile->datasource) ? -1 : ov_time_total
-     (vorbisfile, -1) * 1000;
-
-    /* associate with tuple */
-    tuple_set_int(tuple, FIELD_LENGTH, length);
-
-    if ((comment = ov_comment(vorbisfile, -1)) != NULL) {
-        gchar *tmps;
-        set_tuple_str(tuple, FIELD_TITLE, comment, "title");
-        set_tuple_str(tuple, FIELD_ARTIST, comment, "artist");
-        set_tuple_str(tuple, FIELD_ALBUM, comment, "album");
-        set_tuple_str(tuple, FIELD_GENRE, comment, "genre");
-        set_tuple_str(tuple, FIELD_COMMENT, comment, "comment");
-
-        if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != NULL)
-            tuple_set_int(tuple, FIELD_TRACK_NUMBER, atoi(tmps));
-
-        if ((tmps = vorbis_comment_query (comment, "date", 0)) != NULL)
-            tuple_set_int (tuple, FIELD_YEAR, atoi (tmps));
-    }
-
-    vorbis_info * info = ov_info (vorbisfile, -1);
-    tuple_set_format (tuple, "Ogg Vorbis", info->channels, info->rate,
-     info->bitrate_nominal / 1000);
-
-    tuple_set_str(tuple, FIELD_MIMETYPE, "application/ogg");
-
-    return tuple;
-}
-
-static gfloat atof_no_locale (const gchar * string)
-{
-    gfloat result = 0;
-    gboolean negative = FALSE;
-
-    if (* string == '+')
-        string ++;
-    else if (* string == '-')
-    {
-        negative = TRUE;
-        string ++;
-    }
-
-    while (* string >= '0' && * string <= '9')
-        result = 10 * result + (* string ++ - '0');
-
-    if (* string == '.')
-    {
-        gfloat place = 0.1;
-
-        string ++;
-
-        while (* string >= '0' && * string <= '9')
-        {
-            result += (* string ++ - '0') * place;
-            place *= 0.1;
-        }
-    }
-
-    return negative ? -result : result;
-}
-
-static gboolean
-vorbis_update_replaygain(OggVorbis_File *vf, ReplayGainInfo *rg_info)
-{
-    vorbis_comment *comment;
-    gchar *rg_gain, *rg_peak;
-
-    if (vf == NULL || rg_info == NULL || (comment = ov_comment(vf, -1)) == NULL)
-    {
-#ifdef DEBUG
-        printf ("No replay gain info.\n");
-#endif
-        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 != NULL) ? atof_no_locale (rg_gain) : 0.0;
-#ifdef DEBUG
-    printf ("Album gain: %s (%f)\n", rg_gain, rg_info->album_gain);
-#endif
-
-    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 != NULL) ? atof_no_locale (rg_gain) : 0.0;
-#ifdef DEBUG
-    printf ("Track gain: %s (%f)\n", rg_gain, rg_info->track_gain);
-#endif
-
-    rg_peak = vorbis_comment_query(comment, "replaygain_album_peak", 0);
-    rg_info->album_peak = rg_peak != NULL ? atof_no_locale (rg_peak) : 0.0;
-#ifdef DEBUG
-    printf ("Album peak: %s (%f)\n", rg_peak, rg_info->album_peak);
-#endif
-
-    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 != NULL ? atof_no_locale (rg_peak) : 0.0;
-#ifdef DEBUG
-    printf ("Track peak: %s (%f)\n", rg_peak, rg_info->track_peak);
-#endif
-
-    return TRUE;
-}
-
-static long
-vorbis_interleave_buffer(float **pcm, int samples, int ch, float *pcmout)
-{
-    int i, j;
-    for (i = 0; i < samples; i++)
-        for (j = 0; j < ch; j++)
-            *pcmout++ = pcm[j][i];
-
-    return ch * samples * sizeof(float);
-}
-
-
-#define PCM_FRAMES 1024
-#define PCM_BUFSIZE (PCM_FRAMES * 2)
-
-static gboolean vorbis_play (const gchar * filename, VFSFile * file)
-{
-    if (file == NULL)
-        return FALSE;
-
-    vorbis_info *vi;
-    OggVorbis_File vf;
-    gint last_section = -1;
-    ReplayGainInfo rg_info;
-    gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm;
-    gint bytes, channels, samplerate, br;
-    gchar * title = NULL;
-
-    memset(&vf, 0, sizeof(vf));
-
-    gboolean error = FALSE;
-
-    if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ?
-     vorbis_callbacks_stream : vorbis_callbacks) < 0)
-    {
-        error = TRUE;
-        goto play_cleanup;
-    }
-
-    vi = ov_info(&vf, -1);
-
-    if (vi->channels > 2)
-        goto play_cleanup;
-
-    br = vi->bitrate_nominal;
-    channels = vi->channels;
-    samplerate = vi->rate;
-
-    aud_input_set_bitrate (br);
-
-    if (!aud_input_open_audio(FMT_FLOAT, samplerate, channels)) {
-        error = TRUE;
-        goto play_cleanup;
-    }
-
-    vorbis_update_replaygain(&vf, &rg_info);
-    aud_input_set_gain (& rg_info);
-
-    /*
-     * Note that chaining changes things here; A vorbis file may
-     * be a mix of different channels, bitrates and sample rates.
-     * You can fetch the information for any section of the file
-     * using the ov_ interface.
-     */
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_value = aud_input_check_seek();
-
-        if (seek_value >= 0 && ov_time_seek (& vf, (double) seek_value / 1000) < 0)
-        {
-            fprintf (stderr, "vorbis: seek failed\n");
-            error = TRUE;
-            break;
-        }
-
-        gint current_section = last_section;
-        bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, &current_section);
-        if (bytes == OV_HOLE)
-            continue;
-
-        if (bytes <= 0)
-            break;
-
-        bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout);
-
-        { /* try to detect when metadata has changed */
-            vorbis_comment * comment = ov_comment (& vf, -1);
-            const gchar * new_title = (comment == NULL) ? NULL :
-             vorbis_comment_query (comment, "title", 0);
-
-            if (new_title != NULL && (title == NULL || strcmp (title, new_title)))
-            {
-                g_free (title);
-                title = g_strdup (new_title);
-
-                aud_input_set_tuple (get_tuple_for_vorbisfile (& vf,
-                 filename));
-            }
-        }
-
-        if (current_section != last_section)
-        {
-            /*
-             * The info struct is different in each section.  vf
-             * holds them all for the given bitstream.  This
-             * requests the current one
-             */
-            vi = ov_info(&vf, -1);
-
-            if (vi->channels > 2)
-                goto stop_processing;
-
-            if (vi->rate != samplerate || vi->channels != channels)
-            {
-                samplerate = vi->rate;
-                channels = vi->channels;
-
-                if (!aud_input_open_audio(FMT_FLOAT, vi->rate, vi->channels)) {
-                    error = TRUE;
-                    goto stop_processing;
-                }
-
-                vorbis_update_replaygain(&vf, &rg_info);
-                aud_input_set_gain (& rg_info); /* audio reopened */
-            }
-        }
-
-        aud_input_write_audio (pcmout, bytes);
-
-stop_processing:
-
-        if (current_section != last_section)
-        {
-            aud_input_set_bitrate (br);
-            last_section = current_section;
-        }
-    } /* main loop */
-
-play_cleanup:
-
-    ov_clear(&vf);
-    g_free (title);
-    return ! error;
-}
-
-static Tuple * get_song_tuple (const gchar * filename, VFSFile * file)
-{
-    OggVorbis_File vfile;          /* avoid thread interaction */
-    Tuple *tuple = NULL;
-
-    /*
-     * The open function performs full stream detection and
-     * machine initialization.  If it returns zero, the stream
-     * *is* Vorbis and we're fully ready to decode.
-     */
-    if (ov_open_callbacks (file, & vfile, NULL, 0, vfs_is_streaming (file) ?
-     vorbis_callbacks_stream : vorbis_callbacks) < 0)
-        return NULL;
-
-    tuple = get_tuple_for_vorbisfile(&vfile, filename);
-    ov_clear(&vfile);
-    return tuple;
-}
-
-static gboolean get_song_image (const gchar * filename, VFSFile * file,
- void * * data, gint64 * size)
-{
-    OggVorbis_File vfile;
-
-    if (ov_open_callbacks (file, & vfile, NULL, 0, vfs_is_streaming (file) ?
-     vorbis_callbacks_stream : vorbis_callbacks) < 0)
-        return FALSE;
-
-    vorbis_comment * comment = ov_comment (& vfile, -1);
-    if (! comment)
-        goto ERR;
-
-    const gchar * s;
-
-    if ((s = vorbis_comment_query (comment, "METADATA_BLOCK_PICTURE", 0)))
-    {
-        gsize length2;
-        void * data2 = g_base64_decode (s, & length2);
-        if (! data2 || length2 < 8)
-            goto PARSE_ERR;
-
-        gint mime_length = GUINT32_FROM_BE (* (guint32 *) (data2 + 4));
-        if (length2 < 8 + mime_length + 4)
-            goto PARSE_ERR;
-
-        gint desc_length = GUINT32_FROM_BE (* (guint32 *) (data2 + 8 + mime_length));
-        if (length2 < 8 + mime_length + 4 + desc_length + 20)
-            goto PARSE_ERR;
-
-        * size = GUINT32_FROM_BE (* (guint32 *) (data2 + 8 + mime_length + 4 + desc_length + 16));
-        if (length2 < 8 + mime_length + 4 + desc_length + 20 + * size)
-            goto PARSE_ERR;
-
-        * data = g_memdup ((char *) data2 + 8 + mime_length + 4 + desc_length + 20, * size);
-
-        g_free (data2);
-        ov_clear (& vfile);
-        return TRUE;
-
-    PARSE_ERR:
-        fprintf (stderr, "vorbis: Error parsing METADATA_BLOCK_PICTURE in %s.\n", filename);
-        g_free (data2);
-    }
-
-    if ((s = vorbis_comment_query (comment, "COVERART", 0)))
-    {
-        gsize length2;
-        void * data2 = g_base64_decode (s, & length2);
-
-        if (! data2 || ! length2)
-        {
-            fprintf (stderr, "vorbis: Error parsing COVERART in %s.\n", filename);
-            g_free (data2);
-            goto ERR;
-        }
-
-        * data = data2;
-        * size = length2;
-
-        ov_clear (& vfile);
-        return TRUE;
-    }
-
-ERR:
-    ov_clear (& vfile);
-    return FALSE;
-}
-
-static const char vorbis_about[] =
- N_("Audacious Ogg Vorbis Decoder\n\n"
-    "Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
-    "http://www.xiph.org/\n\n"
-    "Original code by:\n"
-    "Tony Arcieri <bascule at inferno.tusculum.edu>\n\n"
-    "Contributions from:\n"
-    "Chris Montgomery <monty at xiph.org>\n"
-    "Peter Alm <peter at xmms.org>\n"
-    "Michael Smith <msmith at labyrinth.edu.au>\n"
-    "Jack Moffitt <jack at icecast.org>\n"
-    "Jorn Baayen <jorn at nl.linux.org>\n"
-    "Håvard Kvålen <havardk at xmms.org>\n"
-    "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
-    "Eugene Zagidullin <e.asphyx at gmail.com>");
-
-static const gchar *vorbis_fmts[] = { "ogg", "ogm", "oga", NULL };
-static const gchar * const mimes[] = {"application/ogg", NULL};
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("Ogg Vorbis Decoder"),
-    .domain = PACKAGE,
-    .about_text = vorbis_about,
-    .play = vorbis_play,
-    .probe_for_tuple = get_song_tuple,
-    .get_song_image = get_song_image,
-    .update_song_tuple = vorbis_update_song_tuple,
-    .is_our_file_from_vfs = vorbis_check_fd,
-    .extensions = vorbis_fmts,
-    .mimes = mimes,
-
-    /* medium-high priority (a little slow) */
-    .priority = 2,
-)
diff --git a/src/vorbis/vorbis.cc b/src/vorbis/vorbis.cc
new file mode 100644
index 000000000000..531ec95fe082
--- /dev/null
+++ b/src/vorbis/vorbis.cc
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) Tony Arcieri <bascule at inferno.tusculum.edu>
+ * Copyright (C) 2001-2002 Håvard Kvålen <havardk at xmms.org>
+ * Copyright (C) 2007 William Pitcock <nenolod at sacredspiral.co.uk>
+ * Copyright (C) 2008 Cristi Măgherușan <majeru at gentoo.ro>
+ * Copyright (C) 2008 Eugene Zagidullin <e.asphyx at gmail.com>
+ * Copyright (C) 2009-2011 Audacious Developers
+ *
+ * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp at sjeng.org>
+ *
+ * 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.
+ *
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+#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 size_t ovcb_read (void * buffer, size_t size, size_t count, void * file)
+{
+    return ((VFSFile *) file)->fread (buffer, size, count);
+}
+
+static int ovcb_seek (void * file, ogg_int64_t offset, int whence)
+{
+    return ((VFSFile *) file)->fseek (offset, to_vfs_seek_type (whence));
+}
+
+static int ovcb_close (void * file)
+{
+    return 0;
+}
+
+static long ovcb_tell (void * file)
+{
+    return ((VFSFile *) file)->ftell ();
+}
+
+ov_callbacks vorbis_callbacks = {
+    ovcb_read,
+    ovcb_seek,
+    ovcb_close,
+    ovcb_tell
+};
+
+ov_callbacks vorbis_callbacks_stream = {
+    ovcb_read,
+    nullptr,
+    ovcb_close,
+    nullptr
+};
+
+bool VorbisPlugin::is_our_file (const char * filename, VFSFile & file)
+{
+    ogg_sync_state oy = {0};
+    ogg_stream_state os = {0};
+    ogg_page og = {0};
+    ogg_packet op = {0};
+
+    bool result = false;
+
+    ogg_sync_init (& oy);
+
+    while (1)
+    {
+        int64_t bytes = ogg_sync_pageseek (& oy, & og);
+
+        if (bytes < 0) /* skipped some bytes */
+            continue;
+        if (bytes > 0) /* got a page */
+            break;
+
+        void * buffer = ogg_sync_buffer (& oy, 2048);
+        bytes = file.fread (buffer, 1, 2048);
+
+        if (bytes <= 0)
+            goto end;
+
+        ogg_sync_wrote (& oy, bytes);
+    }
+
+    if (! ogg_page_bos (& og))
+        goto end;
+
+    ogg_stream_init (& os, ogg_page_serialno (& og));
+    ogg_stream_pagein (& os, & og);
+
+    if (ogg_stream_packetout (& os, & op) > 0 && vorbis_synthesis_idheader (& op))
+        result = true;
+
+end:
+    ogg_sync_clear (& oy);
+    ogg_stream_clear (& os);
+
+    return result;
+}
+
+static void
+set_tuple_str(Tuple &tuple, Tuple::Field field,
+    vorbis_comment *comment, const char *key)
+{
+    tuple.set_str (field, vorbis_comment_query (comment, key, 0));
+}
+
+static Tuple
+get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const char *filename, bool stream)
+{
+    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;
+}
+
+/* try to detect when metadata has changed */
+static bool vorbis_fetch_tuple (OggVorbis_File * vf, const char * filename, bool stream, 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 (! new_title || (old_title && ! strcmp (old_title, new_title)))
+        return false;
+
+    tuple = get_tuple_for_vorbisfile (vf, filename, stream);
+    return true;
+}
+
+static bool vorbis_fetch_replaygain (OggVorbis_File * vf, ReplayGainInfo * rg_info)
+{
+    vorbis_comment *comment;
+    char *rg_gain, *rg_peak;
+
+    if (vf == nullptr || rg_info == nullptr || (comment = ov_comment(vf, -1)) == nullptr)
+    {
+        AUDDBG ("No replay gain info.\n");
+        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;
+    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;
+    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;
+    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;
+    AUDDBG ("Track peak: %s (%f)\n", rg_peak, rg_info->track_peak);
+
+    return true;
+}
+
+static long
+vorbis_interleave_buffer(float **pcm, int samples, int ch, float *pcmout)
+{
+    int i, j;
+    for (i = 0; i < samples; i++)
+        for (j = 0; j < ch; j++)
+            *pcmout++ = pcm[j][i];
+
+    return ch * samples * sizeof(float);
+}
+
+
+#define PCM_FRAMES 1024
+#define PCM_BUFSIZE (PCM_FRAMES * 2)
+
+bool VorbisPlugin::play (const char * filename, VFSFile & file)
+{
+    vorbis_info *vi;
+    OggVorbis_File vf;
+    int last_section = -1;
+    Tuple tuple;
+    ReplayGainInfo rg_info;
+    float pcmout[PCM_BUFSIZE*sizeof(float)], **pcm;
+    int bytes, channels, samplerate, br;
+
+    memset(&vf, 0, sizeof(vf));
+
+    bool stream = (file.fsize () < 0);
+    bool error = false;
+
+    if (ov_open_callbacks (& file, & vf, nullptr, 0, stream ?
+     vorbis_callbacks_stream : vorbis_callbacks) < 0)
+    {
+        error = true;
+        goto play_cleanup;
+    }
+
+    vi = ov_info(&vf, -1);
+
+    br = vi->bitrate_nominal;
+    channels = vi->channels;
+    samplerate = vi->rate;
+
+    set_stream_bitrate (br);
+
+    if (vorbis_fetch_tuple (& vf, filename, stream, tuple))
+        set_playback_tuple (tuple.ref ());
+
+    if (vorbis_fetch_replaygain (& vf, & rg_info))
+        set_replay_gain (rg_info);
+
+    open_audio (FMT_FLOAT, samplerate, channels);
+
+    /*
+     * Note that chaining changes things here; A vorbis file may
+     * be a mix of different channels, bitrates and sample rates.
+     * You can fetch the information for any section of the file
+     * using the ov_ interface.
+     */
+
+    while (! check_stop ())
+    {
+        int seek_value = check_seek ();
+
+        if (seek_value >= 0 && ov_time_seek (& vf, (double) seek_value / 1000) < 0)
+        {
+            AUDERR ("seek failed\n");
+            error = true;
+            break;
+        }
+
+        int current_section = last_section;
+        bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, &current_section);
+        if (bytes == OV_HOLE)
+            continue;
+
+        if (bytes <= 0)
+            break;
+
+        bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout);
+
+        if (vorbis_fetch_tuple (& vf, filename, stream, tuple))
+            set_playback_tuple (tuple.ref ());
+
+        if (current_section != last_section)
+        {
+            /*
+             * The info struct is different in each section.  vf
+             * holds them all for the given bitstream.  This
+             * requests the current one
+             */
+            vi = ov_info(&vf, -1);
+
+            if (vi->rate != samplerate || vi->channels != channels)
+            {
+                samplerate = vi->rate;
+                channels = vi->channels;
+
+                if (vorbis_fetch_replaygain (& vf, & rg_info))
+                    set_replay_gain (rg_info);
+
+                open_audio (FMT_FLOAT, vi->rate, vi->channels);
+            }
+        }
+
+        write_audio (pcmout, bytes);
+
+        if (current_section != last_section)
+        {
+            set_stream_bitrate (br);
+            last_section = current_section;
+        }
+    } /* main loop */
+
+play_cleanup:
+
+    ov_clear(&vf);
+    return ! error;
+}
+
+Tuple VorbisPlugin::read_tuple (const char * filename, VFSFile & file)
+{
+    OggVorbis_File vfile;          /* avoid thread interaction */
+
+    bool stream = (file.fsize () < 0);
+
+    /*
+     * The open function performs full stream detection and
+     * machine initialization.  If it returns zero, the stream
+     * *is* Vorbis and we're fully ready to decode.
+     */
+    if (ov_open_callbacks (& file, & vfile, nullptr, 0, stream ?
+     vorbis_callbacks_stream : vorbis_callbacks) < 0)
+        return Tuple ();
+
+    Tuple tuple = get_tuple_for_vorbisfile(&vfile, filename, stream);
+    ov_clear(&vfile);
+    return tuple;
+}
+
+Index<char> VorbisPlugin::read_image (const char * filename, VFSFile & file)
+{
+    Index<char> data;
+
+    OggVorbis_File vfile;
+
+    bool stream = (file.fsize () < 0);
+
+    if (ov_open_callbacks (& file, & vfile, nullptr, 0, stream ?
+     vorbis_callbacks_stream : vorbis_callbacks) < 0)
+        return data;
+
+    vorbis_comment * comment = ov_comment (& vfile, -1);
+    if (! comment)
+        goto ERR;
+
+    const char * s;
+
+    if ((s = vorbis_comment_query (comment, "METADATA_BLOCK_PICTURE", 0)))
+    {
+        unsigned mime_length, desc_length, length;
+
+        size_t length2;
+        unsigned char * data2 = g_base64_decode (s, & length2);
+        if (! data2 || length2 < 8)
+            goto PARSE_ERR;
+
+        mime_length = FROM_BE32 (* (uint32_t *) (data2 + 4));
+        if (length2 < 8 + mime_length + 4)
+            goto PARSE_ERR;
+
+        desc_length = FROM_BE32 (* (uint32_t *) (data2 + 8 + mime_length));
+        if (length2 < 8 + mime_length + 4 + desc_length + 20)
+            goto PARSE_ERR;
+
+        length = FROM_BE32 (* (uint32_t *) (data2 + 8 + mime_length + 4 + desc_length + 16));
+        if (length2 < 8 + mime_length + 4 + desc_length + 20 + length)
+            goto PARSE_ERR;
+
+        data.insert ((char *) data2 + 8 + mime_length + 4 + desc_length + 20, 0, length);
+
+        g_free (data2);
+        ov_clear (& vfile);
+        return data;
+
+    PARSE_ERR:
+        AUDERR ("Error parsing METADATA_BLOCK_PICTURE in %s.\n", filename);
+        g_free (data2);
+    }
+
+    if ((s = vorbis_comment_query (comment, "COVERART", 0)))
+    {
+        size_t length2;
+        void * data2 = g_base64_decode (s, & length2);
+
+        if (! data2 || ! length2)
+        {
+            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;
+}
+
+const char VorbisPlugin::about[] =
+ N_("Audacious Ogg Vorbis Decoder\n\n"
+    "Based on the Xiph.org Foundation's Ogg Vorbis Plugin:\n"
+    "http://www.xiph.org/\n\n"
+    "Original code by:\n"
+    "Tony Arcieri <bascule at inferno.tusculum.edu>\n\n"
+    "Contributions from:\n"
+    "Chris Montgomery <monty at xiph.org>\n"
+    "Peter Alm <peter at xmms.org>\n"
+    "Michael Smith <msmith at labyrinth.edu.au>\n"
+    "Jack Moffitt <jack at icecast.org>\n"
+    "Jorn Baayen <jorn at nl.linux.org>\n"
+    "Håvard Kvålen <havardk at xmms.org>\n"
+    "Gian-Carlo Pascutto <gcp at sjeng.org>\n"
+    "Eugene Zagidullin <e.asphyx at gmail.com>");
+
+const char * const VorbisPlugin::exts[] = {"ogg", "ogm", "oga", nullptr};
+const char * const VorbisPlugin::mimes[] = {"application/ogg", nullptr};
diff --git a/src/vorbis/vorbis.h b/src/vorbis/vorbis.h
index 268c5112ef5b..28ab572decf5 100644
--- a/src/vorbis/vorbis.h
+++ b/src/vorbis/vorbis.h
@@ -3,10 +3,35 @@
 
 #include <vorbis/vorbisfile.h>
 
-#include <audacious/plugin.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
 
 extern ov_callbacks vorbis_callbacks;
 
-gboolean vorbis_update_song_tuple (const char * filename, VFSFile * fd, const Tuple * tuple);
+class VorbisPlugin : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[], * const mimes[];
+
+    static constexpr PluginInfo info = {
+        N_("Ogg Vorbis Decoder"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagWritesTag)
+        .with_priority (2)  /* medium-high priority (a little slow) */
+        .with_exts (exts)
+        .with_mimes (mimes);
+
+    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 write_tuple (const char * filename, VFSFile & file, const Tuple & tuple);
+    bool play (const char * filename, VFSFile & file);
+};
 
 #endif                          /* __VORBIS_H__ */
diff --git a/src/vtx/Makefile b/src/vtx/Makefile
index 0b8c1c4e3090..7fbab2f6aa5b 100644
--- a/src/vtx/Makefile
+++ b/src/vtx/Makefile
@@ -1,16 +1,18 @@
 PLUGIN = vtx${PLUGIN_SUFFIX}
 
-SRCS = ay8912.c		\
-       info.c		\
-       lh5dec.c		\
-       vtx.c		\
-       vtxfile.c
+SRCS = ay8912.cc		\
+       info.cc		\
+       lh5dec.cc		\
+       vtx.cc		\
+       vtxfile.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS}  -I../.. -I.
-LIBS += ${GTK_LIBS} ${GLIB_LIBS}
+LIBS += ${GTK_LIBS} ${GLIB_LIBS} -laudgui
diff --git a/src/vtx/ay8912.c b/src/vtx/ay8912.c
deleted file mode 100644
index 7587418e63b9..000000000000
--- a/src/vtx/ay8912.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* AY/YM emulator implementation. */
-
-#include <stdio.h>
-#include <inttypes.h>
-#include "ayemu.h"
-
-#define debuglog stderr;
-
-char *ayemu_err;
-
-/*static const char VERSION[] = "libayemu 0.9";*/
-
-const int MAGIC1 = 0xcdef;	/* for check ayemu_t structure inited */
-
-enum {
-/* Max amplitude value for stereo signal for avoiding for possible
-    folowwing SSRC for clipping */
-  AYEMU_MAX_AMP = 24575,
-  AYEMU_DEFAULT_CHIP_FREQ = 1773400
-};
-
-/* sound chip volume envelops (will calculated by gen_env()) */
-static int bEnvGenInit = 0;
-static int Envelope [16][128];
-
-
-/* AY volume table (c) by V_Soft and Lion 17 */
-static int Lion17_AY_table [16] =
-  { 0, 513, 828, 1239, 1923, 3238, 4926, 9110,
-    10344, 17876, 24682, 30442, 38844, 47270, 56402, 65535};
-
-/* YM volume table (c) by V_Soft and Lion 17 */
-static int Lion17_YM_table [32] =
-  { 0, 0, 190, 286, 375, 470, 560, 664,
-    866, 1130, 1515, 1803, 2253, 2848, 3351, 3862,
-    4844, 6058, 7290, 8559, 10474, 12878, 15297, 17787,
-    21500, 26172, 30866, 35676, 42664, 50986, 58842, 65535};
-
-/* AY volume table (c) by Hacker KAY */
-static int KAY_AY_table [16] =
-  { 0, 836, 1212, 1773, 2619, 3875, 5397, 8823,
-    10392, 16706, 23339, 29292, 36969, 46421, 55195, 65535};
-
-/* YM volume table (c) by Hacker KAY */
-static int KAY_YM_table [32] =
-  { 0, 0, 248, 450, 670, 826, 1010, 1239,
-    1552, 1919, 2314, 2626, 3131, 3778, 4407, 5031,
-    5968, 7161, 8415, 9622, 11421, 13689, 15957, 18280,
-    21759, 26148, 30523, 34879, 41434, 49404, 57492, 65535};
-
-/* default equlaizer (layout) settings for AY and YM, 7 stereo types */
-static const int default_layout [2][7][6] = {
-  {
-    /* A_l, A_r,  B_l, B_r,  C_l, C_r */
-
-    /* for AY */
-    {100, 100, 100, 100, 100, 100},	// _MONO
-    {100, 33, 70, 70, 33, 100},	   // _ABC
-    {100, 33, 33, 100, 70, 70},	   // _ACB
-    {70, 70, 100, 33, 33, 100},	   // _BAC
-    {33, 100, 100, 33, 70, 70},	   // _BCA
-    {70, 70, 33, 100, 100, 33},	   // _CAB
-    {33, 100, 70, 70, 100, 33}},   // _CBA
-  {
-    /* for YM */
-    {100, 100, 100, 100, 100, 100},	// _MONO
-    {100, 5, 70, 70, 5, 100},	// _ABC
-    {100, 5, 5, 100, 70, 70},	// _ACB
-    {70, 70, 100, 5, 5, 100},	// _BAC
-    {5, 100, 100, 5, 70, 70},	// _BCA
-    {70, 70, 5, 100, 100, 5},	// _CAB
-    {5, 100, 70, 70, 100, 5}}   // _CBA
-};
-
-
-static int check_magic(ayemu_ay_t *ay)
-{
-  if (ay->magic == MAGIC1)
-    return 1;
-  fprintf(stderr, "libayemu: passed pointer %p to uninitialized ayemu_ay_t structure\n", (void *) ay);
-  return 0;
-}
-
-
-/* make chip hardware envelop tables.
-    Will execute once before first use. */
-static void gen_env()
-{
-  int env;
-  int pos;
-  int hold;
-  int dir;
-  int vol;
-
-  for (env = 0; env < 16; env++) {
-    hold = 0;
-    dir = (env & 4)?  1 : -1;
-    vol = (env & 4)? -1 : 32;
-    for (pos = 0; pos < 128; pos++) {
-      if (!hold) {
-	vol += dir;
-	if (vol < 0 || vol >= 32) {
-	  if ( env & 8 ) {
-	    if ( env & 2 ) dir = -dir;
-	    vol = (dir > 0 )? 0:31;
-	    if ( env & 1 ) {
-	      hold = 1;
-	      vol = ( dir > 0 )? 31:0;
-	    }
-	  } else {
-	    vol = 0;
-	    hold = 1;
-	  }
-	}
-      }
-      Envelope[env][pos] = vol;
-    }
-  }
-  bEnvGenInit = 1;
-}
-
-
-/**
- * \retval ayemu_init none.
- *
-*/
-void ayemu_init(ayemu_ay_t *ay)
-{
-  ay->default_chip_flag = 1;
-  ay->ChipFreq = AYEMU_DEFAULT_CHIP_FREQ;
-  ay->default_stereo_flag = 1;
-  ay->default_sound_format_flag = 1;
-  ay->dirty = 1;
-  ay->magic = MAGIC1;
-
-  ayemu_reset(ay);
-}
-
-/** Reset AY/YM chip.
- *
- * \arg \c ay - pointer to ayemu_ay_t structure.
- * \return none.
- */
-void ayemu_reset(ayemu_ay_t *ay)
-{
-  if (!check_magic(ay)) return;
-
-  ay->cnt_a = ay->cnt_b = ay->cnt_c = ay->cnt_n = ay->cnt_e = 0;
-  ay->bit_a = ay->bit_b = ay->bit_c = ay->bit_n = 0;
-  ay->env_pos = ay->EnvNum = 0;
-  ay->Cur_Seed = 0xffff;
-}
-
-
-static void set_table_ay (ayemu_ay_t *ay, int tbl[16])
-{
-  int n;
-  for (n = 0; n < 32; n++)
-    ay->table[n] = tbl[n/2];
-  ay->type = AYEMU_AY;
-}
-
-static void set_table_ym (ayemu_ay_t *ay, int tbl[32])
-{
-  int n;
-  for (n = 0; n < 32; n++)
-    ay->table[n] = tbl[n];
-  ay->type = AYEMU_YM;
-}
-
-
-/** Set chip type. */
-int ayemu_set_chip_type(ayemu_ay_t *ay, ayemu_chip_t type, int *custom_table)
-{
-if (!check_magic(ay))
-		return 0;
-
-  if (!(type == AYEMU_AY_CUSTOM || type == AYEMU_YM_CUSTOM) && custom_table != NULL) {
-    ayemu_err = "For non-custom chip type 'custom_table' param must be NULL";
-    return 0;
-  }
-
-  switch(type) {
-  case AYEMU_AY:
-  case AYEMU_AY_LION17:
-    set_table_ay(ay, Lion17_AY_table);
-    break;
-  case AYEMU_YM:
-  case AYEMU_YM_LION17:
-    set_table_ym(ay, Lion17_YM_table);
-    break;
-  case AYEMU_AY_KAY:
-    set_table_ay(ay, KAY_AY_table);
-    break;
-  case AYEMU_YM_KAY:
-    set_table_ym(ay, KAY_YM_table);
-    break;
-  case AYEMU_AY_CUSTOM:
-    set_table_ay(ay, custom_table);
-    break;
-  case AYEMU_YM_CUSTOM:
-    set_table_ym(ay, custom_table);
-    break;
-  default:
-    ayemu_err = "Incorrect chip type";
-    return 0;
-  }
-
-  ay->default_chip_flag = 0;
-  ay->dirty = 1;
-  return 1;
-}
-
-
-/** Set chip frequency. */
-void ayemu_set_chip_freq(ayemu_ay_t *ay, int32_t chipfreq)
-{
-  if (!check_magic(ay)) return;
-
-  ay->ChipFreq = chipfreq;
-  ay->dirty = 1;
-}
-
-/*! Set output sound format
- * \arg \c ay - pointer to ayemu_t structure
- * \arg \c freq - sound freq (44100 for example)
- * \arg \c chans - number of channels (1-mono, 2-stereo)
- * \arg \c bits - now supported only 16 and 8.
- * \retval \b 1 on success, \b 0 if error occure
- */
-int ayemu_set_sound_format (ayemu_ay_t *ay, int freq, int chans, int bits)
-{
-  if (!check_magic(ay))
-    return 0;
-
-  if (!(bits == 16 || bits == 8)) {
-    ayemu_err = "Incorrect bits value";
-    return 0;
-  }
-  else if (!(chans == 1 || chans == 2)) {
-    ayemu_err = "Incorrect number of channels";
-    return 0;
-  }
-  else if (freq < 50) {
-    ayemu_err = "Incorrect output sound freq";
-    return 0;
-  }
-  else {
-    ay->sndfmt.freq = freq;
-    ay->sndfmt.channels = chans;
-    ay->sndfmt.bpc = bits;
-  }
-
-  ay->default_sound_format_flag = 0;
-  ay->dirty = 1;
-  return 1;
-}
-
-
-/*! Set amplitude factor for each of channels (A,B anc C, tone and noise).
- * Factor's value must be from (-100) to 100.
- * \arg ay - pointer to ayemu_t structure
- * \arg stereo_type - type of stereo
- * \arg custom_eq - NULL or pointer to custom table of mixer layout.
- * \retval 1 if OK, 0 if error occures.
- */
-int ayemu_set_stereo(ayemu_ay_t *ay, ayemu_stereo_t stereo_type, int *custom_eq)
-{
-  int i;
-  int chip;
-
-  if (!check_magic(ay))
-    return 0;
-
-  if (stereo_type != AYEMU_STEREO_CUSTOM && custom_eq != NULL) {
-    ayemu_err = "Stereo type not custom, 'custom_eq' parametr must be NULL";
-    return 0;
-  }
-
-  chip = (ay->type == AYEMU_AY)? 0 : 1;
-
-  switch(stereo_type) {
-  case AYEMU_MONO:
-  case AYEMU_ABC:
-  case AYEMU_ACB:
-  case AYEMU_BAC:
-  case AYEMU_BCA:
-  case AYEMU_CAB:
-  case AYEMU_CBA:
-    for (i = 0 ; i < 6 ; i++)
-      ay->eq[i] = default_layout[chip][stereo_type][i];
-    break;
-  case AYEMU_STEREO_CUSTOM:
-    for (i = 0 ; i < 6 ; i++)
-      ay->eq[i] = custom_eq[i];
-    break;
-  default:
-    ayemu_err = "Incorrect stereo type";
-    return 0;
-  }
-
-  ay->default_stereo_flag = 0;
-  ay->dirty = 1;
-  return 1;
-}
-
-
-#define WARN_IF_REGISTER_GREAT_THAN(r,m) \
-if (*(regs + r) > m) \
-   fprintf(stderr, "ayemu_set_regs: warning: possible bad register data- R%d > %d\n", r, m)
-
-
-/** Assign values for AY registers.
- *
- * You must pass array of char [14] to this function
- */
-void ayemu_set_regs(ayemu_ay_t *ay, unsigned char *regs)
-{
-  if (!check_magic(ay)) return;
-
-  WARN_IF_REGISTER_GREAT_THAN(1,15);
-  WARN_IF_REGISTER_GREAT_THAN(3,15);
-  WARN_IF_REGISTER_GREAT_THAN(5,15);
-  WARN_IF_REGISTER_GREAT_THAN(8,31);
-  WARN_IF_REGISTER_GREAT_THAN(9,31);
-  WARN_IF_REGISTER_GREAT_THAN(10,31);
-
-  ay->regs.tone_a  = regs[0] + ((regs[1]&0x0f) << 8);
-  ay->regs.tone_b  = regs[2] + ((regs[3]&0x0f) << 8);
-  ay->regs.tone_c  = regs[4] + ((regs[5]&0x0f) << 8);
-
-  ay->regs.noise = regs[6] & 0x1f;
-
-  ay->regs.R7_tone_a  = ! (regs[7] & 0x01);
-  ay->regs.R7_tone_b  = ! (regs[7] & 0x02);
-  ay->regs.R7_tone_c  = ! (regs[7] & 0x04);
-
-  ay->regs.R7_noise_a = ! (regs[7] & 0x08);
-  ay->regs.R7_noise_b = ! (regs[7] & 0x10);
-  ay->regs.R7_noise_c = ! (regs[7] & 0x20);
-
-  ay->regs.vol_a = regs[8]  & 0x0f;
-  ay->regs.vol_b = regs[9]  & 0x0f;
-  ay->regs.vol_c = regs[10] & 0x0f;
-  ay->regs.env_a = regs[8]  & 0x10;
-  ay->regs.env_b = regs[9]  & 0x10;
-  ay->regs.env_c = regs[10] & 0x10;
-  ay->regs.env_freq = regs[11] + (regs[12] << 8);
-
-  if (regs[13] != 0xff) {                   /* R13 = 255 means continue curent envelop */
-    ay->regs.env_style = regs[13] & 0x0f;
-    ay->env_pos = ay->cnt_e = 0;
-  }
-}
-
-
-static void prepare_generation(ayemu_ay_t *ay)
-{
-  int vol, max_l, max_r;
-
-  if (!ay->dirty) return;
-
-  if (!bEnvGenInit) gen_env ();
-
-  if (ay->default_chip_flag) ayemu_set_chip_type(ay, AYEMU_AY, NULL);
-
-  if (ay->default_stereo_flag) ayemu_set_stereo(ay, AYEMU_ABC, NULL);
-
-  if (ay->default_sound_format_flag) ayemu_set_sound_format(ay, 44100, 2, 16);
-
-  ay->ChipTacts_per_outcount = ay->ChipFreq / ay->sndfmt.freq / 8;
-
-  {  /* GenVols */
-    int n, m;
-    int vol;
-    for (n = 0; n < 32; n++) {
-      vol = ay->table[n];
-      for (m=0; m < 6; m++)
-	ay->vols[m][n] = (int) (((double) vol * ay->eq[m]) / 100);
-    }
-  }
-
-  /* ������ ����������������� ����
-     �������� ���vols [x][31] ���������������     TODO: �������� � ��;-)
-  */
-  max_l = ay->vols[0][31] + ay->vols[2][31] + ay->vols[3][31];
-  max_r = ay->vols[1][31] + ay->vols[3][31] + ay->vols[5][31];
-  vol = (max_l > max_r) ? max_l : max_r;  // =157283 on all defaults
-  ay->Amp_Global = ay->ChipTacts_per_outcount *vol / AYEMU_MAX_AMP;
-
-  ay->dirty = 0;
-}
-
-
-/*! Generate sound.
- * Fill sound buffer with current register data
- * Return value: pointer to next data in output sound buffer
- * \retval \b 1 if OK, \b 0 if error occures.
- */
-void *ayemu_gen_sound(ayemu_ay_t *ay, void *buff, size_t sound_bufsize)
-{
-  int mix_l, mix_r;
-  int tmpvol;
-  int m;
-  int snd_numcount;
-  unsigned char *sound_buf = buff;
-
-  if (!check_magic(ay))
-    return 0;
-
-  prepare_generation(ay);
-
-  snd_numcount = sound_bufsize / (ay->sndfmt.channels * (ay->sndfmt.bpc >> 3));
-  while (snd_numcount-- > 0) {
-    mix_l = mix_r = 0;
-
-    for (m = 0 ; m < ay->ChipTacts_per_outcount ; m++) {
-      if (++ay->cnt_a >= ay->regs.tone_a) {
-	ay->cnt_a = 0;
-	ay->bit_a = ! ay->bit_a;
-      }
-      if (++ay->cnt_b >= ay->regs.tone_b) {
-	ay->cnt_b = 0;
-	ay->bit_b = ! ay->bit_b;
-      }
-      if (++ay->cnt_c >= ay->regs.tone_c) {
-	ay->cnt_c = 0;
-	ay->bit_c = ! ay->bit_c;
-      }
-
-      /* GenNoise (c) Hacker KAY & Sergey Bulba */
-      if (++ay->cnt_n >= (ay->regs.noise * 2)) {
-	ay->cnt_n = 0;
-	ay->Cur_Seed = (ay->Cur_Seed * 2 + 1) ^ \
-	  (((ay->Cur_Seed >> 16) ^ (ay->Cur_Seed >> 13)) & 1);
-	ay->bit_n = ((ay->Cur_Seed >> 16) & 1);
-      }
-
-      if (++ay->cnt_e >= ay->regs.env_freq) {
-	ay->cnt_e = 0;
-	if (++ay->env_pos > 127)
-	  ay->env_pos = 64;
-      }
-
-#define ENVVOL Envelope [ay->regs.env_style][ay->env_pos]
-
-      if ((ay->bit_a | !ay->regs.R7_tone_a) & (ay->bit_n | !ay->regs.R7_noise_a)) {
-	tmpvol = (ay->regs.env_a)? ENVVOL : ay->regs.vol_a * 2 + 1;
-	mix_l += ay->vols[0][tmpvol];
-	mix_r += ay->vols[1][tmpvol];
-      }
-
-      if ((ay->bit_b | !ay->regs.R7_tone_b) & (ay->bit_n | !ay->regs.R7_noise_b)) {
-	tmpvol =(ay->regs.env_b)? ENVVOL :  ay->regs.vol_b * 2 + 1;
-	mix_l += ay->vols[2][tmpvol];
-	mix_r += ay->vols[3][tmpvol];
-      }
-
-      if ((ay->bit_c | !ay->regs.R7_tone_c) & (ay->bit_n | !ay->regs.R7_noise_c)) {
-	tmpvol = (ay->regs.env_c)? ENVVOL : ay->regs.vol_c * 2 + 1;
-	mix_l += ay->vols[4][tmpvol];
-	mix_r += ay->vols[5][tmpvol];
-      }
-    } /* end for (m=0; ...) */
-
-    mix_l /= ay->Amp_Global;
-    mix_r /= ay->Amp_Global;
-
-    if (ay->sndfmt.bpc == 8) {
-      mix_l = (mix_l >> 8) | 128; /* 8 bit sound */
-      mix_r = (mix_r >> 8) | 128;
-      *sound_buf++ = mix_l;
-      if (ay->sndfmt.channels != 1)
-	*sound_buf++ = mix_r;
-    } else {
-      *sound_buf++ = mix_l & 0x00FF; /* 16 bit sound */
-      *sound_buf++ = (mix_l >> 8);
-      if (ay->sndfmt.channels != 1) {
-	*sound_buf++ = mix_r & 0x00FF;
-	*sound_buf++ = (mix_r >> 8);
-      }
-    }
-  }
-  return sound_buf;
-}
-
-/** Free all data allocated by emulator
- *
- * For now it do nothing.
- */
-void ayemu_free (ayemu_ay_t *ay)
-{
-  /* nothing to do here */
-  return;
-}
diff --git a/src/vtx/ay8912.cc b/src/vtx/ay8912.cc
new file mode 100644
index 000000000000..8276cf0fd556
--- /dev/null
+++ b/src/vtx/ay8912.cc
@@ -0,0 +1,494 @@
+/* AY/YM emulator implementation. */
+
+#include <inttypes.h>
+#include "ayemu.h"
+
+#include <libaudcore/runtime.h>
+
+const char *ayemu_err;
+
+/*static const char VERSION[] = "libayemu 0.9";*/
+
+const int MAGIC1 = 0xcdef;	/* for check ayemu_t structure inited */
+
+enum {
+/* Max amplitude value for stereo signal for avoiding for possible
+    folowwing SSRC for clipping */
+  AYEMU_MAX_AMP = 24575,
+  AYEMU_DEFAULT_CHIP_FREQ = 1773400
+};
+
+/* sound chip volume envelops (will calculated by gen_env()) */
+static int bEnvGenInit = 0;
+static int Envelope [16][128];
+
+
+/* AY volume table (c) by V_Soft and Lion 17 */
+static int Lion17_AY_table [16] =
+  { 0, 513, 828, 1239, 1923, 3238, 4926, 9110,
+    10344, 17876, 24682, 30442, 38844, 47270, 56402, 65535};
+
+/* YM volume table (c) by V_Soft and Lion 17 */
+static int Lion17_YM_table [32] =
+  { 0, 0, 190, 286, 375, 470, 560, 664,
+    866, 1130, 1515, 1803, 2253, 2848, 3351, 3862,
+    4844, 6058, 7290, 8559, 10474, 12878, 15297, 17787,
+    21500, 26172, 30866, 35676, 42664, 50986, 58842, 65535};
+
+/* AY volume table (c) by Hacker KAY */
+static int KAY_AY_table [16] =
+  { 0, 836, 1212, 1773, 2619, 3875, 5397, 8823,
+    10392, 16706, 23339, 29292, 36969, 46421, 55195, 65535};
+
+/* YM volume table (c) by Hacker KAY */
+static int KAY_YM_table [32] =
+  { 0, 0, 248, 450, 670, 826, 1010, 1239,
+    1552, 1919, 2314, 2626, 3131, 3778, 4407, 5031,
+    5968, 7161, 8415, 9622, 11421, 13689, 15957, 18280,
+    21759, 26148, 30523, 34879, 41434, 49404, 57492, 65535};
+
+/* default equlaizer (layout) settings for AY and YM, 7 stereo types */
+static const int default_layout [2][7][6] = {
+  {
+    /* A_l, A_r,  B_l, B_r,  C_l, C_r */
+
+    /* for AY */
+    {100, 100, 100, 100, 100, 100},	// _MONO
+    {100, 33, 70, 70, 33, 100},	   // _ABC
+    {100, 33, 33, 100, 70, 70},	   // _ACB
+    {70, 70, 100, 33, 33, 100},	   // _BAC
+    {33, 100, 100, 33, 70, 70},	   // _BCA
+    {70, 70, 33, 100, 100, 33},	   // _CAB
+    {33, 100, 70, 70, 100, 33}},   // _CBA
+  {
+    /* for YM */
+    {100, 100, 100, 100, 100, 100},	// _MONO
+    {100, 5, 70, 70, 5, 100},	// _ABC
+    {100, 5, 5, 100, 70, 70},	// _ACB
+    {70, 70, 100, 5, 5, 100},	// _BAC
+    {5, 100, 100, 5, 70, 70},	// _BCA
+    {70, 70, 5, 100, 100, 5},	// _CAB
+    {5, 100, 70, 70, 100, 5}}   // _CBA
+};
+
+
+static int check_magic(ayemu_ay_t *ay)
+{
+  if (ay->magic == MAGIC1)
+    return 1;
+  AUDERR("passed pointer %p to uninitialized ayemu_ay_t structure\n", (void *) ay);
+  return 0;
+}
+
+
+/* make chip hardware envelop tables.
+    Will execute once before first use. */
+static void gen_env()
+{
+  int env;
+  int pos;
+  int hold;
+  int dir;
+  int vol;
+
+  for (env = 0; env < 16; env++) {
+    hold = 0;
+    dir = (env & 4)?  1 : -1;
+    vol = (env & 4)? -1 : 32;
+    for (pos = 0; pos < 128; pos++) {
+      if (!hold) {
+	vol += dir;
+	if (vol < 0 || vol >= 32) {
+	  if ( env & 8 ) {
+	    if ( env & 2 ) dir = -dir;
+	    vol = (dir > 0 )? 0:31;
+	    if ( env & 1 ) {
+	      hold = 1;
+	      vol = ( dir > 0 )? 31:0;
+	    }
+	  } else {
+	    vol = 0;
+	    hold = 1;
+	  }
+	}
+      }
+      Envelope[env][pos] = vol;
+    }
+  }
+  bEnvGenInit = 1;
+}
+
+
+/**
+ * \retval ayemu_init none.
+ *
+*/
+void ayemu_init(ayemu_ay_t *ay)
+{
+  ay->default_chip_flag = 1;
+  ay->ChipFreq = AYEMU_DEFAULT_CHIP_FREQ;
+  ay->default_stereo_flag = 1;
+  ay->default_sound_format_flag = 1;
+  ay->dirty = 1;
+  ay->magic = MAGIC1;
+
+  ayemu_reset(ay);
+}
+
+/** Reset AY/YM chip.
+ *
+ * \arg \c ay - pointer to ayemu_ay_t structure.
+ * \return none.
+ */
+void ayemu_reset(ayemu_ay_t *ay)
+{
+  if (!check_magic(ay)) return;
+
+  ay->cnt_a = ay->cnt_b = ay->cnt_c = ay->cnt_n = ay->cnt_e = 0;
+  ay->bit_a = ay->bit_b = ay->bit_c = ay->bit_n = 0;
+  ay->env_pos = ay->EnvNum = 0;
+  ay->Cur_Seed = 0xffff;
+}
+
+
+static void set_table_ay (ayemu_ay_t *ay, int tbl[16])
+{
+  int n;
+  for (n = 0; n < 32; n++)
+    ay->table[n] = tbl[n/2];
+  ay->type = AYEMU_AY;
+}
+
+static void set_table_ym (ayemu_ay_t *ay, int tbl[32])
+{
+  int n;
+  for (n = 0; n < 32; n++)
+    ay->table[n] = tbl[n];
+  ay->type = AYEMU_YM;
+}
+
+
+/** Set chip type. */
+int ayemu_set_chip_type(ayemu_ay_t *ay, ayemu_chip_t type, int *custom_table)
+{
+if (!check_magic(ay))
+		return 0;
+
+  if (!(type == AYEMU_AY_CUSTOM || type == AYEMU_YM_CUSTOM) && custom_table != nullptr) {
+    ayemu_err = "For non-custom chip type 'custom_table' param must be nullptr";
+    return 0;
+  }
+
+  switch(type) {
+  case AYEMU_AY:
+  case AYEMU_AY_LION17:
+    set_table_ay(ay, Lion17_AY_table);
+    break;
+  case AYEMU_YM:
+  case AYEMU_YM_LION17:
+    set_table_ym(ay, Lion17_YM_table);
+    break;
+  case AYEMU_AY_KAY:
+    set_table_ay(ay, KAY_AY_table);
+    break;
+  case AYEMU_YM_KAY:
+    set_table_ym(ay, KAY_YM_table);
+    break;
+  case AYEMU_AY_CUSTOM:
+    set_table_ay(ay, custom_table);
+    break;
+  case AYEMU_YM_CUSTOM:
+    set_table_ym(ay, custom_table);
+    break;
+  default:
+    ayemu_err = "Incorrect chip type";
+    return 0;
+  }
+
+  ay->default_chip_flag = 0;
+  ay->dirty = 1;
+  return 1;
+}
+
+
+/** Set chip frequency. */
+void ayemu_set_chip_freq(ayemu_ay_t *ay, int32_t chipfreq)
+{
+  if (!check_magic(ay)) return;
+
+  ay->ChipFreq = chipfreq;
+  ay->dirty = 1;
+}
+
+/*! Set output sound format
+ * \arg \c ay - pointer to ayemu_t structure
+ * \arg \c freq - sound freq (44100 for example)
+ * \arg \c chans - number of channels (1-mono, 2-stereo)
+ * \arg \c bits - now supported only 16 and 8.
+ * \retval \b 1 on success, \b 0 if error occure
+ */
+int ayemu_set_sound_format (ayemu_ay_t *ay, int freq, int chans, int bits)
+{
+  if (!check_magic(ay))
+    return 0;
+
+  if (!(bits == 16 || bits == 8)) {
+    ayemu_err = "Incorrect bits value";
+    return 0;
+  }
+  else if (!(chans == 1 || chans == 2)) {
+    ayemu_err = "Incorrect number of channels";
+    return 0;
+  }
+  else if (freq < 50) {
+    ayemu_err = "Incorrect output sound freq";
+    return 0;
+  }
+  else {
+    ay->sndfmt.freq = freq;
+    ay->sndfmt.channels = chans;
+    ay->sndfmt.bpc = bits;
+  }
+
+  ay->default_sound_format_flag = 0;
+  ay->dirty = 1;
+  return 1;
+}
+
+
+/*! Set amplitude factor for each of channels (A,B anc C, tone and noise).
+ * Factor's value must be from (-100) to 100.
+ * \arg ay - pointer to ayemu_t structure
+ * \arg stereo_type - type of stereo
+ * \arg custom_eq - nullptr or pointer to custom table of mixer layout.
+ * \retval 1 if OK, 0 if error occures.
+ */
+int ayemu_set_stereo(ayemu_ay_t *ay, ayemu_stereo_t stereo_type, int *custom_eq)
+{
+  int i;
+  int chip;
+
+  if (!check_magic(ay))
+    return 0;
+
+  if (stereo_type != AYEMU_STEREO_CUSTOM && custom_eq != nullptr) {
+    ayemu_err = "Stereo type not custom, 'custom_eq' parametr must be nullptr";
+    return 0;
+  }
+
+  chip = (ay->type == AYEMU_AY)? 0 : 1;
+
+  switch(stereo_type) {
+  case AYEMU_MONO:
+  case AYEMU_ABC:
+  case AYEMU_ACB:
+  case AYEMU_BAC:
+  case AYEMU_BCA:
+  case AYEMU_CAB:
+  case AYEMU_CBA:
+    for (i = 0 ; i < 6 ; i++)
+      ay->eq[i] = default_layout[chip][stereo_type][i];
+    break;
+  case AYEMU_STEREO_CUSTOM:
+    for (i = 0 ; i < 6 ; i++)
+      ay->eq[i] = custom_eq[i];
+    break;
+  default:
+    ayemu_err = "Incorrect stereo type";
+    return 0;
+  }
+
+  ay->default_stereo_flag = 0;
+  ay->dirty = 1;
+  return 1;
+}
+
+
+#define WARN_IF_REGISTER_GREAT_THAN(r,m) \
+if (*(regs + r) > m) \
+   AUDWARN("possible bad register data- R%d > %d\n", r, m)
+
+
+/** Assign values for AY registers.
+ *
+ * You must pass array of char [14] to this function
+ */
+void ayemu_set_regs(ayemu_ay_t *ay, unsigned char *regs)
+{
+  if (!check_magic(ay)) return;
+
+  WARN_IF_REGISTER_GREAT_THAN(1,15);
+  WARN_IF_REGISTER_GREAT_THAN(3,15);
+  WARN_IF_REGISTER_GREAT_THAN(5,15);
+  WARN_IF_REGISTER_GREAT_THAN(8,31);
+  WARN_IF_REGISTER_GREAT_THAN(9,31);
+  WARN_IF_REGISTER_GREAT_THAN(10,31);
+
+  ay->regs.tone_a  = regs[0] + ((regs[1]&0x0f) << 8);
+  ay->regs.tone_b  = regs[2] + ((regs[3]&0x0f) << 8);
+  ay->regs.tone_c  = regs[4] + ((regs[5]&0x0f) << 8);
+
+  ay->regs.noise = regs[6] & 0x1f;
+
+  ay->regs.R7_tone_a  = ! (regs[7] & 0x01);
+  ay->regs.R7_tone_b  = ! (regs[7] & 0x02);
+  ay->regs.R7_tone_c  = ! (regs[7] & 0x04);
+
+  ay->regs.R7_noise_a = ! (regs[7] & 0x08);
+  ay->regs.R7_noise_b = ! (regs[7] & 0x10);
+  ay->regs.R7_noise_c = ! (regs[7] & 0x20);
+
+  ay->regs.vol_a = regs[8]  & 0x0f;
+  ay->regs.vol_b = regs[9]  & 0x0f;
+  ay->regs.vol_c = regs[10] & 0x0f;
+  ay->regs.env_a = regs[8]  & 0x10;
+  ay->regs.env_b = regs[9]  & 0x10;
+  ay->regs.env_c = regs[10] & 0x10;
+  ay->regs.env_freq = regs[11] + (regs[12] << 8);
+
+  if (regs[13] != 0xff) {                   /* R13 = 255 means continue curent envelop */
+    ay->regs.env_style = regs[13] & 0x0f;
+    ay->env_pos = ay->cnt_e = 0;
+  }
+}
+
+
+static void prepare_generation(ayemu_ay_t *ay)
+{
+  int vol, max_l, max_r;
+
+  if (!ay->dirty) return;
+
+  if (!bEnvGenInit) gen_env ();
+
+  if (ay->default_chip_flag) ayemu_set_chip_type(ay, AYEMU_AY, nullptr);
+
+  if (ay->default_stereo_flag) ayemu_set_stereo(ay, AYEMU_ABC, nullptr);
+
+  if (ay->default_sound_format_flag) ayemu_set_sound_format(ay, 44100, 2, 16);
+
+  ay->ChipTacts_per_outcount = ay->ChipFreq / ay->sndfmt.freq / 8;
+
+  {  /* GenVols */
+    int n, m;
+    int vol;
+    for (n = 0; n < 32; n++) {
+      vol = ay->table[n];
+      for (m=0; m < 6; m++)
+	ay->vols[m][n] = (int) (((double) vol * ay->eq[m]) / 100);
+    }
+  }
+
+  /* ������ ����������������� ����
+     �������� ���vols [x][31] ���������������     TODO: �������� � ��;-)
+  */
+  max_l = ay->vols[0][31] + ay->vols[2][31] + ay->vols[3][31];
+  max_r = ay->vols[1][31] + ay->vols[3][31] + ay->vols[5][31];
+  vol = (max_l > max_r) ? max_l : max_r;  // =157283 on all defaults
+  ay->Amp_Global = ay->ChipTacts_per_outcount *vol / AYEMU_MAX_AMP;
+
+  ay->dirty = 0;
+}
+
+
+/*! Generate sound.
+ * Fill sound buffer with current register data
+ * Return value: pointer to next data in output sound buffer
+ * \retval \b 1 if OK, \b 0 if error occures.
+ */
+void *ayemu_gen_sound(ayemu_ay_t *ay, void *buff, size_t sound_bufsize)
+{
+  int mix_l, mix_r;
+  int tmpvol;
+  int m;
+  int snd_numcount;
+  unsigned char *sound_buf = (unsigned char *) buff;
+
+  if (!check_magic(ay))
+    return 0;
+
+  prepare_generation(ay);
+
+  snd_numcount = sound_bufsize / (ay->sndfmt.channels * (ay->sndfmt.bpc >> 3));
+  while (snd_numcount-- > 0) {
+    mix_l = mix_r = 0;
+
+    for (m = 0 ; m < ay->ChipTacts_per_outcount ; m++) {
+      if (++ay->cnt_a >= ay->regs.tone_a) {
+	ay->cnt_a = 0;
+	ay->bit_a = ! ay->bit_a;
+      }
+      if (++ay->cnt_b >= ay->regs.tone_b) {
+	ay->cnt_b = 0;
+	ay->bit_b = ! ay->bit_b;
+      }
+      if (++ay->cnt_c >= ay->regs.tone_c) {
+	ay->cnt_c = 0;
+	ay->bit_c = ! ay->bit_c;
+      }
+
+      /* GenNoise (c) Hacker KAY & Sergey Bulba */
+      if (++ay->cnt_n >= (ay->regs.noise * 2)) {
+	ay->cnt_n = 0;
+	ay->Cur_Seed = (ay->Cur_Seed * 2 + 1) ^ \
+	  (((ay->Cur_Seed >> 16) ^ (ay->Cur_Seed >> 13)) & 1);
+	ay->bit_n = ((ay->Cur_Seed >> 16) & 1);
+      }
+
+      if (++ay->cnt_e >= ay->regs.env_freq) {
+	ay->cnt_e = 0;
+	if (++ay->env_pos > 127)
+	  ay->env_pos = 64;
+      }
+
+#define ENVVOL Envelope [ay->regs.env_style][ay->env_pos]
+
+      if ((ay->bit_a | !ay->regs.R7_tone_a) & (ay->bit_n | !ay->regs.R7_noise_a)) {
+	tmpvol = (ay->regs.env_a)? ENVVOL : ay->regs.vol_a * 2 + 1;
+	mix_l += ay->vols[0][tmpvol];
+	mix_r += ay->vols[1][tmpvol];
+      }
+
+      if ((ay->bit_b | !ay->regs.R7_tone_b) & (ay->bit_n | !ay->regs.R7_noise_b)) {
+	tmpvol =(ay->regs.env_b)? ENVVOL :  ay->regs.vol_b * 2 + 1;
+	mix_l += ay->vols[2][tmpvol];
+	mix_r += ay->vols[3][tmpvol];
+      }
+
+      if ((ay->bit_c | !ay->regs.R7_tone_c) & (ay->bit_n | !ay->regs.R7_noise_c)) {
+	tmpvol = (ay->regs.env_c)? ENVVOL : ay->regs.vol_c * 2 + 1;
+	mix_l += ay->vols[4][tmpvol];
+	mix_r += ay->vols[5][tmpvol];
+      }
+    } /* end for (m=0; ...) */
+
+    mix_l /= ay->Amp_Global;
+    mix_r /= ay->Amp_Global;
+
+    if (ay->sndfmt.bpc == 8) {
+      mix_l = (mix_l >> 8) | 128; /* 8 bit sound */
+      mix_r = (mix_r >> 8) | 128;
+      *sound_buf++ = mix_l;
+      if (ay->sndfmt.channels != 1)
+	*sound_buf++ = mix_r;
+    } else {
+      *sound_buf++ = mix_l & 0x00FF; /* 16 bit sound */
+      *sound_buf++ = (mix_l >> 8);
+      if (ay->sndfmt.channels != 1) {
+	*sound_buf++ = mix_r & 0x00FF;
+	*sound_buf++ = (mix_r >> 8);
+      }
+    }
+  }
+  return sound_buf;
+}
+
+/** Free all data allocated by emulator
+ *
+ * For now it do nothing.
+ */
+void ayemu_free (ayemu_ay_t *ay)
+{
+  /* nothing to do here */
+  return;
+}
diff --git a/src/vtx/ayemu.h b/src/vtx/ayemu.h
index 15ab7ac355bb..18195a5b42a9 100644
--- a/src/vtx/ayemu.h
+++ b/src/vtx/ayemu.h
@@ -16,20 +16,12 @@
   License along with this library; if not, write to the Free
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
-  Alexander Sashnov 
+  Alexander Sashnov
   sashnov at ngs.ru
 */
 #ifndef _AYEMU_H
 #define _AYEMU_H
 
-#ifdef __cplusplus
-#  define BEGIN_C_DECLS extern "C" {
-#  define END_C_DECLS   }
-#else /* !__cplusplus */
-#  define BEGIN_C_DECLS
-#  define END_C_DECLS
-#endif /* __cplusplus */
-
 #define EXTERN extern
 
 /* typedefs for 32-bit architecture */
diff --git a/src/vtx/ayemu_8912.h b/src/vtx/ayemu_8912.h
index a43a195f0b6a..2ffc5dc80008 100644
--- a/src/vtx/ayemu_8912.h
+++ b/src/vtx/ayemu_8912.h
@@ -8,8 +8,6 @@
 #include <stddef.h>
 #include <inttypes.h>
 
-BEGIN_C_DECLS
-
 /** Types of stereo.
     The codes of stereo types used for generage sound. */
 typedef enum
@@ -43,7 +41,7 @@ typedef enum {
 typedef struct
 {
   int tone_a;           /**< R0, R1 */
-  int tone_b;		/**< R2, R3 */	
+  int tone_b;		/**< R2, R3 */
   int tone_c;		/**< R4, R5 */
   int noise;		/**< R6 */
   int R7_tone_a;	/**< R7 bit 0 */
@@ -79,7 +77,7 @@ ayemu_sndfmt_t;
 /*@{*/
 
 /** Data structure for sound chip emulation \internal
- * 
+ *
  */
 typedef struct
 {
@@ -88,7 +86,7 @@ typedef struct
   ayemu_chip_t type;		/**< general chip type (\b AYEMU_AY or \b AYEMU_YM) */
   int32_t ChipFreq;			/**< chip emulator frequency */
   int eq[6];			/**< volumes for channels.
-				   Array contains 6 elements: 
+				   Array contains 6 elements:
 				   A left, A right, B left, B right, C left and C right;
 				   range -100...100 */
   ayemu_regdata_t regs;		/**< parsed registers data */
@@ -126,7 +124,7 @@ ayemu_init(ayemu_ay_t *ay);
 EXTERN void
 ayemu_reset(ayemu_ay_t *ay);
 
-EXTERN int 
+EXTERN int
 ayemu_set_chip_type(ayemu_ay_t *ay, ayemu_chip_t chip, int *custom_table);
 
 EXTERN void
@@ -138,7 +136,7 @@ ayemu_set_stereo(ayemu_ay_t *ay, ayemu_stereo_t stereo, int *custom_eq);
 EXTERN int
 ayemu_set_sound_format (ayemu_ay_t *ay, int freq, int chans, int bits);
 
-EXTERN void 
+EXTERN void
 ayemu_set_regs (ayemu_ay_t *ay, unsigned char *regs);
 
 EXTERN void*
@@ -146,6 +144,4 @@ ayemu_gen_sound (ayemu_ay_t *ay, void *buf, size_t bufsize);
 
 /*@}*/
 
-END_C_DECLS
-
 #endif
diff --git a/src/vtx/ayemu_vtxfile.h b/src/vtx/ayemu_vtxfile.h
index b938d951fbe1..227945db24ec 100644
--- a/src/vtx/ayemu_vtxfile.h
+++ b/src/vtx/ayemu_vtxfile.h
@@ -1,9 +1,8 @@
 #ifndef _AYEMU_vtxfile_h
 #define _AYEMU_vtxfile_h
 
-#include <glib.h>
 #include <inttypes.h>
-#include <audacious/plugin.h>
+#include <libaudcore/plugin.h>
 #include "ayemu_8912.h"
 
 /* The following constants and data structure comes from
@@ -15,8 +14,6 @@
 
 typedef char NTstring[AYEMU_VTX_NTSTRING_MAX+1];
 
-BEGIN_C_DECLS
-
 /** VTX file format header and status of open file
  * \internal
  *
@@ -50,44 +47,33 @@ struct VTXFileHeader
  * It stores VTX file header and current state
  * (open file pointer, extracted register data, etc).
  */
-typedef struct
+struct ayemu_vtx_t
 {
-  VFSFile *fp;			/**< opening .vtx file pointer */
-  struct VTXFileHeader hdr;  	/**< VTX header data */
-  char *regdata;		/**< unpacked song data */
-  int pos;			/**< current data frame offset */
-} ayemu_vtx_t;
+  VTXFileHeader hdr;             /**< VTX header data */
+  Index<unsigned char> regdata;  /**< unpacked song data */
+  int pos;                       /**< current data frame offset */
 
+  /** Read vtx file header
+      \return Return true if success, else false
+  */
+  bool read_header(VFSFile &file);
 
-/** Open vtx file and read vtx file header
-    \arg \c vtx - pointer to ayemu_vtx_t structure
-    \arg \c filename - filename for open vtx file
-    \return Return true if success, else false
-*/
-EXTERN int ayemu_vtx_open (ayemu_vtx_t *vtx, const char *filename);
-  
-/** Read and encode lha data from .vtx file.
- * \return Return pointer to unpacked data or NULL.
- */
-EXTERN char *ayemu_vtx_load_data (ayemu_vtx_t *vtx);
-  
-/** Get next 14-bytes frame of AY register data.
- * \return Return value: true if sucess, false if not enought data.
- */
-EXTERN int ayemu_vtx_get_next_frame (ayemu_vtx_t *vtx, char *regs);
-  
-/** Print formated file name. If fmt is NULL the default format %a - %t will used
- * \return none.
- */
-EXTERN void ayemu_vtx_sprintname (const ayemu_vtx_t *vtx, char *buf, const int sz, const char *fmt);
+  /** Read and encode lha data from .vtx file.
+      \return Return true if success, else false
+   */
+  bool load_data(VFSFile &file);
 
-/** Free all of allocaded resource for this file.
- * You must call this function on end work with vtx file
- */
-EXTERN void ayemu_vtx_free (ayemu_vtx_t *vtx);
+  /** Get next 14-bytes frame of AY register data.
+   * \return Return value: true if success, false if not enough data.
+   */
+  bool get_next_frame(unsigned char *regs);
 
-/*@}*/
+  /** Print formatted file name. If fmt is nullptr the default format %a - %t will be used
+   * \return none.
+   */
+  StringBuf sprintname(const char *fmt);
+};
 
-END_C_DECLS
+/*@}*/
 
 #endif
diff --git a/src/vtx/info.c b/src/vtx/info.c
deleted file mode 100644
index ec54f39252f0..000000000000
--- a/src/vtx/info.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "ayemu.h"
-#include "vtx.h"
-
-#include <audacious/i18n.h>
-#include <libaudgui/libaudgui.h>
-#include <libaudgui/libaudgui-gtk.h>
-
-void vtx_file_info(const gchar *filename)
-{
-  static GtkWidget *box;
-  ayemu_vtx_t vtx;
-
-  if (!ayemu_vtx_open(&vtx, filename))
-    {
-      fprintf(stderr, "Can't open file %s\n", filename);
-      return;
-    }
-  else
-    {
-      gchar head[1024];
-      gchar body[8192];
-
-      sprintf(head, "Details about %s", filename);
-
-	  ayemu_vtx_sprintname(&vtx, body, sizeof(body),
-	      "Title: %t\n"
-	      "Author: %a\n"
-	      "From : %f\n"
-	      "Tracker : %T\n"
-	      "Comment : %C\n"
-	      "Chip type: %c\n"
-	      "Stereo: %s\n"
-	      "Loop: %l\n"
-	      "Chip freq: %F\n"
-	      "Player Freq:%P\n"
-	      "Year: %y");
-
-      audgui_simple_message (& box, GTK_MESSAGE_INFO, head, body);
-    }
-}
diff --git a/src/vtx/info.cc b/src/vtx/info.cc
new file mode 100644
index 000000000000..8401982e70bd
--- /dev/null
+++ b/src/vtx/info.cc
@@ -0,0 +1,38 @@
+#include "ayemu.h"
+#include "vtx.h"
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/runtime.h>
+#include <libaudgui/libaudgui.h>
+#include <libaudgui/libaudgui-gtk.h>
+
+void vtx_file_info(const char *filename, VFSFile &file)
+{
+  static GtkWidget *box;
+  ayemu_vtx_t vtx;
+
+  if (!vtx.read_header(file))
+    {
+      AUDERR("Can't open file %s\n", filename);
+      return;
+    }
+  else
+    {
+      StringBuf head = str_printf(_("Details about %s"), filename);
+      StringBuf body = vtx.sprintname(_(
+        "Title: %t\n"
+        "Author: %a\n"
+        "From: %f\n"
+        "Tracker: %T\n"
+        "Comment: %C\n"
+        "Chip type: %c\n"
+        "Stereo: %s\n"
+        "Loop: %l\n"
+        "Chip freq: %F\n"
+        "Player Freq: %P\n"
+        "Year: %y"));
+
+      audgui_simple_message (& box, GTK_MESSAGE_INFO, head, body);
+    }
+}
diff --git a/src/vtx/lh5dec.c b/src/vtx/lh5dec.c
deleted file mode 100644
index 5c67fe4484b2..000000000000
--- a/src/vtx/lh5dec.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/* extractiong lh5 module
-   (c) Haruhiko Okumura
-   (m) Roman Scherbakov
-*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>   /* memmove */
-#include <limits.h>
-
-static unsigned short bitbuf;
-
-#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
-
-#define DICBIT    13    /* 12(-lh4-) or 13(-lh5-) */
-#define DICSIZ   (1L << DICBIT)
-#define MATCHBIT   8    /* bits for MAXMATCH - THRESHOLD */
-#define MAXMATCH 256    /* formerly F (not more than unsigned char_MAX + 1) */
-#define THRESHOLD  3    /* choose optimal value */
-#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
-#define CBIT 9          /* $\lfloor \log_2 NC \rfloor + 1$ */
-#define CODE_BIT  16    /* codeword length */
-#define NP (DICBIT + 1)
-#define NT (CODE_BIT + 3)
-#define PBIT 4          /* smallest integer such that (1U << PBIT) > NP */
-#define TBIT 5          /* smallest integer such that (1U << TBIT) > NT */
-#if NT > NP
-#define NPT NT
-#else
-#define NPT NP
-#endif
-
-static unsigned long origsize, compsize;
-static unsigned char *in_buf;
-static unsigned char *out_buf;
-
-static unsigned short  subbitbuf;
-static int   bitcount;
-
-static unsigned short left[2 * NC - 1], right[2 * NC - 1];
-static unsigned char  c_len[NC], pt_len[NPT];
-static unsigned short   blocksize;
-
-static unsigned short c_table[4096], pt_table[256];
-
-static int j;  /* remaining bytes to copy */
-
-
-static void error(char *msg)
-{
-  fprintf(stderr, "libayemu: lh5dec.c: %s\n", msg);
-  exit(EXIT_FAILURE);
-}
-
-static void fillbuf(int n)  /* Shift bitbuf n bits left, read n bits */
-{
-  bitbuf <<= n;
-  while (n > bitcount) {
-    bitbuf |= subbitbuf << (n -= bitcount);
-    if (compsize != 0) {
-      compsize--;  subbitbuf = *in_buf++;
-    } else subbitbuf = 0;
-    bitcount = CHAR_BIT;
-  }
-  bitbuf |= subbitbuf >> (bitcount -= n);
-}
-
-static unsigned short getbits(int n)
-{
-  unsigned short x;
-
-  x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n);
-  return x;
-}
-
-// make table for decoding
-
-static void make_table(int nchar, unsigned char bitlen[], int tablebits, unsigned short table[])
-{
-  unsigned short count[17], weight[17], start[18], *p;
-  unsigned short i, k, len, ch, jutbits, avail, nextcode, mask;
-
-  for (i = 1; i <= 16; i++) count[i] = 0;
-  for (i = 0; i < nchar; i++) count[bitlen[i]]++;
-
-  start[1] = 0;
-  for (i = 1; i <= 16; i++)
-    start[i + 1] = start[i] + (count[i] << (16 - i));
-  if (start[17] != (unsigned short)(1U << 16)) error("Bad table");
-
-  jutbits = 16 - tablebits;
-  for (i = 1; i <= tablebits; i++) {
-    start[i] >>= jutbits;
-    weight[i] = 1U << (tablebits - i);
-  }
-  while (i <= 16) {
-      weight[i] = 1U << (16 - i);
-      i++;
-  }
-
-  i = start[tablebits + 1] >> jutbits;
-  if (i != (unsigned short)(1U << 16)) {
-    k = 1U << tablebits;
-    while (i != k) table[i++] = 0;
-  }
-
-  avail = nchar;
-  mask = 1U << (15 - tablebits);
-  for (ch = 0; ch < nchar; ch++) {
-    if ((len = bitlen[ch]) == 0) continue;
-    nextcode = start[len] + weight[len];
-    if (len <= tablebits) {
-      for (i = start[len]; i < nextcode; i++) table[i] = ch;
-    } else {
-      k = start[len];
-      p = &table[k >> jutbits];
-      i = len - tablebits;
-      while (i != 0) {
-	if (*p == 0) {
-	  right[avail] = left[avail] = 0;
-	  *p = avail++;
-	}
-	if (k & mask) p = &right[*p];
-	else          p = &left[*p];
-	k <<= 1;  i--;
-      }
-      *p = ch;
-    }
-    start[len] = nextcode;
-  }
-}
-
-// static Huffman
-
-static void read_pt_len(int nn, int nbit, int i_special)
-{
-  int i, c, n;
-  unsigned short mask;
-
-  n = getbits(nbit);
-  if (n == 0) {
-    c = getbits(nbit);
-    for (i = 0; i < nn; i++) pt_len[i] = 0;
-    for (i = 0; i < 256; i++) pt_table[i] = c;
-  } else {
-    i = 0;
-    while (i < n) {
-      c = bitbuf >> (BITBUFSIZ - 3);
-      if (c == 7) {
-	mask = 1U << (BITBUFSIZ - 1 - 3);
-	while (mask & bitbuf) {  mask >>= 1;  c++;  }
-      }
-      fillbuf((c < 7) ? 3 : c - 3);
-      pt_len[i++] = c;
-      if (i == i_special) {
-	c = getbits(2);
-	while (--c >= 0) pt_len[i++] = 0;
-      }
-    }
-    while (i < nn) pt_len[i++] = 0;
-    make_table(nn, pt_len, 8, pt_table);
-  }
-}
-
-static void read_c_len(void)
-{
-  int i, c, n;
-  unsigned short mask;
-
-  n = getbits(CBIT);
-  if (n == 0) {
-    c = getbits(CBIT);
-    for (i = 0; i < NC; i++) c_len[i] = 0;
-    for (i = 0; i < 4096; i++) c_table[i] = c;
-  } else {
-    i = 0;
-    while (i < n) {
-      c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
-      if (c >= NT) {
-	mask = 1U << (BITBUFSIZ - 1 - 8);
-	do {
-	  if (bitbuf & mask) c = right[c];
-	  else               c = left [c];
-	  mask >>= 1;
-	} while (c >= NT);
-      }
-      fillbuf(pt_len[c]);
-      if (c <= 2) {
-	if      (c == 0) c = 1;
-	else if (c == 1) c = getbits(4) + 3;
-	else             c = getbits(CBIT) + 20;
-	while (--c >= 0) c_len[i++] = 0;
-      } else c_len[i++] = c - 2;
-    }
-    while (i < NC) c_len[i++] = 0;
-    make_table(NC, c_len, 12, c_table);
-  }
-}
-
-
-static unsigned short decode_c(void)
-{
-  unsigned short j, mask;
-
-  if (blocksize == 0) {
-    blocksize = getbits(16);
-    read_pt_len(NT, TBIT, 3);
-    read_c_len();
-    read_pt_len(NP, PBIT, -1);
-  }
-  blocksize--;
-  j = c_table[bitbuf >> (BITBUFSIZ - 12)];
-  if (j >= NC) {
-    mask = 1U << (BITBUFSIZ - 1 - 12);
-    do {
-      if (bitbuf & mask) j = right[j];
-      else               j = left [j];
-      mask >>= 1;
-    } while (j >= NC);
-  }
-  fillbuf(c_len[j]);
-  return j;
-}
-
-
-static unsigned short decode_p(void)
-{
-  unsigned short j, mask;
-
-  j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
-  if (j >= NP) {
-    mask = 1U << (BITBUFSIZ - 1 - 8);
-    do {
-      if (bitbuf & mask) j = right[j];
-      else               j = left [j];
-      mask >>= 1;
-    } while (j >= NP);
-  }
-  fillbuf(pt_len[j]);
-  if (j != 0) j = (1U << (j - 1)) + getbits(j - 1);
-  return j;
-}
-
-
-static void decode(unsigned short count, unsigned char buffer[])
-{
-  static unsigned short i;
-  unsigned short r, c;
-
-  r = 0;
-  while (--j >= 0) {
-    buffer[r] = buffer[i];
-    i = (i + 1) & (DICSIZ - 1);
-    if (++r == count) return;
-  }
-  for ( ; ; ) {
-    c = decode_c();
-    if (c <= UCHAR_MAX) {
-      buffer[r] = c & UCHAR_MAX;
-      if (++r == count) return;
-    } else {
-      j = c - (UCHAR_MAX + 1 - THRESHOLD);
-      i = (r - decode_p() - 1) & (DICSIZ - 1);
-      while (--j >= 0) {
-	buffer[r] = buffer[i];
-	i = (i + 1) & (DICSIZ - 1);
-	if (++r == count) return;
-      }
-    }
-  }
-}
-
-void lh5_decode(unsigned char *inp, unsigned char *outp, unsigned long original_size, unsigned long packed_size)
-{
-  unsigned short n;
-  unsigned char *buffer;
-
-  compsize = packed_size;
-  origsize = original_size;
-  in_buf = inp;
-  out_buf = outp;
-
-  buffer = (unsigned char *) malloc(DICSIZ);
-  if (!buffer) error ("Out of memory");
-
-  bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
-  fillbuf(BITBUFSIZ);
-  blocksize = 0;
-  j = 0;
-
-  while (origsize != 0) {
-    n = (origsize > DICSIZ) ? DICSIZ : (unsigned short)origsize;
-    decode(n, buffer);
-    memmove(out_buf, buffer, n);
-    out_buf += n;
-    origsize -= n;
-  }
-
-  if (buffer) free (buffer);
-  buffer = NULL;
-}
diff --git a/src/vtx/lh5dec.cc b/src/vtx/lh5dec.cc
new file mode 100644
index 000000000000..b9cebc011cb7
--- /dev/null
+++ b/src/vtx/lh5dec.cc
@@ -0,0 +1,305 @@
+/* extractiong lh5 module
+   (c) Haruhiko Okumura
+   (m) Roman Scherbakov
+*/
+#include <string.h>   /* memmove */
+#include <limits.h>
+
+#include <libaudcore/runtime.h>
+
+#include "vtx.h"
+
+static unsigned short bitbuf;
+
+#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
+
+#define DICBIT    13    /* 12(-lh4-) or 13(-lh5-) */
+#define DICSIZ   (1UL << DICBIT)
+#define MATCHBIT   8    /* bits for MAXMATCH - THRESHOLD */
+#define MAXMATCH 256    /* formerly F (not more than unsigned char_MAX + 1) */
+#define THRESHOLD  3    /* choose optimal value */
+#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9          /* $\lfloor \log_2 NC \rfloor + 1$ */
+#define CODE_BIT  16    /* codeword length */
+#define NP (DICBIT + 1)
+#define NT (CODE_BIT + 3)
+#define PBIT 4          /* smallest integer such that (1U << PBIT) > NP */
+#define TBIT 5          /* smallest integer such that (1U << TBIT) > NT */
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+
+static unsigned long origsize, compsize;
+static const unsigned char *in_buf;
+static unsigned char *out_buf;
+
+static unsigned short  subbitbuf;
+static int   bitcount;
+
+static unsigned short left[2 * NC - 1], right[2 * NC - 1];
+static unsigned char  c_len[NC], pt_len[NPT];
+static unsigned short   blocksize;
+
+static unsigned short c_table[4096], pt_table[256];
+
+static int j;  /* remaining bytes to copy */
+
+class DecodeError {}; // exception
+
+static void error(const char *msg)
+{
+  AUDERR("%s\n", msg);
+  throw DecodeError();
+}
+
+static void fillbuf(int n)  /* Shift bitbuf n bits left, read n bits */
+{
+  bitbuf <<= n;
+  while (n > bitcount) {
+    bitbuf |= subbitbuf << (n -= bitcount);
+    if (compsize != 0) {
+      compsize--;  subbitbuf = *in_buf++;
+    } else subbitbuf = 0;
+    bitcount = CHAR_BIT;
+  }
+  bitbuf |= subbitbuf >> (bitcount -= n);
+}
+
+static unsigned short getbits(int n)
+{
+  unsigned short x;
+
+  x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n);
+  return x;
+}
+
+// make table for decoding
+
+static void make_table(int nchar, unsigned char bitlen[], int tablebits, unsigned short table[])
+{
+  unsigned short count[17], weight[17], start[18], *p;
+  unsigned short i, k, len, ch, jutbits, avail, nextcode, mask;
+
+  for (i = 1; i <= 16; i++) count[i] = 0;
+  for (i = 0; i < nchar; i++) count[bitlen[i]]++;
+
+  start[1] = 0;
+  for (i = 1; i <= 16; i++)
+    start[i + 1] = start[i] + (count[i] << (16 - i));
+  if (start[17] != (unsigned short)(1U << 16)) error("Bad table");
+
+  jutbits = 16 - tablebits;
+  for (i = 1; i <= tablebits; i++) {
+    start[i] >>= jutbits;
+    weight[i] = 1U << (tablebits - i);
+  }
+  while (i <= 16) {
+      weight[i] = 1U << (16 - i);
+      i++;
+  }
+
+  i = start[tablebits + 1] >> jutbits;
+  if (i != (unsigned short)(1U << 16)) {
+    k = 1U << tablebits;
+    while (i != k) table[i++] = 0;
+  }
+
+  avail = nchar;
+  mask = 1U << (15 - tablebits);
+  for (ch = 0; ch < nchar; ch++) {
+    if ((len = bitlen[ch]) == 0) continue;
+    nextcode = start[len] + weight[len];
+    if (len <= tablebits) {
+      for (i = start[len]; i < nextcode; i++) table[i] = ch;
+    } else {
+      k = start[len];
+      p = &table[k >> jutbits];
+      i = len - tablebits;
+      while (i != 0) {
+	if (*p == 0) {
+	  right[avail] = left[avail] = 0;
+	  *p = avail++;
+	}
+	if (k & mask) p = &right[*p];
+	else          p = &left[*p];
+	k <<= 1;  i--;
+      }
+      *p = ch;
+    }
+    start[len] = nextcode;
+  }
+}
+
+// static Huffman
+
+static void read_pt_len(int nn, int nbit, int i_special)
+{
+  int i, c, n;
+  unsigned short mask;
+
+  n = getbits(nbit);
+  if (n == 0) {
+    c = getbits(nbit);
+    for (i = 0; i < nn; i++) pt_len[i] = 0;
+    for (i = 0; i < 256; i++) pt_table[i] = c;
+  } else {
+    i = 0;
+    while (i < n) {
+      c = bitbuf >> (BITBUFSIZ - 3);
+      if (c == 7) {
+	mask = 1U << (BITBUFSIZ - 1 - 3);
+	while (mask & bitbuf) {  mask >>= 1;  c++;  }
+      }
+      fillbuf((c < 7) ? 3 : c - 3);
+      pt_len[i++] = c;
+      if (i == i_special) {
+	c = getbits(2);
+	while (--c >= 0) pt_len[i++] = 0;
+      }
+    }
+    while (i < nn) pt_len[i++] = 0;
+    make_table(nn, pt_len, 8, pt_table);
+  }
+}
+
+static void read_c_len(void)
+{
+  int i, c, n;
+  unsigned short mask;
+
+  n = getbits(CBIT);
+  if (n == 0) {
+    c = getbits(CBIT);
+    for (i = 0; i < NC; i++) c_len[i] = 0;
+    for (i = 0; i < 4096; i++) c_table[i] = c;
+  } else {
+    i = 0;
+    while (i < n) {
+      c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+      if (c >= NT) {
+	mask = 1U << (BITBUFSIZ - 1 - 8);
+	do {
+	  if (bitbuf & mask) c = right[c];
+	  else               c = left [c];
+	  mask >>= 1;
+	} while (c >= NT);
+      }
+      fillbuf(pt_len[c]);
+      if (c <= 2) {
+	if      (c == 0) c = 1;
+	else if (c == 1) c = getbits(4) + 3;
+	else             c = getbits(CBIT) + 20;
+	while (--c >= 0) c_len[i++] = 0;
+      } else c_len[i++] = c - 2;
+    }
+    while (i < NC) c_len[i++] = 0;
+    make_table(NC, c_len, 12, c_table);
+  }
+}
+
+
+static unsigned short decode_c(void)
+{
+  unsigned short j, mask;
+
+  if (blocksize == 0) {
+    blocksize = getbits(16);
+    read_pt_len(NT, TBIT, 3);
+    read_c_len();
+    read_pt_len(NP, PBIT, -1);
+  }
+  blocksize--;
+  j = c_table[bitbuf >> (BITBUFSIZ - 12)];
+  if (j >= NC) {
+    mask = 1U << (BITBUFSIZ - 1 - 12);
+    do {
+      if (bitbuf & mask) j = right[j];
+      else               j = left [j];
+      mask >>= 1;
+    } while (j >= NC);
+  }
+  fillbuf(c_len[j]);
+  return j;
+}
+
+
+static unsigned short decode_p(void)
+{
+  unsigned short j, mask;
+
+  j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+  if (j >= NP) {
+    mask = 1U << (BITBUFSIZ - 1 - 8);
+    do {
+      if (bitbuf & mask) j = right[j];
+      else               j = left [j];
+      mask >>= 1;
+    } while (j >= NP);
+  }
+  fillbuf(pt_len[j]);
+  if (j != 0) j = (1U << (j - 1)) + getbits(j - 1);
+  return j;
+}
+
+
+static void decode(unsigned short count, unsigned char buffer[])
+{
+  static unsigned short i;
+  unsigned short r, c;
+
+  r = 0;
+  while (--j >= 0) {
+    buffer[r] = buffer[i];
+    i = (i + 1) & (DICSIZ - 1);
+    if (++r == count) return;
+  }
+  for ( ; ; ) {
+    c = decode_c();
+    if (c <= UCHAR_MAX) {
+      buffer[r] = c & UCHAR_MAX;
+      if (++r == count) return;
+    } else {
+      j = c - (UCHAR_MAX + 1 - THRESHOLD);
+      i = (r - decode_p() - 1) & (DICSIZ - 1);
+      while (--j >= 0) {
+	buffer[r] = buffer[i];
+	i = (i + 1) & (DICSIZ - 1);
+	if (++r == count) return;
+      }
+    }
+  }
+}
+
+bool lh5_decode(const Index<char> &in, Index<unsigned char> &out)
+{
+  unsigned short n;
+  Index<unsigned char> buffer;
+
+  compsize = in.len();
+  origsize = out.len();
+  in_buf = (unsigned char *)in.begin();
+  out_buf = out.begin();
+
+  buffer.resize(DICSIZ);
+
+  bitbuf = 0;  subbitbuf = 0;  bitcount = 0;
+  fillbuf(BITBUFSIZ);
+  blocksize = 0;
+  j = 0;
+
+  try {
+    while (origsize != 0) {
+      n = aud::min(DICSIZ, origsize);
+      decode(n, buffer.begin());
+      memmove(out_buf, buffer.begin(), n);
+      out_buf += n;
+      origsize -= n;
+    }
+  } catch (DecodeError &) {
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/vtx/vtx.c b/src/vtx/vtx.c
deleted file mode 100644
index e88b482c1a8b..000000000000
--- a/src/vtx/vtx.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*  VTX Input Plugin for Audacious
- *
- *  Copyright (C) 2002-2004 Sashnov Alexander
- *  Copyright (C) 2010 Michał Lipski <tallica at o2.pl>
- *
- *  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.
- */
-
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <audacious/debug.h>
-
-#include "vtx.h"
-#include "ayemu.h"
-
-#define SNDBUFSIZE 1024
-static gchar sndbuf[SNDBUFSIZE];
-static gint freq = 44100;
-static gint chans = 2;
-static gint bits = 16;
-
-ayemu_ay_t ay;
-ayemu_vtx_t vtx;
-
-static const gchar *vtx_fmts[] = { "vtx", NULL };
-
-gint vtx_is_our_fd(const gchar * filename, VFSFile * fp)
-{
-    gchar buf[2];
-    if (vfs_fread(buf, 1, 2, fp) < 2)
-        return FALSE;
-    return (!g_ascii_strncasecmp(buf, "ay", 2) || !g_ascii_strncasecmp(buf, "ym", 2));
-}
-
-Tuple *vtx_get_song_tuple_from_vtx(const gchar * filename, ayemu_vtx_t * in)
-{
-    Tuple *out = tuple_new_from_filename(filename);
-
-    tuple_set_str(out, FIELD_ARTIST, in->hdr.author);
-    tuple_set_str(out, FIELD_TITLE, in->hdr.title);
-
-    tuple_set_int(out, FIELD_LENGTH, in->hdr.regdata_size / 14 * 1000 / 50);
-
-    tuple_set_str(out, FIELD_GENRE, (in->hdr.chiptype == AYEMU_AY) ? "AY chiptunes" : "YM chiptunes");
-    tuple_set_str(out, FIELD_ALBUM, in->hdr.from);
-
-    tuple_set_str(out, FIELD_QUALITY, _("sequenced"));
-    tuple_set_str(out, FIELD_CODEC, in->hdr.tracker);
-
-    tuple_set_int(out, FIELD_YEAR, in->hdr.year);
-
-    return out;
-}
-
-Tuple *vtx_probe_for_tuple(const gchar *filename, VFSFile *fd)
-{
-    ayemu_vtx_t tmp;
-
-    if (ayemu_vtx_open(&tmp, filename))
-    {
-        Tuple *ti = vtx_get_song_tuple_from_vtx(filename, &tmp);
-        ayemu_vtx_free(&tmp);
-        return ti;
-    }
-
-    return NULL;
-}
-
-static gboolean vtx_play(const gchar * filename, VFSFile * file)
-{
-    gboolean eof = FALSE;
-    void *stream;               /* pointer to current position in sound buffer */
-    guchar regs[14];
-    gint need;
-    gint left;                   /* how many sound frames can play with current AY register frame */
-    gint donow;
-    gint rate;
-
-    left = 0;
-    rate = chans * (bits / 8);
-
-    memset(&ay, 0, sizeof(ay));
-
-    if (!ayemu_vtx_open(&vtx, filename))
-    {
-        g_print("libvtx: Error read vtx header from %s\n", filename);
-        return FALSE;
-    }
-    else if (!ayemu_vtx_load_data(&vtx))
-    {
-        g_print("libvtx: Error read vtx data from %s\n", filename);
-        return FALSE;
-    }
-
-    ayemu_init(&ay);
-    ayemu_set_chip_type(&ay, vtx.hdr.chiptype, NULL);
-    ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq);
-    ayemu_set_stereo(&ay, vtx.hdr.stereo, NULL);
-
-    if (aud_input_open_audio(FMT_S16_NE, freq, chans) == 0)
-    {
-        g_print("libvtx: output audio error!\n");
-        return FALSE;
-    }
-
-    aud_input_set_bitrate(14 * 50 * 8);
-
-    while (!aud_input_check_stop() && !eof)
-    {
-        /* (time in sec) * 50 = offset in AY register data frames */
-        int seek_value = aud_input_check_seek();
-        if (seek_value >= 0)
-            vtx.pos = seek_value / 20;
-
-        /* fill sound buffer */
-        stream = sndbuf;
-
-        for (need = SNDBUFSIZE / rate; need > 0; need -= donow)
-        {
-            if (left > 0)
-            {                   /* use current AY register frame */
-                donow = (need > left) ? left : need;
-                left -= donow;
-                stream = ayemu_gen_sound(&ay, (char *)stream, donow * rate);
-            }
-            else
-            {                   /* get next AY register frame */
-                if (ayemu_vtx_get_next_frame(&vtx, (char *)regs) == 0)
-                {
-                    donow = need;
-                    memset(stream, 0, donow * rate);
-                    eof = TRUE;
-                }
-                else
-                {
-                    left = freq / vtx.hdr.playerFreq;
-                    ayemu_set_regs(&ay, regs);
-                    donow = 0;
-                }
-            }
-        }
-
-        aud_input_write_audio(sndbuf, SNDBUFSIZE);
-    }
-
-    ayemu_vtx_free(&vtx);
-
-    return TRUE;
-}
-
-static const char vtx_about[] =
- N_("Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
-    "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
-    "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>");
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("VTX Decoder"),
-    .domain = PACKAGE,
-    .about_text = vtx_about,
-    .play = vtx_play,
-    .file_info_box = vtx_file_info,
-    .probe_for_tuple = vtx_probe_for_tuple,
-    .is_our_file_from_vfs = vtx_is_our_fd,
-    .extensions = vtx_fmts
-)
diff --git a/src/vtx/vtx.cc b/src/vtx/vtx.cc
new file mode 100644
index 000000000000..d6709451a984
--- /dev/null
+++ b/src/vtx/vtx.cc
@@ -0,0 +1,186 @@
+/*  VTX Input Plugin for Audacious
+ *
+ *  Copyright (C) 2002-2004 Sashnov Alexander
+ *  Copyright (C) 2010 Michał Lipski <tallica at o2.pl>
+ *
+ *  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.
+ */
+
+#include <string.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include "vtx.h"
+#include "ayemu.h"
+
+class VTXPlugin : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char *const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("VTX Decoder"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo()
+        .with_exts(exts);
+
+    constexpr VTXPlugin() : InputPlugin(info, iinfo) {}
+
+    bool is_our_file(const char *filename, VFSFile &file);
+    Tuple read_tuple(const char *filename, VFSFile &file);
+    bool play(const char *filename, VFSFile &file);
+
+    bool file_info_box(const char *filename, VFSFile &file)
+        { vtx_file_info(filename, file); return true; }
+};
+
+EXPORT VTXPlugin aud_plugin_instance;
+
+#define SNDBUFSIZE 1024
+static char sndbuf[SNDBUFSIZE];
+static int freq = 44100;
+static int chans = 2;
+static int bits = 16;
+
+const char *const VTXPlugin::exts[] = { "vtx", nullptr };
+
+bool VTXPlugin::is_our_file(const char *filename, VFSFile &file)
+{
+    char buf[2];
+    if (file.fread (buf, 1, 2) < 2)
+        return false;
+    return (!strcmp_nocase(buf, "ay", 2) || !strcmp_nocase(buf, "ym", 2));
+}
+
+Tuple vtx_get_song_tuple_from_vtx(const char * filename, ayemu_vtx_t * in)
+{
+    Tuple tuple;
+    tuple.set_filename (filename);
+
+    tuple.set_str (Tuple::Artist, in->hdr.author);
+    tuple.set_str (Tuple::Title, in->hdr.title);
+
+    tuple.set_int (Tuple::Length, in->hdr.regdata_size / 14 * 1000 / 50);
+
+    tuple.set_str (Tuple::Genre, (in->hdr.chiptype == AYEMU_AY) ? "AY chiptunes" : "YM chiptunes");
+    tuple.set_str (Tuple::Album, in->hdr.from);
+
+    tuple.set_str (Tuple::Quality, _("sequenced"));
+    tuple.set_str (Tuple::Codec, in->hdr.tracker);
+
+    tuple.set_int (Tuple::Year, in->hdr.year);
+
+    return tuple;
+}
+
+Tuple VTXPlugin::read_tuple(const char *filename, VFSFile &file)
+{
+    ayemu_vtx_t tmp;
+
+    if (tmp.read_header(file))
+        return vtx_get_song_tuple_from_vtx(filename, &tmp);
+
+    return Tuple ();
+}
+
+bool VTXPlugin::play(const char *filename, VFSFile &file)
+{
+    ayemu_ay_t ay;
+    ayemu_vtx_t vtx;
+
+    bool eof = false;
+    void *stream;               /* pointer to current position in sound buffer */
+    unsigned char regs[14];
+    int need;
+    int left;                   /* how many sound frames can play with current AY register frame */
+    int donow;
+    int rate;
+
+    left = 0;
+    rate = chans * (bits / 8);
+
+    memset(&ay, 0, sizeof(ay));
+
+    if (!vtx.read_header(file))
+    {
+        AUDERR("Error read vtx header from %s\n", filename);
+        return false;
+    }
+    else if (!vtx.load_data(file))
+    {
+        AUDERR("Error read vtx data from %s\n", filename);
+        return false;
+    }
+
+    ayemu_init(&ay);
+    ayemu_set_chip_type(&ay, vtx.hdr.chiptype, nullptr);
+    ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq);
+    ayemu_set_stereo(&ay, (ayemu_stereo_t) vtx.hdr.stereo, nullptr);
+
+    set_stream_bitrate(14 * 50 * 8);
+    open_audio(FMT_S16_NE, freq, chans);
+
+    while (!check_stop() && !eof)
+    {
+        /* (time in sec) * 50 = offset in AY register data frames */
+        int seek_value = check_seek();
+        if (seek_value >= 0)
+            vtx.pos = seek_value / 20;
+
+        /* fill sound buffer */
+        stream = sndbuf;
+
+        for (need = SNDBUFSIZE / rate; need > 0; need -= donow)
+        {
+            if (left > 0)
+            {                   /* use current AY register frame */
+                donow = (need > left) ? left : need;
+                left -= donow;
+                stream = ayemu_gen_sound(&ay, (char *)stream, donow * rate);
+            }
+            else
+            {                   /* get next AY register frame */
+                if (!vtx.get_next_frame(regs))
+                {
+                    donow = need;
+                    memset(stream, 0, donow * rate);
+                    eof = true;
+                }
+                else
+                {
+                    left = freq / vtx.hdr.playerFreq;
+                    ayemu_set_regs(&ay, regs);
+                    donow = 0;
+                }
+            }
+        }
+
+        write_audio(sndbuf, SNDBUFSIZE);
+    }
+
+    return true;
+}
+
+const char VTXPlugin::about[] =
+ N_("Vortex file format player by Sashnov Alexander <sashnov at ngs.ru>\n"
+    "Based on in_vtx.dll by Roman Sherbakov <v_soft at microfor.ru>\n"
+    "Audacious plugin by Pavel Vymetalek <pvymetalek at seznam.cz>");
diff --git a/src/vtx/vtx.h b/src/vtx/vtx.h
index cae6bf830da6..1c96271b234a 100644
--- a/src/vtx/vtx.h
+++ b/src/vtx/vtx.h
@@ -1,12 +1,14 @@
 #ifndef VTX_H
 #define VTX_H
 
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
+#include <libaudcore/index.h>
 
-#include <audacious/plugin.h>
+class VFSFile;
 
-void vtx_file_info(const char *filename);
+/* info.cc */
+void vtx_file_info (const char *filename, VFSFile &file);
+
+/* lh5dec.cc */
+bool lh5_decode(const Index<char> &in, Index<unsigned char> &out);
 
 #endif
diff --git a/src/vtx/vtxfile.c b/src/vtx/vtxfile.c
deleted file mode 100644
index b6f1376ba23c..000000000000
--- a/src/vtx/vtxfile.c
+++ /dev/null
@@ -1,331 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-#include <inttypes.h>
-
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include "ayemu.h"
-
-/* defined in lh5dec.c */
-extern void lh5_decode(unsigned char *inp,unsigned char *outp,unsigned long original_size, unsigned long packed_size);
-
-
-/* Read 8-bit integer from file.
- * Return 1 if error occurs
- */
-static int read_byte(VFSFile *fp, int *p)
-{
-  int c;
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_byte()");
-    return 1;
-  }
-  *p = c;
-  return 0;
-}
-
-/* Read 16-bit integer from file.
- * Return 1 if error occurs
- */
-static int read_word16(VFSFile *fp, int *p)
-{
-  int c;
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word16()");
-    return 1;
-  }
-  *p = c;
-
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word16()");
-    return 1;
-  }
-  *p += c << 8;
-
-  return 0;
-}
-
-/* read 32-bit integer from file.
- *  Returns 1 if error occurs
- */
-static int read_word32(VFSFile *fp, int32_t *p)
-{
-  int c;
-
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word32()");
-    return 1;
-  }
-  *p = c;
-
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word32()");
-    return 1;
-  }
-  *p += c << 8;
-
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word32()");
-    return 1;
-  }
-  *p += c << 16;
-
-  if ((c = vfs_getc(fp)) == EOF) {
-    perror("libayemu: read_word32()");
-    return 1;
-  }
-  *p += c << 24;
-
-  return 0;
-}
-
-/* read_NTstring: reads null-terminated string from file.
- *  Return 1 if error occures.
- */
-static int read_NTstring(VFSFile *fp, char s[])
-{
-  int i, c;
-  for (i = 0 ; i < AYEMU_VTX_NTSTRING_MAX && (c = vfs_getc(fp)) != EOF && c ; i++)
-    s[i] = c;
-  s[i] = '\0';
-  if (c == EOF) {
-    fprintf(stderr, "libayemu: read_NTstring(): uninspected end of file!\n");
-    return 1;
-  }
-  return 0;
-}
-
-/** Open specified .vtx file and read vtx file header
- *
- *  Open specified .vtx file and read vtx file header in struct vtx
- *  Return value: true if success, else false
- */
-int ayemu_vtx_open (ayemu_vtx_t *vtx, const char *filename)
-{
-  char buf[2];
-  int error = 0;
-  int32_t int_regdata_size;
-
-  vtx->regdata = NULL;
-
-  if ((vtx->fp = vfs_fopen (filename, "rb")) == NULL) {
-    fprintf(stderr, "ayemu_vtx_open: Cannot open file %s: %s\n", filename, strerror(errno));
-    return 0;
-  }
-
-  if (vfs_fread(buf, 2, 1, vtx->fp) != 1) {
-    fprintf(stderr,"ayemu_vtx_open: Can't read from %s: %s\n", filename, strerror(errno));
-    error = 1;
-  }
-
-  buf[0] = tolower(buf[0]);
-  buf[1] = tolower(buf[1]);
-
-  if (strncmp(buf, "ay", 2) == 0)
-    vtx->hdr.chiptype = AYEMU_AY;
-  else if (strncmp (buf, "ym", 2) == 0)
-    vtx->hdr.chiptype = AYEMU_YM;
-  else {
-    fprintf (stderr, "File %s is _not_ VORTEX format!\nIt not begins from AY or YM.\n", filename);
-    error = 1;
-  }
-
-  /* read VTX header info in order format specified, see http:// ..... */
-  if (!error) error = read_byte(vtx->fp, &vtx->hdr.stereo);
-  if (!error) error = read_word16(vtx->fp, &vtx->hdr.loop);
-  if (!error) error = read_word32(vtx->fp, &vtx->hdr.chipFreq);
-  if (!error) error = read_byte(vtx->fp, &vtx->hdr.playerFreq);
-  if (!error) error = read_word16(vtx->fp, &vtx->hdr.year);
-  if (!error) {
-	error = read_word32(vtx->fp, &int_regdata_size);
-	vtx->hdr.regdata_size = (size_t) int_regdata_size;
-  }
-
-  if (!error) error = read_NTstring(vtx->fp, vtx->hdr.title);
-  if (!error) error = read_NTstring(vtx->fp, vtx->hdr.author);
-  if (!error) error = read_NTstring(vtx->fp, vtx->hdr.from);
-  if (!error) error = read_NTstring(vtx->fp, vtx->hdr.tracker);
-  if (!error) error = read_NTstring (vtx->fp, vtx->hdr.comment);
-
-  if (error) {
-    vfs_fclose(vtx->fp);
-    vtx->fp = NULL;
-  }
-  return !error;
-}
-
-/** Read and encode lha data from .vtx file
- *
- * Return value: pointer to unpacked data or NULL
- * Note: you must call ayemu_vtx_open() first.
- */
-char *ayemu_vtx_load_data (ayemu_vtx_t *vtx)
-{
-  char *packed_data;
-  size_t packed_size;
-  size_t buf_alloc;
-  int c;
-
-  if (vtx->fp == NULL) {
-    fprintf(stderr, "ayemu_vtx_load_data: tune file not open yet (do you call ayemu_vtx_open first?)\n");
-    return NULL;
-  }
-  packed_size = 0;
-  buf_alloc = 4096;
-  packed_data = (char *) malloc (buf_alloc);
-  /* read packed AY register data to end of file. */
-  while ((c = vfs_getc (vtx->fp)) != EOF) {
-    if (buf_alloc < packed_size) {
-      buf_alloc *= 2;
-      packed_data = (char *) realloc (packed_data, buf_alloc);
-      if (packed_data == NULL) {
-	fprintf (stderr, "ayemu_vtx_load_data: Packed data out of memory!\n");
-	vfs_fclose (vtx->fp);
-	return NULL;
-      }
-    }
-    packed_data[packed_size++] = c;
-  }
-  vfs_fclose (vtx->fp);
-  vtx->fp = NULL;
-  if ((vtx->regdata = (char *) malloc (vtx->hdr.regdata_size)) == NULL) {
-    fprintf (stderr, "ayemu_vtx_load_data: Can allocate %d bytes for unpack register data\n", (int)(vtx->hdr.regdata_size));
-    free (packed_data);
-    return NULL;
-  }
-  lh5_decode ((unsigned char *)packed_data, (unsigned char *)(vtx->regdata), vtx->hdr.regdata_size, packed_size);
-  free (packed_data);
-  vtx->pos = 0;
-  return vtx->regdata;
-}
-
-/** Get next 14-bytes frame of AY register data.
- *
- * Return value: 1 if sucess, 0 if no enought data.
- */
-int ayemu_vtx_get_next_frame (ayemu_vtx_t *vtx, char *regs)
-{
-  int numframes = vtx->hdr.regdata_size / 14;
-  if (vtx->pos++ >= numframes)
-    return 0;
-  else {
-    int n;
-    char *p = vtx->regdata + vtx->pos;
-    for(n = 0 ; n < 14 ; n++, p+=numframes)
-      regs[n] = *p;
-    return 1;
-  }
-}
-
-static void append_string(char *buf, const int sz, const char *str)
-{
-  if (strlen(buf) + strlen(str) < sz - 1)
-    strcat(buf, str);
-}
-
-static void append_number(char *buf, const int sz, const int num)
-{
-  char s[32];
-  str_itoa (num, s, sizeof s);
-  append_string(buf, sz, s);
-}
-
-static void append_char(char *buf, const int sz, const char c)
-{
-  int pos = strlen(buf);
-  if (pos < sz - 1)
-    buf[pos++] = c;
-  buf[pos] = '\0';
-}
-
-/** Print formated file name. If fmt is NULL the default format %a - %t will used
- *
- * %% the % sign
- * %a author of song
- * %t song title
- * %y year
- * %f song from
- * %T Tracker
- * %C Comment
- * %s stereo type (ABC, BCA, ...)
- * %l 'looped' or 'non-looped'
- * %c chip type: 'AY' or 'YM'
- * %F chip Freq
- * %P player freq
- */
-void ayemu_vtx_sprintname (const ayemu_vtx_t *vtx, char *const buf, const int sz, const char *fmt)
-{
-  static char *stereo_types[] = { "MONO", "ABC", "ACB", "BAC", "BCA", "CAB", "CBA" };
-
-  if (fmt == NULL)
-    fmt = "%a - %t";
-
-  buf[0] = '\0';
-
-  while (*fmt != '\0') {
-    if (*fmt == '%') {
-      switch(*++fmt) {
-      case 'a':
-	append_string(buf, sz, vtx->hdr.author);
-	break;
-      case 't':
-	append_string(buf, sz, vtx->hdr.title);
-	break;
-      case 'y':
-	append_number(buf, sz, vtx->hdr.year);
-	break;
-      case 'f':
-	append_string(buf, sz, vtx->hdr.from);
-	break;
-      case 'T':
-	append_string(buf, sz, vtx->hdr.tracker);
-	break;
-      case 'C':
-	append_string(buf, sz, vtx->hdr.comment);
-	break;
-      case 's':
-	append_string(buf, sz, stereo_types[vtx->hdr.stereo]);
-	break;
-      case 'l':
-	append_string(buf, sz, (vtx->hdr.loop)? "looped" : "non-looped" );
-	break;
-      case 'c':
-	append_string(buf, sz, (vtx->hdr.chiptype == AYEMU_AY)? "AY" : "YM" );
-	break;
-      case 'F':
-	append_number(buf, sz, vtx->hdr.chipFreq);
-	break;
-      case 'P':
-	append_number(buf, sz, vtx->hdr.playerFreq);
-	break;
-      default:
-	append_char(buf, sz, *fmt);
-      }
-      fmt++;
-    } else {
-      append_char(buf, sz, *fmt++);
-    }
-  }
-}
-
-/** Free all of allocaded resource for this file.
- *
- * Free the unpacket register data if is and close file.
- */
-void ayemu_vtx_free (ayemu_vtx_t *vtx)
-{
-  if (vtx->fp) {
-    vfs_fclose(vtx->fp);
-    vtx->fp = NULL;
-  }
-
-  if (vtx->regdata) {
-    free(vtx->regdata);
-    vtx->regdata = NULL;
-  }
-}
diff --git a/src/vtx/vtxfile.cc b/src/vtx/vtxfile.cc
new file mode 100644
index 000000000000..ccf95d563a38
--- /dev/null
+++ b/src/vtx/vtxfile.cc
@@ -0,0 +1,229 @@
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/runtime.h>
+
+#include "ayemu.h"
+#include "vtx.h"
+
+/* Read 8-bit integer from file.
+ * Return 1 if error occurs
+ */
+static int read_byte(VFSFile &fp, int *p)
+{
+  unsigned char c;
+  if (fp.fread(&c, 1, 1) != 1) {
+    AUDERR("read_byte() error\n");
+    return 1;
+  }
+  *p = c;
+  return 0;
+}
+
+/* Read 16-bit integer from file.
+ * Return 1 if error occurs
+ */
+static int read_word16(VFSFile &fp, int *p)
+{
+  unsigned char c[2];
+  if (fp.fread(&c, 1, 2) != 2) {
+    AUDERR("read_word16() error\n");
+    return 1;
+  }
+  *p = c[0] | (c[1] << 8);
+  return 0;
+}
+
+/* read 32-bit integer from file.
+ *  Returns 1 if error occurs
+ */
+static int read_word32(VFSFile &fp, int32_t *p)
+{
+  unsigned char c[4];
+  if (fp.fread(&c, 1, 4) != 4) {
+    AUDERR("read_word32() error\n");
+    return 1;
+  }
+  *p = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+  return 0;
+}
+
+/* read_NTstring: reads null-terminated string from file.
+ *  Return 1 if error occures.
+ */
+static int read_NTstring(VFSFile &fp, char s[])
+{
+  int i, n = 0;
+  unsigned char c;
+  for (i = 0 ; i < AYEMU_VTX_NTSTRING_MAX && (n = fp.fread(&c, 1, 1)) == 1 && c ; i++)
+    s[i] = c;
+  s[i] = '\0';
+  if (n != 1) {
+    AUDERR("unexpected end of file!\n");
+    return 1;
+  }
+  return 0;
+}
+
+/** Open specified .vtx file and read vtx file header
+ *
+ *  Open specified .vtx file and read vtx file header in struct vtx
+ *  Return value: true if success, else false
+ */
+bool ayemu_vtx_t::read_header(VFSFile &file)
+{
+  char buf[2];
+  int error = 0;
+  int32_t int_regdata_size;
+
+  if (file.fread(buf, 2, 1) != 1) {
+    AUDERR("Can't read from %s\n", file.filename());
+    error = 1;
+  }
+
+  if (!strcmp_nocase(buf, "ay", 2))
+    hdr.chiptype = AYEMU_AY;
+  else if (!strcmp_nocase(buf, "ym", 2))
+    hdr.chiptype = AYEMU_YM;
+  else {
+    AUDERR("File %s is _not_ VORTEX format!\nIt not begins from AY or YM.\n", file.filename());
+    error = 1;
+  }
+
+  /* read VTX header info in order format specified, see http:// ..... */
+  if (!error) error = read_byte(file, &hdr.stereo);
+  if (!error) error = read_word16(file, &hdr.loop);
+  if (!error) error = read_word32(file, &hdr.chipFreq);
+  if (!error) error = read_byte(file, &hdr.playerFreq);
+  if (!error) error = read_word16(file, &hdr.year);
+  if (!error) {
+    error = read_word32(file, &int_regdata_size);
+    hdr.regdata_size = int_regdata_size;
+  }
+
+  if (!error) error = read_NTstring(file, hdr.title);
+  if (!error) error = read_NTstring(file, hdr.author);
+  if (!error) error = read_NTstring(file, hdr.from);
+  if (!error) error = read_NTstring(file, hdr.tracker);
+  if (!error) error = read_NTstring(file, hdr.comment);
+
+  return !error;
+}
+
+/** Read and encode lha data from .vtx file
+ *
+ * Return value: pointer to unpacked data or nullptr
+ * Note: you must call ayemu_vtx_open() first.
+ */
+bool ayemu_vtx_t::load_data(VFSFile &file)
+{
+  /* read packed AY register data to end of file. */
+  Index<char> packed_data = file.read_all();
+
+  regdata.resize(hdr.regdata_size);
+  if (!lh5_decode(packed_data, regdata))
+    return false;
+
+  pos = 0;
+  return true;
+}
+
+/** Get next 14-bytes frame of AY register data.
+ *
+ * Return value: true if success, false if not enough data.
+ */
+bool ayemu_vtx_t::get_next_frame(unsigned char *regs)
+{
+  int numframes = hdr.regdata_size / 14;
+  if (pos++ >= numframes)
+    return 0;
+  else {
+    int n;
+    unsigned char *p = &regdata[pos];
+    for(n = 0 ; n < 14 ; n++, p+=numframes)
+      regs[n] = *p;
+    return 1;
+  }
+}
+
+/** Print formatted file name. If fmt is nullptr the default format %a - %t will be used
+ *
+ * %% the % sign
+ * %a author of song
+ * %t song title
+ * %y year
+ * %f song from
+ * %T Tracker
+ * %C Comment
+ * %s stereo type (ABC, BCA, ...)
+ * %l 'looped' or 'non-looped'
+ * %c chip type: 'AY' or 'YM'
+ * %F chip Freq
+ * %P player freq
+ */
+StringBuf ayemu_vtx_t::sprintname (const char *fmt)
+{
+  static const char *stereo_types[] = { "MONO", "ABC", "ACB", "BAC", "BCA", "CAB", "CBA" };
+
+  if (!fmt)
+    fmt = "%a - %t";
+
+  StringBuf buf(0);
+
+  while (*fmt) {
+    if (*fmt == '%') {
+      switch(*++fmt) {
+      case 'a':
+        buf.insert(-1, hdr.author);
+        break;
+      case 't':
+        buf.insert(-1, hdr.title);
+        break;
+      case 'y':
+        buf.combine(int_to_str(hdr.year));
+        break;
+      case 'f':
+        buf.insert(-1, hdr.from);
+        break;
+      case 'T':
+        buf.insert(-1, hdr.tracker);
+        break;
+      case 'C':
+        buf.insert(-1, hdr.comment);
+        break;
+      case 's':
+        buf.insert(-1, stereo_types[hdr.stereo]);
+        break;
+      case 'l':
+        buf.insert(-1, (hdr.loop)? "looped" : "non-looped" );
+        break;
+      case 'c':
+        buf.insert(-1, (hdr.chiptype == AYEMU_AY)? "AY" : "YM" );
+        break;
+      case 'F':
+        buf.combine(int_to_str(hdr.chipFreq));
+        break;
+      case 'P':
+        buf.combine(int_to_str(hdr.playerFreq));
+        break;
+      default:
+        buf.insert(-1, fmt, 1);
+      }
+      fmt++;
+    } else {
+      const char *p = strchr(fmt, '%');
+      if (!p)
+        p = fmt + strlen(fmt);
+
+      buf.insert(-1, fmt, p - fmt);
+      fmt = p;
+    }
+  }
+
+  return buf;
+}
diff --git a/src/wavpack/Makefile b/src/wavpack/Makefile
index 56928003d11a..358f41178cc4 100644
--- a/src/wavpack/Makefile
+++ b/src/wavpack/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = wavpack${PLUGIN_SUFFIX}
 
-SRCS = wavpack.c
+SRCS = wavpack.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${WAVPACK_CFLAGS} -I../..
-LIBS += ${GLIB_LIBS} ${WAVPACK_LIBS} -laudtag
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${WAVPACK_CFLAGS} -I../..
+LIBS += ${WAVPACK_LIBS} -laudtag
diff --git a/src/wavpack/wavpack.c b/src/wavpack/wavpack.c
deleted file mode 100644
index b0130165430a..000000000000
--- a/src/wavpack/wavpack.c
+++ /dev/null
@@ -1,279 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include <wavpack/wavpack.h>
-
-#include <audacious/audtag.h>
-#include <audacious/debug.h>
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#define BUFFER_SIZE 256 /* read buffer size, in samples / frames */
-#define SAMPLE_SIZE(a) (a == 8 ? sizeof(uint8_t) : (a == 16 ? sizeof(uint16_t) : sizeof(uint32_t)))
-#define SAMPLE_FMT(a) (a == 8 ? FMT_S8 : (a == 16 ? FMT_S16_NE : (a == 24 ? FMT_S24_NE : FMT_S32_NE)))
-
-
-/* Audacious VFS wrappers for Wavpack stream reading
- */
-
-static int32_t
-wv_read_bytes(void *id, void *data, int32_t bcount)
-{
-    return vfs_fread(data, 1, bcount, (VFSFile *) id);
-}
-
-static uint32_t
-wv_get_pos(void *id)
-{
-    return vfs_ftell((VFSFile *) id);
-}
-
-static int
-wv_set_pos_abs(void *id, uint32_t pos)
-{
-    return vfs_fseek((VFSFile *) id, pos, SEEK_SET);
-}
-
-static int
-wv_set_pos_rel(void *id, int32_t delta, int mode)
-{
-    return vfs_fseek((VFSFile *) id, delta, mode);
-}
-
-static int
-wv_push_back_byte(void *id, int c)
-{
-    return vfs_ungetc(c, (VFSFile *) id);
-}
-
-static uint32_t
-wv_get_length(void *id)
-{
-    VFSFile *file = (VFSFile *) id;
-
-    if (file == NULL)
-        return 0;
-
-    return vfs_fsize(file);
-}
-
-static int wv_can_seek(void *id)
-{
-    return (vfs_is_streaming((VFSFile *) id) == FALSE);
-}
-
-static int32_t wv_write_bytes(void *id, void *data, int32_t bcount)
-{
-    return vfs_fwrite(data, 1, bcount, (VFSFile *) id);
-}
-
-WavpackStreamReader wv_readers = {
-    wv_read_bytes,
-    wv_get_pos,
-    wv_set_pos_abs,
-    wv_set_pos_rel,
-    wv_push_back_byte,
-    wv_get_length,
-    wv_can_seek,
-    wv_write_bytes
-};
-
-static bool_t wv_attach (const char * filename, VFSFile * wv_input,
- VFSFile * * wvc_input, WavpackContext * * ctx, char * error, int flags)
-{
-    if (flags & OPEN_WVC)
-    {
-        SPRINTF (corrFilename, "%sc", filename);
-        if (vfs_file_test (corrFilename, VFS_IS_REGULAR))
-            * wvc_input = vfs_fopen (corrFilename, "r");
-        else
-            * wvc_input = NULL;
-    }
-
-    * ctx = WavpackOpenFileInputEx (& wv_readers, wv_input, * wvc_input, error, flags, 0);
-    return (* ctx != NULL);
-}
-
-static void wv_deattach (VFSFile * wvc_input, WavpackContext * ctx)
-{
-    if (wvc_input != NULL)
-        vfs_fclose(wvc_input);
-    WavpackCloseFile(ctx);
-}
-
-static bool_t wv_play (const char * filename, VFSFile * file)
-{
-    if (file == NULL)
-        return FALSE;
-
-    int32_t *input = NULL;
-    void *output = NULL;
-    int sample_rate, num_channels, bits_per_sample;
-    unsigned num_samples;
-    WavpackContext *ctx = NULL;
-    VFSFile *wvc_input = NULL;
-    bool_t error = FALSE;
-
-    if (! wv_attach (filename, file, & wvc_input, & ctx, NULL, OPEN_TAGS |
-     OPEN_WVC))
-    {
-        fprintf (stderr, "Error opening Wavpack file '%s'.", filename);
-        error = TRUE;
-        goto error_exit;
-    }
-
-    sample_rate = WavpackGetSampleRate(ctx);
-    num_channels = WavpackGetNumChannels(ctx);
-    bits_per_sample = WavpackGetBitsPerSample(ctx);
-    num_samples = WavpackGetNumSamples(ctx);
-
-    if (!aud_input_open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels))
-    {
-        fprintf (stderr, "Error opening audio output.");
-        error = TRUE;
-        goto error_exit;
-    }
-
-    input = g_new(int32_t, BUFFER_SIZE * num_channels);
-    output = g_malloc(BUFFER_SIZE * num_channels * SAMPLE_SIZE(bits_per_sample));
-    if (input == NULL || output == NULL)
-        goto error_exit;
-
-    aud_input_set_bitrate(WavpackGetAverageBitrate(ctx, num_channels));
-
-    while (! aud_input_check_stop ())
-    {
-        int seek_value = aud_input_check_seek ();
-        if (seek_value >= 0)
-            WavpackSeekSample (ctx, (int64_t) seek_value * sample_rate / 1000);
-
-        /* Decode audio data */
-        unsigned samples_left = num_samples - WavpackGetSampleIndex(ctx);
-
-        if (samples_left == 0)
-            break;
-
-        int ret = WavpackUnpackSamples(ctx, input, BUFFER_SIZE);
-
-        if (ret < 0)
-        {
-            fprintf (stderr, "Error decoding file.\n");
-            break;
-        }
-        else
-        {
-            /* Perform audio data conversion and output */
-            unsigned i;
-            int32_t *rp = input;
-            int8_t *wp = output;
-            int16_t *wp2 = output;
-            int32_t *wp4 = output;
-
-            if (bits_per_sample == 8)
-            {
-                for (i = 0; i < ret * num_channels; i++, wp++, rp++)
-                    *wp = *rp & 0xff;
-            }
-            else if (bits_per_sample == 16)
-            {
-                for (i = 0; i < ret * num_channels; i++, wp2++, rp++)
-                    *wp2 = *rp & 0xffff;
-            }
-            else if (bits_per_sample == 24 || bits_per_sample == 32)
-            {
-                for (i = 0; i < ret * num_channels; i++, wp4++, rp++)
-                    *wp4 = *rp;
-            }
-
-            aud_input_write_audio(output, ret * num_channels * SAMPLE_SIZE(bits_per_sample));
-        }
-    }
-
-error_exit:
-
-    g_free(input);
-    g_free(output);
-    wv_deattach (wvc_input, ctx);
-
-    return ! error;
-}
-
-static char *
-wv_get_quality(WavpackContext *ctx)
-{
-    int mode = WavpackGetMode(ctx);
-    const char *quality;
-
-    if (mode & MODE_LOSSLESS)
-        quality = _("lossless");
-    else if (mode & MODE_HYBRID)
-        quality = _("lossy (hybrid)");
-    else
-        quality = _("lossy");
-
-    return str_printf ("%s%s%s", quality,
-        (mode & MODE_WVC) ? " (wvc corrected)" : "",
-#ifdef MODE_DNS /* WavPack 4.50 or later */
-        (mode & MODE_DNS) ? " (dynamic noise shaped)" :
-#endif
-        "");
-}
-
-static Tuple *
-wv_probe_for_tuple(const char * filename, VFSFile * fd)
-{
-    WavpackContext *ctx;
-    Tuple *tu;
-    char error[1024];
-
-    ctx = WavpackOpenFileInputEx(&wv_readers, fd, NULL, error, OPEN_TAGS, 0);
-
-    if (ctx == NULL)
-        return NULL;
-
-    AUDDBG("starting probe of %p\n", (void *) fd);
-
-    tu = tuple_new_from_filename(filename);
-
-    tuple_set_int(tu, FIELD_LENGTH,
-        ((uint64_t) WavpackGetNumSamples(ctx) * 1000) / (uint64_t) WavpackGetSampleRate(ctx));
-    tuple_set_str(tu, FIELD_CODEC, "WavPack");
-
-    char * quality = wv_get_quality (ctx);
-    tuple_set_str (tu, FIELD_QUALITY, quality);
-    str_unref (quality);
-
-    WavpackCloseFile(ctx);
-
-    if (! vfs_fseek (fd, 0, SEEK_SET))
-        tag_tuple_read (tu, fd);
-
-    AUDDBG("returning tuple %p for file %p\n", (void *) tu, (void *) fd);
-    return tu;
-}
-
-static bool_t wv_write_tag (const char * filename, VFSFile * handle, const Tuple * tuple)
-{
-    return tag_tuple_write(tuple, handle, TAG_TYPE_APE);
-}
-
-static const char wv_about[] =
- N_("Copyright 2006 William Pitcock <nenolod at nenolod.net>\n\n"
-    "Some of the plugin code was by Miles Egan.");
-
-static const char *wv_fmts[] = { "wv", NULL };
-
-AUD_INPUT_PLUGIN
-(
-    .name = N_("WavPack Decoder"),
-    .domain = PACKAGE,
-    .about_text = wv_about,
-    .play = wv_play,
-    .extensions = wv_fmts,
-    .probe_for_tuple = wv_probe_for_tuple,
-    .update_song_tuple = wv_write_tag,
-)
diff --git a/src/wavpack/wavpack.cc b/src/wavpack/wavpack.cc
new file mode 100644
index 000000000000..f726702f6484
--- /dev/null
+++ b/src/wavpack/wavpack.cc
@@ -0,0 +1,258 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <wavpack/wavpack.h>
+
+#define WANT_VFS_STDIO_COMPAT
+#include <audacious/audtag.h>
+#include <libaudcore/runtime.h>
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+
+#define BUFFER_SIZE 256 /* read buffer size, in samples / frames */
+#define SAMPLE_SIZE(a) (a == 8 ? sizeof(uint8_t) : (a == 16 ? sizeof(uint16_t) : sizeof(uint32_t)))
+#define SAMPLE_FMT(a) (a == 8 ? FMT_S8 : (a == 16 ? FMT_S16_NE : (a == 24 ? FMT_S24_NE : FMT_S32_NE)))
+
+class WavpackPlugin : public InputPlugin
+{
+public:
+    static const char about[];
+    static const char * const exts[];
+
+    static constexpr PluginInfo info = {
+        N_("WavPack Decoder"),
+        PACKAGE,
+        about
+    };
+
+    static constexpr auto iinfo = InputInfo (FlagWritesTag)
+        .with_exts (exts);
+
+    constexpr WavpackPlugin() : InputPlugin (info, iinfo) {}
+
+    bool is_our_file (const char * filename, VFSFile & file)
+        { return false; }
+
+    Tuple read_tuple (const char * filename, VFSFile & file);
+    bool write_tuple (const char * filename, VFSFile & file, const Tuple & tuple);
+    bool play (const char * filename, VFSFile & file);
+};
+
+EXPORT WavpackPlugin aud_plugin_instance;
+
+/* Audacious VFS wrappers for Wavpack stream reading
+ */
+
+static int32_t
+wv_read_bytes(void *id, void *data, int32_t bcount)
+{
+    return ((VFSFile *) id)->fread (data, 1, bcount);
+}
+
+static uint32_t
+wv_get_pos(void *id)
+{
+    return aud::clamp (((VFSFile *) id)->ftell (), (int64_t) 0, (int64_t) 0xffffffff);
+}
+
+static int
+wv_set_pos_abs(void *id, uint32_t pos)
+{
+    return ((VFSFile *) id)->fseek (pos, VFS_SEEK_SET);
+}
+
+static int
+wv_set_pos_rel(void *id, int32_t delta, int mode)
+{
+    return ((VFSFile *) id)->fseek (delta, to_vfs_seek_type(mode));
+}
+
+static int
+wv_push_back_byte(void *id, int c)
+{
+    return (((VFSFile *) id)->fseek (-1, VFS_SEEK_CUR) == 0) ? c : -1;
+}
+
+static uint32_t
+wv_get_length(void *id)
+{
+    return aud::clamp (((VFSFile *) id)->fsize (), (int64_t) 0, (int64_t) 0xffffffff);
+}
+
+static int wv_can_seek(void *id)
+{
+    return (((VFSFile *) id)->fsize () >= 0);
+}
+
+static int32_t wv_write_bytes(void *id, void *data, int32_t bcount)
+{
+    return ((VFSFile *) id)->fwrite (data, 1, bcount);
+}
+
+WavpackStreamReader wv_readers = {
+    wv_read_bytes,
+    wv_get_pos,
+    wv_set_pos_abs,
+    wv_set_pos_rel,
+    wv_push_back_byte,
+    wv_get_length,
+    wv_can_seek,
+    wv_write_bytes
+};
+
+static bool wv_attach (const char * filename, VFSFile & wv_input,
+ VFSFile & wvc_input, WavpackContext * * ctx, char * error, int flags)
+{
+    if (flags & OPEN_WVC)
+    {
+        StringBuf corrFilename = str_concat ({filename, "c"});
+        if (VFSFile::test_file (corrFilename, VFS_IS_REGULAR))
+            wvc_input = VFSFile (corrFilename, "r");
+    }
+
+    * ctx = WavpackOpenFileInputEx (& wv_readers, & wv_input, & wvc_input, error, flags, 0);
+    return (* ctx != nullptr);
+}
+
+static void wv_deattach (WavpackContext * ctx)
+{
+    WavpackCloseFile(ctx);
+}
+
+bool WavpackPlugin::play (const char * filename, VFSFile & file)
+{
+    int sample_rate, num_channels, bits_per_sample;
+    unsigned num_samples;
+    WavpackContext *ctx = nullptr;
+    VFSFile wvc_input;
+
+    if (! wv_attach (filename, file, wvc_input, & ctx, nullptr, OPEN_TAGS | OPEN_WVC))
+    {
+        AUDERR ("Error opening Wavpack file '%s'.", filename);
+        return false;
+    }
+
+    sample_rate = WavpackGetSampleRate(ctx);
+    num_channels = WavpackGetNumChannels(ctx);
+    bits_per_sample = WavpackGetBitsPerSample(ctx);
+    num_samples = WavpackGetNumSamples(ctx);
+
+    set_stream_bitrate(WavpackGetAverageBitrate(ctx, num_channels));
+    open_audio(SAMPLE_FMT(bits_per_sample), sample_rate, num_channels);
+
+    Index<int32_t> input;
+    input.resize (BUFFER_SIZE * num_channels);
+
+    Index<char> output;
+    output.resize (BUFFER_SIZE * num_channels * SAMPLE_SIZE (bits_per_sample));
+
+    while (! check_stop ())
+    {
+        int seek_value = check_seek ();
+        if (seek_value >= 0)
+            WavpackSeekSample (ctx, (int64_t) seek_value * sample_rate / 1000);
+
+        /* Decode audio data */
+        unsigned samples_left = num_samples - WavpackGetSampleIndex(ctx);
+
+        if (samples_left == 0)
+            break;
+
+        int ret = WavpackUnpackSamples (ctx, input.begin (), BUFFER_SIZE);
+
+        if (ret < 0)
+        {
+            AUDERR ("Error decoding file.\n");
+            break;
+        }
+        else
+        {
+            /* Perform audio data conversion and output */
+            int32_t * rp = input.begin ();
+            int8_t * wp = (int8_t *) output.begin ();
+            int16_t * wp2 = (int16_t *) output.begin ();
+            int32_t * wp4 = (int32_t *) output.begin ();
+
+            if (bits_per_sample == 8)
+            {
+                for (int i = 0; i < ret * num_channels; i++, wp++, rp++)
+                    *wp = *rp & 0xff;
+            }
+            else if (bits_per_sample == 16)
+            {
+                for (int i = 0; i < ret * num_channels; i++, wp2++, rp++)
+                    *wp2 = *rp & 0xffff;
+            }
+            else if (bits_per_sample == 24 || bits_per_sample == 32)
+            {
+                for (int i = 0; i < ret * num_channels; i++, wp4++, rp++)
+                    *wp4 = *rp;
+            }
+
+            write_audio (output.begin (),
+             ret * num_channels * SAMPLE_SIZE (bits_per_sample));
+        }
+    }
+
+    wv_deattach (ctx);
+    return true;
+}
+
+static StringBuf
+wv_get_quality(WavpackContext *ctx)
+{
+    int mode = WavpackGetMode(ctx);
+    const char *quality;
+
+    if (mode & MODE_LOSSLESS)
+        quality = _("lossless");
+    else if (mode & MODE_HYBRID)
+        quality = _("lossy (hybrid)");
+    else
+        quality = _("lossy");
+
+    return str_concat ({quality, (mode & MODE_WVC) ? " (wvc corrected)" : "",
+     (mode & MODE_DNS) ? " (dynamic noise shaped)" : ""});
+}
+
+Tuple WavpackPlugin::read_tuple (const char * filename, VFSFile & file)
+{
+    WavpackContext *ctx;
+    Tuple tuple;
+    char error[1024];
+
+    ctx = WavpackOpenFileInputEx(&wv_readers, &file, nullptr, error, OPEN_TAGS, 0);
+
+    if (ctx == nullptr)
+        return tuple;
+
+    AUDDBG("starting probe of %s\n", file.filename ());
+
+    tuple.set_filename (filename);
+
+    tuple.set_int (Tuple::Length,
+        ((uint64_t) WavpackGetNumSamples(ctx) * 1000) / (uint64_t) WavpackGetSampleRate(ctx));
+    tuple.set_str (Tuple::Codec, "WavPack");
+
+    tuple.set_str (Tuple::Quality, wv_get_quality (ctx));
+
+    WavpackCloseFile(ctx);
+
+    if (! file.fseek (0, VFS_SEEK_SET))
+        audtag::tuple_read (tuple, file);
+
+    AUDDBG("returning tuple for file %s\n", file.filename ());
+    return tuple;
+}
+
+bool WavpackPlugin::write_tuple (const char * filename, VFSFile & handle, const Tuple & tuple)
+{
+    return audtag::tuple_write(tuple, handle, audtag::TagType::APE);
+}
+
+const char WavpackPlugin::about[] =
+ N_("Copyright 2006 William Pitcock <nenolod at nenolod.net>\n\n"
+    "Some of the plugin code was by Miles Egan.");
+
+const char * const WavpackPlugin::exts[] = { "wv", nullptr };
diff --git a/src/xsf/Makefile b/src/xsf/Makefile
index a09708296df7..60b552370509 100644
--- a/src/xsf/Makefile
+++ b/src/xsf/Makefile
@@ -1,16 +1,18 @@
 PLUGIN = xsf${PLUGIN_SUFFIX}
 
-SRCS = corlett.c \
-       plugin.c \
-       vio2sf.c \
-       desmume/armcpu.c            desmume/bios.c  desmume/FIFO.c  desmume/matrix.c  desmume/MMU.c        desmume/SPU.c \
-       desmume/arm_instructions.c  desmume/cp15.c  desmume/GPU.c   desmume/mc.c      desmume/NDSSystem.c  desmume/thumb_instructions.c \
+SRCS = corlett.cc \
+       plugin.cc \
+       vio2sf.cc \
+       desmume/armcpu.cc            desmume/bios.cc  desmume/FIFO.cc  desmume/matrix.cc  desmume/MMU.cc        desmume/SPU.cc \
+       desmume/arm_instructions.cc  desmume/cp15.cc  desmume/GPU.cc   desmume/mc.cc      desmume/NDSSystem.cc  desmume/thumb_instructions.cc \
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${INPUT_PLUGIN_DIR}
 
-CFLAGS += ${PLUGIN_CFLAGS} -O0
-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} -I../.. -Ispu/
-LIBS += -lm -lz ${GLIB_LIBS}
+LD = ${CXX}
+
+CXXFLAGS += ${PLUGIN_CFLAGS} -Wno-sign-compare
+CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. -Ispu/
+LIBS += -lm -lz
diff --git a/src/xsf/corlett.c b/src/xsf/corlett.c
deleted file mode 100644
index 50ee0763e66f..000000000000
--- a/src/xsf/corlett.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
-
-	Audio Overload SDK
-
-	Copyright (c) 2007-2008, R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-// corlett.c
-
-// Decodes file format designed by Neill Corlett (PSF, QSF, ...)
-
-/*
- - First 3 bytes: ASCII signature: "PSF" (case sensitive)
-
-- Next 1 byte: Version byte
-  The version byte is used to determine the type of PSF file.  It does NOT
-  affect the basic structure of the file in any way.
-
-  Currently accepted version bytes are:
-    0x01: Playstation (PSF1)
-    0x02: Playstation 2 (PSF2)
-    0x11: Saturn (SSF) [TENTATIVE]
-    0x12: Dreamcast (DSF) [TENTATIVE]
-    0x21: Nintendo 64 (USF) [RESERVED]
-    0x41: Capcom QSound (QSF)
-
-- Next 4 bytes: Size of reserved area (R), little-endian unsigned long
-
-- Next 4 bytes: Compressed program length (N), little-endian unsigned long
-  This is the length of the program data _after_ compression.
-
-- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long
-  This is the CRC-32 of the program data _after_ compression.  Filling in
-  this value is mandatory, as a PSF file may be regarded as corrupt if it
-  does not match.
-
-- Next R bytes: Reserved area.
-  May be empty if R is 0 bytes.
-
-- Next N bytes: Compressed program, in zlib compress() format.
-  May be empty if N is 0 bytes.
-
-The following data is optional and may be omitted:
-
-- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive)
-  If these 5 bytes do not match, then the remainder of the file may be
-  regarded as invalid and discarded.
-
-- Remainder of file: Uncompressed ASCII tag data.
-*/
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <glib.h>
-#include <zlib.h>
-
-#include "ao.h"
-#include "corlett.h"
-
-#define LE32(x) GUINT32_FROM_LE(x)
-
-#define DECOMP_MAX_SIZE		((32 * 1024 * 1024) + 12)
-
-int corlett_decode(uint8_t *input, uint32_t input_len, uint8_t **output, uint64_t *size, corlett_t **c)
-{
-	uint32_t *buf;
-	uint32_t res_area, comp_crc,  actual_crc;
-	uint8_t *decomp_dat, *tag_dec;
-	uLongf decomp_length, comp_length;
-
-	// 32-bit pointer to data
-	buf = (uint32_t *)input;
-
-	// Check we have a PSF format file.
-	if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F'))
-	{
-		return AO_FAIL;
-	}
-
-	// Get our values
-	res_area = LE32(buf[1]);
-	comp_length = LE32(buf[2]);
-	comp_crc = LE32(buf[3]);
-
-	if (comp_length > 0)
-	{
-		// Check length
-		if (input_len < comp_length + 16)
-			return AO_FAIL;
-
-		// Check CRC is correct
-		actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length);
-		if (actual_crc != comp_crc)
-			return AO_FAIL;
-
-		// Decompress data if any
-		decomp_dat = malloc(DECOMP_MAX_SIZE);
-		decomp_length = DECOMP_MAX_SIZE;
-		if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK)
-		{
-			free(decomp_dat);
-			return AO_FAIL;
-		}
-
-		// Resize memory buffer to what we actually need
-		decomp_dat = realloc(decomp_dat, (size_t)decomp_length + 1);
-	}
-	else
-	{
-		decomp_dat = NULL;
-		decomp_length =  0;
-	}
-
-	// Make structure
-	*c = malloc(sizeof(corlett_t));
-	if (!(*c))
-	{
-		free(decomp_dat);
-		return AO_FAIL;
-	}
-	memset(*c, 0, sizeof(corlett_t));
-	strcpy((*c)->inf_title, "n/a");
-	strcpy((*c)->inf_copy, "n/a");
-	strcpy((*c)->inf_artist, "n/a");
-	strcpy((*c)->inf_game, "n/a");
-	strcpy((*c)->inf_year, "n/a");
-	strcpy((*c)->inf_length, "n/a");
-	strcpy((*c)->inf_fade, "n/a");
-
-	// set reserved section pointer
-	(*c)->res_section = &buf[4];
-	(*c)->res_size = res_area;
-
-	// Return it
-	if (output != NULL && size != NULL)
-	{
-		*output = decomp_dat;
-		*size = decomp_length;
-	}
-	else
-		free(decomp_dat);
-
-	// Next check for tags
-	input_len -= (comp_length + 16 + res_area);
-	if (input_len < 5)
-		return AO_SUCCESS;
-
-//	printf("\n\nNew corlett: input len %d comp length %d res area %d\n", input_len, comp_length, res_area);
-
-	tag_dec = input + (comp_length + res_area + 16);
-	if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']'))
-	{
-		int l, num_tags, data;
-
-		// Tags found!
-		tag_dec += 5;
-		input_len -= 5;
-
-		data = FALSE;
-		num_tags = 0;
-		l = 0;
-		while (input_len && (num_tags < MAX_UNKNOWN_TAGS))
-		{
-			if (data)
-			{
-				if ((*tag_dec == 0xA) || (*tag_dec == 0x00))
-				{
-					(*c)->tag_data[num_tags][l] = 0;
-					data = FALSE;
-					num_tags++;
-					l = 0;
-				}
-				else
-				{
-					(*c)->tag_data[num_tags][l++] = *tag_dec;
-				}
-			}
-			else
-			{
-				if (*tag_dec == '=')
-				{
-					(*c)->tag_name[num_tags][l] = 0;
-					l = 0;
-					data = TRUE;
-				}
-				else
-				{
-					(*c)->tag_name[num_tags][l++] = *tag_dec;
-				}
-			}
-
-			tag_dec++;
-			input_len--;
-		}
-
-
-		// Now, process that tag array into what we expect
-		for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++)
-		{
-			// See if tag belongs in one of the special fields we have
-			if (!g_ascii_strcasecmp((*c)->tag_name[num_tags], "_lib"))
-			{
-				strcpy((*c)->lib, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5))
-			{
-				strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5))
-			{
-				strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5))
-			{
-				strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5))
-			{
-				strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5))
-			{
-				strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5))
-			{
-				strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5))
-			{
-				strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5))
-			{
-				strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8))
-			{
-				strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "title", 5))
-			{
-				strcpy((*c)->inf_title, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9))
-			{
-				strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "artist", 6))
-			{
-				strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "game", 4))
-			{
-				strcpy((*c)->inf_game, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "year", 4))
-			{
-				strcpy((*c)->inf_year, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "length", 6))
-			{
-				strcpy((*c)->inf_length, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-			else if (!strncmp((*c)->tag_name[num_tags], "fade", 4))
-			{
-				strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]);
-				(*c)->tag_data[num_tags][0] = 0;
-				(*c)->tag_name[num_tags][0] = 0;
-			}
-		}
-	}
-
-	// Bingo
-	return AO_SUCCESS;
-}
-
-uint32_t psfTimeToMS(char *str)
-{
-	int x, c=0;
-	uint32_t acc=0;
-	char s[100];
-
-	strncpy(s,str,100);
-	s[99]=0;
-
-	for (x=strlen(s); x>=0; x--)
-	{
-		if (s[x]=='.' || s[x]==',')
-		{
-			acc=atoi(s+x+1);
-			s[x]=0;
-		}
-		else if (s[x]==':')
-		{
-			if(c==0)
-			{
-				acc+=atoi(s+x+1)*10;
-			}
-			else if(c==1)
-			{
-				acc+=atoi(s+x+(x?1:0))*10*60;
-			}
-
-			c++;
-			s[x]=0;
-		}
-		else if (x==0)
-		{
-			if(c==0)
-			{
-				acc+=atoi(s+x)*10;
-			}
-			else if(c==1)
-			{
-				acc+=atoi(s+x)*10*60;
-			}
-			else if(c==2)
-			{
-				acc+=atoi(s+x)*10*60*60;
-			}
-		}
-	}
-
-	acc*=100;
-	return(acc);
-}
-
diff --git a/src/xsf/corlett.cc b/src/xsf/corlett.cc
new file mode 100644
index 000000000000..a7694d5ecdda
--- /dev/null
+++ b/src/xsf/corlett.cc
@@ -0,0 +1,385 @@
+/*
+
+	Audio Overload SDK
+
+	Copyright (c) 2007-2008, R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// corlett.c
+
+// Decodes file format designed by Neill Corlett (PSF, QSF, ...)
+
+/*
+ - First 3 bytes: ASCII signature: "PSF" (case sensitive)
+
+- Next 1 byte: Version byte
+  The version byte is used to determine the type of PSF file.  It does NOT
+  affect the basic structure of the file in any way.
+
+  Currently accepted version bytes are:
+    0x01: Playstation (PSF1)
+    0x02: Playstation 2 (PSF2)
+    0x11: Saturn (SSF) [TENTATIVE]
+    0x12: Dreamcast (DSF) [TENTATIVE]
+    0x21: Nintendo 64 (USF) [RESERVED]
+    0x41: Capcom QSound (QSF)
+
+- Next 4 bytes: Size of reserved area (R), little-endian unsigned long
+
+- Next 4 bytes: Compressed program length (N), little-endian unsigned long
+  This is the length of the program data _after_ compression.
+
+- Next 4 bytes: Compressed program CRC-32, little-endian unsigned long
+  This is the CRC-32 of the program data _after_ compression.  Filling in
+  this value is mandatory, as a PSF file may be regarded as corrupt if it
+  does not match.
+
+- Next R bytes: Reserved area.
+  May be empty if R is 0 bytes.
+
+- Next N bytes: Compressed program, in zlib compress() format.
+  May be empty if N is 0 bytes.
+
+The following data is optional and may be omitted:
+
+- Next 5 bytes: ASCII signature: "[TAG]" (case sensitive)
+  If these 5 bytes do not match, then the remainder of the file may be
+  regarded as invalid and discarded.
+
+- Remainder of file: Uncompressed ASCII tag data.
+*/
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <zlib.h>
+
+#define WANT_AUD_BSWAP
+#include <libaudcore/audio.h>
+#include <libaudcore/audstrings.h>
+
+#include "ao.h"
+#include "corlett.h"
+
+#define LE32(x) FROM_LE32(x)
+
+#define DECOMP_MAX_SIZE		((32 * 1024 * 1024) + 12)
+
+int corlett_decode(uint8_t *input, uint32_t input_len, uint8_t **output, uint64_t *size, corlett_t **c)
+{
+	uint32_t *buf;
+	uint32_t res_area, comp_crc,  actual_crc;
+	uint8_t *decomp_dat, *tag_dec;
+	uLongf decomp_length, comp_length;
+
+	// 32-bit pointer to data
+	buf = (uint32_t *)input;
+
+	// Check we have a PSF format file.
+	if ((input[0] != 'P') || (input[1] != 'S') || (input[2] != 'F'))
+	{
+		return AO_FAIL;
+	}
+
+	// Get our values
+	res_area = LE32(buf[1]);
+	comp_length = LE32(buf[2]);
+	comp_crc = LE32(buf[3]);
+
+	if (comp_length > 0)
+	{
+		// Check length
+		if (input_len < comp_length + 16)
+			return AO_FAIL;
+
+		// Check CRC is correct
+		actual_crc = crc32(0, (unsigned char *)&buf[4+(res_area/4)], comp_length);
+		if (actual_crc != comp_crc)
+			return AO_FAIL;
+
+		// Decompress data if any
+		decomp_dat = (uint8_t *) malloc(DECOMP_MAX_SIZE);
+		decomp_length = DECOMP_MAX_SIZE;
+		if (uncompress(decomp_dat, &decomp_length, (unsigned char *)&buf[4+(res_area/4)], comp_length) != Z_OK)
+		{
+			free(decomp_dat);
+			return AO_FAIL;
+		}
+
+		// Resize memory buffer to what we actually need
+		decomp_dat = (uint8_t *) realloc(decomp_dat, (size_t)decomp_length + 1);
+	}
+	else
+	{
+		decomp_dat = nullptr;
+		decomp_length =  0;
+	}
+
+	// Make structure
+	*c = (corlett_t *) malloc(sizeof(corlett_t));
+	if (!(*c))
+	{
+		free(decomp_dat);
+		return AO_FAIL;
+	}
+	memset(*c, 0, sizeof(corlett_t));
+	strcpy((*c)->inf_title, "n/a");
+	strcpy((*c)->inf_copy, "n/a");
+	strcpy((*c)->inf_artist, "n/a");
+	strcpy((*c)->inf_game, "n/a");
+	strcpy((*c)->inf_year, "n/a");
+	strcpy((*c)->inf_length, "n/a");
+	strcpy((*c)->inf_fade, "n/a");
+
+	// set reserved section pointer
+	(*c)->res_section = &buf[4];
+	(*c)->res_size = res_area;
+
+	// Return it
+	if (output != nullptr && size != nullptr)
+	{
+		*output = decomp_dat;
+		*size = decomp_length;
+	}
+	else
+		free(decomp_dat);
+
+	// Next check for tags
+	input_len -= (comp_length + 16 + res_area);
+	if (input_len < 5)
+		return AO_SUCCESS;
+
+//	printf("\n\nNew corlett: input len %d comp length %d res area %d\n", input_len, comp_length, res_area);
+
+	tag_dec = input + (comp_length + res_area + 16);
+	if ((tag_dec[0] == '[') && (tag_dec[1] == 'T') && (tag_dec[2] == 'A') && (tag_dec[3] == 'G') && (tag_dec[4] == ']'))
+	{
+		int l, num_tags, data;
+
+		// Tags found!
+		tag_dec += 5;
+		input_len -= 5;
+
+		data = false;
+		num_tags = 0;
+		l = 0;
+		while (input_len && (num_tags < MAX_UNKNOWN_TAGS))
+		{
+			if (data)
+			{
+				if ((*tag_dec == 0xA) || (*tag_dec == 0x00))
+				{
+					(*c)->tag_data[num_tags][l] = 0;
+					data = false;
+					num_tags++;
+					l = 0;
+				}
+				else
+				{
+					(*c)->tag_data[num_tags][l++] = *tag_dec;
+				}
+			}
+			else
+			{
+				if (*tag_dec == '=')
+				{
+					(*c)->tag_name[num_tags][l] = 0;
+					l = 0;
+					data = true;
+				}
+				else
+				{
+					(*c)->tag_name[num_tags][l++] = *tag_dec;
+				}
+			}
+
+			tag_dec++;
+			input_len--;
+		}
+
+
+		// Now, process that tag array into what we expect
+		for (num_tags = 0; num_tags < MAX_UNKNOWN_TAGS; num_tags++)
+		{
+			// See if tag belongs in one of the special fields we have
+			if (!strcmp_nocase((*c)->tag_name[num_tags], "_lib"))
+			{
+				strcpy((*c)->lib, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib2", 5))
+			{
+				strcpy((*c)->libaux[0], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib3", 5))
+			{
+				strcpy((*c)->libaux[1], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib4", 5))
+			{
+				strcpy((*c)->libaux[2], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib5", 5))
+			{
+				strcpy((*c)->libaux[3], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib6", 5))
+			{
+				strcpy((*c)->libaux[4], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib7", 5))
+			{
+				strcpy((*c)->libaux[5], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib8", 5))
+			{
+				strcpy((*c)->libaux[6], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_lib9", 5))
+			{
+				strcpy((*c)->libaux[7], (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "_refresh", 8))
+			{
+				strcpy((*c)->inf_refresh, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "title", 5))
+			{
+				strcpy((*c)->inf_title, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "copyright", 9))
+			{
+				strcpy((*c)->inf_copy, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "artist", 6))
+			{
+				strcpy((*c)->inf_artist, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "game", 4))
+			{
+				strcpy((*c)->inf_game, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "year", 4))
+			{
+				strcpy((*c)->inf_year, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "length", 6))
+			{
+				strcpy((*c)->inf_length, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+			else if (!strncmp((*c)->tag_name[num_tags], "fade", 4))
+			{
+				strcpy((*c)->inf_fade, (*c)->tag_data[num_tags]);
+				(*c)->tag_data[num_tags][0] = 0;
+				(*c)->tag_name[num_tags][0] = 0;
+			}
+		}
+	}
+
+	// Bingo
+	return AO_SUCCESS;
+}
+
+uint32_t psfTimeToMS(char *str)
+{
+	int x, c=0;
+	uint32_t acc=0;
+	char s[100];
+
+	strncpy(s,str,100);
+	s[99]=0;
+
+	for (x=strlen(s); x>=0; x--)
+	{
+		if (s[x]=='.' || s[x]==',')
+		{
+			acc=atoi(s+x+1);
+			s[x]=0;
+		}
+		else if (s[x]==':')
+		{
+			if(c==0)
+			{
+				acc+=atoi(s+x+1)*10;
+			}
+			else if(c==1)
+			{
+				acc+=atoi(s+x+(x?1:0))*10*60;
+			}
+
+			c++;
+			s[x]=0;
+		}
+		else if (x==0)
+		{
+			if(c==0)
+			{
+				acc+=atoi(s+x)*10;
+			}
+			else if(c==1)
+			{
+				acc+=atoi(s+x)*10*60;
+			}
+			else if(c==2)
+			{
+				acc+=atoi(s+x)*10*60*60;
+			}
+		}
+	}
+
+	acc*=100;
+	return(acc);
+}
+
diff --git a/src/xsf/desmume/COPYING b/src/xsf/desmume/COPYING
index d60c31a97a54..623b6258a134 100644
--- a/src/xsf/desmume/COPYING
+++ b/src/xsf/desmume/COPYING
@@ -2,7 +2,7 @@
 		       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
 
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
 Also add information on how to contact you by electronic and paper mail.
diff --git a/src/xsf/desmume/FIFO.c b/src/xsf/desmume/FIFO.c
deleted file mode 100644
index c86017f711ef..000000000000
--- a/src/xsf/desmume/FIFO.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-	Copyright (C) 2007 shash
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "FIFO.h"
-
-void FIFOInit(FIFO * fifo)
-{
-        u32 i;
-
-	fifo->begin = 0;
-        fifo->end = 0;
-        for(i = 0; i<0x8000; ++i)
-        	fifo->data[i] = 0;
-        fifo->full = FALSE;
-        fifo->empty = TRUE;
-        fifo->error = FALSE;
-}
-
-void FIFOAdd(FIFO * fifo, u32 v)
-{
-	if(fifo->full) 
-        {
-        	fifo->error = TRUE;
-                return;
-        }
-        fifo->data[fifo->end] = v;
-        fifo->end = (fifo->end + 1)& 0x7FFF;
-        fifo->full = (fifo->end == fifo->begin);
-        fifo->empty = FALSE;
-}
-       
-u32 FIFOValue(FIFO * fifo)
-{
-        u32 v;
-
-	if(fifo->empty)
-        {
-        	fifo->error = TRUE;
-                return 0;
-        }
-        v = fifo->data[fifo->begin];
-        fifo->begin = (fifo->begin + 1)& 0x7FFF;
-        fifo->empty = (fifo->begin == fifo->end);
-        return v;
-}
diff --git a/src/xsf/desmume/FIFO.cc b/src/xsf/desmume/FIFO.cc
new file mode 100644
index 000000000000..09d6fb6e2462
--- /dev/null
+++ b/src/xsf/desmume/FIFO.cc
@@ -0,0 +1,65 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+	Copyright (C) 2007 shash
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "FIFO.h"
+
+void FIFOInit(FIFO * fifo)
+{
+        u32 i;
+
+	fifo->begin = 0;
+        fifo->end = 0;
+        for(i = 0; i<0x8000; ++i)
+        	fifo->data[i] = 0;
+        fifo->full = false;
+        fifo->empty = true;
+        fifo->error = false;
+}
+
+void FIFOAdd(FIFO * fifo, u32 v)
+{
+	if(fifo->full)
+        {
+        	fifo->error = true;
+                return;
+        }
+        fifo->data[fifo->end] = v;
+        fifo->end = (fifo->end + 1)& 0x7FFF;
+        fifo->full = (fifo->end == fifo->begin);
+        fifo->empty = false;
+}
+
+u32 FIFOValue(FIFO * fifo)
+{
+        u32 v;
+
+	if(fifo->empty)
+        {
+        	fifo->error = true;
+                return 0;
+        }
+        v = fifo->data[fifo->begin];
+        fifo->begin = (fifo->begin + 1)& 0x7FFF;
+        fifo->empty = (fifo->begin == fifo->end);
+        return v;
+}
diff --git a/src/xsf/desmume/FIFO.h b/src/xsf/desmume/FIFO.h
index 86e282902260..c9ba28991e96 100644
--- a/src/xsf/desmume/FIFO.h
+++ b/src/xsf/desmume/FIFO.h
@@ -18,7 +18,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef FIFO_H
@@ -26,10 +26,6 @@
 
 #include "types.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct
 {
        u32 data[0x8000];
@@ -44,8 +40,4 @@ void FIFOInit(FIFO * fifo);
 void FIFOAdd(FIFO * fifo, u32 v);
 u32 FIFOValue(FIFO * fifo);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/src/xsf/desmume/GPU.c b/src/xsf/desmume/GPU.c
deleted file mode 100644
index 4dcfe6c3996b..000000000000
--- a/src/xsf/desmume/GPU.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-    Copyright (C) 2006-2007 Theo Berkau
-    Copyright (C) 2007 shash
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// CONTENTS
-//	INITIALIZATION
-//	ENABLING / DISABLING LAYERS
-//	PARAMETERS OF BACKGROUNDS
-//	PARAMETERS OF ROTOSCALE
-//	PARAMETERS OF EFFECTS
-//	PARAMETERS OF WINDOWS
-//	ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS
-//	PIXEL RENDERING
-//	BACKGROUND RENDERING -TEXT-
-//	BACKGROUND RENDERING -ROTOSCALE-
-//	BACKGROUND RENDERING -HELPER FUNCTIONS-
-//	SPRITE RENDERING -HELPER FUNCTIONS-
-//	SPRITE RENDERING
-//	SCREEN FUNCTIONS
-//	GRAPHICS CORE
-//	GPU_ligne
-
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "MMU.h"
-#include "GPU.h"
-
-ARM9_struct ARM9Mem;
-
-NDS_Screen MainScreen;
-NDS_Screen SubScreen;
-
-//#define DEBUG_TRI
-
-/*****************************************************************************/
-//			INITIALIZATION
-/*****************************************************************************/
-
-GPU * GPU_Init(u8 l)
-{
-     GPU * g;
-
-     if ((g = (GPU *) malloc(sizeof(GPU))) == NULL)
-        return NULL;
-
-     GPU_Reset(g, l);
-     return g;
-}
-
-void GPU_Reset(GPU *g, u8 l)
-{
-   memset(g, 0, sizeof(GPU));
-}
-
-void GPU_DeInit(GPU * gpu)
-{
-	if (gpu) free(gpu);
-}
-
-
-int Screen_Init(int coreid) {
-   MainScreen.gpu = GPU_Init(0);
-   SubScreen.gpu = GPU_Init(1);
-
-   return 0;
-}
-
-void Screen_Reset(void) {
-   GPU_Reset(MainScreen.gpu, 0);
-   GPU_Reset(SubScreen.gpu, 1);
-}
-
-void Screen_DeInit(void) {
-	GPU_DeInit(MainScreen.gpu);
-	GPU_DeInit(SubScreen.gpu);
-
-}
diff --git a/src/xsf/desmume/GPU.cc b/src/xsf/desmume/GPU.cc
new file mode 100644
index 000000000000..4ab8f5907452
--- /dev/null
+++ b/src/xsf/desmume/GPU.cc
@@ -0,0 +1,98 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+    Copyright (C) 2006-2007 Theo Berkau
+    Copyright (C) 2007 shash
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// CONTENTS
+//	INITIALIZATION
+//	ENABLING / DISABLING LAYERS
+//	PARAMETERS OF BACKGROUNDS
+//	PARAMETERS OF ROTOSCALE
+//	PARAMETERS OF EFFECTS
+//	PARAMETERS OF WINDOWS
+//	ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS
+//	PIXEL RENDERING
+//	BACKGROUND RENDERING -TEXT-
+//	BACKGROUND RENDERING -ROTOSCALE-
+//	BACKGROUND RENDERING -HELPER FUNCTIONS-
+//	SPRITE RENDERING -HELPER FUNCTIONS-
+//	SPRITE RENDERING
+//	SCREEN FUNCTIONS
+//	GRAPHICS CORE
+//	GPU_ligne
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "MMU.h"
+#include "GPU.h"
+
+ARM9_struct ARM9Mem;
+
+NDS_Screen MainScreen;
+NDS_Screen SubScreen;
+
+//#define DEBUG_TRI
+
+/*****************************************************************************/
+//			INITIALIZATION
+/*****************************************************************************/
+
+GPU * GPU_Init(u8 l)
+{
+     GPU * g;
+
+     if ((g = (GPU *) malloc(sizeof(GPU))) == nullptr)
+        return nullptr;
+
+     GPU_Reset(g, l);
+     return g;
+}
+
+void GPU_Reset(GPU *g, u8 l)
+{
+   memset(g, 0, sizeof(GPU));
+}
+
+void GPU_DeInit(GPU * gpu)
+{
+	if (gpu) free(gpu);
+}
+
+
+int Screen_Init(int coreid) {
+   MainScreen.gpu = GPU_Init(0);
+   SubScreen.gpu = GPU_Init(1);
+
+   return 0;
+}
+
+void Screen_Reset(void) {
+   GPU_Reset(MainScreen.gpu, 0);
+   GPU_Reset(SubScreen.gpu, 1);
+}
+
+void Screen_DeInit(void) {
+	GPU_DeInit(MainScreen.gpu);
+	GPU_DeInit(SubScreen.gpu);
+
+}
diff --git a/src/xsf/desmume/GPU.h b/src/xsf/desmume/GPU.h
index ac89d95434a5..423cf85dbe6f 100644
--- a/src/xsf/desmume/GPU.h
+++ b/src/xsf/desmume/GPU.h
@@ -19,7 +19,7 @@
 
 	You should have received a copy of the GNU General Public License
 	along with DeSmuME; if not, write to the Free Software
-	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef GPU_H
@@ -32,11 +32,6 @@
 #include "FIFO.h"
 #include "MMU.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 /*******************************************************************************
     this structure is for display control,
     it holds flags for general display
@@ -394,7 +389,7 @@ typedef struct _reg_dispx {
 
 
 
-
+#ifndef __cplusplus
 #ifndef min
 #define min(a,b) (((a)<(b))?(a):(b))
 #endif
@@ -402,6 +397,7 @@ typedef struct _reg_dispx {
 #ifndef max
 #define max(a,b) (((a)>(b))?(a):(b))
 #endif
+#endif
 
 typedef BOOL (*fun_gl_Begin) (int screen);
 typedef void (*fun_gl_End) (int screen);
@@ -547,7 +543,7 @@ typedef struct
 /*12*/    unsigned PaletteIndex:4;
 /*10*/    unsigned Priority:2;
 // attr3
-unsigned attr3:16;    
+unsigned attr3:16;
 #else
 // attr0
 /* 0*/	unsigned Y:8;
@@ -805,9 +801,5 @@ void GPU_setBLDALPHA_EVB(GPU *gpu, u8 val);
 
 void GPU_setBLDY_EVY	(GPU *gpu, u8 val);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
diff --git a/src/xsf/desmume/MMU.c b/src/xsf/desmume/MMU.c
deleted file mode 100644
index 36677d774f68..000000000000
--- a/src/xsf/desmume/MMU.c
+++ /dev/null
@@ -1,3565 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-	Copyright (C) 2007 shash
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-//#define RENDER3D
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-//#include "gl_vertex.h"
-
-#include "debug.h"
-#include "NDSSystem.h"
-//#include "cflash.h"
-#define cflash_read(a) 0
-#define cflash_write(a,d)
-#include "cp15.h"
-//#include "wifi.h"
-#include "registers.h"
-
-#if VIO2SF_GPU_ENABLE
-#include "render3D.h"
-#else
-#define GPU_setVideoProp(p1, p2)
-#define GPU_setBGProp(p1, p2, p3)
-
-#define GPU_setBLDCNT(p1, p2) 
-#define GPU_setBLDALPHA(p1, p2) 
-#define GPU_setBLDY(p1, p2) 
-#define GPU_setMOSAIC(p1, p2) 
-
-
-#define GPU_remove(p1,p2)
-#define GPU_addBack(p1,p2)
-
-#define GPU_ChangeGraphicsCore(p1) 0
-
-#define GPU_set_DISPCAPCNT(p1, p2) 
-#define GPU_ligne(p1, p2) 
-#define GPU_setMasterBrightness(p1, p2)
-
-#define GPU_setWIN0_H(p1, p2)
-#define GPU_setWIN0_H0(p1, p2)
-#define GPU_setWIN0_H1(p1, p2)
-
-#define GPU_setWIN0_V(p1, p2)
-#define GPU_setWIN0_V0(p1, p2)
-#define GPU_setWIN0_V1(p1, p2)
-
-#define GPU_setWIN1_H(p1, p2)
-#define GPU_setWIN1_H0(p1, p2)
-#define GPU_setWIN1_H1(p1, p2)
-
-#define GPU_setWIN1_V(p1, p2)
-#define GPU_setWIN1_V0(p1, p2)
-#define GPU_setWIN1_V1(p1, p2)
-
-#define GPU_setWININ(p1, p2)
-#define GPU_setWININ0(p1, p2)
-#define GPU_setWININ1(p1, p2)
-
-#define GPU_setWINOUT16(p1, p2)
-#define GPU_setWINOUT(p1, p2)
-#define GPU_setWINOBJ(p1, p2)
-
-#define GPU_setBLDCNT_LOW(p1, p2)
-#define GPU_setBLDCNT_HIGH(p1, p2)
-#define GPU_setBLDCNT(p1, p2)
-
-#define GPU_setBLDALPHA(p1, p2)
-#define GPU_setBLDALPHA_EVA(p1, p2)
-#define GPU_setBLDALPHA_EVB(p1, p2)
-
-#define GPU_setBLDY_EVY(p1, p2)
-#endif
-
-#define ROM_MASK 3
-
-/*
- *
- */
-//#define PROFILE_MEMORY_ACCESS 1
-#define EARLY_MEMORY_ACCESS 1
-
-#define INTERNAL_DTCM_READ 1
-#define INTERNAL_DTCM_WRITE 1
-
-//#define LOG_CARD
-//#define LOG_GPU
-//#define LOG_DMA
-//#define LOG_DMA2
-//#define LOG_DIV
-
-char szRomPath[512];
-char szRomBaseName[512];
-
-#define DUP2(x)  x, x
-#define DUP4(x)  x, x, x, x
-#define DUP8(x)  x, x, x, x,  x, x, x, x
-#define DUP16(x) x, x, x, x,  x, x, x, x,  x, x, x, x,  x, x, x, x
-
-MMU_struct MMU;
-
-u8 * MMU_ARM9_MEM_MAP[256]={
-/* 0X*/	DUP16(ARM9Mem.ARM9_ITCM), 
-/* 1X*/	//DUP16(ARM9Mem.ARM9_ITCM)
-/* 1X*/	DUP16(ARM9Mem.ARM9_WRAM), 
-/* 2X*/	DUP16(ARM9Mem.MAIN_MEM),
-/* 3X*/	DUP16(MMU.SWIRAM),
-/* 4X*/	DUP16(ARM9Mem.ARM9_REG),
-/* 5X*/	DUP16(ARM9Mem.ARM9_VMEM),
-/* 6X*/	DUP2(ARM9Mem.ARM9_ABG), 
-		DUP2(ARM9Mem.ARM9_BBG),
-		DUP2(ARM9Mem.ARM9_AOBJ),
-		DUP2(ARM9Mem.ARM9_BOBJ),
-		DUP8(ARM9Mem.ARM9_LCD),
-/* 7X*/	DUP16(ARM9Mem.ARM9_OAM),
-/* 8X*/	DUP16(NULL),
-/* 9X*/	DUP16(NULL),
-/* AX*/	DUP16(MMU.CART_RAM),
-/* BX*/	DUP16(MMU.UNUSED_RAM),
-/* CX*/	DUP16(MMU.UNUSED_RAM),
-/* DX*/	DUP16(MMU.UNUSED_RAM),
-/* EX*/	DUP16(MMU.UNUSED_RAM),
-/* FX*/	DUP16(ARM9Mem.ARM9_BIOS)
-};
-	   
-u32 MMU_ARM9_MEM_MASK[256]={
-/* 0X*/	DUP16(0x00007FFF), 
-/* 1X*/	//DUP16(0x00007FFF)
-/* 1X*/	DUP16(0x00FFFFFF), 
-/* 2X*/	DUP16(0x003FFFFF),
-/* 3X*/	DUP16(0x00007FFF),
-/* 4X*/	DUP16(0x00FFFFFF),
-/* 5X*/	DUP16(0x000007FF),
-/* 6X*/	DUP2(0x0007FFFF), 
-		DUP2(0x0001FFFF),
-		DUP2(0x0003FFFF),
-		DUP2(0x0001FFFF),
-		DUP8(0x000FFFFF),
-/* 7X*/	DUP16(0x000007FF),
-/* 8X*/	DUP16(ROM_MASK),
-/* 9X*/	DUP16(ROM_MASK),
-/* AX*/	DUP16(0x0000FFFF),
-/* BX*/	DUP16(0x00000003),
-/* CX*/	DUP16(0x00000003),
-/* DX*/	DUP16(0x00000003),
-/* EX*/	DUP16(0x00000003),
-/* FX*/	DUP16(0x00007FFF)
-};
-
-u8 * MMU_ARM7_MEM_MAP[256]={
-/* 0X*/	DUP16(MMU.ARM7_BIOS), 
-/* 1X*/	DUP16(MMU.UNUSED_RAM), 
-/* 2X*/	DUP16(ARM9Mem.MAIN_MEM),
-/* 3X*/	DUP8(MMU.SWIRAM),
-		DUP8(MMU.ARM7_ERAM),
-/* 4X*/	DUP8(MMU.ARM7_REG),
-		DUP8(MMU.ARM7_WIRAM),
-/* 5X*/	DUP16(MMU.UNUSED_RAM),
-/* 6X*/	DUP16(ARM9Mem.ARM9_ABG), 
-/* 7X*/	DUP16(MMU.UNUSED_RAM),
-/* 8X*/	DUP16(NULL),
-/* 9X*/	DUP16(NULL),
-/* AX*/	DUP16(MMU.CART_RAM),
-/* BX*/	DUP16(MMU.UNUSED_RAM),
-/* CX*/	DUP16(MMU.UNUSED_RAM),
-/* DX*/	DUP16(MMU.UNUSED_RAM),
-/* EX*/	DUP16(MMU.UNUSED_RAM),
-/* FX*/	DUP16(MMU.UNUSED_RAM)
-};
-
-u32 MMU_ARM7_MEM_MASK[256]={
-/* 0X*/	DUP16(0x00003FFF), 
-/* 1X*/	DUP16(0x00000003),
-/* 2X*/	DUP16(0x003FFFFF),
-/* 3X*/	DUP8(0x00007FFF),
-		DUP8(0x0000FFFF),
-/* 4X*/	DUP8(0x00FFFFFF),
-		DUP8(0x0000FFFF),
-/* 5X*/	DUP16(0x00000003),
-/* 6X*/	DUP16(0x0003FFFF), 
-/* 7X*/	DUP16(0x00000003),
-/* 8X*/	DUP16(ROM_MASK),
-/* 9X*/	DUP16(ROM_MASK),
-/* AX*/	DUP16(0x0000FFFF),
-/* BX*/	DUP16(0x00000003),
-/* CX*/	DUP16(0x00000003),
-/* DX*/	DUP16(0x00000003),
-/* EX*/	DUP16(0x00000003),
-/* FX*/	DUP16(0x00000003)
-};
-
-u32 MMU_ARM9_WAIT16[16]={
-	1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
-};
-
-u32 MMU_ARM9_WAIT32[16]={
-	1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1,
-};
-
-u32 MMU_ARM7_WAIT16[16]={
-	1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
-};
-
-u32 MMU_ARM7_WAIT32[16]={
-	1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1,
-};
-
-void MMU_Init(void) {
-	int i;
-
-	LOG("MMU init\n");
-
-	memset(&MMU, 0, sizeof(MMU_struct));
-
-	MMU.CART_ROM = MMU.UNUSED_RAM;
-
-        for(i = 0x80; i<0xA0; ++i)
-        {
-           MMU_ARM9_MEM_MAP[i] = MMU.CART_ROM;
-           MMU_ARM7_MEM_MAP[i] = MMU.CART_ROM;
-        }
-
-	MMU.MMU_MEM[0] = MMU_ARM9_MEM_MAP;
-	MMU.MMU_MEM[1] = MMU_ARM7_MEM_MAP;
-	MMU.MMU_MASK[0]= MMU_ARM9_MEM_MASK;
-	MMU.MMU_MASK[1] = MMU_ARM7_MEM_MASK;
-
-	MMU.ITCMRegion = 0x00800000;
-
-	MMU.MMU_WAIT16[0] = MMU_ARM9_WAIT16;
-	MMU.MMU_WAIT16[1] = MMU_ARM7_WAIT16;
-	MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32;
-	MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32;
-
-	for(i = 0;i < 16;i++)
-		FIFOInit(MMU.fifos + i);
-	
-        mc_init(&MMU.fw, MC_TYPE_FLASH);  /* init fw device */
-        mc_alloc(&MMU.fw, NDS_FW_SIZE_V1);
-        MMU.fw.fp = NULL;
-
-        // Init Backup Memory device, this should really be done when the rom is loaded
-        mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT);
-        mc_alloc(&MMU.bupmem, 1);
-        MMU.bupmem.fp = NULL;
-
-} 
-
-void MMU_DeInit(void) {
-	LOG("MMU deinit\n");
-//    if (MMU.fw.fp)
-//       fclose(MMU.fw.fp);
-    mc_free(&MMU.fw);      
-//    if (MMU.bupmem.fp)
-//       fclose(MMU.bupmem.fp);
-    mc_free(&MMU.bupmem);
-}
-
-//Card rom & ram
-
-u16 SPI_CNT = 0;
-u16 SPI_CMD = 0;
-u16 AUX_SPI_CNT = 0;
-u16 AUX_SPI_CMD = 0;
-
-u32 rom_mask = 0;
-
-u32 DMASrc[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
-u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
-
-void MMU_clearMem()
-{
-	int i;
-	
-	memset(ARM9Mem.ARM9_ABG,  0, 0x080000);
-	memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000);
-	memset(ARM9Mem.ARM9_BBG,  0, 0x020000);
-	memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000);
-	memset(ARM9Mem.ARM9_DTCM, 0, 0x4000);
-	memset(ARM9Mem.ARM9_ITCM, 0, 0x8000);
-	memset(ARM9Mem.ARM9_LCD,  0, 0x0A4000);
-	memset(ARM9Mem.ARM9_OAM,  0, 0x0800);
-	memset(ARM9Mem.ARM9_REG,  0, 0x01000000);
-	memset(ARM9Mem.ARM9_VMEM, 0, 0x0800);
-	memset(ARM9Mem.ARM9_WRAM, 0, 0x01000000);
-	memset(ARM9Mem.MAIN_MEM,  0, 0x400000);
-
-	memset(ARM9Mem.blank_memory,  0, 0x020000);
-	
-	memset(MMU.ARM7_ERAM,     0, 0x010000);
-	memset(MMU.ARM7_REG,      0, 0x010000);
-	
-	for(i = 0;i < 16;i++)
-	FIFOInit(MMU.fifos + i);
-	
-	MMU.DTCMRegion = 0;
-	MMU.ITCMRegion = 0x00800000;
-	
-	memset(MMU.timer,         0, sizeof(u16) * 2 * 4);
-	memset(MMU.timerMODE,     0, sizeof(s32) * 2 * 4);
-	memset(MMU.timerON,       0, sizeof(u32) * 2 * 4);
-	memset(MMU.timerRUN,      0, sizeof(u32) * 2 * 4);
-	memset(MMU.timerReload,   0, sizeof(u16) * 2 * 4);
-	
-	memset(MMU.reg_IME,       0, sizeof(u32) * 2);
-	memset(MMU.reg_IE,        0, sizeof(u32) * 2);
-	memset(MMU.reg_IF,        0, sizeof(u32) * 2);
-	
-	memset(MMU.DMAStartTime,  0, sizeof(u32) * 2 * 4);
-	memset(MMU.DMACycle,      0, sizeof(s32) * 2 * 4);
-	memset(MMU.DMACrt,        0, sizeof(u32) * 2 * 4);
-	memset(MMU.DMAing,        0, sizeof(BOOL) * 2 * 4);
-	
-	memset(MMU.dscard,        0, sizeof(nds_dscard) * 2);
-	
-	MainScreen.offset = 192;
-	SubScreen.offset  = 0;
-
-        /* setup the texture slot pointers */
-#if 0
-        ARM9Mem.textureSlotAddr[0] = ARM9Mem.blank_memory;
-        ARM9Mem.textureSlotAddr[1] = ARM9Mem.blank_memory;
-        ARM9Mem.textureSlotAddr[2] = ARM9Mem.blank_memory;
-        ARM9Mem.textureSlotAddr[3] = ARM9Mem.blank_memory;
-#else
-        ARM9Mem.textureSlotAddr[0] = &ARM9Mem.ARM9_LCD[0x20000 * 0];
-        ARM9Mem.textureSlotAddr[1] = &ARM9Mem.ARM9_LCD[0x20000 * 1];
-        ARM9Mem.textureSlotAddr[2] = &ARM9Mem.ARM9_LCD[0x20000 * 2];
-        ARM9Mem.textureSlotAddr[3] = &ARM9Mem.ARM9_LCD[0x20000 * 3];
-#endif
-}
-
-/* the VRAM blocks keep their content even when not blended in */
-/* to ensure that we write the content back to the LCD ram */
-/* FIXME: VRAM Bank E,F,G,H,I missing */
-void MMU_VRAMWriteBackToLCD(u8 block)
-{
-	u8 *destination;
-	u8 *source;
-	u32 size ;
-	u8 VRAMBankCnt;
-	#if 1
-		return ;
-	#endif
-	destination = 0 ;
-	source = 0;
-	VRAMBankCnt = MMU_read8(ARMCPU_ARM9,REG_VRAMCNTA+block) ;
-	switch (block)
-	{
-		case 0: // Bank A
-			destination = ARM9Mem.ARM9_LCD ;
-			size = 0x20000 ;
-			break ;
-		case 1: // Bank B
-			destination = ARM9Mem.ARM9_LCD + 0x20000 ;
-			size = 0x20000 ;
-			break ;
-		case 2: // Bank C
-			destination = ARM9Mem.ARM9_LCD + 0x40000 ;
-			size = 0x20000 ;
-			break ;
-		case 3: // Bank D
-			destination = ARM9Mem.ARM9_LCD + 0x60000 ;
-			size = 0x20000 ;
-			break ;
-		case 4: // Bank E
-			destination = ARM9Mem.ARM9_LCD + 0x80000 ;
-			size = 0x10000 ;
-			break ;
-		case 5: // Bank F
-			destination = ARM9Mem.ARM9_LCD + 0x90000 ;
-			size = 0x4000 ;
-			break ;
-		case 6: // Bank G
-			destination = ARM9Mem.ARM9_LCD + 0x94000 ;
-			size = 0x4000 ;
-			break ;
-		case 8: // Bank H
-			destination = ARM9Mem.ARM9_LCD + 0x98000 ;
-			size = 0x8000 ;
-			break ;
-		case 9: // Bank I
-			destination = ARM9Mem.ARM9_LCD + 0xA0000 ;
-			size = 0x4000 ;
-			break ;
-		default:
-			return ;
-	}
-	switch (VRAMBankCnt & 7) {
-		case 0:
-			/* vram is allready stored at LCD, we dont need to write it back */
-			MMU.vScreen = 1;
-			break ;
-		case 1:
-	switch(block){
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		/* banks are in use for BG at ABG + ofs * 0x20000 */
-				source = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
-		break ;
-	case 4:
-		/* bank E is in use at ABG */ 
-		source = ARM9Mem.ARM9_ABG ;
-		break;
-	case 5:
-	case 6:
-		/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
-		source = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
-		break;
-	case 8:
-		/* bank H is in use at BBG */ 
-		source = ARM9Mem.ARM9_BBG ;
-		break ;
-	case 9:
-		/* bank I is in use at BBG */ 
-		source = ARM9Mem.ARM9_BBG + 0x8000 ;
-		break;
-	default: return ;
-	}
-			break ;
-		case 2:
-			if (block < 2)
-			{
-				/* banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 */
-				source = ARM9Mem.ARM9_AOBJ + ((VRAMBankCnt >> 3) & 1) * 0x20000 ;
-			} else return ;
-			break ;
-		case 4:
-	switch(block){
-	case 2:
-		/* bank C is in use at BBG */ 
-		source = ARM9Mem.ARM9_BBG ;
-		break ;
-	case 3:
-		/* bank D is in use at BOBJ */ 
-		source = ARM9Mem.ARM9_BOBJ ;
-		break ;
-	default: return ;
-	}
-			break ;
-		default:
-			return ;
-	}
-	if (!destination) return ;
-	if (!source) return ;
-	memcpy(destination,source,size) ;
-}
-
-void MMU_VRAMReloadFromLCD(u8 block,u8 VRAMBankCnt)
-{
-	u8 *destination;
-	u8 *source;
-	u32 size;
-	#if 1
-		return ;
-	#endif
-	destination = 0;
-	source = 0;
-	size = 0;
-	switch (block)
-	{
-		case 0: // Bank A
-			source = ARM9Mem.ARM9_LCD ;
-			size = 0x20000 ;
-			break ;
-		case 1: // Bank B
-			source = ARM9Mem.ARM9_LCD + 0x20000 ;
-			size = 0x20000 ;
-			break ;
-		case 2: // Bank C
-			source = ARM9Mem.ARM9_LCD + 0x40000 ;
-			size = 0x20000 ;
-			break ;
-		case 3: // Bank D
-			source = ARM9Mem.ARM9_LCD + 0x60000 ;
-			size = 0x20000 ;
-			break ;
-		case 4: // Bank E
-			source = ARM9Mem.ARM9_LCD + 0x80000 ;
-			size = 0x10000 ;
-			break ;
-		case 5: // Bank F
-			source = ARM9Mem.ARM9_LCD + 0x90000 ;
-			size = 0x4000 ;
-			break ;
-		case 6: // Bank G
-			source = ARM9Mem.ARM9_LCD + 0x94000 ;
-			size = 0x4000 ;
-			break ;
-		case 8: // Bank H
-			source = ARM9Mem.ARM9_LCD + 0x98000 ;
-			size = 0x8000 ;
-			break ;
-		case 9: // Bank I
-			source = ARM9Mem.ARM9_LCD + 0xA0000 ;
-			size = 0x4000 ;
-			break ;
-		default:
-			return ;
-	}
-	switch (VRAMBankCnt & 7) {
-		case 0:
-			/* vram is allready stored at LCD, we dont need to write it back */
-			MMU.vScreen = 1;
-			break ;
-		case 1:
-			if (block < 4)
-			{
-				/* banks are in use for BG at ABG + ofs * 0x20000 */
-				destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
-			} else return ;
-			break ;
-		case 2:
-				switch(block){
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		/* banks are in use for BG at ABG + ofs * 0x20000 */
-				destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
-		break ;
-	case 4:
-		/* bank E is in use at ABG */ 
-		destination = ARM9Mem.ARM9_ABG ;
-		break;
-	case 5:
-	case 6:
-		/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
-		destination = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
-		break;
-	case 8:
-		/* bank H is in use at BBG */ 
-		destination = ARM9Mem.ARM9_BBG ;
-		break ;
-	case 9:
-		/* bank I is in use at BBG */ 
-		destination = ARM9Mem.ARM9_BBG + 0x8000 ;
-		break;
-	default: return ;
-	}
-			break ;
-		case 4:
-	switch(block){
-	case 2:
-		/* bank C is in use at BBG */ 
-		destination = ARM9Mem.ARM9_BBG ;
-		break ;
-	case 3:
-		/* bank D is in use at BOBJ */ 
-		destination = ARM9Mem.ARM9_BOBJ ;
-		break ;
-	default: return ;
-	}
-			break ;
-		default:
-			return ;
-	}
-	if (!destination) return ;
-	if (!source) return ;
-	memcpy(destination,source,size) ;
-}
-
-void MMU_setRom(u8 * rom, u32 mask)
-{
-	unsigned int i;
-	MMU.CART_ROM = rom;
-	
-	for(i = 0x80; i<0xA0; ++i)
-	{
-		MMU_ARM9_MEM_MAP[i] = rom;
-		MMU_ARM7_MEM_MAP[i] = rom;
-		MMU_ARM9_MEM_MASK[i] = mask;
-		MMU_ARM7_MEM_MASK[i] = mask;
-	}
-	rom_mask = mask;
-}
-
-void MMU_unsetRom()
-{
-	unsigned int i;
-	MMU.CART_ROM=MMU.UNUSED_RAM;
-	
-	for(i = 0x80; i<0xA0; ++i)
-	{
-		MMU_ARM9_MEM_MAP[i] = MMU.UNUSED_RAM;
-		MMU_ARM7_MEM_MAP[i] = MMU.UNUSED_RAM;
-		MMU_ARM9_MEM_MASK[i] = ROM_MASK;
-		MMU_ARM7_MEM_MASK[i] = ROM_MASK;
-	}
-	rom_mask = ROM_MASK;
-}
-char txt[80];	
-
-u8 FASTCALL MMU_read8(u32 proc, u32 adr)
-{
-#ifdef INTERNAL_DTCM_READ
-	if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion))
-	{
-		return ARM9Mem.ARM9_DTCM[adr&0x3FFF];
-	}
-#endif
-	
-	// CFlash reading, Mic
-	if ((adr>=0x9000000)&&(adr<0x9900000))
-		return (unsigned char)cflash_read(adr);
-
-#ifdef EXPERIMENTAL_WIFI
-	/* wifi mac access */
-	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
-	{
-		if (adr & 1)
-			return (WIFI_read16(&wifiMac,adr) >> 8) & 0xFF;
-		else
-			return WIFI_read16(&wifiMac,adr) & 0xFF;
-	}
-#endif
-
-        return MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]];
-}
-
-
-
-u16 FASTCALL MMU_read16(u32 proc, u32 adr)
-{    
-#ifdef INTERNAL_DTCM_READ
-	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
-	{
-		/* Returns data from DTCM (ARM9 only) */
-		return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-	}
-#endif
-	
-	// CFlash reading, Mic
-	if ((adr>=0x08800000)&&(adr<0x09900000))
-	   return (unsigned short)cflash_read(adr);
-
-#ifdef EXPERIMENTAL_WIFI
-	/* wifi mac access */
-	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
-		return WIFI_read16(&wifiMac,adr) ;
-#endif
-
-	adr &= 0x0FFFFFFF;
-
-	if(adr&0x04000000)
-	{
-		/* Adress is an IO register */
-		switch(adr)
-		{
-
-#if VIO2SF_GPU_ENABLE
-			case 0x04000604:
-				return (gpu3D->NDS_3D_GetNumPolys()&2047);
-			case 0x04000606:
-				return (gpu3D->NDS_3D_GetNumVertex()&8191);
-#endif
-
-			case REG_IPCFIFORECV :               /* TODO (clear): ??? */
-				execute = FALSE;
-				return 1;
-				
-			case REG_IME :
-				return (u16)MMU.reg_IME[proc];
-				
-			case REG_IE :
-				return (u16)MMU.reg_IE[proc];
-			case REG_IE + 2 :
-				return (u16)(MMU.reg_IE[proc]>>16);
-				
-			case REG_IF :
-				return (u16)MMU.reg_IF[proc];
-			case REG_IF + 2 :
-				return (u16)(MMU.reg_IF[proc]>>16);
-				
-			case REG_TM0CNTL :
-			case REG_TM1CNTL :
-			case REG_TM2CNTL :
-			case REG_TM3CNTL :
-				return MMU.timer[proc][(adr&0xF)>>2];
-			
-			case 0x04000630 :
-				LOG("vect res\r\n");	/* TODO (clear): ??? */
-				//execute = FALSE;
-				return 0;
-                        case REG_POSTFLG :
-				return 1;
-			default :
-				break;
-		}
-	}
-	
-	/* Returns data from memory */
-	return T1ReadWord(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]); 
-}
-	 
-u32 FASTCALL MMU_read32(u32 proc, u32 adr)
-{
-#ifdef INTERNAL_DTCM_READ
-	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
-	{
-		/* Returns data from DTCM (ARM9 only) */
-		return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-	}
-#endif
-	
-	// CFlash reading, Mic
-	if ((adr>=0x9000000)&&(adr<0x9900000))
-	   return (unsigned long)cflash_read(adr);
-		
-	adr &= 0x0FFFFFFF;
-
-	if((adr >> 24) == 4)
-	{
-		/* Adress is an IO register */
-		switch(adr)
-		{
-			// This is hacked due to the only current 3D core
-			case 0x04000600:
-            {
-                u32 fifonum = IPCFIFO+proc;
-
-				u32 gxstat =	(MMU.fifos[fifonum].empty<<26) | 
-								(1<<25) | 
-								(MMU.fifos[fifonum].full<<24) | 
-								/*((NDS_nbpush[0]&1)<<13) | ((NDS_nbpush[2]&0x1F)<<8) |*/ 
-								2;
-
-				LOG ("GXSTAT: 0x%X", gxstat);
-
-				return	gxstat;
-            }
-
-			case 0x04000640:
-			case 0x04000644:
-			case 0x04000648:
-			case 0x0400064C:
-			case 0x04000650:
-			case 0x04000654:
-			case 0x04000658:
-			case 0x0400065C:
-			case 0x04000660:
-			case 0x04000664:
-			case 0x04000668:
-			case 0x0400066C:
-			case 0x04000670:
-			case 0x04000674:
-			case 0x04000678:
-			case 0x0400067C:
-			{
-				//LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)");
-#if VIO2SF_GPU_ENABLE
-				return gpu3D->NDS_3D_GetClipMatrix ((adr-0x04000640)/4);
-#else
-				return 0;
-#endif
-			}
-			case 0x04000680:
-			case 0x04000684:
-			case 0x04000688:
-			case 0x0400068C:
-			case 0x04000690:
-			case 0x04000694:
-			case 0x04000698:
-			case 0x0400069C:
-			case 0x040006A0:
-			{
-#if VIO2SF_GPU_ENABLE
-				//LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)");
-				return gpu3D->NDS_3D_GetDirectionalMatrix ((adr-0x04000680)/4);
-#else
-				return 0;
-#endif
-			}
-
-			case 0x4000604:
-			{
-#if VIO2SF_GPU_ENABLE
-				return (gpu3D->NDS_3D_GetNumPolys()&2047) & ((gpu3D->NDS_3D_GetNumVertex()&8191) << 16);
-				//LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[proc][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF])>>2]);
-#else
-				return 0;
-#endif
-			}
-			
-			case REG_IME :
-				return MMU.reg_IME[proc];
-			case REG_IE :
-				return MMU.reg_IE[proc];
-			case REG_IF :
-				return MMU.reg_IF[proc];
-			case REG_IPCFIFORECV :
-			{
-				u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
-				if(IPCFIFO_CNT&0x8000)
-				{
-				//execute = FALSE;
-				u32 fifonum = IPCFIFO+proc;
-				u32 val = FIFOValue(MMU.fifos + fifonum);
-				u32 remote = (proc+1) & 1;
-				u16 IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184);
-				IPCFIFO_CNT |= (MMU.fifos[fifonum].empty<<8) | (MMU.fifos[fifonum].full<<9) | (MMU.fifos[fifonum].error<<14);
-				IPCFIFO_CNT_remote |= (MMU.fifos[fifonum].empty) | (MMU.fifos[fifonum].full<<1);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
-				T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
-				if ((MMU.fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2)))
-					NDS_makeInt(remote,17) ; /* remote: SEND FIFO EMPTY */
-				return val;
-				}
-			}
-			return 0;
-                        case REG_TM0CNTL :
-                        case REG_TM1CNTL :
-                        case REG_TM2CNTL :
-                        case REG_TM3CNTL :
-			{
-				u32 val = T1ReadWord(MMU.MMU_MEM[proc][0x40], (adr + 2) & 0xFFF);
-				return MMU.timer[proc][(adr&0xF)>>2] | (val<<16);
-			}	
-			/*
-			case 0x04000640 :	// TODO (clear): again, ??? 
-				LOG("read proj\r\n");
-			return 0;
-			case 0x04000680 :
-				LOG("read roat\r\n");
-			return 0;
-			case 0x04000620 :
-				LOG("point res\r\n");
-			return 0;
-			*/
-                        case REG_GCDATAIN:
-			{
-                                u32 val;
-
-                                if(!MMU.dscard[proc].adress) return 0;
-				
-                                val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].adress);
-
-				MMU.dscard[proc].adress += 4;	/* increment adress */
-				
-				MMU.dscard[proc].transfer_count--;	/* update transfer counter */
-				if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */
-				{
-					return val;	/* return data */
-				}
-				else	/* transfer is done */
-                                {                                                       
-                                        T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, T1ReadLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff) & ~(0x00800000 | 0x80000000));
-					/* = 0x7f7fffff */
-					
-					/* if needed, throw irq for the end of transfer */
-                                        if(T1ReadWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff) & 0x4000)
-					{
-                                                if(proc == ARMCPU_ARM7) NDS_makeARM7Int(19); 
-                                                else NDS_makeARM9Int(19);
-					}
-					
-					return val;
-				}
-			}
-
-			default :
-				break;
-		}
-	}
-	
-	/* Returns data from memory */
-	return T1ReadLong(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]);
-}
-	
-void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val)
-{
-#ifdef INTERNAL_DTCM_WRITE
-	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
-	{
-		/* Writes data in DTCM (ARM9 only) */
-		ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val;
-		return ;
-	}
-#endif
-	
-	// CFlash writing, Mic
-	if ((adr>=0x9000000)&&(adr<0x9900000)) {
-		cflash_write(adr,val);
-		return;
-	}
-
-	adr &= 0x0FFFFFFF;
-
-        // This is bad, remove it
-        if(proc == ARMCPU_ARM7)
-        {
-           if ((adr>=0x04000400)&&(adr<0x0400051D))
-           {
-              SPU_WriteByte(adr, val);
-              return;
-           }
-        }
-
-	if ((adr & 0xFF800000) == 0x04800000)
-	{
-		/* is wifi hardware, dont intermix with regular hardware registers */
-		/* FIXME handle 8 bit writes */
-		return ;
-	}
-
-	switch(adr)
-	{
-		case REG_DISPA_WIN0H: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_H1 (MainScreen.gpu, val);
-			break ; 	 
-		case REG_DISPA_WIN0H+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_H0 (MainScreen.gpu, val);
-			break ; 	 
-		case REG_DISPA_WIN1H: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_H1 (MainScreen.gpu,val);
-			break ; 	 
-		case REG_DISPA_WIN1H+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_H0 (MainScreen.gpu,val);
-			break ; 	 
-
-		case REG_DISPB_WIN0H: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_H1(SubScreen.gpu,val);
-			break ; 	 
-		case REG_DISPB_WIN0H+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_H0(SubScreen.gpu,val);
-			break ; 	 
-		case REG_DISPB_WIN1H: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_H1(SubScreen.gpu,val);
-			break ; 	 
-		case REG_DISPB_WIN1H+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_H0(SubScreen.gpu,val);
-			break ;
-
-		case REG_DISPA_WIN0V: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WIN0V+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WIN1V: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WIN1V+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(MainScreen.gpu,val) ; 	 
-			break ; 	 
-
-		case REG_DISPB_WIN0V: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(SubScreen.gpu,val) ;
-			break ; 	 
-		case REG_DISPB_WIN0V+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(SubScreen.gpu,val) ;
-			break ; 	 
-		case REG_DISPB_WIN1V: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(SubScreen.gpu,val) ;
-			break ; 	 
-		case REG_DISPB_WIN1V+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(SubScreen.gpu,val) ;
-			break ;
-
-		case REG_DISPA_WININ: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWININ0(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WININ+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWININ1(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WINOUT: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWINOUT(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPA_WINOUT+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWINOBJ(MainScreen.gpu,val);
-			break ; 	 
-
-		case REG_DISPB_WININ: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWININ0(SubScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPB_WININ+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWININ1(SubScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPB_WINOUT: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWINOUT(SubScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPB_WINOUT+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setWINOBJ(SubScreen.gpu,val) ; 	 
-			break ;
-
-
-		case REG_DISPA_BLDCNT:
-			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH(MainScreen.gpu,val);
-			break;
-		case REG_DISPA_BLDCNT+1:
-			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (MainScreen.gpu,val);
-			break;
-
-		case REG_DISPB_BLDCNT: 	 
-			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH (SubScreen.gpu,val);
-			break;
-		case REG_DISPB_BLDCNT+1: 	 
-			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (SubScreen.gpu,val);
-			break;
-
-		case REG_DISPA_BLDALPHA: 	 
-			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(MainScreen.gpu,val) ; 	 
-			break;
-		case REG_DISPA_BLDALPHA+1:
-			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(MainScreen.gpu,val) ; 	 
-			break;
-
-		case REG_DISPB_BLDALPHA:
-			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(SubScreen.gpu,val) ; 	 
-			break;
-		case REG_DISPB_BLDALPHA+1:
-			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(SubScreen.gpu,val);
-			break;
-
-		case REG_DISPA_BLDY: 	 
-			if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; 	 
-			break ; 	 
-		case REG_DISPB_BLDY: 	 
-			if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; 	 
-			break;
-
-		/* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */
-		/* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */
-		case REG_VRAMCNTA:
-		case REG_VRAMCNTB:
-		case REG_VRAMCNTC:
-		case REG_VRAMCNTD:
-			if(proc == ARMCPU_ARM9)
-			{
-                MMU_VRAMWriteBackToLCD(0) ;
-                MMU_VRAMWriteBackToLCD(1) ;
-                MMU_VRAMWriteBackToLCD(2) ;
-                MMU_VRAMWriteBackToLCD(3) ;
-				switch(val & 0x1F)
-				{
-				case 1 :
-					MMU.vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM
-					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*0); // BG-VRAM
-					break;
-				case 1 | (1 << 3) :
-					MMU.vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM
-					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*1); // BG-VRAM
-					break;
-				case 1 | (2 << 3) :
-					MMU.vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM
-					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*2); // BG-VRAM
-					break;
-				case 1 | (3 << 3) :
-					MMU.vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM
-					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*3); // BG-VRAM
-					break;
-				case 0: /* mapped to lcd */
-                    MMU.vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ;
-					break ;
-				}
-                                /*
-                                 * FIXME: simply texture slot handling
-                                 * This is a first stab and is not correct. It does
-                                 * not handle a VRAM texture slot becoming
-                                 * unconfigured.
-                                 * Revisit all of VRAM control handling for future
-                                 * release?
-                                 */
-                                if ( val & 0x80) {
-                                  if ( (val & 0x7) == 3) {
-                                    int slot_index = (val >> 3) & 0x3;
-
-                                    ARM9Mem.textureSlotAddr[slot_index] =
-                                      &ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)];
-                                  }
-                                }
-                MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ;
-			}
-			break;
-                case REG_VRAMCNTE :
-			if(proc == ARMCPU_ARM9)
-			{
-                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTE) ;
-                                if((val & 7) == 5)
-				{
-					ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000;
-					ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000;
-					ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000;
-					ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000;
-				}
-                                else if((val & 7) == 3)
-				{
-					ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x80000;
-					ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x82000;
-					ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x84000;
-					ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x86000;
-				}
-                                else if((val & 7) == 4)
-				{
-					ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000;
-					ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000;
-					ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000;
-					ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000;
-				}
-				
-				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTE,val) ;
-			}
-			break;
-		
-                case REG_VRAMCNTF :
-			if(proc == ARMCPU_ARM9)
-			{
-				switch(val & 0x1F)
-				{
-                                        case 4 :
-						ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000;
-						ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000;
-						break;
-						
-                                        case 4 | (1 << 3) :
-						ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x90000;
-						ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x92000;
-						break;
-						
-                                        case 3 :
-						ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x90000;
-						break;
-						
-                                        case 3 | (1 << 3) :
-						ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x90000;
-						break;
-						
-                                        case 3 | (2 << 3) :
-						ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x90000;
-						break;
-						
-                                        case 3 | (3 << 3) :
-						ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x90000;
-						break;
-						
-                                        case 5 :
-                                        case 5 | (1 << 3) :
-                                        case 5 | (2 << 3) :
-                                        case 5 | (3 << 3) :
-						ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000;
-						ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000;
-						break;
-				}
-		 	}
-			break;
-                case REG_VRAMCNTG :
-			if(proc == ARMCPU_ARM9)
-			{
-		 		switch(val & 0x1F)
-				{
-                                        case 4 :
-						ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000;
-						ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000;
-						break;
-						
-                                        case 4 | (1 << 3) :
-						ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x94000;
-						ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x96000;
-						break;
-						
-                                        case 3 :
-						ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x94000;
-						break;
-						
-                                        case 3 | (1 << 3) :
-						ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x94000;
-						break;
-						
-                                        case 3 | (2 << 3) :
-						ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x94000;
-						break;
-						
-                                        case 3 | (3 << 3) :
-						ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x94000;
-						break;
-						
-                                        case 5 :
-                                        case 5 | (1 << 3) :
-                                        case 5 | (2 << 3) :
-                                        case 5 | (3 << 3) :
-						ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000;
-						ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000;
-						break;
-				}
-			}
-			break;
-			
-                case REG_VRAMCNTH  :
-			if(proc == ARMCPU_ARM9)
-			{
-                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTH) ;
-                
-                                if((val & 7) == 2)
-				{
-					ARM9Mem.ExtPal[1][0] = ARM9Mem.ARM9_LCD + 0x98000;
-					ARM9Mem.ExtPal[1][1] = ARM9Mem.ARM9_LCD + 0x9A000;
-					ARM9Mem.ExtPal[1][2] = ARM9Mem.ARM9_LCD + 0x9C000;
-					ARM9Mem.ExtPal[1][3] = ARM9Mem.ARM9_LCD + 0x9E000;
-				}
-				
-				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTH,val) ;
-			}
-			break;
-			
-                case REG_VRAMCNTI  :
-			if(proc == ARMCPU_ARM9)
-			{
-                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTI) ;
-                
-                                if((val & 7) == 3)
-				{
-					ARM9Mem.ObjExtPal[1][0] = ARM9Mem.ARM9_LCD + 0xA0000;
-					ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD + 0xA2000;
-				}
-				
-				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTI,val) ;
-			}
-			break;
-
-#ifdef LOG_CARD
-		case 0x040001A0 : /* TODO (clear): ??? */
-		case 0x040001A1 :
-		case 0x040001A2 :
-		case 0x040001A8 :
-		case 0x040001A9 :
-		case 0x040001AA :
-		case 0x040001AB :
-		case 0x040001AC :
-		case 0x040001AD :
-		case 0x040001AE :
-		case 0x040001AF :
-                    LOG("%08X : %02X\r\n", adr, val);
-#endif
-		
-		default :
-			break;
-	}
-	
-	MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]=val;
-}
-
-u16 partie = 1;
-
-void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val)
-{
-#ifdef INTERNAL_DTCM_WRITE
-	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
-	{
-		/* Writes in DTCM (ARM9 only) */
-		T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
-		return;
-	}
-#endif
-	
-	// CFlash writing, Mic
-	if ((adr>=0x08800000)&&(adr<0x09900000))
-	{
-		cflash_write(adr,val);
-		return;
-	}
-
-#ifdef EXPERIMENTAL_WIFI
-
-	/* wifi mac access */
-	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
-	{
-		WIFI_write16(&wifiMac,adr,val) ;
-		return ;
-	}
-#else
-	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
-		return ;
-#endif
-
-	adr &= 0x0FFFFFFF;
-
-        // This is bad, remove it
-        if(proc == ARMCPU_ARM7)
-        {
-           if ((adr>=0x04000400)&&(adr<0x0400051D))
-           {
-              SPU_WriteWord(adr, val);
-              return;
-           }
-        }
-
-	if((adr >> 24) == 4)
-	{
-		/* Adress is an IO register */
-		switch(adr)
-		{
-#if VIO2SF_GPU_ENABLE
-			case 0x0400035C:
-			{
-				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>1] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_FogOffset (val);
-				}
-				return;
-			}
-			case 0x04000340:
-			{
-				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>1] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_AlphaFunc(val);
-				}
-				return;
-			}
-			case 0x04000060:
-			{
-				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x060>>1] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Control(val);
-				}
-				return;
-			}
-			case 0x04000354:
-			{
-				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>1] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_ClearDepth(val);
-				}
-				return;
-			}
-#endif
-
-			case REG_DISPA_BLDCNT: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDCNT(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_BLDCNT: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDCNT(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_BLDALPHA: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_BLDALPHA: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_BLDY: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_BLDY: 	 
-				if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; 	 
-				break;
-			case REG_DISPA_MASTERBRIGHT:
-				GPU_setMasterBrightness (MainScreen.gpu, val);
-				break;
-				/*
-			case REG_DISPA_MOSAIC: 	 
-				if(proc == ARMCPU_ARM9) GPU_setMOSAIC(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_MOSAIC: 	 
-				if(proc == ARMCPU_ARM9) GPU_setMOSAIC(SubScreen.gpu,val) ; 	 
-				break ;
-				*/
-
-			case REG_DISPA_WIN0H: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN0_H (MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_WIN1H: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN1_H(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_WIN0H: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN0_H(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_WIN1H: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN1_H(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_WIN0V: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN0_V(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_WIN1V: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN1_V(MainScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_WIN0V: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN0_V(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPB_WIN1V: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWIN1_V(SubScreen.gpu,val) ; 	 
-				break ; 	 
-			case REG_DISPA_WININ: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWININ(MainScreen.gpu, val) ; 	 
-				break ; 	 
-			case REG_DISPA_WINOUT: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWINOUT16(MainScreen.gpu, val) ; 	 
-				break ; 	 
-			case REG_DISPB_WININ: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWININ(SubScreen.gpu, val) ; 	 
-				break ; 	 
-			case REG_DISPB_WINOUT: 	 
-				if(proc == ARMCPU_ARM9) GPU_setWINOUT16(SubScreen.gpu, val) ; 	 
-				break ;
-
-			case REG_DISPB_MASTERBRIGHT:
-				GPU_setMasterBrightness (SubScreen.gpu, val);
-				break;
-			
-            case REG_POWCNT1 :
-				if(proc == ARMCPU_ARM9)
-				{
-					if(val & (1<<15))
-					{
-						LOG("Main core on top\n");
-						MainScreen.offset = 0;
-						SubScreen.offset = 192;
-						//nds.swapScreen();
-					}
-					else
-					{
-						LOG("Main core on bottom (%04X)\n", val);
-						MainScreen.offset = 192;
-						SubScreen.offset = 0;
-					}
-				}
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val);
-				return;
-
-                        case REG_AUXSPICNT:
-                                T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff, val);
-                                AUX_SPI_CNT = val;
-
-                                if (val == 0)
-                                   mc_reset_com(&MMU.bupmem);     /* reset backup memory device communication */
-				return;
-				
-                        case REG_AUXSPIDATA:
-                                if(val!=0)
-                                {
-                                   AUX_SPI_CMD = val & 0xFF;
-                                }
-
-                                T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
-				return;
-
-			case REG_SPICNT :
-				if(proc == ARMCPU_ARM7)
-				{
-                                  int reset_firmware = 1;
-
-                                  if ( ((SPI_CNT >> 8) & 0x3) == 1) {
-                                    if ( ((val >> 8) & 0x3) == 1) {
-                                      if ( BIT11(SPI_CNT)) {
-                                        /* select held */
-                                        reset_firmware = 0;
-                                      }
-                                    }
-                                  }
-					
-                                        //MMU.fw.com == 0; /* reset fw device communication */
-                                    if ( reset_firmware) {
-                                      /* reset fw device communication */
-                                      mc_reset_com(&MMU.fw);
-                                    }
-                                    SPI_CNT = val;
-                                }
-				
-				T1WriteWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val);
-				return;
-				
-			case REG_SPIDATA :
-				if(proc==ARMCPU_ARM7)
-				{
-                                        u16 spicnt;
-
-					if(val!=0)
-					{
-						SPI_CMD = val;
-					}
-			
-                                        spicnt = T1ReadWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff);
-					
-                                        switch((spicnt >> 8) & 0x3)
-					{
-                                                case 0 :
-							break;
-							
-                                                case 1 : /* firmware memory device */
-                                                        if((spicnt & 0x3) != 0)      /* check SPI baudrate (must be 4mhz) */
-							{
-								T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0);
-								break;
-							}
-							T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, val));
-
-							return;
-							
-                                                case 2 :
-							switch(SPI_CMD & 0x70)
-							{
-								case 0x00 :
-									val = 0;
-									break;
-								case 0x10 :
-									//execute = FALSE;
-									if(SPI_CNT&(1<<11))
-									{
-										if(partie)
-										{
-											val = ((nds.touchY<<3)&0x7FF);
-											partie = 0;
-											//execute = FALSE;
-											break;
-										}
-										val = (nds.touchY>>5);
-                                                                                partie = 1;
-										break;
-									}
-									val = ((nds.touchY<<3)&0x7FF);
-									partie = 1;
-									break;
-								case 0x20 :
-									val = 0;
-									break;
-								case 0x30 :
-									val = 0;
-									break;
-								case 0x40 :
-									val = 0;
-									break;
-								case 0x50 :
-                                                                        if(spicnt & 0x800)
-									{
-										if(partie)
-										{
-											val = ((nds.touchX<<3)&0x7FF);
-											partie = 0;
-											break;
-										}
-										val = (nds.touchX>>5);
-										partie = 1;
-										break;
-									}
-									val = ((nds.touchX<<3)&0x7FF);
-									partie = 1;
-									break;
-								case 0x60 :
-									val = 0;
-									break;
-								case 0x70 :
-									val = 0;
-									break;
-							}
-							break;
-							
-                                                case 3 :
-							/* NOTICE: Device 3 of SPI is reserved (unused and unusable) */
-							break;
-					}
-				}
-				
-				T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val);
-				return;
-				
-				/* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/
-				
-                        case REG_DISPA_BG0CNT :
-				//GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 0, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x8, val);
-				return;
-                        case REG_DISPA_BG1CNT :
-				//GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 1, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xA, val);
-				return;
-                        case REG_DISPA_BG2CNT :
-				//GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 2, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC, val);
-				return;
-                        case REG_DISPA_BG3CNT :
-				//GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 3, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xE, val);
-				return;
-                        case REG_DISPB_BG0CNT :
-				//GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 0, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x1008, val);
-				return;
-                        case REG_DISPB_BG1CNT :
-				//GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 1, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100A, val);
-				return;
-                        case REG_DISPB_BG2CNT :
-				//GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 2, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100C, val);
-				return;
-                        case REG_DISPB_BG3CNT :
-				//GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val);
-				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 3, val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100E, val);
-				return;
-                        case REG_IME : {
-			        u32 old_val = MMU.reg_IME[proc];
-				u32 new_val = val & 1;
-				MMU.reg_IME[proc] = new_val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val);
-				if ( new_val && old_val != new_val) {
-				  /* raise an interrupt request to the CPU if needed */
-				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
-				    NDS_ARM7.wIRQ = TRUE;
-				    NDS_ARM7.waitIRQ = FALSE;
-				  }
-				}
-				return;
-			}
-			case REG_VRAMCNTA:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				MMU_write8(proc,adr+1,val >> 8) ;
-				return ;
-			case REG_VRAMCNTC:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				MMU_write8(proc,adr+1,val >> 8) ;
-				return ;
-			case REG_VRAMCNTE:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				MMU_write8(proc,adr+1,val >> 8) ;
-				return ;
-			case REG_VRAMCNTG:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				MMU_write8(proc,adr+1,val >> 8) ;
-				return ;
-			case REG_VRAMCNTI:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				return ;
-
-			case REG_IE :
-				MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF0000) | val;
-				if ( MMU.reg_IME[proc]) {
-				  /* raise an interrupt request to the CPU if needed */
-				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
-				    NDS_ARM7.wIRQ = TRUE;
-				    NDS_ARM7.waitIRQ = FALSE;
-				  }
-				}
-				return;
-			case REG_IE + 2 :
-				execute = FALSE;
-				MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF) | (((u32)val)<<16);
-				return;
-				
-			case REG_IF :
-				execute = FALSE;
-				MMU.reg_IF[proc] &= (~((u32)val)); 
-				return;
-			case REG_IF + 2 :
-				execute = FALSE;
-				MMU.reg_IF[proc] &= (~(((u32)val)<<16));
-				return;
-				
-                        case REG_IPCSYNC :
-				{
-				u32 remote = (proc+1)&1;
-				u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
-				T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
-				MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));// 
-				//execute = FALSE;
-				}
-				return;
-                        case REG_IPCFIFOCNT :
-				{
-					u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
-					u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
-					if ((val & 0x8000) && !(cnt_l & 0x8000))
-					{
-						/* this is the first init, the other side didnt init yet */
-						/* so do a complete init */
-						FIFOInit(MMU.fifos + (IPCFIFO+proc));
-						T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ;
-						/* and then handle it as usual */
-					}
-
-				if(val & 0x4008)
-				{
-					FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1)));
-					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
-					T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
-					MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);//
-					return;
-				}
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4));
-				}
-				return;
-                        case REG_TM0CNTL :
-                        case REG_TM1CNTL :
-                        case REG_TM2CNTL :
-                        case REG_TM3CNTL :
-				MMU.timerReload[proc][(adr>>2)&3] = val;
-				return;
-                        case REG_TM0CNTH :
-                        case REG_TM1CNTH :
-                        case REG_TM2CNTH :
-                        case REG_TM3CNTH :
-				if(val&0x80)
-				{
-				  MMU.timer[proc][((adr-2)>>2)&0x3] = MMU.timerReload[proc][((adr-2)>>2)&0x3];
-				}
-				MMU.timerON[proc][((adr-2)>>2)&0x3] = val & 0x80;
-				switch(val&7)
-				{
-				case 0 :
-					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0+1;//proc;
-					break;
-				case 1 :
-					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 6+1;//proc; 
-					break;
-				case 2 :
-					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 8+1;//proc;
-					break;
-				case 3 :
-					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 10+1;//proc;
-					break;
-				default :
-					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0xFFFF;
-					break;
-				}
-				if(!(val & 0x80))
-				MMU.timerRUN[proc][((adr-2)>>2)&0x3] = FALSE;
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val);
-				return;
-                        case REG_DISPA_DISPCNT+2 : 
-				{
-				//execute = FALSE;
-				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF) | ((u32) val << 16);
-				GPU_setVideoProp(MainScreen.gpu, v);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v);
-				}
-				return;
-                        case REG_DISPA_DISPCNT :
-				if(proc == ARMCPU_ARM9)
-				{
-				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF0000) | val;
-				GPU_setVideoProp(MainScreen.gpu, v);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v);
-				}
-				return;
-                        case REG_DISPA_DISPCAPCNT :
-				if(proc == ARMCPU_ARM9)
-				{
-					GPU_set_DISPCAPCNT(MainScreen.gpu,val);
-				}
-				return;
-                        case REG_DISPB_DISPCNT+2 : 
-				if(proc == ARMCPU_ARM9)
-				{
-				//execute = FALSE;
-				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16);
-				GPU_setVideoProp(SubScreen.gpu, v);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v);
-				}
-				return;
-                        case REG_DISPB_DISPCNT :
-				{
-				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF0000) | val;
-				GPU_setVideoProp(SubScreen.gpu, v);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v);
-				}
-				return;
-			//case 0x020D8460 :
-			/*case 0x0235A904 :
-				LOG("ECRIRE %d %04X\r\n", proc, val);
-				execute = FALSE;*/
-                                case REG_DMA0CNTH :
-				{
-                                u32 v;
-
-				//if(val&0x8000) execute = FALSE;
-				//LOG("16 bit dma0 %04X\r\n", val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xBA, val);
-				DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0);
-				DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4);
-                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8);
-				MMU.DMAStartTime[proc][0] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
-				MMU.DMACrt[proc][0] = v;
-				if(MMU.DMAStartTime[proc][0] == 0)
-					MMU_doDMA(proc, 0);
-				#ifdef LOG_DMA2
-				//else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], (val&(1<<25))?"ON":"OFF");
-				}
-				#endif
-				}
-				return;
-                                case REG_DMA1CNTH :
-				{
-                                u32 v;
-				//if(val&0x8000) execute = FALSE;
-				//LOG("16 bit dma1 %04X\r\n", val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC6, val);
-				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC);
-				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0);
-                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC4);
-				MMU.DMAStartTime[proc][1] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
-				MMU.DMACrt[proc][1] = v;
-				if(MMU.DMAStartTime[proc][1] == 0)
-					MMU_doDMA(proc, 1);
-				#ifdef LOG_DMA2
-				//else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], (val&(1<<25))?"ON":"OFF");
-				}
-				#endif
-				}
-				return;
-                                case REG_DMA2CNTH :
-				{
-                                u32 v;
-				//if(val&0x8000) execute = FALSE;
-				//LOG("16 bit dma2 %04X\r\n", val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xD2, val);
-				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8);
-				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC);
-                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD0);
-				MMU.DMAStartTime[proc][2] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
-				MMU.DMACrt[proc][2] = v;
-				if(MMU.DMAStartTime[proc][2] == 0)
-					MMU_doDMA(proc, 2);
-				#ifdef LOG_DMA2
-				//else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], (val&(1<<25))?"ON":"OFF");
-				}
-				#endif
-				}
-				return;
-                                case REG_DMA3CNTH :
-				{
-                                u32 v;
-				//if(val&0x8000) execute = FALSE;
-				//LOG("16 bit dma3 %04X\r\n", val);
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xDE, val);
-				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4);
-				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8);
-                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xDC);
-				MMU.DMAStartTime[proc][3] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
-				MMU.DMACrt[proc][3] = v;
-		
-				if(MMU.DMAStartTime[proc][3] == 0)
-					MMU_doDMA(proc, 3);
-				#ifdef LOG_DMA2
-				//else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], (val&(1<<25))?"ON":"OFF");
-				}
-				#endif
-				}
-				return;
-                        //case REG_AUXSPICNT : execute = FALSE;
-			default :
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); 
-				return;
-		}
-	}
-	T1WriteWord(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
-} 
-
-
-void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val)
-{
-#ifdef INTERNAL_DTCM_WRITE
-	if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion))
-	{
-		T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
-		return ;
-	}
-#endif
-	
-	// CFlash writing, Mic
-	if ((adr>=0x9000000)&&(adr<0x9900000)) {
-	   cflash_write(adr,val);
-	   return;
-	}
-
-	adr &= 0x0FFFFFFF;
-
-        // This is bad, remove it
-        if(proc == ARMCPU_ARM7)
-        {
-           if ((adr>=0x04000400)&&(adr<0x0400051D))
-           {
-              SPU_WriteLong(adr, val);
-              return;
-           }
-        }
-
-		if ((adr & 0xFF800000) == 0x04800000) {
-		/* access to non regular hw registers */
-		/* return to not overwrite valid data */
-			return ;
-		} ;
-
-
-	if((adr>>24)==4)
-	{
-		if (adr >= 0x04000400 && adr < 0x04000440)
-		{
-			// Geometry commands (aka Dislay Lists) - Parameters:X
-			((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x400>>2] = val;
-#if VIO2SF_GPU_ENABLE
-			if(proc==ARMCPU_ARM9)
-			{
-				gpu3D->NDS_3D_CallList(val);
-			}
-#endif
-		}
-		else
-		switch(adr)
-		{
-#if VIO2SF_GPU_ENABLE
-			// Alpha test reference value - Parameters:1
-			case 0x04000340:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_AlphaFunc(val);
-				}
-				return;
-			}
-			// Clear background color setup - Parameters:2
-			case 0x04000350:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x350>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_ClearColor(val);
-				}
-				return;
-			}
-			// Clear background depth setup - Parameters:2
-			case 0x04000354:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_ClearDepth(val);
-				}
-				return;
-			}
-			// Fog Color - Parameters:4b
-			case 0x04000358:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x358>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_FogColor(val);
-				}
-				return;
-			}
-			case 0x0400035C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_FogOffset(val);
-				}
-				return;
-			}
-			// Matrix mode - Parameters:1
-			case 0x04000440:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x440>>2] = val;
-
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_MatrixMode(val);
-				}
-				return;
-			}
-			// Push matrix - Parameters:0
-			case 0x04000444:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x444>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_PushMatrix();
-				}
-				return;
-			}
-			// Pop matrix/es - Parameters:1
-			case 0x04000448:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x448>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_PopMatrix(val);
-				}
-				return;
-			}
-			// Store matrix in the stack - Parameters:1
-			case 0x0400044C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x44C>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_StoreMatrix(val);
-				}
-				return;
-			}
-			// Restore matrix from the stack - Parameters:1
-			case 0x04000450:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x450>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_RestoreMatrix(val);
-				}
-				return;
-			}
-			// Load Identity matrix - Parameters:0
-			case 0x04000454:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x454>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_LoadIdentity();
-				}
-				return;
-			}
-			// Load 4x4 matrix - Parameters:16
-			case 0x04000458:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x458>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_LoadMatrix4x4(val);
-				}
-				return;
-			}
-			// Load 4x3 matrix - Parameters:12
-			case 0x0400045C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x45C>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_LoadMatrix4x3(val);
-				}
-				return;
-			}
-			// Multiply 4x4 matrix - Parameters:16
-			case 0x04000460:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x460>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_MultMatrix4x4(val);
-				}
-				return;
-			}
-			// Multiply 4x4 matrix - Parameters:12
-			case 0x04000464:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x464>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_MultMatrix4x3(val);
-				}
-				return;
-			}
-			// Multiply 3x3 matrix - Parameters:9
-			case 0x04000468 :
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x468>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_MultMatrix3x3(val);
-				}
-				return;
-			}
-			// Multiply current matrix by scaling matrix - Parameters:3
-			case 0x0400046C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x46C>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Scale(val);
-				}
-				return;
-			}
-			// Multiply current matrix by translation matrix - Parameters:3
-			case 0x04000470:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x470>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Translate(val);
-				}
-				return;
-			}
-			// Set vertex color - Parameters:1
-			case 0x04000480:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x480>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Color3b(val);
-				}
-				return;
-			}
-			// Set vertex normal - Parameters:1
-			case 0x04000484:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x484>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Normal(val);
-				}
-				return;
-			}
-			// Set vertex texture coordinate - Parameters:1
-			case 0x04000488:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x488>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_TexCoord(val);
-				}
-				return;
-			}
-			// Set vertex position 16b/coordinate - Parameters:2
-			case 0x0400048C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x48C>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Vertex16b(val);
-				}
-				return;
-			}
-			// Set vertex position 10b/coordinate - Parameters:1
-			case 0x04000490:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x490>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Vertex10b(val);
-				}
-				return;
-			}
-			// Set vertex XY position - Parameters:1
-			case 0x04000494:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x494>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-                    gpu3D->NDS_3D_Vertex3_cord(0,1,val);
-				}
-				return;
-			}
-			// Set vertex XZ position - Parameters:1
-			case 0x04000498:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x498>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-                    gpu3D->NDS_3D_Vertex3_cord(0,2,val);
-				}
-				return;
-			}
-			// Set vertex YZ position - Parameters:1
-			case 0x0400049C:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x49C>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-                    gpu3D->NDS_3D_Vertex3_cord(1,2,val);
-				}
-				return;
-			}
-			// Set vertex difference position (offset from the last vertex) - Parameters:1
-			case 0x040004A0:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A0>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-                    gpu3D->NDS_3D_Vertex_rel (val);
-				}
-				return;
-			}
-			// Set polygon attributes - Parameters:1
-			case 0x040004A4:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A4>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_PolygonAttrib(val);
-				}
-				return;
-			}
-			// Set texture parameteres - Parameters:1
-			case 0x040004A8:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A8>>2] = val;
-				if(proc==ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_TexImage(val);
-				}
-				return;
-			}
-			// Set palette base address - Parameters:1
-			case 0x040004AC:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4AC>>2] = val&0x1FFF;
-				if(proc==ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_TexPalette(val&0x1FFFF);
-				}
-				return;
-			}
-			// Set material diffuse/ambient parameters - Parameters:1
-			case 0x040004C0:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C0>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Material0 (val);
-				}
-				return;
-			}
-			// Set material reflection/emission parameters - Parameters:1
-			case 0x040004C4:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C4>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Material1 (val);
-				}
-				return;
-			}
-			// Light direction vector - Parameters:1
-			case 0x040004C8:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C8>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_LightDirection (val);
-				}
-				return;
-			}
-			// Light color - Parameters:1
-			case 0x040004CC:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4CC>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_LightColor(val);
-				}
-				return;
-			}
-			// Material Shininess - Parameters:32
-			case 0x040004D0:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4D0>>2] = val;
-                if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Shininess(val);
-				}
-				return;
-			}
-			// Begin vertex list - Parameters:1
-			case 0x04000500:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x500>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Begin(val);
-				}
-				return;
-			}
-			// End vertex list - Parameters:0
-			case 0x04000504:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x504>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_End();
-				}
-				return;
-			}
-			// Swap rendering engine buffers - Parameters:1
-			case 0x04000540:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x540>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_Flush(val);
-				}
-				return;
-			}
-			// Set viewport coordinates - Parameters:1
-			case 0x04000580:
-			{
-				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x580>>2] = val;
-				if(proc == ARMCPU_ARM9)
-				{
-					gpu3D->NDS_3D_ViewPort(val);
-				}
-				return;
-			}
-#endif
-
-			case REG_DISPA_WININ: 	 
-			{
-	            if(proc == ARMCPU_ARM9) 	 
-	            { 	 
-	                    GPU_setWININ	(MainScreen.gpu, val & 0xFFFF) ; 	 
-	                    GPU_setWINOUT16	(MainScreen.gpu, (val >> 16) & 0xFFFF) ; 	 
-	            } 	 
-	            break;
-			}
-			case REG_DISPB_WININ:
-			{
-	            if(proc == ARMCPU_ARM9) 	 
-	            { 	 
-	                    GPU_setWININ	(SubScreen.gpu, val & 0xFFFF) ; 	 
-	                    GPU_setWINOUT16	(SubScreen.gpu, (val >> 16) & 0xFFFF) ; 	 
-	            } 	 
-	            break;
-			}
-
-			case REG_DISPA_BLDCNT:
-			{
-				if (proc == ARMCPU_ARM9) 	 
-				{ 	 
-					GPU_setBLDCNT   (MainScreen.gpu,val&0xffff);
-					GPU_setBLDALPHA (MainScreen.gpu,val>>16);
-				}
-				break;
-			}
-			case REG_DISPB_BLDCNT:
-			{
-				if (proc == ARMCPU_ARM9) 	 
-				{ 	 
-					GPU_setBLDCNT   (SubScreen.gpu,val&0xffff);
-					GPU_setBLDALPHA (SubScreen.gpu,val>>16);
-				}
-				break;
-			}
-/*
- // Commented out, as this doesn't use the plug-in system, neither works
-			case cmd_3D_MTX_MODE        // 0x04000440 :
-				if (proc == ARMCPU_ARM9) gl_MTX_MODE(val);
-				return;
-			case cmd_3D_MTX_PUSH        // 0x04000444  :
-			case cmd_3D_MTX_POP         // 0x04000448  :
-			case cmd_3D_MTX_STORE       // 0x0400044C  :
-			case cmd_3D_MTX_RESTORE     // 0x04000450  :
-				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
-				return;
-			case cmd_3D_MTX_IDENTITY    // 0x04000454  :
-				if (proc == ARMCPU_ARM9) gl_MTX_IDENTITY();
-				return;
-			case cmd_3D_MTX_LOAD_4x4    // 0x04000458  :
-				if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x4(val);
-				return;
-			case cmd_3D_MTX_LOAD_4x3    // 0x0400045C  :
-				if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x3(val);
-				return;
-			case cmd_3D_MTX_MULT_4x4    // 0x04000460  :
-				if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x4(val);
-				return;
-			case cmd_3D_MTX_MULT_4x3    // 0x04000464  :
-				if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x3(val);
-				return;
-			case cmd_3D_MTX_MULT_3x3    // 0x04000468  :
-				if (proc == ARMCPU_ARM9) gl_MTX_MULT_3x3(val);
-				return;
-			case cmd_3D_MTX_SCALE       // 0x0400046C  :
-			case cmd_3D_MTX_TRANS       // 0x04000470  :
-			case cmd_3D_COLOR           // 0x04000480  :
-			case cmd_3D_NORMA           // 0x04000484  :
-				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
-				return;
-			case cmd_3D_TEXCOORD        // 0x04000488  :
-				if (proc == ARMCPU_ARM9) gl_TEXCOORD(val);
-				return;
-			case cmd_3D_VTX_16          // 0x0400048C  :
-				if (proc == ARMCPU_ARM9) gl_VTX_16(val);
-				return;
-			case cmd_3D_VTX_10          // 0x04000490  :
-				if (proc == ARMCPU_ARM9) gl_VTX_10(val);
-				return;
-			case cmd_3D_VTX_XY          // 0x04000494  :
-				if (proc == ARMCPU_ARM9) gl_VTX_XY(val);
-				return;
-			case cmd_3D_VTX_XZ          // 0x04000498  :
-				if (proc == ARMCPU_ARM9) gl_VTX_XZ(val);
-				return;
-			case cmd_3D_VTX_YZ          // 0x0400049C  :
-				if (proc == ARMCPU_ARM9) gl_VTX_YZ(val);
-				return;
-			case cmd_3D_VTX_DIFF        // 0x040004A0  :
-				if (proc == ARMCPU_ARM9) gl_VTX_DIFF(val);
-				return;
-			case cmd_3D_POLYGON_ATTR    // 0x040004A4  :
-			case cmd_3D_TEXIMAGE_PARAM  // 0x040004A8  :
-			case cmd_3D_PLTT_BASE       // 0x040004AC  :
-			case cmd_3D_DIF_AMB         // 0x040004C0  :
-			case cmd_3D_SPE_EMI         // 0x040004C4  :
-			case cmd_3D_LIGHT_VECTOR    // 0x040004C8  :
-			case cmd_3D_LIGHT_COLOR     // 0x040004CC  :
-			case cmd_3D_SHININESS       // 0x040004D0  :
-				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
-				return;
-			case cmd_3D_BEGIN_VTXS      // 0x04000500  :
-				if (proc == ARMCPU_ARM9) gl_VTX_begin(val);
-				return;
-			case cmd_3D_END_VTXS        // 0x04000504  :
-				if (proc == ARMCPU_ARM9) gl_VTX_end();
-				return;
-			case cmd_3D_SWAP_BUFFERS    // 0x04000540  :
-			case cmd_3D_VIEWPORT        // 0x04000580  :
-			case cmd_3D_BOX_TEST        // 0x040005C0  :
-			case cmd_3D_POS_TEST        // 0x040005C4  :
-			case cmd_3D_VEC_TEST        // 0x040005C8  :
-				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
-				return;
-*/
-                        case REG_DISPA_DISPCNT :
-								if(proc == ARMCPU_ARM9) GPU_setVideoProp(MainScreen.gpu, val);
-				
-				//GPULOG("MAIN INIT 32B %08X\r\n", val);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, val);
-				return;
-				
-                        case REG_DISPB_DISPCNT : 
-				if (proc == ARMCPU_ARM9) GPU_setVideoProp(SubScreen.gpu, val);
-				//GPULOG("SUB INIT 32B %08X\r\n", val);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, val);
-				return;
-			case REG_VRAMCNTA:
-			case REG_VRAMCNTE:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				MMU_write8(proc,adr+1,val >> 8) ;
-				MMU_write8(proc,adr+2,val >> 16) ;
-				MMU_write8(proc,adr+3,val >> 24) ;
-				return ;
-			case REG_VRAMCNTI:
-				MMU_write8(proc,adr,val & 0xFF) ;
-				return ;
-
-                        case REG_IME : {
-			        u32 old_val = MMU.reg_IME[proc];
-				u32 new_val = val & 1;
-				MMU.reg_IME[proc] = new_val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val);
-				if ( new_val && old_val != new_val) {
-				  /* raise an interrupt request to the CPU if needed */
-				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
-				    NDS_ARM7.wIRQ = TRUE;
-				    NDS_ARM7.waitIRQ = FALSE;
-				  }
-				}
-				return;
-			}
-				
-			case REG_IE :
-				MMU.reg_IE[proc] = val;
-				if ( MMU.reg_IME[proc]) {
-				  /* raise an interrupt request to the CPU if needed */
-				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
-				    NDS_ARM7.wIRQ = TRUE;
-				    NDS_ARM7.waitIRQ = FALSE;
-				  }
-				}
-				return;
-			
-			case REG_IF :
-				MMU.reg_IF[proc] &= (~val); 
-				return;
-                        case REG_TM0CNTL :
-                        case REG_TM1CNTL :
-                        case REG_TM2CNTL :
-                        case REG_TM3CNTL :
-				MMU.timerReload[proc][(adr>>2)&0x3] = (u16)val;
-				if(val&0x800000)
-				{
-					MMU.timer[proc][(adr>>2)&0x3] = MMU.timerReload[proc][(adr>>2)&0x3];
-				}
-				MMU.timerON[proc][(adr>>2)&0x3] = val & 0x800000;
-				switch((val>>16)&7)
-				{
-					case 0 :
-					MMU.timerMODE[proc][(adr>>2)&0x3] = 0+1;//proc;
-					break;
-					case 1 :
-					MMU.timerMODE[proc][(adr>>2)&0x3] = 6+1;//proc;
-					break;
-					case 2 :
-					MMU.timerMODE[proc][(adr>>2)&0x3] = 8+1;//proc;
-					break;
-					case 3 :
-					MMU.timerMODE[proc][(adr>>2)&0x3] = 10+1;//proc;
-					break;
-					default :
-					MMU.timerMODE[proc][(adr>>2)&0x3] = 0xFFFF;
-					break;
-				}
-				if(!(val & 0x800000))
-				{
-					MMU.timerRUN[proc][(adr>>2)&0x3] = FALSE;
-				}
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val);
-				return;
-                        case REG_DIVDENOM :
-				{
-                                        u16 cnt;
-					s64 num = 0;
-					s64 den = 1;
-					s64 res;
-					s64 mod;
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x298, val);
-                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280);
-					switch(cnt&3)
-					{
-					case 0:
-					{
-						num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x290);
-						den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298);
-					}
-					break;
-					case 1:
-					{
-						num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290);
-						den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298);
-					}
-					break;
-					case 2:
-					{
-						return;
-					}
-					break;
-					default: 
-						break;
-					}
-					if(den==0)
-					{
-						res = 0;
-						mod = 0;
-						cnt |= 0x4000;
-						cnt &= 0x7FFF;
-					}
-					else
-					{
-						res = num / den;
-						mod = num % den;
-						cnt &= 0x3FFF;
-					}
-					DIVLOG("BOUT1 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, 
-											(u32)(den>>32), (u32)den, 
-											(u32)(res>>32), (u32)res);
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res);
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt);
-				}
-				return;
-                        case REG_DIVDENOM+4 :
-			{
-                                u16 cnt;
-				s64 num = 0;
-				s64 den = 1;
-				s64 res;
-				s64 mod;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x29C, val);
-                                cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280);
-				switch(cnt&3)
-				{
-				case 0:
-				{
-					return;
-				}
-				break;
-				case 1:
-				{
-					return;
-				}
-				break;
-				case 2:
-				{
-					num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290);
-					den = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x298);
-				}
-				break;
-				default: 
-					break;
-				}
-				if(den==0)
-				{
-					res = 0;
-					mod = 0;
-					cnt |= 0x4000;
-					cnt &= 0x7FFF;
-				}
-				else
-				{
-					res = num / den;
-					mod = num % den;
-					cnt &= 0x3FFF;
-				}
-				DIVLOG("BOUT2 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, 
-										(u32)(den>>32), (u32)den, 
-										(u32)(res>>32), (u32)res);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt);
-			}
-			return;
-                        case REG_SQRTPARAM :
-				{
-                                        u16 cnt;
-					u64 v = 1;
-					//execute = FALSE;
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B8, val);
-                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0);
-					switch(cnt&1)
-					{
-					case 0:
-						v = (u64) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B8);
-						break;
-					case 1:
-						return;
-					}
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v));
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
-					SQRTLOG("BOUT1 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, 
-										T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4));
-				}
-				return;
-                        case REG_SQRTPARAM+4 :
-				{
-                                        u16 cnt;
-					u64 v = 1;
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2BC, val);
-                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0);
-					switch(cnt&1)
-					{
-					case 0:
-						return;
-						//break;
-					case 1:
-						v = T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x2B8);
-						break;
-					}
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v));
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
-					SQRTLOG("BOUT2 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, 
-										T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4));
-				}
-				return;
-                        case REG_IPCSYNC :
-				{
-					//execute=FALSE;
-					u32 remote = (proc+1)&1;
-					u32 IPCSYNC_remote = T1ReadLong(MMU.MMU_MEM[remote][0x40], 0x180);
-					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
-					T1WriteLong(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
-					MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));//
-				}
-				return;
-                        case REG_IPCFIFOCNT :
-							{
-					u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
-					u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
-					if ((val & 0x8000) && !(cnt_l & 0x8000))
-					{
-						/* this is the first init, the other side didnt init yet */
-						/* so do a complete init */
-						FIFOInit(MMU.fifos + (IPCFIFO+proc));
-						T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ;
-						/* and then handle it as usual */
-					}
-				if(val & 0x4008)
-				{
-					FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1)));
-					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
-					T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
-					MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);//
-					return;
-				}
-				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4);
-				//execute = FALSE;
-				return;
-							}
-                        case REG_IPCFIFOSEND :
-				{
-					u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
-					if(IPCFIFO_CNT&0x8000)
-					{
-					//if(val==43) execute = FALSE;
-					u32 remote = (proc+1)&1;
-					u32 fifonum = IPCFIFO+remote;
-                                        u16 IPCFIFO_CNT_remote;
-					FIFOAdd(MMU.fifos + fifonum, val);
-					IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (MMU.fifos[fifonum].full<<1);
-                                        IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184);
-					IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (MMU.fifos[fifonum].full<<10);
-					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
-					T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
-					MMU.reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU.reg_IME[remote] << 18);// & (MMU.reg_IE[remote] & 0x40000);//
-					//execute = FALSE;
-					}
-				}
-				return;
-			case REG_DMA0CNTL :
-				//LOG("32 bit dma0 %04X\r\n", val);
-				DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0);
-				DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4);
-				MMU.DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
-				MMU.DMACrt[proc][0] = val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8, val);
-				if( MMU.DMAStartTime[proc][0] == 0 ||
-					MMU.DMAStartTime[proc][0] == 7)		// Start Immediately
-					MMU_doDMA(proc, 0);
-				#ifdef LOG_DMA2
-				else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], 0, ((MMU.DMACrt[proc][0]>>27)&7));
-				}
-				#endif
-				//execute = FALSE;
-				return;
-			case REG_DMA1CNTL:
-				//LOG("32 bit dma1 %04X\r\n", val);
-				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC);
-				DMADst[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0);
-				MMU.DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
-				MMU.DMACrt[proc][1] = val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xC4, val);
-				if(MMU.DMAStartTime[proc][1] == 0 ||
-					MMU.DMAStartTime[proc][1] == 7)		// Start Immediately
-					MMU_doDMA(proc, 1);
-				#ifdef LOG_DMA2
-				else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], 0, ((MMU.DMACrt[proc][1]>>27)&7));
-				}
-				#endif
-				return;
-			case REG_DMA2CNTL :
-				//LOG("32 bit dma2 %04X\r\n", val);
-				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8);
-				DMADst[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC);
-				MMU.DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
-				MMU.DMACrt[proc][2] = val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xD0, val);
-				if(MMU.DMAStartTime[proc][2] == 0 ||
-					MMU.DMAStartTime[proc][2] == 7)		// Start Immediately
-					MMU_doDMA(proc, 2);
-				#ifdef LOG_DMA2
-				else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], 0, ((MMU.DMACrt[proc][2]>>27)&7));
-				}
-				#endif
-				return;
-			case 0x040000DC :
-				//LOG("32 bit dma3 %04X\r\n", val);
-				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4);
-				DMADst[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8);
-				MMU.DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
-				MMU.DMACrt[proc][3] = val;
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xDC, val);
-				if(	MMU.DMAStartTime[proc][3] == 0 ||
-					MMU.DMAStartTime[proc][3] == 7)		// Start Immediately
-					MMU_doDMA(proc, 3);
-				#ifdef LOG_DMA2
-				else
-				{
-					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], 0, ((MMU.DMACrt[proc][3]>>27)&7));
-				}
-				#endif
-				return;
-                        case REG_GCROMCTRL :
-				{
-					int i;
-
-                                        if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7)
-					{
-                                                MMU.dscard[proc].adress = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4));
-						MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7));
-					}
-                                        else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8)
-                                        {
-                                                // Get ROM chip ID
-                                                val |= 0x800000; // Data-Word Status
-                                                T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
-                                                MMU.dscard[proc].adress = 0;
-                                        }
-					else
-					{
-                                                LOG("CARD command: %02X\n", MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT));
-					}
-					
-					//CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]);
-                    val |= 0x00800000;
-					
-					if(MMU.dscard[proc].adress == 0)
-					{
-                                                val &= ~0x80000000; 
-                                                T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
-						return;
-					}
-                                        T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
-										
-					/* launch DMA if start flag was set to "DS Cart" */
-					if(proc == ARMCPU_ARM7) i = 2;
-					else i = 5;
-					
-					if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][0] == i)	/* dma0/1 on arm7 can't start on ds cart event */
-					{
-						MMU_doDMA(proc, 0);
-						return;
-					}
-					else if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][1] == i)
-					{
-						MMU_doDMA(proc, 1);
-						return;
-					}
-					else if(MMU.DMAStartTime[proc][2] == i)
-					{
-						MMU_doDMA(proc, 2);
-						return;
-					}
-					else if(MMU.DMAStartTime[proc][3] == i)
-					{
-						MMU_doDMA(proc, 3);
-						return;
-					}
-					return;
-
-				}
-				return;
-								case REG_DISPA_DISPCAPCNT :
-				if(proc == ARMCPU_ARM9)
-				{
-					GPU_set_DISPCAPCNT(MainScreen.gpu,val);
-					T1WriteLong(ARM9Mem.ARM9_REG, 0x64, val);
-				}
-				return;
-				
-                        case REG_DISPA_BG0CNT :
-				if (proc == ARMCPU_ARM9)
-				{
-					GPU_setBGProp(MainScreen.gpu, 0, (val&0xFFFF));
-					GPU_setBGProp(MainScreen.gpu, 1, (val>>16));
-				}
-				//if((val>>16)==0x400) execute = FALSE;
-				T1WriteLong(ARM9Mem.ARM9_REG, 8, val);
-				return;
-                        case REG_DISPA_BG2CNT :
-				if (proc == ARMCPU_ARM9)
-				{
-					GPU_setBGProp(MainScreen.gpu, 2, (val&0xFFFF));
-					GPU_setBGProp(MainScreen.gpu, 3, (val>>16));
-				}
-				T1WriteLong(ARM9Mem.ARM9_REG, 0xC, val);
-				return;
-                        case REG_DISPB_BG0CNT :
-				if (proc == ARMCPU_ARM9)
-				{
-					GPU_setBGProp(SubScreen.gpu, 0, (val&0xFFFF));
-					GPU_setBGProp(SubScreen.gpu, 1, (val>>16));
-				}
-				T1WriteLong(ARM9Mem.ARM9_REG, 0x1008, val);
-				return;
-                        case REG_DISPB_BG2CNT :
-				if (proc == ARMCPU_ARM9)
-				{
-					GPU_setBGProp(SubScreen.gpu, 2, (val&0xFFFF));
-					GPU_setBGProp(SubScreen.gpu, 3, (val>>16));
-				}
-				T1WriteLong(ARM9Mem.ARM9_REG, 0x100C, val);
-				return;
-			case REG_DISPA_DISPMMEMFIFO:
-			{
-				// NOTE: right now, the capture unit is not taken into account,
-				//       I don't know is it should be handled here or 
-			
-				FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val);
-				break;
-			}
-			//case 0x21FDFF0 :  if(val==0) execute = FALSE;
-			//case 0x21FDFB0 :  if(val==0) execute = FALSE;
-			default :
-				T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
-				return;
-		}
-	}
-	T1WriteLong(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
-}
-
-
-void FASTCALL MMU_doDMA(u32 proc, u32 num)
-{
-	u32 src = DMASrc[proc][num];
-	u32 dst = DMADst[proc][num];
-        u32 taille;
-
-	if(src==dst)
-	{
-		T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num), T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF);
-		return;
-	}
-	
-	if((!(MMU.DMACrt[proc][num]&(1<<31)))&&(!(MMU.DMACrt[proc][num]&(1<<25))))
-	{       /* not enabled and not to be repeated */
-		MMU.DMAStartTime[proc][num] = 0;
-		MMU.DMACycle[proc][num] = 0;
-		//MMU.DMAing[proc][num] = FALSE;
-		return;
-	}
-	
-	
-	/* word count */
-	taille = (MMU.DMACrt[proc][num]&0xFFFF);
-	
-	// If we are in "Main memory display" mode just copy an entire 
-	// screen (256x192 pixels). 
-	//    Reference:  http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
-	//       (under DISP_MMEM_FIFO)
-	if ((MMU.DMAStartTime[proc][num]==4) &&		// Must be in main memory display mode
-		(taille==4) &&							// Word must be 4
-		(((MMU.DMACrt[proc][num]>>26)&1) == 1))	// Transfer mode must be 32bit wide
-		taille = 256*192/2;
-	
-	if(MMU.DMAStartTime[proc][num] == 5)
-		taille *= 0x80;
-	
-	MMU.DMACycle[proc][num] = taille + nds.cycles;
-	MMU.DMAing[proc][num] = TRUE;
-	
-	DMALOG("proc %d, dma %d src %08X dst %08X start %d taille %d repeat %s %08X\r\n",
-		proc, num, src, dst, MMU.DMAStartTime[proc][num], taille,
-		(MMU.DMACrt[proc][num]&(1<<25))?"on":"off",MMU.DMACrt[proc][num]);
-	
-	if(!(MMU.DMACrt[proc][num]&(1<<25)))
-		MMU.DMAStartTime[proc][num] = 0;
-	
-	// transfer
-	{
-		u32 i=0;
-		// 32 bit or 16 bit transfer ?
-		int sz = ((MMU.DMACrt[proc][num]>>26)&1)? 4 : 2; 
-		int dstinc,srcinc;
-		int u=(MMU.DMACrt[proc][num]>>21);
-		switch(u & 0x3) {
-			case 0 :  dstinc =  sz; break;
-			case 1 :  dstinc = -sz; break;
-			case 2 :  dstinc =   0; break;
-			case 3 :  dstinc =  sz; break; //reload
-		}
-		switch((u >> 2)&0x3) {
-			case 0 :  srcinc =  sz; break;
-			case 1 :  srcinc = -sz; break;
-			case 2 :  srcinc =   0; break;
-			case 3 :  // reserved
-				return;
-		}
-		if ((MMU.DMACrt[proc][num]>>26)&1)
-			for(; i < taille; ++i)
-			{
-				MMU_write32(proc, dst, MMU_read32(proc, src));
-				dst += dstinc;
-				src += srcinc;
-			}
-		else
-			for(; i < taille; ++i)
-			{
-				MMU_write16(proc, dst, MMU_read16(proc, src));
-				dst += dstinc;
-				src += srcinc;
-			}
-	}
-}
-
-#ifdef MMU_ENABLE_ACL
-
-INLINE void check_access(u32 adr, u32 access) {
-	/* every other mode: sys */
-	access |= 1;
-	if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) {
-		/* is user mode access */
-		access ^= 1 ;
-	}
-	if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) {
-		execute = FALSE ;
-	}
-}
-INLINE void check_access_write(u32 adr) {
-	u32 access = CP15_ACCESS_WRITE;
-	check_access(adr, access)
-}
-
-u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access)
-{
-	/* on arm9 we need to check the MPU regions */
-	if (proc == ARMCPU_ARM9)
-		check_access(u32 adr, u32 access);
-	return MMU_read8(proc,adr);
-}
-u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access)
-{
-	/* on arm9 we need to check the MPU regions */
-	if (proc == ARMCPU_ARM9)
-		check_access(u32 adr, u32 access);
-	return MMU_read16(proc,adr);
-}
-u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access)
-{
-	/* on arm9 we need to check the MPU regions */
-	if (proc == ARMCPU_ARM9)
-		check_access(u32 adr, u32 access);
-	return MMU_read32(proc,adr);
-}
-
-void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val)
-{
-	/* check MPU region on ARM9 */
-	if (proc == ARMCPU_ARM9)
-		check_access_write(adr);
-	MMU_write8(proc,adr,val);
-}
-void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val)
-{
-	/* check MPU region on ARM9 */
-	if (proc == ARMCPU_ARM9)
-		check_access_write(adr);
-	MMU_write16(proc,adr,val) ;
-}
-void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val)
-{
-	/* check MPU region on ARM9 */
-	if (proc == ARMCPU_ARM9)
-		check_access_write(adr);
-	MMU_write32(proc,adr,val) ;
-}
-#endif
-
-
-
-#ifdef PROFILE_MEMORY_ACCESS
-
-#define PROFILE_PREFETCH 0
-#define PROFILE_READ 1
-#define PROFILE_WRITE 2
-
-struct mem_access_profile {
-  u64 num_accesses;
-  u32 address_mask;
-  u32 masked_value;
-};
-
-#define PROFILE_NUM_MEM_ACCESS_PROFILES 4
-
-static u64 profile_num_accesses[2][3];
-static u64 profile_unknown_addresses[2][3];
-static struct mem_access_profile
-profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES];
-
-static void
-setup_profiling( void) {
-  int i;
-
-  for ( i = 0; i < 2; i++) {
-    int access_type;
-
-    for ( access_type = 0; access_type < 3; access_type++) {
-      profile_num_accesses[i][access_type] = 0;
-      profile_unknown_addresses[i][access_type] = 0;
-
-      /*
-       * Setup the access testing structures
-       */
-      profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000;
-      profile_memory_accesses[i][access_type][0].masked_value = 0x00000000;
-      profile_memory_accesses[i][access_type][0].num_accesses = 0;
-
-      /* main memory */
-      profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000;
-      profile_memory_accesses[i][access_type][1].masked_value = 0x02000000;
-      profile_memory_accesses[i][access_type][1].num_accesses = 0;
-
-      /* shared memory */
-      profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000;
-      profile_memory_accesses[i][access_type][2].masked_value = 0x03000000;
-      profile_memory_accesses[i][access_type][2].num_accesses = 0;
-
-      /* arm7 memory */
-      profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000;
-      profile_memory_accesses[i][access_type][3].masked_value = 0x03800000;
-      profile_memory_accesses[i][access_type][3].num_accesses = 0;
-    }
-  }
-}
-
-static void
-profile_memory_access( int arm9, u32 adr, int access_type) {
-  static int first = 1;
-  int mem_profile;
-  int address_found = 0;
-
-  if ( first) {
-    setup_profiling();
-    first = 0;
-  }
-
-  profile_num_accesses[arm9][access_type] += 1;
-
-  for ( mem_profile = 0;
-        mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES &&
-          !address_found;
-        mem_profile++) {
-    if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) ==
-         profile_memory_accesses[arm9][access_type][mem_profile].masked_value) {
-      /*printf( "adr %08x mask %08x res %08x expected %08x\n",
-              adr,
-              profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
-              adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
-              profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/
-      address_found = 1;
-      profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1;
-    }
-  }
-
-  if ( !address_found) {
-    profile_unknown_addresses[arm9][access_type] += 1;
-  }
-}
-
-
-static const char *access_type_strings[] = {
-  "prefetch",
-  "read    ",
-  "write   "
-};
-
-void
-print_memory_profiling( void) {
-  int arm;
-
-  printf("------ Memory access profile ------\n");
-
-  for ( arm = 0; arm < 2; arm++) {
-    int access_type;
-
-    for ( access_type = 0; access_type < 3; access_type++) {
-      int mem_profile;
-      printf("ARM%c: num of %s %lld\n",
-             arm ? '9' : '7',
-             access_type_strings[access_type],
-             profile_num_accesses[arm][access_type]);
-
-      for ( mem_profile = 0;
-            mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES;
-            mem_profile++) {
-        printf( "address %08lx: %llu\n",
-                profile_memory_accesses[arm][access_type][mem_profile].masked_value,
-                profile_memory_accesses[arm][access_type][mem_profile].num_accesses);
-      }
-              
-      printf( "unknown addresses %lld\n",
-              profile_unknown_addresses[arm][access_type]);
-
-      printf( "\n");
-    }
-  }
-
-  printf("------ End of Memory access profile ------\n\n");
-}
-#else
-void
-print_memory_profiling( void) {
-}
-#endif /* End of PROFILE_MEMORY_ACCESS area */
-
-static u16 FASTCALL
-arm9_prefetch16( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_PREFETCH);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Returns data from DTCM (ARM9 only) */
-      return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-    }
-  /* access to main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
-                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
-  }
-#endif
-
-  return MMU_read16( ARMCPU_ARM9, adr);
-}
-static u32 FASTCALL
-arm9_prefetch32( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_PREFETCH);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Returns data from DTCM (ARM9 only) */
-      return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-    }
-  /* access to main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
-                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
-  }
-#endif
-
-  return MMU_read32( ARMCPU_ARM9, adr);
-}
-
-static u8 FASTCALL
-arm9_read8( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_READ);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if( (adr&(~0x3FFF)) == MMU.DTCMRegion)
-    {
-      return ARM9Mem.ARM9_DTCM[adr&0x3FFF];
-    }
-  /* access to main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    return MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF]
-      [adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]];
-  }
-#endif
-
-  return MMU_read8( ARMCPU_ARM9, adr);
-}
-static u16 FASTCALL
-arm9_read16( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_READ);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Returns data from DTCM (ARM9 only) */
-      return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-    }
-
-  /* access to main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
-                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
-  }
-#endif
-
-  return MMU_read16( ARMCPU_ARM9, adr);
-}
-static u32 FASTCALL
-arm9_read32( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_READ);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Returns data from DTCM (ARM9 only) */
-      return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
-    }
-  /* access to main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
-                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
-  }
-#endif
-
-  return MMU_read32( ARMCPU_ARM9, adr);
-}
-
-
-static void FASTCALL
-arm9_write8(void *data, u32 adr, u8 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_WRITE);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if( (adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Writes data in DTCM (ARM9 only) */
-      ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val;
-      return ;
-    }
-  /* main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]
-      [adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]] = val;
-    return;
-  }
-#endif
-
-  MMU_write8( ARMCPU_ARM9, adr, val);
-}
-static void FASTCALL
-arm9_write16(void *data, u32 adr, u16 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_WRITE);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Writes in DTCM (ARM9 only) */
-      T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
-      return;
-    }
-  /* main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    T1WriteWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
-                 adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
-    return;
-  }
-#endif
-
-  MMU_write16( ARMCPU_ARM9, adr, val);
-}
-static void FASTCALL
-arm9_write32(void *data, u32 adr, u32 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 1, adr, PROFILE_WRITE);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  if((adr & ~0x3FFF) == MMU.DTCMRegion)
-    {
-      /* Writes in DTCM (ARM9 only) */
-      T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
-      return;
-    }
-  /* main memory */
-  if ( (adr & 0x0f000000) == 0x02000000) {
-    T1WriteLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
-                 adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
-    return;
-  }
-#endif
-
-  MMU_write32( ARMCPU_ARM9, adr, val);
-}
-
-
-
-
-static u16 FASTCALL
-arm7_prefetch16( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_PREFETCH);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  /* ARM7 private memory */
-  if ( (adr & 0x0f800000) == 0x03800000) {
-    T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
-               adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); 
-  }
-#endif
-
-  return MMU_read16( ARMCPU_ARM7, adr);
-}
-static u32 FASTCALL
-arm7_prefetch32( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_PREFETCH);
-#endif
-
-#ifdef EARLY_MEMORY_ACCESS
-  /* ARM7 private memory */
-  if ( (adr & 0x0f800000) == 0x03800000) {
-    T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
-               adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); 
-  }
-#endif
-
-  return MMU_read32( ARMCPU_ARM7, adr);
-}
-
-static u8 FASTCALL
-arm7_read8( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_READ);
-#endif
-
-  return MMU_read8( ARMCPU_ARM7, adr);
-}
-static u16 FASTCALL
-arm7_read16( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_READ);
-#endif
-
-  return MMU_read16( ARMCPU_ARM7, adr);
-}
-static u32 FASTCALL
-arm7_read32( void *data, u32 adr) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_READ);
-#endif
-
-  return MMU_read32( ARMCPU_ARM7, adr);
-}
-
-
-static void FASTCALL
-arm7_write8(void *data, u32 adr, u8 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_WRITE);
-#endif
-
-  MMU_write8( ARMCPU_ARM7, adr, val);
-}
-static void FASTCALL
-arm7_write16(void *data, u32 adr, u16 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_WRITE);
-#endif
-
-  MMU_write16( ARMCPU_ARM7, adr, val);
-}
-static void FASTCALL
-arm7_write32(void *data, u32 adr, u32 val) {
-#ifdef PROFILE_MEMORY_ACCESS
-  profile_memory_access( 0, adr, PROFILE_WRITE);
-#endif
-
-  MMU_write32( ARMCPU_ARM7, adr, val);
-}
-
-
-
-/*
- * the base memory interfaces
- */
-struct armcpu_memory_iface arm9_base_memory_iface = {
-#ifdef __GNUC__
-  .prefetch32 = arm9_prefetch32,
-  .prefetch16 = arm9_prefetch16,
-
-  .read8 = arm9_read8,
-  .read16 = arm9_read16,
-  .read32 = arm9_read32,
-
-  .write8 = arm9_write8,
-  .write16 = arm9_write16,
-  .write32 = arm9_write32
-#else
-  arm9_prefetch32,
-  arm9_prefetch16,
-
-  arm9_read8,
-  arm9_read16,
-  arm9_read32,
-
-  arm9_write8,
-  arm9_write16,
-  arm9_write32
-#endif
-};
-
-struct armcpu_memory_iface arm7_base_memory_iface = {
-#ifdef __GNUC__
-  .prefetch32 = arm7_prefetch32,
-  .prefetch16 = arm7_prefetch16,
-
-  .read8 = arm7_read8,
-  .read16 = arm7_read16,
-  .read32 = arm7_read32,
-
-  .write8 = arm7_write8,
-  .write16 = arm7_write16,
-  .write32 = arm7_write32
-#else
-  arm7_prefetch32,
-  arm7_prefetch16,
-
-  arm7_read8,
-  arm7_read16,
-  arm7_read32,
-
-  arm7_write8,
-  arm7_write16,
-  arm7_write32
-#endif
-};
-
-/*
- * The direct memory interface for the ARM9.
- * This avoids the ARM9 protection unit when accessing
- * memory.
- */
-struct armcpu_memory_iface arm9_direct_memory_iface = {
-#ifdef __GNUC__
-  /* the prefetch is not used */
-  .prefetch32 = NULL,
-  .prefetch16 = NULL,
-
-  .read8 = arm9_read8,
-  .read16 = arm9_read16,
-  .read32 = arm9_read32,
-
-  .write8 = arm9_write8,
-  .write16 = arm9_write16,
-  .write32 = arm9_write32
-#else
-  NULL,
-  NULL,
-
-  arm9_read8,
-  arm9_read16,
-  arm9_read32,
-
-  arm9_write8,
-  arm9_write16,
-  arm9_write32
-#endif
-};
diff --git a/src/xsf/desmume/MMU.cc b/src/xsf/desmume/MMU.cc
new file mode 100644
index 000000000000..79e47ffb8521
--- /dev/null
+++ b/src/xsf/desmume/MMU.cc
@@ -0,0 +1,3526 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+	Copyright (C) 2007 shash
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//#define RENDER3D
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+//#include "gl_vertex.h"
+
+#include "debug.h"
+#include "NDSSystem.h"
+//#include "cflash.h"
+#define cflash_read(a) 0
+#define cflash_write(a,d)
+#include "cp15.h"
+//#include "wifi.h"
+#include "registers.h"
+
+#if VIO2SF_GPU_ENABLE
+#include "render3D.h"
+#else
+#define GPU_setVideoProp(p1, p2)
+#define GPU_setBGProp(p1, p2, p3)
+
+#define GPU_setBLDCNT(p1, p2)
+#define GPU_setBLDALPHA(p1, p2)
+#define GPU_setBLDY(p1, p2)
+#define GPU_setMOSAIC(p1, p2)
+
+
+#define GPU_remove(p1,p2)
+#define GPU_addBack(p1,p2)
+
+#define GPU_ChangeGraphicsCore(p1) 0
+
+#define GPU_set_DISPCAPCNT(p1, p2)
+#define GPU_ligne(p1, p2)
+#define GPU_setMasterBrightness(p1, p2)
+
+#define GPU_setWIN0_H(p1, p2)
+#define GPU_setWIN0_H0(p1, p2)
+#define GPU_setWIN0_H1(p1, p2)
+
+#define GPU_setWIN0_V(p1, p2)
+#define GPU_setWIN0_V0(p1, p2)
+#define GPU_setWIN0_V1(p1, p2)
+
+#define GPU_setWIN1_H(p1, p2)
+#define GPU_setWIN1_H0(p1, p2)
+#define GPU_setWIN1_H1(p1, p2)
+
+#define GPU_setWIN1_V(p1, p2)
+#define GPU_setWIN1_V0(p1, p2)
+#define GPU_setWIN1_V1(p1, p2)
+
+#define GPU_setWININ(p1, p2)
+#define GPU_setWININ0(p1, p2)
+#define GPU_setWININ1(p1, p2)
+
+#define GPU_setWINOUT16(p1, p2)
+#define GPU_setWINOUT(p1, p2)
+#define GPU_setWINOBJ(p1, p2)
+
+#define GPU_setBLDCNT_LOW(p1, p2)
+#define GPU_setBLDCNT_HIGH(p1, p2)
+#define GPU_setBLDCNT(p1, p2)
+
+#define GPU_setBLDALPHA(p1, p2)
+#define GPU_setBLDALPHA_EVA(p1, p2)
+#define GPU_setBLDALPHA_EVB(p1, p2)
+
+#define GPU_setBLDY_EVY(p1, p2)
+#endif
+
+#define ROM_MASK 3
+
+/*
+ *
+ */
+//#define PROFILE_MEMORY_ACCESS 1
+#define EARLY_MEMORY_ACCESS 1
+
+#define INTERNAL_DTCM_READ 1
+#define INTERNAL_DTCM_WRITE 1
+
+//#define LOG_CARD
+//#define LOG_GPU
+//#define LOG_DMA
+//#define LOG_DMA2
+//#define LOG_DIV
+
+char szRomPath[512];
+char szRomBaseName[512];
+
+#define DUP2(x)  x, x
+#define DUP4(x)  x, x, x, x
+#define DUP8(x)  x, x, x, x,  x, x, x, x
+#define DUP16(x) x, x, x, x,  x, x, x, x,  x, x, x, x,  x, x, x, x
+
+MMU_struct MMU;
+
+u8 * MMU_ARM9_MEM_MAP[256]={
+/* 0X*/	DUP16(ARM9Mem.ARM9_ITCM),
+/* 1X*/	//DUP16(ARM9Mem.ARM9_ITCM)
+/* 1X*/	DUP16(ARM9Mem.ARM9_WRAM),
+/* 2X*/	DUP16(ARM9Mem.MAIN_MEM),
+/* 3X*/	DUP16(MMU.SWIRAM),
+/* 4X*/	DUP16(ARM9Mem.ARM9_REG),
+/* 5X*/	DUP16(ARM9Mem.ARM9_VMEM),
+/* 6X*/	DUP2(ARM9Mem.ARM9_ABG),
+		DUP2(ARM9Mem.ARM9_BBG),
+		DUP2(ARM9Mem.ARM9_AOBJ),
+		DUP2(ARM9Mem.ARM9_BOBJ),
+		DUP8(ARM9Mem.ARM9_LCD),
+/* 7X*/	DUP16(ARM9Mem.ARM9_OAM),
+/* 8X*/	DUP16(nullptr),
+/* 9X*/	DUP16(nullptr),
+/* AX*/	DUP16(MMU.CART_RAM),
+/* BX*/	DUP16(MMU.UNUSED_RAM),
+/* CX*/	DUP16(MMU.UNUSED_RAM),
+/* DX*/	DUP16(MMU.UNUSED_RAM),
+/* EX*/	DUP16(MMU.UNUSED_RAM),
+/* FX*/	DUP16(ARM9Mem.ARM9_BIOS)
+};
+
+u32 MMU_ARM9_MEM_MASK[256]={
+/* 0X*/	DUP16(0x00007FFF),
+/* 1X*/	//DUP16(0x00007FFF)
+/* 1X*/	DUP16(0x00FFFFFF),
+/* 2X*/	DUP16(0x003FFFFF),
+/* 3X*/	DUP16(0x00007FFF),
+/* 4X*/	DUP16(0x00FFFFFF),
+/* 5X*/	DUP16(0x000007FF),
+/* 6X*/	DUP2(0x0007FFFF),
+		DUP2(0x0001FFFF),
+		DUP2(0x0003FFFF),
+		DUP2(0x0001FFFF),
+		DUP8(0x000FFFFF),
+/* 7X*/	DUP16(0x000007FF),
+/* 8X*/	DUP16(ROM_MASK),
+/* 9X*/	DUP16(ROM_MASK),
+/* AX*/	DUP16(0x0000FFFF),
+/* BX*/	DUP16(0x00000003),
+/* CX*/	DUP16(0x00000003),
+/* DX*/	DUP16(0x00000003),
+/* EX*/	DUP16(0x00000003),
+/* FX*/	DUP16(0x00007FFF)
+};
+
+u8 * MMU_ARM7_MEM_MAP[256]={
+/* 0X*/	DUP16(MMU.ARM7_BIOS),
+/* 1X*/	DUP16(MMU.UNUSED_RAM),
+/* 2X*/	DUP16(ARM9Mem.MAIN_MEM),
+/* 3X*/	DUP8(MMU.SWIRAM),
+		DUP8(MMU.ARM7_ERAM),
+/* 4X*/	DUP8(MMU.ARM7_REG),
+		DUP8(MMU.ARM7_WIRAM),
+/* 5X*/	DUP16(MMU.UNUSED_RAM),
+/* 6X*/	DUP16(ARM9Mem.ARM9_ABG),
+/* 7X*/	DUP16(MMU.UNUSED_RAM),
+/* 8X*/	DUP16(nullptr),
+/* 9X*/	DUP16(nullptr),
+/* AX*/	DUP16(MMU.CART_RAM),
+/* BX*/	DUP16(MMU.UNUSED_RAM),
+/* CX*/	DUP16(MMU.UNUSED_RAM),
+/* DX*/	DUP16(MMU.UNUSED_RAM),
+/* EX*/	DUP16(MMU.UNUSED_RAM),
+/* FX*/	DUP16(MMU.UNUSED_RAM)
+};
+
+u32 MMU_ARM7_MEM_MASK[256]={
+/* 0X*/	DUP16(0x00003FFF),
+/* 1X*/	DUP16(0x00000003),
+/* 2X*/	DUP16(0x003FFFFF),
+/* 3X*/	DUP8(0x00007FFF),
+		DUP8(0x0000FFFF),
+/* 4X*/	DUP8(0x00FFFFFF),
+		DUP8(0x0000FFFF),
+/* 5X*/	DUP16(0x00000003),
+/* 6X*/	DUP16(0x0003FFFF),
+/* 7X*/	DUP16(0x00000003),
+/* 8X*/	DUP16(ROM_MASK),
+/* 9X*/	DUP16(ROM_MASK),
+/* AX*/	DUP16(0x0000FFFF),
+/* BX*/	DUP16(0x00000003),
+/* CX*/	DUP16(0x00000003),
+/* DX*/	DUP16(0x00000003),
+/* EX*/	DUP16(0x00000003),
+/* FX*/	DUP16(0x00000003)
+};
+
+u32 MMU_ARM9_WAIT16[16]={
+	1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
+};
+
+u32 MMU_ARM9_WAIT32[16]={
+	1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1,
+};
+
+u32 MMU_ARM7_WAIT16[16]={
+	1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1,
+};
+
+u32 MMU_ARM7_WAIT32[16]={
+	1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1,
+};
+
+void MMU_Init(void) {
+	int i;
+
+	LOG("MMU init\n");
+
+	memset(&MMU, 0, sizeof(MMU_struct));
+
+	MMU.CART_ROM = MMU.UNUSED_RAM;
+
+        for(i = 0x80; i<0xA0; ++i)
+        {
+           MMU_ARM9_MEM_MAP[i] = MMU.CART_ROM;
+           MMU_ARM7_MEM_MAP[i] = MMU.CART_ROM;
+        }
+
+	MMU.MMU_MEM[0] = MMU_ARM9_MEM_MAP;
+	MMU.MMU_MEM[1] = MMU_ARM7_MEM_MAP;
+	MMU.MMU_MASK[0]= MMU_ARM9_MEM_MASK;
+	MMU.MMU_MASK[1] = MMU_ARM7_MEM_MASK;
+
+	MMU.ITCMRegion = 0x00800000;
+
+	MMU.MMU_WAIT16[0] = MMU_ARM9_WAIT16;
+	MMU.MMU_WAIT16[1] = MMU_ARM7_WAIT16;
+	MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32;
+	MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32;
+
+	for(i = 0;i < 16;i++)
+		FIFOInit(MMU.fifos + i);
+
+        mc_init(&MMU.fw, MC_TYPE_FLASH);  /* init fw device */
+        mc_alloc(&MMU.fw, NDS_FW_SIZE_V1);
+        MMU.fw.fp = nullptr;
+
+        // Init Backup Memory device, this should really be done when the rom is loaded
+        mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT);
+        mc_alloc(&MMU.bupmem, 1);
+        MMU.bupmem.fp = nullptr;
+
+}
+
+void MMU_DeInit(void) {
+	LOG("MMU deinit\n");
+//    if (MMU.fw.fp)
+//       fclose(MMU.fw.fp);
+    mc_free(&MMU.fw);
+//    if (MMU.bupmem.fp)
+//       fclose(MMU.bupmem.fp);
+    mc_free(&MMU.bupmem);
+}
+
+//Card rom & ram
+
+u16 SPI_CNT = 0;
+u16 SPI_CMD = 0;
+u16 AUX_SPI_CNT = 0;
+u16 AUX_SPI_CMD = 0;
+
+u32 rom_mask = 0;
+
+u32 DMASrc[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
+u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
+
+void MMU_clearMem()
+{
+	int i;
+
+	memset(ARM9Mem.ARM9_ABG,  0, 0x080000);
+	memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000);
+	memset(ARM9Mem.ARM9_BBG,  0, 0x020000);
+	memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000);
+	memset(ARM9Mem.ARM9_DTCM, 0, 0x4000);
+	memset(ARM9Mem.ARM9_ITCM, 0, 0x8000);
+	memset(ARM9Mem.ARM9_LCD,  0, 0x0A4000);
+	memset(ARM9Mem.ARM9_OAM,  0, 0x0800);
+	memset(ARM9Mem.ARM9_REG,  0, 0x01000000);
+	memset(ARM9Mem.ARM9_VMEM, 0, 0x0800);
+	memset(ARM9Mem.ARM9_WRAM, 0, 0x01000000);
+	memset(ARM9Mem.MAIN_MEM,  0, 0x400000);
+
+	memset(ARM9Mem.blank_memory,  0, 0x020000);
+
+	memset(MMU.ARM7_ERAM,     0, 0x010000);
+	memset(MMU.ARM7_REG,      0, 0x010000);
+
+	for(i = 0;i < 16;i++)
+	FIFOInit(MMU.fifos + i);
+
+	MMU.DTCMRegion = 0;
+	MMU.ITCMRegion = 0x00800000;
+
+	memset(MMU.timer,         0, sizeof(u16) * 2 * 4);
+	memset(MMU.timerMODE,     0, sizeof(s32) * 2 * 4);
+	memset(MMU.timerON,       0, sizeof(u32) * 2 * 4);
+	memset(MMU.timerRUN,      0, sizeof(u32) * 2 * 4);
+	memset(MMU.timerReload,   0, sizeof(u16) * 2 * 4);
+
+	memset(MMU.reg_IME,       0, sizeof(u32) * 2);
+	memset(MMU.reg_IE,        0, sizeof(u32) * 2);
+	memset(MMU.reg_IF,        0, sizeof(u32) * 2);
+
+	memset(MMU.DMAStartTime,  0, sizeof(u32) * 2 * 4);
+	memset(MMU.DMACycle,      0, sizeof(s32) * 2 * 4);
+	memset(MMU.DMACrt,        0, sizeof(u32) * 2 * 4);
+	memset(MMU.DMAing,        0, sizeof(BOOL) * 2 * 4);
+
+	memset(MMU.dscard,        0, sizeof(nds_dscard) * 2);
+
+	MainScreen.offset = 192;
+	SubScreen.offset  = 0;
+
+        /* setup the texture slot pointers */
+#if 0
+        ARM9Mem.textureSlotAddr[0] = ARM9Mem.blank_memory;
+        ARM9Mem.textureSlotAddr[1] = ARM9Mem.blank_memory;
+        ARM9Mem.textureSlotAddr[2] = ARM9Mem.blank_memory;
+        ARM9Mem.textureSlotAddr[3] = ARM9Mem.blank_memory;
+#else
+        ARM9Mem.textureSlotAddr[0] = &ARM9Mem.ARM9_LCD[0x20000 * 0];
+        ARM9Mem.textureSlotAddr[1] = &ARM9Mem.ARM9_LCD[0x20000 * 1];
+        ARM9Mem.textureSlotAddr[2] = &ARM9Mem.ARM9_LCD[0x20000 * 2];
+        ARM9Mem.textureSlotAddr[3] = &ARM9Mem.ARM9_LCD[0x20000 * 3];
+#endif
+}
+
+/* the VRAM blocks keep their content even when not blended in */
+/* to ensure that we write the content back to the LCD ram */
+/* FIXME: VRAM Bank E,F,G,H,I missing */
+void MMU_VRAMWriteBackToLCD(u8 block)
+{
+	u8 *destination;
+	u8 *source;
+	u32 size ;
+	u8 VRAMBankCnt;
+	#if 1
+		return ;
+	#endif
+	destination = 0 ;
+	source = 0;
+	VRAMBankCnt = MMU_read8(ARMCPU_ARM9,REG_VRAMCNTA+block) ;
+	switch (block)
+	{
+		case 0: // Bank A
+			destination = ARM9Mem.ARM9_LCD ;
+			size = 0x20000 ;
+			break ;
+		case 1: // Bank B
+			destination = ARM9Mem.ARM9_LCD + 0x20000 ;
+			size = 0x20000 ;
+			break ;
+		case 2: // Bank C
+			destination = ARM9Mem.ARM9_LCD + 0x40000 ;
+			size = 0x20000 ;
+			break ;
+		case 3: // Bank D
+			destination = ARM9Mem.ARM9_LCD + 0x60000 ;
+			size = 0x20000 ;
+			break ;
+		case 4: // Bank E
+			destination = ARM9Mem.ARM9_LCD + 0x80000 ;
+			size = 0x10000 ;
+			break ;
+		case 5: // Bank F
+			destination = ARM9Mem.ARM9_LCD + 0x90000 ;
+			size = 0x4000 ;
+			break ;
+		case 6: // Bank G
+			destination = ARM9Mem.ARM9_LCD + 0x94000 ;
+			size = 0x4000 ;
+			break ;
+		case 8: // Bank H
+			destination = ARM9Mem.ARM9_LCD + 0x98000 ;
+			size = 0x8000 ;
+			break ;
+		case 9: // Bank I
+			destination = ARM9Mem.ARM9_LCD + 0xA0000 ;
+			size = 0x4000 ;
+			break ;
+		default:
+			return ;
+	}
+	switch (VRAMBankCnt & 7) {
+		case 0:
+			/* vram is allready stored at LCD, we dont need to write it back */
+			MMU.vScreen = 1;
+			break ;
+		case 1:
+	switch(block){
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		/* banks are in use for BG at ABG + ofs * 0x20000 */
+				source = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
+		break ;
+	case 4:
+		/* bank E is in use at ABG */
+		source = ARM9Mem.ARM9_ABG ;
+		break;
+	case 5:
+	case 6:
+		/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
+		source = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
+		break;
+	case 8:
+		/* bank H is in use at BBG */
+		source = ARM9Mem.ARM9_BBG ;
+		break ;
+	case 9:
+		/* bank I is in use at BBG */
+		source = ARM9Mem.ARM9_BBG + 0x8000 ;
+		break;
+	default: return ;
+	}
+			break ;
+		case 2:
+			if (block < 2)
+			{
+				/* banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 */
+				source = ARM9Mem.ARM9_AOBJ + ((VRAMBankCnt >> 3) & 1) * 0x20000 ;
+			} else return ;
+			break ;
+		case 4:
+	switch(block){
+	case 2:
+		/* bank C is in use at BBG */
+		source = ARM9Mem.ARM9_BBG ;
+		break ;
+	case 3:
+		/* bank D is in use at BOBJ */
+		source = ARM9Mem.ARM9_BOBJ ;
+		break ;
+	default: return ;
+	}
+			break ;
+		default:
+			return ;
+	}
+	if (!destination) return ;
+	if (!source) return ;
+	memcpy(destination,source,size) ;
+}
+
+void MMU_VRAMReloadFromLCD(u8 block,u8 VRAMBankCnt)
+{
+	u8 *destination;
+	u8 *source;
+	u32 size;
+	#if 1
+		return ;
+	#endif
+	destination = 0;
+	source = 0;
+	size = 0;
+	switch (block)
+	{
+		case 0: // Bank A
+			source = ARM9Mem.ARM9_LCD ;
+			size = 0x20000 ;
+			break ;
+		case 1: // Bank B
+			source = ARM9Mem.ARM9_LCD + 0x20000 ;
+			size = 0x20000 ;
+			break ;
+		case 2: // Bank C
+			source = ARM9Mem.ARM9_LCD + 0x40000 ;
+			size = 0x20000 ;
+			break ;
+		case 3: // Bank D
+			source = ARM9Mem.ARM9_LCD + 0x60000 ;
+			size = 0x20000 ;
+			break ;
+		case 4: // Bank E
+			source = ARM9Mem.ARM9_LCD + 0x80000 ;
+			size = 0x10000 ;
+			break ;
+		case 5: // Bank F
+			source = ARM9Mem.ARM9_LCD + 0x90000 ;
+			size = 0x4000 ;
+			break ;
+		case 6: // Bank G
+			source = ARM9Mem.ARM9_LCD + 0x94000 ;
+			size = 0x4000 ;
+			break ;
+		case 8: // Bank H
+			source = ARM9Mem.ARM9_LCD + 0x98000 ;
+			size = 0x8000 ;
+			break ;
+		case 9: // Bank I
+			source = ARM9Mem.ARM9_LCD + 0xA0000 ;
+			size = 0x4000 ;
+			break ;
+		default:
+			return ;
+	}
+	switch (VRAMBankCnt & 7) {
+		case 0:
+			/* vram is allready stored at LCD, we dont need to write it back */
+			MMU.vScreen = 1;
+			break ;
+		case 1:
+			if (block < 4)
+			{
+				/* banks are in use for BG at ABG + ofs * 0x20000 */
+				destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
+			} else return ;
+			break ;
+		case 2:
+				switch(block){
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+		/* banks are in use for BG at ABG + ofs * 0x20000 */
+				destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ;
+		break ;
+	case 4:
+		/* bank E is in use at ABG */
+		destination = ARM9Mem.ARM9_ABG ;
+		break;
+	case 5:
+	case 6:
+		/* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/
+		destination = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ;
+		break;
+	case 8:
+		/* bank H is in use at BBG */
+		destination = ARM9Mem.ARM9_BBG ;
+		break ;
+	case 9:
+		/* bank I is in use at BBG */
+		destination = ARM9Mem.ARM9_BBG + 0x8000 ;
+		break;
+	default: return ;
+	}
+			break ;
+		case 4:
+	switch(block){
+	case 2:
+		/* bank C is in use at BBG */
+		destination = ARM9Mem.ARM9_BBG ;
+		break ;
+	case 3:
+		/* bank D is in use at BOBJ */
+		destination = ARM9Mem.ARM9_BOBJ ;
+		break ;
+	default: return ;
+	}
+			break ;
+		default:
+			return ;
+	}
+	if (!destination) return ;
+	if (!source) return ;
+	memcpy(destination,source,size) ;
+}
+
+void MMU_setRom(u8 * rom, u32 mask)
+{
+	unsigned int i;
+	MMU.CART_ROM = rom;
+
+	for(i = 0x80; i<0xA0; ++i)
+	{
+		MMU_ARM9_MEM_MAP[i] = rom;
+		MMU_ARM7_MEM_MAP[i] = rom;
+		MMU_ARM9_MEM_MASK[i] = mask;
+		MMU_ARM7_MEM_MASK[i] = mask;
+	}
+	rom_mask = mask;
+}
+
+void MMU_unsetRom()
+{
+	unsigned int i;
+	MMU.CART_ROM=MMU.UNUSED_RAM;
+
+	for(i = 0x80; i<0xA0; ++i)
+	{
+		MMU_ARM9_MEM_MAP[i] = MMU.UNUSED_RAM;
+		MMU_ARM7_MEM_MAP[i] = MMU.UNUSED_RAM;
+		MMU_ARM9_MEM_MASK[i] = ROM_MASK;
+		MMU_ARM7_MEM_MASK[i] = ROM_MASK;
+	}
+	rom_mask = ROM_MASK;
+}
+char txt[80];
+
+u8 FASTCALL MMU_read8(u32 proc, u32 adr)
+{
+#ifdef INTERNAL_DTCM_READ
+	if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion))
+	{
+		return ARM9Mem.ARM9_DTCM[adr&0x3FFF];
+	}
+#endif
+
+	// CFlash reading, Mic
+	if ((adr>=0x9000000)&&(adr<0x9900000))
+		return (unsigned char)cflash_read(adr);
+
+#ifdef EXPERIMENTAL_WIFI
+	/* wifi mac access */
+	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
+	{
+		if (adr & 1)
+			return (WIFI_read16(&wifiMac,adr) >> 8) & 0xFF;
+		else
+			return WIFI_read16(&wifiMac,adr) & 0xFF;
+	}
+#endif
+
+        return MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]];
+}
+
+
+
+u16 FASTCALL MMU_read16(u32 proc, u32 adr)
+{
+#ifdef INTERNAL_DTCM_READ
+	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
+	{
+		/* Returns data from DTCM (ARM9 only) */
+		return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+	}
+#endif
+
+	// CFlash reading, Mic
+	if ((adr>=0x08800000)&&(adr<0x09900000))
+	   return (unsigned short)cflash_read(adr);
+
+#ifdef EXPERIMENTAL_WIFI
+	/* wifi mac access */
+	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
+		return WIFI_read16(&wifiMac,adr) ;
+#endif
+
+	adr &= 0x0FFFFFFF;
+
+	if(adr&0x04000000)
+	{
+		/* Adress is an IO register */
+		switch(adr)
+		{
+
+#if VIO2SF_GPU_ENABLE
+			case 0x04000604:
+				return (gpu3D->NDS_3D_GetNumPolys()&2047);
+			case 0x04000606:
+				return (gpu3D->NDS_3D_GetNumVertex()&8191);
+#endif
+
+			case REG_IPCFIFORECV :               /* TODO (clear): ??? */
+				execute = false;
+				return 1;
+
+			case REG_IME :
+				return (u16)MMU.reg_IME[proc];
+
+			case REG_IE :
+				return (u16)MMU.reg_IE[proc];
+			case REG_IE + 2 :
+				return (u16)(MMU.reg_IE[proc]>>16);
+
+			case REG_IF :
+				return (u16)MMU.reg_IF[proc];
+			case REG_IF + 2 :
+				return (u16)(MMU.reg_IF[proc]>>16);
+
+			case REG_TM0CNTL :
+			case REG_TM1CNTL :
+			case REG_TM2CNTL :
+			case REG_TM3CNTL :
+				return MMU.timer[proc][(adr&0xF)>>2];
+
+			case 0x04000630 :
+				LOG("vect res\r\n");	/* TODO (clear): ??? */
+				//execute = false;
+				return 0;
+                        case REG_POSTFLG :
+				return 1;
+			default :
+				break;
+		}
+	}
+
+	/* Returns data from memory */
+	return T1ReadWord(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]);
+}
+
+u32 FASTCALL MMU_read32(u32 proc, u32 adr)
+{
+#ifdef INTERNAL_DTCM_READ
+	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
+	{
+		/* Returns data from DTCM (ARM9 only) */
+		return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+	}
+#endif
+
+	// CFlash reading, Mic
+	if ((adr>=0x9000000)&&(adr<0x9900000))
+	   return (unsigned long)cflash_read(adr);
+
+	adr &= 0x0FFFFFFF;
+
+	if((adr >> 24) == 4)
+	{
+		/* Adress is an IO register */
+		switch(adr)
+		{
+			// This is hacked due to the only current 3D core
+			case 0x04000600:
+            {
+                u32 fifonum = IPCFIFO+proc;
+
+				u32 gxstat =	(MMU.fifos[fifonum].empty<<26) |
+								(1<<25) |
+								(MMU.fifos[fifonum].full<<24) |
+								/*((NDS_nbpush[0]&1)<<13) | ((NDS_nbpush[2]&0x1F)<<8) |*/
+								2;
+
+				LOG ("GXSTAT: 0x%X", gxstat);
+
+				return	gxstat;
+            }
+
+			case 0x04000640:
+			case 0x04000644:
+			case 0x04000648:
+			case 0x0400064C:
+			case 0x04000650:
+			case 0x04000654:
+			case 0x04000658:
+			case 0x0400065C:
+			case 0x04000660:
+			case 0x04000664:
+			case 0x04000668:
+			case 0x0400066C:
+			case 0x04000670:
+			case 0x04000674:
+			case 0x04000678:
+			case 0x0400067C:
+			{
+				//LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)");
+#if VIO2SF_GPU_ENABLE
+				return gpu3D->NDS_3D_GetClipMatrix ((adr-0x04000640)/4);
+#else
+				return 0;
+#endif
+			}
+			case 0x04000680:
+			case 0x04000684:
+			case 0x04000688:
+			case 0x0400068C:
+			case 0x04000690:
+			case 0x04000694:
+			case 0x04000698:
+			case 0x0400069C:
+			case 0x040006A0:
+			{
+#if VIO2SF_GPU_ENABLE
+				//LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)");
+				return gpu3D->NDS_3D_GetDirectionalMatrix ((adr-0x04000680)/4);
+#else
+				return 0;
+#endif
+			}
+
+			case 0x4000604:
+			{
+#if VIO2SF_GPU_ENABLE
+				return (gpu3D->NDS_3D_GetNumPolys()&2047) & ((gpu3D->NDS_3D_GetNumVertex()&8191) << 16);
+				//LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[proc][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF])>>2]);
+#else
+				return 0;
+#endif
+			}
+
+			case REG_IME :
+				return MMU.reg_IME[proc];
+			case REG_IE :
+				return MMU.reg_IE[proc];
+			case REG_IF :
+				return MMU.reg_IF[proc];
+			case REG_IPCFIFORECV :
+			{
+				u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
+				if(IPCFIFO_CNT&0x8000)
+				{
+				//execute = false;
+				u32 fifonum = IPCFIFO+proc;
+				u32 val = FIFOValue(MMU.fifos + fifonum);
+				u32 remote = (proc+1) & 1;
+				u16 IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184);
+				IPCFIFO_CNT |= (MMU.fifos[fifonum].empty<<8) | (MMU.fifos[fifonum].full<<9) | (MMU.fifos[fifonum].error<<14);
+				IPCFIFO_CNT_remote |= (MMU.fifos[fifonum].empty) | (MMU.fifos[fifonum].full<<1);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
+				T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
+				if ((MMU.fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2)))
+					NDS_makeInt(remote,17) ; /* remote: SEND FIFO EMPTY */
+				return val;
+				}
+			}
+			return 0;
+                        case REG_TM0CNTL :
+                        case REG_TM1CNTL :
+                        case REG_TM2CNTL :
+                        case REG_TM3CNTL :
+			{
+				u32 val = T1ReadWord(MMU.MMU_MEM[proc][0x40], (adr + 2) & 0xFFF);
+				return MMU.timer[proc][(adr&0xF)>>2] | (val<<16);
+			}
+			/*
+			case 0x04000640 :	// TODO (clear): again, ???
+				LOG("read proj\r\n");
+			return 0;
+			case 0x04000680 :
+				LOG("read roat\r\n");
+			return 0;
+			case 0x04000620 :
+				LOG("point res\r\n");
+			return 0;
+			*/
+                        case REG_GCDATAIN:
+			{
+                                u32 val;
+
+                                if(!MMU.dscard[proc].adress) return 0;
+
+                                val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].adress);
+
+				MMU.dscard[proc].adress += 4;	/* increment adress */
+
+				MMU.dscard[proc].transfer_count--;	/* update transfer counter */
+				if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */
+				{
+					return val;	/* return data */
+				}
+				else	/* transfer is done */
+                                {
+                                        T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, T1ReadLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff) & ~(0x00800000 | 0x80000000));
+					/* = 0x7f7fffff */
+
+					/* if needed, throw irq for the end of transfer */
+                                        if(T1ReadWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff) & 0x4000)
+					{
+                                                if(proc == ARMCPU_ARM7) NDS_makeARM7Int(19);
+                                                else NDS_makeARM9Int(19);
+					}
+
+					return val;
+				}
+			}
+
+			default :
+				break;
+		}
+	}
+
+	/* Returns data from memory */
+	return T1ReadLong(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]);
+}
+
+void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val)
+{
+#ifdef INTERNAL_DTCM_WRITE
+	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
+	{
+		/* Writes data in DTCM (ARM9 only) */
+		ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val;
+		return ;
+	}
+#endif
+
+	// CFlash writing, Mic
+	if ((adr>=0x9000000)&&(adr<0x9900000)) {
+		cflash_write(adr,val);
+		return;
+	}
+
+	adr &= 0x0FFFFFFF;
+
+        // This is bad, remove it
+        if(proc == ARMCPU_ARM7)
+        {
+           if ((adr>=0x04000400)&&(adr<0x0400051D))
+           {
+              SPU_WriteByte(adr, val);
+              return;
+           }
+        }
+
+	if ((adr & 0xFF800000) == 0x04800000)
+	{
+		/* is wifi hardware, dont intermix with regular hardware registers */
+		/* FIXME handle 8 bit writes */
+		return ;
+	}
+
+	switch(adr)
+	{
+		case REG_DISPA_WIN0H:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_H1 (MainScreen.gpu, val);
+			break ;
+		case REG_DISPA_WIN0H+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_H0 (MainScreen.gpu, val);
+			break ;
+		case REG_DISPA_WIN1H:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_H1 (MainScreen.gpu,val);
+			break ;
+		case REG_DISPA_WIN1H+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_H0 (MainScreen.gpu,val);
+			break ;
+
+		case REG_DISPB_WIN0H:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_H1(SubScreen.gpu,val);
+			break ;
+		case REG_DISPB_WIN0H+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_H0(SubScreen.gpu,val);
+			break ;
+		case REG_DISPB_WIN1H:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_H1(SubScreen.gpu,val);
+			break ;
+		case REG_DISPB_WIN1H+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_H0(SubScreen.gpu,val);
+			break ;
+
+		case REG_DISPA_WIN0V:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WIN0V+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WIN1V:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WIN1V+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(MainScreen.gpu,val) ;
+			break ;
+
+		case REG_DISPB_WIN0V:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WIN0V+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WIN1V:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WIN1V+1:
+			if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(SubScreen.gpu,val) ;
+			break ;
+
+		case REG_DISPA_WININ:
+			if(proc == ARMCPU_ARM9) GPU_setWININ0(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WININ+1:
+			if(proc == ARMCPU_ARM9) GPU_setWININ1(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WINOUT:
+			if(proc == ARMCPU_ARM9) GPU_setWINOUT(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPA_WINOUT+1:
+			if(proc == ARMCPU_ARM9) GPU_setWINOBJ(MainScreen.gpu,val);
+			break ;
+
+		case REG_DISPB_WININ:
+			if(proc == ARMCPU_ARM9) GPU_setWININ0(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WININ+1:
+			if(proc == ARMCPU_ARM9) GPU_setWININ1(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WINOUT:
+			if(proc == ARMCPU_ARM9) GPU_setWINOUT(SubScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_WINOUT+1:
+			if(proc == ARMCPU_ARM9) GPU_setWINOBJ(SubScreen.gpu,val) ;
+			break ;
+
+
+		case REG_DISPA_BLDCNT:
+			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH(MainScreen.gpu,val);
+			break;
+		case REG_DISPA_BLDCNT+1:
+			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (MainScreen.gpu,val);
+			break;
+
+		case REG_DISPB_BLDCNT:
+			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH (SubScreen.gpu,val);
+			break;
+		case REG_DISPB_BLDCNT+1:
+			if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (SubScreen.gpu,val);
+			break;
+
+		case REG_DISPA_BLDALPHA:
+			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(MainScreen.gpu,val) ;
+			break;
+		case REG_DISPA_BLDALPHA+1:
+			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(MainScreen.gpu,val) ;
+			break;
+
+		case REG_DISPB_BLDALPHA:
+			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(SubScreen.gpu,val) ;
+			break;
+		case REG_DISPB_BLDALPHA+1:
+			if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(SubScreen.gpu,val);
+			break;
+
+		case REG_DISPA_BLDY:
+			if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ;
+			break ;
+		case REG_DISPB_BLDY:
+			if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ;
+			break;
+
+		/* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */
+		/* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */
+		case REG_VRAMCNTA:
+		case REG_VRAMCNTB:
+		case REG_VRAMCNTC:
+		case REG_VRAMCNTD:
+			if(proc == ARMCPU_ARM9)
+			{
+                MMU_VRAMWriteBackToLCD(0) ;
+                MMU_VRAMWriteBackToLCD(1) ;
+                MMU_VRAMWriteBackToLCD(2) ;
+                MMU_VRAMWriteBackToLCD(3) ;
+				switch(val & 0x1F)
+				{
+				case 1 :
+					MMU.vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM
+					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*0); // BG-VRAM
+					break;
+				case 1 | (1 << 3) :
+					MMU.vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM
+					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*1); // BG-VRAM
+					break;
+				case 1 | (2 << 3) :
+					MMU.vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM
+					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*2); // BG-VRAM
+					break;
+				case 1 | (3 << 3) :
+					MMU.vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM
+					//MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*3); // BG-VRAM
+					break;
+				case 0: /* mapped to lcd */
+                    MMU.vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ;
+					break ;
+				}
+                                /*
+                                 * FIXME: simply texture slot handling
+                                 * This is a first stab and is not correct. It does
+                                 * not handle a VRAM texture slot becoming
+                                 * unconfigured.
+                                 * Revisit all of VRAM control handling for future
+                                 * release?
+                                 */
+                                if ( val & 0x80) {
+                                  if ( (val & 0x7) == 3) {
+                                    int slot_index = (val >> 3) & 0x3;
+
+                                    ARM9Mem.textureSlotAddr[slot_index] =
+                                      &ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)];
+                                  }
+                                }
+                MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ;
+			}
+			break;
+                case REG_VRAMCNTE :
+			if(proc == ARMCPU_ARM9)
+			{
+                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTE) ;
+                                if((val & 7) == 5)
+				{
+					ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000;
+					ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000;
+					ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000;
+					ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000;
+				}
+                                else if((val & 7) == 3)
+				{
+					ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x80000;
+					ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x82000;
+					ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x84000;
+					ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x86000;
+				}
+                                else if((val & 7) == 4)
+				{
+					ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000;
+					ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000;
+					ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000;
+					ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000;
+				}
+
+				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTE,val) ;
+			}
+			break;
+
+                case REG_VRAMCNTF :
+			if(proc == ARMCPU_ARM9)
+			{
+				switch(val & 0x1F)
+				{
+                                        case 4 :
+						ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000;
+						ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000;
+						break;
+
+                                        case 4 | (1 << 3) :
+						ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x90000;
+						ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x92000;
+						break;
+
+                                        case 3 :
+						ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x90000;
+						break;
+
+                                        case 3 | (1 << 3) :
+						ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x90000;
+						break;
+
+                                        case 3 | (2 << 3) :
+						ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x90000;
+						break;
+
+                                        case 3 | (3 << 3) :
+						ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x90000;
+						break;
+
+                                        case 5 :
+                                        case 5 | (1 << 3) :
+                                        case 5 | (2 << 3) :
+                                        case 5 | (3 << 3) :
+						ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000;
+						ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000;
+						break;
+				}
+		 	}
+			break;
+                case REG_VRAMCNTG :
+			if(proc == ARMCPU_ARM9)
+			{
+		 		switch(val & 0x1F)
+				{
+                                        case 4 :
+						ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000;
+						ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000;
+						break;
+
+                                        case 4 | (1 << 3) :
+						ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x94000;
+						ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x96000;
+						break;
+
+                                        case 3 :
+						ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x94000;
+						break;
+
+                                        case 3 | (1 << 3) :
+						ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x94000;
+						break;
+
+                                        case 3 | (2 << 3) :
+						ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x94000;
+						break;
+
+                                        case 3 | (3 << 3) :
+						ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x94000;
+						break;
+
+                                        case 5 :
+                                        case 5 | (1 << 3) :
+                                        case 5 | (2 << 3) :
+                                        case 5 | (3 << 3) :
+						ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000;
+						ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000;
+						break;
+				}
+			}
+			break;
+
+                case REG_VRAMCNTH  :
+			if(proc == ARMCPU_ARM9)
+			{
+                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTH) ;
+
+                                if((val & 7) == 2)
+				{
+					ARM9Mem.ExtPal[1][0] = ARM9Mem.ARM9_LCD + 0x98000;
+					ARM9Mem.ExtPal[1][1] = ARM9Mem.ARM9_LCD + 0x9A000;
+					ARM9Mem.ExtPal[1][2] = ARM9Mem.ARM9_LCD + 0x9C000;
+					ARM9Mem.ExtPal[1][3] = ARM9Mem.ARM9_LCD + 0x9E000;
+				}
+
+				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTH,val) ;
+			}
+			break;
+
+                case REG_VRAMCNTI  :
+			if(proc == ARMCPU_ARM9)
+			{
+                MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTI) ;
+
+                                if((val & 7) == 3)
+				{
+					ARM9Mem.ObjExtPal[1][0] = ARM9Mem.ARM9_LCD + 0xA0000;
+					ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD + 0xA2000;
+				}
+
+				MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTI,val) ;
+			}
+			break;
+
+#ifdef LOG_CARD
+		case 0x040001A0 : /* TODO (clear): ??? */
+		case 0x040001A1 :
+		case 0x040001A2 :
+		case 0x040001A8 :
+		case 0x040001A9 :
+		case 0x040001AA :
+		case 0x040001AB :
+		case 0x040001AC :
+		case 0x040001AD :
+		case 0x040001AE :
+		case 0x040001AF :
+                    LOG("%08X : %02X\r\n", adr, val);
+#endif
+
+		default :
+			break;
+	}
+
+	MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]=val;
+}
+
+u16 partie = 1;
+
+void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val)
+{
+#ifdef INTERNAL_DTCM_WRITE
+	if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion))
+	{
+		/* Writes in DTCM (ARM9 only) */
+		T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
+		return;
+	}
+#endif
+
+	// CFlash writing, Mic
+	if ((adr>=0x08800000)&&(adr<0x09900000))
+	{
+		cflash_write(adr,val);
+		return;
+	}
+
+#ifdef EXPERIMENTAL_WIFI
+
+	/* wifi mac access */
+	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
+	{
+		WIFI_write16(&wifiMac,adr,val) ;
+		return ;
+	}
+#else
+	if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000))
+		return ;
+#endif
+
+	adr &= 0x0FFFFFFF;
+
+        // This is bad, remove it
+        if(proc == ARMCPU_ARM7)
+        {
+           if ((adr>=0x04000400)&&(adr<0x0400051D))
+           {
+              SPU_WriteWord(adr, val);
+              return;
+           }
+        }
+
+	if((adr >> 24) == 4)
+	{
+		/* Adress is an IO register */
+		switch(adr)
+		{
+#if VIO2SF_GPU_ENABLE
+			case 0x0400035C:
+			{
+				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>1] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_FogOffset (val);
+				}
+				return;
+			}
+			case 0x04000340:
+			{
+				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>1] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_AlphaFunc(val);
+				}
+				return;
+			}
+			case 0x04000060:
+			{
+				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x060>>1] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Control(val);
+				}
+				return;
+			}
+			case 0x04000354:
+			{
+				((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>1] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_ClearDepth(val);
+				}
+				return;
+			}
+#endif
+
+			case REG_DISPA_BLDCNT:
+				if(proc == ARMCPU_ARM9) GPU_setBLDCNT(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_BLDCNT:
+				if(proc == ARMCPU_ARM9) GPU_setBLDCNT(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_BLDALPHA:
+				if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_BLDALPHA:
+				if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_BLDY:
+				if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_BLDY:
+				if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ;
+				break;
+			case REG_DISPA_MASTERBRIGHT:
+				GPU_setMasterBrightness (MainScreen.gpu, val);
+				break;
+				/*
+			case REG_DISPA_MOSAIC:
+				if(proc == ARMCPU_ARM9) GPU_setMOSAIC(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_MOSAIC:
+				if(proc == ARMCPU_ARM9) GPU_setMOSAIC(SubScreen.gpu,val) ;
+				break ;
+				*/
+
+			case REG_DISPA_WIN0H:
+				if(proc == ARMCPU_ARM9) GPU_setWIN0_H (MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_WIN1H:
+				if(proc == ARMCPU_ARM9) GPU_setWIN1_H(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_WIN0H:
+				if(proc == ARMCPU_ARM9) GPU_setWIN0_H(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_WIN1H:
+				if(proc == ARMCPU_ARM9) GPU_setWIN1_H(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_WIN0V:
+				if(proc == ARMCPU_ARM9) GPU_setWIN0_V(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_WIN1V:
+				if(proc == ARMCPU_ARM9) GPU_setWIN1_V(MainScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_WIN0V:
+				if(proc == ARMCPU_ARM9) GPU_setWIN0_V(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPB_WIN1V:
+				if(proc == ARMCPU_ARM9) GPU_setWIN1_V(SubScreen.gpu,val) ;
+				break ;
+			case REG_DISPA_WININ:
+				if(proc == ARMCPU_ARM9) GPU_setWININ(MainScreen.gpu, val) ;
+				break ;
+			case REG_DISPA_WINOUT:
+				if(proc == ARMCPU_ARM9) GPU_setWINOUT16(MainScreen.gpu, val) ;
+				break ;
+			case REG_DISPB_WININ:
+				if(proc == ARMCPU_ARM9) GPU_setWININ(SubScreen.gpu, val) ;
+				break ;
+			case REG_DISPB_WINOUT:
+				if(proc == ARMCPU_ARM9) GPU_setWINOUT16(SubScreen.gpu, val) ;
+				break ;
+
+			case REG_DISPB_MASTERBRIGHT:
+				GPU_setMasterBrightness (SubScreen.gpu, val);
+				break;
+
+            case REG_POWCNT1 :
+				if(proc == ARMCPU_ARM9)
+				{
+					if(val & (1<<15))
+					{
+						LOG("Main core on top\n");
+						MainScreen.offset = 0;
+						SubScreen.offset = 192;
+						//nds.swapScreen();
+					}
+					else
+					{
+						LOG("Main core on bottom (%04X)\n", val);
+						MainScreen.offset = 192;
+						SubScreen.offset = 0;
+					}
+				}
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val);
+				return;
+
+                        case REG_AUXSPICNT:
+                                T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff, val);
+                                AUX_SPI_CNT = val;
+
+                                if (val == 0)
+                                   mc_reset_com(&MMU.bupmem);     /* reset backup memory device communication */
+				return;
+
+                        case REG_AUXSPIDATA:
+                                if(val!=0)
+                                {
+                                   AUX_SPI_CMD = val & 0xFF;
+                                }
+
+                                T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val));
+				return;
+
+			case REG_SPICNT :
+				if(proc == ARMCPU_ARM7)
+				{
+                                  int reset_firmware = 1;
+
+                                  if ( ((SPI_CNT >> 8) & 0x3) == 1) {
+                                    if ( ((val >> 8) & 0x3) == 1) {
+                                      if ( BIT11(SPI_CNT)) {
+                                        /* select held */
+                                        reset_firmware = 0;
+                                      }
+                                    }
+                                  }
+
+                                        //MMU.fw.com == 0; /* reset fw device communication */
+                                    if ( reset_firmware) {
+                                      /* reset fw device communication */
+                                      mc_reset_com(&MMU.fw);
+                                    }
+                                    SPI_CNT = val;
+                                }
+
+				T1WriteWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val);
+				return;
+
+			case REG_SPIDATA :
+				if(proc==ARMCPU_ARM7)
+				{
+                                        u16 spicnt;
+
+					if(val!=0)
+					{
+						SPI_CMD = val;
+					}
+
+                                        spicnt = T1ReadWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff);
+
+                                        switch((spicnt >> 8) & 0x3)
+					{
+                                                case 0 :
+							break;
+
+                                                case 1 : /* firmware memory device */
+                                                        if((spicnt & 0x3) != 0)      /* check SPI baudrate (must be 4mhz) */
+							{
+								T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0);
+								break;
+							}
+							T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, val));
+
+							return;
+
+                                                case 2 :
+							switch(SPI_CMD & 0x70)
+							{
+								case 0x00 :
+									val = 0;
+									break;
+								case 0x10 :
+									//execute = false;
+									if(SPI_CNT&(1<<11))
+									{
+										if(partie)
+										{
+											val = ((nds.touchY<<3)&0x7FF);
+											partie = 0;
+											//execute = false;
+											break;
+										}
+										val = (nds.touchY>>5);
+                                                                                partie = 1;
+										break;
+									}
+									val = ((nds.touchY<<3)&0x7FF);
+									partie = 1;
+									break;
+								case 0x20 :
+									val = 0;
+									break;
+								case 0x30 :
+									val = 0;
+									break;
+								case 0x40 :
+									val = 0;
+									break;
+								case 0x50 :
+                                                                        if(spicnt & 0x800)
+									{
+										if(partie)
+										{
+											val = ((nds.touchX<<3)&0x7FF);
+											partie = 0;
+											break;
+										}
+										val = (nds.touchX>>5);
+										partie = 1;
+										break;
+									}
+									val = ((nds.touchX<<3)&0x7FF);
+									partie = 1;
+									break;
+								case 0x60 :
+									val = 0;
+									break;
+								case 0x70 :
+									val = 0;
+									break;
+							}
+							break;
+
+                                                case 3 :
+							/* NOTICE: Device 3 of SPI is reserved (unused and unusable) */
+							break;
+					}
+				}
+
+				T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val);
+				return;
+
+				/* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/
+
+                        case REG_DISPA_BG0CNT :
+				//GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 0, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x8, val);
+				return;
+                        case REG_DISPA_BG1CNT :
+				//GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 1, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xA, val);
+				return;
+                        case REG_DISPA_BG2CNT :
+				//GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 2, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC, val);
+				return;
+                        case REG_DISPA_BG3CNT :
+				//GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 3, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xE, val);
+				return;
+                        case REG_DISPB_BG0CNT :
+				//GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 0, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x1008, val);
+				return;
+                        case REG_DISPB_BG1CNT :
+				//GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 1, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100A, val);
+				return;
+                        case REG_DISPB_BG2CNT :
+				//GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 2, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100C, val);
+				return;
+                        case REG_DISPB_BG3CNT :
+				//GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val);
+				if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 3, val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100E, val);
+				return;
+                        case REG_IME : {
+			        u32 old_val = MMU.reg_IME[proc];
+				u32 new_val = val & 1;
+				MMU.reg_IME[proc] = new_val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val);
+				if ( new_val && old_val != new_val) {
+				  /* raise an interrupt request to the CPU if needed */
+				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
+				    NDS_ARM7.wIRQ = true;
+				    NDS_ARM7.waitIRQ = false;
+				  }
+				}
+				return;
+			}
+			case REG_VRAMCNTA:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				MMU_write8(proc,adr+1,val >> 8) ;
+				return ;
+			case REG_VRAMCNTC:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				MMU_write8(proc,adr+1,val >> 8) ;
+				return ;
+			case REG_VRAMCNTE:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				MMU_write8(proc,adr+1,val >> 8) ;
+				return ;
+			case REG_VRAMCNTG:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				MMU_write8(proc,adr+1,val >> 8) ;
+				return ;
+			case REG_VRAMCNTI:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				return ;
+
+			case REG_IE :
+				MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF0000) | val;
+				if ( MMU.reg_IME[proc]) {
+				  /* raise an interrupt request to the CPU if needed */
+				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
+				    NDS_ARM7.wIRQ = true;
+				    NDS_ARM7.waitIRQ = false;
+				  }
+				}
+				return;
+			case REG_IE + 2 :
+				execute = false;
+				MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF) | (((u32)val)<<16);
+				return;
+
+			case REG_IF :
+				execute = false;
+				MMU.reg_IF[proc] &= (~((u32)val));
+				return;
+			case REG_IF + 2 :
+				execute = false;
+				MMU.reg_IF[proc] &= (~(((u32)val)<<16));
+				return;
+
+                        case REG_IPCSYNC :
+				{
+				u32 remote = (proc+1)&1;
+				u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
+				T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
+				MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));//
+				//execute = false;
+				}
+				return;
+                        case REG_IPCFIFOCNT :
+				{
+					u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
+					u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
+					if ((val & 0x8000) && !(cnt_l & 0x8000))
+					{
+						/* this is the first init, the other side didnt init yet */
+						/* so do a complete init */
+						FIFOInit(MMU.fifos + (IPCFIFO+proc));
+						T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ;
+						/* and then handle it as usual */
+					}
+
+				if(val & 0x4008)
+				{
+					FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1)));
+					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
+					T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
+					MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);//
+					return;
+				}
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4));
+				}
+				return;
+                        case REG_TM0CNTL :
+                        case REG_TM1CNTL :
+                        case REG_TM2CNTL :
+                        case REG_TM3CNTL :
+				MMU.timerReload[proc][(adr>>2)&3] = val;
+				return;
+                        case REG_TM0CNTH :
+                        case REG_TM1CNTH :
+                        case REG_TM2CNTH :
+                        case REG_TM3CNTH :
+				if(val&0x80)
+				{
+				  MMU.timer[proc][((adr-2)>>2)&0x3] = MMU.timerReload[proc][((adr-2)>>2)&0x3];
+				}
+				MMU.timerON[proc][((adr-2)>>2)&0x3] = val & 0x80;
+				switch(val&7)
+				{
+				case 0 :
+					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0+1;//proc;
+					break;
+				case 1 :
+					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 6+1;//proc;
+					break;
+				case 2 :
+					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 8+1;//proc;
+					break;
+				case 3 :
+					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 10+1;//proc;
+					break;
+				default :
+					MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0xFFFF;
+					break;
+				}
+				if(!(val & 0x80))
+				MMU.timerRUN[proc][((adr-2)>>2)&0x3] = false;
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val);
+				return;
+                        case REG_DISPA_DISPCNT+2 :
+				{
+				//execute = false;
+				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF) | ((u32) val << 16);
+				GPU_setVideoProp(MainScreen.gpu, v);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v);
+				}
+				return;
+                        case REG_DISPA_DISPCNT :
+				if(proc == ARMCPU_ARM9)
+				{
+				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF0000) | val;
+				GPU_setVideoProp(MainScreen.gpu, v);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v);
+				}
+				return;
+                        case REG_DISPA_DISPCAPCNT :
+				if(proc == ARMCPU_ARM9)
+				{
+					GPU_set_DISPCAPCNT(MainScreen.gpu,val);
+				}
+				return;
+                        case REG_DISPB_DISPCNT+2 :
+				if(proc == ARMCPU_ARM9)
+				{
+				//execute = false;
+				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16);
+				GPU_setVideoProp(SubScreen.gpu, v);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v);
+				}
+				return;
+                        case REG_DISPB_DISPCNT :
+				{
+				u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF0000) | val;
+				GPU_setVideoProp(SubScreen.gpu, v);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v);
+				}
+				return;
+			//case 0x020D8460 :
+			/*case 0x0235A904 :
+				LOG("ECRIRE %d %04X\r\n", proc, val);
+				execute = false;*/
+                                case REG_DMA0CNTH :
+				{
+                                u32 v;
+
+				//if(val&0x8000) execute = false;
+				//LOG("16 bit dma0 %04X\r\n", val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xBA, val);
+				DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0);
+				DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4);
+                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8);
+				MMU.DMAStartTime[proc][0] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
+				MMU.DMACrt[proc][0] = v;
+				if(MMU.DMAStartTime[proc][0] == 0)
+					MMU_doDMA(proc, 0);
+				#ifdef LOG_DMA2
+				//else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], (val&(1<<25))?"ON":"OFF");
+				}
+				#endif
+				}
+				return;
+                                case REG_DMA1CNTH :
+				{
+                                u32 v;
+				//if(val&0x8000) execute = false;
+				//LOG("16 bit dma1 %04X\r\n", val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC6, val);
+				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC);
+				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0);
+                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC4);
+				MMU.DMAStartTime[proc][1] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
+				MMU.DMACrt[proc][1] = v;
+				if(MMU.DMAStartTime[proc][1] == 0)
+					MMU_doDMA(proc, 1);
+				#ifdef LOG_DMA2
+				//else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], (val&(1<<25))?"ON":"OFF");
+				}
+				#endif
+				}
+				return;
+                                case REG_DMA2CNTH :
+				{
+                                u32 v;
+				//if(val&0x8000) execute = false;
+				//LOG("16 bit dma2 %04X\r\n", val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xD2, val);
+				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8);
+				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC);
+                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD0);
+				MMU.DMAStartTime[proc][2] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
+				MMU.DMACrt[proc][2] = v;
+				if(MMU.DMAStartTime[proc][2] == 0)
+					MMU_doDMA(proc, 2);
+				#ifdef LOG_DMA2
+				//else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], (val&(1<<25))?"ON":"OFF");
+				}
+				#endif
+				}
+				return;
+                                case REG_DMA3CNTH :
+				{
+                                u32 v;
+				//if(val&0x8000) execute = false;
+				//LOG("16 bit dma3 %04X\r\n", val);
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xDE, val);
+				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4);
+				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8);
+                                v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xDC);
+				MMU.DMAStartTime[proc][3] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7);
+				MMU.DMACrt[proc][3] = v;
+
+				if(MMU.DMAStartTime[proc][3] == 0)
+					MMU_doDMA(proc, 3);
+				#ifdef LOG_DMA2
+				//else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], (val&(1<<25))?"ON":"OFF");
+				}
+				#endif
+				}
+				return;
+                        //case REG_AUXSPICNT : execute = false;
+			default :
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
+				return;
+		}
+	}
+	T1WriteWord(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
+}
+
+
+void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val)
+{
+#ifdef INTERNAL_DTCM_WRITE
+	if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion))
+	{
+		T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
+		return ;
+	}
+#endif
+
+	// CFlash writing, Mic
+	if ((adr>=0x9000000)&&(adr<0x9900000)) {
+	   cflash_write(adr,val);
+	   return;
+	}
+
+	adr &= 0x0FFFFFFF;
+
+        // This is bad, remove it
+        if(proc == ARMCPU_ARM7)
+        {
+           if ((adr>=0x04000400)&&(adr<0x0400051D))
+           {
+              SPU_WriteLong(adr, val);
+              return;
+           }
+        }
+
+		if ((adr & 0xFF800000) == 0x04800000) {
+		/* access to non regular hw registers */
+		/* return to not overwrite valid data */
+			return ;
+		} ;
+
+
+	if((adr>>24)==4)
+	{
+		if (adr >= 0x04000400 && adr < 0x04000440)
+		{
+			// Geometry commands (aka Dislay Lists) - Parameters:X
+			((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x400>>2] = val;
+#if VIO2SF_GPU_ENABLE
+			if(proc==ARMCPU_ARM9)
+			{
+				gpu3D->NDS_3D_CallList(val);
+			}
+#endif
+		}
+		else
+		switch(adr)
+		{
+#if VIO2SF_GPU_ENABLE
+			// Alpha test reference value - Parameters:1
+			case 0x04000340:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_AlphaFunc(val);
+				}
+				return;
+			}
+			// Clear background color setup - Parameters:2
+			case 0x04000350:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x350>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_ClearColor(val);
+				}
+				return;
+			}
+			// Clear background depth setup - Parameters:2
+			case 0x04000354:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_ClearDepth(val);
+				}
+				return;
+			}
+			// Fog Color - Parameters:4b
+			case 0x04000358:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x358>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_FogColor(val);
+				}
+				return;
+			}
+			case 0x0400035C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_FogOffset(val);
+				}
+				return;
+			}
+			// Matrix mode - Parameters:1
+			case 0x04000440:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x440>>2] = val;
+
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_MatrixMode(val);
+				}
+				return;
+			}
+			// Push matrix - Parameters:0
+			case 0x04000444:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x444>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_PushMatrix();
+				}
+				return;
+			}
+			// Pop matrix/es - Parameters:1
+			case 0x04000448:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x448>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_PopMatrix(val);
+				}
+				return;
+			}
+			// Store matrix in the stack - Parameters:1
+			case 0x0400044C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x44C>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_StoreMatrix(val);
+				}
+				return;
+			}
+			// Restore matrix from the stack - Parameters:1
+			case 0x04000450:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x450>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_RestoreMatrix(val);
+				}
+				return;
+			}
+			// Load Identity matrix - Parameters:0
+			case 0x04000454:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x454>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_LoadIdentity();
+				}
+				return;
+			}
+			// Load 4x4 matrix - Parameters:16
+			case 0x04000458:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x458>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_LoadMatrix4x4(val);
+				}
+				return;
+			}
+			// Load 4x3 matrix - Parameters:12
+			case 0x0400045C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x45C>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_LoadMatrix4x3(val);
+				}
+				return;
+			}
+			// Multiply 4x4 matrix - Parameters:16
+			case 0x04000460:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x460>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_MultMatrix4x4(val);
+				}
+				return;
+			}
+			// Multiply 4x4 matrix - Parameters:12
+			case 0x04000464:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x464>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_MultMatrix4x3(val);
+				}
+				return;
+			}
+			// Multiply 3x3 matrix - Parameters:9
+			case 0x04000468 :
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x468>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_MultMatrix3x3(val);
+				}
+				return;
+			}
+			// Multiply current matrix by scaling matrix - Parameters:3
+			case 0x0400046C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x46C>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Scale(val);
+				}
+				return;
+			}
+			// Multiply current matrix by translation matrix - Parameters:3
+			case 0x04000470:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x470>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Translate(val);
+				}
+				return;
+			}
+			// Set vertex color - Parameters:1
+			case 0x04000480:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x480>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Color3b(val);
+				}
+				return;
+			}
+			// Set vertex normal - Parameters:1
+			case 0x04000484:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x484>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Normal(val);
+				}
+				return;
+			}
+			// Set vertex texture coordinate - Parameters:1
+			case 0x04000488:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x488>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_TexCoord(val);
+				}
+				return;
+			}
+			// Set vertex position 16b/coordinate - Parameters:2
+			case 0x0400048C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x48C>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Vertex16b(val);
+				}
+				return;
+			}
+			// Set vertex position 10b/coordinate - Parameters:1
+			case 0x04000490:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x490>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Vertex10b(val);
+				}
+				return;
+			}
+			// Set vertex XY position - Parameters:1
+			case 0x04000494:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x494>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+                    gpu3D->NDS_3D_Vertex3_cord(0,1,val);
+				}
+				return;
+			}
+			// Set vertex XZ position - Parameters:1
+			case 0x04000498:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x498>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+                    gpu3D->NDS_3D_Vertex3_cord(0,2,val);
+				}
+				return;
+			}
+			// Set vertex YZ position - Parameters:1
+			case 0x0400049C:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x49C>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+                    gpu3D->NDS_3D_Vertex3_cord(1,2,val);
+				}
+				return;
+			}
+			// Set vertex difference position (offset from the last vertex) - Parameters:1
+			case 0x040004A0:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A0>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+                    gpu3D->NDS_3D_Vertex_rel (val);
+				}
+				return;
+			}
+			// Set polygon attributes - Parameters:1
+			case 0x040004A4:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A4>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_PolygonAttrib(val);
+				}
+				return;
+			}
+			// Set texture parameteres - Parameters:1
+			case 0x040004A8:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A8>>2] = val;
+				if(proc==ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_TexImage(val);
+				}
+				return;
+			}
+			// Set palette base address - Parameters:1
+			case 0x040004AC:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4AC>>2] = val&0x1FFF;
+				if(proc==ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_TexPalette(val&0x1FFFF);
+				}
+				return;
+			}
+			// Set material diffuse/ambient parameters - Parameters:1
+			case 0x040004C0:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C0>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Material0 (val);
+				}
+				return;
+			}
+			// Set material reflection/emission parameters - Parameters:1
+			case 0x040004C4:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C4>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Material1 (val);
+				}
+				return;
+			}
+			// Light direction vector - Parameters:1
+			case 0x040004C8:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C8>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_LightDirection (val);
+				}
+				return;
+			}
+			// Light color - Parameters:1
+			case 0x040004CC:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4CC>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_LightColor(val);
+				}
+				return;
+			}
+			// Material Shininess - Parameters:32
+			case 0x040004D0:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4D0>>2] = val;
+                if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Shininess(val);
+				}
+				return;
+			}
+			// Begin vertex list - Parameters:1
+			case 0x04000500:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x500>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Begin(val);
+				}
+				return;
+			}
+			// End vertex list - Parameters:0
+			case 0x04000504:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x504>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_End();
+				}
+				return;
+			}
+			// Swap rendering engine buffers - Parameters:1
+			case 0x04000540:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x540>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_Flush(val);
+				}
+				return;
+			}
+			// Set viewport coordinates - Parameters:1
+			case 0x04000580:
+			{
+				((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x580>>2] = val;
+				if(proc == ARMCPU_ARM9)
+				{
+					gpu3D->NDS_3D_ViewPort(val);
+				}
+				return;
+			}
+#endif
+
+			case REG_DISPA_WININ:
+			{
+	            if(proc == ARMCPU_ARM9)
+	            {
+	                    GPU_setWININ	(MainScreen.gpu, val & 0xFFFF) ;
+	                    GPU_setWINOUT16	(MainScreen.gpu, (val >> 16) & 0xFFFF) ;
+	            }
+	            break;
+			}
+			case REG_DISPB_WININ:
+			{
+	            if(proc == ARMCPU_ARM9)
+	            {
+	                    GPU_setWININ	(SubScreen.gpu, val & 0xFFFF) ;
+	                    GPU_setWINOUT16	(SubScreen.gpu, (val >> 16) & 0xFFFF) ;
+	            }
+	            break;
+			}
+
+			case REG_DISPA_BLDCNT:
+			{
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBLDCNT   (MainScreen.gpu,val&0xffff);
+					GPU_setBLDALPHA (MainScreen.gpu,val>>16);
+				}
+				break;
+			}
+			case REG_DISPB_BLDCNT:
+			{
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBLDCNT   (SubScreen.gpu,val&0xffff);
+					GPU_setBLDALPHA (SubScreen.gpu,val>>16);
+				}
+				break;
+			}
+/*
+ // Commented out, as this doesn't use the plug-in system, neither works
+			case cmd_3D_MTX_MODE        // 0x04000440 :
+				if (proc == ARMCPU_ARM9) gl_MTX_MODE(val);
+				return;
+			case cmd_3D_MTX_PUSH        // 0x04000444  :
+			case cmd_3D_MTX_POP         // 0x04000448  :
+			case cmd_3D_MTX_STORE       // 0x0400044C  :
+			case cmd_3D_MTX_RESTORE     // 0x04000450  :
+				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
+				return;
+			case cmd_3D_MTX_IDENTITY    // 0x04000454  :
+				if (proc == ARMCPU_ARM9) gl_MTX_IDENTITY();
+				return;
+			case cmd_3D_MTX_LOAD_4x4    // 0x04000458  :
+				if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x4(val);
+				return;
+			case cmd_3D_MTX_LOAD_4x3    // 0x0400045C  :
+				if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x3(val);
+				return;
+			case cmd_3D_MTX_MULT_4x4    // 0x04000460  :
+				if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x4(val);
+				return;
+			case cmd_3D_MTX_MULT_4x3    // 0x04000464  :
+				if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x3(val);
+				return;
+			case cmd_3D_MTX_MULT_3x3    // 0x04000468  :
+				if (proc == ARMCPU_ARM9) gl_MTX_MULT_3x3(val);
+				return;
+			case cmd_3D_MTX_SCALE       // 0x0400046C  :
+			case cmd_3D_MTX_TRANS       // 0x04000470  :
+			case cmd_3D_COLOR           // 0x04000480  :
+			case cmd_3D_NORMA           // 0x04000484  :
+				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
+				return;
+			case cmd_3D_TEXCOORD        // 0x04000488  :
+				if (proc == ARMCPU_ARM9) gl_TEXCOORD(val);
+				return;
+			case cmd_3D_VTX_16          // 0x0400048C  :
+				if (proc == ARMCPU_ARM9) gl_VTX_16(val);
+				return;
+			case cmd_3D_VTX_10          // 0x04000490  :
+				if (proc == ARMCPU_ARM9) gl_VTX_10(val);
+				return;
+			case cmd_3D_VTX_XY          // 0x04000494  :
+				if (proc == ARMCPU_ARM9) gl_VTX_XY(val);
+				return;
+			case cmd_3D_VTX_XZ          // 0x04000498  :
+				if (proc == ARMCPU_ARM9) gl_VTX_XZ(val);
+				return;
+			case cmd_3D_VTX_YZ          // 0x0400049C  :
+				if (proc == ARMCPU_ARM9) gl_VTX_YZ(val);
+				return;
+			case cmd_3D_VTX_DIFF        // 0x040004A0  :
+				if (proc == ARMCPU_ARM9) gl_VTX_DIFF(val);
+				return;
+			case cmd_3D_POLYGON_ATTR    // 0x040004A4  :
+			case cmd_3D_TEXIMAGE_PARAM  // 0x040004A8  :
+			case cmd_3D_PLTT_BASE       // 0x040004AC  :
+			case cmd_3D_DIF_AMB         // 0x040004C0  :
+			case cmd_3D_SPE_EMI         // 0x040004C4  :
+			case cmd_3D_LIGHT_VECTOR    // 0x040004C8  :
+			case cmd_3D_LIGHT_COLOR     // 0x040004CC  :
+			case cmd_3D_SHININESS       // 0x040004D0  :
+				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
+				return;
+			case cmd_3D_BEGIN_VTXS      // 0x04000500  :
+				if (proc == ARMCPU_ARM9) gl_VTX_begin(val);
+				return;
+			case cmd_3D_END_VTXS        // 0x04000504  :
+				if (proc == ARMCPU_ARM9) gl_VTX_end();
+				return;
+			case cmd_3D_SWAP_BUFFERS    // 0x04000540  :
+			case cmd_3D_VIEWPORT        // 0x04000580  :
+			case cmd_3D_BOX_TEST        // 0x040005C0  :
+			case cmd_3D_POS_TEST        // 0x040005C4  :
+			case cmd_3D_VEC_TEST        // 0x040005C8  :
+				if (proc == ARMCPU_ARM9) gl_print_cmd(adr);
+				return;
+*/
+                        case REG_DISPA_DISPCNT :
+								if(proc == ARMCPU_ARM9) GPU_setVideoProp(MainScreen.gpu, val);
+
+				//GPULOG("MAIN INIT 32B %08X\r\n", val);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, val);
+				return;
+
+                        case REG_DISPB_DISPCNT :
+				if (proc == ARMCPU_ARM9) GPU_setVideoProp(SubScreen.gpu, val);
+				//GPULOG("SUB INIT 32B %08X\r\n", val);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, val);
+				return;
+			case REG_VRAMCNTA:
+			case REG_VRAMCNTE:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				MMU_write8(proc,adr+1,val >> 8) ;
+				MMU_write8(proc,adr+2,val >> 16) ;
+				MMU_write8(proc,adr+3,val >> 24) ;
+				return ;
+			case REG_VRAMCNTI:
+				MMU_write8(proc,adr,val & 0xFF) ;
+				return ;
+
+                        case REG_IME : {
+			        u32 old_val = MMU.reg_IME[proc];
+				u32 new_val = val & 1;
+				MMU.reg_IME[proc] = new_val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val);
+				if ( new_val && old_val != new_val) {
+				  /* raise an interrupt request to the CPU if needed */
+				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
+				    NDS_ARM7.wIRQ = true;
+				    NDS_ARM7.waitIRQ = false;
+				  }
+				}
+				return;
+			}
+
+			case REG_IE :
+				MMU.reg_IE[proc] = val;
+				if ( MMU.reg_IME[proc]) {
+				  /* raise an interrupt request to the CPU if needed */
+				  if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) {
+				    NDS_ARM7.wIRQ = true;
+				    NDS_ARM7.waitIRQ = false;
+				  }
+				}
+				return;
+
+			case REG_IF :
+				MMU.reg_IF[proc] &= (~val);
+				return;
+                        case REG_TM0CNTL :
+                        case REG_TM1CNTL :
+                        case REG_TM2CNTL :
+                        case REG_TM3CNTL :
+				MMU.timerReload[proc][(adr>>2)&0x3] = (u16)val;
+				if(val&0x800000)
+				{
+					MMU.timer[proc][(adr>>2)&0x3] = MMU.timerReload[proc][(adr>>2)&0x3];
+				}
+				MMU.timerON[proc][(adr>>2)&0x3] = val & 0x800000;
+				switch((val>>16)&7)
+				{
+					case 0 :
+					MMU.timerMODE[proc][(adr>>2)&0x3] = 0+1;//proc;
+					break;
+					case 1 :
+					MMU.timerMODE[proc][(adr>>2)&0x3] = 6+1;//proc;
+					break;
+					case 2 :
+					MMU.timerMODE[proc][(adr>>2)&0x3] = 8+1;//proc;
+					break;
+					case 3 :
+					MMU.timerMODE[proc][(adr>>2)&0x3] = 10+1;//proc;
+					break;
+					default :
+					MMU.timerMODE[proc][(adr>>2)&0x3] = 0xFFFF;
+					break;
+				}
+				if(!(val & 0x800000))
+				{
+					MMU.timerRUN[proc][(adr>>2)&0x3] = false;
+				}
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val);
+				return;
+                        case REG_DIVDENOM :
+				{
+                                        u16 cnt;
+					s64 num = 0;
+					s64 den = 1;
+					s64 res;
+					s64 mod;
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x298, val);
+                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280);
+					switch(cnt&3)
+					{
+					case 0:
+					{
+						num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x290);
+						den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298);
+					}
+					break;
+					case 1:
+					{
+						num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290);
+						den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298);
+					}
+					break;
+					case 2:
+					{
+						return;
+					}
+					break;
+					default:
+						break;
+					}
+					if(den==0)
+					{
+						res = 0;
+						mod = 0;
+						cnt |= 0x4000;
+						cnt &= 0x7FFF;
+					}
+					else
+					{
+						res = num / den;
+						mod = num % den;
+						cnt &= 0x3FFF;
+					}
+					DIVLOG("BOUT1 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num,
+											(u32)(den>>32), (u32)den,
+											(u32)(res>>32), (u32)res);
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res);
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt);
+				}
+				return;
+                        case REG_DIVDENOM+4 :
+			{
+                                u16 cnt;
+				s64 num = 0;
+				s64 den = 1;
+				s64 res;
+				s64 mod;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x29C, val);
+                                cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280);
+				switch(cnt&3)
+				{
+				case 0:
+				{
+					return;
+				}
+				break;
+				case 1:
+				{
+					return;
+				}
+				break;
+				case 2:
+				{
+					num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290);
+					den = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x298);
+				}
+				break;
+				default:
+					break;
+				}
+				if(den==0)
+				{
+					res = 0;
+					mod = 0;
+					cnt |= 0x4000;
+					cnt &= 0x7FFF;
+				}
+				else
+				{
+					res = num / den;
+					mod = num % den;
+					cnt &= 0x3FFF;
+				}
+				DIVLOG("BOUT2 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num,
+										(u32)(den>>32), (u32)den,
+										(u32)(res>>32), (u32)res);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32));
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod);
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32));
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt);
+			}
+			return;
+                        case REG_SQRTPARAM :
+				{
+                                        u16 cnt;
+					u64 v = 1;
+					//execute = false;
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B8, val);
+                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0);
+					switch(cnt&1)
+					{
+					case 0:
+						v = (u64) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B8);
+						break;
+					case 1:
+						return;
+					}
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v));
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
+					SQRTLOG("BOUT1 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v,
+										T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4));
+				}
+				return;
+                        case REG_SQRTPARAM+4 :
+				{
+                                        u16 cnt;
+					u64 v = 1;
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2BC, val);
+                                        cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0);
+					switch(cnt&1)
+					{
+					case 0:
+						return;
+						//break;
+					case 1:
+						v = T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x2B8);
+						break;
+					}
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v));
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF);
+					SQRTLOG("BOUT2 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v,
+										T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4));
+				}
+				return;
+                        case REG_IPCSYNC :
+				{
+					//execute=false;
+					u32 remote = (proc+1)&1;
+					u32 IPCSYNC_remote = T1ReadLong(MMU.MMU_MEM[remote][0x40], 0x180);
+					T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
+					T1WriteLong(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF));
+					MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));//
+				}
+				return;
+                        case REG_IPCFIFOCNT :
+							{
+					u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
+					u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
+					if ((val & 0x8000) && !(cnt_l & 0x8000))
+					{
+						/* this is the first init, the other side didnt init yet */
+						/* so do a complete init */
+						FIFOInit(MMU.fifos + (IPCFIFO+proc));
+						T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ;
+						/* and then handle it as usual */
+					}
+				if(val & 0x4008)
+				{
+					FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1)));
+					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
+					T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
+					MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);//
+					return;
+				}
+				T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4);
+				//execute = false;
+				return;
+							}
+                        case REG_IPCFIFOSEND :
+				{
+					u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
+					if(IPCFIFO_CNT&0x8000)
+					{
+					//if(val==43) execute = false;
+					u32 remote = (proc+1)&1;
+					u32 fifonum = IPCFIFO+remote;
+                                        u16 IPCFIFO_CNT_remote;
+					FIFOAdd(MMU.fifos + fifonum, val);
+					IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (MMU.fifos[fifonum].full<<1);
+                                        IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184);
+					IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (MMU.fifos[fifonum].full<<10);
+					T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
+					T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
+					MMU.reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU.reg_IME[remote] << 18);// & (MMU.reg_IE[remote] & 0x40000);//
+					//execute = false;
+					}
+				}
+				return;
+			case REG_DMA0CNTL :
+				//LOG("32 bit dma0 %04X\r\n", val);
+				DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0);
+				DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4);
+				MMU.DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
+				MMU.DMACrt[proc][0] = val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8, val);
+				if( MMU.DMAStartTime[proc][0] == 0 ||
+					MMU.DMAStartTime[proc][0] == 7)		// Start Immediately
+					MMU_doDMA(proc, 0);
+				#ifdef LOG_DMA2
+				else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], 0, ((MMU.DMACrt[proc][0]>>27)&7));
+				}
+				#endif
+				//execute = false;
+				return;
+			case REG_DMA1CNTL:
+				//LOG("32 bit dma1 %04X\r\n", val);
+				DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC);
+				DMADst[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0);
+				MMU.DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
+				MMU.DMACrt[proc][1] = val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xC4, val);
+				if(MMU.DMAStartTime[proc][1] == 0 ||
+					MMU.DMAStartTime[proc][1] == 7)		// Start Immediately
+					MMU_doDMA(proc, 1);
+				#ifdef LOG_DMA2
+				else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], 0, ((MMU.DMACrt[proc][1]>>27)&7));
+				}
+				#endif
+				return;
+			case REG_DMA2CNTL :
+				//LOG("32 bit dma2 %04X\r\n", val);
+				DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8);
+				DMADst[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC);
+				MMU.DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
+				MMU.DMACrt[proc][2] = val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xD0, val);
+				if(MMU.DMAStartTime[proc][2] == 0 ||
+					MMU.DMAStartTime[proc][2] == 7)		// Start Immediately
+					MMU_doDMA(proc, 2);
+				#ifdef LOG_DMA2
+				else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], 0, ((MMU.DMACrt[proc][2]>>27)&7));
+				}
+				#endif
+				return;
+			case 0x040000DC :
+				//LOG("32 bit dma3 %04X\r\n", val);
+				DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4);
+				DMADst[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8);
+				MMU.DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7);
+				MMU.DMACrt[proc][3] = val;
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xDC, val);
+				if(	MMU.DMAStartTime[proc][3] == 0 ||
+					MMU.DMAStartTime[proc][3] == 7)		// Start Immediately
+					MMU_doDMA(proc, 3);
+				#ifdef LOG_DMA2
+				else
+				{
+					LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], 0, ((MMU.DMACrt[proc][3]>>27)&7));
+				}
+				#endif
+				return;
+                        case REG_GCROMCTRL :
+				{
+					int i;
+
+                                        if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7)
+					{
+                                                MMU.dscard[proc].adress = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4));
+						MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7));
+					}
+                                        else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8)
+                                        {
+                                                // Get ROM chip ID
+                                                val |= 0x800000; // Data-Word Status
+                                                T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
+                                                MMU.dscard[proc].adress = 0;
+                                        }
+					else
+					{
+                                                LOG("CARD command: %02X\n", MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT));
+					}
+
+					//CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]);
+                    val |= 0x00800000;
+
+					if(MMU.dscard[proc].adress == 0)
+					{
+                                                val &= ~0x80000000;
+                                                T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
+						return;
+					}
+                                        T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
+
+					/* launch DMA if start flag was set to "DS Cart" */
+					if(proc == ARMCPU_ARM7) i = 2;
+					else i = 5;
+
+					if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][0] == i)	/* dma0/1 on arm7 can't start on ds cart event */
+					{
+						MMU_doDMA(proc, 0);
+						return;
+					}
+					else if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][1] == i)
+					{
+						MMU_doDMA(proc, 1);
+						return;
+					}
+					else if(MMU.DMAStartTime[proc][2] == i)
+					{
+						MMU_doDMA(proc, 2);
+						return;
+					}
+					else if(MMU.DMAStartTime[proc][3] == i)
+					{
+						MMU_doDMA(proc, 3);
+						return;
+					}
+					return;
+
+				}
+				return;
+								case REG_DISPA_DISPCAPCNT :
+				if(proc == ARMCPU_ARM9)
+				{
+					GPU_set_DISPCAPCNT(MainScreen.gpu,val);
+					T1WriteLong(ARM9Mem.ARM9_REG, 0x64, val);
+				}
+				return;
+
+                        case REG_DISPA_BG0CNT :
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBGProp(MainScreen.gpu, 0, (val&0xFFFF));
+					GPU_setBGProp(MainScreen.gpu, 1, (val>>16));
+				}
+				//if((val>>16)==0x400) execute = false;
+				T1WriteLong(ARM9Mem.ARM9_REG, 8, val);
+				return;
+                        case REG_DISPA_BG2CNT :
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBGProp(MainScreen.gpu, 2, (val&0xFFFF));
+					GPU_setBGProp(MainScreen.gpu, 3, (val>>16));
+				}
+				T1WriteLong(ARM9Mem.ARM9_REG, 0xC, val);
+				return;
+                        case REG_DISPB_BG0CNT :
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBGProp(SubScreen.gpu, 0, (val&0xFFFF));
+					GPU_setBGProp(SubScreen.gpu, 1, (val>>16));
+				}
+				T1WriteLong(ARM9Mem.ARM9_REG, 0x1008, val);
+				return;
+                        case REG_DISPB_BG2CNT :
+				if (proc == ARMCPU_ARM9)
+				{
+					GPU_setBGProp(SubScreen.gpu, 2, (val&0xFFFF));
+					GPU_setBGProp(SubScreen.gpu, 3, (val>>16));
+				}
+				T1WriteLong(ARM9Mem.ARM9_REG, 0x100C, val);
+				return;
+			case REG_DISPA_DISPMMEMFIFO:
+			{
+				// NOTE: right now, the capture unit is not taken into account,
+				//       I don't know is it should be handled here or
+
+				FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val);
+				break;
+			}
+			//case 0x21FDFF0 :  if(val==0) execute = false;
+			//case 0x21FDFB0 :  if(val==0) execute = false;
+			default :
+				T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
+				return;
+		}
+	}
+	T1WriteLong(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val);
+}
+
+
+void FASTCALL MMU_doDMA(u32 proc, u32 num)
+{
+	u32 src = DMASrc[proc][num];
+	u32 dst = DMADst[proc][num];
+        u32 taille;
+
+	if(src==dst)
+	{
+		T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num), T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF);
+		return;
+	}
+
+	if((!(MMU.DMACrt[proc][num]&(1<<31)))&&(!(MMU.DMACrt[proc][num]&(1<<25))))
+	{       /* not enabled and not to be repeated */
+		MMU.DMAStartTime[proc][num] = 0;
+		MMU.DMACycle[proc][num] = 0;
+		//MMU.DMAing[proc][num] = false;
+		return;
+	}
+
+
+	/* word count */
+	taille = (MMU.DMACrt[proc][num]&0xFFFF);
+
+	// If we are in "Main memory display" mode just copy an entire
+	// screen (256x192 pixels).
+	//    Reference:  http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
+	//       (under DISP_MMEM_FIFO)
+	if ((MMU.DMAStartTime[proc][num]==4) &&		// Must be in main memory display mode
+		(taille==4) &&							// Word must be 4
+		(((MMU.DMACrt[proc][num]>>26)&1) == 1))	// Transfer mode must be 32bit wide
+		taille = 256*192/2;
+
+	if(MMU.DMAStartTime[proc][num] == 5)
+		taille *= 0x80;
+
+	MMU.DMACycle[proc][num] = taille + nds.cycles;
+	MMU.DMAing[proc][num] = true;
+
+	DMALOG("proc %d, dma %d src %08X dst %08X start %d taille %d repeat %s %08X\r\n",
+		proc, num, src, dst, MMU.DMAStartTime[proc][num], taille,
+		(MMU.DMACrt[proc][num]&(1<<25))?"on":"off",MMU.DMACrt[proc][num]);
+
+	if(!(MMU.DMACrt[proc][num]&(1<<25)))
+		MMU.DMAStartTime[proc][num] = 0;
+
+	// transfer
+	{
+		u32 i=0;
+		// 32 bit or 16 bit transfer ?
+		int sz = ((MMU.DMACrt[proc][num]>>26)&1)? 4 : 2;
+		int dstinc,srcinc;
+		int u=(MMU.DMACrt[proc][num]>>21);
+		switch(u & 0x3) {
+			case 0 :  dstinc =  sz; break;
+			case 1 :  dstinc = -sz; break;
+			case 2 :  dstinc =   0; break;
+			case 3 :  dstinc =  sz; break; //reload
+		}
+		switch((u >> 2)&0x3) {
+			case 0 :  srcinc =  sz; break;
+			case 1 :  srcinc = -sz; break;
+			case 2 :  srcinc =   0; break;
+			case 3 :  // reserved
+				return;
+		}
+		if ((MMU.DMACrt[proc][num]>>26)&1)
+			for(; i < taille; ++i)
+			{
+				MMU_write32(proc, dst, MMU_read32(proc, src));
+				dst += dstinc;
+				src += srcinc;
+			}
+		else
+			for(; i < taille; ++i)
+			{
+				MMU_write16(proc, dst, MMU_read16(proc, src));
+				dst += dstinc;
+				src += srcinc;
+			}
+	}
+}
+
+#ifdef MMU_ENABLE_ACL
+
+INLINE void check_access(u32 adr, u32 access) {
+	/* every other mode: sys */
+	access |= 1;
+	if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) {
+		/* is user mode access */
+		access ^= 1 ;
+	}
+	if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==false) {
+		execute = false ;
+	}
+}
+INLINE void check_access_write(u32 adr) {
+	u32 access = CP15_ACCESS_WRITE;
+	check_access(adr, access)
+}
+
+u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access)
+{
+	/* on arm9 we need to check the MPU regions */
+	if (proc == ARMCPU_ARM9)
+		check_access(u32 adr, u32 access);
+	return MMU_read8(proc,adr);
+}
+u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access)
+{
+	/* on arm9 we need to check the MPU regions */
+	if (proc == ARMCPU_ARM9)
+		check_access(u32 adr, u32 access);
+	return MMU_read16(proc,adr);
+}
+u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access)
+{
+	/* on arm9 we need to check the MPU regions */
+	if (proc == ARMCPU_ARM9)
+		check_access(u32 adr, u32 access);
+	return MMU_read32(proc,adr);
+}
+
+void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val)
+{
+	/* check MPU region on ARM9 */
+	if (proc == ARMCPU_ARM9)
+		check_access_write(adr);
+	MMU_write8(proc,adr,val);
+}
+void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val)
+{
+	/* check MPU region on ARM9 */
+	if (proc == ARMCPU_ARM9)
+		check_access_write(adr);
+	MMU_write16(proc,adr,val) ;
+}
+void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val)
+{
+	/* check MPU region on ARM9 */
+	if (proc == ARMCPU_ARM9)
+		check_access_write(adr);
+	MMU_write32(proc,adr,val) ;
+}
+#endif
+
+
+
+#ifdef PROFILE_MEMORY_ACCESS
+
+#define PROFILE_PREFETCH 0
+#define PROFILE_READ 1
+#define PROFILE_WRITE 2
+
+struct mem_access_profile {
+  u64 num_accesses;
+  u32 address_mask;
+  u32 masked_value;
+};
+
+#define PROFILE_NUM_MEM_ACCESS_PROFILES 4
+
+static u64 profile_num_accesses[2][3];
+static u64 profile_unknown_addresses[2][3];
+static struct mem_access_profile
+profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES];
+
+static void
+setup_profiling( void) {
+  int i;
+
+  for ( i = 0; i < 2; i++) {
+    int access_type;
+
+    for ( access_type = 0; access_type < 3; access_type++) {
+      profile_num_accesses[i][access_type] = 0;
+      profile_unknown_addresses[i][access_type] = 0;
+
+      /*
+       * Setup the access testing structures
+       */
+      profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000;
+      profile_memory_accesses[i][access_type][0].masked_value = 0x00000000;
+      profile_memory_accesses[i][access_type][0].num_accesses = 0;
+
+      /* main memory */
+      profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000;
+      profile_memory_accesses[i][access_type][1].masked_value = 0x02000000;
+      profile_memory_accesses[i][access_type][1].num_accesses = 0;
+
+      /* shared memory */
+      profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000;
+      profile_memory_accesses[i][access_type][2].masked_value = 0x03000000;
+      profile_memory_accesses[i][access_type][2].num_accesses = 0;
+
+      /* arm7 memory */
+      profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000;
+      profile_memory_accesses[i][access_type][3].masked_value = 0x03800000;
+      profile_memory_accesses[i][access_type][3].num_accesses = 0;
+    }
+  }
+}
+
+static void
+profile_memory_access( int arm9, u32 adr, int access_type) {
+  static int first = 1;
+  int mem_profile;
+  int address_found = 0;
+
+  if ( first) {
+    setup_profiling();
+    first = 0;
+  }
+
+  profile_num_accesses[arm9][access_type] += 1;
+
+  for ( mem_profile = 0;
+        mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES &&
+          !address_found;
+        mem_profile++) {
+    if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) ==
+         profile_memory_accesses[arm9][access_type][mem_profile].masked_value) {
+      /*printf( "adr %08x mask %08x res %08x expected %08x\n",
+              adr,
+              profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
+              adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask,
+              profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/
+      address_found = 1;
+      profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1;
+    }
+  }
+
+  if ( !address_found) {
+    profile_unknown_addresses[arm9][access_type] += 1;
+  }
+}
+
+
+static const char *access_type_strings[] = {
+  "prefetch",
+  "read    ",
+  "write   "
+};
+
+void
+print_memory_profiling( void) {
+  int arm;
+
+  printf("------ Memory access profile ------\n");
+
+  for ( arm = 0; arm < 2; arm++) {
+    int access_type;
+
+    for ( access_type = 0; access_type < 3; access_type++) {
+      int mem_profile;
+      printf("ARM%c: num of %s %lld\n",
+             arm ? '9' : '7',
+             access_type_strings[access_type],
+             profile_num_accesses[arm][access_type]);
+
+      for ( mem_profile = 0;
+            mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES;
+            mem_profile++) {
+        printf( "address %08lx: %llu\n",
+                profile_memory_accesses[arm][access_type][mem_profile].masked_value,
+                profile_memory_accesses[arm][access_type][mem_profile].num_accesses);
+      }
+
+      printf( "unknown addresses %lld\n",
+              profile_unknown_addresses[arm][access_type]);
+
+      printf( "\n");
+    }
+  }
+
+  printf("------ End of Memory access profile ------\n\n");
+}
+#else
+void
+print_memory_profiling( void) {
+}
+#endif /* End of PROFILE_MEMORY_ACCESS area */
+
+static u16 FASTCALL
+arm9_prefetch16( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_PREFETCH);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Returns data from DTCM (ARM9 only) */
+      return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+    }
+  /* access to main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
+                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read16( ARMCPU_ARM9, adr);
+}
+static u32 FASTCALL
+arm9_prefetch32( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_PREFETCH);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Returns data from DTCM (ARM9 only) */
+      return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+    }
+  /* access to main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
+                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read32( ARMCPU_ARM9, adr);
+}
+
+static u8 FASTCALL
+arm9_read8( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_READ);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if( (adr&(~0x3FFF)) == MMU.DTCMRegion)
+    {
+      return ARM9Mem.ARM9_DTCM[adr&0x3FFF];
+    }
+  /* access to main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    return MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF]
+      [adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]];
+  }
+#endif
+
+  return MMU_read8( ARMCPU_ARM9, adr);
+}
+static u16 FASTCALL
+arm9_read16( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_READ);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Returns data from DTCM (ARM9 only) */
+      return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+    }
+
+  /* access to main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
+                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read16( ARMCPU_ARM9, adr);
+}
+static u32 FASTCALL
+arm9_read32( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_READ);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Returns data from DTCM (ARM9 only) */
+      return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF);
+    }
+  /* access to main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF],
+                       adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read32( ARMCPU_ARM9, adr);
+}
+
+
+static void FASTCALL
+arm9_write8(void *data, u32 adr, u8 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_WRITE);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if( (adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Writes data in DTCM (ARM9 only) */
+      ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val;
+      return ;
+    }
+  /* main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]
+      [adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]] = val;
+    return;
+  }
+#endif
+
+  MMU_write8( ARMCPU_ARM9, adr, val);
+}
+static void FASTCALL
+arm9_write16(void *data, u32 adr, u16 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_WRITE);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Writes in DTCM (ARM9 only) */
+      T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
+      return;
+    }
+  /* main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    T1WriteWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
+                 adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
+    return;
+  }
+#endif
+
+  MMU_write16( ARMCPU_ARM9, adr, val);
+}
+static void FASTCALL
+arm9_write32(void *data, u32 adr, u32 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 1, adr, PROFILE_WRITE);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  if((adr & ~0x3FFF) == MMU.DTCMRegion)
+    {
+      /* Writes in DTCM (ARM9 only) */
+      T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val);
+      return;
+    }
+  /* main memory */
+  if ( (adr & 0x0f000000) == 0x02000000) {
+    T1WriteLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF],
+                 adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val);
+    return;
+  }
+#endif
+
+  MMU_write32( ARMCPU_ARM9, adr, val);
+}
+
+
+
+
+static u16 FASTCALL
+arm7_prefetch16( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_PREFETCH);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  /* ARM7 private memory */
+  if ( (adr & 0x0f800000) == 0x03800000) {
+    T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
+               adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read16( ARMCPU_ARM7, adr);
+}
+static u32 FASTCALL
+arm7_prefetch32( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_PREFETCH);
+#endif
+
+#ifdef EARLY_MEMORY_ACCESS
+  /* ARM7 private memory */
+  if ( (adr & 0x0f800000) == 0x03800000) {
+    T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
+               adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
+  }
+#endif
+
+  return MMU_read32( ARMCPU_ARM7, adr);
+}
+
+static u8 FASTCALL
+arm7_read8( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_READ);
+#endif
+
+  return MMU_read8( ARMCPU_ARM7, adr);
+}
+static u16 FASTCALL
+arm7_read16( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_READ);
+#endif
+
+  return MMU_read16( ARMCPU_ARM7, adr);
+}
+static u32 FASTCALL
+arm7_read32( void *data, u32 adr) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_READ);
+#endif
+
+  return MMU_read32( ARMCPU_ARM7, adr);
+}
+
+
+static void FASTCALL
+arm7_write8(void *data, u32 adr, u8 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_WRITE);
+#endif
+
+  MMU_write8( ARMCPU_ARM7, adr, val);
+}
+static void FASTCALL
+arm7_write16(void *data, u32 adr, u16 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_WRITE);
+#endif
+
+  MMU_write16( ARMCPU_ARM7, adr, val);
+}
+static void FASTCALL
+arm7_write32(void *data, u32 adr, u32 val) {
+#ifdef PROFILE_MEMORY_ACCESS
+  profile_memory_access( 0, adr, PROFILE_WRITE);
+#endif
+
+  MMU_write32( ARMCPU_ARM7, adr, val);
+}
+
+
+
+/*
+ * the base memory interfaces
+ */
+struct armcpu_memory_iface arm9_base_memory_iface = {
+  arm9_prefetch32,
+  arm9_prefetch16,
+
+  arm9_read8,
+  arm9_read16,
+  arm9_read32,
+
+  arm9_write8,
+  arm9_write16,
+  arm9_write32
+};
+
+struct armcpu_memory_iface arm7_base_memory_iface = {
+  arm7_prefetch32,
+  arm7_prefetch16,
+
+  arm7_read8,
+  arm7_read16,
+  arm7_read32,
+
+  arm7_write8,
+  arm7_write16,
+  arm7_write32
+};
+
+/*
+ * The direct memory interface for the ARM9.
+ * This avoids the ARM9 protection unit when accessing
+ * memory.
+ */
+struct armcpu_memory_iface arm9_direct_memory_iface = {
+  /* the prefetch is not used */
+  nullptr,
+  nullptr,
+
+  arm9_read8,
+  arm9_read16,
+  arm9_read32,
+
+  arm9_write8,
+  arm9_write16,
+  arm9_write32
+};
diff --git a/src/xsf/desmume/MMU.h b/src/xsf/desmume/MMU.h
index 75c46c844ed5..e9b7263a7ea1 100644
--- a/src/xsf/desmume/MMU.h
+++ b/src/xsf/desmume/MMU.h
@@ -18,7 +18,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef MMU_H
@@ -30,10 +30,6 @@
 #include "ARM9.h"
 #include "mc.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern char szRomPath[512];
 extern char szRomBaseName[512];
 
@@ -42,35 +38,35 @@ extern char szRomBaseName[512];
 
 /* theses ones for reading in rom data */
 #define ROM_8(m, a)  (((u8*)(m))[(a)])
- 
+
 #define IPCFIFO  0
 #define MAIN_MEMORY_DISP_FIFO 2
- 
+
 typedef struct {
         //ARM7 mem
         u8 ARM7_BIOS[0x4000];
         u8 ARM7_ERAM[0x10000];
         u8 ARM7_REG[0x10000];
         u8 ARM7_WIRAM[0x10000];
-        
+
 	u8 vram_mode[9];
 	u8 vScreen;
 
         //Shared ram
         u8 SWIRAM[0x8000];
-        
+
         //Card rom & ram
         u8 * CART_ROM;
         u8 CART_RAM[0x10000];
 
 	//Unused ram
 	u8 UNUSED_RAM[4];
-        
+
         u8 * * MMU_MEM[2];
         u32 * MMU_MASK[2];
-        
+
         u8 ARM9_RW_MODE;
-        
+
         FIFO fifos[16];
 
         u32 * MMU_WAIT16[2];
@@ -78,27 +74,27 @@ typedef struct {
 
         u32 DTCMRegion;
         u32 ITCMRegion;
-        
+
         u16 timer[2][4];
         s32 timerMODE[2][4];
         u32 timerON[2][4];
         u32 timerRUN[2][4];
         u16 timerReload[2][4];
-        
+
         u32 reg_IME[2];
         u32 reg_IE[2];
         u32 reg_IF[2];
-        
+
         u32 DMAStartTime[2][4];
         s32 DMACycle[2][4];
         u32 DMACrt[2][4];
         BOOL DMAing[2][4];
-		  
+
         memory_chip_t fw;
         memory_chip_t bupmem;
-		  
+
         nds_dscard dscard[2];
-		  
+
 } MMU_struct;
 
 extern MMU_struct MMU;
@@ -171,7 +167,7 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val);
 	#define MMU_write16_acl MMU_write16
 	#define MMU_write32_acl MMU_write32
 #endif
- 
+
 void FASTCALL MMU_doDMA(u32 proc, u32 num);
 
 
@@ -180,11 +176,6 @@ void FASTCALL MMU_doDMA(u32 proc, u32 num);
  */
 extern struct armcpu_memory_iface arm9_base_memory_iface;
 extern struct armcpu_memory_iface arm7_base_memory_iface;
-extern struct armcpu_memory_iface arm9_direct_memory_iface;	
-
-
-#ifdef __cplusplus
-}
-#endif
+extern struct armcpu_memory_iface arm9_direct_memory_iface;
 
 #endif
diff --git a/src/xsf/desmume/NDSSystem.c b/src/xsf/desmume/NDSSystem.c
deleted file mode 100644
index cb656c4e41f3..000000000000
--- a/src/xsf/desmume/NDSSystem.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "NDSSystem.h"
-#include "MMU.h"
-//#include "cflash.h"
-
-//#include "ROMReader.h"
-
-/* the count of bytes copied from the firmware into memory */
-#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70
-
-NDSSystem nds;
-
-static u32
-calc_CRC16( u32 start, const u8 *data, int count) {
-  int i,j;
-  u32 crc = start & 0xffff;
-  static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
-  for(i = 0; i < count; i++)
-  {
-    crc = crc ^ data[i];
-
-    for(j = 0; j < 8; j++) {
-      int do_bit = 0;
-
-      if ( crc & 0x1)
-        do_bit = 1;
-
-      crc = crc >> 1;
-
-      if ( do_bit) {
-        crc = crc ^ (val[j] << (7-j));
-      }
-    }
-  }
-  return crc;
-}
-
-static int
-copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) {
-  /*
-   * Determine which of the two user settings in the firmware is the current
-   * and valid one and then copy this into the destination buffer.
-   *
-   * The current setting will have a greater count.
-   * Settings are only valid if its CRC16 is correct.
-   */
-  int user1_valid = 0;
-  int user2_valid = 0;
-  u32 user_settings_offset;
-  u32 fw_crc;
-  u32 crc;
-  int copy_good = 0;
-
-  user_settings_offset = fw_data[0x20];
-  user_settings_offset |= fw_data[0x21] << 8;
-  user_settings_offset <<= 3;
-
-  if ( user_settings_offset <= 0x3FE00) {
-    s32 copy_settings_offset = -1;
-
-    crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
-                      NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
-    fw_crc = fw_data[user_settings_offset + 0x72];
-    fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
-    if ( crc == fw_crc) {
-      user1_valid = 1;
-    }
-
-    crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
-                      NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
-    fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
-    fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
-    if ( crc == fw_crc) {
-      user2_valid = 1;
-    }
-
-    if ( user1_valid) {
-      if ( user2_valid) {
-        u16 count1, count2;
-
-        count1 = fw_data[user_settings_offset + 0x70];
-        count1 |= fw_data[user_settings_offset + 0x71] << 8;
-
-        count2 = fw_data[user_settings_offset + 0x100 + 0x70];
-        count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
-
-        if ( count2 > count1) {
-          copy_settings_offset = user_settings_offset + 0x100;
-        }
-        else {
-          copy_settings_offset = user_settings_offset;
-        }
-      }
-      else {
-        copy_settings_offset = user_settings_offset;
-      }
-    }
-    else if ( user2_valid) {
-      /* copy the second user settings */
-      copy_settings_offset = user_settings_offset + 0x100;
-    }
-
-    if ( copy_settings_offset > 0) {
-      memcpy( dest_buffer, &fw_data[copy_settings_offset],
-              NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
-      copy_good = 1;
-    }
-  }
-
-  return copy_good;
-}
-
-
-#ifdef GDB_STUB
-int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
-              struct armcpu_ctrl_iface **arm9_ctrl_iface,
-              struct armcpu_memory_iface *arm7_mem_if,
-              struct armcpu_ctrl_iface **arm7_ctrl_iface) {
-#else
-int NDS_Init( void) {
-#endif
-     nds.ARM9Cycle = 0;
-     nds.ARM7Cycle = 0;
-     nds.cycles = 0;
-     MMU_Init();
-     nds.nextHBlank = 3168;
-     nds.VCount = 0;
-     nds.lignerendu = FALSE;
-
-     if (Screen_Init(GFXCORE_DUMMY) != 0)
-        return -1;
-     
- #ifdef GDB_STUB
-     armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
-     armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
-#else
-	 armcpu_new(&NDS_ARM7,1);
-     armcpu_new(&NDS_ARM9,0);
-#endif
-
-     if (SPU_Init(SNDCORE_DUMMY, 735) != 0)
-        return -1;
-
-#ifdef EXPERIMENTAL_WIFI
-	 WIFI_Init(&wifiMac) ;
-#endif
-
-     return 0;
-}
-
-static void armcpu_deinit(armcpu_t *armcpu)
-{
-	if(armcpu->coproc[15])
-	{
-		free(armcpu->coproc[15]);
-		armcpu->coproc[15] = 0;
-	}
-}
-
-void NDS_DeInit(void) {
-     if(MMU.CART_ROM != MMU.UNUSED_RAM)
-        NDS_FreeROM();
-
-	armcpu_deinit(&NDS_ARM7);
-	armcpu_deinit(&NDS_ARM9);
-
-     nds.nextHBlank = 3168;
-     SPU_DeInit();
-     Screen_DeInit();
-     MMU_DeInit();
-}
-
-BOOL NDS_SetROM(u8 * rom, u32 mask)
-{
-     MMU_setRom(rom, mask);
-
-     return TRUE;
-} 
-
-NDS_header * NDS_getROMHeader(void)
-{
-	NDS_header * header = malloc(sizeof(NDS_header));
-
-	memcpy(header->gameTile, MMU.CART_ROM, 12);
-	memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
-	header->makerCode = T1ReadWord(MMU.CART_ROM, 16);
-	header->unitCode = MMU.CART_ROM[18];
-	header->deviceCode = MMU.CART_ROM[19];
-	header->cardSize = MMU.CART_ROM[20];
-	memcpy(header->cardInfo, MMU.CART_ROM + 21, 8);
-	header->flags = MMU.CART_ROM[29];
-	header->ARM9src = T1ReadLong(MMU.CART_ROM, 32);
-	header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36);
-	header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40);
-	header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44);
-	header->ARM7src = T1ReadLong(MMU.CART_ROM, 48);
-	header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52);
-	header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56);
-	header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60);
-	header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64);
-	header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68);
-	header->FATOff = T1ReadLong(MMU.CART_ROM, 72);
-	header->FATSize = T1ReadLong(MMU.CART_ROM, 76);
-	header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80);
-	header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84);
-	header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88);
-	header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92);
-	header->unknown2a = T1ReadLong(MMU.CART_ROM, 96);
-	header->unknown2b = T1ReadLong(MMU.CART_ROM, 100);
-	header->IconOff = T1ReadLong(MMU.CART_ROM, 104);
-	header->CRC16 = T1ReadWord(MMU.CART_ROM, 108);
-	header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110);
-	header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112);
-	header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116);
-	memcpy(header->unknown3c, MMU.CART_ROM + 120, 8);
-	header->ROMSize = T1ReadLong(MMU.CART_ROM, 128);
-	header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132);
-	memcpy(header->unknown5, MMU.CART_ROM + 136, 56);
-	memcpy(header->logo, MMU.CART_ROM + 192, 156);
-	header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
-	header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
-	memcpy(header->reserved, MMU.CART_ROM + 352, 160);
-
-	return header;
-
-     //return (NDS_header *)MMU.CART_ROM;
-} 
-
-
-
-void NDS_FreeROM(void)
-{
-   if (MMU.CART_ROM != MMU.UNUSED_RAM)
-      free(MMU.CART_ROM);
-   MMU_unsetRom();
-//   if (MMU.bupmem.fp)
-//      fclose(MMU.bupmem.fp);
-//   MMU.bupmem.fp = NULL;
-}
-
-                         
-
-void NDS_Reset( void)
-{
-   BOOL oldexecute=execute;
-   int i;
-   u32 src;
-   u32 dst;
-   NDS_header * header = NDS_getROMHeader();
-
-	if (!header) return ;
-
-   execute = FALSE;
-
-   MMU_clearMem();
-
-   src = header->ARM9src;
-   dst = header->ARM9cpy;
-
-   for(i = 0; i < (header->ARM9binSize>>2); ++i)
-   {
-      MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src));
-      dst += 4;
-      src += 4;
-   }
-
-   src = header->ARM7src;
-   dst = header->ARM7cpy;
-     
-   for(i = 0; i < (header->ARM7binSize>>2); ++i)
-   {
-      MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src));
-      dst += 4;
-      src += 4;
-   }
-
-   armcpu_init(&NDS_ARM7, header->ARM7exe);
-   armcpu_init(&NDS_ARM9, header->ARM9exe);
-     
-   nds.ARM9Cycle = 0;
-   nds.ARM7Cycle = 0;
-   nds.cycles = 0;
-   memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4);
-   memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4);
-   nds.nextHBlank = 3168;
-   nds.VCount = 0;
-   nds.old = 0;
-   nds.diff = 0;
-   nds.lignerendu = FALSE;
-   nds.touchX = nds.touchY = 0;
-
-   MMU_write16(0, 0x04000130, 0x3FF);
-   MMU_write16(1, 0x04000130, 0x3FF);
-   MMU_write8(1, 0x04000136, 0x43);
-
-   /*
-    * Setup a copy of the firmware user settings in memory.
-    * (this is what the DS firmware would do).
-    */
-   {
-     u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
-     int fw_index;
-
-     if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) {
-       for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) {
-         MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]);
-       }
-     }
-   }
-
-	// Copy the whole header to Main RAM 0x27FFE00 on startup.
-	//  Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader
-	for (i = 0; i < ((0x170+0x90)/4); i++)
-	{
-		MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
-	}
-     
-   MainScreen.offset = 0;
-   SubScreen.offset = 192;
-     
-   //MMU_write32(0, 0x02007FFC, 0xE92D4030);
-
-     //ARM7 BIOS IRQ HANDLER
-     MMU_write32(1, 0x00, 0xE25EF002);
-     MMU_write32(1, 0x04, 0xEAFFFFFE);
-     MMU_write32(1, 0x18, 0xEA000000);
-     MMU_write32(1, 0x20, 0xE92D500F);
-     MMU_write32(1, 0x24, 0xE3A00301);
-     MMU_write32(1, 0x28, 0xE28FE000);
-     MMU_write32(1, 0x2C, 0xE510F004);
-     MMU_write32(1, 0x30, 0xE8BD500F);
-     MMU_write32(1, 0x34, 0xE25EF004);
-    
-     //ARM9 BIOS IRQ HANDLER
-     MMU_write32(0, 0xFFFF0018, 0xEA000000);
-     MMU_write32(0, 0xFFFF0020, 0xE92D500F);
-     MMU_write32(0, 0xFFFF0024, 0xEE190F11);
-     MMU_write32(0, 0xFFFF0028, 0xE1A00620);
-     MMU_write32(0, 0xFFFF002C, 0xE1A00600);
-     MMU_write32(0, 0xFFFF0030, 0xE2800C40);
-     MMU_write32(0, 0xFFFF0034, 0xE28FE000);
-     MMU_write32(0, 0xFFFF0038, 0xE510F004);
-     MMU_write32(0, 0xFFFF003C, 0xE8BD500F);
-     MMU_write32(0, 0xFFFF0040, 0xE25EF004);
-        
-     MMU_write32(0, 0x0000004, 0xE3A0010E);
-     MMU_write32(0, 0x0000008, 0xE3A01020);
-//     MMU_write32(0, 0x000000C, 0xE1B02110);
-     MMU_write32(0, 0x000000C, 0xE1B02040);
-     MMU_write32(0, 0x0000010, 0xE3B02020);
-//     MMU_write32(0, 0x0000010, 0xE2100202);
-
-   free(header);
-
-   GPU_Reset(MainScreen.gpu, 0);
-   GPU_Reset(SubScreen.gpu, 1);
-   SPU_Reset();
-
-   execute = oldexecute;
-}
-
-static void dma_check(void)
-{
-	if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles))
-	{
-		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8);
-		MMU.DMAing[0][0] = FALSE;
-	}
-
-	if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles))
-	{
-		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9);
-		MMU.DMAing[0][1] = FALSE;
-	}
-
-	if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles))
-	{
-		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10);
-		MMU.DMAing[0][2] = FALSE;
-	}
-
-	if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles))
-	{
-		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11);
-		MMU.DMAing[0][3] = FALSE;
-	}
-
-	if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles))
-	{
-		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8);
-		MMU.DMAing[1][0] = FALSE;
-	}
-
-	if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles))
-	{
-		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9);
-		MMU.DMAing[1][1] = FALSE;
-	}
-
-	if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles))
-	{
-		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10);
-		MMU.DMAing[1][2] = FALSE;
-	}
-
-	if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles))
-	{
-		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
-		if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11);
-		MMU.DMAing[1][3] = FALSE;
-	}
-
-	if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))
-	{
-#ifdef GDB_STUB
-		if ( armcpu_flagIrq( &NDS_ARM9)) 
-#else
-		if ( armcpu_irqExeption(&NDS_ARM9))
-#endif
-		{
-			nds.ARM9Cycle = nds.cycles;
-		}
-	}
-
-	if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1]))
-	{
-#ifdef GDB_STUB
-		if ( armcpu_flagIrq( &NDS_ARM7)) 
-#else
-		if ( armcpu_irqExeption(&NDS_ARM7))
-#endif
-		{
-			nds.ARM7Cycle = nds.cycles;
-		}
-	}
-
-}
-
-static void timer_check(void)
-{
-	int p, t;
-	for (p = 0; p < 2; p++)
-	{
-		for (t = 0; t < 4; t++)
-		{
-			nds.timerOver[p][t] = 0;
-			if(MMU.timerON[p][t])
-			{
-				if(MMU.timerRUN[p][t])
-				{
-					switch(MMU.timerMODE[p][t])
-					{
-					case 0xFFFF :
-						if(t > 0 && nds.timerOver[p][t - 1])
-						{
-							++(MMU.timer[p][t]);
-							nds.timerOver[p][t] = !MMU.timer[p][t];
-							if (nds.timerOver[p][t])
-							{
-								if (p == 0)
-								{
-									if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
-										NDS_makeARM9Int(3 + t);
-								}
-								else
-								{
-									if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
-										NDS_makeARM7Int(3 + t);
-								}
-								MMU.timer[p][t] = MMU.timerReload[p][t];
-							}
-						}
-						break;
-					default :
-						{
-							nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]);
-							nds.old = MMU.timer[p][t];
-							MMU.timer[p][t] += nds.diff;
-							nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t];
-							nds.timerOver[p][t] = nds.old >= MMU.timer[p][t];
-							if(nds.timerOver[p][t])
-							{
-								if (p == 0)
-								{
-									if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
-										NDS_makeARM9Int(3 + t);
-								}
-								else
-								{
-									if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
-										NDS_makeARM7Int(3 + t);
-								}
-								MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old;
-							}
-						}
-						break;
-					}
-				}
-				else
-				{
-					MMU.timerRUN[p][t] = TRUE;
-					nds.timerCycle[p][t] = nds.cycles;
-				}
-			}
-		}
-	}
-}
-
-void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
-{
-	int h;
-	for (h = 0; h < 2; h++)
-	{
-		s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12));
-
-		while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ)
-			nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9);
-		if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb;
-		while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ)
-			nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7));
-		if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb;
-		nds.cycles = (nds.ARM9Cycle<nds.ARM7Cycle)?nds.ARM9Cycle : nds.ARM7Cycle;
-
-		/* HBLANK */
-		if (h)
-		{
-			T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 2);
-			T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
-			NDS_ARM9HBlankInt();
-			NDS_ARM7HBlankInt();
-
-			if(nds.VCount<192)
-			{
-				if(MMU.DMAStartTime[0][0] == 2)
-					MMU_doDMA(0, 0);
-				if(MMU.DMAStartTime[0][1] == 2)
-					MMU_doDMA(0, 1);
-				if(MMU.DMAStartTime[0][2] == 2)
-					MMU_doDMA(0, 2);
-				if(MMU.DMAStartTime[0][3] == 2)
-					MMU_doDMA(0, 3);
-			}
-		}
-		else
-		{
-			/* HDISP */
-			u32 vmatch;
-
-			nds.nextHBlank += 4260;
-			++nds.VCount;
-			T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFD);
-			T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
-
-			if(MMU.DMAStartTime[0][0] == 3)
-				MMU_doDMA(0, 0);
-			if(MMU.DMAStartTime[0][1] == 3)
-				MMU_doDMA(0, 1);
-			if(MMU.DMAStartTime[0][2] == 3)
-				MMU_doDMA(0, 2);
-			if(MMU.DMAStartTime[0][3] == 3)
-				MMU_doDMA(0, 3);
-
-			// Main memory display
-			if(MMU.DMAStartTime[0][0] == 4)
-			{
-				MMU_doDMA(0, 0);
-				MMU.DMAStartTime[0][0] = 0;
-			}
-			if(MMU.DMAStartTime[0][1] == 4)
-			{
-				MMU_doDMA(0, 1);
-				MMU.DMAStartTime[0][1] = 0;
-			}
-			if(MMU.DMAStartTime[0][2] == 4)
-			{
-				MMU_doDMA(0, 2);
-				MMU.DMAStartTime[0][2] = 0;
-			}
-			if(MMU.DMAStartTime[0][3] == 4)
-			{
-				MMU_doDMA(0, 3);
-				MMU.DMAStartTime[0][3] = 0;
-			}
-
-			if(MMU.DMAStartTime[1][0] == 4)
-			{
-				MMU_doDMA(1, 0);
-				MMU.DMAStartTime[1][0] = 0;
-			}
-			if(MMU.DMAStartTime[1][1] == 4)
-			{
-				MMU_doDMA(1, 1);
-				MMU.DMAStartTime[0][1] = 0;
-			}
-			if(MMU.DMAStartTime[1][2] == 4)
-			{
-				MMU_doDMA(1, 2);
-				MMU.DMAStartTime[1][2] = 0;
-			}
-			if(MMU.DMAStartTime[1][3] == 4)
-			{
-				MMU_doDMA(1, 3);
-				MMU.DMAStartTime[1][3] = 0;
-			}
-                            
-			if(nds.VCount == 192)
-			{
-				/* VBLANK */
-				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
-				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
-				NDS_ARM9VBlankInt();
-				NDS_ARM7VBlankInt();
-
-				if(MMU.DMAStartTime[0][0] == 1)
-					MMU_doDMA(0, 0);
-				if(MMU.DMAStartTime[0][1] == 1)
-					MMU_doDMA(0, 1);
-				if(MMU.DMAStartTime[0][2] == 1)
-					MMU_doDMA(0, 2);
-				if(MMU.DMAStartTime[0][3] == 1)
-					MMU_doDMA(0, 3);
-
-				if(MMU.DMAStartTime[1][0] == 1)
-					MMU_doDMA(1, 0);
-				if(MMU.DMAStartTime[1][1] == 1)
-					MMU_doDMA(1, 1);
-				if(MMU.DMAStartTime[1][2] == 1)
-					MMU_doDMA(1, 2);
-				if(MMU.DMAStartTime[1][3] == 1)
-					MMU_doDMA(1, 3);
-			}
-			else if(nds.VCount == 263)
-			{
-				const int cycles_per_frame = (263 * (99 * 12 + 256 * 12));
-				/* VDISP */
-				nds.nextHBlank = 3168;
-				nds.VCount = 0;
-				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFE);
-				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
-
-				nds.cycles -= cycles_per_frame;
-				nds.ARM9Cycle -= cycles_per_frame;
-				nds.ARM7Cycle -= cycles_per_frame;
-				nb -= cycles_per_frame;
-				if(MMU.timerON[0][0])
-					nds.timerCycle[0][0] -= cycles_per_frame;
-				if(MMU.timerON[0][1])
-					nds.timerCycle[0][1] -= cycles_per_frame;
-				if(MMU.timerON[0][2])
-					nds.timerCycle[0][2] -= cycles_per_frame;
-				if(MMU.timerON[0][3])
-					nds.timerCycle[0][3] -= cycles_per_frame;
-
-				if(MMU.timerON[1][0])
-					nds.timerCycle[1][0] -= cycles_per_frame;
-				if(MMU.timerON[1][1])
-					nds.timerCycle[1][1] -= cycles_per_frame;
-				if(MMU.timerON[1][2])
-					nds.timerCycle[1][2] -= cycles_per_frame;
-				if(MMU.timerON[1][3])
-					nds.timerCycle[1][3] -= cycles_per_frame;
-				if(MMU.DMAing[0][0])
-					MMU.DMACycle[0][0] -= cycles_per_frame;
-				if(MMU.DMAing[0][1])
-					MMU.DMACycle[0][1] -= cycles_per_frame;
-				if(MMU.DMAing[0][2])
-					MMU.DMACycle[0][2] -= cycles_per_frame;
-				if(MMU.DMAing[0][3])
-					MMU.DMACycle[0][3] -= cycles_per_frame;
-				if(MMU.DMAing[1][0])
-					MMU.DMACycle[1][0] -= cycles_per_frame;
-				if(MMU.DMAing[1][1])
-					MMU.DMACycle[1][1] -= cycles_per_frame;
-				if(MMU.DMAing[1][2])
-					MMU.DMACycle[1][2] -= cycles_per_frame;
-				if(MMU.DMAing[1][3])
-					MMU.DMACycle[1][3] -= cycles_per_frame;
-
-			}
-
-			T1WriteWord(ARM9Mem.ARM9_REG, 6, nds.VCount);
-			T1WriteWord(MMU.ARM7_REG, 6, nds.VCount);
-
-			vmatch = T1ReadWord(ARM9Mem.ARM9_REG, 4);
-			if(nds.VCount== ((vmatch >> 8) | ((vmatch << 1) & 256)))
-			{
-				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4);
-				if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32)
-					NDS_makeARM9Int(2);
-			}
-			else
-				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB);
-
-			vmatch = T1ReadWord(MMU.ARM7_REG, 4);
-			if(nds.VCount== ((vmatch >> 8) | ((vmatch <<1 ) & 256)))
-			{
-				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
-				if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
-					NDS_makeARM7Int(2);
-			}
-			else
-				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
-
-			timer_check();
-			dma_check();
-		}
-	}
-}
-
-void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
-{
-	int v;
-	for (v = 0; v < 263; v++)
-	{
-		NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7);
-	}
-}
-
diff --git a/src/xsf/desmume/NDSSystem.cc b/src/xsf/desmume/NDSSystem.cc
new file mode 100644
index 000000000000..ee02bc938d5e
--- /dev/null
+++ b/src/xsf/desmume/NDSSystem.cc
@@ -0,0 +1,748 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "NDSSystem.h"
+#include "MMU.h"
+//#include "cflash.h"
+
+//#include "ROMReader.h"
+
+/* the count of bytes copied from the firmware into memory */
+#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70
+
+NDSSystem nds;
+
+static u32
+calc_CRC16( u32 start, const u8 *data, int count) {
+  int i,j;
+  u32 crc = start & 0xffff;
+  static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
+  for(i = 0; i < count; i++)
+  {
+    crc = crc ^ data[i];
+
+    for(j = 0; j < 8; j++) {
+      int do_bit = 0;
+
+      if ( crc & 0x1)
+        do_bit = 1;
+
+      crc = crc >> 1;
+
+      if ( do_bit) {
+        crc = crc ^ (val[j] << (7-j));
+      }
+    }
+  }
+  return crc;
+}
+
+static int
+copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) {
+  /*
+   * Determine which of the two user settings in the firmware is the current
+   * and valid one and then copy this into the destination buffer.
+   *
+   * The current setting will have a greater count.
+   * Settings are only valid if its CRC16 is correct.
+   */
+  int user1_valid = 0;
+  int user2_valid = 0;
+  u32 user_settings_offset;
+  u32 fw_crc;
+  u32 crc;
+  int copy_good = 0;
+
+  user_settings_offset = fw_data[0x20];
+  user_settings_offset |= fw_data[0x21] << 8;
+  user_settings_offset <<= 3;
+
+  if ( user_settings_offset <= 0x3FE00) {
+    s32 copy_settings_offset = -1;
+
+    crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
+                      NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
+    fw_crc = fw_data[user_settings_offset + 0x72];
+    fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
+    if ( crc == fw_crc) {
+      user1_valid = 1;
+    }
+
+    crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
+                      NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
+    fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
+    fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
+    if ( crc == fw_crc) {
+      user2_valid = 1;
+    }
+
+    if ( user1_valid) {
+      if ( user2_valid) {
+        u16 count1, count2;
+
+        count1 = fw_data[user_settings_offset + 0x70];
+        count1 |= fw_data[user_settings_offset + 0x71] << 8;
+
+        count2 = fw_data[user_settings_offset + 0x100 + 0x70];
+        count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
+
+        if ( count2 > count1) {
+          copy_settings_offset = user_settings_offset + 0x100;
+        }
+        else {
+          copy_settings_offset = user_settings_offset;
+        }
+      }
+      else {
+        copy_settings_offset = user_settings_offset;
+      }
+    }
+    else if ( user2_valid) {
+      /* copy the second user settings */
+      copy_settings_offset = user_settings_offset + 0x100;
+    }
+
+    if ( copy_settings_offset > 0) {
+      memcpy( dest_buffer, &fw_data[copy_settings_offset],
+              NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
+      copy_good = 1;
+    }
+  }
+
+  return copy_good;
+}
+
+
+#ifdef GDB_STUB
+int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
+              struct armcpu_ctrl_iface **arm9_ctrl_iface,
+              struct armcpu_memory_iface *arm7_mem_if,
+              struct armcpu_ctrl_iface **arm7_ctrl_iface) {
+#else
+int NDS_Init( void) {
+#endif
+     nds.ARM9Cycle = 0;
+     nds.ARM7Cycle = 0;
+     nds.cycles = 0;
+     MMU_Init();
+     nds.nextHBlank = 3168;
+     nds.VCount = 0;
+     nds.lignerendu = false;
+
+     if (Screen_Init(GFXCORE_DUMMY) != 0)
+        return -1;
+
+ #ifdef GDB_STUB
+     armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface);
+     armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface);
+#else
+	 armcpu_new(&NDS_ARM7,1);
+     armcpu_new(&NDS_ARM9,0);
+#endif
+
+     if (SPU_Init(SNDCORE_DUMMY, 735) != 0)
+        return -1;
+
+#ifdef EXPERIMENTAL_WIFI
+	 WIFI_Init(&wifiMac) ;
+#endif
+
+     return 0;
+}
+
+static void armcpu_deinit(armcpu_t *armcpu)
+{
+	if(armcpu->coproc[15])
+	{
+		free(armcpu->coproc[15]);
+		armcpu->coproc[15] = 0;
+	}
+}
+
+void NDS_DeInit(void) {
+     if(MMU.CART_ROM != MMU.UNUSED_RAM)
+        NDS_FreeROM();
+
+	armcpu_deinit(&NDS_ARM7);
+	armcpu_deinit(&NDS_ARM9);
+
+     nds.nextHBlank = 3168;
+     SPU_DeInit();
+     Screen_DeInit();
+     MMU_DeInit();
+}
+
+BOOL NDS_SetROM(u8 * rom, u32 mask)
+{
+     MMU_setRom(rom, mask);
+
+     return true;
+}
+
+NDS_header * NDS_getROMHeader(void)
+{
+	NDS_header * header = (NDS_header *) malloc(sizeof(NDS_header));
+
+	memcpy(header->gameTile, MMU.CART_ROM, 12);
+	memcpy(header->gameCode, MMU.CART_ROM + 12, 4);
+	header->makerCode = T1ReadWord(MMU.CART_ROM, 16);
+	header->unitCode = MMU.CART_ROM[18];
+	header->deviceCode = MMU.CART_ROM[19];
+	header->cardSize = MMU.CART_ROM[20];
+	memcpy(header->cardInfo, MMU.CART_ROM + 21, 8);
+	header->flags = MMU.CART_ROM[29];
+	header->ARM9src = T1ReadLong(MMU.CART_ROM, 32);
+	header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36);
+	header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40);
+	header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44);
+	header->ARM7src = T1ReadLong(MMU.CART_ROM, 48);
+	header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52);
+	header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56);
+	header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60);
+	header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64);
+	header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68);
+	header->FATOff = T1ReadLong(MMU.CART_ROM, 72);
+	header->FATSize = T1ReadLong(MMU.CART_ROM, 76);
+	header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80);
+	header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84);
+	header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88);
+	header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92);
+	header->unknown2a = T1ReadLong(MMU.CART_ROM, 96);
+	header->unknown2b = T1ReadLong(MMU.CART_ROM, 100);
+	header->IconOff = T1ReadLong(MMU.CART_ROM, 104);
+	header->CRC16 = T1ReadWord(MMU.CART_ROM, 108);
+	header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110);
+	header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112);
+	header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116);
+	memcpy(header->unknown3c, MMU.CART_ROM + 120, 8);
+	header->ROMSize = T1ReadLong(MMU.CART_ROM, 128);
+	header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132);
+	memcpy(header->unknown5, MMU.CART_ROM + 136, 56);
+	memcpy(header->logo, MMU.CART_ROM + 192, 156);
+	header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348);
+	header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350);
+	memcpy(header->reserved, MMU.CART_ROM + 352, 160);
+
+	return header;
+
+     //return (NDS_header *)MMU.CART_ROM;
+}
+
+
+
+void NDS_FreeROM(void)
+{
+   if (MMU.CART_ROM != MMU.UNUSED_RAM)
+      free(MMU.CART_ROM);
+   MMU_unsetRom();
+//   if (MMU.bupmem.fp)
+//      fclose(MMU.bupmem.fp);
+//   MMU.bupmem.fp = nullptr;
+}
+
+
+
+void NDS_Reset( void)
+{
+   BOOL oldexecute=execute;
+   int i;
+   u32 src;
+   u32 dst;
+   NDS_header * header = NDS_getROMHeader();
+
+	if (!header) return ;
+
+   execute = false;
+
+   MMU_clearMem();
+
+   src = header->ARM9src;
+   dst = header->ARM9cpy;
+
+   for(i = 0; i < (header->ARM9binSize>>2); ++i)
+   {
+      MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src));
+      dst += 4;
+      src += 4;
+   }
+
+   src = header->ARM7src;
+   dst = header->ARM7cpy;
+
+   for(i = 0; i < (header->ARM7binSize>>2); ++i)
+   {
+      MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src));
+      dst += 4;
+      src += 4;
+   }
+
+   armcpu_init(&NDS_ARM7, header->ARM7exe);
+   armcpu_init(&NDS_ARM9, header->ARM9exe);
+
+   nds.ARM9Cycle = 0;
+   nds.ARM7Cycle = 0;
+   nds.cycles = 0;
+   memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4);
+   memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4);
+   nds.nextHBlank = 3168;
+   nds.VCount = 0;
+   nds.old = 0;
+   nds.diff = 0;
+   nds.lignerendu = false;
+   nds.touchX = nds.touchY = 0;
+
+   MMU_write16(0, 0x04000130, 0x3FF);
+   MMU_write16(1, 0x04000130, 0x3FF);
+   MMU_write8(1, 0x04000136, 0x43);
+
+   /*
+    * Setup a copy of the firmware user settings in memory.
+    * (this is what the DS firmware would do).
+    */
+   {
+     u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT];
+     int fw_index;
+
+     if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) {
+       for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) {
+         MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]);
+       }
+     }
+   }
+
+	// Copy the whole header to Main RAM 0x27FFE00 on startup.
+	//  Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader
+	for (i = 0; i < ((0x170+0x90)/4); i++)
+	{
+		MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
+	}
+
+   MainScreen.offset = 0;
+   SubScreen.offset = 192;
+
+   //MMU_write32(0, 0x02007FFC, 0xE92D4030);
+
+     //ARM7 BIOS IRQ HANDLER
+     MMU_write32(1, 0x00, 0xE25EF002);
+     MMU_write32(1, 0x04, 0xEAFFFFFE);
+     MMU_write32(1, 0x18, 0xEA000000);
+     MMU_write32(1, 0x20, 0xE92D500F);
+     MMU_write32(1, 0x24, 0xE3A00301);
+     MMU_write32(1, 0x28, 0xE28FE000);
+     MMU_write32(1, 0x2C, 0xE510F004);
+     MMU_write32(1, 0x30, 0xE8BD500F);
+     MMU_write32(1, 0x34, 0xE25EF004);
+
+     //ARM9 BIOS IRQ HANDLER
+     MMU_write32(0, 0xFFFF0018, 0xEA000000);
+     MMU_write32(0, 0xFFFF0020, 0xE92D500F);
+     MMU_write32(0, 0xFFFF0024, 0xEE190F11);
+     MMU_write32(0, 0xFFFF0028, 0xE1A00620);
+     MMU_write32(0, 0xFFFF002C, 0xE1A00600);
+     MMU_write32(0, 0xFFFF0030, 0xE2800C40);
+     MMU_write32(0, 0xFFFF0034, 0xE28FE000);
+     MMU_write32(0, 0xFFFF0038, 0xE510F004);
+     MMU_write32(0, 0xFFFF003C, 0xE8BD500F);
+     MMU_write32(0, 0xFFFF0040, 0xE25EF004);
+
+     MMU_write32(0, 0x0000004, 0xE3A0010E);
+     MMU_write32(0, 0x0000008, 0xE3A01020);
+//     MMU_write32(0, 0x000000C, 0xE1B02110);
+     MMU_write32(0, 0x000000C, 0xE1B02040);
+     MMU_write32(0, 0x0000010, 0xE3B02020);
+//     MMU_write32(0, 0x0000010, 0xE2100202);
+
+   free(header);
+
+   GPU_Reset(MainScreen.gpu, 0);
+   GPU_Reset(SubScreen.gpu, 1);
+   SPU_Reset();
+
+   execute = oldexecute;
+}
+
+static void dma_check(void)
+{
+	if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles))
+	{
+		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8);
+		MMU.DMAing[0][0] = false;
+	}
+
+	if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles))
+	{
+		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9);
+		MMU.DMAing[0][1] = false;
+	}
+
+	if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles))
+	{
+		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10);
+		MMU.DMAing[0][2] = false;
+	}
+
+	if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles))
+	{
+		T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11);
+		MMU.DMAing[0][3] = false;
+	}
+
+	if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles))
+	{
+		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8);
+		MMU.DMAing[1][0] = false;
+	}
+
+	if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles))
+	{
+		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9);
+		MMU.DMAing[1][1] = false;
+	}
+
+	if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles))
+	{
+		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10);
+		MMU.DMAing[1][2] = false;
+	}
+
+	if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles))
+	{
+		T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF);
+		if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11);
+		MMU.DMAing[1][3] = false;
+	}
+
+	if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))
+	{
+#ifdef GDB_STUB
+		if ( armcpu_flagIrq( &NDS_ARM9))
+#else
+		if ( armcpu_irqExeption(&NDS_ARM9))
+#endif
+		{
+			nds.ARM9Cycle = nds.cycles;
+		}
+	}
+
+	if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1]))
+	{
+#ifdef GDB_STUB
+		if ( armcpu_flagIrq( &NDS_ARM7))
+#else
+		if ( armcpu_irqExeption(&NDS_ARM7))
+#endif
+		{
+			nds.ARM7Cycle = nds.cycles;
+		}
+	}
+
+}
+
+static void timer_check(void)
+{
+	int p, t;
+	for (p = 0; p < 2; p++)
+	{
+		for (t = 0; t < 4; t++)
+		{
+			nds.timerOver[p][t] = 0;
+			if(MMU.timerON[p][t])
+			{
+				if(MMU.timerRUN[p][t])
+				{
+					switch(MMU.timerMODE[p][t])
+					{
+					case 0xFFFF :
+						if(t > 0 && nds.timerOver[p][t - 1])
+						{
+							++(MMU.timer[p][t]);
+							nds.timerOver[p][t] = !MMU.timer[p][t];
+							if (nds.timerOver[p][t])
+							{
+								if (p == 0)
+								{
+									if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
+										NDS_makeARM9Int(3 + t);
+								}
+								else
+								{
+									if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
+										NDS_makeARM7Int(3 + t);
+								}
+								MMU.timer[p][t] = MMU.timerReload[p][t];
+							}
+						}
+						break;
+					default :
+						{
+							nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]);
+							nds.old = MMU.timer[p][t];
+							MMU.timer[p][t] += nds.diff;
+							nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t];
+							nds.timerOver[p][t] = nds.old >= MMU.timer[p][t];
+							if(nds.timerOver[p][t])
+							{
+								if (p == 0)
+								{
+									if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40)
+										NDS_makeARM9Int(3 + t);
+								}
+								else
+								{
+									if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40)
+										NDS_makeARM7Int(3 + t);
+								}
+								MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old;
+							}
+						}
+						break;
+					}
+				}
+				else
+				{
+					MMU.timerRUN[p][t] = true;
+					nds.timerCycle[p][t] = nds.cycles;
+				}
+			}
+		}
+	}
+}
+
+void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
+{
+	int h;
+	for (h = 0; h < 2; h++)
+	{
+		s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12));
+
+		while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ)
+			nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9);
+		if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb;
+		while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ)
+			nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7));
+		if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb;
+		nds.cycles = (nds.ARM9Cycle<nds.ARM7Cycle)?nds.ARM9Cycle : nds.ARM7Cycle;
+
+		/* HBLANK */
+		if (h)
+		{
+			T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 2);
+			T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2);
+			NDS_ARM9HBlankInt();
+			NDS_ARM7HBlankInt();
+
+			if(nds.VCount<192)
+			{
+				if(MMU.DMAStartTime[0][0] == 2)
+					MMU_doDMA(0, 0);
+				if(MMU.DMAStartTime[0][1] == 2)
+					MMU_doDMA(0, 1);
+				if(MMU.DMAStartTime[0][2] == 2)
+					MMU_doDMA(0, 2);
+				if(MMU.DMAStartTime[0][3] == 2)
+					MMU_doDMA(0, 3);
+			}
+		}
+		else
+		{
+			/* HDISP */
+			u32 vmatch;
+
+			nds.nextHBlank += 4260;
+			++nds.VCount;
+			T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFD);
+			T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFD);
+
+			if(MMU.DMAStartTime[0][0] == 3)
+				MMU_doDMA(0, 0);
+			if(MMU.DMAStartTime[0][1] == 3)
+				MMU_doDMA(0, 1);
+			if(MMU.DMAStartTime[0][2] == 3)
+				MMU_doDMA(0, 2);
+			if(MMU.DMAStartTime[0][3] == 3)
+				MMU_doDMA(0, 3);
+
+			// Main memory display
+			if(MMU.DMAStartTime[0][0] == 4)
+			{
+				MMU_doDMA(0, 0);
+				MMU.DMAStartTime[0][0] = 0;
+			}
+			if(MMU.DMAStartTime[0][1] == 4)
+			{
+				MMU_doDMA(0, 1);
+				MMU.DMAStartTime[0][1] = 0;
+			}
+			if(MMU.DMAStartTime[0][2] == 4)
+			{
+				MMU_doDMA(0, 2);
+				MMU.DMAStartTime[0][2] = 0;
+			}
+			if(MMU.DMAStartTime[0][3] == 4)
+			{
+				MMU_doDMA(0, 3);
+				MMU.DMAStartTime[0][3] = 0;
+			}
+
+			if(MMU.DMAStartTime[1][0] == 4)
+			{
+				MMU_doDMA(1, 0);
+				MMU.DMAStartTime[1][0] = 0;
+			}
+			if(MMU.DMAStartTime[1][1] == 4)
+			{
+				MMU_doDMA(1, 1);
+				MMU.DMAStartTime[0][1] = 0;
+			}
+			if(MMU.DMAStartTime[1][2] == 4)
+			{
+				MMU_doDMA(1, 2);
+				MMU.DMAStartTime[1][2] = 0;
+			}
+			if(MMU.DMAStartTime[1][3] == 4)
+			{
+				MMU_doDMA(1, 3);
+				MMU.DMAStartTime[1][3] = 0;
+			}
+
+			if(nds.VCount == 192)
+			{
+				/* VBLANK */
+				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 1);
+				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1);
+				NDS_ARM9VBlankInt();
+				NDS_ARM7VBlankInt();
+
+				if(MMU.DMAStartTime[0][0] == 1)
+					MMU_doDMA(0, 0);
+				if(MMU.DMAStartTime[0][1] == 1)
+					MMU_doDMA(0, 1);
+				if(MMU.DMAStartTime[0][2] == 1)
+					MMU_doDMA(0, 2);
+				if(MMU.DMAStartTime[0][3] == 1)
+					MMU_doDMA(0, 3);
+
+				if(MMU.DMAStartTime[1][0] == 1)
+					MMU_doDMA(1, 0);
+				if(MMU.DMAStartTime[1][1] == 1)
+					MMU_doDMA(1, 1);
+				if(MMU.DMAStartTime[1][2] == 1)
+					MMU_doDMA(1, 2);
+				if(MMU.DMAStartTime[1][3] == 1)
+					MMU_doDMA(1, 3);
+			}
+			else if(nds.VCount == 263)
+			{
+				const int cycles_per_frame = (263 * (99 * 12 + 256 * 12));
+				/* VDISP */
+				nds.nextHBlank = 3168;
+				nds.VCount = 0;
+				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFE);
+				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
+
+				nds.cycles -= cycles_per_frame;
+				nds.ARM9Cycle -= cycles_per_frame;
+				nds.ARM7Cycle -= cycles_per_frame;
+				nb -= cycles_per_frame;
+				if(MMU.timerON[0][0])
+					nds.timerCycle[0][0] -= cycles_per_frame;
+				if(MMU.timerON[0][1])
+					nds.timerCycle[0][1] -= cycles_per_frame;
+				if(MMU.timerON[0][2])
+					nds.timerCycle[0][2] -= cycles_per_frame;
+				if(MMU.timerON[0][3])
+					nds.timerCycle[0][3] -= cycles_per_frame;
+
+				if(MMU.timerON[1][0])
+					nds.timerCycle[1][0] -= cycles_per_frame;
+				if(MMU.timerON[1][1])
+					nds.timerCycle[1][1] -= cycles_per_frame;
+				if(MMU.timerON[1][2])
+					nds.timerCycle[1][2] -= cycles_per_frame;
+				if(MMU.timerON[1][3])
+					nds.timerCycle[1][3] -= cycles_per_frame;
+				if(MMU.DMAing[0][0])
+					MMU.DMACycle[0][0] -= cycles_per_frame;
+				if(MMU.DMAing[0][1])
+					MMU.DMACycle[0][1] -= cycles_per_frame;
+				if(MMU.DMAing[0][2])
+					MMU.DMACycle[0][2] -= cycles_per_frame;
+				if(MMU.DMAing[0][3])
+					MMU.DMACycle[0][3] -= cycles_per_frame;
+				if(MMU.DMAing[1][0])
+					MMU.DMACycle[1][0] -= cycles_per_frame;
+				if(MMU.DMAing[1][1])
+					MMU.DMACycle[1][1] -= cycles_per_frame;
+				if(MMU.DMAing[1][2])
+					MMU.DMACycle[1][2] -= cycles_per_frame;
+				if(MMU.DMAing[1][3])
+					MMU.DMACycle[1][3] -= cycles_per_frame;
+
+			}
+
+			T1WriteWord(ARM9Mem.ARM9_REG, 6, nds.VCount);
+			T1WriteWord(MMU.ARM7_REG, 6, nds.VCount);
+
+			vmatch = T1ReadWord(ARM9Mem.ARM9_REG, 4);
+			if(nds.VCount== ((vmatch >> 8) | ((vmatch << 1) & 256)))
+			{
+				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4);
+				if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32)
+					NDS_makeARM9Int(2);
+			}
+			else
+				T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB);
+
+			vmatch = T1ReadWord(MMU.ARM7_REG, 4);
+			if(nds.VCount== ((vmatch >> 8) | ((vmatch <<1 ) & 256)))
+			{
+				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4);
+				if(T1ReadWord(MMU.ARM7_REG, 4) & 32)
+					NDS_makeARM7Int(2);
+			}
+			else
+				T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB);
+
+			timer_check();
+			dma_check();
+		}
+	}
+}
+
+void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7)
+{
+	int v;
+	for (v = 0; v < 263; v++)
+	{
+		NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7);
+	}
+}
+
diff --git a/src/xsf/desmume/NDSSystem.h b/src/xsf/desmume/NDSSystem.h
index f55e12ee8606..2417f6135db4 100644
--- a/src/xsf/desmume/NDSSystem.h
+++ b/src/xsf/desmume/NDSSystem.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef NDSSYSTEM_H
@@ -31,11 +31,6 @@
 #include "mem.h"
 //#include "wifi.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
 extern volatile BOOL execute;
 extern BOOL click;
 
@@ -65,37 +60,37 @@ typedef struct
        u8       cardSize;
        u8       cardInfo[8];
        u8       flags;
-       
+
        u32      ARM9src;
        u32      ARM9exe;
        u32      ARM9cpy;
        u32      ARM9binSize;
-       
+
        u32      ARM7src;
        u32      ARM7exe;
        u32      ARM7cpy;
        u32      ARM7binSize;
-       
+
        u32      FNameTblOff;
        u32      FNameTblSize;
-       
+
        u32      FATOff;
        u32      FATSize;
-       
+
        u32     ARM9OverlayOff;
        u32     ARM9OverlaySize;
        u32     ARM7OverlayOff;
        u32     ARM7OverlaySize;
-       
+
        u32     unknown2a;
        u32     unknown2b;
-       
+
        u32     IconOff;
        u16     CRC16;
        u16     ROMtimeout;
        u32     ARM9unk;
        u32     ARM7unk;
-       
+
        u8      unknown3c[8];
        u32     ROMSize;
        u32     HeaderSize;
@@ -120,7 +115,7 @@ typedef struct
        u32 old;
        s32 diff;
        BOOL lignerendu;
-       
+
        u16 touchX;
        u16 touchY;
 } NDSSystem;
@@ -181,7 +176,7 @@ NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config);
 
 BOOL NDS_SetROM(u8 * rom, u32 mask);
 NDS_header * NDS_getROMHeader(void);
- 
+
 void NDS_setTouchPos(u16 x, u16 y);
 void NDS_releasTouch(void);
 
@@ -202,54 +197,50 @@ NDS_exec(s32 nb, BOOL force);
             if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x10)
             {
                  MMU.reg_IF[0] |= 2;// & (MMU.reg_IME[0] << 1);// (MMU.reg_IE[0] & (1<<1));
-                 NDS_ARM9.wIRQ = TRUE;
+                 NDS_ARM9.wIRQ = true;
             }
        }
-       
+
        static INLINE void NDS_ARM7HBlankInt(void)
        {
             if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10)
             {
                  MMU.reg_IF[1] |= 2;// & (MMU.reg_IME[1] << 1);// (MMU.reg_IE[1] & (1<<1));
-                 NDS_ARM7.wIRQ = TRUE;
+                 NDS_ARM7.wIRQ = true;
             }
        }
-       
+
        static INLINE void NDS_ARM9VBlankInt(void)
        {
             if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x8)
             {
                  MMU.reg_IF[0] |= 1;// & (MMU.reg_IME[0]);// (MMU.reg_IE[0] & 1);
-                 NDS_ARM9.wIRQ = TRUE;
-                      //execute = FALSE;
+                 NDS_ARM9.wIRQ = true;
+                      //execute = false;
                       /*logcount++;*/
             }
        }
-       
+
        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;
+                 NDS_ARM7.wIRQ = true;
+                 //execute = false;
        }
-       
+
        static INLINE void NDS_swapScreen(void)
        {
 	       u16 tmp = MainScreen.offset;
 	       MainScreen.offset = SubScreen.offset;
 	       SubScreen.offset = tmp;
        }
- 
- 
+
+
 
 void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
 void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7);
 
-#ifdef __cplusplus
-}
 #endif
 
-#endif
 
- 	  	 
diff --git a/src/xsf/desmume/SPU.c b/src/xsf/desmume/SPU.c
deleted file mode 100644
index 26cd603f7f30..000000000000
--- a/src/xsf/desmume/SPU.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/*  Copyright (C) 2006 Theo Berkau
-
-    Ideas borrowed from Stephane Dallongeville's SCSP core
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "ARM9.h"
-#include "MMU.h"
-#include "SPU.h"
-#include "mem.h"
-
-#include "armcpu.h"
-
-enum
-{
-	FORMAT_PCM8 = 0,
-	FORMAT_PCM16 = 1,
-	FORMAT_ADPCM = 2,
-	FORMAT_PSG = 3
-};
-
-#define VOL_SHIFT 10
-
-typedef struct
-{
-	int id;
-	int status;
-	int format;
-	u8 *buf8; s16 *buf16;
-	double pos, inc;
-	int loopend, looppos;
-	int loop, length;
-	s32 adpcm;
-	int adpcm_pos, adpcm_index;
-	s32 adpcm_loop;
-	int adpcm_loop_pos, adpcm_loop_index;
-	int psg_duty;
-	int timer;
-	int volume;
-	int pan;
-	int shift;
-	int repeat, hold;
-	u32 addr;
-	s32 volumel;
-	s32 volumer;
-	s16 output;
-} SChannel;
-
-typedef struct
-{
-	s32 *pmixbuf;
-	s16 *pclipingbuf;
-	u32 buflen;
-	SChannel ch[16];
-} SPU_struct;
-
-static SPU_struct spu = { 0, 0, 0 };
-
-static SoundInterface_struct *SNDCore=NULL;
-extern SoundInterface_struct *SNDCoreList[];
-
-int SPU_ChangeSoundCore(int coreid, int buffersize)
-{
-	int i;
-	SPU_DeInit();
-
-   // Allocate memory for sound buffer
-	spu.buflen = buffersize * 2; /* stereo */
-	spu.pmixbuf = malloc(spu.buflen * sizeof(s32));
-	if (!spu.pmixbuf)
-	{
-		SPU_DeInit();
-		return -1;
-	}
-
-	spu.pclipingbuf = malloc(spu.buflen * sizeof(s16));
-	if (!spu.pclipingbuf)
-	{
-		SPU_DeInit();
-		return -1;
-	}
-
-	// So which core do we want?
-	if (coreid == SNDCORE_DEFAULT)
-		coreid = 0; // Assume we want the first one
-
-	// Go through core list and find the id
-	for (i = 0; SNDCoreList[i] != NULL; i++)
-	{
-		if (SNDCoreList[i]->id == coreid)
-		{
-			// Set to current core
-			SNDCore = SNDCoreList[i];
-			break;
-		}
-	}
-
-	if (SNDCore == NULL)
-	{
-		SPU_DeInit();
-		return -1;
-	}
-
-	if (SNDCore->Init(spu.buflen) == -1)
-	{
-		// Since it failed, instead of it being fatal, we'll just use the dummy
-		// core instead
-		SNDCore = &SNDDummy;
-	}
-
-   return 0;
-}
-int SPU_Init(int coreid, int buffersize)
-{
-	SPU_DeInit();
-	SPU_Reset();
-	return SPU_ChangeSoundCore(coreid, buffersize);
-}
-void SPU_Pause(int pause)
-{
-	if(pause)
-		SNDCore->MuteAudio();
-	else
-		SNDCore->UnMuteAudio();
-}
-void SPU_SetVolume(int volume)
-{
-	if (SNDCore)
-		SNDCore->SetVolume(volume);
-}
-void SPU_DeInit(void)
-{
-	spu.buflen = 0;
-	if (spu.pmixbuf)
-	{
-		free(spu.pmixbuf);
-		spu.pmixbuf = 0;
-	}
-	if (spu.pclipingbuf)
-	{
-		free(spu.pclipingbuf);
-		spu.pclipingbuf = 0;
-	}
-	if (SNDCore)
-	{
-		SNDCore->DeInit();
-	}
-	SNDCore = &SNDDummy;
-}
-
-static const short g_adpcm_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 4, 4, 6, 6, 8, 8 };
-
-static const int g_adpcm_mult[89] =
-{
-	0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011,
-	0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D,
-	0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076,
-	0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
-	0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C,
-	0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812,
-	0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE,
-	0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
-	0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF,
-};
-
-static const s16 g_psg_duty[8][8] = {
-  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
-  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF },
-};
-
-
-static void reset_channel(SChannel *ch, int id)
-{
-	ch->status = 0;
-	ch->id = id;
-}
-
-void SPU_Reset(void)
-{
-	int i;
-	for (i = 0;i < 16; i++)
-		reset_channel(&spu.ch[i], i);
-
-	for (i = 0x400; i < 0x51D; i++)
-		T1WriteByte(MMU.ARM7_REG, i, 0);
-}
-void SPU_KeyOn(int channel)
-{
-}
-
-static INLINE void adjust_channel_timer(SChannel *ch)
-{
-	ch->inc = (((double)33512000) / (44100 * 2)) / (double)(0x10000 - ch->timer);
-}
-
-static int check_valid(u32 addr, u32 size)
-{
-	u32 t1, t2;
-
-	if(size > MMU.MMU_MASK[1][(addr >> 20) & 0xff]) return 0;
-
-	t1 = addr;
-	t2 = (addr + size);
-	t1 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
-	t2 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
-
-	if(t2 < t1) return 0;
-
-	return 1;
-}
-
-static void start_channel(SChannel *ch)
-{
-
-	switch(ch->format)
-	{
-	case FORMAT_PCM8:
-		{
-			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
-			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
-			u32 size = ((ch->length + ch->loop) << 2);
-			if((p != NULL) && check_valid(ch->addr, size))
-			{
-				ch->buf8 = p + ofs;
-				ch->looppos = ch->loop << 2;
-				ch->loopend = size;
-				ch->pos = 0;
-				ch->status = 1;
-			}
-		}
-	break;
-	case FORMAT_PCM16:
-		{
-			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
-			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
-			u32 size = ((ch->length + ch->loop) << 1);
-			if((p != NULL) && check_valid(ch->addr, size << 1))
-			{
-				ch->buf16 = (s16 *)(p + ofs - (ofs & 1));
-				ch->looppos = ch->loop << 1;
-				ch->loopend = size;
-				ch->pos = 0;
-				ch->status = 1;
-			}
-		}
-	break;
-	case FORMAT_ADPCM:
-		{
-			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
-			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
-			u32 size = ((ch->length + ch->loop) << 3);
-			if((p != NULL) && check_valid(ch->addr, size >> 1))
-			{
-				ch->buf8 = p + ofs;
-#ifdef WORDS_BIGENDIAN
-				ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
-#else
-				ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
-#endif
-				ch->adpcm_index = (ch->buf8[2] & 0x7F);
-				ch->adpcm_pos = 8;
-				ch->pos = 9;
-				ch->looppos = ch->loop << 3;
-				ch->loopend = size;
-				ch->adpcm_loop_index = -1;
-				ch->status = 1;
-			}
-		}
-		break;
-	case FORMAT_PSG:
-		ch->status = 1;
-		if(ch->id < 14)
-		{
-			ch->pos = 0;
-		}
-		else
-		{
-			ch->pos = 0x7FFF;
-		}
-		break;
-	}
-}
-
-static void stop_channel(SChannel *ch)
-{
-	u32 addr = 0x400 + (ch->id << 4) + 3;
-	ch->status = 0;
-	T1WriteByte(MMU.ARM7_REG, addr, (u8)(T1ReadByte(MMU.ARM7_REG, addr) & ~0x80));
-}
-static void set_channel_volume(SChannel *ch)
-{
-	s32 vol1 = (T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F) * ch->volume;
-	s32 vol2;
-	vol2 = vol1 * ch->pan;
-	vol1 = vol1 * (127-ch->pan);
-	ch->volumel = vol1 >> (21 - VOL_SHIFT + ch->shift);
-	ch->volumer = vol2 >> (21 - VOL_SHIFT + ch->shift);
-}
-
-void SPU_WriteByte(u32 addr, u8 x)
-{
-	addr &= 0x00000FFF;
-	T1WriteByte(MMU.ARM7_REG, addr, x);
-
-	if(addr < 0x500)
-	{
-		SChannel *ch;
-		switch(addr & 0x0F)
-		{
-		case 0x0:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->volume = (x & 0x7F);
-			set_channel_volume(ch);
-			break;
-		case 0x1:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->shift = (x & 0x03);
-			ch->hold = (x >> 7 & 0x01);
-			set_channel_volume(ch);
-			break;
-		case 0x2:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->pan = (x & 0x7F);
-			set_channel_volume(ch);
-			break;
-		case 0x3:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->psg_duty = (x & 0x07);
-			ch->repeat = (x >> 3 & 0x03);
-			ch->format = (x >> 5 & 0x03);
-			if(x & 0x80) start_channel(ch); else stop_channel(ch);
-			break;
-#if !DISABLE_XSF_TESTS
-		case 0x04:
-		case 0x05:
-		case 0x06:
-		case 0x07:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
-			break;
-		case 0x08:
-		case 0x09:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->timer = T1ReadWord(MMU.ARM7_REG, addr & ~1);
-			adjust_channel_timer(ch);
-			break;
-		case 0x0a:
-		case 0x0b:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->loop = T1ReadWord(MMU.ARM7_REG, addr & ~1);
-			break;
-		case 0x0c:
-		case 0x0e:
-		case 0x0d:
-		case 0x0f:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
-			break;
-#endif
-		}
-	}
-
-}
-
-
-void SPU_WriteWord(u32 addr, u16 x)
-{
-	addr &= 0x00000FFF;
-	T1WriteWord(MMU.ARM7_REG, addr, x);
-
-	if(addr < 0x500)
-	{
-		SChannel *ch;
-		switch(addr & 0x00F)
-		{
-		case 0x0:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->volume = (x & 0x007F);
-			ch->shift = (x >> 8 & 0x0003);
-			ch->hold = (x >> 15 & 0x0001);
-			set_channel_volume(ch);
-			break;
-		case 0x2:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->pan = (x & 0x007F);
-			ch->psg_duty = (x >> 8 & 0x0007);
-			ch->repeat = (x >> 11 & 0x0003);
-			ch->format = (x >> 13 & 0x0003);
-			set_channel_volume(ch);
-			if(x & 0x8000) start_channel(ch); else stop_channel(ch);
-			break;
-		case 0x08:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->timer = x;
-			adjust_channel_timer(ch);
-			break;
-		case 0x0a:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->loop = x;
-			break;
-#if !DISABLE_XSF_TESTS
-		case 0x04:
-		case 0x06:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
-			break;
-		case 0x0c:
-		case 0x0e:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
-			break;
-#endif
-		}
-	}
-}
-
-
-void SPU_WriteLong(u32 addr, u32 x)
-{
-	addr &= 0x00000FFF;
-	T1WriteLong(MMU.ARM7_REG, addr, x);
-
-	if(addr < 0x500)
-	{
-		SChannel *ch;
-		switch(addr & 0x00F)
-		{
-		case 0x0:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->volume = (x & 0x7F);
-			ch->shift = (x >> 8 & 0x00000003);
-			ch->hold = (x >> 15 & 0x00000001);
-			ch->pan = (x >> 16 & 0x0000007F);
-			ch->psg_duty = (x >> 24 & 0x00000007);
-			ch->repeat = (x >> 27 & 0x00000003);
-			ch->format = (x >> 29 & 0x00000003);
-			set_channel_volume(ch);
-			if(x & 0x80000000) start_channel(ch); else stop_channel(ch);
-			break;
-		case 0x04:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->addr = (x & 0x07FFFFFF);
-			break;
-		case 0x08:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->timer = (x & 0x0000FFFF);
-			ch->loop = (x >> 16 & 0x0000FFFF);
-			adjust_channel_timer(ch);
-			break;
-		case 0x0C:
-			ch = spu.ch + (addr >> 4 & 0xF);
-			ch->length = (x & 0x003FFFFF);
-			break;
-		}
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-u32 SPU_ReadLong(u32 addr)
-{
-	addr &= 0xFFF;
-	return T1ReadLong(MMU.ARM7_REG, addr);
-}
-
-static INLINE s32 clipping(s32 x, s32 min, s32 max) {
-#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-	if (x < min)
-	{
-		return (min);
-	}
-	else if (x > max)
-	{
-		return (max);
-	}
-	return (x);
-#else
-	return x ^ ((-(x < min)) & (x ^ min)) ^ ((-(x > max)) & (x ^ max));
-#endif
-}
-
-extern unsigned long dwChannelMute;
-
-static void decode_pcm8(SChannel *ch, s32 *out, int length)
-{
-	int oi;
-	double pos, inc, len;
-	if (!ch->buf8) return;
-
-	pos = ch->pos; inc = ch->inc; len = ch->loopend;
-
-	for(oi = 0; oi < length; oi++)
-	{
-		ch->output = ((s16)(s8)ch->buf8[(int)pos]) << 8;
-#if 0
-		if (dwChannelMute & (1 << ch->id))
-		{
-			out++;
-			out++;
-		}
-		else
-#endif
-		{
-			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
-			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
-		}
-		pos += inc;
-		if(pos >= len)
-		{
-			switch(ch->repeat)
-			{
-#if !DISABLE_XSF_TESTS
-			case 0:
-#endif
-			case 1:
-				pos += ch->looppos - len;
-				break;
-			default:
-				stop_channel(ch);
-				oi = length;
-				break;
-			}
-		}
-	}
-
-	ch->pos = pos;
-	return;
-}
-
-static void decode_pcm16(SChannel *ch, s32 *out, int length)
-{
-	int oi;
-	double pos, inc, len;
-
-	if (!ch->buf16) return;
-
-	pos = ch->pos; inc = ch->inc; len = ch->loopend;
-
-	for(oi = 0; oi < length; oi++)
-	{
-#ifdef WORDS_BIGENDIAN
-		ch->output = (s16)T1ReadWord((u8 *)ch->buf16, (int)pos << 1);
-#else
-		ch->output = (s16)ch->buf16[(int)pos];
-#endif
-#if 0
-		if (dwChannelMute & (1 << ch->id))
-		{
-			out++;
-			out++;
-		}
-		else
-#endif
-		{
-			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
-			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
-		}
-		pos += inc;
-		if(pos >= len)
-		{
-			switch(ch->repeat)
-			{
-#if !DISABLE_XSF_TESTS
-			case 0:
-#endif
-			case 1:
-				pos += ch->looppos - len;
-				break;
-			default:
-				stop_channel(ch);
-				oi = length;
-				break;
-			}
-		}
-	}
-
-	ch->pos = pos;
-}
-
-static INLINE void decode_adpcmone_P4(SChannel *ch, int m)
-{
-	int i, ci0;
-	u8 *p;
-	s32 s;
-	int N;
-
-	i = ch->adpcm_pos;
-	p = (ch->buf8 + (i >> 1));
-	ci0 = ch->adpcm_index;
-	s = ch->adpcm;
-
-	if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
-	{
-		ch->adpcm_loop_index = ci0;
-		ch->adpcm_loop  = s;
-		ch->adpcm_loop_pos  = i;
-	}
-
-	if(i++ & 1)
-	{
-		s32 x1, d1;
-		x1 = ((*(p++) >> 3) & 0x1F) | 1;
-		d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
-		ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
-#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-		if(x1 & 0x10) d1 = -d1;
-#else
-		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
-#endif
-
-		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
-	}
-
-	N = (((m & ~1) - (i & ~1)) >> 1);
-	for(i = 0; i < N; i++)
-	{
-		s32 x0, d0;
-		s32 x1, d1;
-		int ci1;
-		x0 = ((*p << 1) & 0x1F) | 1;
-		x1 = ((*p >> 3) & 0x1F) | 1;
-		ci1 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
-		d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
-		ci0 = clipping((ci1 + g_adpcm_index[x1 & 0xE]), 0, 88);
-		d1 = ((x1 & 0xF) * g_adpcm_mult[ci1] & ~7);
-#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-		if(x0 & 0x10) d0 = -d0;
-		if(x1 & 0x10) d1 = -d1;
-#else
-		d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
-		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
-#endif
-		s = clipping((s + d0), (-32768 << 3), (32767 << 3));
-		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
-		p++;
-	}
-	if(m & 1)
-	{
-		s32 x0, d0;
-		x0 = ((*p << 1) & 0x1F) | 1;
-		d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
-		ci0 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
-#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-		if(x0 & 0x10) d0 = -d0;
-#else
-		d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
-#endif
-		s = clipping((s + d0), (-32768 << 3), (32767 << 3));
-	}
-
-	ch->output = (s16)(s >> 3);
-
-	ch->adpcm = s;
-	ch->adpcm_index = ci0;
-	ch->adpcm_pos = m;
-}
-
-static INLINE void decode_adpcmone_XX(SChannel *ch, int m)
-{
-	int i, ci0;
-	u8 *p;
-	s32 s;
-
-	i = ch->adpcm_pos;
-	p = (ch->buf8 + (i >> 1));
-	ci0 = ch->adpcm_index;
-	s = ch->adpcm;
-
-	if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
-	{
-		ch->adpcm_loop_index = ci0;
-		ch->adpcm_loop  = s;
-		ch->adpcm_loop_pos  = i;
-	}
-
-	while (i < m)
-	{
-		s32 x1, d1;
-		x1 = ((s32)*p) >> ((i & 1) << 2) & 0xf;
-		x1 = x1 + x1 + 1;
-		d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
-		ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
-#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-		if(x1 & 0x10) d1 = -d1;
-#else
-		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
-#endif
-
-		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
-		p += (i & 1);
-		i++;
-	}
-
-	ch->output = (s16)(s >> 3);
-
-	ch->adpcm = s;
-	ch->adpcm_index = ci0;
-	ch->adpcm_pos = m;
-}
-
-#define decode_adpcmone decode_adpcmone_P4
-
-static void decode_adpcm(SChannel *ch, s32 *out, int length)
-{
-	int oi;
-	double pos, inc, len;
-	if (!ch->buf8) return;
-
-	pos = ch->pos; inc = ch->inc; len = ch->loopend;
-
-	for(oi = 0; oi < length; oi++)
-	{
-		int m = (int)pos;
-		int i = ch->adpcm_pos;
-		if(i < m)
-			decode_adpcmone(ch, m);
-
-#if 0
-		if (dwChannelMute & (1 << ch->id))
-		{
-			out++;
-			out++;
-		}
-		else
-#endif
-		{
-			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
-			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
-		}
-		pos += inc;
-		if(pos >= len)
-		{
-			switch(ch->repeat)
-			{
-			case 1:
-				if (ch->adpcm_loop_index >= 0)
-				{
-					pos += ch->looppos - len;
-					ch->adpcm_pos = ch->adpcm_loop_pos;
-					ch->adpcm_index  = ch->adpcm_loop_index;
-					ch->adpcm  = ch->adpcm_loop;
-					break;
-				}
-#if !DISABLE_XSF_TESTS
-			case 0:
-				pos = 9 - len;
-#ifdef WORDS_BIGENDIAN
-				ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
-#else
-				ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
-#endif
-				ch->adpcm_index = (ch->buf8[2] & 0x7F);
-				ch->adpcm_pos = 8;
-				break;
-#endif
-			default:
-				stop_channel(ch);
-				oi = length;
-				break;
-			}
-		}
-	}
-	ch->pos = pos;
-}
-
-static void decode_psg(SChannel *ch, s32 *out, int length)
-{
-	int oi;
-
-	if(ch->id < 14)
-	{
-		// NOTE: square wave.
-		double pos, inc;
-		pos = ch->pos; inc = ch->inc;
-		for(oi = 0; oi < length; oi++)
-		{
-			ch->output = (s16)g_psg_duty[ch->psg_duty][(int)pos & 0x00000007];
-#if 0
-			if (dwChannelMute & (1 << ch->id))
-			{
-				out++;
-				out++;
-			}
-			else
-#endif
-			{
-				*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
-				*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
-			}
-			pos += inc;
-		}
-		ch->pos = pos;
-	}
-	else
-	{
-		// NOTE: noise.
-		u16 X;
-		X = (u16)ch->pos;
-		for(oi = 0; oi < length; oi++)
-		{
-			if(X & 1)
-			{
-				X >>= 1;
-				X ^= 0x6000;
-				ch->output = -0x8000;
-			}
-			else
-			{
-				X >>= 1;
-				ch->output = +0x7FFF;
-			}
-		}
-#if 0
-		if (dwChannelMute & (1 << ch->id))
-		{
-			out++;
-			out++;
-		}
-		else
-#endif
-		{
-			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
-			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
-		}
-		ch->pos = X;
-	}
-}
-
-
-
-void SPU_EmulateSamples(u32 numsamples)
-{
-	u32 sizesmp = numsamples;
-	u32 sizebyte = sizesmp << 2;
-	if (sizebyte > spu.buflen * sizeof(s16)) sizebyte = spu.buflen * sizeof(s16);
-	sizesmp = sizebyte >> 2;
-	sizebyte = sizesmp << 2;
-	if (sizesmp > 0)
-	{
-		unsigned i;
-		SChannel *ch = spu.ch;
-		memset(spu.pmixbuf, 0, spu.buflen * sizeof(s32));
-		for (i = 0; i < 16; i++)
-		{
-			if (ch->status)
-			{
-				switch (ch->format)
-				{
-				case 0:
-					decode_pcm8(ch, spu.pmixbuf, sizesmp);
-					break;
-				case 1:
-					decode_pcm16(ch, spu.pmixbuf, sizesmp);
-					break;
-				case 2:
-					decode_adpcm(ch, spu.pmixbuf, sizesmp);
-					break;
-				case 3:
-					decode_psg(ch, spu.pmixbuf, sizesmp);
-					break;
-				}
-			}
-			ch++;
-		}
-		for (i = 0; i < sizesmp * 2; i++)
-			spu.pclipingbuf[i] = (s16)clipping(spu.pmixbuf[i], -0x8000, 0x7fff);
-		SNDCore->UpdateAudio(spu.pclipingbuf, sizesmp);
-	}
-}
-
-void SPU_Emulate(void)
-{
-	SPU_EmulateSamples(SNDCore->GetAudioSpace());
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Dummy Sound Interface
-//////////////////////////////////////////////////////////////////////////////
-
-static int SNDDummyInit(int buffersize)
-{
-   return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void SNDDummyDeInit()
-{
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples)
-{
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static u32 SNDDummyGetAudioSpace()
-{
-   return 735;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void SNDDummyMuteAudio()
-{
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void SNDDummyUnMuteAudio()
-{
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void SNDDummySetVolume(int volume)
-{
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-SoundInterface_struct SNDDummy =
-{
-	SNDCORE_DUMMY,
-	"Dummy Sound Interface",
-	SNDDummyInit,
-	SNDDummyDeInit,
-	SNDDummyUpdateAudio,
-	SNDDummyGetAudioSpace,
-	SNDDummyMuteAudio,
-	SNDDummyUnMuteAudio,
-	SNDDummySetVolume
-};
-
diff --git a/src/xsf/desmume/SPU.cc b/src/xsf/desmume/SPU.cc
new file mode 100644
index 000000000000..eca09e9aaf35
--- /dev/null
+++ b/src/xsf/desmume/SPU.cc
@@ -0,0 +1,963 @@
+/*  Copyright (C) 2006 Theo Berkau
+
+    Ideas borrowed from Stephane Dallongeville's SCSP core
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "ARM9.h"
+#include "MMU.h"
+#include "SPU.h"
+#include "mem.h"
+
+#include "armcpu.h"
+
+enum
+{
+	FORMAT_PCM8 = 0,
+	FORMAT_PCM16 = 1,
+	FORMAT_ADPCM = 2,
+	FORMAT_PSG = 3
+};
+
+#define VOL_SHIFT 10
+
+typedef struct
+{
+	int id;
+	int status;
+	int format;
+	u8 *buf8; s16 *buf16;
+	double pos, inc;
+	int loopend, looppos;
+	int loop, length;
+	s32 adpcm;
+	int adpcm_pos, adpcm_index;
+	s32 adpcm_loop;
+	int adpcm_loop_pos, adpcm_loop_index;
+	int psg_duty;
+	int timer;
+	int volume;
+	int pan;
+	int shift;
+	int repeat, hold;
+	u32 addr;
+	s32 volumel;
+	s32 volumer;
+	s16 output;
+} SChannel;
+
+typedef struct
+{
+	s32 *pmixbuf;
+	s16 *pclipingbuf;
+	u32 buflen;
+	SChannel ch[16];
+} SPU_struct;
+
+static SPU_struct spu = { 0, 0, 0 };
+
+static SoundInterface_struct *SNDCore=nullptr;
+extern SoundInterface_struct *SNDCoreList[];
+
+int SPU_ChangeSoundCore(int coreid, int buffersize)
+{
+	int i;
+	SPU_DeInit();
+
+   // Allocate memory for sound buffer
+	spu.buflen = buffersize * 2; /* stereo */
+	spu.pmixbuf = (s32 *) malloc(spu.buflen * sizeof(s32));
+	if (!spu.pmixbuf)
+	{
+		SPU_DeInit();
+		return -1;
+	}
+
+	spu.pclipingbuf = (s16 *) malloc(spu.buflen * sizeof(s16));
+	if (!spu.pclipingbuf)
+	{
+		SPU_DeInit();
+		return -1;
+	}
+
+	// So which core do we want?
+	if (coreid == SNDCORE_DEFAULT)
+		coreid = 0; // Assume we want the first one
+
+	// Go through core list and find the id
+	for (i = 0; SNDCoreList[i] != nullptr; i++)
+	{
+		if (SNDCoreList[i]->id == coreid)
+		{
+			// Set to current core
+			SNDCore = SNDCoreList[i];
+			break;
+		}
+	}
+
+	if (SNDCore == nullptr)
+	{
+		SPU_DeInit();
+		return -1;
+	}
+
+	if (SNDCore->Init(spu.buflen) == -1)
+	{
+		// Since it failed, instead of it being fatal, we'll just use the dummy
+		// core instead
+		SNDCore = &SNDDummy;
+	}
+
+   return 0;
+}
+int SPU_Init(int coreid, int buffersize)
+{
+	SPU_DeInit();
+	SPU_Reset();
+	return SPU_ChangeSoundCore(coreid, buffersize);
+}
+void SPU_Pause(int pause)
+{
+	if(pause)
+		SNDCore->MuteAudio();
+	else
+		SNDCore->UnMuteAudio();
+}
+void SPU_SetVolume(int volume)
+{
+	if (SNDCore)
+		SNDCore->SetVolume(volume);
+}
+void SPU_DeInit(void)
+{
+	spu.buflen = 0;
+	if (spu.pmixbuf)
+	{
+		free(spu.pmixbuf);
+		spu.pmixbuf = 0;
+	}
+	if (spu.pclipingbuf)
+	{
+		free(spu.pclipingbuf);
+		spu.pclipingbuf = 0;
+	}
+	if (SNDCore)
+	{
+		SNDCore->DeInit();
+	}
+	SNDCore = &SNDDummy;
+}
+
+static const short g_adpcm_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 4, 4, 6, 6, 8, 8 };
+
+static const int g_adpcm_mult[89] =
+{
+	0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011,
+	0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D,
+	0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076,
+	0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
+	0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C,
+	0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812,
+	0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE,
+	0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
+	0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF,
+};
+
+static const s16 g_psg_duty[8][8] = {
+  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF },
+  { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF },
+};
+
+
+static void reset_channel(SChannel *ch, int id)
+{
+	ch->status = 0;
+	ch->id = id;
+}
+
+void SPU_Reset(void)
+{
+	int i;
+	for (i = 0;i < 16; i++)
+		reset_channel(&spu.ch[i], i);
+
+	for (i = 0x400; i < 0x51D; i++)
+		T1WriteByte(MMU.ARM7_REG, i, 0);
+}
+void SPU_KeyOn(int channel)
+{
+}
+
+static INLINE void adjust_channel_timer(SChannel *ch)
+{
+	ch->inc = (((double)33512000) / (44100 * 2)) / (double)(0x10000 - ch->timer);
+}
+
+static int check_valid(u32 addr, u32 size)
+{
+	u32 t1, t2;
+
+	if(size > MMU.MMU_MASK[1][(addr >> 20) & 0xff]) return 0;
+
+	t1 = addr;
+	t2 = (addr + size);
+	t1 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
+	t2 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff];
+
+	if(t2 < t1) return 0;
+
+	return 1;
+}
+
+static void start_channel(SChannel *ch)
+{
+
+	switch(ch->format)
+	{
+	case FORMAT_PCM8:
+		{
+			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
+			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
+			u32 size = ((ch->length + ch->loop) << 2);
+			if((p != nullptr) && check_valid(ch->addr, size))
+			{
+				ch->buf8 = p + ofs;
+				ch->looppos = ch->loop << 2;
+				ch->loopend = size;
+				ch->pos = 0;
+				ch->status = 1;
+			}
+		}
+	break;
+	case FORMAT_PCM16:
+		{
+			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
+			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
+			u32 size = ((ch->length + ch->loop) << 1);
+			if((p != nullptr) && check_valid(ch->addr, size << 1))
+			{
+				ch->buf16 = (s16 *)(p + ofs - (ofs & 1));
+				ch->looppos = ch->loop << 1;
+				ch->loopend = size;
+				ch->pos = 0;
+				ch->status = 1;
+			}
+		}
+	break;
+	case FORMAT_ADPCM:
+		{
+			u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff];
+			u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr;
+			u32 size = ((ch->length + ch->loop) << 3);
+			if((p != nullptr) && check_valid(ch->addr, size >> 1))
+			{
+				ch->buf8 = p + ofs;
+#ifdef WORDS_BIGENDIAN
+				ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
+#else
+				ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
+#endif
+				ch->adpcm_index = (ch->buf8[2] & 0x7F);
+				ch->adpcm_pos = 8;
+				ch->pos = 9;
+				ch->looppos = ch->loop << 3;
+				ch->loopend = size;
+				ch->adpcm_loop_index = -1;
+				ch->status = 1;
+			}
+		}
+		break;
+	case FORMAT_PSG:
+		ch->status = 1;
+		if(ch->id < 14)
+		{
+			ch->pos = 0;
+		}
+		else
+		{
+			ch->pos = 0x7FFF;
+		}
+		break;
+	}
+}
+
+static void stop_channel(SChannel *ch)
+{
+	u32 addr = 0x400 + (ch->id << 4) + 3;
+	ch->status = 0;
+	T1WriteByte(MMU.ARM7_REG, addr, (u8)(T1ReadByte(MMU.ARM7_REG, addr) & ~0x80));
+}
+static void set_channel_volume(SChannel *ch)
+{
+	s32 vol1 = (T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F) * ch->volume;
+	s32 vol2;
+	vol2 = vol1 * ch->pan;
+	vol1 = vol1 * (127-ch->pan);
+	ch->volumel = vol1 >> (21 - VOL_SHIFT + ch->shift);
+	ch->volumer = vol2 >> (21 - VOL_SHIFT + ch->shift);
+}
+
+void SPU_WriteByte(u32 addr, u8 x)
+{
+	addr &= 0x00000FFF;
+	T1WriteByte(MMU.ARM7_REG, addr, x);
+
+	if(addr < 0x500)
+	{
+		SChannel *ch;
+		switch(addr & 0x0F)
+		{
+		case 0x0:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->volume = (x & 0x7F);
+			set_channel_volume(ch);
+			break;
+		case 0x1:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->shift = (x & 0x03);
+			ch->hold = (x >> 7 & 0x01);
+			set_channel_volume(ch);
+			break;
+		case 0x2:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->pan = (x & 0x7F);
+			set_channel_volume(ch);
+			break;
+		case 0x3:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->psg_duty = (x & 0x07);
+			ch->repeat = (x >> 3 & 0x03);
+			ch->format = (x >> 5 & 0x03);
+			if(x & 0x80) start_channel(ch); else stop_channel(ch);
+			break;
+#if !DISABLE_XSF_TESTS
+		case 0x04:
+		case 0x05:
+		case 0x06:
+		case 0x07:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
+			break;
+		case 0x08:
+		case 0x09:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->timer = T1ReadWord(MMU.ARM7_REG, addr & ~1);
+			adjust_channel_timer(ch);
+			break;
+		case 0x0a:
+		case 0x0b:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->loop = T1ReadWord(MMU.ARM7_REG, addr & ~1);
+			break;
+		case 0x0c:
+		case 0x0e:
+		case 0x0d:
+		case 0x0f:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
+			break;
+#endif
+		}
+	}
+
+}
+
+
+void SPU_WriteWord(u32 addr, u16 x)
+{
+	addr &= 0x00000FFF;
+	T1WriteWord(MMU.ARM7_REG, addr, x);
+
+	if(addr < 0x500)
+	{
+		SChannel *ch;
+		switch(addr & 0x00F)
+		{
+		case 0x0:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->volume = (x & 0x007F);
+			ch->shift = (x >> 8 & 0x0003);
+			ch->hold = (x >> 15 & 0x0001);
+			set_channel_volume(ch);
+			break;
+		case 0x2:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->pan = (x & 0x007F);
+			ch->psg_duty = (x >> 8 & 0x0007);
+			ch->repeat = (x >> 11 & 0x0003);
+			ch->format = (x >> 13 & 0x0003);
+			set_channel_volume(ch);
+			if(x & 0x8000) start_channel(ch); else stop_channel(ch);
+			break;
+		case 0x08:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->timer = x;
+			adjust_channel_timer(ch);
+			break;
+		case 0x0a:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->loop = x;
+			break;
+#if !DISABLE_XSF_TESTS
+		case 0x04:
+		case 0x06:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF);
+			break;
+		case 0x0c:
+		case 0x0e:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF);
+			break;
+#endif
+		}
+	}
+}
+
+
+void SPU_WriteLong(u32 addr, u32 x)
+{
+	addr &= 0x00000FFF;
+	T1WriteLong(MMU.ARM7_REG, addr, x);
+
+	if(addr < 0x500)
+	{
+		SChannel *ch;
+		switch(addr & 0x00F)
+		{
+		case 0x0:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->volume = (x & 0x7F);
+			ch->shift = (x >> 8 & 0x00000003);
+			ch->hold = (x >> 15 & 0x00000001);
+			ch->pan = (x >> 16 & 0x0000007F);
+			ch->psg_duty = (x >> 24 & 0x00000007);
+			ch->repeat = (x >> 27 & 0x00000003);
+			ch->format = (x >> 29 & 0x00000003);
+			set_channel_volume(ch);
+			if(x & 0x80000000) start_channel(ch); else stop_channel(ch);
+			break;
+		case 0x04:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->addr = (x & 0x07FFFFFF);
+			break;
+		case 0x08:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->timer = (x & 0x0000FFFF);
+			ch->loop = (x >> 16 & 0x0000FFFF);
+			adjust_channel_timer(ch);
+			break;
+		case 0x0C:
+			ch = spu.ch + (addr >> 4 & 0xF);
+			ch->length = (x & 0x003FFFFF);
+			break;
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+u32 SPU_ReadLong(u32 addr)
+{
+	addr &= 0xFFF;
+	return T1ReadLong(MMU.ARM7_REG, addr);
+}
+
+static INLINE s32 clipping(s32 x, s32 min, s32 max) {
+#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+	if (x < min)
+	{
+		return (min);
+	}
+	else if (x > max)
+	{
+		return (max);
+	}
+	return (x);
+#else
+	return x ^ ((-(x < min)) & (x ^ min)) ^ ((-(x > max)) & (x ^ max));
+#endif
+}
+
+extern unsigned long dwChannelMute;
+
+static void decode_pcm8(SChannel *ch, s32 *out, int length)
+{
+	int oi;
+	double pos, inc, len;
+	if (!ch->buf8) return;
+
+	pos = ch->pos; inc = ch->inc; len = ch->loopend;
+
+	for(oi = 0; oi < length; oi++)
+	{
+		ch->output = ((s16)(s8)ch->buf8[(int)pos]) << 8;
+#if 0
+		if (dwChannelMute & (1 << ch->id))
+		{
+			out++;
+			out++;
+		}
+		else
+#endif
+		{
+			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
+			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
+		}
+		pos += inc;
+		if(pos >= len)
+		{
+			switch(ch->repeat)
+			{
+#if !DISABLE_XSF_TESTS
+			case 0:
+#endif
+			case 1:
+				pos += ch->looppos - len;
+				break;
+			default:
+				stop_channel(ch);
+				oi = length;
+				break;
+			}
+		}
+	}
+
+	ch->pos = pos;
+	return;
+}
+
+static void decode_pcm16(SChannel *ch, s32 *out, int length)
+{
+	int oi;
+	double pos, inc, len;
+
+	if (!ch->buf16) return;
+
+	pos = ch->pos; inc = ch->inc; len = ch->loopend;
+
+	for(oi = 0; oi < length; oi++)
+	{
+#ifdef WORDS_BIGENDIAN
+		ch->output = (s16)T1ReadWord((u8 *)ch->buf16, (int)pos << 1);
+#else
+		ch->output = (s16)ch->buf16[(int)pos];
+#endif
+#if 0
+		if (dwChannelMute & (1 << ch->id))
+		{
+			out++;
+			out++;
+		}
+		else
+#endif
+		{
+			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
+			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
+		}
+		pos += inc;
+		if(pos >= len)
+		{
+			switch(ch->repeat)
+			{
+#if !DISABLE_XSF_TESTS
+			case 0:
+#endif
+			case 1:
+				pos += ch->looppos - len;
+				break;
+			default:
+				stop_channel(ch);
+				oi = length;
+				break;
+			}
+		}
+	}
+
+	ch->pos = pos;
+}
+
+static INLINE void decode_adpcmone_P4(SChannel *ch, int m)
+{
+	int i, ci0;
+	u8 *p;
+	s32 s;
+	int N;
+
+	i = ch->adpcm_pos;
+	p = (ch->buf8 + (i >> 1));
+	ci0 = ch->adpcm_index;
+	s = ch->adpcm;
+
+	if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
+	{
+		ch->adpcm_loop_index = ci0;
+		ch->adpcm_loop  = s;
+		ch->adpcm_loop_pos  = i;
+	}
+
+	if(i++ & 1)
+	{
+		s32 x1, d1;
+		x1 = ((*(p++) >> 3) & 0x1F) | 1;
+		d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
+		ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
+#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+		if(x1 & 0x10) d1 = -d1;
+#else
+		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
+#endif
+
+		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
+	}
+
+	N = (((m & ~1) - (i & ~1)) >> 1);
+	for(i = 0; i < N; i++)
+	{
+		s32 x0, d0;
+		s32 x1, d1;
+		int ci1;
+		x0 = ((*p << 1) & 0x1F) | 1;
+		x1 = ((*p >> 3) & 0x1F) | 1;
+		ci1 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
+		d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
+		ci0 = clipping((ci1 + g_adpcm_index[x1 & 0xE]), 0, 88);
+		d1 = ((x1 & 0xF) * g_adpcm_mult[ci1] & ~7);
+#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+		if(x0 & 0x10) d0 = -d0;
+		if(x1 & 0x10) d1 = -d1;
+#else
+		d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
+		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
+#endif
+		s = clipping((s + d0), (-32768 << 3), (32767 << 3));
+		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
+		p++;
+	}
+	if(m & 1)
+	{
+		s32 x0, d0;
+		x0 = ((*p << 1) & 0x1F) | 1;
+		d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7);
+		ci0 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88);
+#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+		if(x0 & 0x10) d0 = -d0;
+#else
+		d0 -= (d0 + d0) & (-(((x0 >> 4) & 1)));
+#endif
+		s = clipping((s + d0), (-32768 << 3), (32767 << 3));
+	}
+
+	ch->output = (s16)(s >> 3);
+
+	ch->adpcm = s;
+	ch->adpcm_index = ci0;
+	ch->adpcm_pos = m;
+}
+
+#if 0  // not used
+static INLINE void decode_adpcmone_XX(SChannel *ch, int m)
+{
+	int i, ci0;
+	u8 *p;
+	s32 s;
+
+	i = ch->adpcm_pos;
+	p = (ch->buf8 + (i >> 1));
+	ci0 = ch->adpcm_index;
+	s = ch->adpcm;
+
+	if (ch->adpcm_loop_index < 0 && m >= ch->looppos)
+	{
+		ch->adpcm_loop_index = ci0;
+		ch->adpcm_loop  = s;
+		ch->adpcm_loop_pos  = i;
+	}
+
+	while (i < m)
+	{
+		s32 x1, d1;
+		x1 = ((s32)*p) >> ((i & 1) << 2) & 0xf;
+		x1 = x1 + x1 + 1;
+		d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7);
+		ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88);
+#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+		if(x1 & 0x10) d1 = -d1;
+#else
+		d1 -= (d1 + d1) & (-(((x1 >> 4) & 1)));
+#endif
+
+		s = clipping((s + d1), (-32768 << 3), (32767 << 3));
+		p += (i & 1);
+		i++;
+	}
+
+	ch->output = (s16)(s >> 3);
+
+	ch->adpcm = s;
+	ch->adpcm_index = ci0;
+	ch->adpcm_pos = m;
+}
+#endif
+
+#define decode_adpcmone decode_adpcmone_P4
+
+static void decode_adpcm(SChannel *ch, s32 *out, int length)
+{
+	int oi;
+	double pos, inc, len;
+	if (!ch->buf8) return;
+
+	pos = ch->pos; inc = ch->inc; len = ch->loopend;
+
+	for(oi = 0; oi < length; oi++)
+	{
+		int m = (int)pos;
+		int i = ch->adpcm_pos;
+		if(i < m)
+			decode_adpcmone(ch, m);
+
+#if 0
+		if (dwChannelMute & (1 << ch->id))
+		{
+			out++;
+			out++;
+		}
+		else
+#endif
+		{
+			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
+			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
+		}
+		pos += inc;
+		if(pos >= len)
+		{
+			switch(ch->repeat)
+			{
+			case 1:
+				if (ch->adpcm_loop_index >= 0)
+				{
+					pos += ch->looppos - len;
+					ch->adpcm_pos = ch->adpcm_loop_pos;
+					ch->adpcm_index  = ch->adpcm_loop_index;
+					ch->adpcm  = ch->adpcm_loop;
+					break;
+				}
+#if !DISABLE_XSF_TESTS
+			case 0:
+				pos = 9 - len;
+#ifdef WORDS_BIGENDIAN
+				ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3;
+#else
+				ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3;
+#endif
+				ch->adpcm_index = (ch->buf8[2] & 0x7F);
+				ch->adpcm_pos = 8;
+				break;
+#endif
+			default:
+				stop_channel(ch);
+				oi = length;
+				break;
+			}
+		}
+	}
+	ch->pos = pos;
+}
+
+static void decode_psg(SChannel *ch, s32 *out, int length)
+{
+	int oi;
+
+	if(ch->id < 14)
+	{
+		// NOTE: square wave.
+		double pos, inc;
+		pos = ch->pos; inc = ch->inc;
+		for(oi = 0; oi < length; oi++)
+		{
+			ch->output = (s16)g_psg_duty[ch->psg_duty][(int)pos & 0x00000007];
+#if 0
+			if (dwChannelMute & (1 << ch->id))
+			{
+				out++;
+				out++;
+			}
+			else
+#endif
+			{
+				*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
+				*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
+			}
+			pos += inc;
+		}
+		ch->pos = pos;
+	}
+	else
+	{
+		// NOTE: noise.
+		u16 X;
+		X = (u16)ch->pos;
+		for(oi = 0; oi < length; oi++)
+		{
+			if(X & 1)
+			{
+				X >>= 1;
+				X ^= 0x6000;
+				ch->output = -0x8000;
+			}
+			else
+			{
+				X >>= 1;
+				ch->output = +0x7FFF;
+			}
+		}
+#if 0
+		if (dwChannelMute & (1 << ch->id))
+		{
+			out++;
+			out++;
+		}
+		else
+#endif
+		{
+			*(out++) += (ch->output * ch->volumel) >> VOL_SHIFT;
+			*(out++) += (ch->output * ch->volumer) >> VOL_SHIFT;
+		}
+		ch->pos = X;
+	}
+}
+
+
+
+void SPU_EmulateSamples(u32 numsamples)
+{
+	u32 sizesmp = numsamples;
+	u32 sizebyte = sizesmp << 2;
+	if (sizebyte > spu.buflen * sizeof(s16)) sizebyte = spu.buflen * sizeof(s16);
+	sizesmp = sizebyte >> 2;
+	sizebyte = sizesmp << 2;
+	if (sizesmp > 0)
+	{
+		unsigned i;
+		SChannel *ch = spu.ch;
+		memset(spu.pmixbuf, 0, spu.buflen * sizeof(s32));
+		for (i = 0; i < 16; i++)
+		{
+			if (ch->status)
+			{
+				switch (ch->format)
+				{
+				case 0:
+					decode_pcm8(ch, spu.pmixbuf, sizesmp);
+					break;
+				case 1:
+					decode_pcm16(ch, spu.pmixbuf, sizesmp);
+					break;
+				case 2:
+					decode_adpcm(ch, spu.pmixbuf, sizesmp);
+					break;
+				case 3:
+					decode_psg(ch, spu.pmixbuf, sizesmp);
+					break;
+				}
+			}
+			ch++;
+		}
+		for (i = 0; i < sizesmp * 2; i++)
+			spu.pclipingbuf[i] = (s16)clipping(spu.pmixbuf[i], -0x8000, 0x7fff);
+		SNDCore->UpdateAudio(spu.pclipingbuf, sizesmp);
+	}
+}
+
+void SPU_Emulate(void)
+{
+	SPU_EmulateSamples(SNDCore->GetAudioSpace());
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Dummy Sound Interface
+//////////////////////////////////////////////////////////////////////////////
+
+static int SNDDummyInit(int buffersize)
+{
+   return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void SNDDummyDeInit()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static u32 SNDDummyGetAudioSpace()
+{
+   return 735;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void SNDDummyMuteAudio()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void SNDDummyUnMuteAudio()
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void SNDDummySetVolume(int volume)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+SoundInterface_struct SNDDummy =
+{
+	SNDCORE_DUMMY,
+	"Dummy Sound Interface",
+	SNDDummyInit,
+	SNDDummyDeInit,
+	SNDDummyUpdateAudio,
+	SNDDummyGetAudioSpace,
+	SNDDummyMuteAudio,
+	SNDDummyUnMuteAudio,
+	SNDDummySetVolume
+};
+
diff --git a/src/xsf/desmume/SPU.h b/src/xsf/desmume/SPU.h
index 2f39b9e674ab..9752a424964f 100644
--- a/src/xsf/desmume/SPU.h
+++ b/src/xsf/desmume/SPU.h
@@ -14,7 +14,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef SPU_H
diff --git a/src/xsf/desmume/arm_instructions.c b/src/xsf/desmume/arm_instructions.c
deleted file mode 100644
index 4bbf42ce99eb..000000000000
--- a/src/xsf/desmume/arm_instructions.c
+++ /dev/null
@@ -1,7857 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    Copyright (C) 2006 shash
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-	Copyright (C) 2006-2007 shash
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "cp15.h"
-#include "debug.h"
-#include "MMU.h"
-
-
-// Use this macros for reading/writing, so the GDB stub isn't broken
-#ifdef GDB_STUB
-	#define READ32(a,b)		cpu->mem_if->read32(a,b)
-	#define WRITE32(a,b,c)	cpu->mem_if->write32(a,b,c)
-	#define READ16(a,b)		cpu->mem_if->read16(a,b)
-	#define WRITE16(a,b,c)	cpu->mem_if->write16(a,b,c)
-	#define READ8(a,b)		cpu->mem_if->read8(a,b)
-	#define WRITE8(a,b,c)	cpu->mem_if->write8(a,b,c)
-#else
-	#define READ32(a,b)		MMU_read32(cpu->proc_ID, b)
-	#define WRITE32(a,b,c)	MMU_write32(cpu->proc_ID,b,c)
-	#define READ16(a,b)		MMU_read16(cpu->proc_ID, b)
-	#define WRITE16(a,b,c)	MMU_write16(cpu->proc_ID,b,c)
-	#define READ8(a,b)		MMU_read8(cpu->proc_ID, b)
-	#define WRITE8(a,b,c)	MMU_write8(cpu->proc_ID,b,c)
-#endif
-
-
-
-#define LSL_IMM shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);
-
-#define S_LSL_IMM u32 shift_op = ((i>>7)&0x1F);\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-          shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-     {\
-         c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\
-         shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);\
-     }
-     
-#define LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     if(shift_op>=32)\
-             shift_op=0;\
-     else\
-             shift_op=cpu->R[REG_POS(i,0)]<<shift_op;
-
-#define S_LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-             shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-             if(shift_op<32)\
-             {\
-                  c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\
-                  shift_op = cpu->R[REG_POS(i,0)]<<shift_op;\
-             }\
-             else\
-                 if(shift_op==32)\
-                 {\
-                      shift_op = 0;\
-                      c = BIT0(cpu->R[REG_POS(i,0)]);\
-                 }\
-                 else\
-                 {\
-                      shift_op = 0;\
-                      c = 0;\
-                 }                 
-
-#define LSR_IMM      shift_op = ((i>>7)&0x1F);\
-     if(shift_op!=0)\
-            shift_op = cpu->R[REG_POS(i,0)]>>shift_op;
-
-#define S_LSR_IMM      u32 shift_op = ((i>>7)&0x1F);\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-     {\
-          c = BIT31(cpu->R[REG_POS(i,0)]);\
-     }\
-     else\
-     {\
-         c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-         shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\
-     }
-
-#define LSR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     if(shift_op>=32)\
-             shift_op = 0;\
-     else\
-             shift_op = cpu->R[REG_POS(i,0)]>>shift_op;
-
-#define S_LSR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-     {\
-             shift_op = cpu->R[REG_POS(i,0)];\
-     }\
-     else\
-             if(shift_op<32)\
-             {\
-                  c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-                  shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\
-             }\
-             else\
-                  if(shift_op==32)\
-                  {\
-                       c = BIT31(cpu->R[REG_POS(i,0)]);\
-                       shift_op = 0;\
-                  }\
-                  else\
-                  {\
-                       c = 0;\
-                       shift_op = 0;\
-                  }
-
-#define ASR_IMM      shift_op = ((i>>7)&0x1F);\
-     if(shift_op==0)\
-            shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
-     else\
-            shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);
-
-#define S_ASR_IMM      u32 shift_op = ((i>>7)&0x1F);\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-     {\
-            shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
-            c = BIT31(cpu->R[REG_POS(i,0)]);\
-     }\
-     else\
-     {\
-            c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-            shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
-     }
-
-#define ASR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     if(shift_op==0)\
-             shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-             if(shift_op<32)\
-                     shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
-             else\
-                     shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;
-                     
-#define S_ASR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-             shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-             if(shift_op<32)\
-             {\
-                     c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-                     shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
-             }\
-             else\
-             {\
-                     c = BIT31(cpu->R[REG_POS(i,0)]);\
-                     shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
-             }
-                     
-#define ROR_IMM      shift_op = ((i>>7)&0x1F);\
-     if(shift_op==0)\
-     {\
-             u32 tmp = cpu->CPSR.bits.C;\
-             shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\
-     }\
-     else\
-             shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);
-             
-#define S_ROR_IMM      u32 shift_op = ((i>>7)&0x1F);\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-     {\
-             u32 tmp = cpu->CPSR.bits.C;\
-             shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\
-             c = BIT0(cpu->R[REG_POS(i,0)]);\
-     }\
-     else\
-     {\
-             c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-             shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);\
-     }
-             
-#define ROR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     if((shift_op==0)||((shift_op&0xF)==0))\
-             shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-             shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));
-
-#define S_ROR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
-     u32 c = cpu->CPSR.bits.C;\
-     if(shift_op==0)\
-             shift_op=cpu->R[REG_POS(i,0)];\
-     else\
-     {\
-             shift_op&=0xF;\
-             if(shift_op==0)\
-             {\
-                  shift_op=cpu->R[REG_POS(i,0)];\
-                  c = BIT31(cpu->R[REG_POS(i,0)]);\
-             }\
-             else\
-             {\
-                 c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
-                  shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));\
-             }\
-     }
-
-#define IMM_VALUE      u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);
-
-#define S_IMM_VALUE      u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\
-     u32 c = cpu->CPSR.bits.C;\
-        if((i>>8)&0xF)\
-             c = BIT31(shift_op);
-
-#define IMM_OFF (((i>>4)&0xF0)+(i&0xF))
-
-#define IMM_OFF_12 ((i)&0xFFF)
-
-extern BOOL execute;
-
-static u32 FASTCALL  OP_UND(armcpu_t *cpu)
-{
-	LOG("Undefined instruction: %08X\n", cpu->instruction);
-	execute = FALSE;
-	return 1;
-}
- 
-//-----------------------AND------------------------------------
-
-#define OP_AND(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-
-#define OP_ANDS(a, b)\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR;\
-          cpu->R[15] = cpu->R[REG_POS(i,16)] & shift_op;\
-          SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     return a;
- 
-static u32 FASTCALL  OP_AND_LSL_IMM(register armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_AND(1, 3);
-}
-
-static u32 FASTCALL  OP_AND_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_AND(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_AND(1, 3);
-}
-
-static u32 FASTCALL  OP_AND_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_AND(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_AND(1, 3);
-}
-
-static u32 FASTCALL  OP_AND_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_AND(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_AND(1, 3);
-}
-
-static u32 FASTCALL  OP_AND_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_AND(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_AND(1, 3);
-}
-
-static u32 FASTCALL  OP_AND_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OP_ANDS(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OP_ANDS(3, 5);
-}
-
-static u32 FASTCALL  OP_AND_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OP_ANDS(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;             
-     OP_ANDS(3, 5);
-}
-
-static u32 FASTCALL  OP_AND_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OP_ANDS(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;                     
-     OP_ANDS(3, 5);
-}
-
-static u32 FASTCALL  OP_AND_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OP_ANDS(2, 4);
-}
-
-static u32 FASTCALL  OP_AND_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OP_ANDS(3, 5);
-}
-
-static u32 FASTCALL  OP_AND_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OP_ANDS(2, 4);
-}
-
-//--------------EOR------------------------------
-
-#define OP_EOR(a, b)    cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a; 
-       
-#define OP_EORS(a, b)          cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     return a;
-
-static u32 FASTCALL  OP_EOR_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_EOR(1, 3); 
-}
-
-static u32 FASTCALL  OP_EOR_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_EOR(2, 4); 
-}
-
-static u32 FASTCALL  OP_EOR_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_EOR(1, 3); 
-}
-
-static u32 FASTCALL  OP_EOR_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_EOR(2, 4); 
-}
-
-static u32 FASTCALL  OP_EOR_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_EOR(1, 3); 
-}
-
-static u32 FASTCALL  OP_EOR_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_EOR(2, 4); 
-}
-
-static u32 FASTCALL  OP_EOR_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_EOR(1, 3); 
-}
-
-static u32 FASTCALL  OP_EOR_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_EOR(2, 4); 
-}
-
-static u32 FASTCALL  OP_EOR_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_EOR(1, 3); 
-}
-
-static u32 FASTCALL  OP_EOR_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OP_EORS(2, 4);
-}
-
-static u32 FASTCALL  OP_EOR_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OP_EORS(3, 5);
-}
-
-static u32 FASTCALL  OP_EOR_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OP_EORS(2, 4);
-}
-
-static u32 FASTCALL  OP_EOR_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;            
-     OP_EORS(3, 5);
-}
-
-static u32 FASTCALL  OP_EOR_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OP_EORS(2, 4);
-}
-
-static u32 FASTCALL  OP_EOR_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;                     
-     OP_EORS(3, 5);
-}
-
-static u32 FASTCALL  OP_EOR_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OP_EORS(2, 4);
-}
-
-static u32 FASTCALL  OP_EOR_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OP_EORS(3, 5);
-}
-
-static u32 FASTCALL  OP_EOR_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OP_EORS(2, 4);
-}
-
-//-------------SUB-------------------------------------
-
-#define OP_SUB(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-
-#define OPSUBS(a, b)          cpu->R[REG_POS(i,12)] = v - shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
-     return a;
-
-static u32 FASTCALL  OP_SUB_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_SUB(1, 3);
-}
-
-static u32 FASTCALL  OP_SUB_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_SUB(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_SUB(1, 3);
-}
-
-static u32 FASTCALL  OP_SUB_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_SUB(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_SUB(1, 3);
-}
-
-static u32 FASTCALL  OP_SUB_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_SUB(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_SUB(1, 3);
-}
-
-static u32 FASTCALL  OP_SUB_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_SUB(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_SUB(1, 3);
-}
-
-static u32 FASTCALL  OP_SUB_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OPSUBS(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OPSUBS(3, 5);
-}
-
-static u32 FASTCALL  OP_SUB_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OPSUBS(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OPSUBS(3, 5);
-}
-
-static u32 FASTCALL  OP_SUB_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OPSUBS(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OPSUBS(3, 5);
-}
-
-static u32 FASTCALL  OP_SUB_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OPSUBS(2, 4);
-}
-
-static u32 FASTCALL  OP_SUB_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OPSUBS(3, 5);
-}
-
-static u32 FASTCALL  OP_SUB_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OPSUBS(2, 4);
-}
-
-//------------------RSB------------------------
-
-#define OP_RSB(a, b)      cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)];\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-
-#define OP_RSBS(a, b)      cpu->R[REG_POS(i,12)] = shift_op - v;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\
-     return a;
-     
-static u32 FASTCALL  OP_RSB_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_RSB(1, 3);
-}
-
-static u32 FASTCALL  OP_RSB_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_RSB(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_RSB(1, 3);
-}
-
-static u32 FASTCALL  OP_RSB_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_RSB(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_RSB(1, 3);
-}
-
-static u32 FASTCALL  OP_RSB_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_RSB(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_RSB(1, 3);
-}
-
-static u32 FASTCALL  OP_RSB_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_RSB(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_RSB(1, 3);
-}
-
-static u32 FASTCALL  OP_RSB_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OP_RSBS(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OP_RSBS(3, 5);
-}
-
-static u32 FASTCALL  OP_RSB_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OP_RSBS(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OP_RSBS(3, 5);
-}
-
-static u32 FASTCALL  OP_RSB_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OP_RSBS(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OP_RSBS(3, 5);
-}
-
-static u32 FASTCALL  OP_RSB_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OP_RSBS(2, 4);
-}
-
-static u32 FASTCALL  OP_RSB_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OP_RSBS(3, 5);
-}
-
-static u32 FASTCALL  OP_RSB_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OP_RSBS(2, 4);
-}
-
-//------------------ADD-----------------------------------
-
-#define OP_ADD(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-
-static u32 FASTCALL  OP_ADD_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_ADD(1, 3);
-}
-
-static u32 FASTCALL  OP_ADD_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_ADD(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_ADD(1, 3);
-}
-
-static u32 FASTCALL  OP_ADD_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_ADD(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_ADD(1, 3);
-}
-
-static u32 FASTCALL  OP_ADD_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_ADD(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_ADD(1, 3);
-}
-
-static u32 FASTCALL  OP_ADD_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_ADD(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_ADD(1, 3);
-}
-
-#define OP_ADDS(a, b) cpu->R[REG_POS(i,12)] = v + shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
-     return a;
-     
-static u32 FASTCALL  OP_ADD_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OP_ADDS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OP_ADDS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADD_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OP_ADDS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OP_ADDS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADD_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OP_ADDS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OP_ADDS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADD_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OP_ADDS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADD_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OP_ADDS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADD_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OP_ADDS(2, 4);
-}
-
-//------------------ADC-----------------------------------
-
-#define OP_ADC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op + cpu->CPSR.bits.C;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-     
-static u32 FASTCALL  OP_ADC_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_ADC(1, 3);
-}
-
-static u32 FASTCALL  OP_ADC_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_ADC(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_ADC(1, 3);
-}
-
-static u32 FASTCALL  OP_ADC_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_ADC(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_ADC(1, 3);
-}
-
-static u32 FASTCALL  OP_ADC_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_ADC(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_ADC(1, 3);
-}
-
-static u32 FASTCALL  OP_ADC_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_ADC(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_ADC(1, 3);
-}
-
-#define OP_ADCS(a, b) \
-     { \
-     u32 tmp = shift_op + cpu->CPSR.bits.C;\
-     cpu->R[REG_POS(i,12)] = v + tmp;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\
-     return a; \
-     }
-     
-static u32 FASTCALL  OP_ADC_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OP_ADCS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OP_ADCS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADC_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OP_ADCS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OP_ADCS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADC_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OP_ADCS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OP_ADCS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADC_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OP_ADCS(2, 4);
-}
-
-static u32 FASTCALL  OP_ADC_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OP_ADCS(3, 5);
-}
-
-static u32 FASTCALL  OP_ADC_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OP_ADCS(2, 4);
-}
-
-//-------------SBC-------------------------------------
-
-#define OP_SBC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op - (!cpu->CPSR.bits.C);\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-     
-static u32 FASTCALL  OP_SBC_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_SBC(1, 3);
-}
-
-static u32 FASTCALL  OP_SBC_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_SBC(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_SBC(1, 3);
-}
-
-static u32 FASTCALL  OP_SBC_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_SBC(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_SBC(1, 3);
-}
-
-static u32 FASTCALL  OP_SBC_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_SBC(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_SBC(1, 3);
-}
-
-static u32 FASTCALL  OP_SBC_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_SBC(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_SBC(1, 3);
-}
-
-#define OP_SBCS(a, b) \
-     { \
-     u32 tmp = v - (!cpu->CPSR.bits.C);\
-     cpu->R[REG_POS(i,12)] = tmp - shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]));\
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]);\
-     return a; \
-     }
-
-static u32 FASTCALL  OP_SBC_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OP_SBCS(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OP_SBCS(3, 5);
-}
-
-static u32 FASTCALL  OP_SBC_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OP_SBCS(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OP_SBCS(3, 5);
-}
-
-static u32 FASTCALL  OP_SBC_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OP_SBCS(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OP_SBCS(3, 5);
-}
-
-static u32 FASTCALL  OP_SBC_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OP_SBCS(2, 4);
-}
-
-static u32 FASTCALL  OP_SBC_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OP_SBCS(3, 5);
-}
-
-static u32 FASTCALL  OP_SBC_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OP_SBCS(2, 4);
-}
-
-//---------------RSC----------------------------------
-
-#define OP_RSC(a, b) cpu->R[REG_POS(i,12)] =  shift_op - cpu->R[REG_POS(i,16)] - (!cpu->CPSR.bits.C);\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-     
-static u32 FASTCALL  OP_RSC_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_RSC(1, 3);
-}
-
-static u32 FASTCALL  OP_RSC_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_RSC(2, 4);
-}
-
-static u32 FASTCALL  OP_RSC_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_RSC(1, 3);
-}
-
-static u32 FASTCALL  OP_RSC_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_RSC(2, 4);
-}
-
-static u32 FASTCALL  OP_RSC_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_RSC(1, 3);
-}
-
-static u32 FASTCALL  OP_RSC_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_RSC(2, 4);
-}
-
-static u32 FASTCALL  OP_RSC_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_RSC(1, 3);
-}
-
-static u32 FASTCALL  OP_RSC_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_RSC(2, 4);
-}
-
-static u32 FASTCALL  OP_RSC_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_RSC(1, 3);
-}
-
-#define OP_RSCS(a,b) \
-     { \
-     u32 tmp = shift_op - (!cpu->CPSR.bits.C);\
-     cpu->R[REG_POS(i,12)] = tmp - v;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-          }\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]));\
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]);\
-     return a; \
-     }
-
-static u32 FASTCALL  OP_RSC_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSL_IMM;
-     OP_RSCS(2,4);
-}
-
-static u32 FASTCALL  OP_RSC_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSL_REG;
-     OP_RSCS(3,5);
-}
-
-static u32 FASTCALL  OP_RSC_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     LSR_IMM;            
-     OP_RSCS(2,4);
-}
-
-static u32 FASTCALL  OP_RSC_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     LSR_REG;             
-     OP_RSCS(3,5);
-}
-
-static u32 FASTCALL  OP_RSC_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ASR_IMM;
-     OP_RSCS(2,4);
-}
-
-static u32 FASTCALL  OP_RSC_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ASR_REG;                     
-     OP_RSCS(3,5);
-}
-
-static u32 FASTCALL  OP_RSC_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     u32 shift_op;
-     ROR_IMM;
-     OP_RSCS(2,4);
-}
-
-static u32 FASTCALL  OP_RSC_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     ROR_REG;
-     OP_RSCS(3,5);
-}
-
-static u32 FASTCALL  OP_RSC_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,16)];
-     IMM_VALUE;
-     OP_RSCS(2,4);
-}
-
-//-------------------TST----------------------------
-
-#define OP_TST(a) \
-     { \
-     unsigned tmp = cpu->R[REG_POS(i,16)] & shift_op;\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(tmp);\
-     cpu->CPSR.bits.Z = (tmp==0);\
-     return a; \
-     }
-     
-static u32 FASTCALL  OP_TST_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OP_TST(1);
-}
-
-static u32 FASTCALL  OP_TST_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OP_TST(2);
-}
-
-static u32 FASTCALL  OP_TST_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OP_TST(1);
-}
-
-static u32 FASTCALL  OP_TST_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;             
-     OP_TST(2);
-}
-
-static u32 FASTCALL  OP_TST_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OP_TST(1);
-}
-
-static u32 FASTCALL  OP_TST_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;                     
-     OP_TST(2);
-}
-
-static u32 FASTCALL  OP_TST_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OP_TST(1);
-}
-
-static u32 FASTCALL  OP_TST_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OP_TST(2);
-}
-
-static u32 FASTCALL  OP_TST_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OP_TST(1);
-}
-
-//-------------------TEQ----------------------------
-
-#define OP_TEQ(a) \
-     { \
-     unsigned tmp = cpu->R[REG_POS(i,16)] ^ shift_op;\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(tmp);\
-     cpu->CPSR.bits.Z = (tmp==0);\
-     return a; \
-     }
-     
-static u32 FASTCALL  OP_TEQ_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OP_TEQ(1);
-}
-
-static u32 FASTCALL  OP_TEQ_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OP_TEQ(2);
-}
-
-static u32 FASTCALL  OP_TEQ_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OP_TEQ(1);
-}
-
-static u32 FASTCALL  OP_TEQ_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;             
-     OP_TEQ(2);
-}
-
-static u32 FASTCALL  OP_TEQ_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OP_TEQ(1);
-}
-
-static u32 FASTCALL  OP_TEQ_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;                     
-     OP_TEQ(2);
-}
-
-static u32 FASTCALL  OP_TEQ_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OP_TEQ(1);
-}
-
-static u32 FASTCALL  OP_TEQ_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OP_TEQ(2);
-}
-
-static u32 FASTCALL  OP_TEQ_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OP_TEQ(1);
-}
-
-//-------------CMP-------------------------------------
-
-#define OP_CMP(a) \
-     { \
-     u32 tmp = cpu->R[REG_POS(i,16)] - shift_op;\
-     cpu->CPSR.bits.N = BIT31(tmp);\
-     cpu->CPSR.bits.Z = (tmp==0);\
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
-     return a; \
-     }
-     
-static u32 FASTCALL  OP_CMP_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_CMP(1);
-}
-
-static u32 FASTCALL  OP_CMP_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_CMP(2);
-}
-
-static u32 FASTCALL  OP_CMP_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_CMP(1);
-}
-
-static u32 FASTCALL  OP_CMP_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_CMP(2);
-}
-
-static u32 FASTCALL  OP_CMP_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_CMP(1);
-}
-
-static u32 FASTCALL  OP_CMP_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_CMP(2);
-}
-
-static u32 FASTCALL  OP_CMP_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_CMP(1);
-}
-
-static u32 FASTCALL  OP_CMP_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_CMP(2);
-}
-
-static u32 FASTCALL  OP_CMP_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_CMP(1);
-}
-
-//---------------CMN---------------------------
-
-#define OP_CMN(a) \
-     { \
-     u32 tmp = cpu->R[REG_POS(i,16)] + shift_op;\
-     cpu->CPSR.bits.N = BIT31(tmp);\
-     cpu->CPSR.bits.Z = (tmp==0);\
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
-     return a; \
-     }
-
-static u32 FASTCALL  OP_CMN_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_CMN(1);
-}
-
-static u32 FASTCALL  OP_CMN_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_CMN(2);
-}
-
-static u32 FASTCALL  OP_CMN_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_CMN(1);
-}
-
-static u32 FASTCALL  OP_CMN_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_CMN(2);
-}
-
-static u32 FASTCALL  OP_CMN_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_CMN(1);
-}
-
-static u32 FASTCALL  OP_CMN_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_CMN(2);
-}
-
-static u32 FASTCALL  OP_CMN_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_CMN(1);
-}
-
-static u32 FASTCALL  OP_CMN_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_CMN(2);
-}
-
-static u32 FASTCALL  OP_CMN_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_CMN(1);
-}
-
-//------------------ORR-------------------
-
-#define OP_ORR(a, b)  cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-
-static u32 FASTCALL  OP_ORR_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_ORR(1, 3);
-}
-
-static u32 FASTCALL  OP_ORR_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OP_ORR(2, 4);
-}
-
-static u32 FASTCALL  OP_ORR_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_ORR(1, 3);
-}
-
-static u32 FASTCALL  OP_ORR_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OP_ORR(2, 4);
-}
-
-static u32 FASTCALL  OP_ORR_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_ORR(1, 3);
-}
-
-static u32 FASTCALL  OP_ORR_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_ORR(2, 4);
-}
-
-static u32 FASTCALL  OP_ORR_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_ORR(1, 3);
-}
-
-static u32 FASTCALL  OP_ORR_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_ORR(2, 4);
-}
-
-static u32 FASTCALL  OP_ORR_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_ORR(1, 3);
-}
-
-static u32 FASTCALL  OP_ORR_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 4;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 2;
-}
-
-static u32 FASTCALL  OP_ORR_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 5;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 3;
-}
-
-static u32 FASTCALL  OP_ORR_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 4;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 2;
-}
-
-static u32 FASTCALL  OP_ORR_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;             
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 5;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 3;
-}
-
-static u32 FASTCALL  OP_ORR_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 4;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 2;
-}
-
-static u32 FASTCALL  OP_ORR_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;                     
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 5;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 3;
-}
-
-static u32 FASTCALL  OP_ORR_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 4;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 2;
-}
-
-static u32 FASTCALL  OP_ORR_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 5;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 3;
-}
-
-static u32 FASTCALL  OP_ORR_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
-     if(REG_POS(i,12)==15)
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
-          cpu->next_instruction = cpu->R[15];
-          return 4;
-     }
-     cpu->CPSR.bits.C = c;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
-     return 2;
-}
-
-//------------------MOV-------------------
-
-#define OP_MOV(a, b)      cpu->R[REG_POS(i,12)] = shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = shift_op;\
-          return b;\
-     }\
-     return a;
-     
-#define OP_MOV_S(a, b)    cpu->R[REG_POS(i,12)] = shift_op;\
-     if(BIT20(i) && REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     return a;\
-
-static u32 FASTCALL  OP_MOV_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OP_MOV(1,3);
-}
-
-static u32 FASTCALL  OP_MOV_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-	 if (REG_POS(i,0) == 15) shift_op += 4;
-     OP_MOV(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OP_MOV(1,3);
-}
-
-static u32 FASTCALL  OP_MOV_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;  
-	 if (REG_POS(i,0) == 15) shift_op += 4;
-     OP_MOV(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OP_MOV(1,3);
-}
-
-static u32 FASTCALL  OP_MOV_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OP_MOV(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OP_MOV(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OP_MOV(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OP_MOV(1,3);
-}
-
-static u32 FASTCALL  OP_MOV_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OP_MOV_S(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-	 if (REG_POS(i,0) == 15) shift_op += 4;
-     OP_MOV_S(3,5);
-}
-
-static u32 FASTCALL  OP_MOV_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;   
-     OP_MOV_S(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;  
-	 if (REG_POS(i,0) == 15) shift_op += 4;
-     OP_MOV_S(3,5);           
-}
-
-static u32 FASTCALL  OP_MOV_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OP_MOV_S(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;  
-     OP_MOV_S(3,5);                   
-}
-
-static u32 FASTCALL  OP_MOV_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OP_MOV_S(2,4);
-}
-
-static u32 FASTCALL  OP_MOV_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OP_MOV_S(3,5);
-}
-
-static u32 FASTCALL  OP_MOV_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OP_MOV_S(2,4);
-}
-
-//------------------BIC-------------------
-#define OPP_BIC(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-     
-#define OPP_BIC_S(a, b)    cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     return a;
-     
-static u32 FASTCALL  OP_BIC_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OPP_BIC(1,3);
-}
-
-static u32 FASTCALL  OP_BIC_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OPP_BIC(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OPP_BIC(1,3);
-}
-
-static u32 FASTCALL  OP_BIC_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;             
-     OPP_BIC(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OPP_BIC(1,3);
-}
-
-static u32 FASTCALL  OP_BIC_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;                     
-     OPP_BIC(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OPP_BIC(1,3);
-}
-
-static u32 FASTCALL  OP_BIC_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OPP_BIC(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OPP_BIC(1,3);
-}
-
-static u32 FASTCALL  OP_BIC_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OPP_BIC_S(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OPP_BIC_S(3,5);
-}
-
-static u32 FASTCALL  OP_BIC_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OPP_BIC_S(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;
-     OPP_BIC_S(3,5);
-}
-
-static u32 FASTCALL  OP_BIC_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OPP_BIC_S(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;
-     OPP_BIC_S(3,5);
-}
-
-static u32 FASTCALL  OP_BIC_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OPP_BIC_S(2,4);
-}
-
-static u32 FASTCALL  OP_BIC_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OPP_BIC_S(3,5);
-}
-
-static u32 FASTCALL  OP_BIC_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OPP_BIC_S(2,4);
-}
-
-//------------------MVN-------------------
-#define OPP_MVN(a, b)     cpu->R[REG_POS(i,12)] = ~shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     return a;
-     
-#define OPP_MVN_S(a, b)   cpu->R[REG_POS(i,12)] = ~shift_op;\
-     if(REG_POS(i,12)==15)\
-     {\
-          Status_Reg SPSR = cpu->SPSR;\
-          armcpu_switchMode(cpu, SPSR.bits.mode);\
-          cpu->CPSR=SPSR;\
-          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
-          cpu->next_instruction = cpu->R[15];\
-          return b;\
-     }\
-     cpu->CPSR.bits.C = c;\
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
-     return a;
-     
-static u32 FASTCALL  OP_MVN_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSL_IMM;
-     OPP_MVN(1,3);
-}
-
-static u32 FASTCALL  OP_MVN_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSL_REG;
-     OPP_MVN(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     LSR_IMM;            
-     OPP_MVN(1,3);
-}
-
-static u32 FASTCALL  OP_MVN_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     LSR_REG;
-     OPP_MVN(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ASR_IMM;
-     OPP_MVN(1,3);
-}
-
-static u32 FASTCALL  OP_MVN_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ASR_REG;
-     OPP_MVN(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 shift_op;
-     ROR_IMM;
-     OPP_MVN(1,3);
-}
-
-static u32 FASTCALL  OP_MVN_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     ROR_REG;
-     OPP_MVN(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     OPP_MVN(1,3);
-}
-
-static u32 FASTCALL  OP_MVN_S_LSL_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_IMM;
-     OPP_MVN_S(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_S_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSL_REG;
-     OPP_MVN_S(3,5);
-}
-
-static u32 FASTCALL  OP_MVN_S_LSR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_IMM;            
-     OPP_MVN_S(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_S_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_LSR_REG;
-     OPP_MVN_S(3,5);
-}
-
-static u32 FASTCALL  OP_MVN_S_ASR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_IMM;
-     OPP_MVN_S(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_S_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ASR_REG;
-     OPP_MVN_S(3,5);
-}
-
-static u32 FASTCALL  OP_MVN_S_ROR_IMM(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_IMM;
-     OPP_MVN_S(2,4);
-}
-
-static u32 FASTCALL  OP_MVN_S_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_ROR_REG;
-     OPP_MVN_S(3,5);
-}
-
-static u32 FASTCALL  OP_MVN_S_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     S_IMM_VALUE;
-     OPP_MVN_S(2,4);
-}
-
-//-------------MUL------------------------
-#define OPP_M(a,b)     v >>= 8;\
-     if((v==0)||(v==0xFFFFFF))\
-          return b;\
-     v >>= 8;\
-     if((v==0)||(v==0xFFFF))\
-          return b+1;\
-     v >>= 8;\
-     if((v==0)||(v==0xFF))\
-          return b+2;\
-     return a;\
-
-static u32 FASTCALL  OP_MUL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v;
-     OPP_M(5,2);
-}
-
-static u32 FASTCALL  OP_MLA(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     u32 a = cpu->R[REG_POS(i,8)];
-     u32 b = cpu->R[REG_POS(i,12)];
-     cpu->R[REG_POS(i,16)] = a * v + b;
-     
-     OPP_M(6,3);
-}
-
-static u32 FASTCALL  OP_MUL_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v;
-     
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0);
-     
-     OPP_M(6,3);
-}
-
-static u32 FASTCALL  OP_MLA_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v + cpu->R[REG_POS(i,12)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0);
-     OPP_M(7,4);
-}
-
-//----------UMUL--------------------------
-
-static u32 FASTCALL  OP_UMULL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)];
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] = (u32)(res>>32);   
-       
-     OPP_M(6,3);
-}
-
-static u32 FASTCALL  OP_UMLAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)];
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] += (u32)(res>>32);     
-     
-     OPP_M(7,4);
-}
-
-static u32 FASTCALL  OP_UMULL_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)];
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] = (u32)(res>>32);     
-     
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
-
-     OPP_M(7,4);
-}
-
-static u32 FASTCALL  OP_UMLAL_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_POS(i,0)];
-     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)];
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] += (u32)(res>>32);    
-      
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
-     
-     OPP_M(8,5);
-}
-
-//----------SMUL--------------------------
-
-static u32 FASTCALL  OP_SMULL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 v = (s32)cpu->R[REG_POS(i,0)];
-     s64 b = (s32)cpu->R[REG_POS(i,8)];
-     s64 res = v * b;
-     
-     cpu->R[REG_POS(i,12)] = (u32)(res&0xFFFFFFFF);
-     cpu->R[REG_POS(i,16)] = (u32)(res>>32);     
-     
-     v &= 0xFFFFFFFF;
-          
-     OPP_M(6,3);
-}
-
-static u32 FASTCALL  OP_SMLAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     
-     s64 v = (s32)cpu->R[REG_POS(i,0)];
-     s64 b = (s32)cpu->R[REG_POS(i,8)];
-     s64 res = v * b + (u64)cpu->R[REG_POS(i,12)];
-     
-     //LOG("%08X * %08X + %08X%08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]);
-
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] += (u32)(res>>32);     
-     
-     //LOG("= %08X%08X  %08X%08X\r\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res);
-     
-     v &= 0xFFFFFFFF;
-          
-     OPP_M(7,4);
-}
-
-static u32 FASTCALL  OP_SMULL_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 v = (s32)cpu->R[REG_POS(i,0)];
-     s64 b = (s32)cpu->R[REG_POS(i,8)];
-     s64 res = v * b;
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] = (u32)(res>>32);     
-     
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
-
-     v &= 0xFFFFFFFF;
-          
-     OPP_M(7,4);
-}
-
-static u32 FASTCALL  OP_SMLAL_S(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 v = (s32)cpu->R[REG_POS(i,0)];
-     s64 b = (s32)cpu->R[REG_POS(i,8)];
-     s64 res = v * b + (u64)cpu->R[REG_POS(i,12)];
-     
-     cpu->R[REG_POS(i,12)] = (u32)res;
-     cpu->R[REG_POS(i,16)] += (u32)(res>>32);    
-      
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
-     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
-
-     v &= 0xFFFFFFFF;
-          
-     OPP_M(8,5);
-}
-
-//---------------SWP------------------------------
-
-static u32 FASTCALL  OP_SWP(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 tmp = ROR(READ32(cpu->mem_if->data, adr), ((cpu->R[REG_POS(i,16)]&3)<<3));
-     
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]);
-     cpu->R[REG_POS(i,12)] = tmp;
-     
-     return 4 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]*2;
-}
-
-static u32 FASTCALL  OP_SWPB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u8 tmp = READ8(cpu->mem_if->data, adr);
-     WRITE8(cpu->mem_if->data, adr, (u8)(cpu->R[REG_POS(i,0)]&0xFF));
-     cpu->R[REG_POS(i,12)] = tmp;
-
-     return 4 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]*2;
-}
-
-//------------LDRH-----------------------------
-
-static u32 FASTCALL  OP_LDRH_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-    return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] =(u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] += IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] -= IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//------------STRH-----------------------------
-
-static u32 FASTCALL  OP_STRH_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-	 cpu->R[REG_POS(i,16)] = adr;
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] += IMM_OFF;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] -= IMM_OFF;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//----------------LDRSH--------------------------
-
-static u32 FASTCALL  OP_LDRSH_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] += IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] -= IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//----------------------LDRSB----------------------
-
-static u32 FASTCALL  OP_LDRSB_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] += IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] -= IMM_OFF;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_POS_INDE_P_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRSB_POS_INDE_M_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//--------------MRS--------------------------------
-
-static u32 FASTCALL  OP_MRS_CPSR(armcpu_t *cpu)
-{
-     cpu->R[REG_POS(cpu->instruction,12)] = cpu->CPSR.val;
-     
-     return 1;
-}
-
-static u32 FASTCALL  OP_MRS_SPSR(armcpu_t *cpu)
-{
-     cpu->R[REG_POS(cpu->instruction,12)] = cpu->SPSR.val;
-     
-     return 1;
-}
-
-//--------------MSR--------------------------------
-
-static u32 FASTCALL  OP_MSR_CPSR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 operand = cpu->R[REG_POS(i,0)];
-          
-     if(cpu->CPSR.bits.mode!=USR)
-     {
-          if(BIT16(i))
-          {
-               armcpu_switchMode(cpu, operand & 0x1F);
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF);
-          }
-          if(BIT17(i))
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00);
-          if(BIT18(i))
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000);
-     }
-     if(BIT19(i))
-          cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000);
-          
-     return 1;
-}
-
-static u32 FASTCALL  OP_MSR_SPSR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 operand = cpu->R[REG_POS(i,0)];
-          
-     if(cpu->CPSR.bits.mode!=USR)
-     {
-          if(BIT16(i))
-          {
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0XFF);
-          }
-          if(BIT17(i))
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0XFF00);
-          if(BIT18(i))
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0XFF0000);
-     }
-     if(BIT19(i))
-          cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0XFF000000);
-     
-     return 1;
-}
-
-static u32 FASTCALL  OP_MSR_CPSR_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-     
-     if(cpu->CPSR.bits.mode!=USR)
-     {
-          if(BIT16(i))
-          {
-               armcpu_switchMode(cpu, shift_op & 0x1F);
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0XFF);
-          }
-          if(BIT17(i))
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00);
-          if(BIT18(i))
-               cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000);
-     }
-     if(BIT19(i))
-	  {
-          //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0XFF000000);
-		  cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000);
-	  }
-     
-     return 1;
-}
-
-static u32 FASTCALL  OP_MSR_SPSR_IMM_VAL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     IMM_VALUE;
-
-     if(cpu->CPSR.bits.mode!=USR)
-     {
-          if(BIT16(i))
-          {
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0XFF);
-          }
-          if(BIT17(i))
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00);
-          if(BIT18(i))
-               cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000);
-     }
-     if(BIT19(i))
-          cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0XFF000000);
-     
-     return 1;
-}
-
-//-----------------BRANCH--------------------------
-
-static u32 FASTCALL  OP_BX(armcpu_t *cpu)
-{
-     u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
-     
-     cpu->CPSR.bits.T = BIT0(tmp);
-     cpu->R[15] = tmp & 0xFFFFFFFE;
-     cpu->next_instruction = cpu->R[15];
-     return 3;
-}
-
-static u32 FASTCALL  OP_BLX_REG(armcpu_t *cpu)
-{
-     u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
-     
-     cpu->R[14] = cpu->next_instruction;
-     cpu->CPSR.bits.T = BIT0(tmp);
-     cpu->R[15] = tmp & 0xFFFFFFFE;
-     cpu->next_instruction = cpu->R[15];
-     return 3;
-}
-
-#define SIGNEXTEND_24(i) (((s32)((i)<<8))>>8)
-
-static u32 FASTCALL  OP_B(armcpu_t *cpu)
-{
-	u32 off = SIGNEXTEND_24(cpu->instruction);
-	if(CONDITION(cpu->instruction)==0xF)
-	{
-		cpu->R[14] = cpu->next_instruction;
-		cpu->CPSR.bits.T = 1;
-	}
-	cpu->R[15] += (off<<2);
-	cpu->next_instruction = cpu->R[15];
-
-    return 3;
-}
-
-static u32 FASTCALL  OP_BL(armcpu_t *cpu)
-{
-	u32 off = SIGNEXTEND_24(cpu->instruction);
-	if(CONDITION(cpu->instruction)==0xF)
-	{
-		cpu->CPSR.bits.T = 1;
-		cpu->R[15] += 2;
-	}
-	cpu->R[14] = cpu->next_instruction;
-	cpu->R[15] += (off<<2);
-	cpu->next_instruction = cpu->R[15];
-
-	return 3;
-}
-
-//----------------CLZ-------------------------------
-
-u8 CLZ_TAB[16]=
-{
-     0,                     // 0000
-     1,                     // 0001
-     2, 2,                  // 001X
-     3, 3, 3, 3,            // 01XX
-     4, 4, 4, 4, 4, 4, 4, 4 // 1XXX
-};
-     
-static u32 FASTCALL  OP_CLZ(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 Rm = cpu->R[REG_POS(i,0)];
-     u32 pos;
-     
-     if(Rm==0)
-     {
-          cpu->R[REG_POS(i,12)]=32;
-          return 2;
-     }
-     
-     Rm |= (Rm >>1);
-     Rm |= (Rm >>2);
-     Rm |= (Rm >>4);
-     Rm |= (Rm >>8);
-     Rm |= (Rm >>16);
-     
-     pos =      
-          CLZ_TAB[Rm&0xF] +
-          CLZ_TAB[(Rm>>4)&0xF] +
-          CLZ_TAB[(Rm>>8)&0xF] +
-          CLZ_TAB[(Rm>>12)&0xF] +
-          CLZ_TAB[(Rm>>16)&0xF] +
-          CLZ_TAB[(Rm>>20)&0xF] +
-          CLZ_TAB[(Rm>>24)&0xF] +
-          CLZ_TAB[(Rm>>28)&0xF];
-     
-     cpu->R[REG_POS(i,12)]=32 - pos;
-     
-     return 2;
-}
-
-//--------------------QADD--QSUB------------------------------
-
-static u32 FASTCALL  OP_QADD(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-        u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)];
-
-    LOG("spe add\r\n");
-	if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)],cpu->R[REG_POS(i,0)], res))
-	{
-		cpu->CPSR.bits.Q=1;
-		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
-		return 2;
-	}
-	cpu->R[REG_POS(i,12)]=res;
-	if(REG_POS(i,12)==15)
-	{
-         cpu->R[15] &= 0XFFFFFFFC;
-	     cpu->next_instruction = cpu->R[15];
-	     return 3;
-    }
-    return 2;
-}
-
-static u32 FASTCALL  OP_QSUB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-        u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)];
-
-    LOG("spe add\r\n");
-	if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,16)], res))
-	{
-		cpu->CPSR.bits.Q=1;
-		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
-		return 2;
-	}
-	cpu->R[REG_POS(i,12)]=res;
-	if(REG_POS(i,12)==15)
-	{
-         cpu->R[15] &= 0XFFFFFFFC;
-	     cpu->next_instruction = cpu->R[15];
-	     return 3;
-    }
-    return 2;
-}
-
-static u32 FASTCALL  OP_QDADD(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-        u32 mul = cpu->R[REG_POS(i,16)]<<1;
-        u32 res;
-
-
-    LOG("spe add\r\n");
-	if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
-	{
-		cpu->CPSR.bits.Q=1;
-		mul = 0x80000000-BIT31(mul);
-	}
-
-	res = mul + cpu->R[REG_POS(i,0)];
-	if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,0)],mul, res))
-	{
-		cpu->CPSR.bits.Q=1;
-		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
-		return 2;
-	}
-	cpu->R[REG_POS(i,12)]=res;
-	if(REG_POS(i,12)==15)
-	{
-         cpu->R[15] &= 0XFFFFFFFC;
-	     cpu->next_instruction = cpu->R[15];
-	     return 3;
-    }
-    return 2;
-}
-
-static u32 FASTCALL  OP_QDSUB(armcpu_t *cpu)
-{
-    u32 i = cpu->instruction;
-        u32 mul = cpu->R[REG_POS(i,16)]<<1;
-        u32 res;
-
-
-    LOG("spe add\r\n");
-	if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
-	{
-		cpu->CPSR.bits.Q=1;
-		mul = 0x80000000-BIT31(mul);
-	}
-
-	res = cpu->R[REG_POS(i,0)] - mul;
-	if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], mul, res))
-	{
-		cpu->CPSR.bits.Q=1;
-		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
-		return 2;
-	}
-	cpu->R[REG_POS(i,12)]=res;
-	if(REG_POS(i,12)==15)
-	{
-         cpu->R[15] &= 0XFFFFFFFC;
-	     cpu->next_instruction = cpu->R[15];
-	     return 3;
-    }
-    return 2;
-}
-
-//-----------------SMUL-------------------------------
-
-#define HWORD(i)   ((s32)(((s32)(i))>>16))
-#define LWORD(i)   (s32)(((s32)((i)<<16))>>16)
-
-static u32 FASTCALL  OP_SMUL_B_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     
-     cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMUL_B_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-
-     cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMUL_T_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-
-     cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMUL_T_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-
-     cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-
-     return 2;
-}
-
-//-----------SMLA----------------------------
-
-static u32 FASTCALL  OP_SMLA_B_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
-     u32 a = cpu->R[REG_POS(i,12)];
-
-     //LOG("SMLABB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
-     cpu->R[REG_POS(i,16)] = tmp + a;
-     
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLA_B_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-     u32 a = cpu->R[REG_POS(i,12)];
-
-     //LOG("SMLABT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
-     cpu->R[REG_POS(i,16)] = tmp + a;
-     
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLA_T_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
-     u32 a = cpu->R[REG_POS(i,12)];
-
-     //LOG("SMLATB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
-     cpu->R[REG_POS(i,16)] = tmp + a;
-     
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLA_T_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-     u32 a = cpu->R[REG_POS(i,12)];
-
-     //LOG("SMLATT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
-     cpu->R[REG_POS(i,16)] = tmp + a;
-     
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-//--------------SMLAL---------------------------------------
-
-static u32 FASTCALL  OP_SMLAL_B_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
-     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
-
-     LOG("SMLALBB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(u32) res);
-
-     cpu->R[REG_POS(i,12)] = (u32) res;
-     cpu->R[REG_POS(i,16)] += (res + ((tmp<0)*0xFFFFFFFF));
-     
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLAL_B_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
-     
-     LOG("SMLALBT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
-
-     cpu->R[REG_POS(i,12)] = (u32) res;
-     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLAL_T_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* (s64)LWORD(cpu->R[REG_POS(i,8)]));
-     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
-     
-     LOG("SMLALTB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
-
-     cpu->R[REG_POS(i,12)] = (u32) res;
-     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLAL_T_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
-     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
-     
-     LOG("SMLALTT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
-     
-     cpu->R[REG_POS(i,12)] = (u32) res;
-     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
-
-     return 2;
-}
-
-//--------------SMULW--------------------
-
-static u32 FASTCALL  OP_SMULW_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
-     
-     //LOG("SMULWB %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF);
-     
-     cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF);
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMULW_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
-     
-     //LOG("SMULWT %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF));
-     
-     cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF);
-
-     return 2;
-}
-
-//--------------SMLAW-------------------
-static u32 FASTCALL  OP_SMLAW_B(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
-     u32 a = cpu->R[REG_POS(i,12)];
-     
-     //LOG("SMLAWB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a);
-     
-     tmp = (tmp>>16);
-     
-     cpu->R[REG_POS(i,16)] = tmp + a;
-          
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-static u32 FASTCALL  OP_SMLAW_T(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
-     u32 a = cpu->R[REG_POS(i,12)];
-     
-     //LOG("SMLAWT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a);
-
-     tmp = ((tmp>>16)&0xFFFFFFFF);
-     cpu->R[REG_POS(i,16)] = tmp + a;
-
-     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
-          cpu->CPSR.bits.Q = 1;
-
-     return 2;
-}
-
-//------------LDR---------------------------
-
-static u32 FASTCALL  OP_LDR_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;    
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//------------------------------------------------------------
-static u32 FASTCALL  OP_LDR_P_IMM_OFF_POSTIND2(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 val = READ32(cpu->mem_if->data, adr);
-     u32 old;
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     old = armcpu_switchMode(cpu, USR);
-     cpu->R[REG_POS(i,12)] = val;
-     armcpu_switchMode(cpu, old);
-     
-     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//------------------------------------------------------------
-
-static u32 FASTCALL  OP_LDR_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr - shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr - shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr - shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-	 cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr + shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ32(cpu->mem_if->data, adr);
-     
-     if(adr&3)
-         val = ROR(val, 8*(adr&3));
-     
-     if(REG_POS(i,12)==15)
-     {
-          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
-          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
-	      cpu->next_instruction = cpu->R[15];
-          cpu->R[REG_POS(i,16)] = adr - shift_op;
-          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     }
-     
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//-----------------LDRB-------------------------------------------
-
-static u32 FASTCALL  OP_LDRB_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     u32 val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     u32 val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     u32 val = READ8(cpu->mem_if->data, adr);
-
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     u32 val = READ8(cpu->mem_if->data, adr);
-
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-
-	 cpu->R[REG_POS(i,16)] = adr;
-     cpu->R[REG_POS(i,12)] = val;
-     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,16)] = adr;
-	 cpu->R[REG_POS(i,12)] = val;
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     u32 val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr + shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-	 cpu->R[REG_POS(i,16)] = adr - shift_op;
-     cpu->R[REG_POS(i,12)] = val;     
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//----------------------STR--------------------------------
-
-static u32 FASTCALL  OP_STR_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-
-//	 execute = false;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//-----------------------STRB-------------------------------------
-
-static u32 FASTCALL  OP_STRB_P_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
-     WRITE8(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] + shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)] - shift_op;
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr;
-     u32 shift_op;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//-----------------------LDRBT-------------------------------------
-
-static u32 FASTCALL  OP_LDRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;     
-     u32 i;
-     u32 adr;
-     u32 val;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     oldmode = armcpu_switchMode(cpu, SYS);
-     
-     i = cpu->instruction;
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     
-     armcpu_switchMode(cpu, oldmode);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     oldmode = armcpu_switchMode(cpu, SYS);
-
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_M_IMM_OFF_POSTIND\n");
-     
-     
-     i = cpu->instruction;
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     
-     armcpu_switchMode(cpu, oldmode);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_P_LSL_IMM_OFF_POSTIND");  
-          
-
-     i = cpu->instruction;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_M_LSL_IMM_OFF_POSTIND");  
-          
-
-     i = cpu->instruction;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_P_LSR_IMM_OFF_POSTIND");  
-          
-
-     i = cpu->instruction;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-     
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_M_LSR_IMM_OFF_POSTIND");
-          
-
-     i = cpu->instruction;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_P_ASR_IMM_OFF_POSTIND");
-          
-
-     i = cpu->instruction;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_M_ASR_IMM_OFF_POSTIND");
-          
-
-     i = cpu->instruction;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_P_ROR_IMM_OFF_POSTIND");
-          
-
-     i = cpu->instruction;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_LDRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 val;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDRBT_M_ROR_IMM_OFF_POSTIND");
-          
-
-     i = cpu->instruction;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     val = READ8(cpu->mem_if->data, adr);
-     cpu->R[REG_POS(i,12)] = val;
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//----------------------STRBT----------------------------
-
-static u32 FASTCALL  OP_STRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     LSL_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     LSR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     ASR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr + shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL  OP_STRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
-{
-     u32 oldmode;
-     u32 i;
-     u32 adr;
-     u32 shift_op;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     oldmode = armcpu_switchMode(cpu, SYS);
-          
-
-     i = cpu->instruction;
-     ROR_IMM; 
-     adr = cpu->R[REG_POS(i,16)];
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
-     cpu->R[REG_POS(i,16)] = adr - shift_op;
-     
-     armcpu_switchMode(cpu, oldmode);
-
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-//---------------------LDM-----------------------------
-
-#define OP_L_IA(reg, adr)  if(BIT##reg(i))\
-     {\
-          registres[reg] = READ32(cpu->mem_if->data, start);\
-          c += waitState[(start>>24)&0xF];\
-          adr += 4;\
-     }
-
-#define OP_L_IB(reg, adr)  if(BIT##reg(i))\
-     {\
-          adr += 4;\
-          registres[reg] = READ32(cpu->mem_if->data, start);\
-          c += waitState[(start>>24)&0xF];\
-     }
-
-#define OP_L_DA(reg, adr)  if(BIT##reg(i))\
-     {\
-          registres[reg] = READ32(cpu->mem_if->data, start);\
-          c += waitState[(start>>24)&0xF];\
-          adr -= 4;\
-     }
-
-#define OP_L_DB(reg, adr)  if(BIT##reg(i))\
-     {\
-          adr -= 4;\
-          registres[reg] = READ32(cpu->mem_if->data, start);\
-          c += waitState[(start>>24)&0xF];\
-     }
-
-static u32 FASTCALL  OP_LDMIA(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     OP_L_IA(0, start);
-     OP_L_IA(1, start);
-     OP_L_IA(2, start);
-     OP_L_IA(3, start);
-     OP_L_IA(4, start);
-     OP_L_IA(5, start);
-     OP_L_IA(6, start);
-     OP_L_IA(7, start);
-     OP_L_IA(8, start);
-     OP_L_IA(9, start);
-     OP_L_IA(10, start);
-     OP_L_IA(11, start);
-     OP_L_IA(12, start);
-     OP_L_IA(13, start);
-     OP_L_IA(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-          //start += 4;
-	      cpu->next_instruction = registres[15];
-          c += waitState[(start>>24)&0xF];
-     }
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     OP_L_IB(0, start);
-     OP_L_IB(1, start);
-     OP_L_IB(2, start);
-     OP_L_IB(3, start);
-     OP_L_IB(4, start);
-     OP_L_IB(5, start);
-     OP_L_IB(6, start);
-     OP_L_IB(7, start);
-     OP_L_IB(8, start);
-     OP_L_IB(9, start);
-     OP_L_IB(10, start);
-     OP_L_IB(11, start);
-     OP_L_IB(12, start);
-     OP_L_IB(13, start);
-     OP_L_IB(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          start += 4;
-          c += waitState[(start>>24)&0xF];
-          tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-	      cpu->next_instruction = registres[15];
-          c += 2 + (c==0);
-     }
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDA(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-          c += waitState[(start>>24)&0xF];
-          start -= 4;
-	      cpu->next_instruction = registres[15];
-     }
-
-     OP_L_DA(14, start);
-     OP_L_DA(13, start);
-     OP_L_DA(12, start);
-     OP_L_DA(11, start);
-     OP_L_DA(10, start);
-     OP_L_DA(9, start);
-     OP_L_DA(8, start);
-     OP_L_DA(7, start);
-     OP_L_DA(6, start);
-     OP_L_DA(5, start);
-     OP_L_DA(4, start);
-     OP_L_DA(3, start);
-     OP_L_DA(2, start);
-     OP_L_DA(1, start);
-     OP_L_DA(0, start);
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          start -= 4;
-          tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-	      cpu->next_instruction = registres[15];
-          c += waitState[(start>>24)&0xF];
-     }
-
-     OP_L_DB(14, start);
-     OP_L_DB(13, start);
-     OP_L_DB(12, start);
-     OP_L_DB(11, start);
-     OP_L_DB(10, start);
-     OP_L_DB(9, start);
-     OP_L_DB(8, start);
-     OP_L_DB(7, start);
-     OP_L_DB(6, start);
-     OP_L_DB(5, start);
-     OP_L_DB(4, start);
-     OP_L_DB(3, start);
-     OP_L_DB(2, start);
-     OP_L_DB(1, start);
-     OP_L_DB(0, start);
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIA_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-	 u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     OP_L_IA(0, start);
-     OP_L_IA(1, start);
-     OP_L_IA(2, start);
-     OP_L_IA(3, start);
-     OP_L_IA(4, start);
-     OP_L_IA(5, start);
-     OP_L_IA(6, start);
-     OP_L_IA(7, start);
-     OP_L_IA(8, start);
-     OP_L_IA(9, start);
-     OP_L_IA(10, start);
-     OP_L_IA(11, start);
-     OP_L_IA(12, start);
-     OP_L_IA(13, start);
-     OP_L_IA(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-          c += waitState[(start>>24)&0xF];
-          start += 4;
-	      cpu->next_instruction = registres[15];
-     }
-
-	if(i & (1 << REG_POS(i,16))) {
-		if(i & bitList)
-			cpu->R[REG_POS(i,16)] = start;
-	}
-	else
-		cpu->R[REG_POS(i,16)] = start;
-
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIB_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0;
-     u32 start = cpu->R[REG_POS(i,16)];
-	 u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
-     
-     u32 * registres = cpu->R;
-     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-
-	 OP_L_IB(0, start);
-     OP_L_IB(1, start);
-     OP_L_IB(2, start);
-     OP_L_IB(3, start);
-     OP_L_IB(4, start);
-     OP_L_IB(5, start);
-     OP_L_IB(6, start);
-     OP_L_IB(7, start);
-     OP_L_IB(8, start);
-     OP_L_IB(9, start);
-     OP_L_IB(10, start);
-     OP_L_IB(11, start);
-     OP_L_IB(12, start);
-     OP_L_IB(13, start);
-     OP_L_IB(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          start += 4;
-          c += waitState[(start>>24)&0xF];
-          tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR.bits.T = BIT0(tmp);
-	      cpu->next_instruction = registres[15];
-          c += 2 + (c==0);
-     }
-
-	if(i & (1 << REG_POS(i,16))) {
-		if(i & bitList)
-			cpu->R[REG_POS(i,16)] = start;
-	}
-	else
-		cpu->R[REG_POS(i,16)] = start;
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDA_W(armcpu_t *cpu)
-{
-	u32 i = cpu->instruction, c = 0;
-	u32 start = cpu->R[REG_POS(i,16)];
-	u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
-
-	u32 * registres = cpu->R;
-	u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-
-	if(BIT15(i))
-	{
-		u32 tmp = READ32(cpu->mem_if->data, start);
-		registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-		cpu->CPSR.bits.T = BIT0(tmp);
-		c += waitState[(start>>24)&0xF];
-		start -= 4;
-		cpu->next_instruction = registres[15];
-	}
-
-	OP_L_DA(14, start);
-	OP_L_DA(13, start);
-	OP_L_DA(12, start);
-	OP_L_DA(11, start);
-	OP_L_DA(10, start);
-	OP_L_DA(9, start);
-	OP_L_DA(8, start);
-	OP_L_DA(7, start);
-	OP_L_DA(6, start);
-	OP_L_DA(5, start);
-	OP_L_DA(4, start);
-	OP_L_DA(3, start);
-	OP_L_DA(2, start);
-	OP_L_DA(1, start);
-	OP_L_DA(0, start);
-
-	if(i & (1 << REG_POS(i,16))) {
-		if(i & bitList)
-			cpu->R[REG_POS(i,16)] = start;
-	}
-	else
-		cpu->R[REG_POS(i,16)] = start;
-	
-	return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDB_W(armcpu_t *cpu)
-{
-	u32 i = cpu->instruction, c = 0;
-	u32 start = cpu->R[REG_POS(i,16)];
-	u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
-	u32 * registres = cpu->R;
-	u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-
-	if(BIT15(i))
-	{
-		u32 tmp;
-		start -= 4;
-		tmp = READ32(cpu->mem_if->data, start);
-		registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-		cpu->CPSR.bits.T = BIT0(tmp);
-		cpu->next_instruction = registres[15];
-		c += waitState[(start>>24)&0xF];
-	}
-
-	OP_L_DB(14, start);
-	OP_L_DB(13, start);
-	OP_L_DB(12, start);
-	OP_L_DB(11, start);
-	OP_L_DB(10, start);
-	OP_L_DB(9, start);
-	OP_L_DB(8, start);
-	OP_L_DB(7, start);
-	OP_L_DB(6, start);
-	OP_L_DB(5, start);
-	OP_L_DB(4, start);
-	OP_L_DB(3, start);
-	OP_L_DB(2, start);
-	OP_L_DB(1, start);
-	OP_L_DB(0, start);
-
-	if(i & (1 << REG_POS(i,16))) {
-		if(i & bitList)
-			cpu->R[REG_POS(i,16)] = start;
-	}
-	else
-		cpu->R[REG_POS(i,16)] = start;
-
-	return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIA2(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 oldmode;
-     
-     u32 c = 0;
-     
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 1;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-               
-     OP_L_IA(0, start);
-     OP_L_IA(1, start);
-     OP_L_IA(2, start);
-     OP_L_IA(3, start);
-     OP_L_IA(4, start);
-     OP_L_IA(5, start);
-     OP_L_IA(6, start);
-     OP_L_IA(7, start);
-     OP_L_IA(8, start);
-     OP_L_IA(9, start);
-     OP_L_IA(10, start);
-     OP_L_IA(11, start);
-     OP_L_IA(12, start);
-     OP_L_IA(13, start);
-     OP_L_IA(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          Status_Reg SPSR;
-          cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-          //start += 4;
-	      cpu->next_instruction = cpu->R[15];
-          c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-     }
-     else
-     {
-         armcpu_switchMode(cpu, oldmode);
-     }
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIB2(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 oldmode;
-     u32 c = 0;
-     
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDMIB2");
-
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-               
-     OP_L_IB(0, start);
-     OP_L_IB(1, start);
-     OP_L_IB(2, start);
-     OP_L_IB(3, start);
-     OP_L_IB(4, start);
-     OP_L_IB(5, start);
-     OP_L_IB(6, start);
-     OP_L_IB(7, start);
-     OP_L_IB(8, start);
-     OP_L_IB(9, start);
-     OP_L_IB(10, start);
-     OP_L_IB(11, start);
-     OP_L_IB(12, start);
-     OP_L_IB(13, start);
-     OP_L_IB(14, start);
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          Status_Reg SPSR;
-          start += 4;
-          tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-	      cpu->next_instruction = registres[15];
-          c += waitState[(start>>24)&0xF];
-     }
-     else
-     {
-         armcpu_switchMode(cpu, oldmode);
-     }
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDA2(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-          
-     u32 oldmode;
-     u32 c = 0;
-     u32 * registres;
-     u32 * waitState;
-     
-     u32 start = cpu->R[REG_POS(i,16)];
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_LDMDA2");
-
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-     
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR = cpu->SPSR;
-          c += waitState[(start>>24)&0xF];
-          start -= 4;
-	      cpu->next_instruction = registres[15];
-     }
- 
-     OP_L_DA(14, start);
-     OP_L_DA(13, start);
-     OP_L_DA(12, start);
-     OP_L_DA(11, start);
-     OP_L_DA(10, start);
-     OP_L_DA(9, start);
-     OP_L_DA(8, start);
-     OP_L_DA(7, start);
-     OP_L_DA(6, start);
-     OP_L_DA(5, start);
-     OP_L_DA(4, start);
-     OP_L_DA(3, start);
-     OP_L_DA(2, start);
-     OP_L_DA(1, start);
-     OP_L_DA(0, start);
-     
-     if(BIT15(i)==0)
-     {
-          armcpu_switchMode(cpu, oldmode);
-     }
-     else
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-     }
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDB2(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-          
-     u32 oldmode;
-     u32 c = 0;
-     u32 * registres;
-     u32 * waitState;
-     
-     u32 start = cpu->R[REG_POS(i,16)];
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          start -= 4;
-          tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR = cpu->SPSR;
-	      cpu->next_instruction = registres[15];
-          c += waitState[(start>>24)&0xF];
-     }
-
-     OP_L_DB(14, start);
-     OP_L_DB(13, start);
-     OP_L_DB(12, start);
-     OP_L_DB(11, start);
-     OP_L_DB(10, start);
-     OP_L_DB(9, start);
-     OP_L_DB(8, start);
-     OP_L_DB(7, start);
-     OP_L_DB(6, start);
-     OP_L_DB(5, start);
-     OP_L_DB(4, start);
-     OP_L_DB(3, start);
-     OP_L_DB(2, start);
-     OP_L_DB(1, start);
-     OP_L_DB(0, start);
-     
-     if(BIT15(i)==0)
-     {
-          armcpu_switchMode(cpu, oldmode);
-     }
-     else
-     {
-          Status_Reg SPSR = cpu->SPSR;
-          armcpu_switchMode(cpu, SPSR.bits.mode);
-          cpu->CPSR=SPSR;
-     }
-     
-     return 2 + c;
-}
-
-static u32 FASTCALL  OP_LDMIA2_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-          
-     u32 oldmode;
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-     u32 tmp;
-     Status_Reg SPSR;
-//     execute = FALSE;     
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     OP_L_IA(0, start);
-     OP_L_IA(1, start);
-     OP_L_IA(2, start);
-     OP_L_IA(3, start);
-     OP_L_IA(4, start);
-     OP_L_IA(5, start);
-     OP_L_IA(6, start);
-     OP_L_IA(7, start);
-     OP_L_IA(8, start);
-     OP_L_IA(9, start);
-     OP_L_IA(10, start);
-     OP_L_IA(11, start);
-     OP_L_IA(12, start);
-     OP_L_IA(13, start);
-     OP_L_IA(14, start);
-     
-     if(BIT15(i)==0)
-     {
-          registres[REG_POS(i,16)] = start;
-          armcpu_switchMode(cpu, oldmode);
-          return c + 2;
-     }
-
-     registres[REG_POS(i,16)] = start + 4;
-     tmp = READ32(cpu->mem_if->data, start);
-     registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-     SPSR = cpu->SPSR;
-     armcpu_switchMode(cpu, SPSR.bits.mode);
-     cpu->CPSR=SPSR;
-     cpu->next_instruction = registres[15];
-     c += waitState[(start>>24)&0xF];
-
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMIB2_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-          
-     u32 oldmode;
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-     u32 tmp;
-     Status_Reg SPSR;
-
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-
-     OP_L_IB(0, start);
-     OP_L_IB(1, start);
-     OP_L_IB(2, start);
-     OP_L_IB(3, start);
-     OP_L_IB(4, start);
-     OP_L_IB(5, start);
-     OP_L_IB(6, start);
-     OP_L_IB(7, start);
-     OP_L_IB(8, start);
-     OP_L_IB(9, start);
-     OP_L_IB(10, start);
-     OP_L_IB(11, start);
-     OP_L_IB(12, start);
-     OP_L_IB(13, start);
-     OP_L_IB(14, start);
-     
-     if(BIT15(i)==0)
-     {
-          armcpu_switchMode(cpu, oldmode);
-          registres[REG_POS(i,16)] = start;
-          
-          return c + 2;
-     }
-
-     registres[REG_POS(i,16)] = start + 4;
-     tmp = READ32(cpu->mem_if->data, start + 4);
-     registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-     cpu->CPSR = cpu->SPSR;
-     cpu->next_instruction = registres[15];
-     SPSR = cpu->SPSR;
-     armcpu_switchMode(cpu, SPSR.bits.mode);
-     cpu->CPSR=SPSR;
-     c += waitState[(start>>24)&0xF];
-     
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDA2_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-          
-     u32 oldmode;
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-     Status_Reg SPSR;
-//     execute = FALSE;     
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp = READ32(cpu->mem_if->data, start);
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          c += waitState[(start>>24)&0xF];
-          start -= 4;
-          cpu->next_instruction = registres[15];
-     }
-
-     OP_L_DA(14, start);
-     OP_L_DA(13, start);
-     OP_L_DA(12, start);
-     OP_L_DA(11, start);
-     OP_L_DA(10, start);
-     OP_L_DA(9, start);
-     OP_L_DA(8, start);
-     OP_L_DA(7, start);
-     OP_L_DA(6, start);
-     OP_L_DA(5, start);
-     OP_L_DA(4, start);
-     OP_L_DA(3, start);
-     OP_L_DA(2, start);
-     OP_L_DA(1, start);
-     OP_L_DA(0, start);
-     
-     registres[REG_POS(i,16)] = start;
-     
-     if(BIT15(i)==0)
-     {
-          armcpu_switchMode(cpu, oldmode);
-          return c + 2;
-     }
-
-     SPSR = cpu->SPSR;
-     armcpu_switchMode(cpu, SPSR.bits.mode);
-     cpu->CPSR=SPSR;
-     return c + 2;
-}
-
-static u32 FASTCALL  OP_LDMDB2_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 c = 0;
-          
-     u32 oldmode;
-     u32 start = cpu->R[REG_POS(i,16)];
-     u32 * registres;
-     u32 * waitState;
-     Status_Reg SPSR;
-//     execute = FALSE;     
-     if(BIT15(i)==0)
-     {  
-          if(cpu->CPSR.bits.mode==USR)
-               return 2;
-          oldmode = armcpu_switchMode(cpu, SYS);
-     }
-
-     registres = cpu->R;
-     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
-     
-     if(BIT15(i))
-     {
-          u32 tmp;
-          start -= 4;
-          tmp = READ32(cpu->mem_if->data, start);
-          c += waitState[(start>>24)&0xF];
-          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
-          cpu->CPSR = cpu->SPSR;
-          cpu->next_instruction = registres[15];
-     }
-
-     OP_L_DB(14, start);
-     OP_L_DB(13, start);
-     OP_L_DB(12, start);
-     OP_L_DB(11, start);
-     OP_L_DB(10, start);
-     OP_L_DB(9, start);
-     OP_L_DB(8, start);
-     OP_L_DB(7, start);
-     OP_L_DB(6, start);
-     OP_L_DB(5, start);
-     OP_L_DB(4, start);
-     OP_L_DB(3, start);
-     OP_L_DB(2, start);
-     OP_L_DB(1, start);
-     OP_L_DB(0, start);
-     
-     registres[REG_POS(i,16)] = start;
-     
-     if(BIT15(i)==0)
-     {
-          armcpu_switchMode(cpu, oldmode);
-          return c + 2;
-     }
-
-     SPSR = cpu->SPSR;
-     armcpu_switchMode(cpu, SPSR.bits.mode);
-     cpu->CPSR=SPSR;
-     return c + 2;
-}
-
-//------------------------------STM----------------------------------
-
-static u32 FASTCALL  OP_STMIA(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start += 4;
-          }
-     }
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               start += 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDA(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start -= 4;
-          }
-     }     
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               start -= 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }     
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIA_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start += 4;
-          }
-     }
-     
-     cpu->R[REG_POS(i,16)] = start;
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIB_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               start += 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }
-     cpu->R[REG_POS(i,16)] = start;
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDA_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start -= 4;
-          }
-     }     
-     
-     cpu->R[REG_POS(i,16)] = start;
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDB_W(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction, c = 0, b;
-     u32 start = cpu->R[REG_POS(i,16)];
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               start -= 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }     
-     
-     cpu->R[REG_POS(i,16)] = start;
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIA2(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     i = cpu->instruction;
-     c = 0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMIA2");
-
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start += 4;
-          }
-     }
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIB2(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     i = cpu->instruction;
-     c = 0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-     
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMIB2");
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               start += 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDA2(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-
-     i = cpu->instruction;
-     c = 0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);     
-     
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMDA2");  
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start -= 4;
-          }
-     }     
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDB2(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     i = cpu->instruction;
-     c=0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               start -= 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }     
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIA2_W(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     
-     i = cpu->instruction;
-     c=0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-     
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMIA2_W");
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start += 4;
-          }
-     }
-     
-     cpu->R[REG_POS(i,16)] = start;
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMIB2_W(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-     i = cpu->instruction;
-     c=0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, b))
-          {
-               start += 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }
-     armcpu_switchMode(cpu, oldmode);
-     cpu->R[REG_POS(i,16)] = start;
-     
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDA2_W(armcpu_t *cpu)
-{
-     u32 i, c, b;
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     i = cpu->instruction;
-     c = 0;
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMDA2_W");
-     
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-               start -= 4;
-          }
-     }     
-     
-     cpu->R[REG_POS(i,16)] = start;
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-static u32 FASTCALL  OP_STMDB2_W(armcpu_t *cpu)
-{
-     u32 i, c, b;     
-     u32 start;
-     u32 oldmode;
-
-     if(cpu->CPSR.bits.mode==USR)
-          return 2;
-          
-     i = cpu->instruction;
-     c = 0;
-     
-     start = cpu->R[REG_POS(i,16)];
-     oldmode = armcpu_switchMode(cpu, SYS);
-
-     //execute = FALSE;
-	 LOG("Untested opcode: OP_STMDB2_W");   
-
-     for(b=0; b<16; ++b)
-     {
-          if(BIT_N(i, 15-b))
-          {
-               start -= 4;
-               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
-          }
-     }     
-     
-     cpu->R[REG_POS(i,16)] = start;
-     
-     armcpu_switchMode(cpu, oldmode);
-     return c + 1;
-}
-
-/*
- *
- * The Enhanced DSP Extension LDRD and STRD instructions.
- *
- */
-static u32 FASTCALL
-OP_LDRD_STRD_POST_INDEX( armcpu_t *cpu) {
-  u32 i = cpu->instruction;
-  u32 Rd_num = REG_POS( i, 12);
-  u32 addr = cpu->R[REG_POS(i,16)];
-  u32 index;
-
-  /* I bit - immediate or register */
-  if ( BIT22(i))
-    index = IMM_OFF;
-  else
-    index = cpu->R[REG_POS(i,0)];
-
-  /* U bit - add or subtract */
-  if ( BIT23(i))
-    cpu->R[REG_POS(i,16)] += index;
-  else
-    cpu->R[REG_POS(i,16)] -= index;
-
-  if ( !(Rd_num & 0x1)) {
-    /* Store/Load */
-    if ( BIT5(i)) {
-      WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]);
-      WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]);
-    }
-    else {
-      cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr);
-      cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4);
-    }
-  }
-
-  return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2);
-}
-
-static u32 FASTCALL
-OP_LDRD_STRD_OFFSET_PRE_INDEX( armcpu_t *cpu) {
-  u32 i = cpu->instruction;
-  u32 Rd_num = REG_POS( i, 12);
-  u32 addr = cpu->R[REG_POS(i,16)];
-  u32 index;
-
-  /* I bit - immediate or register */
-  if ( BIT22(i))
-    index = IMM_OFF;
-  else
-    index = cpu->R[REG_POS(i,0)];
-
-  /* U bit - add or subtract */
-  if ( BIT23(i)) {
-    addr += index;
-
-    /* W bit - writeback */
-    if ( BIT21(i))
-      cpu->R[REG_POS(i,16)] = addr;
-  }
-  else {
-    addr -= index;
-
-    /* W bit - writeback */
-    if ( BIT21(i))
-      cpu->R[REG_POS(i,16)] = addr;
-  }
-
-  if ( !(Rd_num & 0x1)) {
-    /* Store/Load */
-    if ( BIT5(i)) {
-      WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]);
-      WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]);
-    }
-    else {
-      cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr);
-      cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4);
-    }
-  }
-
-  return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2);
-}
-
-
-
-//---------------------STC----------------------------------
-
-static u32 FASTCALL  OP_STC_P_IMM_OFF(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_M_IMM_OFF(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_P_PREIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_M_PREIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_P_POSTIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_M_POSTIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_STC_OPTION(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-//---------------------LDC----------------------------------
-
-static u32 FASTCALL  OP_LDC_P_IMM_OFF(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_M_IMM_OFF(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_P_PREIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_M_PREIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_P_POSTIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_M_POSTIND(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-static u32 FASTCALL  OP_LDC_OPTION(armcpu_t *cpu)
-{
-     {
-		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
-          return 2;
-     }
-}
-
-//----------------MCR-----------------------
-
-static u32 FASTCALL  OP_MCR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 cpnum = REG_POS(i, 8);
-     
-     if(!cpu->coproc[cpnum])
-     {
-          execute = FALSE;
-          return 2;
-     }
-     
-	  armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
-			  //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
-     return 2;
-}
-
-//----------------MRC-----------------------
-
-static u32 FASTCALL  OP_MRC(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 cpnum = REG_POS(i, 8);
-     
-     if(!cpu->coproc[cpnum])
-     {
-          execute = FALSE;
-          return 2;
-     }
-     
-	  armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
-     //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
-     return 4;
-}
-
-//--------------SWI-------------------------------
-static u32 FASTCALL  OP_SWI(armcpu_t *cpu)
-{
-     if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
-     {
-        /* TODO (#1#): translocated SWI vectors */
-        /* we use an irq thats not in the irq tab, as
-           it was replaced duie to a changed intVector */
-        Status_Reg tmp = cpu->CPSR;
-        armcpu_switchMode(cpu, SVC);            /* enter svc mode */
-        cpu->R[14] = cpu->R[15] - 4;            /* jump to swi Vector */
-        cpu->SPSR = tmp;                        /* save old CPSR as new SPSR */
-        cpu->CPSR.bits.T = 0;                   /* handle as ARM32 code */
-        cpu->CPSR.bits.I = cpu->SPSR.bits.I;    /* keep int disable flag */
-        cpu->R[15] = cpu->intVector + 0x08;
-        cpu->next_instruction = cpu->R[15];
-        return 4;
-     }
-     else
-     {
-        u32 swinum = (cpu->instruction>>16)&0x1F;
-        return cpu->swi_tab[swinum](cpu) + 3;
-     }
-}
-
-//----------------BKPT-------------------------
-static u32 FASTCALL OP_BKPT(armcpu_t *cpu)
-{
-     execute = FALSE;
-     return 4;
-}
-
-//----------------CDP-----------------------
-
-static u32 FASTCALL  OP_CDP(armcpu_t *cpu)
-{
-     execute = FALSE;
-     return 4;
-}
-
-#define TYPE_RETOUR u32
-#define PARAMETRES  armcpu_t *cpu
-#define CALLTYPE    FASTCALL 
-#define NOM_TAB     arm_instructions_set
-
-#include "instruction_tabdef.inc"
diff --git a/src/xsf/desmume/arm_instructions.cc b/src/xsf/desmume/arm_instructions.cc
new file mode 100644
index 000000000000..b246a974c947
--- /dev/null
+++ b/src/xsf/desmume/arm_instructions.cc
@@ -0,0 +1,7857 @@
+/*  Copyright (C) 2006 yopyop
+    Copyright (C) 2006 shash
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+	Copyright (C) 2006-2007 shash
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "cp15.h"
+#include "debug.h"
+#include "MMU.h"
+
+
+// Use this macros for reading/writing, so the GDB stub isn't broken
+#ifdef GDB_STUB
+	#define READ32(a,b)		cpu->mem_if->read32(a,b)
+	#define WRITE32(a,b,c)	cpu->mem_if->write32(a,b,c)
+	#define READ16(a,b)		cpu->mem_if->read16(a,b)
+	#define WRITE16(a,b,c)	cpu->mem_if->write16(a,b,c)
+	#define READ8(a,b)		cpu->mem_if->read8(a,b)
+	#define WRITE8(a,b,c)	cpu->mem_if->write8(a,b,c)
+#else
+	#define READ32(a,b)		MMU_read32(cpu->proc_ID, b)
+	#define WRITE32(a,b,c)	MMU_write32(cpu->proc_ID,b,c)
+	#define READ16(a,b)		MMU_read16(cpu->proc_ID, b)
+	#define WRITE16(a,b,c)	MMU_write16(cpu->proc_ID,b,c)
+	#define READ8(a,b)		MMU_read8(cpu->proc_ID, b)
+	#define WRITE8(a,b,c)	MMU_write8(cpu->proc_ID,b,c)
+#endif
+
+
+
+#define LSL_IMM shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);
+
+#define S_LSL_IMM u32 shift_op = ((i>>7)&0x1F);\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+          shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+     {\
+         c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\
+         shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);\
+     }
+
+#define LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     if(shift_op>=32)\
+             shift_op=0;\
+     else\
+             shift_op=cpu->R[REG_POS(i,0)]<<shift_op;
+
+#define S_LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+             shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+             if(shift_op<32)\
+             {\
+                  c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\
+                  shift_op = cpu->R[REG_POS(i,0)]<<shift_op;\
+             }\
+             else\
+                 if(shift_op==32)\
+                 {\
+                      shift_op = 0;\
+                      c = BIT0(cpu->R[REG_POS(i,0)]);\
+                 }\
+                 else\
+                 {\
+                      shift_op = 0;\
+                      c = 0;\
+                 }
+
+#define LSR_IMM      shift_op = ((i>>7)&0x1F);\
+     if(shift_op!=0)\
+            shift_op = cpu->R[REG_POS(i,0)]>>shift_op;
+
+#define S_LSR_IMM      u32 shift_op = ((i>>7)&0x1F);\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+     {\
+          c = BIT31(cpu->R[REG_POS(i,0)]);\
+     }\
+     else\
+     {\
+         c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+         shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\
+     }
+
+#define LSR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     if(shift_op>=32)\
+             shift_op = 0;\
+     else\
+             shift_op = cpu->R[REG_POS(i,0)]>>shift_op;
+
+#define S_LSR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+     {\
+             shift_op = cpu->R[REG_POS(i,0)];\
+     }\
+     else\
+             if(shift_op<32)\
+             {\
+                  c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+                  shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\
+             }\
+             else\
+                  if(shift_op==32)\
+                  {\
+                       c = BIT31(cpu->R[REG_POS(i,0)]);\
+                       shift_op = 0;\
+                  }\
+                  else\
+                  {\
+                       c = 0;\
+                       shift_op = 0;\
+                  }
+
+#define ASR_IMM      shift_op = ((i>>7)&0x1F);\
+     if(shift_op==0)\
+            shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
+     else\
+            shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);
+
+#define S_ASR_IMM      u32 shift_op = ((i>>7)&0x1F);\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+     {\
+            shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
+            c = BIT31(cpu->R[REG_POS(i,0)]);\
+     }\
+     else\
+     {\
+            c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+            shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
+     }
+
+#define ASR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     if(shift_op==0)\
+             shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+             if(shift_op<32)\
+                     shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
+             else\
+                     shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;
+
+#define S_ASR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+             shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+             if(shift_op<32)\
+             {\
+                     c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+                     shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\
+             }\
+             else\
+             {\
+                     c = BIT31(cpu->R[REG_POS(i,0)]);\
+                     shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\
+             }
+
+#define ROR_IMM      shift_op = ((i>>7)&0x1F);\
+     if(shift_op==0)\
+     {\
+             u32 tmp = cpu->CPSR.bits.C;\
+             shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\
+     }\
+     else\
+             shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);
+
+#define S_ROR_IMM      u32 shift_op = ((i>>7)&0x1F);\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+     {\
+             u32 tmp = cpu->CPSR.bits.C;\
+             shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\
+             c = BIT0(cpu->R[REG_POS(i,0)]);\
+     }\
+     else\
+     {\
+             c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+             shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);\
+     }
+
+#define ROR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     if((shift_op==0)||((shift_op&0xF)==0))\
+             shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+             shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));
+
+#define S_ROR_REG      u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\
+     u32 c = cpu->CPSR.bits.C;\
+     if(shift_op==0)\
+             shift_op=cpu->R[REG_POS(i,0)];\
+     else\
+     {\
+             shift_op&=0xF;\
+             if(shift_op==0)\
+             {\
+                  shift_op=cpu->R[REG_POS(i,0)];\
+                  c = BIT31(cpu->R[REG_POS(i,0)]);\
+             }\
+             else\
+             {\
+                 c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\
+                  shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));\
+             }\
+     }
+
+#define IMM_VALUE      u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);
+
+#define S_IMM_VALUE      u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\
+     u32 c = cpu->CPSR.bits.C;\
+        if((i>>8)&0xF)\
+             c = BIT31(shift_op);
+
+#define IMM_OFF (((i>>4)&0xF0)+(i&0xF))
+
+#define IMM_OFF_12 ((i)&0xFFF)
+
+extern BOOL execute;
+
+static u32 FASTCALL  OP_UND(armcpu_t *cpu)
+{
+	LOG("Undefined instruction: %08X\n", cpu->instruction);
+	execute = false;
+	return 1;
+}
+
+//-----------------------AND------------------------------------
+
+#define OP_AND(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OP_ANDS(a, b)\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR;\
+          cpu->R[15] = cpu->R[REG_POS(i,16)] & shift_op;\
+          SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     return a;
+
+static u32 FASTCALL  OP_AND_LSL_IMM(register armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_AND(1, 3);
+}
+
+static u32 FASTCALL  OP_AND_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_AND(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_AND(1, 3);
+}
+
+static u32 FASTCALL  OP_AND_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_AND(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_AND(1, 3);
+}
+
+static u32 FASTCALL  OP_AND_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_AND(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_AND(1, 3);
+}
+
+static u32 FASTCALL  OP_AND_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_AND(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_AND(1, 3);
+}
+
+static u32 FASTCALL  OP_AND_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OP_ANDS(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OP_ANDS(3, 5);
+}
+
+static u32 FASTCALL  OP_AND_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OP_ANDS(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OP_ANDS(3, 5);
+}
+
+static u32 FASTCALL  OP_AND_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OP_ANDS(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OP_ANDS(3, 5);
+}
+
+static u32 FASTCALL  OP_AND_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OP_ANDS(2, 4);
+}
+
+static u32 FASTCALL  OP_AND_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OP_ANDS(3, 5);
+}
+
+static u32 FASTCALL  OP_AND_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OP_ANDS(2, 4);
+}
+
+//--------------EOR------------------------------
+
+#define OP_EOR(a, b)    cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OP_EORS(a, b)          cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     return a;
+
+static u32 FASTCALL  OP_EOR_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_EOR(1, 3);
+}
+
+static u32 FASTCALL  OP_EOR_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_EOR(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_EOR(1, 3);
+}
+
+static u32 FASTCALL  OP_EOR_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_EOR(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_EOR(1, 3);
+}
+
+static u32 FASTCALL  OP_EOR_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_EOR(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_EOR(1, 3);
+}
+
+static u32 FASTCALL  OP_EOR_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_EOR(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_EOR(1, 3);
+}
+
+static u32 FASTCALL  OP_EOR_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OP_EORS(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OP_EORS(3, 5);
+}
+
+static u32 FASTCALL  OP_EOR_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OP_EORS(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OP_EORS(3, 5);
+}
+
+static u32 FASTCALL  OP_EOR_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OP_EORS(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OP_EORS(3, 5);
+}
+
+static u32 FASTCALL  OP_EOR_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OP_EORS(2, 4);
+}
+
+static u32 FASTCALL  OP_EOR_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OP_EORS(3, 5);
+}
+
+static u32 FASTCALL  OP_EOR_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OP_EORS(2, 4);
+}
+
+//-------------SUB-------------------------------------
+
+#define OP_SUB(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OPSUBS(a, b)          cpu->R[REG_POS(i,12)] = v - shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
+     return a;
+
+static u32 FASTCALL  OP_SUB_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_SUB(1, 3);
+}
+
+static u32 FASTCALL  OP_SUB_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_SUB(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_SUB(1, 3);
+}
+
+static u32 FASTCALL  OP_SUB_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_SUB(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_SUB(1, 3);
+}
+
+static u32 FASTCALL  OP_SUB_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_SUB(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_SUB(1, 3);
+}
+
+static u32 FASTCALL  OP_SUB_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_SUB(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_SUB(1, 3);
+}
+
+static u32 FASTCALL  OP_SUB_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OPSUBS(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OPSUBS(3, 5);
+}
+
+static u32 FASTCALL  OP_SUB_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OPSUBS(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OPSUBS(3, 5);
+}
+
+static u32 FASTCALL  OP_SUB_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OPSUBS(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OPSUBS(3, 5);
+}
+
+static u32 FASTCALL  OP_SUB_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OPSUBS(2, 4);
+}
+
+static u32 FASTCALL  OP_SUB_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OPSUBS(3, 5);
+}
+
+static u32 FASTCALL  OP_SUB_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OPSUBS(2, 4);
+}
+
+//------------------RSB------------------------
+
+#define OP_RSB(a, b)      cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)];\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OP_RSBS(a, b)      cpu->R[REG_POS(i,12)] = shift_op - v;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\
+     return a;
+
+static u32 FASTCALL  OP_RSB_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_RSB(1, 3);
+}
+
+static u32 FASTCALL  OP_RSB_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_RSB(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_RSB(1, 3);
+}
+
+static u32 FASTCALL  OP_RSB_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_RSB(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_RSB(1, 3);
+}
+
+static u32 FASTCALL  OP_RSB_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_RSB(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_RSB(1, 3);
+}
+
+static u32 FASTCALL  OP_RSB_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_RSB(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_RSB(1, 3);
+}
+
+static u32 FASTCALL  OP_RSB_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OP_RSBS(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OP_RSBS(3, 5);
+}
+
+static u32 FASTCALL  OP_RSB_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OP_RSBS(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OP_RSBS(3, 5);
+}
+
+static u32 FASTCALL  OP_RSB_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OP_RSBS(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OP_RSBS(3, 5);
+}
+
+static u32 FASTCALL  OP_RSB_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OP_RSBS(2, 4);
+}
+
+static u32 FASTCALL  OP_RSB_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OP_RSBS(3, 5);
+}
+
+static u32 FASTCALL  OP_RSB_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OP_RSBS(2, 4);
+}
+
+//------------------ADD-----------------------------------
+
+#define OP_ADD(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+static u32 FASTCALL  OP_ADD_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_ADD(1, 3);
+}
+
+static u32 FASTCALL  OP_ADD_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_ADD(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_ADD(1, 3);
+}
+
+static u32 FASTCALL  OP_ADD_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_ADD(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_ADD(1, 3);
+}
+
+static u32 FASTCALL  OP_ADD_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_ADD(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_ADD(1, 3);
+}
+
+static u32 FASTCALL  OP_ADD_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_ADD(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_ADD(1, 3);
+}
+
+#define OP_ADDS(a, b) cpu->R[REG_POS(i,12)] = v + shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\
+     return a;
+
+static u32 FASTCALL  OP_ADD_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OP_ADDS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OP_ADDS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADD_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OP_ADDS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OP_ADDS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADD_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OP_ADDS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OP_ADDS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADD_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OP_ADDS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADD_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OP_ADDS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADD_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OP_ADDS(2, 4);
+}
+
+//------------------ADC-----------------------------------
+
+#define OP_ADC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op + cpu->CPSR.bits.C;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+static u32 FASTCALL  OP_ADC_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_ADC(1, 3);
+}
+
+static u32 FASTCALL  OP_ADC_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_ADC(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_ADC(1, 3);
+}
+
+static u32 FASTCALL  OP_ADC_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_ADC(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_ADC(1, 3);
+}
+
+static u32 FASTCALL  OP_ADC_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_ADC(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_ADC(1, 3);
+}
+
+static u32 FASTCALL  OP_ADC_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_ADC(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_ADC(1, 3);
+}
+
+#define OP_ADCS(a, b) \
+     { \
+     u32 tmp = shift_op + cpu->CPSR.bits.C;\
+     cpu->R[REG_POS(i,12)] = v + tmp;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_ADC_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OP_ADCS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OP_ADCS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADC_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OP_ADCS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OP_ADCS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADC_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OP_ADCS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OP_ADCS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADC_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OP_ADCS(2, 4);
+}
+
+static u32 FASTCALL  OP_ADC_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OP_ADCS(3, 5);
+}
+
+static u32 FASTCALL  OP_ADC_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OP_ADCS(2, 4);
+}
+
+//-------------SBC-------------------------------------
+
+#define OP_SBC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op - (!cpu->CPSR.bits.C);\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+static u32 FASTCALL  OP_SBC_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_SBC(1, 3);
+}
+
+static u32 FASTCALL  OP_SBC_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_SBC(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_SBC(1, 3);
+}
+
+static u32 FASTCALL  OP_SBC_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_SBC(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_SBC(1, 3);
+}
+
+static u32 FASTCALL  OP_SBC_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_SBC(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_SBC(1, 3);
+}
+
+static u32 FASTCALL  OP_SBC_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_SBC(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_SBC(1, 3);
+}
+
+#define OP_SBCS(a, b) \
+     { \
+     u32 tmp = v - (!cpu->CPSR.bits.C);\
+     cpu->R[REG_POS(i,12)] = tmp - shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]));\
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_SBC_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OP_SBCS(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OP_SBCS(3, 5);
+}
+
+static u32 FASTCALL  OP_SBC_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OP_SBCS(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OP_SBCS(3, 5);
+}
+
+static u32 FASTCALL  OP_SBC_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OP_SBCS(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OP_SBCS(3, 5);
+}
+
+static u32 FASTCALL  OP_SBC_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OP_SBCS(2, 4);
+}
+
+static u32 FASTCALL  OP_SBC_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OP_SBCS(3, 5);
+}
+
+static u32 FASTCALL  OP_SBC_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OP_SBCS(2, 4);
+}
+
+//---------------RSC----------------------------------
+
+#define OP_RSC(a, b) cpu->R[REG_POS(i,12)] =  shift_op - cpu->R[REG_POS(i,16)] - (!cpu->CPSR.bits.C);\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+static u32 FASTCALL  OP_RSC_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_RSC(1, 3);
+}
+
+static u32 FASTCALL  OP_RSC_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_RSC(2, 4);
+}
+
+static u32 FASTCALL  OP_RSC_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_RSC(1, 3);
+}
+
+static u32 FASTCALL  OP_RSC_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_RSC(2, 4);
+}
+
+static u32 FASTCALL  OP_RSC_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_RSC(1, 3);
+}
+
+static u32 FASTCALL  OP_RSC_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_RSC(2, 4);
+}
+
+static u32 FASTCALL  OP_RSC_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_RSC(1, 3);
+}
+
+static u32 FASTCALL  OP_RSC_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_RSC(2, 4);
+}
+
+static u32 FASTCALL  OP_RSC_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_RSC(1, 3);
+}
+
+#define OP_RSCS(a,b) \
+     { \
+     u32 tmp = shift_op - (!cpu->CPSR.bits.C);\
+     cpu->R[REG_POS(i,12)] = tmp - v;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+          }\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]));\
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_RSC_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSL_IMM;
+     OP_RSCS(2,4);
+}
+
+static u32 FASTCALL  OP_RSC_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSL_REG;
+     OP_RSCS(3,5);
+}
+
+static u32 FASTCALL  OP_RSC_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     LSR_IMM;
+     OP_RSCS(2,4);
+}
+
+static u32 FASTCALL  OP_RSC_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     LSR_REG;
+     OP_RSCS(3,5);
+}
+
+static u32 FASTCALL  OP_RSC_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ASR_IMM;
+     OP_RSCS(2,4);
+}
+
+static u32 FASTCALL  OP_RSC_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ASR_REG;
+     OP_RSCS(3,5);
+}
+
+static u32 FASTCALL  OP_RSC_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     u32 shift_op;
+     ROR_IMM;
+     OP_RSCS(2,4);
+}
+
+static u32 FASTCALL  OP_RSC_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     ROR_REG;
+     OP_RSCS(3,5);
+}
+
+static u32 FASTCALL  OP_RSC_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,16)];
+     IMM_VALUE;
+     OP_RSCS(2,4);
+}
+
+//-------------------TST----------------------------
+
+#define OP_TST(a) \
+     { \
+     unsigned tmp = cpu->R[REG_POS(i,16)] & shift_op;\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(tmp);\
+     cpu->CPSR.bits.Z = (tmp==0);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_TST_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OP_TST(1);
+}
+
+static u32 FASTCALL  OP_TST_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OP_TST(2);
+}
+
+static u32 FASTCALL  OP_TST_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OP_TST(1);
+}
+
+static u32 FASTCALL  OP_TST_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OP_TST(2);
+}
+
+static u32 FASTCALL  OP_TST_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OP_TST(1);
+}
+
+static u32 FASTCALL  OP_TST_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OP_TST(2);
+}
+
+static u32 FASTCALL  OP_TST_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OP_TST(1);
+}
+
+static u32 FASTCALL  OP_TST_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OP_TST(2);
+}
+
+static u32 FASTCALL  OP_TST_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OP_TST(1);
+}
+
+//-------------------TEQ----------------------------
+
+#define OP_TEQ(a) \
+     { \
+     unsigned tmp = cpu->R[REG_POS(i,16)] ^ shift_op;\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(tmp);\
+     cpu->CPSR.bits.Z = (tmp==0);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_TEQ_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OP_TEQ(1);
+}
+
+static u32 FASTCALL  OP_TEQ_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OP_TEQ(2);
+}
+
+static u32 FASTCALL  OP_TEQ_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OP_TEQ(1);
+}
+
+static u32 FASTCALL  OP_TEQ_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OP_TEQ(2);
+}
+
+static u32 FASTCALL  OP_TEQ_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OP_TEQ(1);
+}
+
+static u32 FASTCALL  OP_TEQ_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OP_TEQ(2);
+}
+
+static u32 FASTCALL  OP_TEQ_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OP_TEQ(1);
+}
+
+static u32 FASTCALL  OP_TEQ_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OP_TEQ(2);
+}
+
+static u32 FASTCALL  OP_TEQ_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OP_TEQ(1);
+}
+
+//-------------CMP-------------------------------------
+
+#define OP_CMP(a) \
+     { \
+     u32 tmp = cpu->R[REG_POS(i,16)] - shift_op;\
+     cpu->CPSR.bits.N = BIT31(tmp);\
+     cpu->CPSR.bits.Z = (tmp==0);\
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_CMP_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_CMP(1);
+}
+
+static u32 FASTCALL  OP_CMP_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_CMP(2);
+}
+
+static u32 FASTCALL  OP_CMP_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_CMP(1);
+}
+
+static u32 FASTCALL  OP_CMP_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_CMP(2);
+}
+
+static u32 FASTCALL  OP_CMP_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_CMP(1);
+}
+
+static u32 FASTCALL  OP_CMP_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_CMP(2);
+}
+
+static u32 FASTCALL  OP_CMP_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_CMP(1);
+}
+
+static u32 FASTCALL  OP_CMP_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_CMP(2);
+}
+
+static u32 FASTCALL  OP_CMP_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_CMP(1);
+}
+
+//---------------CMN---------------------------
+
+#define OP_CMN(a) \
+     { \
+     u32 tmp = cpu->R[REG_POS(i,16)] + shift_op;\
+     cpu->CPSR.bits.N = BIT31(tmp);\
+     cpu->CPSR.bits.Z = (tmp==0);\
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\
+     return a; \
+     }
+
+static u32 FASTCALL  OP_CMN_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_CMN(1);
+}
+
+static u32 FASTCALL  OP_CMN_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_CMN(2);
+}
+
+static u32 FASTCALL  OP_CMN_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_CMN(1);
+}
+
+static u32 FASTCALL  OP_CMN_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_CMN(2);
+}
+
+static u32 FASTCALL  OP_CMN_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_CMN(1);
+}
+
+static u32 FASTCALL  OP_CMN_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_CMN(2);
+}
+
+static u32 FASTCALL  OP_CMN_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_CMN(1);
+}
+
+static u32 FASTCALL  OP_CMN_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_CMN(2);
+}
+
+static u32 FASTCALL  OP_CMN_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_CMN(1);
+}
+
+//------------------ORR-------------------
+
+#define OP_ORR(a, b)  cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+static u32 FASTCALL  OP_ORR_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_ORR(1, 3);
+}
+
+static u32 FASTCALL  OP_ORR_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OP_ORR(2, 4);
+}
+
+static u32 FASTCALL  OP_ORR_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_ORR(1, 3);
+}
+
+static u32 FASTCALL  OP_ORR_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OP_ORR(2, 4);
+}
+
+static u32 FASTCALL  OP_ORR_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_ORR(1, 3);
+}
+
+static u32 FASTCALL  OP_ORR_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_ORR(2, 4);
+}
+
+static u32 FASTCALL  OP_ORR_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_ORR(1, 3);
+}
+
+static u32 FASTCALL  OP_ORR_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_ORR(2, 4);
+}
+
+static u32 FASTCALL  OP_ORR_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_ORR(1, 3);
+}
+
+static u32 FASTCALL  OP_ORR_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 4;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 2;
+}
+
+static u32 FASTCALL  OP_ORR_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 5;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 3;
+}
+
+static u32 FASTCALL  OP_ORR_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 4;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 2;
+}
+
+static u32 FASTCALL  OP_ORR_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 5;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 3;
+}
+
+static u32 FASTCALL  OP_ORR_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 4;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 2;
+}
+
+static u32 FASTCALL  OP_ORR_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 5;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 3;
+}
+
+static u32 FASTCALL  OP_ORR_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 4;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 2;
+}
+
+static u32 FASTCALL  OP_ORR_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 5;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 3;
+}
+
+static u32 FASTCALL  OP_ORR_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;
+     if(REG_POS(i,12)==15)
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));
+          cpu->next_instruction = cpu->R[15];
+          return 4;
+     }
+     cpu->CPSR.bits.C = c;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);
+     return 2;
+}
+
+//------------------MOV-------------------
+
+#define OP_MOV(a, b)      cpu->R[REG_POS(i,12)] = shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = shift_op;\
+          return b;\
+     }\
+     return a;
+
+#define OP_MOV_S(a, b)    cpu->R[REG_POS(i,12)] = shift_op;\
+     if(BIT20(i) && REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     return a;\
+
+static u32 FASTCALL  OP_MOV_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OP_MOV(1,3);
+}
+
+static u32 FASTCALL  OP_MOV_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+	 if (REG_POS(i,0) == 15) shift_op += 4;
+     OP_MOV(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OP_MOV(1,3);
+}
+
+static u32 FASTCALL  OP_MOV_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+	 if (REG_POS(i,0) == 15) shift_op += 4;
+     OP_MOV(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OP_MOV(1,3);
+}
+
+static u32 FASTCALL  OP_MOV_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OP_MOV(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OP_MOV(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OP_MOV(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OP_MOV(1,3);
+}
+
+static u32 FASTCALL  OP_MOV_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OP_MOV_S(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+	 if (REG_POS(i,0) == 15) shift_op += 4;
+     OP_MOV_S(3,5);
+}
+
+static u32 FASTCALL  OP_MOV_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OP_MOV_S(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+	 if (REG_POS(i,0) == 15) shift_op += 4;
+     OP_MOV_S(3,5);
+}
+
+static u32 FASTCALL  OP_MOV_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OP_MOV_S(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OP_MOV_S(3,5);
+}
+
+static u32 FASTCALL  OP_MOV_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OP_MOV_S(2,4);
+}
+
+static u32 FASTCALL  OP_MOV_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OP_MOV_S(3,5);
+}
+
+static u32 FASTCALL  OP_MOV_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OP_MOV_S(2,4);
+}
+
+//------------------BIC-------------------
+#define OPP_BIC(a, b)      cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OPP_BIC_S(a, b)    cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     return a;
+
+static u32 FASTCALL  OP_BIC_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OPP_BIC(1,3);
+}
+
+static u32 FASTCALL  OP_BIC_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OPP_BIC(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OPP_BIC(1,3);
+}
+
+static u32 FASTCALL  OP_BIC_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OPP_BIC(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OPP_BIC(1,3);
+}
+
+static u32 FASTCALL  OP_BIC_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OPP_BIC(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OPP_BIC(1,3);
+}
+
+static u32 FASTCALL  OP_BIC_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OPP_BIC(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OPP_BIC(1,3);
+}
+
+static u32 FASTCALL  OP_BIC_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OPP_BIC_S(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OPP_BIC_S(3,5);
+}
+
+static u32 FASTCALL  OP_BIC_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OPP_BIC_S(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OPP_BIC_S(3,5);
+}
+
+static u32 FASTCALL  OP_BIC_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OPP_BIC_S(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OPP_BIC_S(3,5);
+}
+
+static u32 FASTCALL  OP_BIC_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OPP_BIC_S(2,4);
+}
+
+static u32 FASTCALL  OP_BIC_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OPP_BIC_S(3,5);
+}
+
+static u32 FASTCALL  OP_BIC_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OPP_BIC_S(2,4);
+}
+
+//------------------MVN-------------------
+#define OPP_MVN(a, b)     cpu->R[REG_POS(i,12)] = ~shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     return a;
+
+#define OPP_MVN_S(a, b)   cpu->R[REG_POS(i,12)] = ~shift_op;\
+     if(REG_POS(i,12)==15)\
+     {\
+          Status_Reg SPSR = cpu->SPSR;\
+          armcpu_switchMode(cpu, SPSR.bits.mode);\
+          cpu->CPSR=SPSR;\
+          cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\
+          cpu->next_instruction = cpu->R[15];\
+          return b;\
+     }\
+     cpu->CPSR.bits.C = c;\
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\
+     return a;
+
+static u32 FASTCALL  OP_MVN_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSL_IMM;
+     OPP_MVN(1,3);
+}
+
+static u32 FASTCALL  OP_MVN_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSL_REG;
+     OPP_MVN(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     LSR_IMM;
+     OPP_MVN(1,3);
+}
+
+static u32 FASTCALL  OP_MVN_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     LSR_REG;
+     OPP_MVN(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ASR_IMM;
+     OPP_MVN(1,3);
+}
+
+static u32 FASTCALL  OP_MVN_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ASR_REG;
+     OPP_MVN(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 shift_op;
+     ROR_IMM;
+     OPP_MVN(1,3);
+}
+
+static u32 FASTCALL  OP_MVN_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     ROR_REG;
+     OPP_MVN(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+     OPP_MVN(1,3);
+}
+
+static u32 FASTCALL  OP_MVN_S_LSL_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_IMM;
+     OPP_MVN_S(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_S_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSL_REG;
+     OPP_MVN_S(3,5);
+}
+
+static u32 FASTCALL  OP_MVN_S_LSR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_IMM;
+     OPP_MVN_S(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_S_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_LSR_REG;
+     OPP_MVN_S(3,5);
+}
+
+static u32 FASTCALL  OP_MVN_S_ASR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_IMM;
+     OPP_MVN_S(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_S_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ASR_REG;
+     OPP_MVN_S(3,5);
+}
+
+static u32 FASTCALL  OP_MVN_S_ROR_IMM(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_IMM;
+     OPP_MVN_S(2,4);
+}
+
+static u32 FASTCALL  OP_MVN_S_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_ROR_REG;
+     OPP_MVN_S(3,5);
+}
+
+static u32 FASTCALL  OP_MVN_S_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     S_IMM_VALUE;
+     OPP_MVN_S(2,4);
+}
+
+//-------------MUL------------------------
+#define OPP_M(a,b)     v >>= 8;\
+     if((v==0)||(v==0xFFFFFF))\
+          return b;\
+     v >>= 8;\
+     if((v==0)||(v==0xFFFF))\
+          return b+1;\
+     v >>= 8;\
+     if((v==0)||(v==0xFF))\
+          return b+2;\
+     return a;\
+
+static u32 FASTCALL  OP_MUL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v;
+     OPP_M(5,2);
+}
+
+static u32 FASTCALL  OP_MLA(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     u32 a = cpu->R[REG_POS(i,8)];
+     u32 b = cpu->R[REG_POS(i,12)];
+     cpu->R[REG_POS(i,16)] = a * v + b;
+
+     OPP_M(6,3);
+}
+
+static u32 FASTCALL  OP_MUL_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v;
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0);
+
+     OPP_M(6,3);
+}
+
+static u32 FASTCALL  OP_MLA_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v + cpu->R[REG_POS(i,12)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0);
+     OPP_M(7,4);
+}
+
+//----------UMUL--------------------------
+
+static u32 FASTCALL  OP_UMULL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)];
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] = (u32)(res>>32);
+
+     OPP_M(6,3);
+}
+
+static u32 FASTCALL  OP_UMLAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)];
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] += (u32)(res>>32);
+
+     OPP_M(7,4);
+}
+
+static u32 FASTCALL  OP_UMULL_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)];
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] = (u32)(res>>32);
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
+
+     OPP_M(7,4);
+}
+
+static u32 FASTCALL  OP_UMLAL_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_POS(i,0)];
+     u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)];
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] += (u32)(res>>32);
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
+
+     OPP_M(8,5);
+}
+
+//----------SMUL--------------------------
+
+static u32 FASTCALL  OP_SMULL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 v = (s32)cpu->R[REG_POS(i,0)];
+     s64 b = (s32)cpu->R[REG_POS(i,8)];
+     s64 res = v * b;
+
+     cpu->R[REG_POS(i,12)] = (u32)(res&0xFFFFFFFF);
+     cpu->R[REG_POS(i,16)] = (u32)(res>>32);
+
+     v &= 0xFFFFFFFF;
+
+     OPP_M(6,3);
+}
+
+static u32 FASTCALL  OP_SMLAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     s64 v = (s32)cpu->R[REG_POS(i,0)];
+     s64 b = (s32)cpu->R[REG_POS(i,8)];
+     s64 res = v * b + (u64)cpu->R[REG_POS(i,12)];
+
+     //LOG("%08X * %08X + %08X%08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]);
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] += (u32)(res>>32);
+
+     //LOG("= %08X%08X  %08X%08X\r\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res);
+
+     v &= 0xFFFFFFFF;
+
+     OPP_M(7,4);
+}
+
+static u32 FASTCALL  OP_SMULL_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 v = (s32)cpu->R[REG_POS(i,0)];
+     s64 b = (s32)cpu->R[REG_POS(i,8)];
+     s64 res = v * b;
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] = (u32)(res>>32);
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
+
+     v &= 0xFFFFFFFF;
+
+     OPP_M(7,4);
+}
+
+static u32 FASTCALL  OP_SMLAL_S(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 v = (s32)cpu->R[REG_POS(i,0)];
+     s64 b = (s32)cpu->R[REG_POS(i,8)];
+     s64 res = v * b + (u64)cpu->R[REG_POS(i,12)];
+
+     cpu->R[REG_POS(i,12)] = (u32)res;
+     cpu->R[REG_POS(i,16)] += (u32)(res>>32);
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]);
+     cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0);
+
+     v &= 0xFFFFFFFF;
+
+     OPP_M(8,5);
+}
+
+//---------------SWP------------------------------
+
+static u32 FASTCALL  OP_SWP(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 tmp = ROR(READ32(cpu->mem_if->data, adr), ((cpu->R[REG_POS(i,16)]&3)<<3));
+
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]);
+     cpu->R[REG_POS(i,12)] = tmp;
+
+     return 4 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]*2;
+}
+
+static u32 FASTCALL  OP_SWPB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u8 tmp = READ8(cpu->mem_if->data, adr);
+     WRITE8(cpu->mem_if->data, adr, (u8)(cpu->R[REG_POS(i,0)]&0xFF));
+     cpu->R[REG_POS(i,12)] = tmp;
+
+     return 4 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]*2;
+}
+
+//------------LDRH-----------------------------
+
+static u32 FASTCALL  OP_LDRH_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+    return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] =(u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] += IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] -= IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//------------STRH-----------------------------
+
+static u32 FASTCALL  OP_STRH_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+	 cpu->R[REG_POS(i,16)] = adr;
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] += IMM_OFF;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] -= IMM_OFF;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//----------------LDRSH--------------------------
+
+static u32 FASTCALL  OP_LDRSH_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] += IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] -= IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_POS_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSH_POS_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//----------------------LDRSB----------------------
+
+static u32 FASTCALL  OP_LDRSB_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_PRE_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_PRE_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF;
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_PRE_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_PRE_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_POS_INDE_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] += IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_POS_INDE_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] -= IMM_OFF;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_POS_INDE_P_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRSB_POS_INDE_M_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+     cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)];
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//--------------MRS--------------------------------
+
+static u32 FASTCALL  OP_MRS_CPSR(armcpu_t *cpu)
+{
+     cpu->R[REG_POS(cpu->instruction,12)] = cpu->CPSR.val;
+
+     return 1;
+}
+
+static u32 FASTCALL  OP_MRS_SPSR(armcpu_t *cpu)
+{
+     cpu->R[REG_POS(cpu->instruction,12)] = cpu->SPSR.val;
+
+     return 1;
+}
+
+//--------------MSR--------------------------------
+
+static u32 FASTCALL  OP_MSR_CPSR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 operand = cpu->R[REG_POS(i,0)];
+
+     if(cpu->CPSR.bits.mode!=USR)
+     {
+          if(BIT16(i))
+          {
+               armcpu_switchMode(cpu, operand & 0x1F);
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF);
+          }
+          if(BIT17(i))
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00);
+          if(BIT18(i))
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000);
+     }
+     if(BIT19(i))
+          cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000);
+
+     return 1;
+}
+
+static u32 FASTCALL  OP_MSR_SPSR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 operand = cpu->R[REG_POS(i,0)];
+
+     if(cpu->CPSR.bits.mode!=USR)
+     {
+          if(BIT16(i))
+          {
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0XFF);
+          }
+          if(BIT17(i))
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0XFF00);
+          if(BIT18(i))
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0XFF0000);
+     }
+     if(BIT19(i))
+          cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0XFF000000);
+
+     return 1;
+}
+
+static u32 FASTCALL  OP_MSR_CPSR_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+
+     if(cpu->CPSR.bits.mode!=USR)
+     {
+          if(BIT16(i))
+          {
+               armcpu_switchMode(cpu, shift_op & 0x1F);
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0XFF);
+          }
+          if(BIT17(i))
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00);
+          if(BIT18(i))
+               cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000);
+     }
+     if(BIT19(i))
+	  {
+          //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0XFF000000);
+		  cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000);
+	  }
+
+     return 1;
+}
+
+static u32 FASTCALL  OP_MSR_SPSR_IMM_VAL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     IMM_VALUE;
+
+     if(cpu->CPSR.bits.mode!=USR)
+     {
+          if(BIT16(i))
+          {
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0XFF);
+          }
+          if(BIT17(i))
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00);
+          if(BIT18(i))
+               cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000);
+     }
+     if(BIT19(i))
+          cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0XFF000000);
+
+     return 1;
+}
+
+//-----------------BRANCH--------------------------
+
+static u32 FASTCALL  OP_BX(armcpu_t *cpu)
+{
+     u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
+
+     cpu->CPSR.bits.T = BIT0(tmp);
+     cpu->R[15] = tmp & 0xFFFFFFFE;
+     cpu->next_instruction = cpu->R[15];
+     return 3;
+}
+
+static u32 FASTCALL  OP_BLX_REG(armcpu_t *cpu)
+{
+     u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)];
+
+     cpu->R[14] = cpu->next_instruction;
+     cpu->CPSR.bits.T = BIT0(tmp);
+     cpu->R[15] = tmp & 0xFFFFFFFE;
+     cpu->next_instruction = cpu->R[15];
+     return 3;
+}
+
+#define SIGNEXTEND_24(i) (((s32)((i)<<8))>>8)
+
+static u32 FASTCALL  OP_B(armcpu_t *cpu)
+{
+	u32 off = SIGNEXTEND_24(cpu->instruction);
+	if(CONDITION(cpu->instruction)==0xF)
+	{
+		cpu->R[14] = cpu->next_instruction;
+		cpu->CPSR.bits.T = 1;
+	}
+	cpu->R[15] += (off<<2);
+	cpu->next_instruction = cpu->R[15];
+
+    return 3;
+}
+
+static u32 FASTCALL  OP_BL(armcpu_t *cpu)
+{
+	u32 off = SIGNEXTEND_24(cpu->instruction);
+	if(CONDITION(cpu->instruction)==0xF)
+	{
+		cpu->CPSR.bits.T = 1;
+		cpu->R[15] += 2;
+	}
+	cpu->R[14] = cpu->next_instruction;
+	cpu->R[15] += (off<<2);
+	cpu->next_instruction = cpu->R[15];
+
+	return 3;
+}
+
+//----------------CLZ-------------------------------
+
+u8 CLZ_TAB[16]=
+{
+     0,                     // 0000
+     1,                     // 0001
+     2, 2,                  // 001X
+     3, 3, 3, 3,            // 01XX
+     4, 4, 4, 4, 4, 4, 4, 4 // 1XXX
+};
+
+static u32 FASTCALL  OP_CLZ(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 Rm = cpu->R[REG_POS(i,0)];
+     u32 pos;
+
+     if(Rm==0)
+     {
+          cpu->R[REG_POS(i,12)]=32;
+          return 2;
+     }
+
+     Rm |= (Rm >>1);
+     Rm |= (Rm >>2);
+     Rm |= (Rm >>4);
+     Rm |= (Rm >>8);
+     Rm |= (Rm >>16);
+
+     pos =
+          CLZ_TAB[Rm&0xF] +
+          CLZ_TAB[(Rm>>4)&0xF] +
+          CLZ_TAB[(Rm>>8)&0xF] +
+          CLZ_TAB[(Rm>>12)&0xF] +
+          CLZ_TAB[(Rm>>16)&0xF] +
+          CLZ_TAB[(Rm>>20)&0xF] +
+          CLZ_TAB[(Rm>>24)&0xF] +
+          CLZ_TAB[(Rm>>28)&0xF];
+
+     cpu->R[REG_POS(i,12)]=32 - pos;
+
+     return 2;
+}
+
+//--------------------QADD--QSUB------------------------------
+
+static u32 FASTCALL  OP_QADD(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+        u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)];
+
+    LOG("spe add\r\n");
+	if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)],cpu->R[REG_POS(i,0)], res))
+	{
+		cpu->CPSR.bits.Q=1;
+		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
+		return 2;
+	}
+	cpu->R[REG_POS(i,12)]=res;
+	if(REG_POS(i,12)==15)
+	{
+         cpu->R[15] &= 0XFFFFFFFC;
+	     cpu->next_instruction = cpu->R[15];
+	     return 3;
+    }
+    return 2;
+}
+
+static u32 FASTCALL  OP_QSUB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+        u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)];
+
+    LOG("spe add\r\n");
+	if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,16)], res))
+	{
+		cpu->CPSR.bits.Q=1;
+		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
+		return 2;
+	}
+	cpu->R[REG_POS(i,12)]=res;
+	if(REG_POS(i,12)==15)
+	{
+         cpu->R[15] &= 0XFFFFFFFC;
+	     cpu->next_instruction = cpu->R[15];
+	     return 3;
+    }
+    return 2;
+}
+
+static u32 FASTCALL  OP_QDADD(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+        u32 mul = cpu->R[REG_POS(i,16)]<<1;
+        u32 res;
+
+
+    LOG("spe add\r\n");
+	if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
+	{
+		cpu->CPSR.bits.Q=1;
+		mul = 0x80000000-BIT31(mul);
+	}
+
+	res = mul + cpu->R[REG_POS(i,0)];
+	if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,0)],mul, res))
+	{
+		cpu->CPSR.bits.Q=1;
+		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
+		return 2;
+	}
+	cpu->R[REG_POS(i,12)]=res;
+	if(REG_POS(i,12)==15)
+	{
+         cpu->R[15] &= 0XFFFFFFFC;
+	     cpu->next_instruction = cpu->R[15];
+	     return 3;
+    }
+    return 2;
+}
+
+static u32 FASTCALL  OP_QDSUB(armcpu_t *cpu)
+{
+    u32 i = cpu->instruction;
+        u32 mul = cpu->R[REG_POS(i,16)]<<1;
+        u32 res;
+
+
+    LOG("spe add\r\n");
+	if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul))
+	{
+		cpu->CPSR.bits.Q=1;
+		mul = 0x80000000-BIT31(mul);
+	}
+
+	res = cpu->R[REG_POS(i,0)] - mul;
+	if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], mul, res))
+	{
+		cpu->CPSR.bits.Q=1;
+		cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res);
+		return 2;
+	}
+	cpu->R[REG_POS(i,12)]=res;
+	if(REG_POS(i,12)==15)
+	{
+         cpu->R[15] &= 0XFFFFFFFC;
+	     cpu->next_instruction = cpu->R[15];
+	     return 3;
+    }
+    return 2;
+}
+
+//-----------------SMUL-------------------------------
+
+#define HWORD(i)   ((s32)(((s32)(i))>>16))
+#define LWORD(i)   (s32)(((s32)((i)<<16))>>16)
+
+static u32 FASTCALL  OP_SMUL_B_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMUL_B_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMUL_T_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMUL_T_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+
+     return 2;
+}
+
+//-----------SMLA----------------------------
+
+static u32 FASTCALL  OP_SMLA_B_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLABB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLA_B_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLABT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLA_T_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLATB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLA_T_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLATT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a);
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+//--------------SMLAL---------------------------------------
+
+static u32 FASTCALL  OP_SMLAL_B_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)]));
+     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
+
+     LOG("SMLALBB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(u32) res);
+
+     cpu->R[REG_POS(i,12)] = (u32) res;
+     cpu->R[REG_POS(i,16)] += (res + ((tmp<0)*0xFFFFFFFF));
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLAL_B_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
+
+     LOG("SMLALBT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
+
+     cpu->R[REG_POS(i,12)] = (u32) res;
+     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLAL_T_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* (s64)LWORD(cpu->R[REG_POS(i,8)]));
+     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
+
+     LOG("SMLALTB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
+
+     cpu->R[REG_POS(i,12)] = (u32) res;
+     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLAL_T_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)]));
+     u64 res = (u64)tmp + cpu->R[REG_POS(i,12)];
+
+     LOG("SMLALTT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res);
+
+     cpu->R[REG_POS(i,12)] = (u32) res;
+     cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF);
+
+     return 2;
+}
+
+//--------------SMULW--------------------
+
+static u32 FASTCALL  OP_SMULW_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
+
+     //LOG("SMULWB %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF);
+
+     cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF);
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMULW_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
+
+     //LOG("SMULWT %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF));
+
+     cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF);
+
+     return 2;
+}
+
+//--------------SMLAW-------------------
+static u32 FASTCALL  OP_SMLAW_B(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLAWB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a);
+
+     tmp = (tmp>>16);
+
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+static u32 FASTCALL  OP_SMLAW_T(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]);
+     u32 a = cpu->R[REG_POS(i,12)];
+
+     //LOG("SMLAWT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a);
+
+     tmp = ((tmp>>16)&0xFFFFFFFF);
+     cpu->R[REG_POS(i,16)] = tmp + a;
+
+     if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)]))
+          cpu->CPSR.bits.Q = 1;
+
+     return 2;
+}
+
+//------------LDR---------------------------
+
+static u32 FASTCALL  OP_LDR_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//------------------------------------------------------------
+static u32 FASTCALL  OP_LDR_P_IMM_OFF_POSTIND2(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 val = READ32(cpu->mem_if->data, adr);
+     u32 old;
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     old = armcpu_switchMode(cpu, USR);
+     cpu->R[REG_POS(i,12)] = val;
+     armcpu_switchMode(cpu, old);
+
+     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//------------------------------------------------------------
+
+static u32 FASTCALL  OP_LDR_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr - shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr - shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr - shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr + shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ32(cpu->mem_if->data, adr);
+
+     if(adr&3)
+         val = ROR(val, 8*(adr&3));
+
+     if(REG_POS(i,12)==15)
+     {
+          cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1));
+          cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit;
+	      cpu->next_instruction = cpu->R[15];
+          cpu->R[REG_POS(i,16)] = adr - shift_op;
+          return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     }
+
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//-----------------LDRB-------------------------------------------
+
+static u32 FASTCALL  OP_LDRB_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     u32 val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     u32 val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     u32 val = READ8(cpu->mem_if->data, adr);
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     u32 val = READ8(cpu->mem_if->data, adr);
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+
+	 cpu->R[REG_POS(i,16)] = adr;
+     cpu->R[REG_POS(i,12)] = val;
+
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,16)] = adr;
+	 cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     u32 val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr + shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+	 cpu->R[REG_POS(i,16)] = adr - shift_op;
+     cpu->R[REG_POS(i,12)] = val;
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//----------------------STR--------------------------------
+
+static u32 FASTCALL  OP_STR_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+//	 execute = false;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//-----------------------STRB-------------------------------------
+
+static u32 FASTCALL  OP_STRB_P_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12;
+     WRITE8(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] + shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)] - shift_op;
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr;
+     u32 shift_op;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//-----------------------LDRBT-------------------------------------
+
+static u32 FASTCALL  OP_LDRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     i = cpu->instruction;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_M_IMM_OFF_POSTIND\n");
+
+
+     i = cpu->instruction;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_P_LSL_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_M_LSL_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_P_LSR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_M_LSR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_P_ASR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_M_ASR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_P_ROR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_LDRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 val;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_LDRBT_M_ROR_IMM_OFF_POSTIND");
+
+
+     i = cpu->instruction;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     val = READ8(cpu->mem_if->data, adr);
+     cpu->R[REG_POS(i,12)] = val;
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//----------------------STRBT----------------------------
+
+static u32 FASTCALL  OP_STRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     LSL_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     LSR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     ASR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr + shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL  OP_STRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu)
+{
+     u32 oldmode;
+     u32 i;
+     u32 adr;
+     u32 shift_op;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+
+     i = cpu->instruction;
+     ROR_IMM;
+     adr = cpu->R[REG_POS(i,16)];
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]);
+     cpu->R[REG_POS(i,16)] = adr - shift_op;
+
+     armcpu_switchMode(cpu, oldmode);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+//---------------------LDM-----------------------------
+
+#define OP_L_IA(reg, adr)  if(BIT##reg(i))\
+     {\
+          registres[reg] = READ32(cpu->mem_if->data, start);\
+          c += waitState[(start>>24)&0xF];\
+          adr += 4;\
+     }
+
+#define OP_L_IB(reg, adr)  if(BIT##reg(i))\
+     {\
+          adr += 4;\
+          registres[reg] = READ32(cpu->mem_if->data, start);\
+          c += waitState[(start>>24)&0xF];\
+     }
+
+#define OP_L_DA(reg, adr)  if(BIT##reg(i))\
+     {\
+          registres[reg] = READ32(cpu->mem_if->data, start);\
+          c += waitState[(start>>24)&0xF];\
+          adr -= 4;\
+     }
+
+#define OP_L_DB(reg, adr)  if(BIT##reg(i))\
+     {\
+          adr -= 4;\
+          registres[reg] = READ32(cpu->mem_if->data, start);\
+          c += waitState[(start>>24)&0xF];\
+     }
+
+static u32 FASTCALL  OP_LDMIA(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IA(0, start);
+     OP_L_IA(1, start);
+     OP_L_IA(2, start);
+     OP_L_IA(3, start);
+     OP_L_IA(4, start);
+     OP_L_IA(5, start);
+     OP_L_IA(6, start);
+     OP_L_IA(7, start);
+     OP_L_IA(8, start);
+     OP_L_IA(9, start);
+     OP_L_IA(10, start);
+     OP_L_IA(11, start);
+     OP_L_IA(12, start);
+     OP_L_IA(13, start);
+     OP_L_IA(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+          //start += 4;
+	      cpu->next_instruction = registres[15];
+          c += waitState[(start>>24)&0xF];
+     }
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IB(0, start);
+     OP_L_IB(1, start);
+     OP_L_IB(2, start);
+     OP_L_IB(3, start);
+     OP_L_IB(4, start);
+     OP_L_IB(5, start);
+     OP_L_IB(6, start);
+     OP_L_IB(7, start);
+     OP_L_IB(8, start);
+     OP_L_IB(9, start);
+     OP_L_IB(10, start);
+     OP_L_IB(11, start);
+     OP_L_IB(12, start);
+     OP_L_IB(13, start);
+     OP_L_IB(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          start += 4;
+          c += waitState[(start>>24)&0xF];
+          tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+	      cpu->next_instruction = registres[15];
+          c += 2 + (c==0);
+     }
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDA(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+          c += waitState[(start>>24)&0xF];
+          start -= 4;
+	      cpu->next_instruction = registres[15];
+     }
+
+     OP_L_DA(14, start);
+     OP_L_DA(13, start);
+     OP_L_DA(12, start);
+     OP_L_DA(11, start);
+     OP_L_DA(10, start);
+     OP_L_DA(9, start);
+     OP_L_DA(8, start);
+     OP_L_DA(7, start);
+     OP_L_DA(6, start);
+     OP_L_DA(5, start);
+     OP_L_DA(4, start);
+     OP_L_DA(3, start);
+     OP_L_DA(2, start);
+     OP_L_DA(1, start);
+     OP_L_DA(0, start);
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          start -= 4;
+          tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+	      cpu->next_instruction = registres[15];
+          c += waitState[(start>>24)&0xF];
+     }
+
+     OP_L_DB(14, start);
+     OP_L_DB(13, start);
+     OP_L_DB(12, start);
+     OP_L_DB(11, start);
+     OP_L_DB(10, start);
+     OP_L_DB(9, start);
+     OP_L_DB(8, start);
+     OP_L_DB(7, start);
+     OP_L_DB(6, start);
+     OP_L_DB(5, start);
+     OP_L_DB(4, start);
+     OP_L_DB(3, start);
+     OP_L_DB(2, start);
+     OP_L_DB(1, start);
+     OP_L_DB(0, start);
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIA_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+	 u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IA(0, start);
+     OP_L_IA(1, start);
+     OP_L_IA(2, start);
+     OP_L_IA(3, start);
+     OP_L_IA(4, start);
+     OP_L_IA(5, start);
+     OP_L_IA(6, start);
+     OP_L_IA(7, start);
+     OP_L_IA(8, start);
+     OP_L_IA(9, start);
+     OP_L_IA(10, start);
+     OP_L_IA(11, start);
+     OP_L_IA(12, start);
+     OP_L_IA(13, start);
+     OP_L_IA(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+          c += waitState[(start>>24)&0xF];
+          start += 4;
+	      cpu->next_instruction = registres[15];
+     }
+
+	if(i & (1 << REG_POS(i,16))) {
+		if(i & bitList)
+			cpu->R[REG_POS(i,16)] = start;
+	}
+	else
+		cpu->R[REG_POS(i,16)] = start;
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIB_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+	 u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
+
+     u32 * registres = cpu->R;
+     u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+	 OP_L_IB(0, start);
+     OP_L_IB(1, start);
+     OP_L_IB(2, start);
+     OP_L_IB(3, start);
+     OP_L_IB(4, start);
+     OP_L_IB(5, start);
+     OP_L_IB(6, start);
+     OP_L_IB(7, start);
+     OP_L_IB(8, start);
+     OP_L_IB(9, start);
+     OP_L_IB(10, start);
+     OP_L_IB(11, start);
+     OP_L_IB(12, start);
+     OP_L_IB(13, start);
+     OP_L_IB(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          start += 4;
+          c += waitState[(start>>24)&0xF];
+          tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR.bits.T = BIT0(tmp);
+	      cpu->next_instruction = registres[15];
+          c += 2 + (c==0);
+     }
+
+	if(i & (1 << REG_POS(i,16))) {
+		if(i & bitList)
+			cpu->R[REG_POS(i,16)] = start;
+	}
+	else
+		cpu->R[REG_POS(i,16)] = start;
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDA_W(armcpu_t *cpu)
+{
+	u32 i = cpu->instruction, c = 0;
+	u32 start = cpu->R[REG_POS(i,16)];
+	u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
+
+	u32 * registres = cpu->R;
+	u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+	if(BIT15(i))
+	{
+		u32 tmp = READ32(cpu->mem_if->data, start);
+		registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+		cpu->CPSR.bits.T = BIT0(tmp);
+		c += waitState[(start>>24)&0xF];
+		start -= 4;
+		cpu->next_instruction = registres[15];
+	}
+
+	OP_L_DA(14, start);
+	OP_L_DA(13, start);
+	OP_L_DA(12, start);
+	OP_L_DA(11, start);
+	OP_L_DA(10, start);
+	OP_L_DA(9, start);
+	OP_L_DA(8, start);
+	OP_L_DA(7, start);
+	OP_L_DA(6, start);
+	OP_L_DA(5, start);
+	OP_L_DA(4, start);
+	OP_L_DA(3, start);
+	OP_L_DA(2, start);
+	OP_L_DA(1, start);
+	OP_L_DA(0, start);
+
+	if(i & (1 << REG_POS(i,16))) {
+		if(i & bitList)
+			cpu->R[REG_POS(i,16)] = start;
+	}
+	else
+		cpu->R[REG_POS(i,16)] = start;
+
+	return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDB_W(armcpu_t *cpu)
+{
+	u32 i = cpu->instruction, c = 0;
+	u32 start = cpu->R[REG_POS(i,16)];
+	u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF;
+	u32 * registres = cpu->R;
+	u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+	if(BIT15(i))
+	{
+		u32 tmp;
+		start -= 4;
+		tmp = READ32(cpu->mem_if->data, start);
+		registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+		cpu->CPSR.bits.T = BIT0(tmp);
+		cpu->next_instruction = registres[15];
+		c += waitState[(start>>24)&0xF];
+	}
+
+	OP_L_DB(14, start);
+	OP_L_DB(13, start);
+	OP_L_DB(12, start);
+	OP_L_DB(11, start);
+	OP_L_DB(10, start);
+	OP_L_DB(9, start);
+	OP_L_DB(8, start);
+	OP_L_DB(7, start);
+	OP_L_DB(6, start);
+	OP_L_DB(5, start);
+	OP_L_DB(4, start);
+	OP_L_DB(3, start);
+	OP_L_DB(2, start);
+	OP_L_DB(1, start);
+	OP_L_DB(0, start);
+
+	if(i & (1 << REG_POS(i,16))) {
+		if(i & bitList)
+			cpu->R[REG_POS(i,16)] = start;
+	}
+	else
+		cpu->R[REG_POS(i,16)] = start;
+
+	return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIA2(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 oldmode = 0;
+
+     u32 c = 0;
+
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 1;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IA(0, start);
+     OP_L_IA(1, start);
+     OP_L_IA(2, start);
+     OP_L_IA(3, start);
+     OP_L_IA(4, start);
+     OP_L_IA(5, start);
+     OP_L_IA(6, start);
+     OP_L_IA(7, start);
+     OP_L_IA(8, start);
+     OP_L_IA(9, start);
+     OP_L_IA(10, start);
+     OP_L_IA(11, start);
+     OP_L_IA(12, start);
+     OP_L_IA(13, start);
+     OP_L_IA(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          Status_Reg SPSR;
+          cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+          //start += 4;
+	      cpu->next_instruction = cpu->R[15];
+          c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+     }
+     else
+     {
+         armcpu_switchMode(cpu, oldmode);
+     }
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIB2(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 oldmode = 0;
+     u32 c = 0;
+
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+     //execute = false;
+	 LOG("Untested opcode: OP_LDMIB2");
+
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IB(0, start);
+     OP_L_IB(1, start);
+     OP_L_IB(2, start);
+     OP_L_IB(3, start);
+     OP_L_IB(4, start);
+     OP_L_IB(5, start);
+     OP_L_IB(6, start);
+     OP_L_IB(7, start);
+     OP_L_IB(8, start);
+     OP_L_IB(9, start);
+     OP_L_IB(10, start);
+     OP_L_IB(11, start);
+     OP_L_IB(12, start);
+     OP_L_IB(13, start);
+     OP_L_IB(14, start);
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          Status_Reg SPSR;
+          start += 4;
+          tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+	      cpu->next_instruction = registres[15];
+          c += waitState[(start>>24)&0xF];
+     }
+     else
+     {
+         armcpu_switchMode(cpu, oldmode);
+     }
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDA2(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     u32 oldmode = 0;
+     u32 c = 0;
+     u32 * registres;
+     u32 * waitState;
+
+     u32 start = cpu->R[REG_POS(i,16)];
+     //execute = false;
+	 LOG("Untested opcode: OP_LDMDA2");
+
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR = cpu->SPSR;
+          c += waitState[(start>>24)&0xF];
+          start -= 4;
+	      cpu->next_instruction = registres[15];
+     }
+
+     OP_L_DA(14, start);
+     OP_L_DA(13, start);
+     OP_L_DA(12, start);
+     OP_L_DA(11, start);
+     OP_L_DA(10, start);
+     OP_L_DA(9, start);
+     OP_L_DA(8, start);
+     OP_L_DA(7, start);
+     OP_L_DA(6, start);
+     OP_L_DA(5, start);
+     OP_L_DA(4, start);
+     OP_L_DA(3, start);
+     OP_L_DA(2, start);
+     OP_L_DA(1, start);
+     OP_L_DA(0, start);
+
+     if(BIT15(i)==0)
+     {
+          armcpu_switchMode(cpu, oldmode);
+     }
+     else
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+     }
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDB2(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+
+     u32 oldmode = 0;
+     u32 c = 0;
+     u32 * registres;
+     u32 * waitState;
+
+     u32 start = cpu->R[REG_POS(i,16)];
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          start -= 4;
+          tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR = cpu->SPSR;
+	      cpu->next_instruction = registres[15];
+          c += waitState[(start>>24)&0xF];
+     }
+
+     OP_L_DB(14, start);
+     OP_L_DB(13, start);
+     OP_L_DB(12, start);
+     OP_L_DB(11, start);
+     OP_L_DB(10, start);
+     OP_L_DB(9, start);
+     OP_L_DB(8, start);
+     OP_L_DB(7, start);
+     OP_L_DB(6, start);
+     OP_L_DB(5, start);
+     OP_L_DB(4, start);
+     OP_L_DB(3, start);
+     OP_L_DB(2, start);
+     OP_L_DB(1, start);
+     OP_L_DB(0, start);
+
+     if(BIT15(i)==0)
+     {
+          armcpu_switchMode(cpu, oldmode);
+     }
+     else
+     {
+          Status_Reg SPSR = cpu->SPSR;
+          armcpu_switchMode(cpu, SPSR.bits.mode);
+          cpu->CPSR=SPSR;
+     }
+
+     return 2 + c;
+}
+
+static u32 FASTCALL  OP_LDMIA2_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+
+     u32 oldmode = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+     u32 tmp;
+     Status_Reg SPSR;
+//     execute = false;
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IA(0, start);
+     OP_L_IA(1, start);
+     OP_L_IA(2, start);
+     OP_L_IA(3, start);
+     OP_L_IA(4, start);
+     OP_L_IA(5, start);
+     OP_L_IA(6, start);
+     OP_L_IA(7, start);
+     OP_L_IA(8, start);
+     OP_L_IA(9, start);
+     OP_L_IA(10, start);
+     OP_L_IA(11, start);
+     OP_L_IA(12, start);
+     OP_L_IA(13, start);
+     OP_L_IA(14, start);
+
+     if(BIT15(i)==0)
+     {
+          registres[REG_POS(i,16)] = start;
+          armcpu_switchMode(cpu, oldmode);
+          return c + 2;
+     }
+
+     registres[REG_POS(i,16)] = start + 4;
+     tmp = READ32(cpu->mem_if->data, start);
+     registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+     SPSR = cpu->SPSR;
+     armcpu_switchMode(cpu, SPSR.bits.mode);
+     cpu->CPSR=SPSR;
+     cpu->next_instruction = registres[15];
+     c += waitState[(start>>24)&0xF];
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMIB2_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+
+     u32 oldmode = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+     u32 tmp;
+     Status_Reg SPSR;
+
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     OP_L_IB(0, start);
+     OP_L_IB(1, start);
+     OP_L_IB(2, start);
+     OP_L_IB(3, start);
+     OP_L_IB(4, start);
+     OP_L_IB(5, start);
+     OP_L_IB(6, start);
+     OP_L_IB(7, start);
+     OP_L_IB(8, start);
+     OP_L_IB(9, start);
+     OP_L_IB(10, start);
+     OP_L_IB(11, start);
+     OP_L_IB(12, start);
+     OP_L_IB(13, start);
+     OP_L_IB(14, start);
+
+     if(BIT15(i)==0)
+     {
+          armcpu_switchMode(cpu, oldmode);
+          registres[REG_POS(i,16)] = start;
+
+          return c + 2;
+     }
+
+     registres[REG_POS(i,16)] = start + 4;
+     tmp = READ32(cpu->mem_if->data, start + 4);
+     registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+     cpu->CPSR = cpu->SPSR;
+     cpu->next_instruction = registres[15];
+     SPSR = cpu->SPSR;
+     armcpu_switchMode(cpu, SPSR.bits.mode);
+     cpu->CPSR=SPSR;
+     c += waitState[(start>>24)&0xF];
+
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDA2_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+
+     u32 oldmode = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+     Status_Reg SPSR;
+//     execute = false;
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp = READ32(cpu->mem_if->data, start);
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          c += waitState[(start>>24)&0xF];
+          start -= 4;
+          cpu->next_instruction = registres[15];
+     }
+
+     OP_L_DA(14, start);
+     OP_L_DA(13, start);
+     OP_L_DA(12, start);
+     OP_L_DA(11, start);
+     OP_L_DA(10, start);
+     OP_L_DA(9, start);
+     OP_L_DA(8, start);
+     OP_L_DA(7, start);
+     OP_L_DA(6, start);
+     OP_L_DA(5, start);
+     OP_L_DA(4, start);
+     OP_L_DA(3, start);
+     OP_L_DA(2, start);
+     OP_L_DA(1, start);
+     OP_L_DA(0, start);
+
+     registres[REG_POS(i,16)] = start;
+
+     if(BIT15(i)==0)
+     {
+          armcpu_switchMode(cpu, oldmode);
+          return c + 2;
+     }
+
+     SPSR = cpu->SPSR;
+     armcpu_switchMode(cpu, SPSR.bits.mode);
+     cpu->CPSR=SPSR;
+     return c + 2;
+}
+
+static u32 FASTCALL  OP_LDMDB2_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 c = 0;
+
+     u32 oldmode = 0;
+     u32 start = cpu->R[REG_POS(i,16)];
+     u32 * registres;
+     u32 * waitState;
+     Status_Reg SPSR;
+//     execute = false;
+     if(BIT15(i)==0)
+     {
+          if(cpu->CPSR.bits.mode==USR)
+               return 2;
+          oldmode = armcpu_switchMode(cpu, SYS);
+     }
+
+     registres = cpu->R;
+     waitState = MMU.MMU_WAIT32[cpu->proc_ID];
+
+     if(BIT15(i))
+     {
+          u32 tmp;
+          start -= 4;
+          tmp = READ32(cpu->mem_if->data, start);
+          c += waitState[(start>>24)&0xF];
+          registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1));
+          cpu->CPSR = cpu->SPSR;
+          cpu->next_instruction = registres[15];
+     }
+
+     OP_L_DB(14, start);
+     OP_L_DB(13, start);
+     OP_L_DB(12, start);
+     OP_L_DB(11, start);
+     OP_L_DB(10, start);
+     OP_L_DB(9, start);
+     OP_L_DB(8, start);
+     OP_L_DB(7, start);
+     OP_L_DB(6, start);
+     OP_L_DB(5, start);
+     OP_L_DB(4, start);
+     OP_L_DB(3, start);
+     OP_L_DB(2, start);
+     OP_L_DB(1, start);
+     OP_L_DB(0, start);
+
+     registres[REG_POS(i,16)] = start;
+
+     if(BIT15(i)==0)
+     {
+          armcpu_switchMode(cpu, oldmode);
+          return c + 2;
+     }
+
+     SPSR = cpu->SPSR;
+     armcpu_switchMode(cpu, SPSR.bits.mode);
+     cpu->CPSR=SPSR;
+     return c + 2;
+}
+
+//------------------------------STM----------------------------------
+
+static u32 FASTCALL  OP_STMIA(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start += 4;
+          }
+     }
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               start += 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDA(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start -= 4;
+          }
+     }
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               start -= 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIA_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start += 4;
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIB_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               start += 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+     cpu->R[REG_POS(i,16)] = start;
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDA_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start -= 4;
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDB_W(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction, c = 0, b;
+     u32 start = cpu->R[REG_POS(i,16)];
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               start -= 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIA2(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c = 0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_STMIA2");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start += 4;
+          }
+     }
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIB2(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c = 0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_STMIB2");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               start += 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDA2(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c = 0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_STMDA2");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start -= 4;
+          }
+     }
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDB2(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+     i = cpu->instruction;
+     c=0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               start -= 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIA2_W(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c=0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_STMIA2_W");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start += 4;
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMIB2_W(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+     i = cpu->instruction;
+     c=0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, b))
+          {
+               start += 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+     armcpu_switchMode(cpu, oldmode);
+     cpu->R[REG_POS(i,16)] = start;
+
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDA2_W(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c = 0;
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+     //execute = false;
+	 LOG("Untested opcode: OP_STMDA2_W");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+               start -= 4;
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+static u32 FASTCALL  OP_STMDB2_W(armcpu_t *cpu)
+{
+     u32 i, c, b;
+     u32 start;
+     u32 oldmode;
+
+     if(cpu->CPSR.bits.mode==USR)
+          return 2;
+
+     i = cpu->instruction;
+     c = 0;
+
+     start = cpu->R[REG_POS(i,16)];
+     oldmode = armcpu_switchMode(cpu, SYS);
+
+     //execute = false;
+	 LOG("Untested opcode: OP_STMDB2_W");
+
+     for(b=0; b<16; ++b)
+     {
+          if(BIT_N(i, 15-b))
+          {
+               start -= 4;
+               WRITE32(cpu->mem_if->data, start, cpu->R[15-b]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF];
+          }
+     }
+
+     cpu->R[REG_POS(i,16)] = start;
+
+     armcpu_switchMode(cpu, oldmode);
+     return c + 1;
+}
+
+/*
+ *
+ * The Enhanced DSP Extension LDRD and STRD instructions.
+ *
+ */
+static u32 FASTCALL
+OP_LDRD_STRD_POST_INDEX( armcpu_t *cpu) {
+  u32 i = cpu->instruction;
+  u32 Rd_num = REG_POS( i, 12);
+  u32 addr = cpu->R[REG_POS(i,16)];
+  u32 index;
+
+  /* I bit - immediate or register */
+  if ( BIT22(i))
+    index = IMM_OFF;
+  else
+    index = cpu->R[REG_POS(i,0)];
+
+  /* U bit - add or subtract */
+  if ( BIT23(i))
+    cpu->R[REG_POS(i,16)] += index;
+  else
+    cpu->R[REG_POS(i,16)] -= index;
+
+  if ( !(Rd_num & 0x1)) {
+    /* Store/Load */
+    if ( BIT5(i)) {
+      WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]);
+      WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]);
+    }
+    else {
+      cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr);
+      cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4);
+    }
+  }
+
+  return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2);
+}
+
+static u32 FASTCALL
+OP_LDRD_STRD_OFFSET_PRE_INDEX( armcpu_t *cpu) {
+  u32 i = cpu->instruction;
+  u32 Rd_num = REG_POS( i, 12);
+  u32 addr = cpu->R[REG_POS(i,16)];
+  u32 index;
+
+  /* I bit - immediate or register */
+  if ( BIT22(i))
+    index = IMM_OFF;
+  else
+    index = cpu->R[REG_POS(i,0)];
+
+  /* U bit - add or subtract */
+  if ( BIT23(i)) {
+    addr += index;
+
+    /* W bit - writeback */
+    if ( BIT21(i))
+      cpu->R[REG_POS(i,16)] = addr;
+  }
+  else {
+    addr -= index;
+
+    /* W bit - writeback */
+    if ( BIT21(i))
+      cpu->R[REG_POS(i,16)] = addr;
+  }
+
+  if ( !(Rd_num & 0x1)) {
+    /* Store/Load */
+    if ( BIT5(i)) {
+      WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]);
+      WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]);
+    }
+    else {
+      cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr);
+      cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4);
+    }
+  }
+
+  return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2);
+}
+
+
+
+//---------------------STC----------------------------------
+
+static u32 FASTCALL  OP_STC_P_IMM_OFF(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_M_IMM_OFF(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_P_PREIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_M_PREIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_P_POSTIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_M_POSTIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_STC_OPTION(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a STC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+//---------------------LDC----------------------------------
+
+static u32 FASTCALL  OP_LDC_P_IMM_OFF(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_M_IMM_OFF(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_P_PREIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_M_PREIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_P_POSTIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_M_POSTIND(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+static u32 FASTCALL  OP_LDC_OPTION(armcpu_t *cpu)
+{
+     {
+		/* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */
+          return 2;
+     }
+}
+
+//----------------MCR-----------------------
+
+static u32 FASTCALL  OP_MCR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 cpnum = REG_POS(i, 8);
+
+     if(!cpu->coproc[cpnum])
+     {
+          execute = false;
+          return 2;
+     }
+
+	  armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
+			  //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
+     return 2;
+}
+
+//----------------MRC-----------------------
+
+static u32 FASTCALL  OP_MRC(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 cpnum = REG_POS(i, 8);
+
+     if(!cpu->coproc[cpnum])
+     {
+          execute = false;
+          return 2;
+     }
+
+	  armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
+     //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7);
+     return 4;
+}
+
+//--------------SWI-------------------------------
+static u32 FASTCALL  OP_SWI(armcpu_t *cpu)
+{
+     if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
+     {
+        /* TODO (#1#): translocated SWI vectors */
+        /* we use an irq thats not in the irq tab, as
+           it was replaced duie to a changed intVector */
+        Status_Reg tmp = cpu->CPSR;
+        armcpu_switchMode(cpu, SVC);            /* enter svc mode */
+        cpu->R[14] = cpu->R[15] - 4;            /* jump to swi Vector */
+        cpu->SPSR = tmp;                        /* save old CPSR as new SPSR */
+        cpu->CPSR.bits.T = 0;                   /* handle as ARM32 code */
+        cpu->CPSR.bits.I = cpu->SPSR.bits.I;    /* keep int disable flag */
+        cpu->R[15] = cpu->intVector + 0x08;
+        cpu->next_instruction = cpu->R[15];
+        return 4;
+     }
+     else
+     {
+        u32 swinum = (cpu->instruction>>16)&0x1F;
+        return cpu->swi_tab[swinum](cpu) + 3;
+     }
+}
+
+//----------------BKPT-------------------------
+static u32 FASTCALL OP_BKPT(armcpu_t *cpu)
+{
+     execute = false;
+     return 4;
+}
+
+//----------------CDP-----------------------
+
+static u32 FASTCALL  OP_CDP(armcpu_t *cpu)
+{
+     execute = false;
+     return 4;
+}
+
+#define TYPE_RETOUR u32
+#define PARAMETRES  armcpu_t *cpu
+#define CALLTYPE    FASTCALL
+#define NOM_TAB     arm_instructions_set
+
+#include "instruction_tabdef.inc"
diff --git a/src/xsf/desmume/arm_instructions.h b/src/xsf/desmume/arm_instructions.h
index 350680aafc44..2d6461b675d7 100644
--- a/src/xsf/desmume/arm_instructions.h
+++ b/src/xsf/desmume/arm_instructions.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef ARMINSTRUCTION_H
diff --git a/src/xsf/desmume/armcpu.c b/src/xsf/desmume/armcpu.c
deleted file mode 100644
index a1760934a5c5..000000000000
--- a/src/xsf/desmume/armcpu.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "arm_instructions.h"
-#include "thumb_instructions.h"
-#include "cp15.h"
-#include "bios.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-const unsigned char arm_cond_table[16*16] = {
-    /* N=0, Z=0, C=0, V=0 */
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
-    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
-    /* N=0, Z=0, C=0, V=1 */
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=0, Z=0, C=1, V=0 */
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,
-    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
-    /* N=0, Z=0, C=1, V=1 */
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,
-    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=0, Z=1, C=0, V=0 */
-    0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
-    /* N=0, Z=1, C=0, V=1 */
-    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=0, Z=1, C=1, V=0 */
-    0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF,
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
-    /* N=0, Z=1, C=1, V=1 */
-    0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=0, C=0, V=0 */
-    0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=0, C=0, V=1 */
-    0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00,
-    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
-    /* N=1, Z=0, C=1, V=0 */
-    0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF,
-    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=0, C=1, V=1 */
-    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,
-    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
-    /* N=1, Z=1, C=0, V=0 */
-    0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=1, C=0, V=1 */
-    0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00,
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=1, C=1, V=0 */
-    0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF,
-    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
-    /* N=1, Z=1, C=1, V=1 */
-    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
-    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
-};
-
-armcpu_t NDS_ARM7;
-armcpu_t NDS_ARM9;
-
-#define SWAP(a, b, c) do      \
-	              {       \
-                         c=a; \
-                         a=b; \
-                         b=c; \
-		      }       \
-                      while(0)
-
-#ifdef GDB_STUB
-
-#define STALLED_CYCLE_COUNT 10
-
-static void
-stall_cpu( void *instance) {
-  armcpu_t *armcpu = (armcpu_t *)instance;
-
-  armcpu->stalled = 1;
-}
-                      
-static void
-unstall_cpu( void *instance) {
-  armcpu_t *armcpu = (armcpu_t *)instance;
-
-  armcpu->stalled = 0;
-}
-
-static void
-install_post_exec_fn( void *instance,
-                      void (*ex_fn)( void *, u32 adr, int thumb),
-                      void *fn_data) {
-  armcpu_t *armcpu = (armcpu_t *)instance;
-
-  armcpu->post_ex_fn = ex_fn;
-  armcpu->post_ex_fn_data = fn_data;
-}
-
-static void
-remove_post_exec_fn( void *instance) {
-  armcpu_t *armcpu = (armcpu_t *)instance;
-
-  armcpu->post_ex_fn = NULL;
-}
-#endif
-
-#ifdef GDB_STUB
-int armcpu_new( armcpu_t *armcpu, u32 id,
-                struct armcpu_memory_iface *mem_if,
-                struct armcpu_ctrl_iface **ctrl_iface_ret)
-#else
-int armcpu_new( armcpu_t *armcpu, u32 id)
-#endif
-{
-	armcpu->proc_ID = id;
-
-	if(id==0) 
-		armcpu->swi_tab = ARM9_swi_tab;
-	else 
-		armcpu->swi_tab = ARM7_swi_tab;
-
-#ifdef GDB_STUB
-	armcpu->mem_if = mem_if;
-
-	/* populate the control interface */
-	armcpu->ctrl_iface.stall = stall_cpu;
-	armcpu->ctrl_iface.unstall = unstall_cpu;
-	armcpu->ctrl_iface.read_reg = read_cpu_reg;
-	armcpu->ctrl_iface.set_reg = set_cpu_reg;
-	armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn;
-	armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn;
-	armcpu->ctrl_iface.data = armcpu;
-
-	*ctrl_iface_ret = &armcpu->ctrl_iface;
-
-	armcpu->stalled = 0;
-	armcpu->post_ex_fn = NULL;
-#endif
-
-	armcpu_init(armcpu, 0);
-
-	return 0;
-} 
-
-void armcpu_init(armcpu_t *armcpu, u32 adr)
-{
-   u32 i;
-
-	armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load
-	armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
-	armcpu->waitIRQ = FALSE;
-	armcpu->wirq = FALSE;
-
-#ifdef GDB_STUB
-    armcpu->irq_flag = 0;
-#endif
-
-	if(armcpu->coproc[15]) free(armcpu->coproc[15]);
-	
-   for(i = 0; i < 15; ++i)
-	{
-		armcpu->R[i] = 0;
-		armcpu->coproc[i] = NULL;
-   }
-	
-	armcpu->CPSR.val = armcpu->SPSR.val = SYS;
-	
-	armcpu->R13_usr = armcpu->R14_usr = 0;
-	armcpu->R13_svc = armcpu->R14_svc = 0;
-	armcpu->R13_abt = armcpu->R14_abt = 0;
-	armcpu->R13_und = armcpu->R14_und = 0;
-	armcpu->R13_irq = armcpu->R14_irq = 0;
-	armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
-	
-	armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
-
-#ifdef GDB_STUB
-    armcpu->instruct_adr = adr;
-	armcpu->R[15] = adr + 8;
-#else
-	armcpu->R[15] = adr;
-#endif
-
-	armcpu->next_instruction = adr;
-	
-	armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu);
-
-#ifndef GDB_STUB
-	armcpu_prefetch(armcpu);
-#endif
-}
-
-u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
-{
-        u32 oldmode = armcpu->CPSR.bits.mode;
-	
-	switch(oldmode)
-	{
-		case USR :
-		case SYS :
-			armcpu->R13_usr = armcpu->R[13];
-			armcpu->R14_usr = armcpu->R[14];
-			break;
-			
-		case FIQ :
-			{
-                                u32 tmp;
-				SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
-				SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
-				SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
-				SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
-				SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
-				armcpu->R13_fiq = armcpu->R[13];
-				armcpu->R14_fiq = armcpu->R[14];
-				armcpu->SPSR_fiq = armcpu->SPSR;
-				break;
-			}
-		case IRQ :
-			armcpu->R13_irq = armcpu->R[13];
-			armcpu->R14_irq = armcpu->R[14];
-			armcpu->SPSR_irq = armcpu->SPSR;
-			break;
-			
-		case SVC :
-			armcpu->R13_svc = armcpu->R[13];
-			armcpu->R14_svc = armcpu->R[14];
-			armcpu->SPSR_svc = armcpu->SPSR;
-			break;
-		
-		case ABT :
-			armcpu->R13_abt = armcpu->R[13];
-			armcpu->R14_abt = armcpu->R[14];
-			armcpu->SPSR_abt = armcpu->SPSR;
-			break;
-			
-		case UND :
-			armcpu->R13_und = armcpu->R[13];
-			armcpu->R14_und = armcpu->R[14];
-			armcpu->SPSR_und = armcpu->SPSR;
-			break;
-		default :
-			break;
-		}
-		
-		switch(mode)
-		{
-			case USR :
-			case SYS :
-				armcpu->R[13] = armcpu->R13_usr;
-				armcpu->R[14] = armcpu->R14_usr;
-				//SPSR = CPSR;
-				break;
-				
-			case FIQ :
-				{
-                                        u32 tmp;
-					SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
-					SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
-					SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
-					SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
-					SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
-					armcpu->R[13] = armcpu->R13_fiq;
-					armcpu->R[14] = armcpu->R14_fiq;
-					armcpu->SPSR = armcpu->SPSR_fiq;
-					break;
-				}
-				
-			case IRQ :
-				armcpu->R[13] = armcpu->R13_irq;
-				armcpu->R[14] = armcpu->R14_irq;
-				armcpu->SPSR = armcpu->SPSR_irq;
-				break;
-				
-			case SVC :
-				armcpu->R[13] = armcpu->R13_svc;
-				armcpu->R[14] = armcpu->R14_svc;
-				armcpu->SPSR = armcpu->SPSR_svc;
-				break;
-				
-			case ABT :
-				armcpu->R[13] = armcpu->R13_abt;
-				armcpu->R[14] = armcpu->R14_abt;
-				armcpu->SPSR = armcpu->SPSR_abt;
-				break;
-				
-          case UND :
-				armcpu->R[13] = armcpu->R13_und;
-				armcpu->R[14] = armcpu->R14_und;
-				armcpu->SPSR = armcpu->SPSR_und;
-				break;
-				
-				default :
-					break;
-	}
-	
-	armcpu->CPSR.bits.mode = mode & 0x1F;
-	return oldmode;
-}
-
-u32 armcpu_prefetch(armcpu_t *armcpu)
-{
-#ifdef GDB_STUB
-	u32 temp_instruction;
-#endif
-
-	if(armcpu->CPSR.bits.T == 0)
-	{
-#ifdef GDB_STUB
-		temp_instruction =
-			armcpu->mem_if->prefetch32( armcpu->mem_if->data,
-			armcpu->next_instruction);
-
-		if ( !armcpu->stalled) {
-			armcpu->instruction = temp_instruction;
-			armcpu->instruct_adr = armcpu->next_instruction;
-			armcpu->next_instruction += 4;
-			armcpu->R[15] = armcpu->next_instruction + 4;
-		}
-#else
-		armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
-
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction += 4;
-		armcpu->R[15] = armcpu->next_instruction + 4;
-#endif
-          
-        return MMU.MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
-	}
-
-#ifdef GDB_STUB
-	temp_instruction =
-          armcpu->mem_if->prefetch16( armcpu->mem_if->data,
-                                      armcpu->next_instruction);
-
-	if ( !armcpu->stalled) {
-		armcpu->instruction = temp_instruction;
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction = armcpu->next_instruction + 2;
-		armcpu->R[15] = armcpu->next_instruction + 2;
-	}
-#else
-	armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
-
-	armcpu->instruct_adr = armcpu->next_instruction;
-	armcpu->next_instruction += 2;
-	armcpu->R[15] = armcpu->next_instruction + 2;
-#endif
-
-	return MMU.MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
-}
- 
-
-BOOL armcpu_irqExeption(armcpu_t *armcpu)
-{
-    Status_Reg tmp;
-
-	if(armcpu->CPSR.bits.I) return FALSE;
-
-#ifdef GDB_STUB
-	armcpu->irq_flag = 0;
-#endif
-      
-	tmp = armcpu->CPSR;
-	armcpu_switchMode(armcpu, IRQ);
-
-#ifdef GDB_STUB
-	armcpu->R[14] = armcpu->next_instruction + 4;
-#else
-	armcpu->R[14] = armcpu->instruct_adr + 4;
-#endif
-	armcpu->SPSR = tmp;
-	armcpu->CPSR.bits.T = 0;
-	armcpu->CPSR.bits.I = 1;
-	armcpu->next_instruction = armcpu->intVector + 0x18;
-	armcpu->waitIRQ = 0;
-
-#ifndef GDB_STUB
-	armcpu->R[15] = armcpu->next_instruction + 8;
-	armcpu_prefetch(armcpu);
-#endif
-
-	return TRUE;
-}
-/*
-static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
-{
-        Status_Reg tmp;
-	if(armcpu->CPSR.bits.I) return FALSE;
-        tmp = armcpu->CPSR;
-	armcpu_switchMode(armcpu, ABT);
-	armcpu->R[14] = armcpu->next_instruction + 4;
-	armcpu->SPSR = tmp;
-	armcpu->CPSR.bits.T = 0;
-	armcpu->CPSR.bits.I = 1;
-	armcpu->next_instruction = armcpu->intVector + 0xC;
-	armcpu->R[15] = armcpu->next_instruction + 8;
-	armcpu->waitIRQ = 0;
-	return TRUE;
-}
-*/
-
-BOOL
-armcpu_flagIrq( armcpu_t *armcpu) {
-  if(armcpu->CPSR.bits.I) return FALSE;
-
-  armcpu->waitIRQ = 0;
-
-#ifdef GDB_STUB
-  armcpu->irq_flag = 1;
-#endif
-
-  return TRUE;
-}
-
-
-u32 armcpu_exec(armcpu_t *armcpu)
-{
-        u32 c = 1;
-
-#ifdef GDB_STUB
-        if ( armcpu->stalled)
-          return STALLED_CYCLE_COUNT;
-
-        /* check for interrupts */
-        if ( armcpu->irq_flag) {
-          armcpu_irqExeption( armcpu);
-        }
-
-        c = armcpu_prefetch(armcpu);
-
-        if ( armcpu->stalled) {
-          return c;
-        }
-#endif
-
-	if(armcpu->CPSR.bits.T == 0)
-	{
-/*        if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/
-        if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR)))
-		{
-			c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu);
-		}
-#ifdef GDB_STUB
-        if ( armcpu->post_ex_fn != NULL) {
-            /* call the external post execute function */
-            armcpu->post_ex_fn( armcpu->post_ex_fn_data,
-                                armcpu->instruct_adr, 0);
-        }
-#else
-		c += armcpu_prefetch(armcpu);
-#endif
-		return c;
-	}
-
-	c += thumb_instructions_set[armcpu->instruction>>6](armcpu);
-
-#ifdef GDB_STUB
-    if ( armcpu->post_ex_fn != NULL) {
-        /* call the external post execute function */
-        armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1);
-    }
-#else
-	c += armcpu_prefetch(armcpu);
-#endif
-	return c;
-}
-
diff --git a/src/xsf/desmume/armcpu.cc b/src/xsf/desmume/armcpu.cc
new file mode 100644
index 000000000000..09356fea0598
--- /dev/null
+++ b/src/xsf/desmume/armcpu.cc
@@ -0,0 +1,487 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "arm_instructions.h"
+#include "thumb_instructions.h"
+#include "cp15.h"
+#include "bios.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+const unsigned char arm_cond_table[16*16] = {
+    /* N=0, Z=0, C=0, V=0 */
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
+    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
+    /* N=0, Z=0, C=0, V=1 */
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=0, Z=0, C=1, V=0 */
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF,
+    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
+    /* N=0, Z=0, C=1, V=1 */
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,
+    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=0, Z=1, C=0, V=0 */
+    0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF,
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
+    /* N=0, Z=1, C=0, V=1 */
+    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=0, Z=1, C=1, V=0 */
+    0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF,
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
+    /* N=0, Z=1, C=1, V=1 */
+    0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=0, C=0, V=0 */
+    0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=0, C=0, V=1 */
+    0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00,
+    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
+    /* N=1, Z=0, C=1, V=0 */
+    0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF,
+    0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=0, C=1, V=1 */
+    0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,
+    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
+    /* N=1, Z=1, C=0, V=0 */
+    0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=1, C=0, V=1 */
+    0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00,
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=1, C=1, V=0 */
+    0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF,
+    0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
+    /* N=1, Z=1, C=1, V=1 */
+    0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
+    0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
+};
+
+armcpu_t NDS_ARM7;
+armcpu_t NDS_ARM9;
+
+#define SWAP(a, b, c) do      \
+	              {       \
+                         c=a; \
+                         a=b; \
+                         b=c; \
+		      }       \
+                      while(0)
+
+#ifdef GDB_STUB
+
+#define STALLED_CYCLE_COUNT 10
+
+static void
+stall_cpu( void *instance) {
+  armcpu_t *armcpu = (armcpu_t *)instance;
+
+  armcpu->stalled = 1;
+}
+
+static void
+unstall_cpu( void *instance) {
+  armcpu_t *armcpu = (armcpu_t *)instance;
+
+  armcpu->stalled = 0;
+}
+
+static void
+install_post_exec_fn( void *instance,
+                      void (*ex_fn)( void *, u32 adr, int thumb),
+                      void *fn_data) {
+  armcpu_t *armcpu = (armcpu_t *)instance;
+
+  armcpu->post_ex_fn = ex_fn;
+  armcpu->post_ex_fn_data = fn_data;
+}
+
+static void
+remove_post_exec_fn( void *instance) {
+  armcpu_t *armcpu = (armcpu_t *)instance;
+
+  armcpu->post_ex_fn = nullptr;
+}
+#endif
+
+#ifdef GDB_STUB
+int armcpu_new( armcpu_t *armcpu, u32 id,
+                struct armcpu_memory_iface *mem_if,
+                struct armcpu_ctrl_iface **ctrl_iface_ret)
+#else
+int armcpu_new( armcpu_t *armcpu, u32 id)
+#endif
+{
+	armcpu->proc_ID = id;
+
+	if(id==0)
+		armcpu->swi_tab = ARM9_swi_tab;
+	else
+		armcpu->swi_tab = ARM7_swi_tab;
+
+#ifdef GDB_STUB
+	armcpu->mem_if = mem_if;
+
+	/* populate the control interface */
+	armcpu->ctrl_iface.stall = stall_cpu;
+	armcpu->ctrl_iface.unstall = unstall_cpu;
+	armcpu->ctrl_iface.read_reg = read_cpu_reg;
+	armcpu->ctrl_iface.set_reg = set_cpu_reg;
+	armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn;
+	armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn;
+	armcpu->ctrl_iface.data = armcpu;
+
+	*ctrl_iface_ret = &armcpu->ctrl_iface;
+
+	armcpu->stalled = 0;
+	armcpu->post_ex_fn = nullptr;
+#endif
+
+	armcpu_init(armcpu, 0);
+
+	return 0;
+}
+
+void armcpu_init(armcpu_t *armcpu, u32 adr)
+{
+   u32 i;
+
+	armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load
+	armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
+	armcpu->waitIRQ = false;
+	armcpu->wirq = false;
+
+#ifdef GDB_STUB
+    armcpu->irq_flag = 0;
+#endif
+
+	if(armcpu->coproc[15]) free(armcpu->coproc[15]);
+
+   for(i = 0; i < 15; ++i)
+	{
+		armcpu->R[i] = 0;
+		armcpu->coproc[i] = nullptr;
+   }
+
+	armcpu->CPSR.val = armcpu->SPSR.val = SYS;
+
+	armcpu->R13_usr = armcpu->R14_usr = 0;
+	armcpu->R13_svc = armcpu->R14_svc = 0;
+	armcpu->R13_abt = armcpu->R14_abt = 0;
+	armcpu->R13_und = armcpu->R14_und = 0;
+	armcpu->R13_irq = armcpu->R14_irq = 0;
+	armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
+
+	armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
+
+#ifdef GDB_STUB
+    armcpu->instruct_adr = adr;
+	armcpu->R[15] = adr + 8;
+#else
+	armcpu->R[15] = adr;
+#endif
+
+	armcpu->next_instruction = adr;
+
+	armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu);
+
+#ifndef GDB_STUB
+	armcpu_prefetch(armcpu);
+#endif
+}
+
+u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
+{
+        u32 oldmode = armcpu->CPSR.bits.mode;
+
+	switch(oldmode)
+	{
+		case USR :
+		case SYS :
+			armcpu->R13_usr = armcpu->R[13];
+			armcpu->R14_usr = armcpu->R[14];
+			break;
+
+		case FIQ :
+			{
+                                u32 tmp;
+				SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
+				SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
+				SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
+				SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
+				SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
+				armcpu->R13_fiq = armcpu->R[13];
+				armcpu->R14_fiq = armcpu->R[14];
+				armcpu->SPSR_fiq = armcpu->SPSR;
+				break;
+			}
+		case IRQ :
+			armcpu->R13_irq = armcpu->R[13];
+			armcpu->R14_irq = armcpu->R[14];
+			armcpu->SPSR_irq = armcpu->SPSR;
+			break;
+
+		case SVC :
+			armcpu->R13_svc = armcpu->R[13];
+			armcpu->R14_svc = armcpu->R[14];
+			armcpu->SPSR_svc = armcpu->SPSR;
+			break;
+
+		case ABT :
+			armcpu->R13_abt = armcpu->R[13];
+			armcpu->R14_abt = armcpu->R[14];
+			armcpu->SPSR_abt = armcpu->SPSR;
+			break;
+
+		case UND :
+			armcpu->R13_und = armcpu->R[13];
+			armcpu->R14_und = armcpu->R[14];
+			armcpu->SPSR_und = armcpu->SPSR;
+			break;
+		default :
+			break;
+		}
+
+		switch(mode)
+		{
+			case USR :
+			case SYS :
+				armcpu->R[13] = armcpu->R13_usr;
+				armcpu->R[14] = armcpu->R14_usr;
+				//SPSR = CPSR;
+				break;
+
+			case FIQ :
+				{
+                                        u32 tmp;
+					SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
+					SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
+					SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
+					SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
+					SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
+					armcpu->R[13] = armcpu->R13_fiq;
+					armcpu->R[14] = armcpu->R14_fiq;
+					armcpu->SPSR = armcpu->SPSR_fiq;
+					break;
+				}
+
+			case IRQ :
+				armcpu->R[13] = armcpu->R13_irq;
+				armcpu->R[14] = armcpu->R14_irq;
+				armcpu->SPSR = armcpu->SPSR_irq;
+				break;
+
+			case SVC :
+				armcpu->R[13] = armcpu->R13_svc;
+				armcpu->R[14] = armcpu->R14_svc;
+				armcpu->SPSR = armcpu->SPSR_svc;
+				break;
+
+			case ABT :
+				armcpu->R[13] = armcpu->R13_abt;
+				armcpu->R[14] = armcpu->R14_abt;
+				armcpu->SPSR = armcpu->SPSR_abt;
+				break;
+
+          case UND :
+				armcpu->R[13] = armcpu->R13_und;
+				armcpu->R[14] = armcpu->R14_und;
+				armcpu->SPSR = armcpu->SPSR_und;
+				break;
+
+				default :
+					break;
+	}
+
+	armcpu->CPSR.bits.mode = mode & 0x1F;
+	return oldmode;
+}
+
+u32 armcpu_prefetch(armcpu_t *armcpu)
+{
+#ifdef GDB_STUB
+	u32 temp_instruction;
+#endif
+
+	if(armcpu->CPSR.bits.T == 0)
+	{
+#ifdef GDB_STUB
+		temp_instruction =
+			armcpu->mem_if->prefetch32( armcpu->mem_if->data,
+			armcpu->next_instruction);
+
+		if ( !armcpu->stalled) {
+			armcpu->instruction = temp_instruction;
+			armcpu->instruct_adr = armcpu->next_instruction;
+			armcpu->next_instruction += 4;
+			armcpu->R[15] = armcpu->next_instruction + 4;
+		}
+#else
+		armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
+
+		armcpu->instruct_adr = armcpu->next_instruction;
+		armcpu->next_instruction += 4;
+		armcpu->R[15] = armcpu->next_instruction + 4;
+#endif
+
+        return MMU.MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
+	}
+
+#ifdef GDB_STUB
+	temp_instruction =
+          armcpu->mem_if->prefetch16( armcpu->mem_if->data,
+                                      armcpu->next_instruction);
+
+	if ( !armcpu->stalled) {
+		armcpu->instruction = temp_instruction;
+		armcpu->instruct_adr = armcpu->next_instruction;
+		armcpu->next_instruction = armcpu->next_instruction + 2;
+		armcpu->R[15] = armcpu->next_instruction + 2;
+	}
+#else
+	armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
+
+	armcpu->instruct_adr = armcpu->next_instruction;
+	armcpu->next_instruction += 2;
+	armcpu->R[15] = armcpu->next_instruction + 2;
+#endif
+
+	return MMU.MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF];
+}
+
+
+BOOL armcpu_irqExeption(armcpu_t *armcpu)
+{
+    Status_Reg tmp;
+
+	if(armcpu->CPSR.bits.I) return false;
+
+#ifdef GDB_STUB
+	armcpu->irq_flag = 0;
+#endif
+
+	tmp = armcpu->CPSR;
+	armcpu_switchMode(armcpu, IRQ);
+
+#ifdef GDB_STUB
+	armcpu->R[14] = armcpu->next_instruction + 4;
+#else
+	armcpu->R[14] = armcpu->instruct_adr + 4;
+#endif
+	armcpu->SPSR = tmp;
+	armcpu->CPSR.bits.T = 0;
+	armcpu->CPSR.bits.I = 1;
+	armcpu->next_instruction = armcpu->intVector + 0x18;
+	armcpu->waitIRQ = 0;
+
+#ifndef GDB_STUB
+	armcpu->R[15] = armcpu->next_instruction + 8;
+	armcpu_prefetch(armcpu);
+#endif
+
+	return true;
+}
+/*
+static BOOL armcpu_prefetchExeption(armcpu_t *armcpu)
+{
+        Status_Reg tmp;
+	if(armcpu->CPSR.bits.I) return false;
+        tmp = armcpu->CPSR;
+	armcpu_switchMode(armcpu, ABT);
+	armcpu->R[14] = armcpu->next_instruction + 4;
+	armcpu->SPSR = tmp;
+	armcpu->CPSR.bits.T = 0;
+	armcpu->CPSR.bits.I = 1;
+	armcpu->next_instruction = armcpu->intVector + 0xC;
+	armcpu->R[15] = armcpu->next_instruction + 8;
+	armcpu->waitIRQ = 0;
+	return true;
+}
+*/
+
+BOOL
+armcpu_flagIrq( armcpu_t *armcpu) {
+  if(armcpu->CPSR.bits.I) return false;
+
+  armcpu->waitIRQ = 0;
+
+#ifdef GDB_STUB
+  armcpu->irq_flag = 1;
+#endif
+
+  return true;
+}
+
+
+u32 armcpu_exec(armcpu_t *armcpu)
+{
+        u32 c = 1;
+
+#ifdef GDB_STUB
+        if ( armcpu->stalled)
+          return STALLED_CYCLE_COUNT;
+
+        /* check for interrupts */
+        if ( armcpu->irq_flag) {
+          armcpu_irqExeption( armcpu);
+        }
+
+        c = armcpu_prefetch(armcpu);
+
+        if ( armcpu->stalled) {
+          return c;
+        }
+#endif
+
+	if(armcpu->CPSR.bits.T == 0)
+	{
+/*        if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/
+        if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR)))
+		{
+			c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu);
+		}
+#ifdef GDB_STUB
+        if ( armcpu->post_ex_fn != nullptr) {
+            /* call the external post execute function */
+            armcpu->post_ex_fn( armcpu->post_ex_fn_data,
+                                armcpu->instruct_adr, 0);
+        }
+#else
+		c += armcpu_prefetch(armcpu);
+#endif
+		return c;
+	}
+
+	c += thumb_instructions_set[armcpu->instruction>>6](armcpu);
+
+#ifdef GDB_STUB
+    if ( armcpu->post_ex_fn != nullptr) {
+        /* call the external post execute function */
+        armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1);
+    }
+#else
+	c += armcpu_prefetch(armcpu);
+#endif
+	return c;
+}
+
diff --git a/src/xsf/desmume/armcpu.h b/src/xsf/desmume/armcpu.h
index 7fa3ef9b4fbd..4b91f9d62de9 100644
--- a/src/xsf/desmume/armcpu.h
+++ b/src/xsf/desmume/armcpu.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef ARM_CPU
@@ -26,10 +26,6 @@
 #include "bits.h"
 #include "MMU.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define ARMCPU_ARM7 1
 #define ARMCPU_ARM9 0
 
@@ -249,8 +245,8 @@ static INLINE void NDS_makeARM9Int(u32 num)
         /* generate the interrupt if enabled */
 	if ((MMU.reg_IE[0] & (1 << num)) && MMU.reg_IME[0])
 	{
-		NDS_ARM9.wIRQ = TRUE;
-		NDS_ARM9.waitIRQ = FALSE;
+		NDS_ARM9.wIRQ = true;
+		NDS_ARM9.waitIRQ = false;
 	}
 }
 
@@ -262,8 +258,8 @@ static INLINE void NDS_makeARM7Int(u32 num)
         /* generate the interrupt if enabled */
 	if ((MMU.reg_IE[1] & (1 << num)) && MMU.reg_IME[1])
 	{
-		NDS_ARM7.wIRQ = TRUE;
-		NDS_ARM7.waitIRQ = FALSE;
+		NDS_ARM7.wIRQ = true;
+		NDS_ARM7.waitIRQ = false;
 	}
 }
 
@@ -280,9 +276,4 @@ static INLINE void NDS_makeInt(u8 proc_ID,u32 num)
 	}
 }
 
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/src/xsf/desmume/bios.c b/src/xsf/desmume/bios.c
deleted file mode 100644
index 87114043877e..000000000000
--- a/src/xsf/desmume/bios.c
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "cp15.h"
-#include <math.h>
-#include "MMU.h"
-#include "SPU.h"
-#include "debug.h"
-
-extern BOOL execute;
-
-static u16 getsinetbl[] = {
-0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2, 
-0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11, 
-0x30FB, 0x33DF, 0x36BA, 0x398C, 0x3C56, 0x3F17, 0x41CE, 0x447A, 
-0x471C, 0x49B4, 0x4C3F, 0x4EBF, 0x5133, 0x539B, 0x55F5, 0x5842, 
-0x5A82, 0x5CB3, 0x5ED7, 0x60EB, 0x62F1, 0x64E8, 0x66CF, 0x68A6, 
-0x6A6D, 0x6C23, 0x6DC9, 0x6F5E, 0x70E2, 0x7254, 0x73B5, 0x7504, 
-0x7641, 0x776B, 0x7884, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE3, 
-0x7D89, 0x7E1D, 0x7E9C, 0x7F09, 0x7F61, 0x7FA6, 0x7FD8, 0x7FF5
-};
-
-static u16 getpitchtbl[] = {
-0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F, 
-0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D, 
-0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F, 
-0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743, 
-0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C, 
-0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18, 
-0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07, 
-0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA, 
-0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1, 
-0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB, 
-0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9, 
-0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB, 
-0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0, 
-0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA, 
-0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07, 
-0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17, 
-0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C, 
-0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344, 
-0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561, 
-0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781, 
-0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5, 
-0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD, 
-0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9, 
-0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A, 
-0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E, 
-0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496, 
-0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3, 
-0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913, 
-0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58, 
-0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1, 
-0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE, 
-0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240, 
-0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495, 
-0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0, 
-0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E, 
-0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1, 
-0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18, 
-0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084, 
-0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4, 
-0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569, 
-0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2, 
-0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60, 
-0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3, 
-0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A, 
-0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6, 
-0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487, 
-0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C, 
-0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6, 
-0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55, 
-0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9, 
-0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2, 
-0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450, 
-0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702, 
-0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA, 
-0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77, 
-0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38, 
-0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF, 
-0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB, 
-0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D, 
-0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73, 
-0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F, 
-0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030, 
-0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316, 
-0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602, 
-0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3, 
-0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA, 
-0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6, 
-0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8, 
-0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF, 
-0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC, 
-0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E, 
-0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27, 
-0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145, 
-0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468, 
-0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792, 
-0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1, 
-0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7, 
-0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132, 
-0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473, 
-0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB, 
-0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08, 
-0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B, 
-0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5, 
-0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515, 
-0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B, 
-0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8, 
-0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B, 
-0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4, 
-0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654, 
-0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA, 
-0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66, 
-0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA, 
-0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494, 
-0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834, 
-0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC, 
-0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A
-};
-
-static u8 getvoltbl[] = {
-0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 
-0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
-0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
-0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 
-0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 
-0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 
-0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 
-0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 
-0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 
-0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 
-0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 
-0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29, 
-0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31, 
-0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, 
-0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, 
-0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55, 
-0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 
-0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B, 
-0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 
-0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 
-0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36, 
-0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40, 
-0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D, 
-0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 
-0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70, 
-0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43, 
-0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 
-0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 
-0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75, 
-0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, 
-0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 
-0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, 
-0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 
-0x7C, 0x7D, 0x7E, 0x7F
-};
-
-u32 bios_nop(armcpu_t * cpu)
-{
-     if (cpu->proc_ID == ARMCPU_ARM9)
-     {
-        LOG("Unimplemented bios function %02X(ARM9) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]);
-     }
-     else
-     {
-        LOG("Unimplemented bios function %02X(ARM7) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]);
-     }
-     return 3;
-}
-
-u32 delayLoop(armcpu_t * cpu)
-{
-     return cpu->R[0] * 4;
-}
-
-//u32 oldmode[2];
-
-u32 intrWaitARM(armcpu_t * cpu)
-{
-     u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
-     u32 intr;
-     u32 intrFlag = 0;
-     
-     //execute = FALSE;
-     if(cpu->proc_ID) 
-     {
-      intrFlagAdr = 0x380FFF8;
-     } else {
-      intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
-     }
-     intr = MMU_read32(cpu->proc_ID, intrFlagAdr);
-     intrFlag = cpu->R[1] & intr;
-     
-     if(intrFlag)
-     {
-          // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s)
-          // on efface son(les) occurence(s).
-          intr ^= intrFlag;
-          MMU_write32(cpu->proc_ID, intrFlagAdr, intr);
-          //cpu->switchMode(oldmode[cpu->proc_ID]);
-          return 1;
-     }
-         
-     cpu->R[15] = cpu->instruct_adr;
-     cpu->next_instruction = cpu->R[15];
-     cpu->waitIRQ = 1;
-     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
-
-     return 1;
-}
-
-u32 waitVBlankARM(armcpu_t * cpu)
-{
-     u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
-     u32 intr;
-     u32 intrFlag = 0;
-     
-     //execute = FALSE;
-     if(cpu->proc_ID) 
-     {
-      intrFlagAdr = 0x380FFF8;
-     } else {
-      intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
-     }
-     intr = MMU_read32(cpu->proc_ID, intrFlagAdr);
-     intrFlag = 1 & intr;
-     
-     if(intrFlag)
-     {
-          // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s)
-          // on efface son(les) occurence(s).
-          intr ^= intrFlag;
-          MMU_write32(cpu->proc_ID, intrFlagAdr, intr);
-          //cpu->switchMode(oldmode[cpu->proc_ID]);
-          return 1;
-     }
-         
-     cpu->R[15] = cpu->instruct_adr;
-     cpu->next_instruction = cpu->R[15];
-     cpu->waitIRQ = 1;
-     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
-
-     return 1;
-}
-
-u32 wait4IRQ(armcpu_t* cpu)
-{
-     //execute= FALSE;
-     if(cpu->wirq)
-     {
-          if(!cpu->waitIRQ)
-          {
-               cpu->waitIRQ = 0;
-               cpu->wirq = 0;
-               //cpu->switchMode(oldmode[cpu->proc_ID]);
-               return 1;
-          }
-          cpu->R[15] = cpu->instruct_adr;
-          cpu->next_instruction = cpu->R[15];
-          return 1;
-     }
-     cpu->waitIRQ = 1;
-     cpu->wirq = 1;
-     cpu->R[15] = cpu->instruct_adr;
-     cpu->next_instruction = cpu->R[15];
-     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
-     return 1;
-}
-
-u32 devide(armcpu_t* cpu)
-{
-     s32 num = (s32)cpu->R[0];
-     s32 dnum = (s32)cpu->R[1];
-     
-     if(dnum==0) return 0;
-     
-     cpu->R[0] = (u32)(num / dnum);
-     cpu->R[1] = (u32)(num % dnum);
-     cpu->R[3] = (u32) (((s32)cpu->R[0])<0 ? -cpu->R[0] : cpu->R[0]);
-     
-     return 6;
-}
-
-u32 copy(armcpu_t* cpu)
-{
-     u32 src = cpu->R[0];
-     u32 dst = cpu->R[1];
-     u32 cnt = cpu->R[2];
-
-     switch(BIT26(cnt))
-     {
-          case 0:
-               src &= 0xFFFFFFFE;
-               dst &= 0xFFFFFFFE;
-               switch(BIT24(cnt))
-               {
-                    case 0:
-                         cnt &= 0x1FFFFF;
-                         while(cnt)
-                         {
-                              MMU_write16(cpu->proc_ID, dst, MMU_read16(cpu->proc_ID, src));
-                              cnt--;
-                              dst+=2;
-                              src+=2;
-                         }
-                         break;
-                    case 1:
-                         {
-                              u32 val = MMU_read16(cpu->proc_ID, src);
-                              cnt &= 0x1FFFFF;
-                              while(cnt)
-                              {
-                                   MMU_write16(cpu->proc_ID, dst, val);
-                                   cnt--;
-                                   dst+=2;
-                              }
-                         }
-                         break;
-               }
-               break;
-          case 1:
-               src &= 0xFFFFFFFC;
-               dst &= 0xFFFFFFFC;
-               switch(BIT24(cnt))
-               {
-                    case 0:
-                         cnt &= 0x1FFFFF;
-                         while(cnt)
-                         {
-                              MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src));
-                              cnt--;
-                              dst+=4;
-                              src+=4;
-                         }
-                         break;
-                    case 1:
-                         {
-                              u32 val = MMU_read32(cpu->proc_ID, src);
-                              cnt &= 0x1FFFFF;
-                              while(cnt)
-                              {
-                                   MMU_write32(cpu->proc_ID, dst, val);
-                                   cnt--;
-                                   dst+=4;
-                              }
-                         }
-                         break;
-               }
-               break;
-     }
-     return 1;
-}
-
-u32 fastCopy(armcpu_t* cpu)
-{
-     u32 src = cpu->R[0] & 0xFFFFFFFC;
-     u32 dst = cpu->R[1] & 0xFFFFFFFC;
-     u32 cnt = cpu->R[2];
-
-     switch(BIT24(cnt))
-     {
-          case 0:
-               cnt &= 0x1FFFFF;
-               while(cnt)
-               {
-                    MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src));
-                    cnt--;
-                    dst+=4;
-                    src+=4;
-               }
-               break;
-          case 1:
-               {
-                    u32 val = MMU_read32(cpu->proc_ID, src);
-                    cnt &= 0x1FFFFF;
-                    while(cnt)
-                    {
-                         MMU_write32(cpu->proc_ID, dst, val);
-                         cnt--;
-                         dst+=4;
-                    }
-               }
-               break;
-     }
-     return 1;
-}
-
-u32 LZ77UnCompVram(armcpu_t* cpu)
-{
-  int i1, i2;
-  int byteCount;
-  int byteShift;
-  u32 writeValue;
-  int len;
-  u32 source = cpu->R[0];
-  u32 dest = cpu->R[1];
-  u32 header = MMU_read32(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;    
-
-  byteCount = 0;
-  byteShift = 0;
-  writeValue = 0;
-
-  len = header >> 8;
-
-  while(len > 0) {
-    u8 d = MMU_read8(cpu->proc_ID, source++);
-
-    if(d) {
-      for(i1 = 0; i1 < 8; i1++) {
-        if(d & 0x80) {
-          int length;
-          int offset;
-          u32 windowOffset;
-          u16 data = MMU_read8(cpu->proc_ID, source++) << 8;
-          data |= MMU_read8(cpu->proc_ID, source++);
-          length = (data >> 12) + 3;
-          offset = (data & 0x0FFF);
-          windowOffset = dest + byteCount - offset - 1;
-          for(i2 = 0; i2 < length; i2++) {
-            writeValue |= (MMU_read8(cpu->proc_ID, windowOffset++) << byteShift);
-            byteShift += 8;
-            byteCount++;
-
-            if(byteCount == 2) {
-              MMU_write16(cpu->proc_ID, dest, writeValue);
-              dest += 2;
-              byteCount = 0;
-              byteShift = 0;
-              writeValue = 0;
-            }
-            len--;
-            if(len == 0)
-              return 0;
-          }
-        } else {
-          writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
-          byteShift += 8;
-          byteCount++;
-          if(byteCount == 2) {
-            MMU_write16(cpu->proc_ID, dest, writeValue);
-            dest += 2;
-            byteCount = 0;
-            byteShift = 0;
-            writeValue = 0;
-          }
-          len--;
-          if(len == 0)
-            return 0;
-        }
-        d <<= 1;
-      }
-    } else {
-      for(i1 = 0; i1 < 8; i1++) {
-        writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
-        byteShift += 8;
-        byteCount++;
-        if(byteCount == 2) {
-          MMU_write16(cpu->proc_ID, dest, writeValue);
-          dest += 2;      
-          byteShift = 0;
-          byteCount = 0;
-          writeValue = 0;
-        }
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    }
-  }
-  return 1;
-}
-
-u32 LZ77UnCompWram(armcpu_t* cpu)
-{
-  int i1, i2;
-  int len;
-  u32 source = cpu->R[0];
-  u32 dest = cpu->R[1];
-
-  u32 header = MMU_read32(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;  
-  
-  len = header >> 8;
-
-  while(len > 0) {
-    u8 d = MMU_read8(cpu->proc_ID, source++);
-
-    if(d) {
-      for(i1 = 0; i1 < 8; i1++) {
-        if(d & 0x80) {
-          int length;
-          int offset;
-          u32 windowOffset;
-          u16 data = MMU_read8(cpu->proc_ID, source++) << 8;
-          data |= MMU_read8(cpu->proc_ID, source++);
-          length = (data >> 12) + 3;
-          offset = (data & 0x0FFF);
-          windowOffset = dest - offset - 1;
-          for(i2 = 0; i2 < length; i2++) {
-            MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, windowOffset++));
-            len--;
-            if(len == 0)
-              return 0;
-          }
-        } else {
-          MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++));
-          len--;
-          if(len == 0)
-            return 0;
-        }
-        d <<= 1;
-      }
-    } else {
-      for(i1 = 0; i1 < 8; i1++) {
-        MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++));
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    }
-  }
-  return 1;
-}
-
-u32 RLUnCompVram(armcpu_t* cpu)
-{
-  int i;
-  int len;
-  int byteCount;
-  int byteShift;
-  u32 writeValue;
-  u32 source = cpu->R[0];
-  u32 dest = cpu->R[1];
-
-  u32 header = MMU_read32(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;  
-  
-  len = header >> 8;
-  byteCount = 0;
-  byteShift = 0;
-  writeValue = 0;
-
-  while(len > 0) {
-    u8 d = MMU_read8(cpu->proc_ID, source++);
-    int l = d & 0x7F;
-    if(d & 0x80) {
-      u8 data = MMU_read8(cpu->proc_ID, source++);
-      l += 3;
-      for(i = 0;i < l; i++) {
-        writeValue |= (data << byteShift);
-        byteShift += 8;
-        byteCount++;
-
-        if(byteCount == 2) {
-          MMU_write16(cpu->proc_ID, dest, writeValue);
-          dest += 2;
-          byteCount = 0;
-          byteShift = 0;
-          writeValue = 0;
-        }
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    } else {
-      l++;
-      for(i = 0; i < l; i++) {
-        writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
-        byteShift += 8;
-        byteCount++;
-        if(byteCount == 2) {
-          MMU_write16(cpu->proc_ID, dest, writeValue);
-          dest += 2;
-          byteCount = 0;
-          byteShift = 0;
-          writeValue = 0;
-        }
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    }
-  }
-  return 1;
-}
-
-u32 RLUnCompWram(armcpu_t* cpu)
-{
-  int i;
-  int len;
-  u32 source = cpu->R[0];
-  u32 dest = cpu->R[1];
-
-  u32 header = MMU_read32(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;  
-  
-  len = header >> 8;
-
-  while(len > 0) {
-    u8 d = MMU_read8(cpu->proc_ID, source++);
-    int l = d & 0x7F;
-    if(d & 0x80) {
-      u8 data = MMU_read8(cpu->proc_ID, source++);
-      l += 3;
-      for(i = 0;i < l; i++) {
-        MMU_write8(cpu->proc_ID, dest++, data);
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    } else {
-      l++;
-      for(i = 0; i < l; i++) {
-        MMU_write8(cpu->proc_ID, dest++,  MMU_read8(cpu->proc_ID, source++));
-        len--;
-        if(len == 0)
-          return 0;
-      }
-    }
-  }
-  return 1;
-}
-
-u32 UnCompHuffman(armcpu_t* cpu)
-{
-  u32 source, dest, writeValue, header, treeStart, mask;
-  u32 data;
-  u8 treeSize, currentNode, rootNode;
-  int byteCount, byteShift, len, pos;
-  int writeData;
-
-  source = cpu->R[0];
-  dest = cpu->R[1];
-
-  header = MMU_read8(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;  
-  
-  treeSize = MMU_read8(cpu->proc_ID, source++);
-
-  treeStart = source;
-
-  source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
-  
-  len = header >> 8;
-
-  mask = 0x80000000;
-  data = MMU_read8(cpu->proc_ID, source);
-  source += 4;
-
-  pos = 0;
-  rootNode = MMU_read8(cpu->proc_ID, treeStart);
-  currentNode = rootNode;
-  writeData = 0;
-  byteShift = 0;
-  byteCount = 0;
-  writeValue = 0;
-
-  if((header & 0x0F) == 8) {
-    while(len > 0) {
-      // take left
-      if(pos == 0)
-        pos++;
-      else
-        pos += (((currentNode & 0x3F)+1)<<1);
-      
-      if(data & mask) {
-        // right
-        if(currentNode & 0x40)
-          writeData = 1;
-        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1);
-      } else {
-        // left
-        if(currentNode & 0x80)
-          writeData = 1;
-        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos);
-      }
-      
-      if(writeData) {
-        writeValue |= (currentNode << byteShift);
-        byteCount++;
-        byteShift += 8;
-
-        pos = 0;
-        currentNode = rootNode;
-        writeData = 0;
-
-        if(byteCount == 4) {
-          byteCount = 0;
-          byteShift = 0;
-          MMU_write8(cpu->proc_ID, dest, writeValue);
-          writeValue = 0;
-          dest += 4;
-          len -= 4;
-        }
-      }
-      mask >>= 1;
-      if(mask == 0) {
-        mask = 0x80000000;
-        data = MMU_read8(cpu->proc_ID, source);
-        source += 4;
-      }
-    }
-  } else {
-    int halfLen = 0;
-    int value = 0;
-    while(len > 0) {
-      // take left
-      if(pos == 0)
-        pos++;
-      else
-        pos += (((currentNode & 0x3F)+1)<<1);
-
-      if((data & mask)) {
-        // right
-        if(currentNode & 0x40)
-          writeData = 1;
-        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1);
-      } else {
-        // left
-        if(currentNode & 0x80)
-          writeData = 1;
-        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos);
-      }
-      
-      if(writeData) {
-        if(halfLen == 0)
-          value |= currentNode;
-        else
-          value |= (currentNode<<4);
-
-        halfLen += 4;
-        if(halfLen == 8) {
-          writeValue |= (value << byteShift);
-          byteCount++;
-          byteShift += 8;
-          
-          halfLen = 0;
-          value = 0;
-
-          if(byteCount == 4) {
-            byteCount = 0;
-            byteShift = 0;
-            MMU_write8(cpu->proc_ID, dest, writeValue);
-            dest += 4;
-            writeValue = 0;
-            len -= 4;
-          }
-        }
-        pos = 0;
-        currentNode = rootNode;
-        writeData = 0;
-      }
-      mask >>= 1;
-      if(mask == 0) {
-        mask = 0x80000000;
-        data = MMU_read8(cpu->proc_ID, source);
-        source += 4;
-      }
-    }    
-  }
-  return 1;
-}
-
-u32 BitUnPack(armcpu_t* cpu)
-{
-  u32 source,dest,header,base,d,temp;
-  int len,bits,revbits,dataSize,data,bitwritecount,mask,bitcount,addBase;
-  u8 b;
-
-  source = cpu->R[0];
-  dest = cpu->R[1];
-  header = cpu->R[2];
-  
-  len = MMU_read16(cpu->proc_ID, header);
-  // check address
-  bits = MMU_read8(cpu->proc_ID, header+2);
-  revbits = 8 - bits; 
-  // u32 value = 0;
-  base = MMU_read8(cpu->proc_ID, header+4);
-  addBase = (base & 0x80000000) ? 1 : 0;
-  base &= 0x7fffffff;
-  dataSize = MMU_read8(cpu->proc_ID, header+3);
-
-  data = 0; 
-  bitwritecount = 0; 
-  while(1) {
-    len -= 1;
-    if(len < 0)
-      break;
-    mask = 0xff >> revbits; 
-    b = MMU_read8(cpu->proc_ID, source); 
-    source++;
-    bitcount = 0;
-    while(1) {
-      if(bitcount >= 8)
-        break;
-      d = b & mask;
-      temp = d >> bitcount;
-      if(!temp && addBase) {
-        temp += base;
-      }
-      data |= temp << bitwritecount;
-      bitwritecount += dataSize;
-      if(bitwritecount >= 32) {
-        MMU_write8(cpu->proc_ID, dest, data);
-        dest += 4;
-        data = 0;
-        bitwritecount = 0;
-      }
-      mask <<= bits;
-      bitcount += bits;
-    }
-  }
-  return 1;
-}
-
-u32 Diff8bitUnFilterWram(armcpu_t* cpu)
-{
-  u32 source,dest,header;
-  u8 data,diff;
-  int len;
-
-  source = cpu->R[0];
-  dest = cpu->R[1];
-
-  header = MMU_read8(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     (( (source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0))
-    return 0;  
-
-  len = header >> 8;
-
-  data = MMU_read8(cpu->proc_ID, source++);
-  MMU_write8(cpu->proc_ID, dest++, data);
-  len--;
-  
-  while(len > 0) {
-    diff = MMU_read8(cpu->proc_ID, source++);
-    data += diff;
-    MMU_write8(cpu->proc_ID, dest++, data);
-    len--;
-  }
-  return 1;
-}
-
-u32 Diff16bitUnFilter(armcpu_t* cpu)
-{
-  u32 source,dest,header;
-  u16 data;
-  int len;
-
-  source = cpu->R[0];
-  dest = cpu->R[1];
-
-  header = MMU_read8(cpu->proc_ID, source);
-  source += 4;
-
-  if(((source & 0xe000000) == 0) ||
-     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
-    return 0;  
-  
-  len = header >> 8;
-
-  data = MMU_read16(cpu->proc_ID, source);
-  source += 2;
-  MMU_write16(cpu->proc_ID, dest, data);
-  dest += 2;
-  len -= 2;
-  
-  while(len >= 2) {
-    u16 diff = MMU_read16(cpu->proc_ID, source);
-    source += 2;
-    data += diff;
-    MMU_write16(cpu->proc_ID, dest, data);
-    dest += 2;
-    len -= 2;
-  }
-  return 1;
-}
-
-u32 bios_sqrt(armcpu_t* cpu)
-{
-     cpu->R[0] = (u32)sqrt((double)(cpu->R[0]));
-     return 1;
-}
-
-u32 setHaltCR(armcpu_t* cpu)
-{ 
-     MMU_write8(cpu->proc_ID, 0x4000300+cpu->proc_ID, cpu->R[0]);
-     return 1;
-}
-
-u32 getSineTab(armcpu_t* cpu)
-{ 
-     cpu->R[0] = getsinetbl[cpu->R[0]];
-     return 1;
-}
-
-u32 getPitchTab(armcpu_t* cpu)
-{ 
-     cpu->R[0] = getpitchtbl[cpu->R[0]];
-     return 1;
-}
-
-u32 getVolumeTab(armcpu_t* cpu)
-{ 
-     cpu->R[0] = getvoltbl[cpu->R[0]];
-     return 1;
-}
-
-u32 getCRC16(armcpu_t* cpu)
-{
-  unsigned int i,j;
-  
-  u32 crc = cpu->R[0];
-  u32 datap = cpu->R[1];
-  u32 size = cpu->R[2];
-  
-  static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
-  for(i = 0; i < size; i++)
-  {
-    crc = crc ^ MMU_read8( cpu->proc_ID, datap + i);
-
-    for(j = 0; j < 8; j++) {
-      int do_bit = 0;
-
-      if ( crc & 0x1)
-        do_bit = 1;
-
-      crc = crc >> 1;
-
-      if ( do_bit) {
-        crc = crc ^ (val[j] << (7-j));
-      }
-    }
-  }
-  cpu->R[0] = crc;
-  return 1;
-}
-
-u32 SoundBias(armcpu_t* cpu)
-{
-     u32 current = SPU_ReadLong(0x4000504);
-     if (cpu->R[0] > current)
-	SPU_WriteLong(0x4000504, current + 0x1);
-     else
-	SPU_WriteLong(0x4000504, current - 0x1);
-     return cpu->R[1];
-}
-
-u32 (* ARM9_swi_tab[32])(armcpu_t* cpu)={
-         bios_nop,             // 0x00
-         bios_nop,             // 0x01
-         bios_nop,             // 0x02
-         delayLoop,            // 0x03
-         intrWaitARM,          // 0x04
-         waitVBlankARM,        // 0x05
-         wait4IRQ,             // 0x06
-         bios_nop,             // 0x07
-         bios_nop,             // 0x08
-         devide,               // 0x09
-         bios_nop,             // 0x0A
-         copy,                 // 0x0B
-         fastCopy,             // 0x0C
-         bios_sqrt,            // 0x0D
-         getCRC16,             // 0x0E
-         bios_nop,             // 0x0F
-         BitUnPack,            // 0x10
-         LZ77UnCompWram,       // 0x11
-         LZ77UnCompVram,       // 0x12
-         UnCompHuffman,        // 0x13
-         RLUnCompWram,         // 0x14
-         RLUnCompVram,         // 0x15
-         Diff8bitUnFilterWram, // 0x16
-         bios_nop,             // 0x17
-         Diff16bitUnFilter,    // 0x18
-         bios_nop,             // 0x19
-         bios_nop,             // 0x1A
-         bios_nop,             // 0x1B
-         bios_nop,             // 0x1C
-         bios_nop,             // 0x1D
-         bios_nop,             // 0x1E
-         setHaltCR,            // 0x1F
-};
-
-u32 (* ARM7_swi_tab[32])(armcpu_t* cpu)={
-         bios_nop,             // 0x00
-         bios_nop,             // 0x01
-         bios_nop,             // 0x02
-         delayLoop,            // 0x03
-         intrWaitARM,          // 0x04
-         waitVBlankARM,        // 0x05
-         wait4IRQ,             // 0x06
-         wait4IRQ,             // 0x07
-         SoundBias,            // 0x08
-         devide,               // 0x09
-         bios_nop,             // 0x0A
-         copy,                 // 0x0B
-         fastCopy,             // 0x0C
-         bios_sqrt,            // 0x0D
-         getCRC16,             // 0x0E
-         bios_nop,             // 0x0F
-         BitUnPack,            // 0x10
-         LZ77UnCompWram,       // 0x11
-         LZ77UnCompVram,       // 0x12
-         UnCompHuffman,        // 0x13
-         RLUnCompWram,         // 0x14
-         RLUnCompVram,         // 0x15
-         Diff8bitUnFilterWram, // 0x16
-         bios_nop,             // 0x17
-         bios_nop,             // 0x18
-         bios_nop,             // 0x19
-         getSineTab,           // 0x1A
-         getPitchTab,          // 0x1B
-         getVolumeTab,         // 0x1C
-         bios_nop,             // 0x1D
-         bios_nop,             // 0x1E
-         setHaltCR,            // 0x1F
-};
diff --git a/src/xsf/desmume/bios.cc b/src/xsf/desmume/bios.cc
new file mode 100644
index 000000000000..2a0c7727c19d
--- /dev/null
+++ b/src/xsf/desmume/bios.cc
@@ -0,0 +1,1073 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "cp15.h"
+#include <math.h>
+#include "MMU.h"
+#include "SPU.h"
+#include "debug.h"
+
+extern BOOL execute;
+
+static u16 getsinetbl[] = {
+0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2,
+0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11,
+0x30FB, 0x33DF, 0x36BA, 0x398C, 0x3C56, 0x3F17, 0x41CE, 0x447A,
+0x471C, 0x49B4, 0x4C3F, 0x4EBF, 0x5133, 0x539B, 0x55F5, 0x5842,
+0x5A82, 0x5CB3, 0x5ED7, 0x60EB, 0x62F1, 0x64E8, 0x66CF, 0x68A6,
+0x6A6D, 0x6C23, 0x6DC9, 0x6F5E, 0x70E2, 0x7254, 0x73B5, 0x7504,
+0x7641, 0x776B, 0x7884, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE3,
+0x7D89, 0x7E1D, 0x7E9C, 0x7F09, 0x7F61, 0x7FA6, 0x7FD8, 0x7FF5
+};
+
+static u16 getpitchtbl[] = {
+0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F,
+0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D,
+0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F,
+0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743,
+0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C,
+0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18,
+0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07,
+0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA,
+0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1,
+0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB,
+0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9,
+0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB,
+0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0,
+0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA,
+0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07,
+0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17,
+0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C,
+0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344,
+0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561,
+0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781,
+0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5,
+0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD,
+0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9,
+0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A,
+0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E,
+0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496,
+0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3,
+0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913,
+0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58,
+0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1,
+0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE,
+0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240,
+0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495,
+0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0,
+0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E,
+0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1,
+0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18,
+0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084,
+0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4,
+0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569,
+0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2,
+0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60,
+0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3,
+0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A,
+0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6,
+0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487,
+0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C,
+0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6,
+0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55,
+0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9,
+0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2,
+0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450,
+0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702,
+0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA,
+0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77,
+0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38,
+0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF,
+0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB,
+0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D,
+0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73,
+0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F,
+0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030,
+0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316,
+0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602,
+0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3,
+0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA,
+0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6,
+0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8,
+0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF,
+0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC,
+0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E,
+0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27,
+0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145,
+0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468,
+0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792,
+0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1,
+0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7,
+0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132,
+0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473,
+0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB,
+0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08,
+0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B,
+0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5,
+0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515,
+0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B,
+0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8,
+0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B,
+0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4,
+0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654,
+0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA,
+0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66,
+0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA,
+0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494,
+0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834,
+0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC,
+0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A
+};
+
+static u8 getvoltbl[] = {
+0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08,
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
+0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E,
+0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10,
+0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14,
+0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18,
+0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C,
+0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
+0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29,
+0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31,
+0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B,
+0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47,
+0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55,
+0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67,
+0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B,
+0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25,
+0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D,
+0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36,
+0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40,
+0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D,
+0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D,
+0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70,
+0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43,
+0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,
+0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61,
+0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75,
+0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46,
+0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66,
+0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A,
+0x7C, 0x7D, 0x7E, 0x7F
+};
+
+u32 bios_nop(armcpu_t * cpu)
+{
+     if (cpu->proc_ID == ARMCPU_ARM9)
+     {
+        LOG("Unimplemented bios function %02X(ARM9) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]);
+     }
+     else
+     {
+        LOG("Unimplemented bios function %02X(ARM7) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]);
+     }
+     return 3;
+}
+
+u32 delayLoop(armcpu_t * cpu)
+{
+     return cpu->R[0] * 4;
+}
+
+//u32 oldmode[2];
+
+u32 intrWaitARM(armcpu_t * cpu)
+{
+     u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
+     u32 intr;
+     u32 intrFlag = 0;
+
+     //execute = false;
+     if(cpu->proc_ID)
+     {
+      intrFlagAdr = 0x380FFF8;
+     } else {
+      intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
+     }
+     intr = MMU_read32(cpu->proc_ID, intrFlagAdr);
+     intrFlag = cpu->R[1] & intr;
+
+     if(intrFlag)
+     {
+          // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s)
+          // on efface son(les) occurence(s).
+          intr ^= intrFlag;
+          MMU_write32(cpu->proc_ID, intrFlagAdr, intr);
+          //cpu->switchMode(oldmode[cpu->proc_ID]);
+          return 1;
+     }
+
+     cpu->R[15] = cpu->instruct_adr;
+     cpu->next_instruction = cpu->R[15];
+     cpu->waitIRQ = 1;
+     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
+
+     return 1;
+}
+
+u32 waitVBlankARM(armcpu_t * cpu)
+{
+     u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
+     u32 intr;
+     u32 intrFlag = 0;
+
+     //execute = false;
+     if(cpu->proc_ID)
+     {
+      intrFlagAdr = 0x380FFF8;
+     } else {
+      intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8;
+     }
+     intr = MMU_read32(cpu->proc_ID, intrFlagAdr);
+     intrFlag = 1 & intr;
+
+     if(intrFlag)
+     {
+          // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s)
+          // on efface son(les) occurence(s).
+          intr ^= intrFlag;
+          MMU_write32(cpu->proc_ID, intrFlagAdr, intr);
+          //cpu->switchMode(oldmode[cpu->proc_ID]);
+          return 1;
+     }
+
+     cpu->R[15] = cpu->instruct_adr;
+     cpu->next_instruction = cpu->R[15];
+     cpu->waitIRQ = 1;
+     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
+
+     return 1;
+}
+
+u32 wait4IRQ(armcpu_t* cpu)
+{
+     //execute= false;
+     if(cpu->wirq)
+     {
+          if(!cpu->waitIRQ)
+          {
+               cpu->waitIRQ = 0;
+               cpu->wirq = 0;
+               //cpu->switchMode(oldmode[cpu->proc_ID]);
+               return 1;
+          }
+          cpu->R[15] = cpu->instruct_adr;
+          cpu->next_instruction = cpu->R[15];
+          return 1;
+     }
+     cpu->waitIRQ = 1;
+     cpu->wirq = 1;
+     cpu->R[15] = cpu->instruct_adr;
+     cpu->next_instruction = cpu->R[15];
+     //oldmode[cpu->proc_ID] = cpu->switchMode(SVC);
+     return 1;
+}
+
+u32 devide(armcpu_t* cpu)
+{
+     s32 num = (s32)cpu->R[0];
+     s32 dnum = (s32)cpu->R[1];
+
+     if(dnum==0) return 0;
+
+     cpu->R[0] = (u32)(num / dnum);
+     cpu->R[1] = (u32)(num % dnum);
+     cpu->R[3] = (u32) (((s32)cpu->R[0])<0 ? -cpu->R[0] : cpu->R[0]);
+
+     return 6;
+}
+
+u32 copy(armcpu_t* cpu)
+{
+     u32 src = cpu->R[0];
+     u32 dst = cpu->R[1];
+     u32 cnt = cpu->R[2];
+
+     switch(BIT26(cnt))
+     {
+          case 0:
+               src &= 0xFFFFFFFE;
+               dst &= 0xFFFFFFFE;
+               switch(BIT24(cnt))
+               {
+                    case 0:
+                         cnt &= 0x1FFFFF;
+                         while(cnt)
+                         {
+                              MMU_write16(cpu->proc_ID, dst, MMU_read16(cpu->proc_ID, src));
+                              cnt--;
+                              dst+=2;
+                              src+=2;
+                         }
+                         break;
+                    case 1:
+                         {
+                              u32 val = MMU_read16(cpu->proc_ID, src);
+                              cnt &= 0x1FFFFF;
+                              while(cnt)
+                              {
+                                   MMU_write16(cpu->proc_ID, dst, val);
+                                   cnt--;
+                                   dst+=2;
+                              }
+                         }
+                         break;
+               }
+               break;
+          case 1:
+               src &= 0xFFFFFFFC;
+               dst &= 0xFFFFFFFC;
+               switch(BIT24(cnt))
+               {
+                    case 0:
+                         cnt &= 0x1FFFFF;
+                         while(cnt)
+                         {
+                              MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src));
+                              cnt--;
+                              dst+=4;
+                              src+=4;
+                         }
+                         break;
+                    case 1:
+                         {
+                              u32 val = MMU_read32(cpu->proc_ID, src);
+                              cnt &= 0x1FFFFF;
+                              while(cnt)
+                              {
+                                   MMU_write32(cpu->proc_ID, dst, val);
+                                   cnt--;
+                                   dst+=4;
+                              }
+                         }
+                         break;
+               }
+               break;
+     }
+     return 1;
+}
+
+u32 fastCopy(armcpu_t* cpu)
+{
+     u32 src = cpu->R[0] & 0xFFFFFFFC;
+     u32 dst = cpu->R[1] & 0xFFFFFFFC;
+     u32 cnt = cpu->R[2];
+
+     switch(BIT24(cnt))
+     {
+          case 0:
+               cnt &= 0x1FFFFF;
+               while(cnt)
+               {
+                    MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src));
+                    cnt--;
+                    dst+=4;
+                    src+=4;
+               }
+               break;
+          case 1:
+               {
+                    u32 val = MMU_read32(cpu->proc_ID, src);
+                    cnt &= 0x1FFFFF;
+                    while(cnt)
+                    {
+                         MMU_write32(cpu->proc_ID, dst, val);
+                         cnt--;
+                         dst+=4;
+                    }
+               }
+               break;
+     }
+     return 1;
+}
+
+u32 LZ77UnCompVram(armcpu_t* cpu)
+{
+  int i1, i2;
+  int byteCount;
+  int byteShift;
+  u32 writeValue;
+  int len;
+  u32 source = cpu->R[0];
+  u32 dest = cpu->R[1];
+  u32 header = MMU_read32(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  byteCount = 0;
+  byteShift = 0;
+  writeValue = 0;
+
+  len = header >> 8;
+
+  while(len > 0) {
+    u8 d = MMU_read8(cpu->proc_ID, source++);
+
+    if(d) {
+      for(i1 = 0; i1 < 8; i1++) {
+        if(d & 0x80) {
+          int length;
+          int offset;
+          u32 windowOffset;
+          u16 data = MMU_read8(cpu->proc_ID, source++) << 8;
+          data |= MMU_read8(cpu->proc_ID, source++);
+          length = (data >> 12) + 3;
+          offset = (data & 0x0FFF);
+          windowOffset = dest + byteCount - offset - 1;
+          for(i2 = 0; i2 < length; i2++) {
+            writeValue |= (MMU_read8(cpu->proc_ID, windowOffset++) << byteShift);
+            byteShift += 8;
+            byteCount++;
+
+            if(byteCount == 2) {
+              MMU_write16(cpu->proc_ID, dest, writeValue);
+              dest += 2;
+              byteCount = 0;
+              byteShift = 0;
+              writeValue = 0;
+            }
+            len--;
+            if(len == 0)
+              return 0;
+          }
+        } else {
+          writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
+          byteShift += 8;
+          byteCount++;
+          if(byteCount == 2) {
+            MMU_write16(cpu->proc_ID, dest, writeValue);
+            dest += 2;
+            byteCount = 0;
+            byteShift = 0;
+            writeValue = 0;
+          }
+          len--;
+          if(len == 0)
+            return 0;
+        }
+        d <<= 1;
+      }
+    } else {
+      for(i1 = 0; i1 < 8; i1++) {
+        writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
+        byteShift += 8;
+        byteCount++;
+        if(byteCount == 2) {
+          MMU_write16(cpu->proc_ID, dest, writeValue);
+          dest += 2;
+          byteShift = 0;
+          byteCount = 0;
+          writeValue = 0;
+        }
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    }
+  }
+  return 1;
+}
+
+u32 LZ77UnCompWram(armcpu_t* cpu)
+{
+  int i1, i2;
+  int len;
+  u32 source = cpu->R[0];
+  u32 dest = cpu->R[1];
+
+  u32 header = MMU_read32(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  len = header >> 8;
+
+  while(len > 0) {
+    u8 d = MMU_read8(cpu->proc_ID, source++);
+
+    if(d) {
+      for(i1 = 0; i1 < 8; i1++) {
+        if(d & 0x80) {
+          int length;
+          int offset;
+          u32 windowOffset;
+          u16 data = MMU_read8(cpu->proc_ID, source++) << 8;
+          data |= MMU_read8(cpu->proc_ID, source++);
+          length = (data >> 12) + 3;
+          offset = (data & 0x0FFF);
+          windowOffset = dest - offset - 1;
+          for(i2 = 0; i2 < length; i2++) {
+            MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, windowOffset++));
+            len--;
+            if(len == 0)
+              return 0;
+          }
+        } else {
+          MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++));
+          len--;
+          if(len == 0)
+            return 0;
+        }
+        d <<= 1;
+      }
+    } else {
+      for(i1 = 0; i1 < 8; i1++) {
+        MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++));
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    }
+  }
+  return 1;
+}
+
+u32 RLUnCompVram(armcpu_t* cpu)
+{
+  int i;
+  int len;
+  int byteCount;
+  int byteShift;
+  u32 writeValue;
+  u32 source = cpu->R[0];
+  u32 dest = cpu->R[1];
+
+  u32 header = MMU_read32(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  len = header >> 8;
+  byteCount = 0;
+  byteShift = 0;
+  writeValue = 0;
+
+  while(len > 0) {
+    u8 d = MMU_read8(cpu->proc_ID, source++);
+    int l = d & 0x7F;
+    if(d & 0x80) {
+      u8 data = MMU_read8(cpu->proc_ID, source++);
+      l += 3;
+      for(i = 0;i < l; i++) {
+        writeValue |= (data << byteShift);
+        byteShift += 8;
+        byteCount++;
+
+        if(byteCount == 2) {
+          MMU_write16(cpu->proc_ID, dest, writeValue);
+          dest += 2;
+          byteCount = 0;
+          byteShift = 0;
+          writeValue = 0;
+        }
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    } else {
+      l++;
+      for(i = 0; i < l; i++) {
+        writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift);
+        byteShift += 8;
+        byteCount++;
+        if(byteCount == 2) {
+          MMU_write16(cpu->proc_ID, dest, writeValue);
+          dest += 2;
+          byteCount = 0;
+          byteShift = 0;
+          writeValue = 0;
+        }
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    }
+  }
+  return 1;
+}
+
+u32 RLUnCompWram(armcpu_t* cpu)
+{
+  int i;
+  int len;
+  u32 source = cpu->R[0];
+  u32 dest = cpu->R[1];
+
+  u32 header = MMU_read32(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  len = header >> 8;
+
+  while(len > 0) {
+    u8 d = MMU_read8(cpu->proc_ID, source++);
+    int l = d & 0x7F;
+    if(d & 0x80) {
+      u8 data = MMU_read8(cpu->proc_ID, source++);
+      l += 3;
+      for(i = 0;i < l; i++) {
+        MMU_write8(cpu->proc_ID, dest++, data);
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    } else {
+      l++;
+      for(i = 0; i < l; i++) {
+        MMU_write8(cpu->proc_ID, dest++,  MMU_read8(cpu->proc_ID, source++));
+        len--;
+        if(len == 0)
+          return 0;
+      }
+    }
+  }
+  return 1;
+}
+
+u32 UnCompHuffman(armcpu_t* cpu)
+{
+  u32 source, dest, writeValue, header, treeStart, mask;
+  u32 data;
+  u8 treeSize, currentNode, rootNode;
+  int byteCount, byteShift, len, pos;
+  int writeData;
+
+  source = cpu->R[0];
+  dest = cpu->R[1];
+
+  header = MMU_read8(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  treeSize = MMU_read8(cpu->proc_ID, source++);
+
+  treeStart = source;
+
+  source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte
+
+  len = header >> 8;
+
+  mask = 0x80000000;
+  data = MMU_read8(cpu->proc_ID, source);
+  source += 4;
+
+  pos = 0;
+  rootNode = MMU_read8(cpu->proc_ID, treeStart);
+  currentNode = rootNode;
+  writeData = 0;
+  byteShift = 0;
+  byteCount = 0;
+  writeValue = 0;
+
+  if((header & 0x0F) == 8) {
+    while(len > 0) {
+      // take left
+      if(pos == 0)
+        pos++;
+      else
+        pos += (((currentNode & 0x3F)+1)<<1);
+
+      if(data & mask) {
+        // right
+        if(currentNode & 0x40)
+          writeData = 1;
+        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1);
+      } else {
+        // left
+        if(currentNode & 0x80)
+          writeData = 1;
+        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos);
+      }
+
+      if(writeData) {
+        writeValue |= (currentNode << byteShift);
+        byteCount++;
+        byteShift += 8;
+
+        pos = 0;
+        currentNode = rootNode;
+        writeData = 0;
+
+        if(byteCount == 4) {
+          byteCount = 0;
+          byteShift = 0;
+          MMU_write8(cpu->proc_ID, dest, writeValue);
+          writeValue = 0;
+          dest += 4;
+          len -= 4;
+        }
+      }
+      mask >>= 1;
+      if(mask == 0) {
+        mask = 0x80000000;
+        data = MMU_read8(cpu->proc_ID, source);
+        source += 4;
+      }
+    }
+  } else {
+    int halfLen = 0;
+    int value = 0;
+    while(len > 0) {
+      // take left
+      if(pos == 0)
+        pos++;
+      else
+        pos += (((currentNode & 0x3F)+1)<<1);
+
+      if((data & mask)) {
+        // right
+        if(currentNode & 0x40)
+          writeData = 1;
+        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1);
+      } else {
+        // left
+        if(currentNode & 0x80)
+          writeData = 1;
+        currentNode = MMU_read8(cpu->proc_ID, treeStart+pos);
+      }
+
+      if(writeData) {
+        if(halfLen == 0)
+          value |= currentNode;
+        else
+          value |= (currentNode<<4);
+
+        halfLen += 4;
+        if(halfLen == 8) {
+          writeValue |= (value << byteShift);
+          byteCount++;
+          byteShift += 8;
+
+          halfLen = 0;
+          value = 0;
+
+          if(byteCount == 4) {
+            byteCount = 0;
+            byteShift = 0;
+            MMU_write8(cpu->proc_ID, dest, writeValue);
+            dest += 4;
+            writeValue = 0;
+            len -= 4;
+          }
+        }
+        pos = 0;
+        currentNode = rootNode;
+        writeData = 0;
+      }
+      mask >>= 1;
+      if(mask == 0) {
+        mask = 0x80000000;
+        data = MMU_read8(cpu->proc_ID, source);
+        source += 4;
+      }
+    }
+  }
+  return 1;
+}
+
+u32 BitUnPack(armcpu_t* cpu)
+{
+  u32 source,dest,header,base,d,temp;
+  int len,bits,revbits,dataSize,data,bitwritecount,mask,bitcount,addBase;
+  u8 b;
+
+  source = cpu->R[0];
+  dest = cpu->R[1];
+  header = cpu->R[2];
+
+  len = MMU_read16(cpu->proc_ID, header);
+  // check address
+  bits = MMU_read8(cpu->proc_ID, header+2);
+  revbits = 8 - bits;
+  // u32 value = 0;
+  base = MMU_read8(cpu->proc_ID, header+4);
+  addBase = (base & 0x80000000) ? 1 : 0;
+  base &= 0x7fffffff;
+  dataSize = MMU_read8(cpu->proc_ID, header+3);
+
+  data = 0;
+  bitwritecount = 0;
+  while(1) {
+    len -= 1;
+    if(len < 0)
+      break;
+    mask = 0xff >> revbits;
+    b = MMU_read8(cpu->proc_ID, source);
+    source++;
+    bitcount = 0;
+    while(1) {
+      if(bitcount >= 8)
+        break;
+      d = b & mask;
+      temp = d >> bitcount;
+      if(!temp && addBase) {
+        temp += base;
+      }
+      data |= temp << bitwritecount;
+      bitwritecount += dataSize;
+      if(bitwritecount >= 32) {
+        MMU_write8(cpu->proc_ID, dest, data);
+        dest += 4;
+        data = 0;
+        bitwritecount = 0;
+      }
+      mask <<= bits;
+      bitcount += bits;
+    }
+  }
+  return 1;
+}
+
+u32 Diff8bitUnFilterWram(armcpu_t* cpu)
+{
+  u32 source,dest,header;
+  u8 data,diff;
+  int len;
+
+  source = cpu->R[0];
+  dest = cpu->R[1];
+
+  header = MMU_read8(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     (( (source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0))
+    return 0;
+
+  len = header >> 8;
+
+  data = MMU_read8(cpu->proc_ID, source++);
+  MMU_write8(cpu->proc_ID, dest++, data);
+  len--;
+
+  while(len > 0) {
+    diff = MMU_read8(cpu->proc_ID, source++);
+    data += diff;
+    MMU_write8(cpu->proc_ID, dest++, data);
+    len--;
+  }
+  return 1;
+}
+
+u32 Diff16bitUnFilter(armcpu_t* cpu)
+{
+  u32 source,dest,header;
+  u16 data;
+  int len;
+
+  source = cpu->R[0];
+  dest = cpu->R[1];
+
+  header = MMU_read8(cpu->proc_ID, source);
+  source += 4;
+
+  if(((source & 0xe000000) == 0) ||
+     ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)
+    return 0;
+
+  len = header >> 8;
+
+  data = MMU_read16(cpu->proc_ID, source);
+  source += 2;
+  MMU_write16(cpu->proc_ID, dest, data);
+  dest += 2;
+  len -= 2;
+
+  while(len >= 2) {
+    u16 diff = MMU_read16(cpu->proc_ID, source);
+    source += 2;
+    data += diff;
+    MMU_write16(cpu->proc_ID, dest, data);
+    dest += 2;
+    len -= 2;
+  }
+  return 1;
+}
+
+u32 bios_sqrt(armcpu_t* cpu)
+{
+     cpu->R[0] = (u32)sqrt((double)(cpu->R[0]));
+     return 1;
+}
+
+u32 setHaltCR(armcpu_t* cpu)
+{
+     MMU_write8(cpu->proc_ID, 0x4000300+cpu->proc_ID, cpu->R[0]);
+     return 1;
+}
+
+u32 getSineTab(armcpu_t* cpu)
+{
+     cpu->R[0] = getsinetbl[cpu->R[0]];
+     return 1;
+}
+
+u32 getPitchTab(armcpu_t* cpu)
+{
+     cpu->R[0] = getpitchtbl[cpu->R[0]];
+     return 1;
+}
+
+u32 getVolumeTab(armcpu_t* cpu)
+{
+     cpu->R[0] = getvoltbl[cpu->R[0]];
+     return 1;
+}
+
+u32 getCRC16(armcpu_t* cpu)
+{
+  unsigned int i,j;
+
+  u32 crc = cpu->R[0];
+  u32 datap = cpu->R[1];
+  u32 size = cpu->R[2];
+
+  static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
+  for(i = 0; i < size; i++)
+  {
+    crc = crc ^ MMU_read8( cpu->proc_ID, datap + i);
+
+    for(j = 0; j < 8; j++) {
+      int do_bit = 0;
+
+      if ( crc & 0x1)
+        do_bit = 1;
+
+      crc = crc >> 1;
+
+      if ( do_bit) {
+        crc = crc ^ (val[j] << (7-j));
+      }
+    }
+  }
+  cpu->R[0] = crc;
+  return 1;
+}
+
+u32 SoundBias(armcpu_t* cpu)
+{
+     u32 current = SPU_ReadLong(0x4000504);
+     if (cpu->R[0] > current)
+	SPU_WriteLong(0x4000504, current + 0x1);
+     else
+	SPU_WriteLong(0x4000504, current - 0x1);
+     return cpu->R[1];
+}
+
+u32 (* ARM9_swi_tab[32])(armcpu_t* cpu)={
+         bios_nop,             // 0x00
+         bios_nop,             // 0x01
+         bios_nop,             // 0x02
+         delayLoop,            // 0x03
+         intrWaitARM,          // 0x04
+         waitVBlankARM,        // 0x05
+         wait4IRQ,             // 0x06
+         bios_nop,             // 0x07
+         bios_nop,             // 0x08
+         devide,               // 0x09
+         bios_nop,             // 0x0A
+         copy,                 // 0x0B
+         fastCopy,             // 0x0C
+         bios_sqrt,            // 0x0D
+         getCRC16,             // 0x0E
+         bios_nop,             // 0x0F
+         BitUnPack,            // 0x10
+         LZ77UnCompWram,       // 0x11
+         LZ77UnCompVram,       // 0x12
+         UnCompHuffman,        // 0x13
+         RLUnCompWram,         // 0x14
+         RLUnCompVram,         // 0x15
+         Diff8bitUnFilterWram, // 0x16
+         bios_nop,             // 0x17
+         Diff16bitUnFilter,    // 0x18
+         bios_nop,             // 0x19
+         bios_nop,             // 0x1A
+         bios_nop,             // 0x1B
+         bios_nop,             // 0x1C
+         bios_nop,             // 0x1D
+         bios_nop,             // 0x1E
+         setHaltCR,            // 0x1F
+};
+
+u32 (* ARM7_swi_tab[32])(armcpu_t* cpu)={
+         bios_nop,             // 0x00
+         bios_nop,             // 0x01
+         bios_nop,             // 0x02
+         delayLoop,            // 0x03
+         intrWaitARM,          // 0x04
+         waitVBlankARM,        // 0x05
+         wait4IRQ,             // 0x06
+         wait4IRQ,             // 0x07
+         SoundBias,            // 0x08
+         devide,               // 0x09
+         bios_nop,             // 0x0A
+         copy,                 // 0x0B
+         fastCopy,             // 0x0C
+         bios_sqrt,            // 0x0D
+         getCRC16,             // 0x0E
+         bios_nop,             // 0x0F
+         BitUnPack,            // 0x10
+         LZ77UnCompWram,       // 0x11
+         LZ77UnCompVram,       // 0x12
+         UnCompHuffman,        // 0x13
+         RLUnCompWram,         // 0x14
+         RLUnCompVram,         // 0x15
+         Diff8bitUnFilterWram, // 0x16
+         bios_nop,             // 0x17
+         bios_nop,             // 0x18
+         bios_nop,             // 0x19
+         getSineTab,           // 0x1A
+         getPitchTab,          // 0x1B
+         getVolumeTab,         // 0x1C
+         bios_nop,             // 0x1D
+         bios_nop,             // 0x1E
+         setHaltCR,            // 0x1F
+};
diff --git a/src/xsf/desmume/bios.h b/src/xsf/desmume/bios.h
index 7f717cb8cfdc..ad41d6a0b6c8 100644
--- a/src/xsf/desmume/bios.h
+++ b/src/xsf/desmume/bios.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef BIOS_H
diff --git a/src/xsf/desmume/config.h b/src/xsf/desmume/config.h
index 2f2f707ee041..53a2a936b7ac 100644
--- a/src/xsf/desmume/config.h
+++ b/src/xsf/desmume/config.h
@@ -14,7 +14,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef __CONFIG_H__
diff --git a/src/xsf/desmume/cp15.c b/src/xsf/desmume/cp15.c
deleted file mode 100644
index 3a54a2654662..000000000000
--- a/src/xsf/desmume/cp15.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*  Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdlib.h>
-
-#include "cp15.h"
-#include "debug.h"
-#include "MMU.h"
-
-armcp15_t *armcp15_new(armcpu_t * c)
-{
-	int i;
-	armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t));
-	if(!armcp15) return NULL;
-
-	armcp15->cpu = c;
-	armcp15->IDCode = 0x41049460;
-	armcp15->cacheType = 0x0F0D2112;
-	armcp15->TCMSize = 0x00140140;
-	armcp15->ctrl = 0x00000000;
-	armcp15->DCConfig = 0x0;
-	armcp15->ICConfig = 0x0;
-	armcp15->writeBuffCtrl = 0x0;
-	armcp15->und = 0x0;
-	armcp15->DaccessPerm = 0x22222222;
-	armcp15->IaccessPerm = 0x22222222;
-	armcp15->protectBaseSize0 = 0x0;
-	armcp15->protectBaseSize1 = 0x0;
-	armcp15->protectBaseSize2 = 0x0;
-	armcp15->protectBaseSize3 = 0x0;
-	armcp15->protectBaseSize4 = 0x0;
-	armcp15->protectBaseSize5 = 0x0;
-	armcp15->protectBaseSize6 = 0x0;
-	armcp15->protectBaseSize7 = 0x0;
-	armcp15->cacheOp = 0x0;
-	armcp15->DcacheLock = 0x0;
-	armcp15->IcacheLock = 0x0;
-	armcp15->ITCMRegion = 0x0C;
-	armcp15->DTCMRegion = 0x0080000A;
-	armcp15->processID = 0;
-
-    /* preset calculated regionmasks */
-	for (i=0;i<8;i++) {
-        armcp15->regionWriteMask_USR[i] = 0 ;
-        armcp15->regionWriteMask_SYS[i] = 0 ;
-        armcp15->regionReadMask_USR[i] = 0 ;
-        armcp15->regionReadMask_SYS[i] = 0 ;
-        armcp15->regionExecuteMask_USR[i] = 0 ;
-        armcp15->regionExecuteMask_SYS[i] = 0 ;
-        armcp15->regionWriteSet_USR[i] = 0 ;
-        armcp15->regionWriteSet_SYS[i] = 0 ;
-        armcp15->regionReadSet_USR[i] = 0 ;
-        armcp15->regionReadSet_SYS[i] = 0 ;
-        armcp15->regionExecuteSet_USR[i] = 0 ;
-        armcp15->regionExecuteSet_SYS[i] = 0 ;
-    } ;
-
-	return armcp15;
-}
-
-#define ACCESSTYPE(val,n)   (((val) >> (4*n)) & 0x0F)
-#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
-#define SIZEBINARY(val)     (1 << (SIZEIDENTIFIER(val)+1))
-#define MASKFROMREG(val)    (~((SIZEBINARY(val)-1) | 0x3F))
-#define SETFROMREG(val)     ((val) & MASKFROMREG(val))
-/* sets the precalculated regions to mask,set for the affected accesstypes */
-void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) {
-
-	switch (ACCESSTYPE(dAccess,num)) {
-		case 4: /* UNP */
-		case 7: /* UNP */
-		case 8: /* UNP */
-		case 9: /* UNP */
-		case 10: /* UNP */
-		case 11: /* UNP */
-		case 12: /* UNP */
-		case 13: /* UNP */
-		case 14: /* UNP */
-		case 15: /* UNP */
-		case 0: /* no access at all */
-			armcp15->regionWriteMask_USR[num] = 0 ;
-			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_USR[num] = 0 ;
-			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionWriteMask_SYS[num] = 0 ;
-			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_SYS[num] = 0 ;
-			armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ;
-			break ;
-		case 1: /* no access at USR, all to sys */
-			armcp15->regionWriteMask_USR[num] = 0 ;
-			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_USR[num] = 0 ;
-			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionWriteMask_SYS[num] = mask ;
-			armcp15->regionWriteSet_SYS[num] = set ;
-			armcp15->regionReadMask_SYS[num] = mask ;
-			armcp15->regionReadSet_SYS[num] = set ;
-			break ;
-		case 2: /* read at USR, all to sys */
-			armcp15->regionWriteMask_USR[num] = 0 ;
-			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_USR[num] = mask ;
-			armcp15->regionReadSet_USR[num] = set ;
-			armcp15->regionWriteMask_SYS[num] = mask ;
-			armcp15->regionWriteSet_SYS[num] = set ;
-			armcp15->regionReadMask_SYS[num] = mask ;
-			armcp15->regionReadSet_SYS[num] = set ;
-			break ;
-		case 3: /* all to USR, all to sys */
-			armcp15->regionWriteMask_USR[num] = mask ;
-			armcp15->regionWriteSet_USR[num] = set ;
-			armcp15->regionReadMask_USR[num] = mask ;
-			armcp15->regionReadSet_USR[num] = set ;
-			armcp15->regionWriteMask_SYS[num] = mask ;
-			armcp15->regionWriteSet_SYS[num] = set ;
-			armcp15->regionReadMask_SYS[num] = mask ;
-			armcp15->regionReadSet_SYS[num] = set ;
-			break ;
-		case 5: /* no access at USR, read to sys */
-			armcp15->regionWriteMask_USR[num] = 0 ;
-			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_USR[num] = 0 ;
-			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionWriteMask_SYS[num] = 0 ;
-			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_SYS[num] = mask ;
-			armcp15->regionReadSet_SYS[num] = set ;
-			break ;
-		case 6: /* read at USR, read to sys */
-			armcp15->regionWriteMask_USR[num] = 0 ;
-			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_USR[num] = mask ;
-			armcp15->regionReadSet_USR[num] = set ;
-			armcp15->regionWriteMask_SYS[num] = 0 ;
-			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
-			armcp15->regionReadMask_SYS[num] = mask ;
-			armcp15->regionReadSet_SYS[num] = set ;
-			break ;
-	}
-	switch (ACCESSTYPE(iAccess,num)) {
-		case 4: /* UNP */
-		case 7: /* UNP */
-		case 8: /* UNP */
-		case 9: /* UNP */
-		case 10: /* UNP */
-		case 11: /* UNP */
-		case 12: /* UNP */
-		case 13: /* UNP */
-		case 14: /* UNP */
-		case 15: /* UNP */
-		case 0: /* no access at all */
-			armcp15->regionExecuteMask_USR[num] = 0 ;
-			armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionExecuteMask_SYS[num] = 0 ;
-			armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
-			break ;
-		case 1:
-			armcp15->regionExecuteMask_USR[num] = 0 ;
-			armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
-			armcp15->regionExecuteMask_SYS[num] = mask ;
-			armcp15->regionExecuteSet_SYS[num] = set ;
-			break ;
-		case 2:
-		case 3:
-		case 6:
-			armcp15->regionExecuteMask_USR[num] = mask ;
-			armcp15->regionExecuteSet_USR[num] = set ;
-			armcp15->regionExecuteMask_SYS[num] = mask ;
-			armcp15->regionExecuteSet_SYS[num] = set ;
-			break ;
-	}
-}
-
-/* precalculate region masks/sets from cp15 register */
-void armcp15_maskPrecalc(armcp15_t *armcp15)
-{
-	#define precalc(num) {  \
-	u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */  \
-	if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \
-	{    /* reason for this define: naming includes var */  \
-		mask = MASKFROMREG(armcp15->protectBaseSize##num) ;   \
-		set = SETFROMREG(armcp15->protectBaseSize##num) ; \
-		if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F)  \
-		{   /* for the 4GB region, u32 suffers wraparound */   \
-		mask = 0 ; set = 0 ;   /* (x & 0) == 0  is allways true (enabled) */  \
-		} \
-	}  \
-		armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ;  \
-	}
-	precalc(0) ;
-	precalc(1) ;
-	precalc(2) ;
-	precalc(3) ;
-	precalc(4) ;
-	precalc(5) ;
-	precalc(6) ;
-	precalc(7) ;
-}
-
-INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
-{
-	int i ;
-	if (!(armcp15->ctrl & 1)) return TRUE ;        /* protection checking is not enabled */
-	for (i=0;i<8;i++) {
-		switch (access) {
-		case CP15_ACCESS_WRITEUSR:
-			if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ;
-			break ;
-		case CP15_ACCESS_WRITESYS:
-			if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ;
-			break ;
-		case CP15_ACCESS_READUSR:
-			if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ;
-			break ;
-		case CP15_ACCESS_READSYS:
-			if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ;
-			break ;
-		case CP15_ACCESS_EXECUSR:
-			if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ;
-			break ;
-		case CP15_ACCESS_EXECSYS:
-			if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ;
-			break ;
-		}
-	}
-	/* when protections are enabled, but no region allows access, deny access */
-	return FALSE ;
-}
-
-BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
-{
-   return FALSE;
-}
-
-BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr)
-{
-   return FALSE;
-}
-
-BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr)
-{
-   return FALSE;
-}
-
-BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
-{
-	if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
-
-	switch(CRn)
-	{
-		case 0 :
-			if((opcode1 == 0)&&(CRm==0))
-			{
-			switch(opcode2)
-			{
-				case 1 :
-					*R = armcp15->cacheType;
-					return TRUE;
-				case 2 :
-					*R = armcp15->TCMSize;
-					return TRUE;
-				default :
-					*R = armcp15->IDCode;
-					return TRUE;
-			}
-			}
-			return FALSE;
-		case 1 :
-			if((opcode1==0) && (opcode2==0) && (CRm==0))
-			{
-				*R = armcp15->ctrl;
-				return TRUE;
-			}
-			return FALSE;
-
-		case 2 :
-			if((opcode1==0) && (CRm==0))
-			{
-				switch(opcode2)
-				{
-					case 0 :
-						*R = armcp15->DCConfig;
-					return TRUE;
-					case 1 :
-						*R = armcp15->ICConfig;
-					return TRUE;
-					default :
-					return FALSE;
-				}
-			}
-			return FALSE;
-		case 3 :
-			if((opcode1==0) && (opcode2==0) && (CRm==0))
-			{
-				*R = armcp15->writeBuffCtrl;
-				return TRUE;
-			}
-			return FALSE;
-		case 5 :
-			if((opcode1==0) && (CRm==0))
-			{
-				switch(opcode2)
-				{
-					case 2 :
-						*R = armcp15->DaccessPerm;
-					    return TRUE;
-					case 3 :
-						*R = armcp15->IaccessPerm;
-					return TRUE;
-					default :
-					return FALSE;
-				}
-			}
-			return FALSE;
-		case 6 :
-			if((opcode1==0) && (opcode2==0))
-			{
-				switch(CRm)
-				{
-					case 0 :
-						*R = armcp15->protectBaseSize0;
-					return TRUE;
-					case 1 :
-						*R = armcp15->protectBaseSize1;
-					return TRUE;
-					case 2 :
-						*R = armcp15->protectBaseSize2;
-					return TRUE;
-					case 3 :
-						*R = armcp15->protectBaseSize3;
-					return TRUE;
-					case 4 :
-						*R = armcp15->protectBaseSize4;
-					return TRUE;
-					case 5 :
-						*R = armcp15->protectBaseSize5;
-					return TRUE;
-					case 6 :
-						*R = armcp15->protectBaseSize6;
-					return TRUE;
-					case 7 :
-						*R = armcp15->protectBaseSize7;
-					return TRUE;
-					default :
-					return FALSE;
-				}
-			}
-			return FALSE;
-		case 9 :
-			if(opcode1==0)
-			{
-				switch(CRm)
-				{
-					case 0 :
-						switch(opcode2)
-						{
-							case 0 :
-							*R = armcp15->DcacheLock;
-							return TRUE;
-							case 1 :
-							*R = armcp15->IcacheLock;
-							return TRUE;
-							default :
-								return FALSE;
-						}
-					case 1 :
-						switch(opcode2)
-						{
-						case 0 :
-						*R = armcp15->DTCMRegion;
-						return TRUE;
-						case 1 :
-						*R = armcp15->ITCMRegion;
-						return TRUE;
-						default :
-							return FALSE;
-						}
-				}
-			}
-		return FALSE;
-		default :
-			return FALSE;
-	}
-}
-
-
-u32 CP15wait4IRQ(armcpu_t *cpu)
-{
-	/* on the first call, wirq is not set */
-	if(cpu->wirq)
-	{
-		/* check wether an irq was issued */
-		if(!cpu->waitIRQ)
-		{
-			cpu->waitIRQ = 0;
-			cpu->wirq = 0;
-			return 1;   /* return execution */
-		}
-		/* otherwise, repeat this instruction */
-		cpu->R[15] = cpu->instruct_adr;
-		cpu->next_instruction = cpu->R[15];
-		return 1;
-	}
-	/* first run, set us into waiting state */
-	cpu->waitIRQ = 1;
-	cpu->wirq = 1;
-	/* and set next instruction to repeat this */
-	cpu->R[15] = cpu->instruct_adr;
-	cpu->next_instruction = cpu->R[15];
-	/* CHECKME: IME shouldn't be modified (?) */
-	MMU.reg_IME[0] = 1;
-	return 1;
-}
-
-BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
-{
-	if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE;
-
-	switch(CRn)
-	{
-		case 1 :
-		if((opcode1==0) && (opcode2==0) && (CRm==0))
-		{
-			armcp15->ctrl = val;
-			MMU.ARM9_RW_MODE = BIT7(val);
-			armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val));
-			armcp15->cpu->LDTBit = !BIT15(val); //TBit
-			/*if(BIT17(val))
-			{
-				log::ajouter("outch !!!!!!!");
-			}
-			if(BIT19(val))
-			{
-				log::ajouter("outch !!!!!!!");
-			}*/
-			return TRUE;
-		}
-		return FALSE;
-		case 2 :
-		if((opcode1==0) && (CRm==0))
-		{
-			switch(opcode2)
-			{
-				case 0 :
-					armcp15->DCConfig = val;
-					return TRUE;
-				case 1 :
-					armcp15->ICConfig = val;
-					return TRUE;
-				default :
-					return FALSE;
-			}
-		}
-		return FALSE;
-		case 3 :
-		if((opcode1==0) && (opcode2==0) && (CRm==0))
-		{
-			armcp15->writeBuffCtrl = val;
-			return TRUE;
-		}
-		return FALSE;
-		if((opcode1==0) && (CRm==0))
-		{
-			switch(opcode2)
-			{
-				case 2 :
-					armcp15->DaccessPerm = val;
-					armcp15_maskPrecalc(armcp15);
- 					return TRUE;
-				case 3 :
-					armcp15->IaccessPerm = val;
-					armcp15_maskPrecalc(armcp15);
-					return TRUE;
-				default :
-					return FALSE;
-			}
-		}
-		return FALSE;
-		case 6 :
-		if((opcode1==0) && (opcode2==0))
-		{
-			switch(CRm)
-			{
-				case 0 :
-					armcp15->protectBaseSize0 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 1 :
-					armcp15->protectBaseSize1 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 2 :
-					armcp15->protectBaseSize2 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 3 :
-					armcp15->protectBaseSize3 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 4 :
-					armcp15->protectBaseSize4 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 5 :
-					armcp15->protectBaseSize5 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 6 :
-					armcp15->protectBaseSize6 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				case 7 :
-					armcp15->protectBaseSize7 = val;
-					armcp15_maskPrecalc(armcp15) ;
-					return TRUE;
-				default :
-					return FALSE;
-			}
-		}
-		return FALSE;
-		case 7 :
-		if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
-		{
-			CP15wait4IRQ(armcp15->cpu);
-			return TRUE;
-		}
-		return FALSE;
-		case 9 :
-		if(opcode1==0)
-		{
-			switch(CRm)
-			{
-				case 0 :
-				switch(opcode2)
-				{
-					case 0 :
-						armcp15->DcacheLock = val;
-						return TRUE;
-					case 1 :
-						armcp15->IcacheLock = val;
-						return TRUE;
-					default :
-						return FALSE;
-			}
-			case 1 :
-			switch(opcode2)
-			{
-				case 0 :
-					armcp15->DTCMRegion = val;
-					MMU.DTCMRegion = val & 0x0FFFFFFC0;
-					/*sprintf(logbuf, "%08X", val);
-					log::ajouter(logbuf);*/
-					return TRUE;
-				case 1 :
-					armcp15->ITCMRegion = val;
-					/* ITCM base is not writeable! */
-					MMU.ITCMRegion = 0;
-					return TRUE;
-				default :
-					return FALSE;
-				}
-			}
-		}
-		return FALSE;
-		default :
-			return FALSE;
-	}
-}
-
-
-
diff --git a/src/xsf/desmume/cp15.cc b/src/xsf/desmume/cp15.cc
new file mode 100644
index 000000000000..1c07c550c301
--- /dev/null
+++ b/src/xsf/desmume/cp15.cc
@@ -0,0 +1,590 @@
+/*  Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdlib.h>
+
+#include "cp15.h"
+#include "debug.h"
+#include "MMU.h"
+
+armcp15_t *armcp15_new(armcpu_t * c)
+{
+	int i;
+	armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t));
+	if(!armcp15) return nullptr;
+
+	armcp15->cpu = c;
+	armcp15->IDCode = 0x41049460;
+	armcp15->cacheType = 0x0F0D2112;
+	armcp15->TCMSize = 0x00140140;
+	armcp15->ctrl = 0x00000000;
+	armcp15->DCConfig = 0x0;
+	armcp15->ICConfig = 0x0;
+	armcp15->writeBuffCtrl = 0x0;
+	armcp15->und = 0x0;
+	armcp15->DaccessPerm = 0x22222222;
+	armcp15->IaccessPerm = 0x22222222;
+	armcp15->protectBaseSize0 = 0x0;
+	armcp15->protectBaseSize1 = 0x0;
+	armcp15->protectBaseSize2 = 0x0;
+	armcp15->protectBaseSize3 = 0x0;
+	armcp15->protectBaseSize4 = 0x0;
+	armcp15->protectBaseSize5 = 0x0;
+	armcp15->protectBaseSize6 = 0x0;
+	armcp15->protectBaseSize7 = 0x0;
+	armcp15->cacheOp = 0x0;
+	armcp15->DcacheLock = 0x0;
+	armcp15->IcacheLock = 0x0;
+	armcp15->ITCMRegion = 0x0C;
+	armcp15->DTCMRegion = 0x0080000A;
+	armcp15->processID = 0;
+
+    /* preset calculated regionmasks */
+	for (i=0;i<8;i++) {
+        armcp15->regionWriteMask_USR[i] = 0 ;
+        armcp15->regionWriteMask_SYS[i] = 0 ;
+        armcp15->regionReadMask_USR[i] = 0 ;
+        armcp15->regionReadMask_SYS[i] = 0 ;
+        armcp15->regionExecuteMask_USR[i] = 0 ;
+        armcp15->regionExecuteMask_SYS[i] = 0 ;
+        armcp15->regionWriteSet_USR[i] = 0 ;
+        armcp15->regionWriteSet_SYS[i] = 0 ;
+        armcp15->regionReadSet_USR[i] = 0 ;
+        armcp15->regionReadSet_SYS[i] = 0 ;
+        armcp15->regionExecuteSet_USR[i] = 0 ;
+        armcp15->regionExecuteSet_SYS[i] = 0 ;
+    } ;
+
+	return armcp15;
+}
+
+#define ACCESSTYPE(val,n)   (((val) >> (4*n)) & 0x0F)
+#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F))
+#define SIZEBINARY(val)     (1 << (SIZEIDENTIFIER(val)+1))
+#define MASKFROMREG(val)    (~((SIZEBINARY(val)-1) | 0x3F))
+#define SETFROMREG(val)     ((val) & MASKFROMREG(val))
+/* sets the precalculated regions to mask,set for the affected accesstypes */
+void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) {
+
+	switch (ACCESSTYPE(dAccess,num)) {
+		case 4: /* UNP */
+		case 7: /* UNP */
+		case 8: /* UNP */
+		case 9: /* UNP */
+		case 10: /* UNP */
+		case 11: /* UNP */
+		case 12: /* UNP */
+		case 13: /* UNP */
+		case 14: /* UNP */
+		case 15: /* UNP */
+		case 0: /* no access at all */
+			armcp15->regionWriteMask_USR[num] = 0 ;
+			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_USR[num] = 0 ;
+			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionWriteMask_SYS[num] = 0 ;
+			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_SYS[num] = 0 ;
+			armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ;
+			break ;
+		case 1: /* no access at USR, all to sys */
+			armcp15->regionWriteMask_USR[num] = 0 ;
+			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_USR[num] = 0 ;
+			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionWriteMask_SYS[num] = mask ;
+			armcp15->regionWriteSet_SYS[num] = set ;
+			armcp15->regionReadMask_SYS[num] = mask ;
+			armcp15->regionReadSet_SYS[num] = set ;
+			break ;
+		case 2: /* read at USR, all to sys */
+			armcp15->regionWriteMask_USR[num] = 0 ;
+			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_USR[num] = mask ;
+			armcp15->regionReadSet_USR[num] = set ;
+			armcp15->regionWriteMask_SYS[num] = mask ;
+			armcp15->regionWriteSet_SYS[num] = set ;
+			armcp15->regionReadMask_SYS[num] = mask ;
+			armcp15->regionReadSet_SYS[num] = set ;
+			break ;
+		case 3: /* all to USR, all to sys */
+			armcp15->regionWriteMask_USR[num] = mask ;
+			armcp15->regionWriteSet_USR[num] = set ;
+			armcp15->regionReadMask_USR[num] = mask ;
+			armcp15->regionReadSet_USR[num] = set ;
+			armcp15->regionWriteMask_SYS[num] = mask ;
+			armcp15->regionWriteSet_SYS[num] = set ;
+			armcp15->regionReadMask_SYS[num] = mask ;
+			armcp15->regionReadSet_SYS[num] = set ;
+			break ;
+		case 5: /* no access at USR, read to sys */
+			armcp15->regionWriteMask_USR[num] = 0 ;
+			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_USR[num] = 0 ;
+			armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionWriteMask_SYS[num] = 0 ;
+			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_SYS[num] = mask ;
+			armcp15->regionReadSet_SYS[num] = set ;
+			break ;
+		case 6: /* read at USR, read to sys */
+			armcp15->regionWriteMask_USR[num] = 0 ;
+			armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_USR[num] = mask ;
+			armcp15->regionReadSet_USR[num] = set ;
+			armcp15->regionWriteMask_SYS[num] = 0 ;
+			armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ;
+			armcp15->regionReadMask_SYS[num] = mask ;
+			armcp15->regionReadSet_SYS[num] = set ;
+			break ;
+	}
+	switch (ACCESSTYPE(iAccess,num)) {
+		case 4: /* UNP */
+		case 7: /* UNP */
+		case 8: /* UNP */
+		case 9: /* UNP */
+		case 10: /* UNP */
+		case 11: /* UNP */
+		case 12: /* UNP */
+		case 13: /* UNP */
+		case 14: /* UNP */
+		case 15: /* UNP */
+		case 0: /* no access at all */
+			armcp15->regionExecuteMask_USR[num] = 0 ;
+			armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionExecuteMask_SYS[num] = 0 ;
+			armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ;
+			break ;
+		case 1:
+			armcp15->regionExecuteMask_USR[num] = 0 ;
+			armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ;
+			armcp15->regionExecuteMask_SYS[num] = mask ;
+			armcp15->regionExecuteSet_SYS[num] = set ;
+			break ;
+		case 2:
+		case 3:
+		case 6:
+			armcp15->regionExecuteMask_USR[num] = mask ;
+			armcp15->regionExecuteSet_USR[num] = set ;
+			armcp15->regionExecuteMask_SYS[num] = mask ;
+			armcp15->regionExecuteSet_SYS[num] = set ;
+			break ;
+	}
+}
+
+/* precalculate region masks/sets from cp15 register */
+void armcp15_maskPrecalc(armcp15_t *armcp15)
+{
+	#define precalc(num) {  \
+	u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */  \
+	if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \
+	{    /* reason for this define: naming includes var */  \
+		mask = MASKFROMREG(armcp15->protectBaseSize##num) ;   \
+		set = SETFROMREG(armcp15->protectBaseSize##num) ; \
+		if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F)  \
+		{   /* for the 4GB region, u32 suffers wraparound */   \
+		mask = 0 ; set = 0 ;   /* (x & 0) == 0  is allways true (enabled) */  \
+		} \
+	}  \
+		armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ;  \
+	}
+	precalc(0) ;
+	precalc(1) ;
+	precalc(2) ;
+	precalc(3) ;
+	precalc(4) ;
+	precalc(5) ;
+	precalc(6) ;
+	precalc(7) ;
+}
+
+INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access)
+{
+	int i ;
+	if (!(armcp15->ctrl & 1)) return true ;        /* protection checking is not enabled */
+	for (i=0;i<8;i++) {
+		switch (access) {
+		case CP15_ACCESS_WRITEUSR:
+			if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return true ;
+			break ;
+		case CP15_ACCESS_WRITESYS:
+			if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return true ;
+			break ;
+		case CP15_ACCESS_READUSR:
+			if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return true ;
+			break ;
+		case CP15_ACCESS_READSYS:
+			if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return true ;
+			break ;
+		case CP15_ACCESS_EXECUSR:
+			if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return true ;
+			break ;
+		case CP15_ACCESS_EXECSYS:
+			if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return true ;
+			break ;
+		}
+	}
+	/* when protections are enabled, but no region allows access, deny access */
+	return false ;
+}
+
+BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
+{
+   return false;
+}
+
+BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr)
+{
+   return false;
+}
+
+BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr)
+{
+   return false;
+}
+
+BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
+{
+	if(armcp15->cpu->CPSR.bits.mode == USR) return false;
+
+	switch(CRn)
+	{
+		case 0 :
+			if((opcode1 == 0)&&(CRm==0))
+			{
+			switch(opcode2)
+			{
+				case 1 :
+					*R = armcp15->cacheType;
+					return true;
+				case 2 :
+					*R = armcp15->TCMSize;
+					return true;
+				default :
+					*R = armcp15->IDCode;
+					return true;
+			}
+			}
+			return false;
+		case 1 :
+			if((opcode1==0) && (opcode2==0) && (CRm==0))
+			{
+				*R = armcp15->ctrl;
+				return true;
+			}
+			return false;
+
+		case 2 :
+			if((opcode1==0) && (CRm==0))
+			{
+				switch(opcode2)
+				{
+					case 0 :
+						*R = armcp15->DCConfig;
+					return true;
+					case 1 :
+						*R = armcp15->ICConfig;
+					return true;
+					default :
+					return false;
+				}
+			}
+			return false;
+		case 3 :
+			if((opcode1==0) && (opcode2==0) && (CRm==0))
+			{
+				*R = armcp15->writeBuffCtrl;
+				return true;
+			}
+			return false;
+		case 5 :
+			if((opcode1==0) && (CRm==0))
+			{
+				switch(opcode2)
+				{
+					case 2 :
+						*R = armcp15->DaccessPerm;
+					    return true;
+					case 3 :
+						*R = armcp15->IaccessPerm;
+					return true;
+					default :
+					return false;
+				}
+			}
+			return false;
+		case 6 :
+			if((opcode1==0) && (opcode2==0))
+			{
+				switch(CRm)
+				{
+					case 0 :
+						*R = armcp15->protectBaseSize0;
+					return true;
+					case 1 :
+						*R = armcp15->protectBaseSize1;
+					return true;
+					case 2 :
+						*R = armcp15->protectBaseSize2;
+					return true;
+					case 3 :
+						*R = armcp15->protectBaseSize3;
+					return true;
+					case 4 :
+						*R = armcp15->protectBaseSize4;
+					return true;
+					case 5 :
+						*R = armcp15->protectBaseSize5;
+					return true;
+					case 6 :
+						*R = armcp15->protectBaseSize6;
+					return true;
+					case 7 :
+						*R = armcp15->protectBaseSize7;
+					return true;
+					default :
+					return false;
+				}
+			}
+			return false;
+		case 9 :
+			if(opcode1==0)
+			{
+				switch(CRm)
+				{
+					case 0 :
+						switch(opcode2)
+						{
+							case 0 :
+							*R = armcp15->DcacheLock;
+							return true;
+							case 1 :
+							*R = armcp15->IcacheLock;
+							return true;
+							default :
+								return false;
+						}
+					case 1 :
+						switch(opcode2)
+						{
+						case 0 :
+						*R = armcp15->DTCMRegion;
+						return true;
+						case 1 :
+						*R = armcp15->ITCMRegion;
+						return true;
+						default :
+							return false;
+						}
+				}
+			}
+		return false;
+		default :
+			return false;
+	}
+}
+
+
+u32 CP15wait4IRQ(armcpu_t *cpu)
+{
+	/* on the first call, wirq is not set */
+	if(cpu->wirq)
+	{
+		/* check wether an irq was issued */
+		if(!cpu->waitIRQ)
+		{
+			cpu->waitIRQ = 0;
+			cpu->wirq = 0;
+			return 1;   /* return execution */
+		}
+		/* otherwise, repeat this instruction */
+		cpu->R[15] = cpu->instruct_adr;
+		cpu->next_instruction = cpu->R[15];
+		return 1;
+	}
+	/* first run, set us into waiting state */
+	cpu->waitIRQ = 1;
+	cpu->wirq = 1;
+	/* and set next instruction to repeat this */
+	cpu->R[15] = cpu->instruct_adr;
+	cpu->next_instruction = cpu->R[15];
+	/* CHECKME: IME shouldn't be modified (?) */
+	MMU.reg_IME[0] = 1;
+	return 1;
+}
+
+BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2)
+{
+	if(armcp15->cpu->CPSR.bits.mode == USR) return false;
+
+	switch(CRn)
+	{
+		case 1 :
+		if((opcode1==0) && (opcode2==0) && (CRm==0))
+		{
+			armcp15->ctrl = val;
+			MMU.ARM9_RW_MODE = BIT7(val);
+			armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val));
+			armcp15->cpu->LDTBit = !BIT15(val); //TBit
+			/*if(BIT17(val))
+			{
+				log::ajouter("outch !!!!!!!");
+			}
+			if(BIT19(val))
+			{
+				log::ajouter("outch !!!!!!!");
+			}*/
+			return true;
+		}
+		return false;
+		case 2 :
+		if((opcode1==0) && (CRm==0))
+		{
+			switch(opcode2)
+			{
+				case 0 :
+					armcp15->DCConfig = val;
+					return true;
+				case 1 :
+					armcp15->ICConfig = val;
+					return true;
+				default :
+					return false;
+			}
+		}
+		return false;
+		case 3 :
+		if((opcode1==0) && (opcode2==0) && (CRm==0))
+		{
+			armcp15->writeBuffCtrl = val;
+			return true;
+		}
+		return false;
+		if((opcode1==0) && (CRm==0))
+		{
+			switch(opcode2)
+			{
+				case 2 :
+					armcp15->DaccessPerm = val;
+					armcp15_maskPrecalc(armcp15);
+ 					return true;
+				case 3 :
+					armcp15->IaccessPerm = val;
+					armcp15_maskPrecalc(armcp15);
+					return true;
+				default :
+					return false;
+			}
+		}
+		return false;
+		case 6 :
+		if((opcode1==0) && (opcode2==0))
+		{
+			switch(CRm)
+			{
+				case 0 :
+					armcp15->protectBaseSize0 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 1 :
+					armcp15->protectBaseSize1 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 2 :
+					armcp15->protectBaseSize2 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 3 :
+					armcp15->protectBaseSize3 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 4 :
+					armcp15->protectBaseSize4 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 5 :
+					armcp15->protectBaseSize5 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 6 :
+					armcp15->protectBaseSize6 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				case 7 :
+					armcp15->protectBaseSize7 = val;
+					armcp15_maskPrecalc(armcp15) ;
+					return true;
+				default :
+					return false;
+			}
+		}
+		return false;
+		case 7 :
+		if((CRm==0)&&(opcode1==0)&&((opcode2==4)))
+		{
+			CP15wait4IRQ(armcp15->cpu);
+			return true;
+		}
+		return false;
+		case 9 :
+		if(opcode1==0)
+		{
+			switch(CRm)
+			{
+				case 0 :
+				switch(opcode2)
+				{
+					case 0 :
+						armcp15->DcacheLock = val;
+						return true;
+					case 1 :
+						armcp15->IcacheLock = val;
+						return true;
+					default :
+						return false;
+			}
+			case 1 :
+			switch(opcode2)
+			{
+				case 0 :
+					armcp15->DTCMRegion = val;
+					MMU.DTCMRegion = val & 0x0FFFFFFC0;
+					/*sprintf(logbuf, "%08X", val);
+					log::ajouter(logbuf);*/
+					return true;
+				case 1 :
+					armcp15->ITCMRegion = val;
+					/* ITCM base is not writeable! */
+					MMU.ITCMRegion = 0;
+					return true;
+				default :
+					return false;
+				}
+			}
+		}
+		return false;
+		default :
+			return false;
+	}
+}
+
+
+
diff --git a/src/xsf/desmume/cp15.h b/src/xsf/desmume/cp15.h
index 83122516bce5..4735a9668311 100644
--- a/src/xsf/desmume/cp15.h
+++ b/src/xsf/desmume/cp15.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef __CP15_H__
diff --git a/src/xsf/desmume/dscard.h b/src/xsf/desmume/dscard.h
index 9b002e3479c3..dc185e1c36b4 100644
--- a/src/xsf/desmume/dscard.h
+++ b/src/xsf/desmume/dscard.h
@@ -14,7 +14,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef __DSCARD_H__
diff --git a/src/xsf/desmume/instruction_tabdef.inc b/src/xsf/desmume/instruction_tabdef.inc
index f63763a732a7..cc7d9416ca37 100644
--- a/src/xsf/desmume/instruction_tabdef.inc
+++ b/src/xsf/desmume/instruction_tabdef.inc
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 TYPE_RETOUR (*CALLTYPE NOM_TAB[4096])(PARAMETRES)={
diff --git a/src/xsf/desmume/matrix.c b/src/xsf/desmume/matrix.c
deleted file mode 100644
index 555d62b1532d..000000000000
--- a/src/xsf/desmume/matrix.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*  
-	Copyright (C) 2006-2007 shash
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "matrix.h"
-
-void MatrixInit  (float *matrix)
-{
-	memset (matrix, 0, sizeof(float)*16);
-
-	matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
-}
-
-void MatrixMultVec4x4 (float *matrix, float *vecPtr)
-{
-	float x = vecPtr[0];
-	float y = vecPtr[1];
-	float z = vecPtr[2];
-
-	vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12];
-	vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13];
-	vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
-}
-
-void MatrixMultVec3x3 (float *matrix, float *vecPtr)
-{
-	float x = vecPtr[0];
-	float y = vecPtr[1];
-	float z = vecPtr[2];
-
-	vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8];
-	vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9];
-	vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10];
-}
-
-void MatrixIdentity	(float *matrix)
-{
-	memset (matrix, 0, sizeof(float)*16);
-
-	matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
-}
-
-void MatrixMultiply (float *matrix, float *rightMatrix)
-{
-	float tmpMatrix[16];
-
-	tmpMatrix[0]  = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]);
-	tmpMatrix[1]  = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]);
-	tmpMatrix[2]  = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]);
-	tmpMatrix[3]  = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]);
-
-	tmpMatrix[4]  = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]);
-	tmpMatrix[5]  = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]);
-	tmpMatrix[6]  = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]);
-	tmpMatrix[7]  = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]);
-
-	tmpMatrix[8]  = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]);
-	tmpMatrix[9]  = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]);
-	tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]);
-	tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]);
-
-	tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]);
-	tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]);
-	tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]);
-	tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]);
-
-	memcpy (matrix, tmpMatrix, sizeof(float)*16);
-}
-/*
-void MatrixMulti (float* right)
-{
-	float tmpMatrix[16];
-
-	tmpMatrix[0]  = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]);
-	tmpMatrix[1]  = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]);
-	tmpMatrix[2]  = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]);
-	tmpMatrix[3]  = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]);
-
-	tmpMatrix[4]  = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]);
-	tmpMatrix[5]  = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]);
-	tmpMatrix[6]  = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]);
-	tmpMatrix[7]  = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]);
-
-	tmpMatrix[8]  = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]);
-	tmpMatrix[9]  = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]);
-	tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]);
-	tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]);
-
-	tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]);
-	tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]);
-	tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]);
-	tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]);
-
-	memcpy (matrix, tmpMatrix, sizeof(float)*16);
-}
-
-
-float*	Matrix::Get		(void)
-{
-	return matrix;
-}
-
-float MatrixGet (float *matrix, int index)
-{
-	return matrix[index];
-}
-*/
-
-float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix)
-{
-	int iMod = index%4, iDiv = (index>>2)<<2;
-
-	return	(matrix[iMod  ]*rightMatrix[iDiv  ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+
-			(matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]);
-}
-
-void MatrixSet (float *matrix, int x, int y, float value)
-{
-	matrix [x+(y<<2)] = value;
-}
-/*
-void	Matrix::Set		(int pos, float value)
-{
-	matrix [pos] = value;
-}
-*/
-void MatrixCopy (float *matrixDST, float *matrixSRC)
-{
-	memcpy (matrixDST, matrixSRC, sizeof(float)*16);
-}
-
-void MatrixTranslate	(float *matrix, float *ptr)
-{
-	matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]);
-	matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]);
-	matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]);
-	matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]);
-}
-
-void MatrixScale (float *matrix, float *ptr)
-{
-	matrix[0]  *= ptr[0];
-	matrix[1]  *= ptr[0];
-	matrix[2]  *= ptr[0];
-	matrix[3]  *= ptr[0];
-
-	matrix[4]  *= ptr[1];
-	matrix[5]  *= ptr[1];
-	matrix[6]  *= ptr[1];
-	matrix[7]  *= ptr[1];
-
-	matrix[8] *= ptr[2];
-	matrix[9] *= ptr[2];
-	matrix[10] *= ptr[2];
-	matrix[11] *= ptr[2];
-}
-/*
-void	Matrix::Set	(float a11, float a21, float a31, float a41,
-					 float a12, float a22, float a32, float a42,
-					 float a13, float a23, float a33, float a43,
-					 float a14, float a24, float a34, float a44)
-{
-}
-*/
-
-
-//-----------------------------------------
-
-void MatrixStackInit (MatrixStack *stack)
-{
-	stack->matrix	= NULL;
-	stack->position	= 0;
-	stack->size		= 0;
-}
-
-void MatrixStackSetMaxSize (MatrixStack *stack, int size)
-{
-	int i = 0;
-
-	stack->size = size;
-
-	if (stack->matrix == NULL)
-	{
-		stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
-	}
-	else
-	{
-		free (stack->matrix);
-		stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
-	}
-
-	for (i = 0; i < stack->size; i++)
-	{
-		MatrixInit (&stack->matrix[i*16]);
-	}
-
-	stack->size--;
-}
-
-
-void MatrixStackSetStackPosition (MatrixStack *stack, int pos)
-{
-	stack->position += pos;
-
-	if (stack->position < 0)
-		stack->position = 0;
-	else if (stack->position > stack->size)	
-		stack->position = stack->size;
-}
-
-void MatrixStackPushMatrix (MatrixStack *stack, float *ptr)
-{
-	MatrixCopy (&stack->matrix[stack->position*16], ptr);
-
-	MatrixStackSetStackPosition (stack, 1);
-}
-
-float * MatrixStackPopMatrix (MatrixStack *stack, int size)
-{
-	MatrixStackSetStackPosition(stack, -size);
-
-	return &stack->matrix[stack->position*16];
-}
-
-float * MatrixStackGetPos (MatrixStack *stack, int pos)
-{
-	return &stack->matrix[pos*16];
-}
-
-float * MatrixStackGet (MatrixStack *stack)
-{
-	return &stack->matrix[stack->position*16];
-}
-
-void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr)
-{
-	MatrixCopy (&stack->matrix[pos*16], ptr);
-}
diff --git a/src/xsf/desmume/matrix.cc b/src/xsf/desmume/matrix.cc
new file mode 100644
index 000000000000..217ad316b83e
--- /dev/null
+++ b/src/xsf/desmume/matrix.cc
@@ -0,0 +1,257 @@
+/*
+	Copyright (C) 2006-2007 shash
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "matrix.h"
+
+void MatrixInit  (float *matrix)
+{
+	memset (matrix, 0, sizeof(float)*16);
+
+	matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
+}
+
+void MatrixMultVec4x4 (float *matrix, float *vecPtr)
+{
+	float x = vecPtr[0];
+	float y = vecPtr[1];
+	float z = vecPtr[2];
+
+	vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12];
+	vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13];
+	vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
+}
+
+void MatrixMultVec3x3 (float *matrix, float *vecPtr)
+{
+	float x = vecPtr[0];
+	float y = vecPtr[1];
+	float z = vecPtr[2];
+
+	vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8];
+	vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9];
+	vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10];
+}
+
+void MatrixIdentity	(float *matrix)
+{
+	memset (matrix, 0, sizeof(float)*16);
+
+	matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
+}
+
+void MatrixMultiply (float *matrix, float *rightMatrix)
+{
+	float tmpMatrix[16];
+
+	tmpMatrix[0]  = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]);
+	tmpMatrix[1]  = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]);
+	tmpMatrix[2]  = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]);
+	tmpMatrix[3]  = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]);
+
+	tmpMatrix[4]  = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]);
+	tmpMatrix[5]  = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]);
+	tmpMatrix[6]  = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]);
+	tmpMatrix[7]  = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]);
+
+	tmpMatrix[8]  = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]);
+	tmpMatrix[9]  = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]);
+	tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]);
+	tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]);
+
+	tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]);
+	tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]);
+	tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]);
+	tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]);
+
+	memcpy (matrix, tmpMatrix, sizeof(float)*16);
+}
+/*
+void MatrixMulti (float* right)
+{
+	float tmpMatrix[16];
+
+	tmpMatrix[0]  = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]);
+	tmpMatrix[1]  = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]);
+	tmpMatrix[2]  = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]);
+	tmpMatrix[3]  = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]);
+
+	tmpMatrix[4]  = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]);
+	tmpMatrix[5]  = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]);
+	tmpMatrix[6]  = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]);
+	tmpMatrix[7]  = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]);
+
+	tmpMatrix[8]  = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]);
+	tmpMatrix[9]  = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]);
+	tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]);
+	tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]);
+
+	tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]);
+	tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]);
+	tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]);
+	tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]);
+
+	memcpy (matrix, tmpMatrix, sizeof(float)*16);
+}
+
+
+float*	Matrix::Get		(void)
+{
+	return matrix;
+}
+
+float MatrixGet (float *matrix, int index)
+{
+	return matrix[index];
+}
+*/
+
+float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix)
+{
+	int iMod = index%4, iDiv = (index>>2)<<2;
+
+	return	(matrix[iMod  ]*rightMatrix[iDiv  ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+
+			(matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]);
+}
+
+void MatrixSet (float *matrix, int x, int y, float value)
+{
+	matrix [x+(y<<2)] = value;
+}
+/*
+void	Matrix::Set		(int pos, float value)
+{
+	matrix [pos] = value;
+}
+*/
+void MatrixCopy (float *matrixDST, float *matrixSRC)
+{
+	memcpy (matrixDST, matrixSRC, sizeof(float)*16);
+}
+
+void MatrixTranslate	(float *matrix, float *ptr)
+{
+	matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]);
+	matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]);
+	matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]);
+	matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]);
+}
+
+void MatrixScale (float *matrix, float *ptr)
+{
+	matrix[0]  *= ptr[0];
+	matrix[1]  *= ptr[0];
+	matrix[2]  *= ptr[0];
+	matrix[3]  *= ptr[0];
+
+	matrix[4]  *= ptr[1];
+	matrix[5]  *= ptr[1];
+	matrix[6]  *= ptr[1];
+	matrix[7]  *= ptr[1];
+
+	matrix[8] *= ptr[2];
+	matrix[9] *= ptr[2];
+	matrix[10] *= ptr[2];
+	matrix[11] *= ptr[2];
+}
+/*
+void	Matrix::Set	(float a11, float a21, float a31, float a41,
+					 float a12, float a22, float a32, float a42,
+					 float a13, float a23, float a33, float a43,
+					 float a14, float a24, float a34, float a44)
+{
+}
+*/
+
+
+//-----------------------------------------
+
+void MatrixStackInit (MatrixStack *stack)
+{
+	stack->matrix	= nullptr;
+	stack->position	= 0;
+	stack->size		= 0;
+}
+
+void MatrixStackSetMaxSize (MatrixStack *stack, int size)
+{
+	int i = 0;
+
+	stack->size = size;
+
+	if (stack->matrix == nullptr)
+	{
+		stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
+	}
+	else
+	{
+		free (stack->matrix);
+		stack->matrix = (float*) malloc (stack->size*16*sizeof(float));
+	}
+
+	for (i = 0; i < stack->size; i++)
+	{
+		MatrixInit (&stack->matrix[i*16]);
+	}
+
+	stack->size--;
+}
+
+
+void MatrixStackSetStackPosition (MatrixStack *stack, int pos)
+{
+	stack->position += pos;
+
+	if (stack->position < 0)
+		stack->position = 0;
+	else if (stack->position > stack->size)
+		stack->position = stack->size;
+}
+
+void MatrixStackPushMatrix (MatrixStack *stack, float *ptr)
+{
+	MatrixCopy (&stack->matrix[stack->position*16], ptr);
+
+	MatrixStackSetStackPosition (stack, 1);
+}
+
+float * MatrixStackPopMatrix (MatrixStack *stack, int size)
+{
+	MatrixStackSetStackPosition(stack, -size);
+
+	return &stack->matrix[stack->position*16];
+}
+
+float * MatrixStackGetPos (MatrixStack *stack, int pos)
+{
+	return &stack->matrix[pos*16];
+}
+
+float * MatrixStackGet (MatrixStack *stack)
+{
+	return &stack->matrix[stack->position*16];
+}
+
+void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr)
+{
+	MatrixCopy (&stack->matrix[pos*16], ptr);
+}
diff --git a/src/xsf/desmume/matrix.h b/src/xsf/desmume/matrix.h
index 05c0786e2b94..d9aa8cb1d8ff 100644
--- a/src/xsf/desmume/matrix.h
+++ b/src/xsf/desmume/matrix.h
@@ -15,7 +15,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef MATRIX_H
diff --git a/src/xsf/desmume/mc.c b/src/xsf/desmume/mc.c
deleted file mode 100644
index 756a92c8d9de..000000000000
--- a/src/xsf/desmume/mc.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*  Copyright (C) 2006 thoduv
-    Copyright (C) 2006-2007 Theo Berkau
-
-    This file is part of DeSmuME
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <stdlib.h>
-#include "debug.h"
-#include "types.h"
-#include "mc.h"
-
-#define FW_CMD_READ             0x3
-#define FW_CMD_WRITEDISABLE     0x4
-#define FW_CMD_READSTATUS       0x5
-#define FW_CMD_WRITEENABLE      0x6
-#define FW_CMD_PAGEWRITE        0xA
-
-#define BM_CMD_AUTODETECT       0xFF
-#define BM_CMD_WRITESTATUS      0x1
-#define BM_CMD_WRITELOW         0x2
-#define BM_CMD_READLOW          0x3
-#define BM_CMD_WRITEDISABLE     0x4
-#define BM_CMD_READSTATUS       0x5
-#define BM_CMD_WRITEENABLE      0x6
-#define BM_CMD_WRITEHIGH        0xA
-#define BM_CMD_READHIGH         0xB
-
-/* FLASH*/
-#define COMM_PAGE_WRITE		0x0A
-#define COMM_PAGE_ERASE		0xDB
-#define COMM_SECTOR_ERASE	0xD8
-#define COMM_CHIP_ERASE		0xC7
-#define CARDFLASH_READ_BYTES_FAST	0x0B    /* Not used*/
-#define CARDFLASH_DEEP_POWDOWN		0xB9    /* Not used*/
-#define CARDFLASH_WAKEUP			0xAB    /* Not used*/
-
-void mc_init(memory_chip_t *mc, int type)
-{
-        mc->com = 0;
-        mc->addr = 0;
-        mc->addr_shift = 0;
-        mc->data = NULL;
-        mc->size = 0;
-        mc->write_enable = FALSE;
-        mc->writeable_buffer = FALSE;
-        mc->type = type;
-        mc->autodetectsize = 0;
-                               
-        switch(mc->type)
-        {
-           case MC_TYPE_EEPROM1:
-              mc->addr_size = 1;
-              break;
-           case MC_TYPE_EEPROM2:
-           case MC_TYPE_FRAM:
-              mc->addr_size = 2;
-              break;
-           case MC_TYPE_FLASH:
-              mc->addr_size = 3;
-              break;
-           default: break;
-        }
-}
-
-u8 *mc_alloc(memory_chip_t *mc, u32 size)
-{
-	u8 *buffer;
-	buffer = malloc(size);
-
-	mc->data = buffer;
-	if(!buffer) { return NULL; }
-	mc->size = size;
-	mc->writeable_buffer = TRUE;
-
-	return buffer;
-}
-
-void mc_free(memory_chip_t *mc)
-{
-	if(mc->data)
-	{
-		free(mc->data);
-		mc->data = 0;
-	}
-	mc_init(mc, 0);
-}
-
-void mc_realloc(memory_chip_t *mc, int type, u32 size)
-{
-	mc_free(mc);
-	mc_init(mc, type);
-	mc_alloc(mc, size);
-}
-
-
-void mc_reset_com(memory_chip_t *mc)
-{
-}
-u8 fw_transfer(memory_chip_t *mc, u8 data)
-{
-	return 0;
-}
-u8 bm_transfer(memory_chip_t *mc, u8 data)
-{
-	return 0;
-}
-
diff --git a/src/xsf/desmume/mc.cc b/src/xsf/desmume/mc.cc
new file mode 100644
index 000000000000..4f7dd706644f
--- /dev/null
+++ b/src/xsf/desmume/mc.cc
@@ -0,0 +1,121 @@
+/*  Copyright (C) 2006 thoduv
+    Copyright (C) 2006-2007 Theo Berkau
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdlib.h>
+#include "debug.h"
+#include "types.h"
+#include "mc.h"
+
+#define FW_CMD_READ             0x3
+#define FW_CMD_WRITEDISABLE     0x4
+#define FW_CMD_READSTATUS       0x5
+#define FW_CMD_WRITEENABLE      0x6
+#define FW_CMD_PAGEWRITE        0xA
+
+#define BM_CMD_AUTODETECT       0xFF
+#define BM_CMD_WRITESTATUS      0x1
+#define BM_CMD_WRITELOW         0x2
+#define BM_CMD_READLOW          0x3
+#define BM_CMD_WRITEDISABLE     0x4
+#define BM_CMD_READSTATUS       0x5
+#define BM_CMD_WRITEENABLE      0x6
+#define BM_CMD_WRITEHIGH        0xA
+#define BM_CMD_READHIGH         0xB
+
+/* FLASH*/
+#define COMM_PAGE_WRITE		0x0A
+#define COMM_PAGE_ERASE		0xDB
+#define COMM_SECTOR_ERASE	0xD8
+#define COMM_CHIP_ERASE		0xC7
+#define CARDFLASH_READ_BYTES_FAST	0x0B    /* Not used*/
+#define CARDFLASH_DEEP_POWDOWN		0xB9    /* Not used*/
+#define CARDFLASH_WAKEUP			0xAB    /* Not used*/
+
+void mc_init(memory_chip_t *mc, int type)
+{
+        mc->com = 0;
+        mc->addr = 0;
+        mc->addr_shift = 0;
+        mc->data = nullptr;
+        mc->size = 0;
+        mc->write_enable = false;
+        mc->writeable_buffer = false;
+        mc->type = type;
+        mc->autodetectsize = 0;
+
+        switch(mc->type)
+        {
+           case MC_TYPE_EEPROM1:
+              mc->addr_size = 1;
+              break;
+           case MC_TYPE_EEPROM2:
+           case MC_TYPE_FRAM:
+              mc->addr_size = 2;
+              break;
+           case MC_TYPE_FLASH:
+              mc->addr_size = 3;
+              break;
+           default: break;
+        }
+}
+
+u8 *mc_alloc(memory_chip_t *mc, u32 size)
+{
+	u8 *buffer;
+	buffer = (u8 *) malloc(size);
+
+	mc->data = buffer;
+	if(!buffer) { return nullptr; }
+	mc->size = size;
+	mc->writeable_buffer = true;
+
+	return buffer;
+}
+
+void mc_free(memory_chip_t *mc)
+{
+	if(mc->data)
+	{
+		free(mc->data);
+		mc->data = 0;
+	}
+	mc_init(mc, 0);
+}
+
+void mc_realloc(memory_chip_t *mc, int type, u32 size)
+{
+	mc_free(mc);
+	mc_init(mc, type);
+	mc_alloc(mc, size);
+}
+
+
+void mc_reset_com(memory_chip_t *mc)
+{
+}
+u8 fw_transfer(memory_chip_t *mc, u8 data)
+{
+	return 0;
+}
+u8 bm_transfer(memory_chip_t *mc, u8 data)
+{
+	return 0;
+}
+
diff --git a/src/xsf/desmume/mc.h b/src/xsf/desmume/mc.h
index dd567c9d0280..3e9f4e298ee2 100644
--- a/src/xsf/desmume/mc.h
+++ b/src/xsf/desmume/mc.h
@@ -15,16 +15,12 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef __FW_H__
 #define __FW_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <stdio.h>
 #include "types.h"
 
@@ -51,9 +47,9 @@ typedef struct
         u32 addr;        /* current address for reading/writing */
         u8 addr_shift;   /* shift for address (since addresses are transfered by 3 bytes units) */
         u8 addr_size;    /* size of addr when writing/reading */
-	
+
 	BOOL write_enable;	/* is write enabled ? */
-	
+
         u8 *data;       /* memory data */
         u32 size;       /* memory size */
 	BOOL writeable_buffer;	/* is "data" writeable ? */
@@ -77,9 +73,5 @@ void mc_reset_com(memory_chip_t *mc);       /* reset communication with mc */
 u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */
 u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /*__FW_H__*/
 
diff --git a/src/xsf/desmume/mem.h b/src/xsf/desmume/mem.h
index 72060f1f5531..5d48c2b9d50c 100644
--- a/src/xsf/desmume/mem.h
+++ b/src/xsf/desmume/mem.h
@@ -15,7 +15,7 @@
 
     You should have received a copy of the GNU General Public License
     along with Yabause; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef MEM_H
diff --git a/src/xsf/desmume/registers.h b/src/xsf/desmume/registers.h
index f9060214d916..3371b4c257ff 100644
--- a/src/xsf/desmume/registers.h
+++ b/src/xsf/desmume/registers.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef REGISTERS_H
diff --git a/src/xsf/desmume/thumb_instructions.c b/src/xsf/desmume/thumb_instructions.c
deleted file mode 100644
index fbe5e31c8dbe..000000000000
--- a/src/xsf/desmume/thumb_instructions.c
+++ /dev/null
@@ -1,944 +0,0 @@
-/*  
-	Copyright (C) 2006 yopyop
-    yopyop156 at ifrance.com
-    yopyop156.ifrance.com
-
-	Code added on 18/08/2006 by shash
-		- Missing missaligned addresses correction
-			(reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments)
-
-    This file is part of DeSmuME 
-
-    DeSmuME 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.
-
-    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "bios.h"
-#include "debug.h"
-#include "MMU.h"
-
-#define REG_NUM(i, n) (((i)>>n)&0x7)
-
-extern BOOL execute;
-
-// Use this macros for reading/writing, so the GDB stub isn't broken
-#ifdef GDB_STUB
-	#define READ32(a,b)		cpu->mem_if->read32(a,b)
-	#define WRITE32(a,b,c)	cpu->mem_if->write32(a,b,c)
-	#define READ16(a,b)		cpu->mem_if->read16(a,b)
-	#define WRITE16(a,b,c)	cpu->mem_if->write16(a,b,c)
-	#define READ8(a,b)		cpu->mem_if->read8(a,b)
-	#define WRITE8(a,b,c)	cpu->mem_if->write8(a,b,c)
-#else
-	#define READ32(a,b)		MMU_read32(cpu->proc_ID, b)
-	#define WRITE32(a,b,c)	MMU_write32(cpu->proc_ID,b,c)
-	#define READ16(a,b)		MMU_read16(cpu->proc_ID, b)
-	#define WRITE16(a,b,c)	MMU_write16(cpu->proc_ID,b,c)
-	#define READ8(a,b)		MMU_read8(cpu->proc_ID, b)
-	#define WRITE8(a,b,c)	MMU_write8(cpu->proc_ID,b,c)
-#endif
-
-static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu)
-{
-     execute = FALSE;
-     return 1;
-}
-
-static u32 FASTCALL OP_LSL_0(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-	  
-     return 2;
-}
-
-static u32 FASTCALL OP_LSL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = (i>>6) & 0x1F;
-     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v);
-     cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-	  
-     return 2;
-}
-
-static u32 FASTCALL OP_LSR_0(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-	  // cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
-     cpu->R[REG_NUM(i, 0)] = 0;
-     cpu->CPSR.bits.N = 0;
-     cpu->CPSR.bits.Z = 1;
-	  
-     return 2;
-}
-
-static u32 FASTCALL OP_LSR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = (i>>6) & 0x1F;
-     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
-     cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_ASR_0(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
-     cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_ASR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = (i>>6) & 0x1F;
-     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1);
-     cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 3)];
-     u32 b = cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = a + b;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 3)];
-     u32 b = cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = a - b;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 3)];
-     cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 3)];
-     cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 8)] = i & 0xFF;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF);
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     cpu->R[REG_NUM(i, 8)] = tmp;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
-     cpu->R[REG_NUM(i, 8)] = tmp;
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_AND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_EOR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
-     
-     if(!v)
-     {
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }     
-     if(v<32)
-     {
-          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v);
-          cpu->R[REG_NUM(i, 0)] <<= v;
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }
-     if(v==32)
-          cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]);
-     else
-          cpu->CPSR.bits.C = 0;
-     cpu->R[REG_NUM(i, 0)] = 0;
-     cpu->CPSR.bits.N = 0;
-     cpu->CPSR.bits.Z = 1;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
-     
-     if(!v)
-     {
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }     
-     if(v<32)
-     {
-          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
-          cpu->R[REG_NUM(i, 0)] >>= v;
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }
-     if(v==32)
-          cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
-     else
-          cpu->CPSR.bits.C = 0;
-     cpu->R[REG_NUM(i, 0)] = 0;
-     cpu->CPSR.bits.N = 0;
-     cpu->CPSR.bits.Z = 1;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
-     
-     if(!v)
-     {
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }     
-     if(v<32)
-     {
-          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
-          cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v);
-          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-          return 3;
-     }
-     
-     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF;
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 0)];
-     u32 b = cpu->R[REG_NUM(i, 3)];
-     u32 tmp = b + cpu->CPSR.bits.C;
-     u32 res = a + tmp;
-
-     cpu->R[REG_NUM(i, 0)] = res;
-     
-     cpu->CPSR.bits.N = BIT31(res);
-     cpu->CPSR.bits.Z = res == 0;
-     
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res);
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 0)];
-     u32 b = cpu->R[REG_NUM(i, 3)];
-     u32 tmp = a - (!cpu->CPSR.bits.C);
-     u32 res = tmp - b;
-     cpu->R[REG_NUM(i, 0)] = res;
-     
-     cpu->CPSR.bits.N = BIT31(res);
-     cpu->CPSR.bits.Z = res == 0;
-     
-     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res));
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
-     
-     if(v == 0)
-     {
-               cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-               cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-               return 3;
-     }
-     v &= 0xF;
-     if(v == 0)
-     {
-               cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
-               cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-               cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-               return 3;
-     }
-     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
-     cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_TST(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_NEG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 a = cpu->R[REG_NUM(i, 3)];
-     cpu->R[REG_NUM(i, 0)] = -((signed int)a);
-     
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_CMP(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)];
-     
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_CMN(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)];
-     
-     //execute = FALSE;
-     //log::ajouter("OP_CMN THUMB");
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
-     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ORR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)];
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_BIC(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_MVN(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]);
-     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
-     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 Rd = (i&7) | ((i>>4)&8);
-     cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
-     
-     if(Rd==15)
-          cpu->next_instruction = cpu->R[15];
-          
-     return 2;
-}
-
-static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 Rn = (i&7) | ((i>>4)&8);
-     u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)];
-     
-     cpu->CPSR.bits.N = BIT31(tmp);
-     cpu->CPSR.bits.Z = tmp == 0;
-     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
-     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 Rd = (i&7) | ((i>>4)&8);
-     cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
-     
-     if(Rd==15)
-          cpu->next_instruction = cpu->R[15];
-          
-     return 2;
-}
-
-static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu)
-{
-     u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
-     
-     cpu->CPSR.bits.T = BIT0(Rm);
-     cpu->R[15] = (Rm & 0xFFFFFFFE);
-     cpu->next_instruction = cpu->R[15];
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu)
-{
-     u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
-     
-     cpu->CPSR.bits.T = BIT0(Rm);
-     cpu->R[14] = cpu->next_instruction | 1;
-     cpu->R[15] = (Rm & 0xFFFFFFFE);
-     cpu->next_instruction = cpu->R[15];
-     
-     return 3;
-}
-
-static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu)
-{
-	u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2);
-     
-    cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr);
-               
-    return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)];
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
-               
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)]));
-               
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)]));
-               
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]);
-	 u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
-
-	 adr = (adr&3)*8;
-	 tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
-	 cpu->R[REG_NUM(i, 0)] = tempValue;
-               
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr);
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr);
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
-     cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
-               
-     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
-     u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
-	 adr = (adr&3)*8;
-	 tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
-	 cpu->R[REG_NUM(i, 0)] = tempValue;
-               
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
-     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]);
-               
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
-     cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr);
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
-     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]);
-               
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
-     cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr);
-               
-     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13] + ((i&0xFF)<<2);
-     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]);
-               
-     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13] + ((i&0xFF)<<2);
-	 cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr);
-               
-     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-}
-
-static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2);
-               
-     return 5;
-}
-
-static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
-     
-     return 2;
-}
-
-static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu)
-{
-     cpu->R[13] += ((cpu->instruction&0x7F)<<2);
-     
-     return 1;
-}
-
-static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu)
-{
-     cpu->R[13] -= ((cpu->instruction&0x7F)<<2);
-     
-     return 1;
-}
-
-static u32 FASTCALL OP_PUSH(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13] - 4;
-     u32 c = 0, j;
-     
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, 7-j))
-          {
-               WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr -= 4;
-          }
-     cpu->R[13] = adr + 4;
-     
-     return c + 3;
-}
-
-static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13] - 4;
-     u32 c = 0, j;
-     
-     WRITE32(cpu->mem_if->data, adr, cpu->R[14]);
-     c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     adr -= 4;
-          
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, 7-j))
-          {
-               WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr -= 4;
-          }
-     cpu->R[13] = adr + 4;
-     
-     return c + 4;
-}
-
-static u32 FASTCALL OP_POP(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13];
-     u32 c = 0, j;
-
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, j))
-          {
-               cpu->R[j] = READ32(cpu->mem_if->data, adr);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr += 4;
-          }
-     cpu->R[13] = adr;       
-     
-     return c + 2;
-}
-
-static u32 FASTCALL OP_POP_PC(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[13];
-     u32 c = 0, j;
-     u32 v;
-
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, j))
-          {
-               cpu->R[j] = READ32(cpu->mem_if->data, adr);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr += 4;
-          }
-
-     v = READ32(cpu->mem_if->data, adr);
-     c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-     cpu->R[15] = v & 0xFFFFFFFE;
-     cpu->next_instruction = v & 0xFFFFFFFE;
-     if(cpu->proc_ID==0)
-          cpu->CPSR.bits.T = BIT0(v);
-     adr += 4;
-
-     cpu->R[13] = adr;   
-     return c + 5;    
-}
-
-static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu)
-{
-     return 1;
-}
-
-static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 8)];
-     u32 c = 0, j;
-
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, j))
-          {
-               WRITE32(cpu->mem_if->data, adr, cpu->R[j]);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr += 4;
-          }
-     cpu->R[REG_NUM(i, 8)] = adr;
-     return c + 2;
-}
-
-static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     u32 adr = cpu->R[REG_NUM(i, 8)];
-     u32 c = 0, j;
-
-     for(j = 0; j<8; ++j)
-          if(BIT_N(i, j))
-          {
-               cpu->R[j] = READ32(cpu->mem_if->data, adr);
-               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
-               adr += 4;
-          }
-     cpu->R[REG_NUM(i, 8)] = adr;
-     return c + 3;
-}
-
-static u32 FASTCALL OP_B_COND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR))
-          return 1;
-     
-     cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1;
-     cpu->next_instruction = cpu->R[15];
-     return 3;
-}
-
-static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu)
-{
-     if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
-     {
-        /* we use an irq thats not in the irq tab, as
-        it was replaced duie to a changed intVector */
-        Status_Reg tmp = cpu->CPSR;
-        armcpu_switchMode(cpu, SVC);            /* enter svc mode */
-        cpu->R[14] = cpu->R[15] - 4;            /* jump to swi Vector */
-        cpu->SPSR = tmp;                        /* save old CPSR as new SPSR */
-        cpu->CPSR.bits.T = 0;                   /* handle as ARM32 code */
-        cpu->CPSR.bits.I = cpu->SPSR.bits.I;    /* keep int disable flag */
-        cpu->R[15] = cpu->intVector + 0x08;
-        cpu->next_instruction = cpu->R[15];
-        return 3;
-     }
-     else
-     {
-        u32 swinum = cpu->instruction & 0xFF;
-        return cpu->swi_tab[swinum](cpu) + 3;  
-     }
-     //return 3;
-}
-
-#define SIGNEEXT_IMM11(i)     (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800))
-
-static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[15] += (SIGNEEXT_IMM11(i)<<1);
-     cpu->next_instruction = cpu->R[15];
-     return 3;
-}
- 
-static u32 FASTCALL OP_BLX(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC;
-     cpu->R[14] = cpu->next_instruction | 1;
-     cpu->next_instruction = cpu->R[15];
-     cpu->CPSR.bits.T = 0;
-     return 3;
-}
-
-static u32 FASTCALL OP_BL_10(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12);
-     return 1;
-}
-
-static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu)
-{
-     u32 i = cpu->instruction;
-     cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1));
-     cpu->R[14] = cpu->next_instruction | 1;
-     cpu->next_instruction = cpu->R[15];
-     return 3;
-}
-
-#define TYPE_RETOUR u32
-#define CALLTYPE FASTCALL 
-#define PARAMETRES  armcpu_t *cpu
-#define NOM_THUMB_TAB     thumb_instructions_set
-
-#include "thumb_tabdef.inc"
diff --git a/src/xsf/desmume/thumb_instructions.cc b/src/xsf/desmume/thumb_instructions.cc
new file mode 100644
index 000000000000..fedf03b900ff
--- /dev/null
+++ b/src/xsf/desmume/thumb_instructions.cc
@@ -0,0 +1,944 @@
+/*
+	Copyright (C) 2006 yopyop
+    yopyop156 at ifrance.com
+    yopyop156.ifrance.com
+
+	Code added on 18/08/2006 by shash
+		- Missing missaligned addresses correction
+			(reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments)
+
+    This file is part of DeSmuME
+
+    DeSmuME 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.
+
+    DeSmuME is distributed in the hope that 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 DeSmuME; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "bios.h"
+#include "debug.h"
+#include "MMU.h"
+
+#define REG_NUM(i, n) (((i)>>n)&0x7)
+
+extern BOOL execute;
+
+// Use this macros for reading/writing, so the GDB stub isn't broken
+#ifdef GDB_STUB
+	#define READ32(a,b)		cpu->mem_if->read32(a,b)
+	#define WRITE32(a,b,c)	cpu->mem_if->write32(a,b,c)
+	#define READ16(a,b)		cpu->mem_if->read16(a,b)
+	#define WRITE16(a,b,c)	cpu->mem_if->write16(a,b,c)
+	#define READ8(a,b)		cpu->mem_if->read8(a,b)
+	#define WRITE8(a,b,c)	cpu->mem_if->write8(a,b,c)
+#else
+	#define READ32(a,b)		MMU_read32(cpu->proc_ID, b)
+	#define WRITE32(a,b,c)	MMU_write32(cpu->proc_ID,b,c)
+	#define READ16(a,b)		MMU_read16(cpu->proc_ID, b)
+	#define WRITE16(a,b,c)	MMU_write16(cpu->proc_ID,b,c)
+	#define READ8(a,b)		MMU_read8(cpu->proc_ID, b)
+	#define WRITE8(a,b,c)	MMU_write8(cpu->proc_ID,b,c)
+#endif
+
+static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu)
+{
+     execute = false;
+     return 1;
+}
+
+static u32 FASTCALL OP_LSL_0(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_LSL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = (i>>6) & 0x1F;
+     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v);
+     cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_LSR_0(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+	  // cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
+     cpu->R[REG_NUM(i, 0)] = 0;
+     cpu->CPSR.bits.N = 0;
+     cpu->CPSR.bits.Z = 1;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_LSR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = (i>>6) & 0x1F;
+     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
+     cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_ASR_0(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]);
+     cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_ASR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = (i>>6) & 0x1F;
+     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1);
+     cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 3)];
+     u32 b = cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = a + b;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 3)];
+     u32 b = cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = a - b;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 3)];
+     cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
+
+     return 2;
+}
+
+static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 3)];
+     cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]);
+
+     return 2;
+}
+
+static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 8)] = i & 0xFF;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+
+     return 2;
+}
+
+static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF);
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+     cpu->R[REG_NUM(i, 8)] = tmp;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF);
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp);
+     cpu->R[REG_NUM(i, 8)] = tmp;
+
+     return 2;
+}
+
+static u32 FASTCALL OP_AND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_EOR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
+
+     if(!v)
+     {
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+     if(v<32)
+     {
+          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v);
+          cpu->R[REG_NUM(i, 0)] <<= v;
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+     if(v==32)
+          cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]);
+     else
+          cpu->CPSR.bits.C = 0;
+     cpu->R[REG_NUM(i, 0)] = 0;
+     cpu->CPSR.bits.N = 0;
+     cpu->CPSR.bits.Z = 1;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
+
+     if(!v)
+     {
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+     if(v<32)
+     {
+          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
+          cpu->R[REG_NUM(i, 0)] >>= v;
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+     if(v==32)
+          cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
+     else
+          cpu->CPSR.bits.C = 0;
+     cpu->R[REG_NUM(i, 0)] = 0;
+     cpu->CPSR.bits.N = 0;
+     cpu->CPSR.bits.Z = 1;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
+
+     if(!v)
+     {
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+     if(v<32)
+     {
+          cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
+          cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v);
+          cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+          cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+          return 3;
+     }
+
+     cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF;
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 0)];
+     u32 b = cpu->R[REG_NUM(i, 3)];
+     u32 tmp = b + cpu->CPSR.bits.C;
+     u32 res = a + tmp;
+
+     cpu->R[REG_NUM(i, 0)] = res;
+
+     cpu->CPSR.bits.N = BIT31(res);
+     cpu->CPSR.bits.Z = res == 0;
+
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res);
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 0)];
+     u32 b = cpu->R[REG_NUM(i, 3)];
+     u32 tmp = a - (!cpu->CPSR.bits.C);
+     u32 res = tmp - b;
+     cpu->R[REG_NUM(i, 0)] = res;
+
+     cpu->CPSR.bits.N = BIT31(res);
+     cpu->CPSR.bits.Z = res == 0;
+
+     cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res));
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 v = cpu->R[REG_NUM(i, 3)]&0xFF;
+
+     if(v == 0)
+     {
+               cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+               cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+               return 3;
+     }
+     v &= 0xF;
+     if(v == 0)
+     {
+               cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]);
+               cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+               cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+               return 3;
+     }
+     cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1);
+     cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_TST(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_NEG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 a = cpu->R[REG_NUM(i, 3)];
+     cpu->R[REG_NUM(i, 0)] = -((signed int)a);
+
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_CMP(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)];
+
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_CMN(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)];
+
+     //execute = false;
+     //log::ajouter("OP_CMN THUMB");
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
+     cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ORR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)];
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_BIC(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_MVN(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]);
+     cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]);
+     cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0;
+
+     return 3;
+}
+
+static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 Rd = (i&7) | ((i>>4)&8);
+     cpu->R[Rd] += cpu->R[REG_POS(i, 3)];
+
+     if(Rd==15)
+          cpu->next_instruction = cpu->R[15];
+
+     return 2;
+}
+
+static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 Rn = (i&7) | ((i>>4)&8);
+     u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)];
+
+     cpu->CPSR.bits.N = BIT31(tmp);
+     cpu->CPSR.bits.Z = tmp == 0;
+     cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
+     cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp);
+
+     return 3;
+}
+
+static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 Rd = (i&7) | ((i>>4)&8);
+     cpu->R[Rd] = cpu->R[REG_POS(i, 3)];
+
+     if(Rd==15)
+          cpu->next_instruction = cpu->R[15];
+
+     return 2;
+}
+
+static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu)
+{
+     u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
+
+     cpu->CPSR.bits.T = BIT0(Rm);
+     cpu->R[15] = (Rm & 0xFFFFFFFE);
+     cpu->next_instruction = cpu->R[15];
+
+     return 3;
+}
+
+static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu)
+{
+     u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)];
+
+     cpu->CPSR.bits.T = BIT0(Rm);
+     cpu->R[14] = cpu->next_instruction | 1;
+     cpu->R[15] = (Rm & 0xFFFFFFFE);
+     cpu->next_instruction = cpu->R[15];
+
+     return 3;
+}
+
+static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu)
+{
+	u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2);
+
+    cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr);
+
+    return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)];
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)]));
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)]));
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]);
+	 u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
+
+	 adr = (adr&3)*8;
+	 tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
+	 cpu->R[REG_NUM(i, 0)] = tempValue;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)];
+     cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr));
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]);
+
+     return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C);
+     u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC);
+	 adr = (adr&3)*8;
+	 tempValue = (tempValue>>adr) | (tempValue<<(32-adr));
+	 cpu->R[REG_NUM(i, 0)] = tempValue;
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
+     WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F);
+     cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
+     WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E);
+     cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13] + ((i&0xFF)<<2);
+     WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]);
+
+     return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13] + ((i&0xFF)<<2);
+	 cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr);
+
+     return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+}
+
+static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2);
+
+     return 5;
+}
+
+static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2);
+
+     return 2;
+}
+
+static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu)
+{
+     cpu->R[13] += ((cpu->instruction&0x7F)<<2);
+
+     return 1;
+}
+
+static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu)
+{
+     cpu->R[13] -= ((cpu->instruction&0x7F)<<2);
+
+     return 1;
+}
+
+static u32 FASTCALL OP_PUSH(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13] - 4;
+     u32 c = 0, j;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, 7-j))
+          {
+               WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr -= 4;
+          }
+     cpu->R[13] = adr + 4;
+
+     return c + 3;
+}
+
+static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13] - 4;
+     u32 c = 0, j;
+
+     WRITE32(cpu->mem_if->data, adr, cpu->R[14]);
+     c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     adr -= 4;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, 7-j))
+          {
+               WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr -= 4;
+          }
+     cpu->R[13] = adr + 4;
+
+     return c + 4;
+}
+
+static u32 FASTCALL OP_POP(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13];
+     u32 c = 0, j;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, j))
+          {
+               cpu->R[j] = READ32(cpu->mem_if->data, adr);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr += 4;
+          }
+     cpu->R[13] = adr;
+
+     return c + 2;
+}
+
+static u32 FASTCALL OP_POP_PC(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[13];
+     u32 c = 0, j;
+     u32 v;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, j))
+          {
+               cpu->R[j] = READ32(cpu->mem_if->data, adr);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr += 4;
+          }
+
+     v = READ32(cpu->mem_if->data, adr);
+     c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+     cpu->R[15] = v & 0xFFFFFFFE;
+     cpu->next_instruction = v & 0xFFFFFFFE;
+     if(cpu->proc_ID==0)
+          cpu->CPSR.bits.T = BIT0(v);
+     adr += 4;
+
+     cpu->R[13] = adr;
+     return c + 5;
+}
+
+static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu)
+{
+     return 1;
+}
+
+static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 8)];
+     u32 c = 0, j;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, j))
+          {
+               WRITE32(cpu->mem_if->data, adr, cpu->R[j]);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr += 4;
+          }
+     cpu->R[REG_NUM(i, 8)] = adr;
+     return c + 2;
+}
+
+static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     u32 adr = cpu->R[REG_NUM(i, 8)];
+     u32 c = 0, j;
+
+     for(j = 0; j<8; ++j)
+          if(BIT_N(i, j))
+          {
+               cpu->R[j] = READ32(cpu->mem_if->data, adr);
+               c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF];
+               adr += 4;
+          }
+     cpu->R[REG_NUM(i, 8)] = adr;
+     return c + 3;
+}
+
+static u32 FASTCALL OP_B_COND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR))
+          return 1;
+
+     cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1;
+     cpu->next_instruction = cpu->R[15];
+     return 3;
+}
+
+static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu)
+{
+     if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
+     {
+        /* we use an irq thats not in the irq tab, as
+        it was replaced duie to a changed intVector */
+        Status_Reg tmp = cpu->CPSR;
+        armcpu_switchMode(cpu, SVC);            /* enter svc mode */
+        cpu->R[14] = cpu->R[15] - 4;            /* jump to swi Vector */
+        cpu->SPSR = tmp;                        /* save old CPSR as new SPSR */
+        cpu->CPSR.bits.T = 0;                   /* handle as ARM32 code */
+        cpu->CPSR.bits.I = cpu->SPSR.bits.I;    /* keep int disable flag */
+        cpu->R[15] = cpu->intVector + 0x08;
+        cpu->next_instruction = cpu->R[15];
+        return 3;
+     }
+     else
+     {
+        u32 swinum = cpu->instruction & 0xFF;
+        return cpu->swi_tab[swinum](cpu) + 3;
+     }
+     //return 3;
+}
+
+#define SIGNEEXT_IMM11(i)     (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800))
+
+static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[15] += (SIGNEEXT_IMM11(i)<<1);
+     cpu->next_instruction = cpu->R[15];
+     return 3;
+}
+
+static u32 FASTCALL OP_BLX(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC;
+     cpu->R[14] = cpu->next_instruction | 1;
+     cpu->next_instruction = cpu->R[15];
+     cpu->CPSR.bits.T = 0;
+     return 3;
+}
+
+static u32 FASTCALL OP_BL_10(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12);
+     return 1;
+}
+
+static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu)
+{
+     u32 i = cpu->instruction;
+     cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1));
+     cpu->R[14] = cpu->next_instruction | 1;
+     cpu->next_instruction = cpu->R[15];
+     return 3;
+}
+
+#define TYPE_RETOUR u32
+#define CALLTYPE FASTCALL
+#define PARAMETRES  armcpu_t *cpu
+#define NOM_THUMB_TAB     thumb_instructions_set
+
+#include "thumb_tabdef.inc"
diff --git a/src/xsf/desmume/thumb_instructions.h b/src/xsf/desmume/thumb_instructions.h
index 27088a6e33eb..7795d2868f80 100644
--- a/src/xsf/desmume/thumb_instructions.h
+++ b/src/xsf/desmume/thumb_instructions.h
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef THUMB_INSTRUCTIONS_H
diff --git a/src/xsf/desmume/thumb_tabdef.inc b/src/xsf/desmume/thumb_tabdef.inc
index 1a9c53b03475..37c0dcaf34ac 100644
--- a/src/xsf/desmume/thumb_tabdef.inc
+++ b/src/xsf/desmume/thumb_tabdef.inc
@@ -16,7 +16,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 TYPE_RETOUR (* CALLTYPE NOM_THUMB_TAB[1024])(PARAMETRES)={
diff --git a/src/xsf/desmume/types.h b/src/xsf/desmume/types.h
index ed4f210762bd..42c005bb55cd 100644
--- a/src/xsf/desmume/types.h
+++ b/src/xsf/desmume/types.h
@@ -14,7 +14,7 @@
 
     You should have received a copy of the GNU General Public License
     along with DeSmuME; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #ifndef TYPES_HPP
@@ -124,12 +124,12 @@ typedef int desmume_BOOL;
 #define BOOL desmume_BOOL
 #endif
 
-#ifndef TRUE
-#define TRUE 1
+#ifndef true
+#define true 1
 #endif
 
-#ifndef FALSE
-#define FALSE 0
+#ifndef false
+#define false 0
 #endif
 
 #ifdef __GNUC__
diff --git a/src/xsf/plugin.c b/src/xsf/plugin.c
deleted file mode 100644
index c7e32831b27d..000000000000
--- a/src/xsf/plugin.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-	Audio Overload SDK - main driver.  for demonstration only, not user friendly!
-
-	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
-
-	All rights reserved.
-
-	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <audacious/i18n.h>
-#include <audacious/input.h>
-#include <audacious/misc.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#include "ao.h"
-#include "corlett.h"
-#include "vio2sf.h"
-
-/* xsf_get_lib: called to load secondary files */
-static const char *dirpath;
-
-int xsf_get_lib(char *filename, void **buffer, unsigned int *length)
-{
-	void *filebuf;
-	int64_t size;
-
-	SPRINTF(path2, "%s/%s", dirpath, filename);
-	vfs_file_get_contents(path2, &filebuf, &size);
-
-	*buffer = filebuf;
-	*length = (uint64_t)size;
-
-	return AO_SUCCESS;
-}
-
-Tuple *xsf_tuple(const char *filename, VFSFile *fd)
-{
-	Tuple *t;
-	corlett_t *c;
-	void *buf;
-	int64_t sz;
-
-	vfs_file_get_contents (filename, & buf, & sz);
-
-	if (!buf)
-		return NULL;
-
-	if (corlett_decode(buf, sz, NULL, NULL, &c) != AO_SUCCESS)
-		return NULL;
-
-	t = tuple_new_from_filename(filename);
-
-	tuple_set_int(t, FIELD_LENGTH, c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1);
-	tuple_set_str(t, FIELD_ARTIST, c->inf_artist);
-	tuple_set_str(t, FIELD_ALBUM, c->inf_game);
-	tuple_set_str(t, FIELD_TITLE, c->inf_title);
-	tuple_set_str(t, FIELD_COPYRIGHT, c->inf_copy);
-	tuple_set_str(t, FIELD_QUALITY, _("sequenced"));
-	tuple_set_str(t, FIELD_CODEC, "GBA/Nintendo DS Audio");
-
-	free(c);
-	free(buf);
-
-	return t;
-}
-
-static int xsf_get_length(const char *filename)
-{
-	corlett_t *c;
-	void *buf;
-	int64_t size;
-
-	vfs_file_get_contents(filename, &buf, &size);
-
-	if (!buf)
-		return -1;
-
-	if (corlett_decode(buf, size, NULL, NULL, &c) != AO_SUCCESS)
-	{
-		free(buf);
-		return -1;
-	}
-
-	int length = c->inf_length ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1;
-
-	free(c);
-	free(buf);
-
-	return length;
-}
-
-static bool_t xsf_play(const char * filename, VFSFile * file)
-{
-	void *buffer;
-	int64_t size;
-	int length = xsf_get_length(filename);
-	int16_t samples[44100*2];
-	int seglen = 44100 / 60;
-	float pos;
-	bool_t error = FALSE;
-
-	const char * slash = strrchr (filename, '/');
-	if (! slash)
-		return FALSE;
-
-	SNCOPY (dirbuf, filename, slash + 1 - filename);
-	dirpath = dirbuf;
-
-	vfs_file_get_contents (filename, & buffer, & size);
-
-	if (xsf_start(buffer, size) != AO_SUCCESS)
-	{
-		error = TRUE;
-		goto ERR_NO_CLOSE;
-	}
-
-	if (!aud_input_open_audio(FMT_S16_NE, 44100, 2))
-	{
-		error = TRUE;
-		goto ERR_NO_CLOSE;
-	}
-
-	aud_input_set_bitrate(44100*2*2*8);
-
-	while (! aud_input_check_stop ())
-	{
-		int seek_value = aud_input_check_seek ();
-
-		if (seek_value >= 0)
-		{
-			if (seek_value > aud_input_written_time ())
-			{
-				pos = aud_input_written_time ();
-
-				while (pos < seek_value)
-				{
-					xsf_gen(samples, seglen);
-					pos += 16.666;
-				}
-			}
-			else if (seek_value < aud_input_written_time ())
-			{
-				xsf_term();
-
-				if (xsf_start(buffer, size) == AO_SUCCESS)
-				{
-					pos = 0;
-					while (pos < seek_value)
-					{
-						xsf_gen(samples, seglen);
-						pos += 16.666; /* each segment is 16.666ms */
-					}
-				}
-			   	else
-				{
-					error = TRUE;
-					goto CLEANUP;
-				}
-			}
-		}
-
-		xsf_gen(samples, seglen);
-		aud_input_write_audio((uint8_t *)samples, seglen * 4);
-
-		if (aud_input_written_time() >= length)
-			goto CLEANUP;
-	}
-
-CLEANUP:
-	xsf_term();
-
-ERR_NO_CLOSE:
-	dirpath = NULL;
-	free(buffer);
-
-	return !error;
-}
-
-int xsf_is_our_fd(const char *filename, VFSFile *file)
-{
-	char magic[4];
-	if (vfs_fread(magic, 1, 4, file) < 4)
-		return FALSE;
-
-	if (!memcmp(magic, "PSF$", 4))
-		return 1;
-
-	return 0;
-}
-
-static const char *xsf_fmts[] = { "2sf", "mini2sf", NULL };
-
-AUD_INPUT_PLUGIN
-(
-	.name = N_("2SF Decoder"),
-	.domain = PACKAGE,
-	.play = xsf_play,
-	.probe_for_tuple = xsf_tuple,
-	.is_our_file_from_vfs = xsf_is_our_fd,
-	.extensions = xsf_fmts,
-)
diff --git a/src/xsf/plugin.cc b/src/xsf/plugin.cc
new file mode 100644
index 000000000000..3f38f8593229
--- /dev/null
+++ b/src/xsf/plugin.cc
@@ -0,0 +1,242 @@
+/*
+	Audio Overload SDK - main driver.  for demonstration only, not user friendly!
+
+	Copyright (c) 2007-2008 R. Belmont and Richard Bannister.
+
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+	* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+	* Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+	CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+	PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/preferences.h>
+#include <libaudcore/audstrings.h>
+#include <libaudcore/runtime.h>
+
+#include "ao.h"
+#include "corlett.h"
+#include "vio2sf.h"
+
+class XSFPlugin : public InputPlugin
+{
+public:
+	static const char *const exts[];
+	static const char *const defaults[];
+	static const PreferencesWidget widgets[];
+	static const PluginPreferences prefs;
+
+	static constexpr PluginInfo info = {
+		N_("2SF Decoder"),
+		PACKAGE,
+		nullptr,
+		& prefs
+	};
+
+	static constexpr auto iinfo = InputInfo()
+		.with_exts(exts);
+
+	constexpr XSFPlugin() : InputPlugin(info, iinfo) {}
+
+	bool init();
+
+	bool is_our_file(const char *filename, VFSFile &file);
+	Tuple read_tuple(const char *filename, VFSFile &file);
+	bool play(const char *filename, VFSFile &file);
+};
+
+EXPORT XSFPlugin aud_plugin_instance;
+
+/* xsf_get_lib: called to load secondary files */
+static String dirpath;
+
+#define CFG_ID "xsf"
+
+const char* const XSFPlugin::defaults[] =
+{
+	"ignore_length", "FALSE",
+	NULL
+};
+
+bool XSFPlugin::init()
+{
+	aud_config_set_defaults(CFG_ID, defaults);
+	return true;
+}
+
+Index<char> xsf_get_lib(char *filename)
+{
+	VFSFile file(filename_build({dirpath, filename}), "r");
+	return file ? file.read_all() : Index<char>();
+}
+
+Tuple XSFPlugin::read_tuple(const char *filename, VFSFile &fd)
+{
+	Tuple t;
+	corlett_t *c;
+
+	Index<char> buf = fd.read_all ();
+
+	if (!buf.len())
+		return t;
+
+	if (corlett_decode((uint8_t *)buf.begin(), buf.len(), nullptr, nullptr, &c) != AO_SUCCESS)
+		return t;
+
+	t.set_filename (filename);
+
+	t.set_int (Tuple::Length, psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade));
+	t.set_str (Tuple::Artist, c->inf_artist);
+	t.set_str (Tuple::Album, c->inf_game);
+	t.set_str (Tuple::Title, c->inf_title);
+	t.set_str (Tuple::Copyright, c->inf_copy);
+	t.set_str (Tuple::Quality, _("sequenced"));
+	t.set_str (Tuple::Codec, "GBA/Nintendo DS Audio");
+
+	free(c);
+
+	return t;
+}
+
+static int xsf_get_length(const Index<char> &buf)
+{
+	corlett_t *c;
+
+	if (corlett_decode((uint8_t *)buf.begin(), buf.len(), nullptr, nullptr, &c) != AO_SUCCESS)
+		return -1;
+
+	bool ignore_length = aud_get_bool(CFG_ID, "ignore_length");
+	int length = (!ignore_length) ? psfTimeToMS(c->inf_length) + psfTimeToMS(c->inf_fade) : -1;
+
+	free(c);
+
+	return length;
+}
+
+bool XSFPlugin::play(const char *filename, VFSFile &file)
+{
+	int length = -1;
+	int16_t samples[44100*2];
+	int seglen = 44100 / 60;
+	float pos = 0.0;
+	bool error = false;
+
+	const char * slash = strrchr (filename, '/');
+	if (! slash)
+		return false;
+
+	dirpath = String (str_copy (filename, slash + 1 - filename));
+
+	Index<char> buf = file.read_all ();
+
+	if (!buf.len())
+	{
+		error = true;
+		goto ERR_NO_CLOSE;
+	}
+
+	length = xsf_get_length(buf);
+
+	if (xsf_start(buf.begin(), buf.len()) != AO_SUCCESS)
+	{
+		error = true;
+		goto ERR_NO_CLOSE;
+	}
+
+	set_stream_bitrate(44100*2*2*8);
+	open_audio(FMT_S16_NE, 44100, 2);
+
+	while (! check_stop ())
+	{
+		int seek_value = check_seek ();
+
+		if (seek_value >= 0)
+		{
+			if (seek_value > pos)
+			{
+				while (pos < seek_value)
+				{
+					xsf_gen(samples, seglen);
+					pos += 16.666;
+				}
+			}
+			else if (seek_value < pos)
+			{
+				xsf_term();
+
+				if (xsf_start(buf.begin(), buf.len()) == AO_SUCCESS)
+				{
+					pos = 0.0;
+					while (pos < seek_value)
+					{
+						xsf_gen(samples, seglen);
+						pos += 16.666; /* each segment is 16.666ms */
+					}
+				}
+			   	else
+				{
+					error = true;
+					goto CLEANUP;
+				}
+			}
+		}
+
+		xsf_gen(samples, seglen);
+		pos += 16.666;
+
+        write_audio(samples, seglen * 4);
+
+		bool ignore_length = aud_get_bool(CFG_ID, "ignore_length");
+		if (pos >= length && !ignore_length)
+			goto CLEANUP;
+	}
+
+CLEANUP:
+	xsf_term();
+
+ERR_NO_CLOSE:
+	dirpath = String ();
+
+	return !error;
+}
+
+bool XSFPlugin::is_our_file(const char *filename, VFSFile &file)
+{
+	char magic[4];
+	if (file.fread (magic, 1, 4) < 4)
+		return false;
+
+	if (!memcmp(magic, "PSF$", 4))
+		return 1;
+
+	return 0;
+}
+
+const char *const XSFPlugin::exts[] = { "2sf", "mini2sf", nullptr };
+
+const PreferencesWidget XSFPlugin::widgets[] = {
+	WidgetLabel(N_("<b>XSF Configuration</b>")),
+	WidgetCheck(N_("Ignore length from file"), WidgetBool(CFG_ID, "ignore_length")),
+};
+
+const PluginPreferences XSFPlugin::prefs = {{widgets}};
diff --git a/src/xsf/tagget.h b/src/xsf/tagget.h
index 4ba361bba8d9..07a58fe0af08 100644
--- a/src/xsf/tagget.h
+++ b/src/xsf/tagget.h
@@ -92,7 +92,7 @@ typedef struct
 static int xsf_tagenum_callback_tagget(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
 {
 	xsf_tagget_work_t *pwork = (xsf_tagget_work_t *)pWork;
-	if (pwork->taglen == pNameEnd - pNameTop && !g_ascii_strncasecmp(pNameTop, pwork->tag, pwork->taglen))
+	if (pwork->taglen == pNameEnd - pNameTop && !strcmp_nocase(pNameTop, pwork->tag, pwork->taglen))
 	{
 		char *ret = (char *)malloc(pValueEnd - pValueTop + 1);
 		if (!ret) return xsf_tagenum_callback_returnvaluecontinue;
diff --git a/src/xsf/vio2sf.c b/src/xsf/vio2sf.c
deleted file mode 100644
index 0a53c602be9c..000000000000
--- a/src/xsf/vio2sf.c
+++ /dev/null
@@ -1,841 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "desmume/MMU.h"
-#include "desmume/armcpu.h"
-#include "desmume/NDSSystem.h"
-#include "desmume/SPU.h"
-#include "desmume/cp15.h"
-
-#include <glib.h>
-#include <zlib.h>
-#include "tagget.h"
-#include "vio2sf.h"
-
-volatile BOOL execute = FALSE;
-
-static struct
-{
-	unsigned char *rom;
-	unsigned char *state;
-	unsigned romsize;
-	unsigned statesize;
-	unsigned stateptr;
-} loaderwork = {0, 0, 0, 0, 0};
-
-static void load_term(void)
-{
-	if (loaderwork.rom)
-	{
-		free(loaderwork.rom);
-		loaderwork.rom = 0;
-	}
-	loaderwork.romsize = 0;
-	if (loaderwork.state)
-	{
-		free(loaderwork.state);
-		loaderwork.state = 0;
-	}
-	loaderwork.statesize = 0;
-}
-
-static int load_map(int issave, unsigned char *udata, unsigned usize)
-{
-	unsigned char *iptr;
-	unsigned isize;
-	unsigned char *xptr;
-	unsigned xsize = getdwordle(udata + 4);
-	unsigned xofs = getdwordle(udata + 0);
-	if (issave)
-	{
-		iptr = loaderwork.state;
-		isize = loaderwork.statesize;
-		loaderwork.state = 0;
-		loaderwork.statesize = 0;
-	}
-	else
-	{
-		iptr = loaderwork.rom;
-		isize = loaderwork.romsize;
-		loaderwork.rom = 0;
-		loaderwork.romsize = 0;
-	}
-	if (!iptr)
-	{
-		iptr = malloc(xofs + xsize + 10);
-		if (!iptr)
-			return XSF_FALSE;
-		memset(iptr, 0, xofs + xsize + 10);
-		isize = xofs + xsize;
-	}
-	else if (isize < xofs + xsize)
-	{
-		unsigned rsize = xofs + xsize;
-		if (!issave)
-		{
-			rsize -= 1;
-			rsize |= rsize >> 1;
-			rsize |= rsize >> 2;
-			rsize |= rsize >> 4;
-			rsize |= rsize >> 8;
-			rsize |= rsize >> 16;
-			rsize += 1;
-		}
-		xptr = realloc(iptr, xofs + rsize + 10);
-		if (!xptr)
-		{
-			free(iptr);
-			return XSF_FALSE;
-		}
-		iptr = xptr;
-		isize = rsize;
-	}
-	memcpy(iptr + xofs, udata + 8, xsize);
-	if (issave)
-	{
-		loaderwork.state = iptr;
-		loaderwork.statesize = isize;
-	}
-	else
-	{
-		loaderwork.rom = iptr;
-		loaderwork.romsize = isize;
-	}
-	return XSF_TRUE;
-}
-
-static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc)
-{
-	int ret;
-	int zerr;
-	uLongf usize = 8;
-	uLongf rsize = usize;
-	unsigned char *udata;
-	unsigned char *rdata;
-
-	udata = malloc(usize);
-	if (!udata)
-		return XSF_FALSE;
-
-	while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize)))
-	{
-		if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr)
-		{
-			free(udata);
-			return XSF_FALSE;
-		}
-		if (usize >= 8)
-		{
-			usize = getdwordle(udata + 4) + 8;
-			if (usize < rsize)
-			{
-				rsize += rsize;
-				usize = rsize;
-			}
-			else
-				rsize = usize;
-		}
-		else
-		{
-			rsize += rsize;
-			usize = rsize;
-		}
-		free(udata);
-		udata = malloc(usize);
-		if (!udata)
-			return XSF_FALSE;
-	}
-
-	rdata = realloc(udata, usize);
-	if (!rdata)
-	{
-		free(udata);
-		return XSF_FALSE;
-	}
-
-	if (0)
-	{
-		unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize);
-		if (ccrc != zcrc)
-			return XSF_FALSE;
-	}
-
-	ret = load_map(issave, rdata, usize);
-	free(rdata);
-	return ret;
-}
-
-static int load_psf_one(unsigned char *pfile, unsigned bytes)
-{
-	unsigned char *ptr = pfile;
-	unsigned code_size;
-	unsigned resv_size;
-	unsigned code_crc;
-	if (bytes < 16 || getdwordle(ptr) != 0x24465350)
-		return XSF_FALSE;
-
-	resv_size = getdwordle(ptr + 4);
-	code_size = getdwordle(ptr + 8);
-	code_crc = getdwordle(ptr + 12);
-
-	if (resv_size)
-	{
-		unsigned resv_pos = 0;
-		ptr = pfile + 16;
-		if (16+ resv_size > bytes)
-			return XSF_FALSE;
-		while (resv_pos + 12 < resv_size)
-		{
-			unsigned save_size = getdwordle(ptr + resv_pos + 4);
-			unsigned save_crc = getdwordle(ptr + resv_pos + 8);
-			if (getdwordle(ptr + resv_pos + 0) == 0x45564153)
-			{
-				if (resv_pos + 12 + save_size > resv_size)
-					return XSF_FALSE;
-				if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc))
-					return XSF_FALSE;
-			}
-			resv_pos += 12 + save_size;
-		}
-	}
-
-	if (code_size)
-	{
-		ptr = pfile + 16 + resv_size;
-		if (16 + resv_size + code_size > bytes)
-			return XSF_FALSE;
-		if (!load_mapz(0, ptr, code_size, code_crc))
-			return XSF_FALSE;
-	}
-
-	return XSF_TRUE;
-}
-
-typedef struct
-{
-	const char *tag;
-	int taglen;
-	int level;
-	int found;
-} loadlibwork_t;
-
-static int load_libs(int level, void *pfile, unsigned bytes);
-
-static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
-{
-	loadlibwork_t *pwork = (loadlibwork_t *)pWork;
-	int ret = xsf_tagenum_callback_returnvaluecontinue;
-	if (pNameEnd - pNameTop == pwork->taglen && !g_ascii_strncasecmp(pNameTop, pwork->tag , pwork->taglen))
-	{
-		unsigned l = pValueEnd - pValueTop;
-		char *lib = malloc(l + 1);
-		if (!lib)
-		{
-			ret = xsf_tagenum_callback_returnvaluebreak;
-		}
-		else
-		{
-			void *libbuf;
-			unsigned libsize;
-			memcpy(lib, pValueTop, l);
-			lib[l] = '\0';
-			if (!xsf_get_lib(lib, &libbuf, &libsize))
-			{
-				ret = xsf_tagenum_callback_returnvaluebreak;
-			}
-			else
-			{
-				if (!load_libs(pwork->level + 1, libbuf, libsize) || !load_psf_one(libbuf, libsize))
-					ret = xsf_tagenum_callback_returnvaluebreak;
-				else
-				{
-					pwork->found++;
-					free(libbuf);
-				}
-			}
-			free(lib);
-		}
-	}
-	return ret;
-}
-
-static int load_libs(int level, void *pfile, unsigned bytes)
-{
-	char tbuf[16];
-	loadlibwork_t work;
-	int n = 1;
-
-	if (level > 10)
-		return XSF_TRUE;
-
-	work.level = level;
-	work.tag = "_lib";
-
-	do
-	{
-		work.taglen = strlen(work.tag);
-		work.found = 0;
-
-		if (xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0)
-			return XSF_FALSE;
-
-#ifdef HAVE_SPRINTF_S
-		sprintf_s(tbuf, sizeof(tbuf), "_lib%10d", ++n);
-#else
-		sprintf(tbuf, "_lib%10d", ++n);
-#endif
-		work.tag = tbuf;
-	}
-	while (work.found);
-
-	return XSF_TRUE;
-}
-
-static int load_psf(void *pfile, unsigned bytes)
-{
-	load_term();
-
-	if (!load_libs(1, pfile, bytes) || !load_psf_one(pfile, bytes))
-		return XSF_FALSE;
-
-	return XSF_TRUE;
-}
-
-static void load_getstateinit(unsigned ptr)
-{
-	loaderwork.stateptr = ptr;
-}
-
-static u16 getwordle(const unsigned char *pData)
-{
-	return pData[0] | (((u16)pData[1]) << 8);
-}
-
-static void load_getsta(Status_Reg *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		{
-			u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
-			ptr[i].bits.N = (st >> 31) & 1;
-			ptr[i].bits.Z = (st >> 30) & 1;
-			ptr[i].bits.C = (st >> 29) & 1;
-			ptr[i].bits.V = (st >> 28) & 1;
-			ptr[i].bits.Q = (st >> 27) & 1;
-			ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1);
-			ptr[i].bits.I = (st >> 7) & 1;
-			ptr[i].bits.F = (st >> 6) & 1;
-			ptr[i].bits.T = (st >> 5) & 1;
-			ptr[i].bits.mode = (st >> 0) & 0x1f;
-		}
-	loaderwork.stateptr += s;
-}
-
-static void load_getbool(BOOL *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
-	loaderwork.stateptr += s;
-}
-
-#if defined(SIGNED_IS_NOT_2S_COMPLEMENT)
-/* 2's complement */
-#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x8000) - 0x8000))
-#else
-/* 2's complement */
-#define u32tos32(v) ((s32)v)
-#endif
-
-static void load_gets32(s32 *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)));
-	loaderwork.stateptr += s;
-}
-
-static void load_getu32(u32 *ptr, unsigned l)
-{
-	unsigned s = l << 2;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
-	loaderwork.stateptr += s;
-}
-
-static void load_getu16(u16 *ptr, unsigned l)
-{
-	unsigned s = l << 1;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1));
-	loaderwork.stateptr += s;
-}
-
-static void load_getu8(u8 *ptr, unsigned l)
-{
-	unsigned s = l;
-	unsigned i;
-	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
-		return;
-	for (i = 0; i < l; i++)
-		ptr[i] = loaderwork.state[loaderwork.stateptr + i];
-	loaderwork.stateptr += s;
-}
-
-void gdb_stub_fix(armcpu_t *armcpu)
-{
-	/* armcpu->R[15] = armcpu->instruct_adr; */
-	armcpu->next_instruction = armcpu->instruct_adr;
-	if(armcpu->CPSR.bits.T == 0)
-	{
-		armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction += 4;
-		armcpu->R[15] = armcpu->next_instruction + 4;
-	}
-	else
-	{
-		armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
-		armcpu->instruct_adr = armcpu->next_instruction;
-		armcpu->next_instruction += 2;
-		armcpu->R[15] = armcpu->next_instruction + 2;
-	}
-}
-
-static void load_setstate(void)
-{
-	if (!loaderwork.statesize)
-		return;
-
-    /* Skip over "Desmume Save File" crap */
-	load_getstateinit(0x17);
-
-	/* Read ARM7 cpu registers */
-	load_getu32(&NDS_ARM7.proc_ID, 1);
-	load_getu32(&NDS_ARM7.instruction, 1);
-	load_getu32(&NDS_ARM7.instruct_adr, 1);
-	load_getu32(&NDS_ARM7.next_instruction, 1);
-	load_getu32(NDS_ARM7.R, 16);
-	load_getsta(&NDS_ARM7.CPSR, 1);
-	load_getsta(&NDS_ARM7.SPSR, 1);
-	load_getu32(&NDS_ARM7.R13_usr, 1);
-	load_getu32(&NDS_ARM7.R14_usr, 1);
-	load_getu32(&NDS_ARM7.R13_svc, 1);
-	load_getu32(&NDS_ARM7.R14_svc, 1);
-	load_getu32(&NDS_ARM7.R13_abt, 1);
-	load_getu32(&NDS_ARM7.R14_abt, 1);
-	load_getu32(&NDS_ARM7.R13_und, 1);
-	load_getu32(&NDS_ARM7.R14_und, 1);
-	load_getu32(&NDS_ARM7.R13_irq, 1);
-	load_getu32(&NDS_ARM7.R14_irq, 1);
-	load_getu32(&NDS_ARM7.R8_fiq, 1);
-	load_getu32(&NDS_ARM7.R9_fiq, 1);
-	load_getu32(&NDS_ARM7.R10_fiq, 1);
-	load_getu32(&NDS_ARM7.R11_fiq, 1);
-	load_getu32(&NDS_ARM7.R12_fiq, 1);
-	load_getu32(&NDS_ARM7.R13_fiq, 1);
-	load_getu32(&NDS_ARM7.R14_fiq, 1);
-	load_getsta(&NDS_ARM7.SPSR_svc, 1);
-	load_getsta(&NDS_ARM7.SPSR_abt, 1);
-	load_getsta(&NDS_ARM7.SPSR_und, 1);
-	load_getsta(&NDS_ARM7.SPSR_irq, 1);
-	load_getsta(&NDS_ARM7.SPSR_fiq, 1);
-	load_getu32(&NDS_ARM7.intVector, 1);
-	load_getu8(&NDS_ARM7.LDTBit, 1);
-	load_getbool(&NDS_ARM7.waitIRQ, 1);
-	load_getbool(&NDS_ARM7.wIRQ, 1);
-	load_getbool(&NDS_ARM7.wirq, 1);
-
-	/* Read ARM9 cpu registers */
-	load_getu32(&NDS_ARM9.proc_ID, 1);
-	load_getu32(&NDS_ARM9.instruction, 1);
-	load_getu32(&NDS_ARM9.instruct_adr, 1);
-	load_getu32(&NDS_ARM9.next_instruction, 1);
-	load_getu32(NDS_ARM9.R, 16);
-	load_getsta(&NDS_ARM9.CPSR, 1);
-	load_getsta(&NDS_ARM9.SPSR, 1);
-	load_getu32(&NDS_ARM9.R13_usr, 1);
-	load_getu32(&NDS_ARM9.R14_usr, 1);
-	load_getu32(&NDS_ARM9.R13_svc, 1);
-	load_getu32(&NDS_ARM9.R14_svc, 1);
-	load_getu32(&NDS_ARM9.R13_abt, 1);
-	load_getu32(&NDS_ARM9.R14_abt, 1);
-	load_getu32(&NDS_ARM9.R13_und, 1);
-	load_getu32(&NDS_ARM9.R14_und, 1);
-	load_getu32(&NDS_ARM9.R13_irq, 1);
-	load_getu32(&NDS_ARM9.R14_irq, 1);
-	load_getu32(&NDS_ARM9.R8_fiq, 1);
-	load_getu32(&NDS_ARM9.R9_fiq, 1);
-	load_getu32(&NDS_ARM9.R10_fiq, 1);
-	load_getu32(&NDS_ARM9.R11_fiq, 1);
-	load_getu32(&NDS_ARM9.R12_fiq, 1);
-	load_getu32(&NDS_ARM9.R13_fiq, 1);
-	load_getu32(&NDS_ARM9.R14_fiq, 1);
-	load_getsta(&NDS_ARM9.SPSR_svc, 1);
-	load_getsta(&NDS_ARM9.SPSR_abt, 1);
-	load_getsta(&NDS_ARM9.SPSR_und, 1);
-	load_getsta(&NDS_ARM9.SPSR_irq, 1);
-	load_getsta(&NDS_ARM9.SPSR_fiq, 1);
-	load_getu32(&NDS_ARM9.intVector, 1);
-	load_getu8(&NDS_ARM9.LDTBit, 1);
-	load_getbool(&NDS_ARM9.waitIRQ, 1);
-	load_getbool(&NDS_ARM9.wIRQ, 1);
-	load_getbool(&NDS_ARM9.wirq, 1);
-
-	/* Read in other internal variables that are important */
-	load_gets32(&nds.ARM9Cycle, 1);
-	load_gets32(&nds.ARM7Cycle, 1);
-	load_gets32(&nds.cycles, 1);
-	load_gets32(nds.timerCycle[0], 4);
-	load_gets32(nds.timerCycle[1], 4);
-	load_getbool(nds.timerOver[0], 4);
-	load_getbool(nds.timerOver[1], 4);
-	load_gets32(&nds.nextHBlank, 1);
-	load_getu32(&nds.VCount, 1);
-	load_getu32(&nds.old, 1);
-	load_gets32(&nds.diff, 1);
-	load_getbool(&nds.lignerendu, 1);
-	load_getu16(&nds.touchX, 1);
-	load_getu16(&nds.touchY, 1);
-
-	/* Read in memory/registers specific to the ARM9 */
-	load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000);
-	load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000);
-	load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000);
-	load_getu8 (ARM9Mem.MAIN_MEM, 0x400000);
-	load_getu8 (ARM9Mem.ARM9_REG, 0x10000);
-	load_getu8 (ARM9Mem.ARM9_VMEM, 0x800);
-	load_getu8 (ARM9Mem.ARM9_OAM, 0x800);
-	load_getu8 (ARM9Mem.ARM9_ABG, 0x80000);
-	load_getu8 (ARM9Mem.ARM9_BBG, 0x20000);
-	load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000);
-	load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000);
-	load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000);
-
-	/* Read in memory/registers specific to the ARM7 */
-	load_getu8 (MMU.ARM7_ERAM, 0x10000);
-	load_getu8 (MMU.ARM7_REG, 0x10000);
-	load_getu8 (MMU.ARM7_WIRAM, 0x10000);
-
-	/* Read in shared memory */
-	load_getu8 (MMU.SWIRAM, 0x8000);
-
-#ifdef GDB_STUB
-#else
-	gdb_stub_fix(&NDS_ARM9);
-	gdb_stub_fix(&NDS_ARM7);
-#endif
-}
-
-static struct
-{
-	unsigned char *pcmbufalloc;
-	unsigned char *pcmbuftop;
-	unsigned filled;
-	unsigned used;
-	u32 bufferbytes;
-	u32 cycles;
-	int xfs_load;
-	int sync_type;
-	int arm7_clockdown_level;
-	int arm9_clockdown_level;
-} sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-static void SNDIFDeInit(void)
-{
-	if (sndifwork.pcmbufalloc)
-	{
-		free(sndifwork.pcmbufalloc);
-		sndifwork.pcmbufalloc = 0;
-		sndifwork.pcmbuftop = 0;
-		sndifwork.bufferbytes = 0;
-	}
-}
-static int SNDIFInit(int buffersize)
-{
-	u32 bufferbytes = buffersize * sizeof(s16);
-	SNDIFDeInit();
-	sndifwork.pcmbufalloc = malloc(bufferbytes + 3);
-	if (!sndifwork.pcmbufalloc)
-		return -1;
-	sndifwork.pcmbuftop = (void *) (((uintptr_t) sndifwork.pcmbufalloc + 3) & ~3);
-	sndifwork.bufferbytes = bufferbytes;
-	sndifwork.filled = 0;
-	sndifwork.used = 0;
-	sndifwork.cycles = 0;
-	return 0;
-}
-static void SNDIFMuteAudio(void)
-{
-}
-static void SNDIFUnMuteAudio(void)
-{
-}
-static void SNDIFSetVolume(int volume)
-{
-}
-static u32 SNDIFGetAudioSpace(void)
-{
-	return sndifwork.bufferbytes >> 2; // bytes to samples
-}
-static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples)
-{
-	u32 num_bytes = num_samples << 2;
-	if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes;
-	memcpy(sndifwork.pcmbuftop, buffer, num_bytes);
-	sndifwork.filled = num_bytes;
-	sndifwork.used = 0;
-}
-#define VIO2SFSNDIFID 2
-static SoundInterface_struct VIO2SFSNDIF =
-{
-	VIO2SFSNDIFID,
-	"vio2sf Sound Interface",
-	SNDIFInit,
-	SNDIFDeInit,
-	SNDIFUpdateAudio,
-	SNDIFGetAudioSpace,
-	SNDIFMuteAudio,
-	SNDIFUnMuteAudio,
-	SNDIFSetVolume
-};
-
-SoundInterface_struct *SNDCoreList[] = {
-	&VIO2SFSNDIF,
-	&SNDDummy,
-	NULL
-};
-
-#ifdef GDB_STUB
-static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0;
-static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0;
-#endif
-
-int xsf_start(void *pfile, unsigned bytes)
-{
-	int frames = xsf_tagget_int("_frames", pfile, bytes, -1);
-	int clockdown = xsf_tagget_int("_clockdown", pfile, bytes, 0);
-	sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", pfile, bytes, 0);
-	sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", pfile, bytes, clockdown);
-	sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", pfile, bytes, clockdown);
-
-	sndifwork.xfs_load = 0;
-	printf("load_psf... ");
-	if (!load_psf(pfile, bytes))
-		return XSF_FALSE;
-	printf("ok!\n");
-
-#ifdef GDB_STUB
-	if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface))
-#else
-	if (NDS_Init())
-#endif
-		return XSF_FALSE;
-
-	SPU_ChangeSoundCore(VIO2SFSNDIFID, 737);
-
-	execute = FALSE;
-
-	MMU_unsetRom();
-	if (loaderwork.rom)
-	{
-		NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1);
-	}
-
-	NDS_Reset();
-
-	execute = TRUE;
-
-	if (loaderwork.state)
-	{
-		armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15];
-		int proc;
-		if (frames == -1)
-		{
-
-			/* set initial ARM9 coprocessor state */
-
-			armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
-			armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4);
-			armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0);
-			armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0);
-			armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0);
-			armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0);
-			armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1);
-
-			armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0);
-
-			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1);
-			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3);
-			armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2);
-			armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0);
-			armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0);
-
-			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
-			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1);
-			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1);
-
-			/* set initial timer state */
-
-			MMU_write16(0, REG_TM0CNTL, 0x0000);
-			MMU_write16(0, REG_TM0CNTH, 0x00C1);
-			MMU_write16(1, REG_TM0CNTL, 0x0000);
-			MMU_write16(1, REG_TM0CNTH, 0x00C1);
-			MMU_write16(1, REG_TM1CNTL, 0xf7e7);
-			MMU_write16(1, REG_TM1CNTH, 0x00C1);
-
-			/* set initial interrupt state */
-
-			MMU.reg_IME[0] = 0x00000001;
-			MMU.reg_IE[0]  = 0x00042001;
-			MMU.reg_IME[1] = 0x00000001;
-			MMU.reg_IE[1]  = 0x0104009d;
-		}
-		else if (frames > 0)
-		{
-			/* execute boot code */
-			int i;
-			for (i=0; i<frames; i++)
-				NDS_exec_frame(0, 0);
-			i = 0;
-		}
-
-		/* load state */
-
-		load_setstate();
-		free(loaderwork.state);
-		loaderwork.state = 0;
-
-		if (frames == -1)
-		{
-			armcp15_moveARM2CP(c9, (NDS_ARM9.R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
-		}
-
-		/* restore timer state */
-
-		for (proc = 0; proc < 2; proc++)
-		{
-			MMU_write16(proc, REG_TM0CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM1CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM2CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
-			MMU_write16(proc, REG_TM3CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
-		}
-	}
-	else if (frames > 0)
-	{
-		/* skip 1 sec */
-		int i;
-		for (i=0; i<frames; i++)
-			NDS_exec_frame(0, 0);
-	}
-	execute = TRUE;
-	sndifwork.xfs_load = 1;
-	return XSF_TRUE;
-}
-
-int xsf_gen(void *pbuffer, unsigned samples)
-{
-	unsigned char *ptr = pbuffer;
-	unsigned bytes = samples <<= 2;
-	if (!sndifwork.xfs_load) return 0;
-	while (bytes)
-	{
-		unsigned remainbytes = sndifwork.filled - sndifwork.used;
-		if (remainbytes > 0)
-		{
-			if (remainbytes > bytes)
-			{
-				memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes);
-				sndifwork.used += bytes;
-				ptr += bytes;
-				remainbytes -= bytes; /**/
-				bytes = 0;  /**/
-				break;
-			}
-			else
-			{
-				memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes);
-				sndifwork.used += remainbytes;
-				ptr += remainbytes;
-				bytes -= remainbytes;
-				remainbytes = 0;
-			}
-		}
-		if (remainbytes == 0)
-		{
-
-#define HBASE_CYCLES 33509300.322234
-#define VBASE_CYCLES (((double)HBASE_CYCLES) / 100)
-#define HSAMPLES ((u32)((44100.0 * 6 * (99 + 256)) / HBASE_CYCLES))
-#define VSAMPLES ((u32)((44100.0 * 6 * (99 + 256) * 263) / HBASE_CYCLES))
-
-			int numsamples;
-			if (sndifwork.sync_type == 1)
-			{
-				/* vsync */
-				sndifwork.cycles += (441 * 6 * (99 + 256) * 263);
-				if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1)))
-				{
-					numsamples = (VSAMPLES + 1);
-					sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1));
-				}
-				else
-				{
-					numsamples = (VSAMPLES + 0);
-					sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0));
-				}
-				NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
-			}
-			else
-			{
-				/* hsync */
-				sndifwork.cycles += (44100 * 6 * (99 + 256));
-				if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1)))
-				{
-					numsamples = (HSAMPLES + 1);
-					sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1));
-				}
-				else
-				{
-					numsamples = (HSAMPLES + 0);
-					sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0));
-				}
-				NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
-			}
-			SPU_EmulateSamples(numsamples);
-		}
-	}
-	return ptr - (unsigned char *)pbuffer;
-}
-
-void xsf_term(void)
-{
-	MMU_unsetRom();
-	NDS_DeInit();
-	load_term();
-}
diff --git a/src/xsf/vio2sf.cc b/src/xsf/vio2sf.cc
new file mode 100644
index 000000000000..6359fb08ab83
--- /dev/null
+++ b/src/xsf/vio2sf.cc
@@ -0,0 +1,828 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "desmume/MMU.h"
+#include "desmume/armcpu.h"
+#include "desmume/NDSSystem.h"
+#include "desmume/SPU.h"
+#include "desmume/cp15.h"
+
+#include <zlib.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "tagget.h"
+#include "vio2sf.h"
+
+volatile BOOL execute = false;
+
+static struct
+{
+	unsigned char *rom;
+	unsigned char *state;
+	unsigned romsize;
+	unsigned statesize;
+	unsigned stateptr;
+} loaderwork = {0, 0, 0, 0, 0};
+
+static void load_term(void)
+{
+	if (loaderwork.rom)
+	{
+		free(loaderwork.rom);
+		loaderwork.rom = 0;
+	}
+	loaderwork.romsize = 0;
+	if (loaderwork.state)
+	{
+		free(loaderwork.state);
+		loaderwork.state = 0;
+	}
+	loaderwork.statesize = 0;
+}
+
+static int load_map(int issave, unsigned char *udata, unsigned usize)
+{
+	unsigned char *iptr;
+	unsigned isize;
+	unsigned char *xptr;
+	unsigned xsize = getdwordle(udata + 4);
+	unsigned xofs = getdwordle(udata + 0);
+	if (issave)
+	{
+		iptr = loaderwork.state;
+		isize = loaderwork.statesize;
+		loaderwork.state = 0;
+		loaderwork.statesize = 0;
+	}
+	else
+	{
+		iptr = loaderwork.rom;
+		isize = loaderwork.romsize;
+		loaderwork.rom = 0;
+		loaderwork.romsize = 0;
+	}
+	if (!iptr)
+	{
+		iptr = (unsigned char *) malloc(xofs + xsize + 10);
+		if (!iptr)
+			return false;
+		memset(iptr, 0, xofs + xsize + 10);
+		isize = xofs + xsize;
+	}
+	else if (isize < xofs + xsize)
+	{
+		unsigned rsize = xofs + xsize;
+		if (!issave)
+		{
+			rsize -= 1;
+			rsize |= rsize >> 1;
+			rsize |= rsize >> 2;
+			rsize |= rsize >> 4;
+			rsize |= rsize >> 8;
+			rsize |= rsize >> 16;
+			rsize += 1;
+		}
+		xptr = (unsigned char *) realloc(iptr, xofs + rsize + 10);
+		if (!xptr)
+		{
+			free(iptr);
+			return false;
+		}
+		iptr = xptr;
+		isize = rsize;
+	}
+	memcpy(iptr + xofs, udata + 8, xsize);
+	if (issave)
+	{
+		loaderwork.state = iptr;
+		loaderwork.statesize = isize;
+	}
+	else
+	{
+		loaderwork.rom = iptr;
+		loaderwork.romsize = isize;
+	}
+	return true;
+}
+
+static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc)
+{
+	int ret;
+	int zerr;
+	uLongf usize = 8;
+	uLongf rsize = usize;
+	unsigned char *udata;
+	unsigned char *rdata;
+
+	udata = (unsigned char *) malloc(usize);
+	if (!udata)
+		return false;
+
+	while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize)))
+	{
+		if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr)
+		{
+			free(udata);
+			return false;
+		}
+		if (usize >= 8)
+		{
+			usize = getdwordle(udata + 4) + 8;
+			if (usize < rsize)
+			{
+				rsize += rsize;
+				usize = rsize;
+			}
+			else
+				rsize = usize;
+		}
+		else
+		{
+			rsize += rsize;
+			usize = rsize;
+		}
+		free(udata);
+		udata = (unsigned char *) malloc(usize);
+		if (!udata)
+			return false;
+	}
+
+	rdata = (unsigned char *) realloc(udata, usize);
+	if (!rdata)
+	{
+		free(udata);
+		return false;
+	}
+
+	if (0)
+	{
+		unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize);
+		if (ccrc != zcrc)
+			return false;
+	}
+
+	ret = load_map(issave, rdata, usize);
+	free(rdata);
+	return ret;
+}
+
+static int load_psf_one(unsigned char *pfile, unsigned bytes)
+{
+	unsigned char *ptr = pfile;
+	unsigned code_size;
+	unsigned resv_size;
+	unsigned code_crc;
+	if (bytes < 16 || getdwordle(ptr) != 0x24465350)
+		return false;
+
+	resv_size = getdwordle(ptr + 4);
+	code_size = getdwordle(ptr + 8);
+	code_crc = getdwordle(ptr + 12);
+
+	if (resv_size)
+	{
+		unsigned resv_pos = 0;
+		ptr = pfile + 16;
+		if (16+ resv_size > bytes)
+			return false;
+		while (resv_pos + 12 < resv_size)
+		{
+			unsigned save_size = getdwordle(ptr + resv_pos + 4);
+			unsigned save_crc = getdwordle(ptr + resv_pos + 8);
+			if (getdwordle(ptr + resv_pos + 0) == 0x45564153)
+			{
+				if (resv_pos + 12 + save_size > resv_size)
+					return false;
+				if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc))
+					return false;
+			}
+			resv_pos += 12 + save_size;
+		}
+	}
+
+	if (code_size)
+	{
+		ptr = pfile + 16 + resv_size;
+		if (16 + resv_size + code_size > bytes)
+			return false;
+		if (!load_mapz(0, ptr, code_size, code_crc))
+			return false;
+	}
+
+	return true;
+}
+
+typedef struct
+{
+	const char *tag;
+	int taglen;
+	int level;
+	int found;
+} loadlibwork_t;
+
+static int load_libs(int level, void *pfile, unsigned bytes);
+
+static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd)
+{
+	loadlibwork_t *pwork = (loadlibwork_t *)pWork;
+	int ret = xsf_tagenum_callback_returnvaluecontinue;
+	if (pNameEnd - pNameTop == pwork->taglen && !strcmp_nocase(pNameTop, pwork->tag, pwork->taglen))
+	{
+		StringBuf lib = str_copy(pValueTop, pValueEnd - pValueTop);
+		Index<char> buf = xsf_get_lib(lib);
+
+		if (buf.len() &&
+			load_libs(pwork->level + 1, buf.begin(), buf.len()) &&
+			load_psf_one((unsigned char *) buf.begin(), buf.len()))
+		{
+			pwork->found++;
+		}
+		else
+		{
+			ret = xsf_tagenum_callback_returnvaluebreak;
+		}
+	}
+	return ret;
+}
+
+static int load_libs(int level, void *pfile, unsigned bytes)
+{
+	char tbuf[16];
+	loadlibwork_t work;
+	int n = 1;
+
+	if (level > 10)
+		return true;
+
+	work.level = level;
+	work.tag = "_lib";
+
+	do
+	{
+		work.taglen = strlen(work.tag);
+		work.found = 0;
+
+		if (xsf_tagenum(load_psfcb, &work, (unsigned char *) pfile, bytes) < 0)
+			return false;
+
+#ifdef HAVE_SPRINTF_S
+		sprintf_s(tbuf, sizeof(tbuf), "_lib%10d", ++n);
+#else
+		sprintf(tbuf, "_lib%10d", ++n);
+#endif
+		work.tag = tbuf;
+	}
+	while (work.found);
+
+	return true;
+}
+
+static int load_psf(void *pfile, unsigned bytes)
+{
+	load_term();
+
+	if (!load_libs(1, pfile, bytes) || !load_psf_one((unsigned char *) pfile, bytes))
+		return false;
+
+	return true;
+}
+
+static void load_getstateinit(unsigned ptr)
+{
+	loaderwork.stateptr = ptr;
+}
+
+static u16 getwordle(const unsigned char *pData)
+{
+	return pData[0] | (((u16)pData[1]) << 8);
+}
+
+static void load_getsta(Status_Reg *ptr, unsigned l)
+{
+	unsigned s = l << 2;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		{
+			u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
+			ptr[i].bits.N = (st >> 31) & 1;
+			ptr[i].bits.Z = (st >> 30) & 1;
+			ptr[i].bits.C = (st >> 29) & 1;
+			ptr[i].bits.V = (st >> 28) & 1;
+			ptr[i].bits.Q = (st >> 27) & 1;
+			ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1);
+			ptr[i].bits.I = (st >> 7) & 1;
+			ptr[i].bits.F = (st >> 6) & 1;
+			ptr[i].bits.T = (st >> 5) & 1;
+			ptr[i].bits.mode = (st >> 0) & 0x1f;
+		}
+	loaderwork.stateptr += s;
+}
+
+static void load_getbool(BOOL *ptr, unsigned l)
+{
+	unsigned s = l << 2;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
+	loaderwork.stateptr += s;
+}
+
+#if defined(SIGNED_IS_NOT_2S_COMPLEMENT)
+/* 2's complement */
+#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x8000) - 0x8000))
+#else
+/* 2's complement */
+#define u32tos32(v) ((s32)v)
+#endif
+
+static void load_gets32(s32 *ptr, unsigned l)
+{
+	unsigned s = l << 2;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)));
+	loaderwork.stateptr += s;
+}
+
+static void load_getu32(u32 *ptr, unsigned l)
+{
+	unsigned s = l << 2;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2));
+	loaderwork.stateptr += s;
+}
+
+static void load_getu16(u16 *ptr, unsigned l)
+{
+	unsigned s = l << 1;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1));
+	loaderwork.stateptr += s;
+}
+
+static void load_getu8(u8 *ptr, unsigned l)
+{
+	unsigned s = l;
+	unsigned i;
+	if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize))
+		return;
+	for (i = 0; i < l; i++)
+		ptr[i] = loaderwork.state[loaderwork.stateptr + i];
+	loaderwork.stateptr += s;
+}
+
+void gdb_stub_fix(armcpu_t *armcpu)
+{
+	/* armcpu->R[15] = armcpu->instruct_adr; */
+	armcpu->next_instruction = armcpu->instruct_adr;
+	if(armcpu->CPSR.bits.T == 0)
+	{
+		armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
+		armcpu->instruct_adr = armcpu->next_instruction;
+		armcpu->next_instruction += 4;
+		armcpu->R[15] = armcpu->next_instruction + 4;
+	}
+	else
+	{
+		armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE);
+		armcpu->instruct_adr = armcpu->next_instruction;
+		armcpu->next_instruction += 2;
+		armcpu->R[15] = armcpu->next_instruction + 2;
+	}
+}
+
+static void load_setstate(void)
+{
+	if (!loaderwork.statesize)
+		return;
+
+	/* Skip over "Desmume Save File" crap */
+	load_getstateinit(0x17);
+
+	/* Read ARM7 cpu registers */
+	load_getu32(&NDS_ARM7.proc_ID, 1);
+	load_getu32(&NDS_ARM7.instruction, 1);
+	load_getu32(&NDS_ARM7.instruct_adr, 1);
+	load_getu32(&NDS_ARM7.next_instruction, 1);
+	load_getu32(NDS_ARM7.R, 16);
+	load_getsta(&NDS_ARM7.CPSR, 1);
+	load_getsta(&NDS_ARM7.SPSR, 1);
+	load_getu32(&NDS_ARM7.R13_usr, 1);
+	load_getu32(&NDS_ARM7.R14_usr, 1);
+	load_getu32(&NDS_ARM7.R13_svc, 1);
+	load_getu32(&NDS_ARM7.R14_svc, 1);
+	load_getu32(&NDS_ARM7.R13_abt, 1);
+	load_getu32(&NDS_ARM7.R14_abt, 1);
+	load_getu32(&NDS_ARM7.R13_und, 1);
+	load_getu32(&NDS_ARM7.R14_und, 1);
+	load_getu32(&NDS_ARM7.R13_irq, 1);
+	load_getu32(&NDS_ARM7.R14_irq, 1);
+	load_getu32(&NDS_ARM7.R8_fiq, 1);
+	load_getu32(&NDS_ARM7.R9_fiq, 1);
+	load_getu32(&NDS_ARM7.R10_fiq, 1);
+	load_getu32(&NDS_ARM7.R11_fiq, 1);
+	load_getu32(&NDS_ARM7.R12_fiq, 1);
+	load_getu32(&NDS_ARM7.R13_fiq, 1);
+	load_getu32(&NDS_ARM7.R14_fiq, 1);
+	load_getsta(&NDS_ARM7.SPSR_svc, 1);
+	load_getsta(&NDS_ARM7.SPSR_abt, 1);
+	load_getsta(&NDS_ARM7.SPSR_und, 1);
+	load_getsta(&NDS_ARM7.SPSR_irq, 1);
+	load_getsta(&NDS_ARM7.SPSR_fiq, 1);
+	load_getu32(&NDS_ARM7.intVector, 1);
+	load_getu8(&NDS_ARM7.LDTBit, 1);
+	load_getbool(&NDS_ARM7.waitIRQ, 1);
+	load_getbool(&NDS_ARM7.wIRQ, 1);
+	load_getbool(&NDS_ARM7.wirq, 1);
+
+	/* Read ARM9 cpu registers */
+	load_getu32(&NDS_ARM9.proc_ID, 1);
+	load_getu32(&NDS_ARM9.instruction, 1);
+	load_getu32(&NDS_ARM9.instruct_adr, 1);
+	load_getu32(&NDS_ARM9.next_instruction, 1);
+	load_getu32(NDS_ARM9.R, 16);
+	load_getsta(&NDS_ARM9.CPSR, 1);
+	load_getsta(&NDS_ARM9.SPSR, 1);
+	load_getu32(&NDS_ARM9.R13_usr, 1);
+	load_getu32(&NDS_ARM9.R14_usr, 1);
+	load_getu32(&NDS_ARM9.R13_svc, 1);
+	load_getu32(&NDS_ARM9.R14_svc, 1);
+	load_getu32(&NDS_ARM9.R13_abt, 1);
+	load_getu32(&NDS_ARM9.R14_abt, 1);
+	load_getu32(&NDS_ARM9.R13_und, 1);
+	load_getu32(&NDS_ARM9.R14_und, 1);
+	load_getu32(&NDS_ARM9.R13_irq, 1);
+	load_getu32(&NDS_ARM9.R14_irq, 1);
+	load_getu32(&NDS_ARM9.R8_fiq, 1);
+	load_getu32(&NDS_ARM9.R9_fiq, 1);
+	load_getu32(&NDS_ARM9.R10_fiq, 1);
+	load_getu32(&NDS_ARM9.R11_fiq, 1);
+	load_getu32(&NDS_ARM9.R12_fiq, 1);
+	load_getu32(&NDS_ARM9.R13_fiq, 1);
+	load_getu32(&NDS_ARM9.R14_fiq, 1);
+	load_getsta(&NDS_ARM9.SPSR_svc, 1);
+	load_getsta(&NDS_ARM9.SPSR_abt, 1);
+	load_getsta(&NDS_ARM9.SPSR_und, 1);
+	load_getsta(&NDS_ARM9.SPSR_irq, 1);
+	load_getsta(&NDS_ARM9.SPSR_fiq, 1);
+	load_getu32(&NDS_ARM9.intVector, 1);
+	load_getu8(&NDS_ARM9.LDTBit, 1);
+	load_getbool(&NDS_ARM9.waitIRQ, 1);
+	load_getbool(&NDS_ARM9.wIRQ, 1);
+	load_getbool(&NDS_ARM9.wirq, 1);
+
+	/* Read in other internal variables that are important */
+	load_gets32(&nds.ARM9Cycle, 1);
+	load_gets32(&nds.ARM7Cycle, 1);
+	load_gets32(&nds.cycles, 1);
+	load_gets32(nds.timerCycle[0], 4);
+	load_gets32(nds.timerCycle[1], 4);
+	load_getbool(nds.timerOver[0], 4);
+	load_getbool(nds.timerOver[1], 4);
+	load_gets32(&nds.nextHBlank, 1);
+	load_getu32(&nds.VCount, 1);
+	load_getu32(&nds.old, 1);
+	load_gets32(&nds.diff, 1);
+	load_getbool(&nds.lignerendu, 1);
+	load_getu16(&nds.touchX, 1);
+	load_getu16(&nds.touchY, 1);
+
+	/* Read in memory/registers specific to the ARM9 */
+	load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000);
+	load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000);
+	load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000);
+	load_getu8 (ARM9Mem.MAIN_MEM, 0x400000);
+	load_getu8 (ARM9Mem.ARM9_REG, 0x10000);
+	load_getu8 (ARM9Mem.ARM9_VMEM, 0x800);
+	load_getu8 (ARM9Mem.ARM9_OAM, 0x800);
+	load_getu8 (ARM9Mem.ARM9_ABG, 0x80000);
+	load_getu8 (ARM9Mem.ARM9_BBG, 0x20000);
+	load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000);
+	load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000);
+	load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000);
+
+	/* Read in memory/registers specific to the ARM7 */
+	load_getu8 (MMU.ARM7_ERAM, 0x10000);
+	load_getu8 (MMU.ARM7_REG, 0x10000);
+	load_getu8 (MMU.ARM7_WIRAM, 0x10000);
+
+	/* Read in shared memory */
+	load_getu8 (MMU.SWIRAM, 0x8000);
+
+#ifdef GDB_STUB
+#else
+	gdb_stub_fix(&NDS_ARM9);
+	gdb_stub_fix(&NDS_ARM7);
+#endif
+}
+
+static struct
+{
+	unsigned char *pcmbufalloc;
+	unsigned char *pcmbuftop;
+	unsigned filled;
+	unsigned used;
+	u32 bufferbytes;
+	u32 cycles;
+	int xfs_load;
+	int sync_type;
+	int arm7_clockdown_level;
+	int arm9_clockdown_level;
+} sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static void SNDIFDeInit(void)
+{
+	if (sndifwork.pcmbufalloc)
+	{
+		free(sndifwork.pcmbufalloc);
+		sndifwork.pcmbufalloc = 0;
+		sndifwork.pcmbuftop = 0;
+		sndifwork.bufferbytes = 0;
+	}
+}
+static int SNDIFInit(int buffersize)
+{
+	u32 bufferbytes = buffersize * sizeof(s16);
+	SNDIFDeInit();
+	sndifwork.pcmbufalloc = (unsigned char *) malloc(bufferbytes + 3);
+	if (!sndifwork.pcmbufalloc)
+		return -1;
+	sndifwork.pcmbuftop = (unsigned char *) (((uintptr_t) sndifwork.pcmbufalloc + 3) & ~3);
+	sndifwork.bufferbytes = bufferbytes;
+	sndifwork.filled = 0;
+	sndifwork.used = 0;
+	sndifwork.cycles = 0;
+	return 0;
+}
+static void SNDIFMuteAudio(void)
+{
+}
+static void SNDIFUnMuteAudio(void)
+{
+}
+static void SNDIFSetVolume(int volume)
+{
+}
+static u32 SNDIFGetAudioSpace(void)
+{
+	return sndifwork.bufferbytes >> 2; // bytes to samples
+}
+static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples)
+{
+	u32 num_bytes = num_samples << 2;
+	if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes;
+	memcpy(sndifwork.pcmbuftop, buffer, num_bytes);
+	sndifwork.filled = num_bytes;
+	sndifwork.used = 0;
+}
+#define VIO2SFSNDIFID 2
+static SoundInterface_struct VIO2SFSNDIF =
+{
+	VIO2SFSNDIFID,
+	"vio2sf Sound Interface",
+	SNDIFInit,
+	SNDIFDeInit,
+	SNDIFUpdateAudio,
+	SNDIFGetAudioSpace,
+	SNDIFMuteAudio,
+	SNDIFUnMuteAudio,
+	SNDIFSetVolume
+};
+
+SoundInterface_struct *SNDCoreList[] = {
+	&VIO2SFSNDIF,
+	&SNDDummy,
+	nullptr
+};
+
+#ifdef GDB_STUB
+static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0;
+static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0;
+#endif
+
+int xsf_start(void *pfile, unsigned bytes)
+{
+	int frames = xsf_tagget_int("_frames", (unsigned char *) pfile, bytes, -1);
+	int clockdown = xsf_tagget_int("_clockdown", (unsigned char *) pfile, bytes, 0);
+	sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", (unsigned char *) pfile, bytes, 0);
+	sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", (unsigned char *) pfile, bytes, clockdown);
+	sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", (unsigned char *) pfile, bytes, clockdown);
+
+	sndifwork.xfs_load = 0;
+	printf("load_psf... ");
+	if (!load_psf(pfile, bytes))
+		return false;
+	printf("ok!\n");
+
+#ifdef GDB_STUB
+	if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface))
+#else
+	if (NDS_Init())
+#endif
+		return false;
+
+	SPU_ChangeSoundCore(VIO2SFSNDIFID, 737);
+
+	execute = false;
+
+	MMU_unsetRom();
+	if (loaderwork.rom)
+	{
+		NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1);
+	}
+
+	NDS_Reset();
+
+	execute = true;
+
+	if (loaderwork.state)
+	{
+		armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15];
+		int proc;
+		if (frames == -1)
+		{
+
+			/* set initial ARM9 coprocessor state */
+
+			armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0);
+			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0);
+			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0);
+			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
+			armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4);
+			armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0);
+			armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0);
+			armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0);
+			armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0);
+			armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0);
+			armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0);
+			armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0);
+			armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1);
+
+			armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0);
+
+			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1);
+			armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0);
+			armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0);
+			armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3);
+			armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2);
+			armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0);
+			armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0);
+
+			armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4);
+			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1);
+			armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1);
+
+			/* set initial timer state */
+
+			MMU_write16(0, REG_TM0CNTL, 0x0000);
+			MMU_write16(0, REG_TM0CNTH, 0x00C1);
+			MMU_write16(1, REG_TM0CNTL, 0x0000);
+			MMU_write16(1, REG_TM0CNTH, 0x00C1);
+			MMU_write16(1, REG_TM1CNTL, 0xf7e7);
+			MMU_write16(1, REG_TM1CNTH, 0x00C1);
+
+			/* set initial interrupt state */
+
+			MMU.reg_IME[0] = 0x00000001;
+			MMU.reg_IE[0]  = 0x00042001;
+			MMU.reg_IME[1] = 0x00000001;
+			MMU.reg_IE[1]  = 0x0104009d;
+		}
+		else if (frames > 0)
+		{
+			/* execute boot code */
+			int i;
+			for (i=0; i<frames; i++)
+				NDS_exec_frame(0, 0);
+			i = 0;
+		}
+
+		/* load state */
+
+		load_setstate();
+		free(loaderwork.state);
+		loaderwork.state = 0;
+
+		if (frames == -1)
+		{
+			armcp15_moveARM2CP(c9, (NDS_ARM9.R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0);
+		}
+
+		/* restore timer state */
+
+		for (proc = 0; proc < 2; proc++)
+		{
+			MMU_write16(proc, REG_TM0CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF));
+			MMU_write16(proc, REG_TM1CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF));
+			MMU_write16(proc, REG_TM2CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF));
+			MMU_write16(proc, REG_TM3CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF));
+		}
+	}
+	else if (frames > 0)
+	{
+		/* skip 1 sec */
+		int i;
+		for (i=0; i<frames; i++)
+			NDS_exec_frame(0, 0);
+	}
+	execute = true;
+	sndifwork.xfs_load = 1;
+	return true;
+}
+
+int xsf_gen(void *pbuffer, unsigned samples)
+{
+	unsigned char *ptr = (unsigned char *) pbuffer;
+	unsigned bytes = samples <<= 2;
+	if (!sndifwork.xfs_load) return 0;
+	while (bytes)
+	{
+		unsigned remainbytes = sndifwork.filled - sndifwork.used;
+		if (remainbytes > 0)
+		{
+			if (remainbytes > bytes)
+			{
+				memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes);
+				sndifwork.used += bytes;
+				ptr += bytes;
+				remainbytes -= bytes; /**/
+				bytes = 0;  /**/
+				break;
+			}
+			else
+			{
+				memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes);
+				sndifwork.used += remainbytes;
+				ptr += remainbytes;
+				bytes -= remainbytes;
+				remainbytes = 0;
+			}
+		}
+		if (remainbytes == 0)
+		{
+
+#define HBASE_CYCLES 33509300.322234
+#define VBASE_CYCLES (((double)HBASE_CYCLES) / 100)
+#define HSAMPLES ((u32)((44100.0 * 6 * (99 + 256)) / HBASE_CYCLES))
+#define VSAMPLES ((u32)((44100.0 * 6 * (99 + 256) * 263) / HBASE_CYCLES))
+
+			int numsamples;
+			if (sndifwork.sync_type == 1)
+			{
+				/* vsync */
+				sndifwork.cycles += (441 * 6 * (99 + 256) * 263);
+				if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1)))
+				{
+					numsamples = (VSAMPLES + 1);
+					sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1));
+				}
+				else
+				{
+					numsamples = (VSAMPLES + 0);
+					sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0));
+				}
+				NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
+			}
+			else
+			{
+				/* hsync */
+				sndifwork.cycles += (44100 * 6 * (99 + 256));
+				if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1)))
+				{
+					numsamples = (HSAMPLES + 1);
+					sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1));
+				}
+				else
+				{
+					numsamples = (HSAMPLES + 0);
+					sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0));
+				}
+				NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level);
+			}
+			SPU_EmulateSamples(numsamples);
+		}
+	}
+	return ptr - (unsigned char *)pbuffer;
+}
+
+void xsf_term(void)
+{
+	MMU_unsetRom();
+	NDS_DeInit();
+	load_term();
+}
diff --git a/src/xsf/vio2sf.h b/src/xsf/vio2sf.h
index 1415436311fc..542f7160e603 100644
--- a/src/xsf/vio2sf.h
+++ b/src/xsf/vio2sf.h
@@ -1,7 +1,6 @@
-#define XSF_FALSE (0)
-#define XSF_TRUE (!XSF_FALSE)
+#include <libaudcore/index.h>
 
 int xsf_start(void *pfile, unsigned bytes);
 int xsf_gen(void *pbuffer, unsigned samples);
-int xsf_get_lib(char *pfilename, void **ppbuffer, unsigned int *plength);
+Index<char> xsf_get_lib(char *pfilename);
 void xsf_term(void);
diff --git a/src/xsf/xsfdrv.h b/src/xsf/xsfdrv.h
index a1c7300c01ab..afcb17adba73 100644
--- a/src/xsf/xsfdrv.h
+++ b/src/xsf/xsfdrv.h
@@ -1,7 +1,3 @@
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef int (PASCAL * LPFNGETLIB_XSFDRV)(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize);
 typedef struct
 {
@@ -14,8 +10,3 @@ typedef struct
 
 typedef IXSFDRV * (PASCAL * LPFNXSFDRVSETUP)(LPFNGETLIB_XSFDRV lpfn, void *lpWork);
 /* IXSFDRV * PASCAL XSFDRVSetup(LPFNGETLIB_XSFDRV lpfn, void *lpWork); */
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/src/xspf/Makefile b/src/xspf/Makefile
index 4443d5014e05..9a1771ae84bb 100644
--- a/src/xspf/Makefile
+++ b/src/xspf/Makefile
@@ -1,12 +1,14 @@
 PLUGIN = xspf${PLUGIN_SUFFIX}
 
-SRCS = xspf.c
+SRCS = xspf.cc
 
 include ../../buildsys.mk
 include ../../extra.mk
 
 plugindir := ${plugindir}/${CONTAINER_PLUGIN_DIR}
 
+LD = ${CXX}
+
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${XML_CFLAGS} -I../..
 LIBS += ${GLIB_LIBS} ${XML_LIBS}
diff --git a/src/xspf/xspf.c b/src/xspf/xspf.c
deleted file mode 100644
index e513a029a1a2..000000000000
--- a/src/xspf/xspf.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- *                    Giacomo Lozito, Derek Pomery, Yoshiki Yazawa
- *                    and Matti Hämäläinen.
- * 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; 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.
- */
-
-#include <glib.h>
-#include <string.h>
-
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-#include <libxml/xmlsave.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#include <libxml/uri.h>
-
-#include <audacious/i18n.h>
-#include <audacious/plugin.h>
-#include <libaudcore/audstrings.h>
-
-#define XSPF_ROOT_NODE_NAME "playlist"
-#define XSPF_XMLNS "http://xspf.org/ns/0/"
-
-typedef struct {
-    gint tupleField;
-    gchar *xspfName;
-    TupleValueType type;
-    gboolean isMeta;
-} xspf_entry_t;
-
-
-static const xspf_entry_t xspf_entries[] = {
-    { FIELD_ARTIST,       "creator",      TUPLE_STRING,   FALSE},
-    { FIELD_TITLE,        "title",        TUPLE_STRING,   FALSE},
-    { FIELD_ALBUM,        "album",        TUPLE_STRING,   FALSE},
-    { FIELD_COMMENT,      "annotation",   TUPLE_STRING,   FALSE},
-    { FIELD_GENRE,        "genre",        TUPLE_STRING,   TRUE},
-
-    { FIELD_TRACK_NUMBER, "trackNum",     TUPLE_INT,      FALSE},
-    { FIELD_LENGTH,       "duration",     TUPLE_INT,      FALSE},
-    { FIELD_YEAR,         "year",         TUPLE_INT,      TRUE},
-    { FIELD_QUALITY,      "quality",      TUPLE_STRING,   TRUE},
-
-    { FIELD_CODEC,        "codec",        TUPLE_STRING,   TRUE},
-
-    { FIELD_SONG_ARTIST,  "song-artist",  TUPLE_STRING,   TRUE},
-    { FIELD_COMPOSER,     "composer",     TUPLE_STRING,   TRUE},
-    { FIELD_PERFORMER,    "performer",    TUPLE_STRING,   TRUE},
-    { FIELD_COPYRIGHT,    "copyright",    TUPLE_STRING,   TRUE},
-    { FIELD_DATE,         "date",         TUPLE_STRING,   TRUE},
-
-    { FIELD_SUBSONG_ID,   "subsong-id",   TUPLE_INT,      TRUE},
-    { FIELD_SUBSONG_NUM,  "subsong-num",  TUPLE_INT,      TRUE},
-    { FIELD_MIMETYPE,     "mime-type",    TUPLE_STRING,   TRUE},
-    { FIELD_BITRATE,      "bitrate",      TUPLE_INT,      TRUE},
-    { FIELD_SEGMENT_START,"seg-start",    TUPLE_INT,      TRUE},
-    { FIELD_SEGMENT_END,  "seg-end",      TUPLE_INT,      TRUE},
-
-    { FIELD_GAIN_ALBUM_GAIN, "gain-album-gain", TUPLE_INT, TRUE},
-    { FIELD_GAIN_ALBUM_PEAK, "gain-album-peak", TUPLE_INT, TRUE},
-    { FIELD_GAIN_TRACK_GAIN, "gain-track-gain", TUPLE_INT, TRUE},
-    { FIELD_GAIN_TRACK_PEAK, "gain-track-peak", TUPLE_INT, TRUE},
-    { FIELD_GAIN_GAIN_UNIT, "gain-gain-unit", TUPLE_INT,  TRUE},
-    { FIELD_GAIN_PEAK_UNIT, "gain-peak-unit", TUPLE_INT,  TRUE},
-};
-
-static void xspf_add_file (xmlNode * track, const gchar * filename, const gchar
- * base, Index * filenames, Index * tuples)
-{
-    xmlNode *nptr;
-    gchar *location = NULL;
-    Tuple * tuple = NULL;
-
-    for (nptr = track->children; nptr != NULL; nptr = nptr->next) {
-        if (nptr->type == XML_ELEMENT_NODE) {
-            if (!xmlStrcmp(nptr->name, (xmlChar *)"location")) {
-                /* Location is a special case */
-                gchar *str = (gchar *)xmlNodeGetContent(nptr);
-
-                if (strstr (str, "://") != NULL)
-                    location = str_get (str);
-                else if (str[0] == '/' && base != NULL)
-                {
-                    const gchar * colon = strstr (base, "://");
-
-                    if (colon != NULL)
-                        location = str_printf ("%.*s%s", (gint) (colon + 3 -
-                         base), base, str);
-                }
-                else if (base != NULL)
-                {
-                    const gchar * slash = strrchr (base, '/');
-
-                    if (slash != NULL)
-                        location = str_printf ("%.*s%s", (gint) (slash + 1 -
-                         base), base, str);
-                }
-
-                xmlFree(str);
-            } else {
-                /* Rest of the nodes are handled here */
-                gint i;
-                gboolean isMeta;
-                xmlChar *findName;
-
-                if (!xmlStrcmp(nptr->name, (xmlChar *)"meta")) {
-                    isMeta = TRUE;
-                    findName = xmlGetProp(nptr, (xmlChar *)"rel");
-                } else {
-                    isMeta = FALSE;
-                    findName = xmlStrdup(nptr->name);
-                }
-
-                for (i = 0; i < ARRAY_LEN (xspf_entries); i++)
-                if ((xspf_entries[i].isMeta == isMeta) &&
-                    !xmlStrcmp(findName, (xmlChar *)xspf_entries[i].xspfName)) {
-                    xmlChar *str = xmlNodeGetContent(nptr);
-                    switch (xspf_entries[i].type) {
-                        case TUPLE_STRING:
-                            if (! tuple)
-                                tuple = tuple_new ();
-                            tuple_set_str(tuple, xspf_entries[i].tupleField, (gchar *)str);
-                            break;
-
-                        case TUPLE_INT:
-                            if (! tuple)
-                                tuple = tuple_new ();
-                            tuple_set_int(tuple, xspf_entries[i].tupleField, atol((char *)str));
-                            break;
-
-                        default:
-                            break;
-                    }
-                    xmlFree(str);
-                    break;
-                }
-
-                xmlFree(findName);
-            }
-        }
-    }
-
-    if (location != NULL)
-    {
-        if (tuple)
-            tuple_set_filename (tuple, location);
-
-        index_insert (filenames, -1, location);
-        index_insert (tuples, -1, tuple);
-    }
-    else if (tuple)
-        tuple_unref (tuple);
-}
-
-
-static void xspf_find_track (xmlNode * tracklist, const gchar * filename, const
- gchar * base, Index * filenames, Index * tuples)
-{
-    xmlNode *nptr;
-
-    for (nptr = tracklist->children; nptr != NULL; nptr = nptr->next) {
-        if (nptr->type == XML_ELEMENT_NODE &&
-         ! xmlStrcmp (nptr->name, (xmlChar *) "track"))
-            xspf_add_file (nptr, filename, base, filenames, tuples);
-    }
-}
-
-static gint read_cb (void * file, gchar * buf, gint len)
-{
-    return vfs_fread (buf, 1, len, file);
-}
-
-static gint write_cb (void * file, const gchar * buf, gint len)
-{
-    return vfs_fwrite (buf, 1, len, file);
-}
-
-static gint close_cb (void * file)
-{
-    return 0;
-}
-
-static gboolean xspf_playlist_load (const gchar * filename, VFSFile * file,
- gchar * * title, Index * filenames, Index * tuples)
-{
-    xmlDoc * doc = xmlReadIO (read_cb, close_cb, file, filename, NULL,
-     XML_PARSE_RECOVER);
-    if (! doc)
-        return FALSE;
-
-    * title = NULL;
-
-    xmlNode *nptr, *nptr2;
-
-    // find trackList
-    for (nptr = doc->children; nptr != NULL; nptr = nptr->next) {
-        if (nptr->type == XML_ELEMENT_NODE &&
-            !xmlStrcmp(nptr->name, (xmlChar *)"playlist")) {
-            gchar * base;
-
-            base = (gchar *)xmlNodeGetBase(doc, nptr);
-
-            for (nptr2 = nptr->children; nptr2; nptr2 = nptr2->next)
-            {
-                if (nptr2->type != XML_ELEMENT_NODE)
-                    continue;
-
-                if (! xmlStrcmp (nptr2->name, (xmlChar *) "title"))
-                {
-                    xmlChar * xml_title = xmlNodeGetContent (nptr2);
-                    if (xml_title && xml_title[0])
-                    {
-                        str_unref (* title);
-                        * title = str_get ((gchar *) xml_title);
-                    }
-                    xmlFree (xml_title);
-                }
-                else if (! xmlStrcmp (nptr2->name, (xmlChar *) "trackList"))
-                    xspf_find_track (nptr2, filename, base, filenames, tuples);
-            }
-
-            xmlFree (base);
-        }
-    }
-
-    xmlFreeDoc(doc);
-    return TRUE;
-}
-
-
-#define IS_VALID_CHAR(c) (((c) >= 0x20 && (c) <= 0xd7ff) || \
-                          ((c) == 0x9) || \
-                          ((c) == 0xa) || \
-                          ((c) == 0xd) || \
-                          ((c) >= 0xe000 && (c) <= 0xfffd) || \
-                          ((c) >= 0x10000 && (c) <= 0x10ffff))
-
-/* check for characters that are invalid in XML */
-static gboolean is_valid_string (const gchar * s, gchar * * subst)
-{
-    if (! g_utf8_validate (s, -1, NULL))
-        goto NOT_VALID;
-
-    const gchar * p = s;
-    while (* p)
-    {
-        gunichar c = g_utf8_get_char (p);
-
-        if (IS_VALID_CHAR (c))
-            p = g_utf8_next_char (p);
-        else
-            goto NOT_VALID;
-    }
-
-    return TRUE;
-
-NOT_VALID:;
-    gint len = 0;
-
-    p = s;
-    while (* p)
-    {
-        gunichar c = g_utf8_get_char_validated (p, -1);
-
-        if (IS_VALID_CHAR (c))
-        {
-            len += g_unichar_to_utf8 (c, NULL);
-            p = g_utf8_next_char (p);
-        }
-        else
-            p ++;
-    }
-
-    * subst = g_malloc (len + 1);
-    gchar * w = * subst;
-
-    p = s;
-    while (* p)
-    {
-        gunichar c = g_utf8_get_char_validated (p, -1);
-
-        if (IS_VALID_CHAR (c))
-        {
-            w += g_unichar_to_utf8 (c, w);
-            p = g_utf8_next_char (p);
-        }
-        else
-            p ++;
-    }
-
-    * w = 0;
-    return FALSE;
-}
-
-
-static void xspf_add_node(xmlNodePtr node, TupleValueType type,
-        gboolean isMeta, const gchar *xspfName, const gchar *strVal,
-        const gint intVal)
-{
-    gchar tmps[64];
-    xmlNodePtr tmp;
-
-    if (isMeta) {
-        tmp = xmlNewNode(NULL, (xmlChar *) "meta");
-        xmlSetProp(tmp, (xmlChar *) "rel", (xmlChar *) xspfName);
-    } else
-        tmp = xmlNewNode(NULL, (xmlChar *) xspfName);
-
-    switch (type) {
-        case TUPLE_STRING:;
-            gchar * subst;
-            if (is_valid_string (strVal, & subst))
-                xmlAddChild (tmp, xmlNewText ((xmlChar *) strVal));
-            else
-            {
-                xmlAddChild (tmp, xmlNewText ((xmlChar *) subst));
-                g_free (subst);
-            }
-            break;
-
-        case TUPLE_INT:
-            str_itoa (intVal, tmps, sizeof tmps);
-            xmlAddChild(tmp, xmlNewText((xmlChar *) tmps));
-            break;
-
-        default:
-            break;
-    }
-
-    xmlAddChild(node, tmp);
-}
-
-
-static gboolean xspf_playlist_save (const gchar * filename, VFSFile * file,
- const gchar * title, Index * filenames, Index * tuples)
-{
-    gint entries = index_count (filenames);
-    xmlDocPtr doc;
-    xmlNodePtr rootnode, tracklist;
-    gint count;
-
-    doc = xmlNewDoc((xmlChar *)"1.0");
-    doc->charset = XML_CHAR_ENCODING_UTF8;
-    doc->encoding = xmlStrdup((xmlChar *)"UTF-8");
-
-    rootnode = xmlNewNode(NULL, (xmlChar *)XSPF_ROOT_NODE_NAME);
-    xmlSetProp(rootnode, (xmlChar *)"version", (xmlChar *)"1");
-    xmlSetProp(rootnode, (xmlChar *)"xmlns", (xmlChar *)XSPF_XMLNS);
-
-    /* common */
-    xmlDocSetRootElement(doc, rootnode);
-
-    if (title)
-        xspf_add_node (rootnode, TUPLE_STRING, FALSE, "title", title, 0);
-
-    tracklist = xmlNewNode(NULL, (xmlChar *)"trackList");
-    xmlAddChild(rootnode, tracklist);
-
-    for (count = 0; count < entries; count ++)
-    {
-        const gchar * filename = index_get (filenames, count);
-        const Tuple * tuple = index_get (tuples, count);
-        xmlNodePtr track, location;
-        gchar *scratch = NULL;
-        gint scratchi = 0;
-
-        track = xmlNewNode(NULL, (xmlChar *)"track");
-        location = xmlNewNode(NULL, (xmlChar *)"location");
-
-        xmlAddChild(location, xmlNewText((xmlChar *)filename));
-        xmlAddChild(track, location);
-        xmlAddChild(tracklist, track);
-
-        if (tuple != NULL)
-        {
-            gint i;
-            for (i = 0; i < ARRAY_LEN (xspf_entries); i++) {
-                const xspf_entry_t *xs = &xspf_entries[i];
-                gboolean isOK = (tuple_get_value_type (tuple, xs->tupleField) == xs->type);
-
-                switch (xs->type) {
-                    case TUPLE_STRING:
-                        scratch = tuple_get_str (tuple, xs->tupleField);
-                        if (! scratch)
-                            isOK = FALSE;
-                        str_unref(scratch);
-                        break;
-                    case TUPLE_INT:
-                        scratchi = tuple_get_int (tuple, xs->tupleField);
-                        break;
-                    default:
-                        break;
-                }
-
-                if (isOK)
-                    xspf_add_node(track, xs->type, xs->isMeta, xs->xspfName, scratch, scratchi);
-            }
-        }
-    }
-
-    xmlSaveCtxt * save = xmlSaveToIO (write_cb, close_cb, file, NULL,
-     XML_SAVE_FORMAT);
-    if (! save)
-        goto ERR;
-
-    if (xmlSaveDoc (save, doc) < 0 || xmlSaveClose (save) < 0)
-        goto ERR;
-
-    xmlFreeDoc(doc);
-    return TRUE;
-
-ERR:
-    xmlFreeDoc (doc);
-    return FALSE;
-}
-
-static const gchar * const xspf_exts[] = {"xspf", NULL};
-
-AUD_PLAYLIST_PLUGIN
-(
- .name = N_("XML Shareable Playlists (XSPF)"),
- .domain = PACKAGE,
- .extensions = xspf_exts,
- .load = xspf_playlist_load,
- .save = xspf_playlist_save
-)
diff --git a/src/xspf/xspf.cc b/src/xspf/xspf.cc
new file mode 100644
index 000000000000..67b71b7c279e
--- /dev/null
+++ b/src/xspf/xspf.cc
@@ -0,0 +1,429 @@
+/*
+ * Audacious: A cross-platform multimedia player
+ * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
+ *                    Giacomo Lozito, Derek Pomery, Yoshiki Yazawa
+ *                    and Matti Hämäläinen.
+ * 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; 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.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlsave.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/uri.h>
+
+#include <libaudcore/i18n.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/audstrings.h>
+
+#define XSPF_ROOT_NODE_NAME "playlist"
+#define XSPF_XMLNS "http://xspf.org/ns/0/"
+
+typedef struct {
+    Tuple::Field tupleField;
+    const char *xspfName;
+    Tuple::ValueType type;
+    bool isMeta;
+} xspf_entry_t;
+
+
+static const xspf_entry_t xspf_entries[] = {
+    {Tuple::Artist, "creator", Tuple::String, false},
+    {Tuple::Title, "title", Tuple::String, false},
+    {Tuple::Album, "album", Tuple::String, false},
+    {Tuple::Comment, "annotation", Tuple::String, false},
+    {Tuple::Genre, "genre", Tuple::String, true},
+
+    {Tuple::Track, "trackNum", Tuple::Int, false},
+    {Tuple::Length, "duration", Tuple::Int, false},
+    {Tuple::Year, "year", Tuple::Int, true},
+    {Tuple::Quality, "quality", Tuple::String, true},
+
+    {Tuple::Codec, "codec", Tuple::String, true},
+
+    {Tuple::AlbumArtist, "album-artist", Tuple::String, true},
+    {Tuple::Composer, "composer", Tuple::String, true},
+    {Tuple::Performer, "performer", Tuple::String, true},
+    {Tuple::Copyright, "copyright", Tuple::String, true},
+    {Tuple::Date, "date", Tuple::String, true},
+
+    {Tuple::Subtune, "subsong-id", Tuple::Int, true},
+    {Tuple::NumSubtunes, "subsong-num", Tuple::Int, true},
+    {Tuple::MIMEType, "mime-type", Tuple::String, true},
+    {Tuple::Bitrate, "bitrate", Tuple::Int, true},
+    {Tuple::StartTime, "seg-start", Tuple::Int, true},
+    {Tuple::EndTime, "seg-end", Tuple::Int, true},
+
+    {Tuple::AlbumGain, "gain-album-gain", Tuple::Int, true},
+    {Tuple::AlbumPeak, "gain-album-peak", Tuple::Int, true},
+    {Tuple::TrackGain, "gain-track-gain", Tuple::Int, true},
+    {Tuple::TrackPeak, "gain-track-peak", Tuple::Int, true},
+    {Tuple::GainDivisor, "gain-gain-unit", Tuple::Int, true},
+    {Tuple::PeakDivisor, "gain-peak-unit", Tuple::Int, true},
+};
+
+static const char * const xspf_exts[] = {"xspf"};
+
+class XSPFLoader : public PlaylistPlugin
+{
+public:
+    static constexpr PluginInfo info = {N_("XML Shareable Playlists (XSPF)"), PACKAGE};
+
+    constexpr XSPFLoader () : PlaylistPlugin (info, xspf_exts, true) {}
+
+    bool load (const char * filename, VFSFile & file, String & title,
+     Index<PlaylistAddItem> & items);
+    bool save (const char * filename, VFSFile & file, const char * title,
+     const Index<PlaylistAddItem> & items);
+};
+
+EXPORT XSPFLoader aud_plugin_instance;
+
+static void xspf_add_file (xmlNode * track, const char * filename,
+ const char * base, Index<PlaylistAddItem> & items)
+{
+    xmlNode *nptr;
+    String location;
+    Tuple tuple;
+
+    for (nptr = track->children; nptr != nullptr; nptr = nptr->next) {
+        if (nptr->type == XML_ELEMENT_NODE) {
+            if (!xmlStrcmp(nptr->name, (xmlChar *)"location")) {
+                /* Location is a special case */
+                char *str = (char *)xmlNodeGetContent(nptr);
+
+                if (strstr (str, "://") != nullptr)
+                    location = String (str);
+                else if (str[0] == '/' && base != nullptr)
+                {
+                    const char * colon = strstr (base, "://");
+
+                    if (colon != nullptr)
+                        location = String (str_printf ("%.*s%s",
+                         (int) (colon + 3 - base), base, str));
+                }
+                else if (base != nullptr)
+                {
+                    const char * slash = strrchr (base, '/');
+
+                    if (slash != nullptr)
+                        location = String (str_printf ("%.*s%s",
+                         (int) (slash + 1 - base), base, str));
+                }
+
+                xmlFree(str);
+            } else {
+                /* Rest of the nodes are handled here */
+                bool isMeta;
+                xmlChar *findName;
+
+                if (!xmlStrcmp(nptr->name, (xmlChar *)"meta")) {
+                    isMeta = true;
+                    findName = xmlGetProp(nptr, (xmlChar *)"rel");
+                } else {
+                    isMeta = false;
+                    findName = xmlStrdup(nptr->name);
+                }
+
+                for (const xspf_entry_t & entry : xspf_entries)
+                if ((entry.isMeta == isMeta) &&
+                    !xmlStrcmp(findName, (xmlChar *)entry.xspfName)) {
+                    xmlChar *str = xmlNodeGetContent(nptr);
+                    switch (entry.type) {
+                        case Tuple::String:
+                            tuple.set_str (entry.tupleField, (char *)str);
+                            break;
+
+                        case Tuple::Int:
+                            tuple.set_int (entry.tupleField, atol((char *)str));
+                            break;
+
+                        default:
+                            break;
+                    }
+                    xmlFree(str);
+                    break;
+                }
+
+                xmlFree(findName);
+            }
+        }
+    }
+
+    if (location != nullptr)
+    {
+        if (tuple)
+            tuple.set_filename (location);
+
+        items.append (location, std::move (tuple));
+    }
+}
+
+
+static void xspf_find_track (xmlNode * tracklist, const char * filename,
+ const char * base, Index<PlaylistAddItem> & items)
+{
+    xmlNode *nptr;
+
+    for (nptr = tracklist->children; nptr != nullptr; nptr = nptr->next) {
+        if (nptr->type == XML_ELEMENT_NODE &&
+         ! xmlStrcmp (nptr->name, (xmlChar *) "track"))
+            xspf_add_file (nptr, filename, base, items);
+    }
+}
+
+static int read_cb (void * file, char * buf, int len)
+{
+    return ((VFSFile *) file)->fread (buf, 1, len);
+}
+
+static int write_cb (void * file, const char * buf, int len)
+{
+    return ((VFSFile *) file)->fwrite (buf, 1, len);
+}
+
+static int close_cb (void * file)
+{
+    return 0;
+}
+
+bool XSPFLoader::load (const char * filename, VFSFile & file, String & title,
+ Index<PlaylistAddItem> & items)
+{
+    xmlDoc * doc = xmlReadIO (read_cb, close_cb, & file, filename, nullptr, XML_PARSE_RECOVER);
+    if (! doc)
+        return false;
+
+    xmlNode *nptr, *nptr2;
+
+    // find trackList
+    for (nptr = doc->children; nptr != nullptr; nptr = nptr->next) {
+        if (nptr->type == XML_ELEMENT_NODE &&
+            !xmlStrcmp(nptr->name, (xmlChar *)"playlist")) {
+            char * base;
+
+            base = (char *)xmlNodeGetBase(doc, nptr);
+
+            for (nptr2 = nptr->children; nptr2; nptr2 = nptr2->next)
+            {
+                if (nptr2->type != XML_ELEMENT_NODE)
+                    continue;
+
+                if (! xmlStrcmp (nptr2->name, (xmlChar *) "title"))
+                {
+                    xmlChar * xml_title = xmlNodeGetContent (nptr2);
+                    if (xml_title && xml_title[0])
+                        title = String ((char *) xml_title);
+                    xmlFree (xml_title);
+                }
+                else if (! xmlStrcmp (nptr2->name, (xmlChar *) "trackList"))
+                    xspf_find_track (nptr2, filename, base, items);
+            }
+
+            xmlFree (base);
+        }
+    }
+
+    xmlFreeDoc(doc);
+    return true;
+}
+
+
+#define IS_VALID_CHAR(c) (((c) >= 0x20 && (c) <= 0xd7ff) || \
+                          ((c) == 0x9) || \
+                          ((c) == 0xa) || \
+                          ((c) == 0xd) || \
+                          ((c) >= 0xe000 && (c) <= 0xfffd) || \
+                          ((c) >= 0x10000 && (c) <= 0x10ffff))
+
+/* check for characters that are invalid in XML */
+static bool is_valid_string (const char * s, char * * subst)
+{
+    bool valid = g_utf8_validate (s, -1, nullptr);
+
+    if (valid)
+    {
+        for (const char * p = s; * p; p = g_utf8_next_char (p))
+        {
+            if (! IS_VALID_CHAR (g_utf8_get_char (p)))
+            {
+                valid = false;
+                break;
+            }
+        }
+
+        if (valid)
+            return true;
+    }
+
+    int len = 0;
+
+    const char * p = s;
+    while (* p)
+    {
+        gunichar c = g_utf8_get_char_validated (p, -1);
+
+        if (IS_VALID_CHAR (c))
+        {
+            len += g_unichar_to_utf8 (c, nullptr);
+            p = g_utf8_next_char (p);
+        }
+        else
+            p ++;
+    }
+
+    * subst = g_new (char, len + 1);
+    char * w = * subst;
+
+    p = s;
+    while (* p)
+    {
+        gunichar c = g_utf8_get_char_validated (p, -1);
+
+        if (IS_VALID_CHAR (c))
+        {
+            w += g_unichar_to_utf8 (c, w);
+            p = g_utf8_next_char (p);
+        }
+        else
+            p ++;
+    }
+
+    * w = 0;
+    return false;
+}
+
+
+static void xspf_add_node(xmlNodePtr node, Tuple::ValueType type,
+        bool isMeta, const char *xspfName, const char *strVal,
+        const int intVal)
+{
+    xmlNodePtr tmp;
+
+    if (isMeta) {
+        tmp = xmlNewNode(nullptr, (xmlChar *) "meta");
+        xmlSetProp(tmp, (xmlChar *) "rel", (xmlChar *) xspfName);
+    } else
+        tmp = xmlNewNode(nullptr, (xmlChar *) xspfName);
+
+    switch (type) {
+        case Tuple::String:;
+            char * subst;
+            if (is_valid_string (strVal, & subst))
+                xmlAddChild (tmp, xmlNewText ((xmlChar *) strVal));
+            else
+            {
+                xmlAddChild (tmp, xmlNewText ((xmlChar *) subst));
+                g_free (subst);
+            }
+            break;
+
+        case Tuple::Int:
+            xmlAddChild (tmp, xmlNewText ((xmlChar *) (char *) int_to_str (intVal)));
+            break;
+
+        default:
+            break;
+    }
+
+    xmlAddChild(node, tmp);
+}
+
+
+bool XSPFLoader::save (const char * filename, VFSFile & file,
+ const char * title, const Index<PlaylistAddItem> & items)
+{
+    xmlDocPtr doc;
+    xmlNodePtr rootnode, tracklist;
+
+    doc = xmlNewDoc((xmlChar *)"1.0");
+    doc->charset = XML_CHAR_ENCODING_UTF8;
+    doc->encoding = xmlStrdup((xmlChar *)"UTF-8");
+
+    rootnode = xmlNewNode(nullptr, (xmlChar *)XSPF_ROOT_NODE_NAME);
+    xmlSetProp(rootnode, (xmlChar *)"version", (xmlChar *)"1");
+    xmlSetProp(rootnode, (xmlChar *)"xmlns", (xmlChar *)XSPF_XMLNS);
+
+    /* common */
+    xmlDocSetRootElement(doc, rootnode);
+
+    if (title)
+        xspf_add_node (rootnode, Tuple::String, false, "title", title, 0);
+
+    tracklist = xmlNewNode(nullptr, (xmlChar *)"trackList");
+    xmlAddChild(rootnode, tracklist);
+
+    for (auto & item : items)
+    {
+        const char * filename = item.filename;
+        const Tuple & tuple = item.tuple;
+        xmlNodePtr track, location;
+        String scratch;
+        int scratchi = 0;
+
+        track = xmlNewNode(nullptr, (xmlChar *)"track");
+        location = xmlNewNode(nullptr, (xmlChar *)"location");
+
+        xmlAddChild(location, xmlNewText((xmlChar *)filename));
+        xmlAddChild(track, location);
+        xmlAddChild(tracklist, track);
+
+        if (tuple)
+        {
+            for (const xspf_entry_t & entry : xspf_entries)
+            {
+                bool isOK = (tuple.get_value_type (entry.tupleField) == entry.type);
+
+                switch (entry.type) {
+                    case Tuple::String:
+                        scratch = tuple.get_str (entry.tupleField);
+                        if (! scratch)
+                            isOK = false;
+                        break;
+                    case Tuple::Int:
+                        scratchi = tuple.get_int (entry.tupleField);
+                        break;
+                    default:
+                        break;
+                }
+
+                if (isOK)
+                    xspf_add_node (track, entry.type, entry.isMeta,
+                     entry.xspfName, scratch, scratchi);
+            }
+        }
+    }
+
+    xmlSaveCtxt * save = xmlSaveToIO (write_cb, close_cb, & file, nullptr, XML_SAVE_FORMAT);
+    if (! save)
+        goto ERR;
+
+    if (xmlSaveDoc (save, doc) < 0 || xmlSaveClose (save) < 0)
+        goto ERR;
+
+    xmlFreeDoc(doc);
+    return true;
+
+ERR:
+    xmlFreeDoc (doc);
+    return false;
+}
-- 
2.1.4




More information about the pkg-multimedia-maintainers mailing list